@headless-lms/server 0.1.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 (351) hide show
  1. package/README.md +1 -1
  2. package/dist/_virtual/_rolldown/runtime.js +5 -0
  3. package/dist/app/community-mail.d.ts +26 -0
  4. package/dist/app/community-mail.js +96 -0
  5. package/dist/app/community-mail.js.map +1 -0
  6. package/dist/app/container.d.ts +22 -14
  7. package/dist/app/container.js +186 -62
  8. package/dist/app/container.js.map +1 -1
  9. package/dist/app/mcp-endpoints.d.ts +13 -0
  10. package/dist/app/mcp-endpoints.js +25 -0
  11. package/dist/app/mcp-endpoints.js.map +1 -0
  12. package/dist/http/config.d.ts +2 -1
  13. package/dist/http/errors.d.ts +14 -0
  14. package/dist/http/errors.js +147 -0
  15. package/dist/http/errors.js.map +1 -0
  16. package/dist/http/mcp/catalogue.d.ts +37 -0
  17. package/dist/http/mcp/catalogue.js +69 -0
  18. package/dist/http/mcp/catalogue.js.map +1 -0
  19. package/dist/http/mcp/challenge.d.ts +7 -0
  20. package/dist/http/mcp/challenge.js +35 -0
  21. package/dist/http/mcp/challenge.js.map +1 -0
  22. package/dist/http/mcp/input-schema.d.ts +7 -0
  23. package/dist/http/mcp/input-schema.js +28 -0
  24. package/dist/http/mcp/input-schema.js.map +1 -0
  25. package/dist/http/mcp/route.d.ts +8 -0
  26. package/dist/http/mcp/route.js +75 -0
  27. package/dist/http/mcp/route.js.map +1 -0
  28. package/dist/http/mcp/server.d.ts +8 -0
  29. package/dist/http/mcp/server.js +31 -0
  30. package/dist/http/mcp/server.js.map +1 -0
  31. package/dist/http/mcp/test-support.d.ts +55 -0
  32. package/dist/http/mcp/test-support.js +151 -0
  33. package/dist/http/mcp/test-support.js.map +1 -0
  34. package/dist/http/mcp/tool.d.ts +48 -0
  35. package/dist/http/mcp/tool.js +58 -0
  36. package/dist/http/mcp/tool.js.map +1 -0
  37. package/dist/http/mcp/tools/automations.d.ts +6 -0
  38. package/dist/http/mcp/tools/automations.js +120 -0
  39. package/dist/http/mcp/tools/automations.js.map +1 -0
  40. package/dist/http/mcp/tools/catalog.d.ts +6 -0
  41. package/dist/http/mcp/tools/catalog.js +200 -0
  42. package/dist/http/mcp/tools/catalog.js.map +1 -0
  43. package/dist/http/mcp/tools/comments.d.ts +6 -0
  44. package/dist/http/mcp/tools/comments.js +70 -0
  45. package/dist/http/mcp/tools/comments.js.map +1 -0
  46. package/dist/http/mcp/tools/communities.d.ts +6 -0
  47. package/dist/http/mcp/tools/communities.js +175 -0
  48. package/dist/http/mcp/tools/communities.js.map +1 -0
  49. package/dist/http/mcp/tools/community-members.d.ts +6 -0
  50. package/dist/http/mcp/tools/community-members.js +89 -0
  51. package/dist/http/mcp/tools/community-members.js.map +1 -0
  52. package/dist/http/mcp/tools/community-moderation.d.ts +6 -0
  53. package/dist/http/mcp/tools/community-moderation.js +144 -0
  54. package/dist/http/mcp/tools/community-moderation.js.map +1 -0
  55. package/dist/http/mcp/tools/courses.d.ts +6 -0
  56. package/dist/http/mcp/tools/courses.js +121 -0
  57. package/dist/http/mcp/tools/courses.js.map +1 -0
  58. package/dist/http/mcp/tools/index.d.ts +6 -0
  59. package/dist/http/mcp/tools/index.js +23 -0
  60. package/dist/http/mcp/tools/index.js.map +1 -0
  61. package/dist/http/mcp/tools/people.d.ts +6 -0
  62. package/dist/http/mcp/tools/people.js +145 -0
  63. package/dist/http/mcp/tools/people.js.map +1 -0
  64. package/dist/http/plugins/auth.js +13 -5
  65. package/dist/http/plugins/auth.js.map +1 -1
  66. package/dist/http/plugins/error-handler.d.ts +3 -2
  67. package/dist/http/plugins/error-handler.js +52 -57
  68. package/dist/http/plugins/error-handler.js.map +1 -1
  69. package/dist/http/plugins/openapi.js +70 -20
  70. package/dist/http/plugins/openapi.js.map +1 -1
  71. package/dist/http/routes/access.d.ts +7 -0
  72. package/dist/http/routes/access.js +140 -0
  73. package/dist/http/routes/access.js.map +1 -0
  74. package/dist/http/routes/activities.js +97 -20
  75. package/dist/http/routes/activities.js.map +1 -1
  76. package/dist/http/routes/assets.js +60 -51
  77. package/dist/http/routes/assets.js.map +1 -1
  78. package/dist/http/routes/automations.js +64 -20
  79. package/dist/http/routes/automations.js.map +1 -1
  80. package/dist/http/routes/bundles.d.ts +7 -0
  81. package/dist/http/routes/bundles.js +181 -0
  82. package/dist/http/routes/bundles.js.map +1 -0
  83. package/dist/http/routes/communities.d.ts +7 -0
  84. package/dist/http/routes/communities.js +462 -0
  85. package/dist/http/routes/communities.js.map +1 -0
  86. package/dist/http/routes/community-moderation.d.ts +7 -0
  87. package/dist/http/routes/community-moderation.js +425 -0
  88. package/dist/http/routes/community-moderation.js.map +1 -0
  89. package/dist/http/routes/course-analytics.d.ts +7 -0
  90. package/dist/http/routes/course-analytics.js +60 -0
  91. package/dist/http/routes/course-analytics.js.map +1 -0
  92. package/dist/http/routes/courses.js +38 -23
  93. package/dist/http/routes/courses.js.map +1 -1
  94. package/dist/http/routes/dashboard.js +17 -8
  95. package/dist/http/routes/dashboard.js.map +1 -1
  96. package/dist/http/routes/discussion.js +35 -27
  97. package/dist/http/routes/discussion.js.map +1 -1
  98. package/dist/http/routes/downloads.js +58 -40
  99. package/dist/http/routes/downloads.js.map +1 -1
  100. package/dist/http/routes/entitlements.js +16 -7
  101. package/dist/http/routes/entitlements.js.map +1 -1
  102. package/dist/http/routes/integrations.js +38 -41
  103. package/dist/http/routes/integrations.js.map +1 -1
  104. package/dist/http/routes/member/actor.d.ts +14 -0
  105. package/dist/http/routes/member/actor.js +11 -0
  106. package/dist/http/routes/member/actor.js.map +1 -0
  107. package/dist/http/routes/member/assets.d.ts +7 -0
  108. package/dist/http/routes/member/assets.js +79 -0
  109. package/dist/http/routes/member/assets.js.map +1 -0
  110. package/dist/http/routes/member/chats.d.ts +7 -0
  111. package/dist/http/routes/member/chats.js +456 -0
  112. package/dist/http/routes/member/chats.js.map +1 -0
  113. package/dist/http/routes/member/comments.d.ts +7 -0
  114. package/dist/http/routes/member/comments.js +187 -0
  115. package/dist/http/routes/member/comments.js.map +1 -0
  116. package/dist/http/routes/member/community.d.ts +7 -0
  117. package/dist/http/routes/member/community.js +288 -0
  118. package/dist/http/routes/member/community.js.map +1 -0
  119. package/dist/http/routes/member/courses.d.ts +7 -0
  120. package/dist/http/routes/member/courses.js +101 -0
  121. package/dist/http/routes/member/courses.js.map +1 -0
  122. package/dist/http/routes/member/downloads.d.ts +7 -0
  123. package/dist/http/routes/member/downloads.js +56 -0
  124. package/dist/http/routes/member/downloads.js.map +1 -0
  125. package/dist/http/routes/member/files.d.ts +7 -0
  126. package/dist/http/routes/member/files.js +184 -0
  127. package/dist/http/routes/member/files.js.map +1 -0
  128. package/dist/http/routes/member/index.d.ts +7 -0
  129. package/dist/http/routes/member/index.js +31 -0
  130. package/dist/http/routes/member/index.js.map +1 -0
  131. package/dist/http/routes/member/notifications.d.ts +7 -0
  132. package/dist/http/routes/member/notifications.js +101 -0
  133. package/dist/http/routes/member/notifications.js.map +1 -0
  134. package/dist/http/routes/member/org.d.ts +7 -0
  135. package/dist/http/routes/member/org.js +56 -0
  136. package/dist/http/routes/member/org.js.map +1 -0
  137. package/dist/http/routes/member/posts.d.ts +7 -0
  138. package/dist/http/routes/member/posts.js +612 -0
  139. package/dist/http/routes/member/posts.js.map +1 -0
  140. package/dist/http/routes/member/profile.d.ts +7 -0
  141. package/dist/http/routes/member/profile.js +48 -0
  142. package/dist/http/routes/member/profile.js.map +1 -0
  143. package/dist/http/routes/member/progress.d.ts +7 -0
  144. package/dist/http/routes/member/progress.js +60 -0
  145. package/dist/http/routes/member/progress.js.map +1 -0
  146. package/dist/http/routes/organizations.js +49 -24
  147. package/dist/http/routes/organizations.js.map +1 -1
  148. package/dist/http/routes/students.js +43 -37
  149. package/dist/http/routes/students.js.map +1 -1
  150. package/dist/http/routes/webhooks.d.ts +7 -0
  151. package/dist/http/routes/webhooks.js +167 -0
  152. package/dist/http/routes/webhooks.js.map +1 -0
  153. package/dist/http/routes.js +14 -2
  154. package/dist/http/routes.js.map +1 -1
  155. package/dist/http/schemas/access.d.ts +146 -0
  156. package/dist/http/schemas/access.js +36 -0
  157. package/dist/http/schemas/access.js.map +1 -0
  158. package/dist/http/schemas/activities.d.ts +36 -1
  159. package/dist/http/schemas/activities.js +9 -4
  160. package/dist/http/schemas/activities.js.map +1 -1
  161. package/dist/http/schemas/assets.d.ts +76 -73
  162. package/dist/http/schemas/assets.js +23 -13
  163. package/dist/http/schemas/assets.js.map +1 -1
  164. package/dist/http/schemas/automations.d.ts +85 -8
  165. package/dist/http/schemas/automations.js +13 -2
  166. package/dist/http/schemas/automations.js.map +1 -1
  167. package/dist/http/schemas/bundles.d.ts +63 -0
  168. package/dist/http/schemas/bundles.js +23 -0
  169. package/dist/http/schemas/bundles.js.map +1 -0
  170. package/dist/http/schemas/chats.d.ts +386 -0
  171. package/dist/http/schemas/chats.js +58 -0
  172. package/dist/http/schemas/chats.js.map +1 -0
  173. package/dist/http/schemas/community.d.ts +537 -0
  174. package/dist/http/schemas/community.js +129 -0
  175. package/dist/http/schemas/community.js.map +1 -0
  176. package/dist/http/schemas/content.d.ts +22 -13
  177. package/dist/http/schemas/content.js +11 -9
  178. package/dist/http/schemas/content.js.map +1 -1
  179. package/dist/http/schemas/course-analytics.d.ts +29 -0
  180. package/dist/http/schemas/course-analytics.js +21 -0
  181. package/dist/http/schemas/course-analytics.js.map +1 -0
  182. package/dist/http/schemas/dashboard.js.map +1 -1
  183. package/dist/http/schemas/discussion.d.ts +85 -23
  184. package/dist/http/schemas/discussion.js +12 -11
  185. package/dist/http/schemas/discussion.js.map +1 -1
  186. package/dist/http/schemas/downloads.d.ts +13 -5
  187. package/dist/http/schemas/downloads.js +14 -11
  188. package/dist/http/schemas/downloads.js.map +1 -1
  189. package/dist/http/schemas/entitlements.d.ts +14 -6
  190. package/dist/http/schemas/entitlements.js +8 -6
  191. package/dist/http/schemas/entitlements.js.map +1 -1
  192. package/dist/http/schemas/files.d.ts +45 -0
  193. package/dist/http/schemas/files.js +25 -0
  194. package/dist/http/schemas/files.js.map +1 -0
  195. package/dist/http/schemas/index.d.ts +19 -10
  196. package/dist/http/schemas/index.js +19 -10
  197. package/dist/http/schemas/integrations.d.ts +4 -4
  198. package/dist/http/schemas/integrations.js.map +1 -1
  199. package/dist/http/schemas/invites.d.ts +4 -0
  200. package/dist/http/schemas/invites.js +3 -1
  201. package/dist/http/schemas/invites.js.map +1 -1
  202. package/dist/http/schemas/{learn.d.ts → member.d.ts} +42 -19
  203. package/dist/http/schemas/{learn.js → member.js} +17 -13
  204. package/dist/http/schemas/member.js.map +1 -0
  205. package/dist/http/schemas/members.d.ts +39 -6
  206. package/dist/http/schemas/members.js +17 -3
  207. package/dist/http/schemas/members.js.map +1 -1
  208. package/dist/http/schemas/notifications.d.ts +227 -0
  209. package/dist/http/schemas/notifications.js +44 -0
  210. package/dist/http/schemas/notifications.js.map +1 -0
  211. package/dist/http/schemas/organizations.js.map +1 -1
  212. package/dist/http/schemas/posts.d.ts +316 -0
  213. package/dist/http/schemas/posts.js +47 -0
  214. package/dist/http/schemas/posts.js.map +1 -0
  215. package/dist/http/schemas/profile.d.ts +23 -0
  216. package/dist/http/schemas/profile.js +15 -0
  217. package/dist/http/schemas/profile.js.map +1 -0
  218. package/dist/http/schemas/settings.js.map +1 -1
  219. package/dist/http/schemas/shared.d.ts +26 -1
  220. package/dist/http/schemas/shared.js +22 -3
  221. package/dist/http/schemas/shared.js.map +1 -1
  222. package/dist/http/schemas/students.d.ts +32 -10
  223. package/dist/http/schemas/students.js +19 -6
  224. package/dist/http/schemas/students.js.map +1 -1
  225. package/dist/http/scope.d.ts +2 -1
  226. package/dist/http/scope.js +20 -4
  227. package/dist/http/scope.js.map +1 -1
  228. package/dist/http/server.js +10 -3
  229. package/dist/http/server.js.map +1 -1
  230. package/dist/http/web-bridge.d.ts +1 -1
  231. package/dist/http/web-bridge.js +2 -2
  232. package/dist/http/web-bridge.js.map +1 -1
  233. package/dist/http/well-known.d.ts +7 -0
  234. package/dist/http/well-known.js +22 -0
  235. package/dist/http/well-known.js.map +1 -0
  236. package/dist/index.d.ts +3 -2
  237. package/dist/index.js +4 -2
  238. package/dist/index.js.map +1 -1
  239. package/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +78 -0
  240. package/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js.map +1 -0
  241. package/dist/node_modules/.pnpm/@vitest_expect@2.1.9/node_modules/@vitest/expect/dist/index.js +1267 -0
  242. package/dist/node_modules/.pnpm/@vitest_expect@2.1.9/node_modules/@vitest/expect/dist/index.js.map +1 -0
  243. package/dist/node_modules/.pnpm/@vitest_pretty-format@2.1.9/node_modules/@vitest/pretty-format/dist/index.js +814 -0
  244. package/dist/node_modules/.pnpm/@vitest_pretty-format@2.1.9/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
  245. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/chunk-tasks.js +43 -0
  246. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/chunk-tasks.js.map +1 -0
  247. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/index.js +527 -0
  248. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/index.js.map +1 -0
  249. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/utils.js +2 -0
  250. package/dist/node_modules/.pnpm/@vitest_snapshot@2.1.9/node_modules/@vitest/snapshot/dist/index.js +1737 -0
  251. package/dist/node_modules/.pnpm/@vitest_snapshot@2.1.9/node_modules/@vitest/snapshot/dist/index.js.map +1 -0
  252. package/dist/node_modules/.pnpm/@vitest_spy@2.1.9/node_modules/@vitest/spy/dist/index.js +137 -0
  253. package/dist/node_modules/.pnpm/@vitest_spy@2.1.9/node_modules/@vitest/spy/dist/index.js.map +1 -0
  254. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +118 -0
  255. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js.map +1 -0
  256. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/diff.js +1222 -0
  257. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/diff.js.map +1 -0
  258. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/error.js +91 -0
  259. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/error.js.map +1 -0
  260. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/helpers.js +113 -0
  261. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
  262. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/index.js +449 -0
  263. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/index.js.map +1 -0
  264. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/source-map.js +163 -0
  265. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
  266. package/dist/node_modules/.pnpm/chai@5.3.3/node_modules/chai/index.js +3187 -0
  267. package/dist/node_modules/.pnpm/chai@5.3.3/node_modules/chai/index.js.map +1 -0
  268. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js +11 -0
  269. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js.map +1 -0
  270. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js +16 -0
  271. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js.map +1 -0
  272. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js +11 -0
  273. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js.map +1 -0
  274. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js +15 -0
  275. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js.map +1 -0
  276. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js +13 -0
  277. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js.map +1 -0
  278. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js +34 -0
  279. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js.map +1 -0
  280. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js +12 -0
  281. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js.map +1 -0
  282. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js +122 -0
  283. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js.map +1 -0
  284. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js +39 -0
  285. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js.map +1 -0
  286. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js +99 -0
  287. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js.map +1 -0
  288. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js +25 -0
  289. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js.map +1 -0
  290. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js +14 -0
  291. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js.map +1 -0
  292. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js +21 -0
  293. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js.map +1 -0
  294. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js +6 -0
  295. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js.map +1 -0
  296. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js +12 -0
  297. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js.map +1 -0
  298. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js +18 -0
  299. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js.map +1 -0
  300. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js +24 -0
  301. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js.map +1 -0
  302. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js +9 -0
  303. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js.map +1 -0
  304. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js +30 -0
  305. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js.map +1 -0
  306. package/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +939 -0
  307. package/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js.map +1 -0
  308. package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.js +82 -0
  309. package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.js.map +1 -0
  310. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +82 -0
  311. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js.map +1 -0
  312. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.js +8 -0
  313. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.js.map +1 -0
  314. package/dist/node_modules/.pnpm/tinyspy@3.0.2/node_modules/tinyspy/dist/index.js +83 -0
  315. package/dist/node_modules/.pnpm/tinyspy@3.0.2/node_modules/tinyspy/dist/index.js.map +1 -0
  316. 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
  317. 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
  318. 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
  319. 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
  320. 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
  321. 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
  322. 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
  323. 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
  324. package/dist/packages/server/package.js +6 -0
  325. package/dist/packages/server/package.js.map +1 -0
  326. package/package.json +9 -7
  327. package/dist/app/notifications.d.ts +0 -7
  328. package/dist/app/notifications.js +0 -23
  329. package/dist/app/notifications.js.map +0 -1
  330. package/dist/http/routes/learn/assets.d.ts +0 -8
  331. package/dist/http/routes/learn/assets.js +0 -32
  332. package/dist/http/routes/learn/assets.js.map +0 -1
  333. package/dist/http/routes/learn/comments.d.ts +0 -7
  334. package/dist/http/routes/learn/comments.js +0 -175
  335. package/dist/http/routes/learn/comments.js.map +0 -1
  336. package/dist/http/routes/learn/courses.d.ts +0 -7
  337. package/dist/http/routes/learn/courses.js +0 -75
  338. package/dist/http/routes/learn/courses.js.map +0 -1
  339. package/dist/http/routes/learn/downloads.d.ts +0 -7
  340. package/dist/http/routes/learn/downloads.js +0 -76
  341. package/dist/http/routes/learn/downloads.js.map +0 -1
  342. package/dist/http/routes/learn/index.d.ts +0 -7
  343. package/dist/http/routes/learn/index.js +0 -19
  344. package/dist/http/routes/learn/index.js.map +0 -1
  345. package/dist/http/routes/learn/org.d.ts +0 -7
  346. package/dist/http/routes/learn/org.js +0 -50
  347. package/dist/http/routes/learn/org.js.map +0 -1
  348. package/dist/http/routes/learn/progress.d.ts +0 -7
  349. package/dist/http/routes/learn/progress.js +0 -63
  350. package/dist/http/routes/learn/progress.js.map +0 -1
  351. package/dist/http/schemas/learn.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"students.js","names":[],"sources":["../../../src/http/schemas/students.ts"],"sourcesContent":["// Students resource schemas.\nimport { z } from \"zod\";\nimport { ListQuery, paginated, OrgUserProfileSchema } from \"./shared.js\";\n\nexport const OrgUserStatus = z.enum([\"invited\", \"active\"]);\nexport type OrgUserStatus = z.infer<typeof OrgUserStatus>;\n\nexport const Student = OrgUserProfileSchema.extend({\n entitlementCount: z.number().int(),\n /** 0–100, averaged across active entitlements. */\n avgProgress: z.number().int(),\n /** `invited` means an admin added them and they have not accepted yet. */\n status: OrgUserStatus,\n joinedAt: z.string(),\n lastActiveAt: z.string().nullable(),\n});\nexport type Student = z.infer<typeof Student>;\n\nexport const StudentsQuery = ListQuery;\nexport type StudentsQuery = z.infer<typeof StudentsQuery>;\n\nexport const StudentsPage = paginated(Student);\nexport type StudentsPage = z.infer<typeof StudentsPage>;\n\nexport const StudentIdParam = z.object({ id: z.string() });\nexport type StudentIdParam = z.infer<typeof StudentIdParam>;\n\n// Every field is a correction to what an admin typed, so all three are sent\n// together — the form edits the whole profile, not one attribute at a time.\nexport const UpdateStudentBody = z.object({\n firstName: z.string().trim().min(1),\n lastName: z.string().trim().min(1),\n email: z.string().email(),\n});\nexport type UpdateStudentBody = z.infer<typeof UpdateStudentBody>;\n"],"mappings":";;;AAIA,MAAa,gBAAgB,EAAE,KAAK,CAAC,WAAW,QAAQ,CAAC;AAGzD,MAAa,UAAU,qBAAqB,OAAO;CACjD,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI;;CAEjC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI;;CAE5B,QAAQ;CACR,UAAU,EAAE,OAAO;CACnB,cAAc,EAAE,OAAO,CAAC,CAAC,SAAS;AACpC,CAAC;AAGD,MAAa,gBAAgB;AAG7B,MAAa,eAAe,UAAU,OAAO;AAG7C,MAAa,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAKzD,MAAa,oBAAoB,EAAE,OAAO;CACxC,WAAW,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;CAClC,UAAU,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;CACjC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM;AAC1B,CAAC"}
1
+ {"version":3,"file":"students.js","names":[],"sources":["../../../src/http/schemas/students.ts"],"sourcesContent":["// Students resource schemas.\nimport { z } from 'zod';\nimport { ListQuery, paginated, OrgUserProfileSchema } from './shared.js';\n\nexport const OrgUserStatus = z.enum(['invited', 'active']);\nexport type OrgUserStatus = z.infer<typeof OrgUserStatus>;\n\nexport const Student = OrgUserProfileSchema.extend({\n entitlementCount: z.number().int(),\n /** 0–100, averaged across active entitlements. */\n avgProgress: z.number().int(),\n /** `invited` means an admin added them and they have not accepted yet. */\n status: OrgUserStatus,\n joinedAt: z.string(),\n lastActiveAt: z.string().nullable(),\n});\nexport type Student = z.infer<typeof Student>;\n\nexport const StudentCourseProgress = z.object({\n courseId: z.string(),\n title: z.string(),\n totalActivities: z.number().int(),\n completedActivities: z.number().int(),\n /** 0–100, completed published activities over the course's total. */\n progress: z.number().int(),\n startedAt: z.string().nullable(),\n lastActivityAt: z.string().nullable(),\n completedAt: z.string().nullable(),\n});\nexport type StudentCourseProgress = z.infer<typeof StudentCourseProgress>;\n\nexport const StudentAnalytics = z.object({\n enrolled: z.number().int(),\n started: z.number().int(),\n completed: z.number().int(),\n avgProgress: z.number().int(),\n courses: z.array(StudentCourseProgress),\n});\nexport type StudentAnalytics = z.infer<typeof StudentAnalytics>;\n\nexport const StudentsQuery = ListQuery;\nexport type StudentsQuery = z.infer<typeof StudentsQuery>;\n\nexport const StudentsPage = paginated(Student);\nexport type StudentsPage = z.infer<typeof StudentsPage>;\n\nexport const StudentIdParam = z.object({ id: z.string() });\nexport type StudentIdParam = z.infer<typeof StudentIdParam>;\n"],"mappings":";;;AAIA,MAAa,gBAAgB,EAAE,KAAK,CAAC,WAAW,QAAQ,CAAC;AAGzD,MAAa,UAAU,qBAAqB,OAAO;CACjD,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI;;CAEjC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI;;CAE5B,QAAQ;CACR,UAAU,EAAE,OAAO;CACnB,cAAc,EAAE,OAAO,CAAC,CAAC,SAAS;AACpC,CAAC;AAGD,MAAa,wBAAwB,EAAE,OAAO;CAC5C,UAAU,EAAE,OAAO;CACnB,OAAO,EAAE,OAAO;CAChB,iBAAiB,EAAE,OAAO,CAAC,CAAC,IAAI;CAChC,qBAAqB,EAAE,OAAO,CAAC,CAAC,IAAI;;CAEpC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI;CACzB,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;CAC/B,gBAAgB,EAAE,OAAO,CAAC,CAAC,SAAS;CACpC,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;AACnC,CAAC;AAGD,MAAa,mBAAmB,EAAE,OAAO;CACvC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI;CACzB,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI;CACxB,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI;CAC1B,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI;CAC5B,SAAS,EAAE,MAAM,qBAAqB;AACxC,CAAC;AAGD,MAAa,gBAAgB;AAG7B,MAAa,eAAe,UAAU,OAAO;AAG7C,MAAa,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC"}
@@ -17,6 +17,7 @@ interface OrgScope {
17
17
  /** Thrown when the session has no resolvable active org / domain user. */
18
18
  declare class NoActiveOrgError extends Error {}
19
19
  declare function resolveScope(container: Container, req: FastifyRequest): Promise<OrgScope>;
20
+ declare function resolveScopeFor(container: Container, authUserId: string, authOrgId: string): Promise<OrgScope>;
20
21
  //#endregion
21
- export { NoActiveOrgError, OrgScope, resolveScope };
22
+ export { NoActiveOrgError, OrgScope, resolveScope, resolveScopeFor };
22
23
  //# sourceMappingURL=scope.d.ts.map
@@ -5,11 +5,27 @@ var NoActiveOrgError = class extends Error {};
5
5
  async function resolveScope(container, req) {
6
6
  const authUser = req.authUser;
7
7
  const authOrgId = req.authOrgId ?? null;
8
- if (!authUser) throw new NoActiveOrgError("no authenticated user");
9
- if (!authOrgId || !req.orgId) throw new NoActiveOrgError("no active organization in session");
8
+ if (!authUser) throw new NoActiveOrgError("Sign in to continue");
9
+ if (!authOrgId || !req.orgId) throw new NoActiveOrgError("Choose an organization to continue");
10
10
  const org = await container.organizations.getById(req.orgId);
11
- if (!org) throw new NoActiveOrgError("active organization not found");
11
+ if (!org) throw new NoActiveOrgError("The active organization no longer exists");
12
12
  const user = await container.identity.getUserByExternalId(authUser.id);
13
+ if (!user) throw new NoActiveOrgError("Your account is not set up yet");
14
+ const orgUser = await container.organizations.getOrgUser(org.id, user.id);
15
+ if (!orgUser || !isStaffRole(orgUser.role)) throw new NoActiveOrgError("Only staff of this organization can do this");
16
+ container.requestContext.set({ orgId: org.id });
17
+ return {
18
+ orgId: org.id,
19
+ userId: user.id,
20
+ orgUserId: orgUser.id,
21
+ role: orgUser.role,
22
+ authOrgId
23
+ };
24
+ }
25
+ async function resolveScopeFor(container, authUserId, authOrgId) {
26
+ const org = await container.organizations.getByExternalId(authOrgId);
27
+ if (!org) throw new NoActiveOrgError("active organization not found");
28
+ const user = await container.identity.getUserByExternalId(authUserId);
13
29
  if (!user) throw new NoActiveOrgError("no domain user for the current user");
14
30
  const orgUser = await container.organizations.getOrgUser(org.id, user.id);
15
31
  if (!orgUser || !isStaffRole(orgUser.role)) throw new NoActiveOrgError("not a staff member of the active organization");
@@ -23,6 +39,6 @@ async function resolveScope(container, req) {
23
39
  };
24
40
  }
25
41
  //#endregion
26
- export { NoActiveOrgError, resolveScope };
42
+ export { NoActiveOrgError, resolveScope, resolveScopeFor };
27
43
 
28
44
  //# sourceMappingURL=scope.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scope.js","names":[],"sources":["../../src/http/scope.ts"],"sourcesContent":["import type { FastifyRequest } from 'fastify';\nimport type { Container } from '../app/container.js';\nimport { isStaffRole, type StaffRole } from '@headless-lms/core/organizations';\n\nexport interface OrgScope {\n /** Domain `organizations.id` for the session's active org. */\n orgId: string;\n /** Domain `users.id` of the acting person. */\n userId: string;\n /** Domain `org_users.id` — the acting org user in this org. */\n orgUserId: string;\n /** The role held in this org. */\n role: StaffRole;\n /** Better-auth organization id (for writes that go through the auth provider). */\n authOrgId: string;\n}\n\n/** Thrown when the session has no resolvable active org / domain user. */\nexport class NoActiveOrgError extends Error {}\n\nexport async function resolveScope(container: Container, req: FastifyRequest): Promise<OrgScope> {\n const authUser = req.authUser;\n const authOrgId = req.authOrgId ?? null;\n if (!authUser) {\n throw new NoActiveOrgError('no authenticated user');\n }\n if (!authOrgId || !req.orgId) {\n throw new NoActiveOrgError('no active organization in session');\n }\n // The session guard already translated the auth org id to the domain org.\n const org = await container.organizations.getById(req.orgId);\n if (!org) {\n throw new NoActiveOrgError('active organization not found');\n }\n const user = await container.identity.getUserByExternalId(authUser.id);\n if (!user) {\n throw new NoActiveOrgError('no domain user for the current user');\n }\n const orgUser = await container.organizations.getOrgUser(org.id, user.id);\n if (!orgUser || !isStaffRole(orgUser.role)) {\n throw new NoActiveOrgError('not a staff member of the active organization');\n }\n container.requestContext.set({ orgId: org.id });\n return {\n orgId: org.id,\n userId: user.id,\n orgUserId: orgUser.id,\n role: orgUser.role,\n authOrgId,\n };\n}\n"],"mappings":";;;AAkBA,IAAa,mBAAb,cAAsC,MAAM,CAAC;AAE7C,eAAsB,aAAa,WAAsB,KAAwC;CAC/F,MAAM,WAAW,IAAI;CACrB,MAAM,YAAY,IAAI,aAAa;CACnC,IAAI,CAAC,UACH,MAAM,IAAI,iBAAiB,uBAAuB;CAEpD,IAAI,CAAC,aAAa,CAAC,IAAI,OACrB,MAAM,IAAI,iBAAiB,mCAAmC;CAGhE,MAAM,MAAM,MAAM,UAAU,cAAc,QAAQ,IAAI,KAAK;CAC3D,IAAI,CAAC,KACH,MAAM,IAAI,iBAAiB,+BAA+B;CAE5D,MAAM,OAAO,MAAM,UAAU,SAAS,oBAAoB,SAAS,EAAE;CACrE,IAAI,CAAC,MACH,MAAM,IAAI,iBAAiB,qCAAqC;CAElE,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,IAAI,KAAK,EAAE;CACxE,IAAI,CAAC,WAAW,CAAC,YAAY,QAAQ,IAAI,GACvC,MAAM,IAAI,iBAAiB,+CAA+C;CAE5E,UAAU,eAAe,IAAI,EAAE,OAAO,IAAI,GAAG,CAAC;CAC9C,OAAO;EACL,OAAO,IAAI;EACX,QAAQ,KAAK;EACb,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd;CACF;AACF"}
1
+ {"version":3,"file":"scope.js","names":[],"sources":["../../src/http/scope.ts"],"sourcesContent":["import type { FastifyRequest } from 'fastify';\nimport type { Container } from '../app/container.js';\nimport { isStaffRole, type StaffRole } from '@headless-lms/core/organizations';\n\nexport interface OrgScope {\n /** Domain `organizations.id` for the session's active org. */\n orgId: string;\n /** Domain `users.id` of the acting person. */\n userId: string;\n /** Domain `org_users.id` — the acting org user in this org. */\n orgUserId: string;\n /** The role held in this org. */\n role: StaffRole;\n /** Better-auth organization id (for writes that go through the auth provider). */\n authOrgId: string;\n}\n\n/** Thrown when the session has no resolvable active org / domain user. */\nexport class NoActiveOrgError extends Error {}\n\nexport async function resolveScope(container: Container, req: FastifyRequest): Promise<OrgScope> {\n const authUser = req.authUser;\n const authOrgId = req.authOrgId ?? null;\n if (!authUser) {\n throw new NoActiveOrgError('Sign in to continue');\n }\n if (!authOrgId || !req.orgId) {\n throw new NoActiveOrgError('Choose an organization to continue');\n }\n // The session guard already translated the auth org id to the domain org.\n const org = await container.organizations.getById(req.orgId);\n if (!org) {\n throw new NoActiveOrgError('The active organization no longer exists');\n }\n const user = await container.identity.getUserByExternalId(authUser.id);\n if (!user) {\n throw new NoActiveOrgError('Your account is not set up yet');\n }\n const orgUser = await container.organizations.getOrgUser(org.id, user.id);\n if (!orgUser || !isStaffRole(orgUser.role)) {\n throw new NoActiveOrgError('Only staff of this organization can do this');\n }\n container.requestContext.set({ orgId: org.id });\n return {\n orgId: org.id,\n userId: user.id,\n orgUserId: orgUser.id,\n role: orgUser.role,\n authOrgId,\n };\n}\n\nexport async function resolveScopeFor(\n container: Container,\n authUserId: string,\n authOrgId: string,\n): Promise<OrgScope> {\n const org = await container.organizations.getByExternalId(authOrgId);\n if (!org) {\n throw new NoActiveOrgError('active organization not found');\n }\n const user = await container.identity.getUserByExternalId(authUserId);\n if (!user) {\n throw new NoActiveOrgError('no domain user for the current user');\n }\n const orgUser = await container.organizations.getOrgUser(org.id, user.id);\n if (!orgUser || !isStaffRole(orgUser.role)) {\n throw new NoActiveOrgError('not a staff member of the active organization');\n }\n container.requestContext.set({ orgId: org.id });\n return { orgId: org.id, userId: user.id, orgUserId: orgUser.id, role: orgUser.role, authOrgId };\n}\n"],"mappings":";;;AAkBA,IAAa,mBAAb,cAAsC,MAAM,CAAC;AAE7C,eAAsB,aAAa,WAAsB,KAAwC;CAC/F,MAAM,WAAW,IAAI;CACrB,MAAM,YAAY,IAAI,aAAa;CACnC,IAAI,CAAC,UACH,MAAM,IAAI,iBAAiB,qBAAqB;CAElD,IAAI,CAAC,aAAa,CAAC,IAAI,OACrB,MAAM,IAAI,iBAAiB,oCAAoC;CAGjE,MAAM,MAAM,MAAM,UAAU,cAAc,QAAQ,IAAI,KAAK;CAC3D,IAAI,CAAC,KACH,MAAM,IAAI,iBAAiB,0CAA0C;CAEvE,MAAM,OAAO,MAAM,UAAU,SAAS,oBAAoB,SAAS,EAAE;CACrE,IAAI,CAAC,MACH,MAAM,IAAI,iBAAiB,gCAAgC;CAE7D,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,IAAI,KAAK,EAAE;CACxE,IAAI,CAAC,WAAW,CAAC,YAAY,QAAQ,IAAI,GACvC,MAAM,IAAI,iBAAiB,6CAA6C;CAE1E,UAAU,eAAe,IAAI,EAAE,OAAO,IAAI,GAAG,CAAC;CAC9C,OAAO;EACL,OAAO,IAAI;EACX,QAAQ,KAAK;EACb,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd;CACF;AACF;AAEA,eAAsB,gBACpB,WACA,YACA,WACmB;CACnB,MAAM,MAAM,MAAM,UAAU,cAAc,gBAAgB,SAAS;CACnE,IAAI,CAAC,KACH,MAAM,IAAI,iBAAiB,+BAA+B;CAE5D,MAAM,OAAO,MAAM,UAAU,SAAS,oBAAoB,UAAU;CACpE,IAAI,CAAC,MACH,MAAM,IAAI,iBAAiB,qCAAqC;CAElE,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,IAAI,KAAK,EAAE;CACxE,IAAI,CAAC,WAAW,CAAC,YAAY,QAAQ,IAAI,GACvC,MAAM,IAAI,iBAAiB,+CAA+C;CAE5E,UAAU,eAAe,IAAI,EAAE,OAAO,IAAI,GAAG,CAAC;CAC9C,OAAO;EAAE,OAAO,IAAI;EAAI,QAAQ,KAAK;EAAI,WAAW,QAAQ;EAAI,MAAM,QAAQ;EAAM;CAAU;AAChG"}
@@ -1,26 +1,33 @@
1
1
  import { registerCors } from "./plugins/cors.js";
2
2
  import { registerOpenApi } from "./plugins/openapi.js";
3
3
  import { registerAuth } from "./plugins/auth.js";
4
- import { errorHandler } from "./plugins/error-handler.js";
4
+ import { registerWellKnown } from "./well-known.js";
5
+ import { errorHandler, notFoundHandler } from "./plugins/error-handler.js";
5
6
  import { registerRoutes } from "./routes.js";
7
+ import { registerMcp } from "./mcp/route.js";
6
8
  import Fastify from "fastify";
7
9
  import { serializerCompiler, validatorCompiler } from "fastify-type-provider-zod";
8
10
  //#region src/http/server.ts
9
11
  async function buildServer(config, container) {
10
12
  const app = Fastify({
11
13
  loggerInstance: container.loggerInstance,
12
- disableRequestLogging: config.requestLogging === false
14
+ disableRequestLogging: config.requestLogging === false,
15
+ requestIdHeader: "x-request-id"
13
16
  });
14
- app.addHook("onRequest", (request, _reply, done) => {
17
+ app.addHook("onRequest", (request, reply, done) => {
18
+ reply.header("x-request-id", request.id);
15
19
  container.requestContext.run({ reqId: request.id }, done);
16
20
  });
17
21
  app.setValidatorCompiler(validatorCompiler);
18
22
  app.setSerializerCompiler(serializerCompiler);
19
23
  app.setErrorHandler(errorHandler);
24
+ app.setNotFoundHandler(notFoundHandler);
20
25
  registerCors(app, config);
21
26
  registerOpenApi(app, config);
22
27
  registerAuth(app, container);
28
+ if (container.mcp.oauthEnabled) registerWellKnown(app, container);
23
29
  registerRoutes(app, container);
30
+ registerMcp(app, container);
24
31
  app.addHook("onClose", async () => {
25
32
  await container.outboxRelay.stop();
26
33
  await container.automationEngine.stop();
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../../src/http/server.ts"],"sourcesContent":["import Fastify, { type FastifyBaseLogger, type FastifyInstance } from 'fastify';\nimport { serializerCompiler, validatorCompiler } from 'fastify-type-provider-zod';\nimport type { Container } from '../app/container.js';\nimport type { ServerConfig } from './config.js';\nimport { registerCors } from './plugins/cors.js';\nimport { registerOpenApi } from './plugins/openapi.js';\nimport { registerAuth } from './plugins/auth.js';\nimport { errorHandler } from './plugins/error-handler.js';\nimport { registerRoutes } from './routes.js';\n\nexport async function buildServer(\n config: ServerConfig,\n container: Container,\n): Promise<FastifyInstance> {\n // One log stream for the whole process: HTTP shares the container's pino root.\n // Widened to FastifyBaseLogger so the instance keeps the default logger\n // generic (a concrete pino type would ripple through every plugin signature).\n const app = Fastify({\n loggerInstance: container.loggerInstance as FastifyBaseLogger,\n // Fastify's own request/response pair per call — noisy in a dev console,\n // useful as an access log in production. Our own logs are unaffected.\n disableRequestLogging: config.requestLogging === false,\n });\n\n // Enter the request-scoped log context: every line logged inside this\n // request's async scope carries its reqId (and orgId once resolveScope runs),\n // wherever it is emitted.\n app.addHook('onRequest', (request, _reply, done) => {\n container.requestContext.run({ reqId: request.id }, done);\n });\n\n // Validate + serialize request/response bodies from the shared Zod contract.\n app.setValidatorCompiler(validatorCompiler);\n app.setSerializerCompiler(serializerCompiler);\n app.setErrorHandler(errorHandler);\n\n registerCors(app, config);\n registerOpenApi(app, config);\n registerAuth(app, container);\n\n registerRoutes(app, container);\n\n // Drain + stop the outbox relay and the automation engine on shutdown.\n // Harmless when neither was started (gen-openapi boots this app with\n // ready() + close() only).\n app.addHook('onClose', async () => {\n await container.outboxRelay.stop();\n await container.automationEngine.stop();\n });\n\n return app;\n}\n"],"mappings":";;;;;;;;AAUA,eAAsB,YACpB,QACA,WAC0B;CAI1B,MAAM,MAAM,QAAQ;EAClB,gBAAgB,UAAU;EAG1B,uBAAuB,OAAO,mBAAmB;CACnD,CAAC;CAKD,IAAI,QAAQ,cAAc,SAAS,QAAQ,SAAS;EAClD,UAAU,eAAe,IAAI,EAAE,OAAO,QAAQ,GAAG,GAAG,IAAI;CAC1D,CAAC;CAGD,IAAI,qBAAqB,iBAAiB;CAC1C,IAAI,sBAAsB,kBAAkB;CAC5C,IAAI,gBAAgB,YAAY;CAEhC,aAAa,KAAK,MAAM;CACxB,gBAAgB,KAAK,MAAM;CAC3B,aAAa,KAAK,SAAS;CAE3B,eAAe,KAAK,SAAS;CAK7B,IAAI,QAAQ,WAAW,YAAY;EACjC,MAAM,UAAU,YAAY,KAAK;EACjC,MAAM,UAAU,iBAAiB,KAAK;CACxC,CAAC;CAED,OAAO;AACT"}
1
+ {"version":3,"file":"server.js","names":[],"sources":["../../src/http/server.ts"],"sourcesContent":["import Fastify, { type FastifyBaseLogger, type FastifyInstance } from 'fastify';\nimport { serializerCompiler, validatorCompiler } from 'fastify-type-provider-zod';\nimport type { Container } from '../app/container.js';\nimport type { ServerConfig } from './config.js';\nimport { registerCors } from './plugins/cors.js';\nimport { registerOpenApi } from './plugins/openapi.js';\nimport { registerAuth } from './plugins/auth.js';\nimport { registerWellKnown } from './well-known.js';\nimport { errorHandler, notFoundHandler } from './plugins/error-handler.js';\nimport { registerRoutes } from './routes.js';\nimport { registerMcp } from './mcp/route.js';\n\nexport async function buildServer(\n config: ServerConfig,\n container: Container,\n): Promise<FastifyInstance> {\n // One log stream for the whole process: HTTP shares the container's pino root.\n // Widened to FastifyBaseLogger so the instance keeps the default logger\n // generic (a concrete pino type would ripple through every plugin signature).\n const app = Fastify({\n loggerInstance: container.loggerInstance as FastifyBaseLogger,\n // Fastify's own request/response pair per call — noisy in a dev console,\n // useful as an access log in production. Our own logs are unaffected.\n disableRequestLogging: config.requestLogging === false,\n // Adopt the caller's correlation id when it sends one, so one id joins\n // the client's log line to this process's.\n requestIdHeader: 'x-request-id',\n });\n\n // Enter the request-scoped log context: every line logged inside this\n // request's async scope carries its reqId (and orgId once resolveScope runs),\n // wherever it is emitted. The id is echoed on the response so callers can\n // quote it when reporting a failure.\n app.addHook('onRequest', (request, reply, done) => {\n reply.header('x-request-id', request.id);\n container.requestContext.run({ reqId: request.id }, done);\n });\n\n // Validate + serialize request/response bodies from the shared Zod contract.\n app.setValidatorCompiler(validatorCompiler);\n app.setSerializerCompiler(serializerCompiler);\n app.setErrorHandler(errorHandler);\n app.setNotFoundHandler(notFoundHandler);\n\n registerCors(app, config);\n registerOpenApi(app, config);\n registerAuth(app, container);\n if (container.mcp.oauthEnabled) {\n registerWellKnown(app, container);\n }\n\n registerRoutes(app, container);\n registerMcp(app, container);\n\n // Drain + stop the outbox relay and the automation engine on shutdown.\n // Harmless when neither was started (gen-openapi boots this app with\n // ready() + close() only).\n app.addHook('onClose', async () => {\n await container.outboxRelay.stop();\n await container.automationEngine.stop();\n });\n\n return app;\n}\n"],"mappings":";;;;;;;;;;AAYA,eAAsB,YACpB,QACA,WAC0B;CAI1B,MAAM,MAAM,QAAQ;EAClB,gBAAgB,UAAU;EAG1B,uBAAuB,OAAO,mBAAmB;EAGjD,iBAAiB;CACnB,CAAC;CAMD,IAAI,QAAQ,cAAc,SAAS,OAAO,SAAS;EACjD,MAAM,OAAO,gBAAgB,QAAQ,EAAE;EACvC,UAAU,eAAe,IAAI,EAAE,OAAO,QAAQ,GAAG,GAAG,IAAI;CAC1D,CAAC;CAGD,IAAI,qBAAqB,iBAAiB;CAC1C,IAAI,sBAAsB,kBAAkB;CAC5C,IAAI,gBAAgB,YAAY;CAChC,IAAI,mBAAmB,eAAe;CAEtC,aAAa,KAAK,MAAM;CACxB,gBAAgB,KAAK,MAAM;CAC3B,aAAa,KAAK,SAAS;CAC3B,IAAI,UAAU,IAAI,cAChB,kBAAkB,KAAK,SAAS;CAGlC,eAAe,KAAK,SAAS;CAC7B,YAAY,KAAK,SAAS;CAK1B,IAAI,QAAQ,WAAW,YAAY;EACjC,MAAM,UAAU,YAAY,KAAK;EACjC,MAAM,UAAU,iBAAiB,KAAK;CACxC,CAAC;CAED,OAAO;AACT"}
@@ -1,7 +1,7 @@
1
1
  import { FastifyReply, FastifyRequest } from "fastify";
2
2
  //#region src/http/web-bridge.d.ts
3
3
  /** Builds a Web `Request` from an incoming Fastify request. */
4
- declare function toWebRequest(request: FastifyRequest): Request;
4
+ declare function toWebRequest(request: FastifyRequest, origin: string): Request;
5
5
  /** Copies a Web `Response` back onto a Fastify reply, preserving multiple cookies. */
6
6
  declare function bridgeWebResponse(response: Response, reply: FastifyReply): Promise<void>;
7
7
  //#endregion
@@ -1,8 +1,8 @@
1
1
  import { fromNodeHeaders } from "better-auth/node";
2
2
  //#region src/http/web-bridge.ts
3
3
  /** Builds a Web `Request` from an incoming Fastify request. */
4
- function toWebRequest(request) {
5
- const url = new URL(request.url, `http://${request.headers.host}`);
4
+ function toWebRequest(request, origin) {
5
+ const url = new URL(request.url, origin);
6
6
  const body = request.method !== "GET" && request.method !== "HEAD" && request.method !== "DELETE" ? typeof request.body === "string" ? request.body : request.body ? JSON.stringify(request.body) : void 0 : void 0;
7
7
  return new Request(url.toString(), {
8
8
  method: request.method,
@@ -1 +1 @@
1
- {"version":3,"file":"web-bridge.js","names":[],"sources":["../../src/http/web-bridge.ts"],"sourcesContent":["// Bridges between Fastify's request/reply and the Web `Request`/`Response` that\n// better-auth speaks. The auth catch-all hands a Fastify request to a\n// Web-standard handler and forwards the\n// Web response back, so the conversion lives here once.\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport { fromNodeHeaders } from 'better-auth/node';\n\n/** Builds a Web `Request` from an incoming Fastify request. */\nexport function toWebRequest(request: FastifyRequest): Request {\n const url = new URL(request.url, `http://${request.headers.host}`);\n // GET/HEAD/DELETE never carry a body; passing one to `Request` throws. For the\n // rest, forward a string body verbatim and JSON-encode a parsed object.\n const hasBody =\n request.method !== 'GET' && request.method !== 'HEAD' && request.method !== 'DELETE';\n const body = hasBody\n ? typeof request.body === 'string'\n ? request.body\n : request.body\n ? JSON.stringify(request.body)\n : undefined\n : undefined;\n return new Request(url.toString(), {\n method: request.method,\n headers: fromNodeHeaders(request.headers),\n body,\n });\n}\n\n/** Copies a Web `Response` back onto a Fastify reply, preserving multiple cookies. */\nexport async function bridgeWebResponse(response: Response, reply: FastifyReply): Promise<void> {\n reply.status(response.status);\n // Emit each Set-Cookie value individually — forEach() collapses multiple\n // Set-Cookie headers into one comma-joined string (undici behaviour), which\n // corrupts multi-cookie auth responses. getSetCookie() returns them as an\n // array so each one is forwarded as a separate header.\n const cookies = response.headers.getSetCookie();\n if (cookies.length > 0) {\n reply.raw.setHeader('set-cookie', cookies);\n }\n response.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'set-cookie') {\n return;\n } // already handled above\n reply.header(key, value);\n });\n reply.send(response.body ? await response.text() : null);\n}\n"],"mappings":";;;AAQA,SAAgB,aAAa,SAAkC;CAC7D,MAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,UAAU,QAAQ,QAAQ,MAAM;CAKjE,MAAM,OADJ,QAAQ,WAAW,SAAS,QAAQ,WAAW,UAAU,QAAQ,WAAW,WAE1E,OAAO,QAAQ,SAAS,WACtB,QAAQ,OACR,QAAQ,OACN,KAAK,UAAU,QAAQ,IAAI,IAC3B,KAAA,IACJ,KAAA;CACJ,OAAO,IAAI,QAAQ,IAAI,SAAS,GAAG;EACjC,QAAQ,QAAQ;EAChB,SAAS,gBAAgB,QAAQ,OAAO;EACxC;CACF,CAAC;AACH;;AAGA,eAAsB,kBAAkB,UAAoB,OAAoC;CAC9F,MAAM,OAAO,SAAS,MAAM;CAK5B,MAAM,UAAU,SAAS,QAAQ,aAAa;CAC9C,IAAI,QAAQ,SAAS,GACnB,MAAM,IAAI,UAAU,cAAc,OAAO;CAE3C,SAAS,QAAQ,SAAS,OAAO,QAAQ;EACvC,IAAI,IAAI,YAAY,MAAM,cACxB;EAEF,MAAM,OAAO,KAAK,KAAK;CACzB,CAAC;CACD,MAAM,KAAK,SAAS,OAAO,MAAM,SAAS,KAAK,IAAI,IAAI;AACzD"}
1
+ {"version":3,"file":"web-bridge.js","names":[],"sources":["../../src/http/web-bridge.ts"],"sourcesContent":["// Bridges between Fastify's request/reply and the Web `Request`/`Response` that\n// better-auth speaks. The auth catch-all hands a Fastify request to a\n// Web-standard handler and forwards the\n// Web response back, so the conversion lives here once.\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport { fromNodeHeaders } from 'better-auth/node';\n\n/** Builds a Web `Request` from an incoming Fastify request. */\nexport function toWebRequest(request: FastifyRequest, origin: string): Request {\n const url = new URL(request.url, origin);\n // GET/HEAD/DELETE never carry a body; passing one to `Request` throws. For the\n // rest, forward a string body verbatim and JSON-encode a parsed object.\n const hasBody =\n request.method !== 'GET' && request.method !== 'HEAD' && request.method !== 'DELETE';\n const body = hasBody\n ? typeof request.body === 'string'\n ? request.body\n : request.body\n ? JSON.stringify(request.body)\n : undefined\n : undefined;\n return new Request(url.toString(), {\n method: request.method,\n headers: fromNodeHeaders(request.headers),\n body,\n });\n}\n\n/** Copies a Web `Response` back onto a Fastify reply, preserving multiple cookies. */\nexport async function bridgeWebResponse(response: Response, reply: FastifyReply): Promise<void> {\n reply.status(response.status);\n // Emit each Set-Cookie value individually — forEach() collapses multiple\n // Set-Cookie headers into one comma-joined string (undici behaviour), which\n // corrupts multi-cookie auth responses. getSetCookie() returns them as an\n // array so each one is forwarded as a separate header.\n const cookies = response.headers.getSetCookie();\n if (cookies.length > 0) {\n reply.raw.setHeader('set-cookie', cookies);\n }\n response.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'set-cookie') {\n return;\n } // already handled above\n reply.header(key, value);\n });\n reply.send(response.body ? await response.text() : null);\n}\n"],"mappings":";;;AAQA,SAAgB,aAAa,SAAyB,QAAyB;CAC7E,MAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,MAAM;CAKvC,MAAM,OADJ,QAAQ,WAAW,SAAS,QAAQ,WAAW,UAAU,QAAQ,WAAW,WAE1E,OAAO,QAAQ,SAAS,WACtB,QAAQ,OACR,QAAQ,OACN,KAAK,UAAU,QAAQ,IAAI,IAC3B,KAAA,IACJ,KAAA;CACJ,OAAO,IAAI,QAAQ,IAAI,SAAS,GAAG;EACjC,QAAQ,QAAQ;EAChB,SAAS,gBAAgB,QAAQ,OAAO;EACxC;CACF,CAAC;AACH;;AAGA,eAAsB,kBAAkB,UAAoB,OAAoC;CAC9F,MAAM,OAAO,SAAS,MAAM;CAK5B,MAAM,UAAU,SAAS,QAAQ,aAAa;CAC9C,IAAI,QAAQ,SAAS,GACnB,MAAM,IAAI,UAAU,cAAc,OAAO;CAE3C,SAAS,QAAQ,SAAS,OAAO,QAAQ;EACvC,IAAI,IAAI,YAAY,MAAM,cACxB;EAEF,MAAM,OAAO,KAAK,KAAK;CACzB,CAAC;CACD,MAAM,KAAK,SAAS,OAAO,MAAM,SAAS,KAAK,IAAI,IAAI;AACzD"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/well-known.d.ts
4
+ declare function registerWellKnown(app: FastifyInstance, container: Container): void;
5
+ //#endregion
6
+ export { registerWellKnown };
7
+ //# sourceMappingURL=well-known.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { bridgeWebResponse, toWebRequest } from "./web-bridge.js";
2
+ import { ACCESS_SCOPES } from "@headless-lms/core/organizations";
3
+ //#region src/http/well-known.ts
4
+ function registerWellKnown(app, container) {
5
+ const origin = new URL(container.mcp.issuer).origin;
6
+ const resourceMetadata = () => ({
7
+ resource: container.mcp.resource,
8
+ authorization_servers: [container.mcp.issuer],
9
+ scopes_supported: [...ACCESS_SCOPES],
10
+ bearer_methods_supported: ["header"]
11
+ });
12
+ const hidden = { schema: { hide: true } };
13
+ app.get("/.well-known/oauth-protected-resource/mcp", hidden, async () => resourceMetadata());
14
+ app.get("/.well-known/oauth-protected-resource", hidden, async () => resourceMetadata());
15
+ app.get("/.well-known/oauth-authorization-server/api/auth", hidden, async (request, reply) => {
16
+ await bridgeWebResponse(await container.auth.authorizationServerMetadata(toWebRequest(request, origin)), reply);
17
+ });
18
+ }
19
+ //#endregion
20
+ export { registerWellKnown };
21
+
22
+ //# sourceMappingURL=well-known.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.js","names":[],"sources":["../../src/http/well-known.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport { ACCESS_SCOPES } from '@headless-lms/core/organizations';\nimport type { Container } from '../app/container.js';\nimport { bridgeWebResponse, toWebRequest } from './web-bridge.js';\n\nexport function registerWellKnown(app: FastifyInstance, container: Container): void {\n const origin = new URL(container.mcp.issuer).origin;\n const resourceMetadata = () => ({\n resource: container.mcp.resource,\n authorization_servers: [container.mcp.issuer],\n scopes_supported: [...ACCESS_SCOPES],\n bearer_methods_supported: ['header'],\n });\n const hidden = { schema: { hide: true } };\n\n app.get('/.well-known/oauth-protected-resource/mcp', hidden, async () => resourceMetadata());\n app.get('/.well-known/oauth-protected-resource', hidden, async () => resourceMetadata());\n app.get('/.well-known/oauth-authorization-server/api/auth', hidden, async (request, reply) => {\n await bridgeWebResponse(\n await container.auth.authorizationServerMetadata(toWebRequest(request, origin)),\n reply,\n );\n });\n}\n"],"mappings":";;;AAKA,SAAgB,kBAAkB,KAAsB,WAA4B;CAClF,MAAM,SAAS,IAAI,IAAI,UAAU,IAAI,MAAM,CAAC,CAAC;CAC7C,MAAM,0BAA0B;EAC9B,UAAU,UAAU,IAAI;EACxB,uBAAuB,CAAC,UAAU,IAAI,MAAM;EAC5C,kBAAkB,CAAC,GAAG,aAAa;EACnC,0BAA0B,CAAC,QAAQ;CACrC;CACA,MAAM,SAAS,EAAE,QAAQ,EAAE,MAAM,KAAK,EAAE;CAExC,IAAI,IAAI,6CAA6C,QAAQ,YAAY,iBAAiB,CAAC;CAC3F,IAAI,IAAI,yCAAyC,QAAQ,YAAY,iBAAiB,CAAC;CACvF,IAAI,IAAI,oDAAoD,QAAQ,OAAO,SAAS,UAAU;EAC5F,MAAM,kBACJ,MAAM,UAAU,KAAK,4BAA4B,aAAa,SAAS,MAAM,CAAC,GAC9E,KACF;CACF,CAAC;AACH"}
package/dist/index.d.ts CHANGED
@@ -2,14 +2,15 @@ import { AuthUser } from "./http/fastify.js";
2
2
  import { AdapterOverrides, BuildContainerOptions, Config, Container, LoggingConfig } from "./app/container.js";
3
3
  import { loadIntegrations } from "./app/integrations.js";
4
4
  import { ServerConfig } from "./http/config.js";
5
+ import { CatalogueField, CatalogueScope, CatalogueTool, McpCatalogue, mcpCatalogue } from "./http/mcp/catalogue.js";
5
6
  import { buildServer } from "./http/server.js";
6
7
  import { runMigrations } from "@headless-lms/adapter-db";
7
8
  import { InlineAutomationEngine } from "@headless-lms/adapter-defaults/workflows";
8
- import { AutomationEngine } from "@headless-lms/core/automations";
9
+ import { AutomationEngine, WebhookSender } from "@headless-lms/core/automations";
9
10
  import { Mailer } from "@headless-lms/core/shared/mailer";
10
11
  import { EmailMessage, EmailSender, ObjectStorage } from "@headless-lms/core/shared/ports";
11
12
  //#region src/index.d.ts
12
13
  declare function createContainer(config: ServerConfig, options?: BuildContainerOptions): Promise<Container>;
13
14
  //#endregion
14
- export { type AdapterOverrides, type AuthUser, type AutomationEngine, type BuildContainerOptions, type Container, type Config as ContainerConfig, type EmailMessage, type EmailSender, InlineAutomationEngine, type LoggingConfig, type Mailer, type ObjectStorage, type ServerConfig, buildServer, createContainer, loadIntegrations, runMigrations };
15
+ export { type AdapterOverrides, type AuthUser, type AutomationEngine, type BuildContainerOptions, type CatalogueField, type CatalogueScope, type CatalogueTool, type Container, type Config as ContainerConfig, type EmailMessage, type EmailSender, InlineAutomationEngine, type LoggingConfig, type Mailer, type McpCatalogue, type ObjectStorage, type ServerConfig, type WebhookSender, buildServer, createContainer, loadIntegrations, mcpCatalogue, runMigrations };
15
16
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,16 +1,18 @@
1
1
  import { loadIntegrations } from "./app/integrations.js";
2
2
  import { buildContainer } from "./app/container.js";
3
3
  import { buildServer } from "./http/server.js";
4
+ import { mcpCatalogue } from "./http/mcp/catalogue.js";
4
5
  import { runMigrations } from "@headless-lms/adapter-db";
5
6
  import { InlineAutomationEngine } from "@headless-lms/adapter-defaults/workflows";
6
7
  //#region src/index.ts
7
8
  async function createContainer(config, options) {
8
9
  return buildContainer({
9
10
  ...config.container,
10
- deliveryExpirySeconds: config.deliveryExpirySeconds
11
+ deliveryExpirySeconds: config.deliveryExpirySeconds,
12
+ memberImageMaxBytes: config.memberImageMaxBytes
11
13
  }, options);
12
14
  }
13
15
  //#endregion
14
- export { InlineAutomationEngine, buildServer, createContainer, loadIntegrations, runMigrations };
16
+ export { InlineAutomationEngine, buildServer, createContainer, loadIntegrations, mcpCatalogue, runMigrations };
15
17
 
16
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// Public surface of @headless-lms/server. Installations compose these:\n// const container = await createContainer(config, { pluginsDir, adapters })\n// const app = await buildServer(config, container)\nimport {\n buildContainer,\n type BuildContainerOptions,\n type Container,\n} from './app/container.js';\nimport type { ServerConfig } from './http/config.js';\n\nexport { buildServer } from './http/server.js';\nexport { loadIntegrations } from './app/integrations.js';\nexport { InlineAutomationEngine } from '@headless-lms/adapter-defaults/workflows';\n// Operational functions consumed by the @headless-lms/cli bin.\nexport { runMigrations } from '@headless-lms/adapter-db';\nexport type { ServerConfig } from './http/config.js';\n// Re-exporting AuthUser also pulls its module into any program that imports\n// this file (directly or via the workspace path mapping), which is what\n// applies its ambient `declare module \"fastify\"` augmentation\n// (FastifyRequest.authUser/orgId, FastifyInstance.requireOrgSession) —\n// otherwise nothing imports fastify.d.ts and the augmentation never loads.\nexport type { AuthUser } from './http/fastify.js';\nexport type {\n Config as ContainerConfig,\n Container,\n AdapterOverrides,\n BuildContainerOptions,\n LoggingConfig,\n} from './app/container.js';\nexport type { EmailSender, EmailMessage, ObjectStorage } from '@headless-lms/core/shared/ports';\nexport type { Mailer } from '@headless-lms/core/shared/mailer';\nexport type { AutomationEngine } from '@headless-lms/core/automations';\n\nexport async function createContainer(\n config: ServerConfig,\n options?: BuildContainerOptions,\n): Promise<Container> {\n return buildContainer(\n { ...config.container, deliveryExpirySeconds: config.deliveryExpirySeconds },\n options,\n );\n}\n"],"mappings":";;;;;;AAiCA,eAAsB,gBACpB,QACA,SACoB;CACpB,OAAO,eACL;EAAE,GAAG,OAAO;EAAW,uBAAuB,OAAO;CAAsB,GAC3E,OACF;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// Public surface of @headless-lms/server. Installations compose these:\n// const container = await createContainer(config, { pluginsDir, adapters })\n// const app = await buildServer(config, container)\nimport { buildContainer, type BuildContainerOptions, type Container } from './app/container.js';\nimport type { ServerConfig } from './http/config.js';\n\nexport { buildServer } from './http/server.js';\nexport { mcpCatalogue } from './http/mcp/catalogue.js';\nexport type {\n CatalogueField,\n CatalogueScope,\n CatalogueTool,\n McpCatalogue,\n} from './http/mcp/catalogue.js';\nexport { loadIntegrations } from './app/integrations.js';\nexport { InlineAutomationEngine } from '@headless-lms/adapter-defaults/workflows';\n// Operational functions consumed by the @headless-lms/cli bin.\nexport { runMigrations } from '@headless-lms/adapter-db';\nexport type { ServerConfig } from './http/config.js';\n// Re-exporting AuthUser also pulls its module into any program that imports\n// this file (directly or via the workspace path mapping), which is what\n// applies its ambient `declare module \"fastify\"` augmentation\n// (FastifyRequest.authUser/orgId, FastifyInstance.requireOrgSession) —\n// otherwise nothing imports fastify.d.ts and the augmentation never loads.\nexport type { AuthUser } from './http/fastify.js';\nexport type {\n Config as ContainerConfig,\n Container,\n AdapterOverrides,\n BuildContainerOptions,\n LoggingConfig,\n} from './app/container.js';\nexport type { EmailSender, EmailMessage, ObjectStorage } from '@headless-lms/core/shared/ports';\nexport type { Mailer } from '@headless-lms/core/shared/mailer';\nexport type { AutomationEngine, WebhookSender } from '@headless-lms/core/automations';\n\nexport async function createContainer(\n config: ServerConfig,\n options?: BuildContainerOptions,\n): Promise<Container> {\n return buildContainer(\n {\n ...config.container,\n deliveryExpirySeconds: config.deliveryExpirySeconds,\n memberImageMaxBytes: config.memberImageMaxBytes,\n },\n options,\n );\n}\n"],"mappings":";;;;;;;AAoCA,eAAsB,gBACpB,QACA,SACoB;CACpB,OAAO,eACL;EACE,GAAG,OAAO;EACV,uBAAuB,OAAO;EAC9B,qBAAqB,OAAO;CAC9B,GACA,OACF;AACF"}
@@ -0,0 +1,78 @@
1
+ //#region ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
2
+ var comma = ",".charCodeAt(0);
3
+ var semicolon = ";".charCodeAt(0);
4
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5
+ var intToChar = /* @__PURE__ */ new Uint8Array(64);
6
+ var charToInt = /* @__PURE__ */ new Uint8Array(128);
7
+ for (let i = 0; i < chars.length; i++) {
8
+ const c = chars.charCodeAt(i);
9
+ intToChar[i] = c;
10
+ charToInt[c] = i;
11
+ }
12
+ function encodeInteger(builder, num, relative) {
13
+ let delta = num - relative;
14
+ delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
15
+ do {
16
+ let clamped = delta & 31;
17
+ delta >>>= 5;
18
+ if (delta > 0) clamped |= 32;
19
+ builder.write(intToChar[clamped]);
20
+ } while (delta > 0);
21
+ return num;
22
+ }
23
+ var bufLength = 1024 * 16;
24
+ var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? { decode(buf) {
25
+ return Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength).toString();
26
+ } } : { decode(buf) {
27
+ let out = "";
28
+ for (let i = 0; i < buf.length; i++) out += String.fromCharCode(buf[i]);
29
+ return out;
30
+ } };
31
+ var StringWriter = class {
32
+ constructor() {
33
+ this.pos = 0;
34
+ this.out = "";
35
+ this.buffer = new Uint8Array(bufLength);
36
+ }
37
+ write(v) {
38
+ const { buffer } = this;
39
+ buffer[this.pos++] = v;
40
+ if (this.pos === bufLength) {
41
+ this.out += td.decode(buffer);
42
+ this.pos = 0;
43
+ }
44
+ }
45
+ flush() {
46
+ const { buffer, out, pos } = this;
47
+ return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
48
+ }
49
+ };
50
+ function encode(decoded) {
51
+ const writer = new StringWriter();
52
+ let sourcesIndex = 0;
53
+ let sourceLine = 0;
54
+ let sourceColumn = 0;
55
+ let namesIndex = 0;
56
+ for (let i = 0; i < decoded.length; i++) {
57
+ const line = decoded[i];
58
+ if (i > 0) writer.write(semicolon);
59
+ if (line.length === 0) continue;
60
+ let genColumn = 0;
61
+ for (let j = 0; j < line.length; j++) {
62
+ const segment = line[j];
63
+ if (j > 0) writer.write(comma);
64
+ genColumn = encodeInteger(writer, segment[0], genColumn);
65
+ if (segment.length === 1) continue;
66
+ sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
67
+ sourceLine = encodeInteger(writer, segment[2], sourceLine);
68
+ sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
69
+ if (segment.length === 4) continue;
70
+ namesIndex = encodeInteger(writer, segment[4], namesIndex);
71
+ }
72
+ }
73
+ return writer.flush();
74
+ }
75
+ //#endregion
76
+ export { encode };
77
+
78
+ //# sourceMappingURL=sourcemap-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sourcemap-codec.js","names":[],"sources":["../../../../../../../../../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs"],"sourcesContent":["// src/vlq.ts\nvar comma = \",\".charCodeAt(0);\nvar semicolon = \";\".charCodeAt(0);\nvar chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nvar intToChar = new Uint8Array(64);\nvar charToInt = new Uint8Array(128);\nfor (let i = 0; i < chars.length; i++) {\n const c = chars.charCodeAt(i);\n intToChar[i] = c;\n charToInt[c] = i;\n}\nfunction decodeInteger(reader, relative) {\n let value = 0;\n let shift = 0;\n let integer = 0;\n do {\n const c = reader.next();\n integer = charToInt[c];\n value |= (integer & 31) << shift;\n shift += 5;\n } while (integer & 32);\n const shouldNegate = value & 1;\n value >>>= 1;\n if (shouldNegate) {\n value = -2147483648 | -value;\n }\n return relative + value;\n}\nfunction encodeInteger(builder, num, relative) {\n let delta = num - relative;\n delta = delta < 0 ? -delta << 1 | 1 : delta << 1;\n do {\n let clamped = delta & 31;\n delta >>>= 5;\n if (delta > 0) clamped |= 32;\n builder.write(intToChar[clamped]);\n } while (delta > 0);\n return num;\n}\nfunction hasMoreVlq(reader, max) {\n if (reader.pos >= max) return false;\n return reader.peek() !== comma;\n}\n\n// src/strings.ts\nvar bufLength = 1024 * 16;\nvar td = typeof TextDecoder !== \"undefined\" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== \"undefined\" ? {\n decode(buf) {\n const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);\n return out.toString();\n }\n} : {\n decode(buf) {\n let out = \"\";\n for (let i = 0; i < buf.length; i++) {\n out += String.fromCharCode(buf[i]);\n }\n return out;\n }\n};\nvar StringWriter = class {\n constructor() {\n this.pos = 0;\n this.out = \"\";\n this.buffer = new Uint8Array(bufLength);\n }\n write(v) {\n const { buffer } = this;\n buffer[this.pos++] = v;\n if (this.pos === bufLength) {\n this.out += td.decode(buffer);\n this.pos = 0;\n }\n }\n flush() {\n const { buffer, out, pos } = this;\n return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;\n }\n};\nvar StringReader = class {\n constructor(buffer) {\n this.pos = 0;\n this.buffer = buffer;\n }\n next() {\n return this.buffer.charCodeAt(this.pos++);\n }\n peek() {\n return this.buffer.charCodeAt(this.pos);\n }\n indexOf(char) {\n const { buffer, pos } = this;\n const idx = buffer.indexOf(char, pos);\n return idx === -1 ? buffer.length : idx;\n }\n};\n\n// src/scopes.ts\nvar EMPTY = [];\nfunction decodeOriginalScopes(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const scopes = [];\n const stack = [];\n let line = 0;\n for (; reader.pos < length; reader.pos++) {\n line = decodeInteger(reader, line);\n const column = decodeInteger(reader, 0);\n if (!hasMoreVlq(reader, length)) {\n const last = stack.pop();\n last[2] = line;\n last[3] = column;\n continue;\n }\n const kind = decodeInteger(reader, 0);\n const fields = decodeInteger(reader, 0);\n const hasName = fields & 1;\n const scope = hasName ? [line, column, 0, 0, kind, decodeInteger(reader, 0)] : [line, column, 0, 0, kind];\n let vars = EMPTY;\n if (hasMoreVlq(reader, length)) {\n vars = [];\n do {\n const varsIndex = decodeInteger(reader, 0);\n vars.push(varsIndex);\n } while (hasMoreVlq(reader, length));\n }\n scope.vars = vars;\n scopes.push(scope);\n stack.push(scope);\n }\n return scopes;\n}\nfunction encodeOriginalScopes(scopes) {\n const writer = new StringWriter();\n for (let i = 0; i < scopes.length; ) {\n i = _encodeOriginalScopes(scopes, i, writer, [0]);\n }\n return writer.flush();\n}\nfunction _encodeOriginalScopes(scopes, index, writer, state) {\n const scope = scopes[index];\n const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, 4: kind, vars } = scope;\n if (index > 0) writer.write(comma);\n state[0] = encodeInteger(writer, startLine, state[0]);\n encodeInteger(writer, startColumn, 0);\n encodeInteger(writer, kind, 0);\n const fields = scope.length === 6 ? 1 : 0;\n encodeInteger(writer, fields, 0);\n if (scope.length === 6) encodeInteger(writer, scope[5], 0);\n for (const v of vars) {\n encodeInteger(writer, v, 0);\n }\n for (index++; index < scopes.length; ) {\n const next = scopes[index];\n const { 0: l, 1: c } = next;\n if (l > endLine || l === endLine && c >= endColumn) {\n break;\n }\n index = _encodeOriginalScopes(scopes, index, writer, state);\n }\n writer.write(comma);\n state[0] = encodeInteger(writer, endLine, state[0]);\n encodeInteger(writer, endColumn, 0);\n return index;\n}\nfunction decodeGeneratedRanges(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const ranges = [];\n const stack = [];\n let genLine = 0;\n let definitionSourcesIndex = 0;\n let definitionScopeIndex = 0;\n let callsiteSourcesIndex = 0;\n let callsiteLine = 0;\n let callsiteColumn = 0;\n let bindingLine = 0;\n let bindingColumn = 0;\n do {\n const semi = reader.indexOf(\";\");\n let genColumn = 0;\n for (; reader.pos < semi; reader.pos++) {\n genColumn = decodeInteger(reader, genColumn);\n if (!hasMoreVlq(reader, semi)) {\n const last = stack.pop();\n last[2] = genLine;\n last[3] = genColumn;\n continue;\n }\n const fields = decodeInteger(reader, 0);\n const hasDefinition = fields & 1;\n const hasCallsite = fields & 2;\n const hasScope = fields & 4;\n let callsite = null;\n let bindings = EMPTY;\n let range;\n if (hasDefinition) {\n const defSourcesIndex = decodeInteger(reader, definitionSourcesIndex);\n definitionScopeIndex = decodeInteger(\n reader,\n definitionSourcesIndex === defSourcesIndex ? definitionScopeIndex : 0\n );\n definitionSourcesIndex = defSourcesIndex;\n range = [genLine, genColumn, 0, 0, defSourcesIndex, definitionScopeIndex];\n } else {\n range = [genLine, genColumn, 0, 0];\n }\n range.isScope = !!hasScope;\n if (hasCallsite) {\n const prevCsi = callsiteSourcesIndex;\n const prevLine = callsiteLine;\n callsiteSourcesIndex = decodeInteger(reader, callsiteSourcesIndex);\n const sameSource = prevCsi === callsiteSourcesIndex;\n callsiteLine = decodeInteger(reader, sameSource ? callsiteLine : 0);\n callsiteColumn = decodeInteger(\n reader,\n sameSource && prevLine === callsiteLine ? callsiteColumn : 0\n );\n callsite = [callsiteSourcesIndex, callsiteLine, callsiteColumn];\n }\n range.callsite = callsite;\n if (hasMoreVlq(reader, semi)) {\n bindings = [];\n do {\n bindingLine = genLine;\n bindingColumn = genColumn;\n const expressionsCount = decodeInteger(reader, 0);\n let expressionRanges;\n if (expressionsCount < -1) {\n expressionRanges = [[decodeInteger(reader, 0)]];\n for (let i = -1; i > expressionsCount; i--) {\n const prevBl = bindingLine;\n bindingLine = decodeInteger(reader, bindingLine);\n bindingColumn = decodeInteger(reader, bindingLine === prevBl ? bindingColumn : 0);\n const expression = decodeInteger(reader, 0);\n expressionRanges.push([expression, bindingLine, bindingColumn]);\n }\n } else {\n expressionRanges = [[expressionsCount]];\n }\n bindings.push(expressionRanges);\n } while (hasMoreVlq(reader, semi));\n }\n range.bindings = bindings;\n ranges.push(range);\n stack.push(range);\n }\n genLine++;\n reader.pos = semi + 1;\n } while (reader.pos < length);\n return ranges;\n}\nfunction encodeGeneratedRanges(ranges) {\n if (ranges.length === 0) return \"\";\n const writer = new StringWriter();\n for (let i = 0; i < ranges.length; ) {\n i = _encodeGeneratedRanges(ranges, i, writer, [0, 0, 0, 0, 0, 0, 0]);\n }\n return writer.flush();\n}\nfunction _encodeGeneratedRanges(ranges, index, writer, state) {\n const range = ranges[index];\n const {\n 0: startLine,\n 1: startColumn,\n 2: endLine,\n 3: endColumn,\n isScope,\n callsite,\n bindings\n } = range;\n if (state[0] < startLine) {\n catchupLine(writer, state[0], startLine);\n state[0] = startLine;\n state[1] = 0;\n } else if (index > 0) {\n writer.write(comma);\n }\n state[1] = encodeInteger(writer, range[1], state[1]);\n const fields = (range.length === 6 ? 1 : 0) | (callsite ? 2 : 0) | (isScope ? 4 : 0);\n encodeInteger(writer, fields, 0);\n if (range.length === 6) {\n const { 4: sourcesIndex, 5: scopesIndex } = range;\n if (sourcesIndex !== state[2]) {\n state[3] = 0;\n }\n state[2] = encodeInteger(writer, sourcesIndex, state[2]);\n state[3] = encodeInteger(writer, scopesIndex, state[3]);\n }\n if (callsite) {\n const { 0: sourcesIndex, 1: callLine, 2: callColumn } = range.callsite;\n if (sourcesIndex !== state[4]) {\n state[5] = 0;\n state[6] = 0;\n } else if (callLine !== state[5]) {\n state[6] = 0;\n }\n state[4] = encodeInteger(writer, sourcesIndex, state[4]);\n state[5] = encodeInteger(writer, callLine, state[5]);\n state[6] = encodeInteger(writer, callColumn, state[6]);\n }\n if (bindings) {\n for (const binding of bindings) {\n if (binding.length > 1) encodeInteger(writer, -binding.length, 0);\n const expression = binding[0][0];\n encodeInteger(writer, expression, 0);\n let bindingStartLine = startLine;\n let bindingStartColumn = startColumn;\n for (let i = 1; i < binding.length; i++) {\n const expRange = binding[i];\n bindingStartLine = encodeInteger(writer, expRange[1], bindingStartLine);\n bindingStartColumn = encodeInteger(writer, expRange[2], bindingStartColumn);\n encodeInteger(writer, expRange[0], 0);\n }\n }\n }\n for (index++; index < ranges.length; ) {\n const next = ranges[index];\n const { 0: l, 1: c } = next;\n if (l > endLine || l === endLine && c >= endColumn) {\n break;\n }\n index = _encodeGeneratedRanges(ranges, index, writer, state);\n }\n if (state[0] < endLine) {\n catchupLine(writer, state[0], endLine);\n state[0] = endLine;\n state[1] = 0;\n } else {\n writer.write(comma);\n }\n state[1] = encodeInteger(writer, endColumn, state[1]);\n return index;\n}\nfunction catchupLine(writer, lastLine, line) {\n do {\n writer.write(semicolon);\n } while (++lastLine < line);\n}\n\n// src/sourcemap-codec.ts\nfunction decode(mappings) {\n const { length } = mappings;\n const reader = new StringReader(mappings);\n const decoded = [];\n let genColumn = 0;\n let sourcesIndex = 0;\n let sourceLine = 0;\n let sourceColumn = 0;\n let namesIndex = 0;\n do {\n const semi = reader.indexOf(\";\");\n const line = [];\n let sorted = true;\n let lastCol = 0;\n genColumn = 0;\n while (reader.pos < semi) {\n let seg;\n genColumn = decodeInteger(reader, genColumn);\n if (genColumn < lastCol) sorted = false;\n lastCol = genColumn;\n if (hasMoreVlq(reader, semi)) {\n sourcesIndex = decodeInteger(reader, sourcesIndex);\n sourceLine = decodeInteger(reader, sourceLine);\n sourceColumn = decodeInteger(reader, sourceColumn);\n if (hasMoreVlq(reader, semi)) {\n namesIndex = decodeInteger(reader, namesIndex);\n seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];\n } else {\n seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];\n }\n } else {\n seg = [genColumn];\n }\n line.push(seg);\n reader.pos++;\n }\n if (!sorted) sort(line);\n decoded.push(line);\n reader.pos = semi + 1;\n } while (reader.pos <= length);\n return decoded;\n}\nfunction sort(line) {\n line.sort(sortComparator);\n}\nfunction sortComparator(a, b) {\n return a[0] - b[0];\n}\nfunction encode(decoded) {\n const writer = new StringWriter();\n let sourcesIndex = 0;\n let sourceLine = 0;\n let sourceColumn = 0;\n let namesIndex = 0;\n for (let i = 0; i < decoded.length; i++) {\n const line = decoded[i];\n if (i > 0) writer.write(semicolon);\n if (line.length === 0) continue;\n let genColumn = 0;\n for (let j = 0; j < line.length; j++) {\n const segment = line[j];\n if (j > 0) writer.write(comma);\n genColumn = encodeInteger(writer, segment[0], genColumn);\n if (segment.length === 1) continue;\n sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);\n sourceLine = encodeInteger(writer, segment[2], sourceLine);\n sourceColumn = encodeInteger(writer, segment[3], sourceColumn);\n if (segment.length === 4) continue;\n namesIndex = encodeInteger(writer, segment[4], namesIndex);\n }\n }\n return writer.flush();\n}\nexport {\n decode,\n decodeGeneratedRanges,\n decodeOriginalScopes,\n encode,\n encodeGeneratedRanges,\n encodeOriginalScopes\n};\n//# sourceMappingURL=sourcemap-codec.mjs.map\n"],"x_google_ignoreList":[0],"mappings":";AACA,IAAI,QAAQ,IAAI,WAAW,CAAC;AAC5B,IAAI,YAAY,IAAI,WAAW,CAAC;AAChC,IAAI,QAAQ;AACZ,IAAI,4BAAY,IAAI,WAAW,EAAE;AACjC,IAAI,4BAAY,IAAI,WAAW,GAAG;AAClC,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;CACrC,MAAM,IAAI,MAAM,WAAW,CAAC;CAC5B,UAAU,KAAK;CACf,UAAU,KAAK;AACjB;AAkBA,SAAS,cAAc,SAAS,KAAK,UAAU;CAC7C,IAAI,QAAQ,MAAM;CAClB,QAAQ,QAAQ,IAAI,CAAC,SAAS,IAAI,IAAI,SAAS;CAC/C,GAAG;EACD,IAAI,UAAU,QAAQ;EACtB,WAAW;EACX,IAAI,QAAQ,GAAG,WAAW;EAC1B,QAAQ,MAAM,UAAU,QAAQ;CAClC,SAAS,QAAQ;CACjB,OAAO;AACT;AAOA,IAAI,YAAY,OAAO;AACvB,IAAI,KAAK,OAAO,gBAAgB,8BAA8B,IAAI,YAAY,IAAI,OAAO,WAAW,cAAc,EAChH,OAAO,KAAK;CAEV,OADY,OAAO,KAAK,IAAI,QAAQ,IAAI,YAAY,IAAI,UAC/C,CAAC,CAAC,SAAS;AACtB,EACF,IAAI,EACF,OAAO,KAAK;CACV,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAC9B,OAAO,OAAO,aAAa,IAAI,EAAE;CAEnC,OAAO;AACT,EACF;AACA,IAAI,eAAe,MAAM;CACvB,cAAc;EACZ,KAAK,MAAM;EACX,KAAK,MAAM;EACX,KAAK,SAAS,IAAI,WAAW,SAAS;CACxC;CACA,MAAM,GAAG;EACP,MAAM,EAAE,WAAW;EACnB,OAAO,KAAK,SAAS;EACrB,IAAI,KAAK,QAAQ,WAAW;GAC1B,KAAK,OAAO,GAAG,OAAO,MAAM;GAC5B,KAAK,MAAM;EACb;CACF;CACA,QAAQ;EACN,MAAM,EAAE,QAAQ,KAAK,QAAQ;EAC7B,OAAO,MAAM,IAAI,MAAM,GAAG,OAAO,OAAO,SAAS,GAAG,GAAG,CAAC,IAAI;CAC9D;AACF;AAuTA,SAAS,OAAO,SAAS;CACvB,MAAM,SAAS,IAAI,aAAa;CAChC,IAAI,eAAe;CACnB,IAAI,aAAa;CACjB,IAAI,eAAe;CACnB,IAAI,aAAa;CACjB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,OAAO,QAAQ;EACrB,IAAI,IAAI,GAAG,OAAO,MAAM,SAAS;EACjC,IAAI,KAAK,WAAW,GAAG;EACvB,IAAI,YAAY;EAChB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,UAAU,KAAK;GACrB,IAAI,IAAI,GAAG,OAAO,MAAM,KAAK;GAC7B,YAAY,cAAc,QAAQ,QAAQ,IAAI,SAAS;GACvD,IAAI,QAAQ,WAAW,GAAG;GAC1B,eAAe,cAAc,QAAQ,QAAQ,IAAI,YAAY;GAC7D,aAAa,cAAc,QAAQ,QAAQ,IAAI,UAAU;GACzD,eAAe,cAAc,QAAQ,QAAQ,IAAI,YAAY;GAC7D,IAAI,QAAQ,WAAW,GAAG;GAC1B,aAAa,cAAc,QAAQ,QAAQ,IAAI,UAAU;EAC3D;CACF;CACA,OAAO,OAAO,MAAM;AACtB"}