@aphexcms/cms-core 3.0.0 → 5.0.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 (311) hide show
  1. package/dist/api/schemas/user.d.ts +10 -0
  2. package/dist/api/schemas/user.d.ts.map +1 -1
  3. package/dist/api/schemas/user.js +10 -0
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +1 -2
  6. package/dist/hooks.d.ts +3 -4
  7. package/dist/hooks.d.ts.map +1 -1
  8. package/dist/hooks.js +20 -99
  9. package/dist/index.d.ts +9 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +43 -4
  12. package/dist/lib/api/schemas/user.d.ts +10 -0
  13. package/dist/lib/api/schemas/user.d.ts.map +1 -1
  14. package/dist/lib/api/schemas/user.js +10 -0
  15. package/dist/lib/api/schemas/user.js.map +1 -1
  16. package/dist/lib/config.d.ts.map +1 -1
  17. package/dist/lib/config.js +1 -2
  18. package/dist/lib/config.js.map +1 -1
  19. package/dist/lib/hooks.d.ts +3 -4
  20. package/dist/lib/hooks.d.ts.map +1 -1
  21. package/dist/lib/hooks.js +20 -99
  22. package/dist/lib/hooks.js.map +1 -1
  23. package/dist/lib/index.d.ts +9 -1
  24. package/dist/lib/index.d.ts.map +1 -1
  25. package/dist/lib/index.js +43 -4
  26. package/dist/lib/index.js.map +1 -1
  27. package/dist/lib/server/api/index.d.ts +55 -0
  28. package/dist/lib/server/api/index.d.ts.map +1 -0
  29. package/dist/lib/server/api/index.js +107 -0
  30. package/dist/lib/server/api/index.js.map +1 -0
  31. package/dist/lib/server/api/routes/assets-bulk.d.ts +4 -0
  32. package/dist/lib/server/api/routes/assets-bulk.d.ts.map +1 -0
  33. package/dist/{routes → lib/server/api/routes}/assets-bulk.js +23 -23
  34. package/dist/lib/server/api/routes/assets-bulk.js.map +1 -0
  35. package/dist/lib/server/api/routes/assets-by-id.d.ts +4 -0
  36. package/dist/lib/server/api/routes/assets-by-id.d.ts.map +1 -0
  37. package/dist/lib/server/api/routes/assets-by-id.js +108 -0
  38. package/dist/lib/server/api/routes/assets-by-id.js.map +1 -0
  39. package/dist/lib/server/api/routes/assets-references.d.ts +15 -0
  40. package/dist/lib/server/api/routes/assets-references.d.ts.map +1 -0
  41. package/dist/lib/server/api/routes/assets-references.js +78 -0
  42. package/dist/lib/server/api/routes/assets-references.js.map +1 -0
  43. package/dist/lib/server/api/routes/assets.d.ts +4 -0
  44. package/dist/lib/server/api/routes/assets.d.ts.map +1 -0
  45. package/dist/{routes → lib/server/api/routes}/assets.js +76 -87
  46. package/dist/lib/server/api/routes/assets.js.map +1 -0
  47. package/dist/lib/server/api/routes/document-versions.d.ts +4 -0
  48. package/dist/lib/server/api/routes/document-versions.d.ts.map +1 -0
  49. package/dist/lib/server/api/routes/document-versions.js +113 -0
  50. package/dist/lib/server/api/routes/document-versions.js.map +1 -0
  51. package/dist/lib/server/api/routes/documents-by-id.d.ts +4 -0
  52. package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -0
  53. package/dist/lib/server/api/routes/documents-by-id.js +148 -0
  54. package/dist/lib/server/api/routes/documents-by-id.js.map +1 -0
  55. package/dist/lib/server/api/routes/documents-publish.d.ts +4 -0
  56. package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -0
  57. package/dist/{routes → lib/server/api/routes}/documents-publish.js +42 -58
  58. package/dist/lib/server/api/routes/documents-publish.js.map +1 -0
  59. package/dist/lib/server/api/routes/documents-query.d.ts +8 -0
  60. package/dist/lib/server/api/routes/documents-query.d.ts.map +1 -0
  61. package/dist/lib/server/api/routes/documents-query.js +75 -0
  62. package/dist/lib/server/api/routes/documents-query.js.map +1 -0
  63. package/dist/lib/server/api/routes/documents.d.ts +4 -0
  64. package/dist/lib/server/api/routes/documents.d.ts.map +1 -0
  65. package/dist/{routes → lib/server/api/routes}/documents.js +55 -76
  66. package/dist/lib/server/api/routes/documents.js.map +1 -0
  67. package/dist/lib/server/api/routes/organizations-by-id.d.ts +4 -0
  68. package/dist/lib/server/api/routes/organizations-by-id.d.ts.map +1 -0
  69. package/dist/{routes → lib/server/api/routes}/organizations-by-id.js +62 -91
  70. package/dist/lib/server/api/routes/organizations-by-id.js.map +1 -0
  71. package/dist/lib/server/api/routes/organizations-invitations.d.ts +10 -0
  72. package/dist/lib/server/api/routes/organizations-invitations.d.ts.map +1 -0
  73. package/dist/{routes → lib/server/api/routes}/organizations-invitations.js +67 -78
  74. package/dist/lib/server/api/routes/organizations-invitations.js.map +1 -0
  75. package/dist/lib/server/api/routes/organizations-members.d.ts +4 -0
  76. package/dist/lib/server/api/routes/organizations-members.d.ts.map +1 -0
  77. package/dist/{routes → lib/server/api/routes}/organizations-members.js +74 -106
  78. package/dist/lib/server/api/routes/organizations-members.js.map +1 -0
  79. package/dist/lib/server/api/routes/organizations-switch.d.ts +4 -0
  80. package/dist/lib/server/api/routes/organizations-switch.d.ts.map +1 -0
  81. package/dist/lib/server/api/routes/organizations-switch.js +54 -0
  82. package/dist/lib/server/api/routes/organizations-switch.js.map +1 -0
  83. package/dist/lib/server/api/routes/organizations.d.ts +4 -0
  84. package/dist/lib/server/api/routes/organizations.d.ts.map +1 -0
  85. package/dist/lib/server/api/routes/organizations.js +99 -0
  86. package/dist/lib/server/api/routes/organizations.js.map +1 -0
  87. package/dist/lib/server/api/routes/roles.d.ts +12 -0
  88. package/dist/lib/server/api/routes/roles.d.ts.map +1 -0
  89. package/dist/lib/server/api/routes/roles.js +219 -0
  90. package/dist/lib/server/api/routes/roles.js.map +1 -0
  91. package/dist/lib/server/api/routes/schemas.d.ts +4 -0
  92. package/dist/lib/server/api/routes/schemas.d.ts.map +1 -0
  93. package/dist/lib/server/api/routes/schemas.js +27 -0
  94. package/dist/lib/server/api/routes/schemas.js.map +1 -0
  95. package/dist/lib/server/api/routes/user-preferences.d.ts +4 -0
  96. package/dist/lib/server/api/routes/user-preferences.d.ts.map +1 -0
  97. package/dist/lib/server/api/routes/user-preferences.js +63 -0
  98. package/dist/lib/server/api/routes/user-preferences.js.map +1 -0
  99. package/dist/lib/server/api/routes/user.d.ts +12 -0
  100. package/dist/lib/server/api/routes/user.d.ts.map +1 -0
  101. package/dist/lib/server/api/routes/user.js +114 -0
  102. package/dist/lib/server/api/routes/user.js.map +1 -0
  103. package/dist/lib/server/index.d.ts +2 -1
  104. package/dist/lib/server/index.d.ts.map +1 -1
  105. package/dist/lib/server/index.js +7 -3
  106. package/dist/lib/server/index.js.map +1 -1
  107. package/dist/lib/types/config.d.ts +28 -29
  108. package/dist/lib/types/config.d.ts.map +1 -1
  109. package/dist/server/api/index.d.ts +55 -0
  110. package/dist/server/api/index.d.ts.map +1 -0
  111. package/dist/server/api/index.js +106 -0
  112. package/dist/server/api/routes/assets-bulk.d.ts +4 -0
  113. package/dist/server/api/routes/assets-bulk.d.ts.map +1 -0
  114. package/dist/{lib → server/api}/routes/assets-bulk.js +22 -24
  115. package/dist/server/api/routes/assets-by-id.d.ts +4 -0
  116. package/dist/server/api/routes/assets-by-id.d.ts.map +1 -0
  117. package/dist/server/api/routes/assets-by-id.js +107 -0
  118. package/dist/server/api/routes/assets-references.d.ts +15 -0
  119. package/dist/server/api/routes/assets-references.d.ts.map +1 -0
  120. package/dist/server/api/routes/assets-references.js +77 -0
  121. package/dist/server/api/routes/assets.d.ts +4 -0
  122. package/dist/server/api/routes/assets.d.ts.map +1 -0
  123. package/dist/{lib → server/api}/routes/assets.js +75 -88
  124. package/dist/server/api/routes/document-versions.d.ts +4 -0
  125. package/dist/server/api/routes/document-versions.d.ts.map +1 -0
  126. package/dist/server/api/routes/document-versions.js +112 -0
  127. package/dist/server/api/routes/documents-by-id.d.ts +4 -0
  128. package/dist/server/api/routes/documents-by-id.d.ts.map +1 -0
  129. package/dist/server/api/routes/documents-by-id.js +147 -0
  130. package/dist/server/api/routes/documents-publish.d.ts +4 -0
  131. package/dist/server/api/routes/documents-publish.d.ts.map +1 -0
  132. package/dist/{lib → server/api}/routes/documents-publish.js +41 -59
  133. package/dist/server/api/routes/documents-query.d.ts +8 -0
  134. package/dist/server/api/routes/documents-query.d.ts.map +1 -0
  135. package/dist/server/api/routes/documents-query.js +74 -0
  136. package/dist/server/api/routes/documents.d.ts +4 -0
  137. package/dist/server/api/routes/documents.d.ts.map +1 -0
  138. package/dist/{lib → server/api}/routes/documents.js +54 -77
  139. package/dist/server/api/routes/organizations-by-id.d.ts +4 -0
  140. package/dist/server/api/routes/organizations-by-id.d.ts.map +1 -0
  141. package/dist/{lib → server/api}/routes/organizations-by-id.js +61 -92
  142. package/dist/server/api/routes/organizations-invitations.d.ts +10 -0
  143. package/dist/server/api/routes/organizations-invitations.d.ts.map +1 -0
  144. package/dist/{lib → server/api}/routes/organizations-invitations.js +66 -79
  145. package/dist/server/api/routes/organizations-members.d.ts +4 -0
  146. package/dist/server/api/routes/organizations-members.d.ts.map +1 -0
  147. package/dist/{lib → server/api}/routes/organizations-members.js +73 -107
  148. package/dist/server/api/routes/organizations-switch.d.ts +4 -0
  149. package/dist/server/api/routes/organizations-switch.d.ts.map +1 -0
  150. package/dist/server/api/routes/organizations-switch.js +53 -0
  151. package/dist/server/api/routes/organizations.d.ts +4 -0
  152. package/dist/server/api/routes/organizations.d.ts.map +1 -0
  153. package/dist/server/api/routes/organizations.js +98 -0
  154. package/dist/server/api/routes/roles.d.ts +12 -0
  155. package/dist/server/api/routes/roles.d.ts.map +1 -0
  156. package/dist/server/api/routes/roles.js +218 -0
  157. package/dist/server/api/routes/schemas.d.ts +4 -0
  158. package/dist/server/api/routes/schemas.d.ts.map +1 -0
  159. package/dist/server/api/routes/schemas.js +26 -0
  160. package/dist/server/api/routes/user-preferences.d.ts +4 -0
  161. package/dist/server/api/routes/user-preferences.d.ts.map +1 -0
  162. package/dist/server/api/routes/user-preferences.js +62 -0
  163. package/dist/server/api/routes/user.d.ts +12 -0
  164. package/dist/server/api/routes/user.d.ts.map +1 -0
  165. package/dist/server/api/routes/user.js +113 -0
  166. package/dist/server/index.d.ts +2 -1
  167. package/dist/server/index.d.ts.map +1 -1
  168. package/dist/server/index.js +7 -3
  169. package/dist/types/config.d.ts +28 -29
  170. package/dist/types/config.d.ts.map +1 -1
  171. package/package.json +4 -2
  172. package/dist/lib/routes/assets-bulk.d.ts +0 -3
  173. package/dist/lib/routes/assets-bulk.d.ts.map +0 -1
  174. package/dist/lib/routes/assets-bulk.js.map +0 -1
  175. package/dist/lib/routes/assets-by-id.d.ts +0 -5
  176. package/dist/lib/routes/assets-by-id.d.ts.map +0 -1
  177. package/dist/lib/routes/assets-by-id.js +0 -116
  178. package/dist/lib/routes/assets-by-id.js.map +0 -1
  179. package/dist/lib/routes/assets-references-counts.d.ts +0 -7
  180. package/dist/lib/routes/assets-references-counts.d.ts.map +0 -1
  181. package/dist/lib/routes/assets-references-counts.js +0 -42
  182. package/dist/lib/routes/assets-references-counts.js.map +0 -1
  183. package/dist/lib/routes/assets-references.d.ts +0 -7
  184. package/dist/lib/routes/assets-references.d.ts.map +0 -1
  185. package/dist/lib/routes/assets-references.js +0 -35
  186. package/dist/lib/routes/assets-references.js.map +0 -1
  187. package/dist/lib/routes/assets.d.ts +0 -4
  188. package/dist/lib/routes/assets.d.ts.map +0 -1
  189. package/dist/lib/routes/assets.js.map +0 -1
  190. package/dist/lib/routes/document-versions.d.ts +0 -5
  191. package/dist/lib/routes/document-versions.d.ts.map +0 -1
  192. package/dist/lib/routes/document-versions.js +0 -114
  193. package/dist/lib/routes/document-versions.js.map +0 -1
  194. package/dist/lib/routes/documents-by-id.d.ts +0 -5
  195. package/dist/lib/routes/documents-by-id.d.ts.map +0 -1
  196. package/dist/lib/routes/documents-by-id.js +0 -188
  197. package/dist/lib/routes/documents-by-id.js.map +0 -1
  198. package/dist/lib/routes/documents-publish.d.ts +0 -4
  199. package/dist/lib/routes/documents-publish.d.ts.map +0 -1
  200. package/dist/lib/routes/documents-publish.js.map +0 -1
  201. package/dist/lib/routes/documents-query.d.ts +0 -26
  202. package/dist/lib/routes/documents-query.d.ts.map +0 -1
  203. package/dist/lib/routes/documents-query.js +0 -104
  204. package/dist/lib/routes/documents-query.js.map +0 -1
  205. package/dist/lib/routes/documents.d.ts +0 -4
  206. package/dist/lib/routes/documents.d.ts.map +0 -1
  207. package/dist/lib/routes/documents.js.map +0 -1
  208. package/dist/lib/routes/index.d.ts +0 -9
  209. package/dist/lib/routes/index.d.ts.map +0 -1
  210. package/dist/lib/routes/index.js +0 -15
  211. package/dist/lib/routes/index.js.map +0 -1
  212. package/dist/lib/routes/organizations-by-id.d.ts +0 -5
  213. package/dist/lib/routes/organizations-by-id.d.ts.map +0 -1
  214. package/dist/lib/routes/organizations-by-id.js.map +0 -1
  215. package/dist/lib/routes/organizations-invitations.d.ts +0 -4
  216. package/dist/lib/routes/organizations-invitations.d.ts.map +0 -1
  217. package/dist/lib/routes/organizations-invitations.js.map +0 -1
  218. package/dist/lib/routes/organizations-members.d.ts +0 -5
  219. package/dist/lib/routes/organizations-members.d.ts.map +0 -1
  220. package/dist/lib/routes/organizations-members.js.map +0 -1
  221. package/dist/lib/routes/organizations-switch.d.ts +0 -3
  222. package/dist/lib/routes/organizations-switch.d.ts.map +0 -1
  223. package/dist/lib/routes/organizations-switch.js +0 -59
  224. package/dist/lib/routes/organizations-switch.js.map +0 -1
  225. package/dist/lib/routes/organizations.d.ts +0 -4
  226. package/dist/lib/routes/organizations.d.ts.map +0 -1
  227. package/dist/lib/routes/organizations.js +0 -117
  228. package/dist/lib/routes/organizations.js.map +0 -1
  229. package/dist/lib/routes/roles-by-name.d.ts +0 -4
  230. package/dist/lib/routes/roles-by-name.d.ts.map +0 -1
  231. package/dist/lib/routes/roles-by-name.js +0 -112
  232. package/dist/lib/routes/roles-by-name.js.map +0 -1
  233. package/dist/lib/routes/roles.d.ts +0 -4
  234. package/dist/lib/routes/roles.d.ts.map +0 -1
  235. package/dist/lib/routes/roles.js +0 -91
  236. package/dist/lib/routes/roles.js.map +0 -1
  237. package/dist/lib/routes/schemas-by-type.d.ts +0 -3
  238. package/dist/lib/routes/schemas-by-type.d.ts.map +0 -1
  239. package/dist/lib/routes/schemas-by-type.js +0 -27
  240. package/dist/lib/routes/schemas-by-type.js.map +0 -1
  241. package/dist/lib/routes/schemas.d.ts +0 -3
  242. package/dist/lib/routes/schemas.d.ts.map +0 -1
  243. package/dist/lib/routes/schemas.js +0 -12
  244. package/dist/lib/routes/schemas.js.map +0 -1
  245. package/dist/lib/routes/user-preferences.d.ts +0 -4
  246. package/dist/lib/routes/user-preferences.d.ts.map +0 -1
  247. package/dist/lib/routes/user-preferences.js +0 -73
  248. package/dist/lib/routes/user-preferences.js.map +0 -1
  249. package/dist/lib/routes-exports.d.ts +0 -20
  250. package/dist/lib/routes-exports.d.ts.map +0 -1
  251. package/dist/lib/routes-exports.js +0 -27
  252. package/dist/lib/routes-exports.js.map +0 -1
  253. package/dist/routes/assets-bulk.d.ts +0 -3
  254. package/dist/routes/assets-bulk.d.ts.map +0 -1
  255. package/dist/routes/assets-by-id.d.ts +0 -5
  256. package/dist/routes/assets-by-id.d.ts.map +0 -1
  257. package/dist/routes/assets-by-id.js +0 -115
  258. package/dist/routes/assets-references-counts.d.ts +0 -7
  259. package/dist/routes/assets-references-counts.d.ts.map +0 -1
  260. package/dist/routes/assets-references-counts.js +0 -41
  261. package/dist/routes/assets-references.d.ts +0 -7
  262. package/dist/routes/assets-references.d.ts.map +0 -1
  263. package/dist/routes/assets-references.js +0 -34
  264. package/dist/routes/assets.d.ts +0 -4
  265. package/dist/routes/assets.d.ts.map +0 -1
  266. package/dist/routes/document-versions.d.ts +0 -5
  267. package/dist/routes/document-versions.d.ts.map +0 -1
  268. package/dist/routes/document-versions.js +0 -113
  269. package/dist/routes/documents-by-id.d.ts +0 -5
  270. package/dist/routes/documents-by-id.d.ts.map +0 -1
  271. package/dist/routes/documents-by-id.js +0 -187
  272. package/dist/routes/documents-publish.d.ts +0 -4
  273. package/dist/routes/documents-publish.d.ts.map +0 -1
  274. package/dist/routes/documents-query.d.ts +0 -26
  275. package/dist/routes/documents-query.d.ts.map +0 -1
  276. package/dist/routes/documents-query.js +0 -103
  277. package/dist/routes/documents.d.ts +0 -4
  278. package/dist/routes/documents.d.ts.map +0 -1
  279. package/dist/routes/index.d.ts +0 -9
  280. package/dist/routes/index.d.ts.map +0 -1
  281. package/dist/routes/index.js +0 -14
  282. package/dist/routes/organizations-by-id.d.ts +0 -5
  283. package/dist/routes/organizations-by-id.d.ts.map +0 -1
  284. package/dist/routes/organizations-invitations.d.ts +0 -4
  285. package/dist/routes/organizations-invitations.d.ts.map +0 -1
  286. package/dist/routes/organizations-members.d.ts +0 -5
  287. package/dist/routes/organizations-members.d.ts.map +0 -1
  288. package/dist/routes/organizations-switch.d.ts +0 -3
  289. package/dist/routes/organizations-switch.d.ts.map +0 -1
  290. package/dist/routes/organizations-switch.js +0 -58
  291. package/dist/routes/organizations.d.ts +0 -4
  292. package/dist/routes/organizations.d.ts.map +0 -1
  293. package/dist/routes/organizations.js +0 -116
  294. package/dist/routes/roles-by-name.d.ts +0 -4
  295. package/dist/routes/roles-by-name.d.ts.map +0 -1
  296. package/dist/routes/roles-by-name.js +0 -111
  297. package/dist/routes/roles.d.ts +0 -4
  298. package/dist/routes/roles.d.ts.map +0 -1
  299. package/dist/routes/roles.js +0 -90
  300. package/dist/routes/schemas-by-type.d.ts +0 -3
  301. package/dist/routes/schemas-by-type.d.ts.map +0 -1
  302. package/dist/routes/schemas-by-type.js +0 -26
  303. package/dist/routes/schemas.d.ts +0 -3
  304. package/dist/routes/schemas.d.ts.map +0 -1
  305. package/dist/routes/schemas.js +0 -11
  306. package/dist/routes/user-preferences.d.ts +0 -4
  307. package/dist/routes/user-preferences.d.ts.map +0 -1
  308. package/dist/routes/user-preferences.js +0 -72
  309. package/dist/routes-exports.d.ts +0 -20
  310. package/dist/routes-exports.d.ts.map +0 -1
  311. package/dist/routes-exports.js +0 -26
@@ -1,84 +1,81 @@
1
- // Aphex CMS Organization Invitations API Handlers
2
- import { json } from '@sveltejs/kit';
3
- import { cmsLogger } from '../utils/logger.js';
4
- import { inviteMemberRequest, cancelInvitationRequest } from '../api/schemas/organizations.js';
5
- import { hasCapability } from '../types/capabilities.js';
6
- // POST /api/organizations/invitations - Create/send an invitation
7
- export const POST = async ({ request, locals }) => {
1
+ import { Hono } from 'hono';
2
+ import { zValidator } from '@hono/zod-validator';
3
+ import { cmsLogger } from '../../../utils/logger.js';
4
+ import { inviteMemberRequest, cancelInvitationRequest } from '../../../api/schemas/organizations.js';
5
+ import { hasCapability } from '../../../types/capabilities.js';
6
+ /**
7
+ * Note: in studio, invitations are wrapped by a SvelteKit `+server.ts`
8
+ * that adds email sending after the invite row is created. While that
9
+ * shim exists, this Hono router sits dormant (specific SK routes win
10
+ * over the catch-all). Phase 5 moves the wrapper into `config.api`.
11
+ */
12
+ export const organizationsInvitationsRouter = new Hono()
13
+ .post('/invitations', zValidator('json', inviteMemberRequest, (result, c) => {
14
+ if (!result.success) {
15
+ return c.json({
16
+ success: false,
17
+ error: 'Invalid request body',
18
+ message: 'email and role are required',
19
+ issues: result.error.issues
20
+ }, 400);
21
+ }
22
+ }), async (c) => {
8
23
  try {
9
- const { databaseAdapter } = locals.aphexCMS;
10
- const auth = locals.auth;
24
+ const { databaseAdapter } = c.var.aphexCMS;
25
+ const auth = c.var.auth;
11
26
  if (!auth || auth.type !== 'session') {
12
- return json({
27
+ return c.json({
13
28
  success: false,
14
29
  error: 'Unauthorized',
15
30
  message: 'Session authentication required'
16
- }, { status: 401 });
31
+ }, 401);
17
32
  }
18
33
  if (!hasCapability(auth, 'member.invite')) {
19
- return json({
34
+ return c.json({
20
35
  success: false,
21
36
  error: 'Forbidden',
22
37
  message: 'You do not have permission to invite members'
23
- }, { status: 403 });
24
- }
25
- const rawBody = await request.json();
26
- const parsed = inviteMemberRequest.safeParse(rawBody);
27
- if (!parsed.success) {
28
- return json({
29
- success: false,
30
- error: 'Invalid request body',
31
- message: 'email and role are required',
32
- issues: parsed.error.issues
33
- }, { status: 400 });
38
+ }, 403);
34
39
  }
35
- const body = parsed.data;
36
- // Verify the role exists in this organization. Defends against
37
- // clients sending a role name that was deleted between page load
38
- // and submit, or against typos slipping past the format regex.
40
+ const body = c.req.valid('json');
39
41
  const roleRow = await databaseAdapter.findRoleByName(auth.organizationId, body.role);
40
42
  if (!roleRow) {
41
- return json({
43
+ return c.json({
42
44
  success: false,
43
45
  error: 'Unknown role',
44
46
  message: `No role named "${body.role}" in this organization`
45
- }, { status: 400 });
47
+ }, 400);
46
48
  }
47
- // Reject self-invitation
48
49
  if (body.email.toLowerCase() === auth.user.email.toLowerCase()) {
49
- return json({
50
+ return c.json({
50
51
  success: false,
51
52
  error: 'Invalid invitation',
52
53
  message: 'You cannot invite yourself'
53
- }, { status: 400 });
54
+ }, 400);
54
55
  }
55
- // Reject if the invitee is already a member of the organization
56
- if (locals.aphexCMS.auth) {
57
- const existingUser = await locals.aphexCMS.auth.getUserByEmail(body.email);
56
+ if (c.var.aphexCMS.auth) {
57
+ const existingUser = await c.var.aphexCMS.auth.getUserByEmail(body.email);
58
58
  if (existingUser) {
59
59
  const existingMembership = await databaseAdapter.findUserMembership(existingUser.id, auth.organizationId);
60
60
  if (existingMembership) {
61
- return json({
61
+ return c.json({
62
62
  success: false,
63
63
  error: 'Already a member',
64
64
  message: 'This user is already a member of the organization'
65
- }, { status: 400 });
65
+ }, 400);
66
66
  }
67
67
  }
68
68
  }
69
- // Check if there's already a pending invitation for this email
70
69
  const existingInvitations = await databaseAdapter.findOrganizationInvitations(auth.organizationId);
71
70
  const pendingInvitation = existingInvitations.find((inv) => inv.email.toLowerCase() === body.email.toLowerCase() && inv.acceptedAt === null);
72
71
  if (pendingInvitation) {
73
- return json({
72
+ return c.json({
74
73
  success: false,
75
74
  error: 'Already invited',
76
75
  message: 'This email has already been invited to the organization'
77
- }, { status: 400 });
76
+ }, 400);
78
77
  }
79
- // Generate a unique invitation token
80
78
  const token = crypto.randomUUID();
81
- // Create invitation - email sending is handled by the app layer
82
79
  const invitation = await databaseAdapter.createInvitation({
83
80
  organizationId: auth.organizationId,
84
81
  email: body.email.toLowerCase(),
@@ -87,71 +84,61 @@ export const POST = async ({ request, locals }) => {
87
84
  token,
88
85
  expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days
89
86
  });
90
- return json({
87
+ return c.json({
91
88
  success: true,
92
89
  data: invitation,
93
90
  message: 'Invitation created successfully.'
94
- }, { status: 201 });
91
+ }, 201);
95
92
  }
96
93
  catch (error) {
97
94
  cmsLogger.error('Failed to create invitation:', error);
98
- return json({
95
+ return c.json({
99
96
  success: false,
100
97
  error: 'Failed to create invitation',
101
98
  message: error instanceof Error ? error.message : 'Unknown error'
102
- }, { status: 500 });
99
+ }, 500);
100
+ }
101
+ })
102
+ .delete('/invitations', zValidator('json', cancelInvitationRequest, (result, c) => {
103
+ if (!result.success) {
104
+ return c.json({
105
+ success: false,
106
+ error: 'Missing required field',
107
+ message: 'invitationId is required',
108
+ issues: result.error.issues
109
+ }, 400);
103
110
  }
104
- };
105
- // DELETE /api/organizations/invitations - Cancel an invitation
106
- export const DELETE = async ({ request, locals }) => {
111
+ }), async (c) => {
107
112
  try {
108
- const { databaseAdapter } = locals.aphexCMS;
109
- const auth = locals.auth;
113
+ const { databaseAdapter } = c.var.aphexCMS;
114
+ const auth = c.var.auth;
110
115
  if (!auth || auth.type !== 'session') {
111
- return json({
116
+ return c.json({
112
117
  success: false,
113
118
  error: 'Unauthorized',
114
119
  message: 'Session authentication required'
115
- }, { status: 401 });
120
+ }, 401);
116
121
  }
117
122
  if (!hasCapability(auth, 'member.invite')) {
118
- return json({
123
+ return c.json({
119
124
  success: false,
120
125
  error: 'Forbidden',
121
126
  message: 'You do not have permission to cancel invitations'
122
- }, { status: 403 });
127
+ }, 403);
123
128
  }
124
- const rawBody = await request.json();
125
- const parsed = cancelInvitationRequest.safeParse(rawBody);
126
- if (!parsed.success) {
127
- return json({
128
- success: false,
129
- error: 'Missing required field',
130
- message: 'invitationId is required',
131
- issues: parsed.error.issues
132
- }, { status: 400 });
133
- }
134
- const body = parsed.data;
135
- // Delete the invitation
129
+ const body = c.req.valid('json');
136
130
  const deleted = await databaseAdapter.deleteInvitation(body.invitationId);
137
131
  if (!deleted) {
138
- return json({
139
- success: false,
140
- error: 'Invitation not found'
141
- }, { status: 404 });
132
+ return c.json({ success: false, error: 'Invitation not found' }, 404);
142
133
  }
143
- return json({
144
- success: true,
145
- message: 'Invitation canceled successfully'
146
- });
134
+ return c.json({ success: true, message: 'Invitation canceled successfully' });
147
135
  }
148
136
  catch (error) {
149
137
  cmsLogger.error('Failed to cancel invitation:', error);
150
- return json({
138
+ return c.json({
151
139
  success: false,
152
140
  error: 'Failed to cancel invitation',
153
141
  message: error instanceof Error ? error.message : 'Unknown error'
154
- }, { status: 500 });
142
+ }, 500);
155
143
  }
156
- };
157
- //# sourceMappingURL=organizations-invitations.js.map
144
+ });
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ import type { AphexEnv } from '../index.js';
3
+ export declare const organizationsMembersRouter: Hono<AphexEnv>;
4
+ //# sourceMappingURL=organizations-members.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations-members.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,0BAA0B,EAAE,IAAI,CAAC,QAAQ,CAgRpD,CAAC"}
@@ -1,214 +1,180 @@
1
- // Aphex CMS Organization Members API Handlers
2
- import { json } from '@sveltejs/kit';
3
- import { cmsLogger } from '../utils/logger.js';
4
- import { removeMemberRequest, updateMemberRoleRequest } from '../api/schemas/organizations.js';
5
- import { hasCapability } from '../types/capabilities.js';
6
- // GET /api/organizations/members - List organization members
7
- export const GET = async ({ locals }) => {
1
+ import { Hono } from 'hono';
2
+ import { zValidator } from '@hono/zod-validator';
3
+ import { cmsLogger } from '../../../utils/logger.js';
4
+ import { removeMemberRequest, updateMemberRoleRequest } from '../../../api/schemas/organizations.js';
5
+ import { hasCapability } from '../../../types/capabilities.js';
6
+ export const organizationsMembersRouter = new Hono()
7
+ .get('/members', async (c) => {
8
8
  try {
9
- const { databaseAdapter } = locals.aphexCMS;
10
- const auth = locals.auth;
9
+ const { databaseAdapter } = c.var.aphexCMS;
10
+ const auth = c.var.auth;
11
11
  if (!auth || auth.type !== 'session') {
12
- return json({
12
+ return c.json({
13
13
  success: false,
14
14
  error: 'Unauthorized',
15
15
  message: 'Session authentication required'
16
- }, { status: 401 });
16
+ }, 401);
17
17
  }
18
- // Get members of the current active organization
19
18
  const members = await databaseAdapter.findOrganizationMembers(auth.organizationId);
20
- return json({
21
- success: true,
22
- data: members
23
- });
19
+ return c.json({ success: true, data: members });
24
20
  }
25
21
  catch (error) {
26
22
  cmsLogger.error('Failed to fetch organization members:', error);
27
- return json({
23
+ return c.json({
28
24
  success: false,
29
25
  error: 'Failed to fetch members',
30
26
  message: error instanceof Error ? error.message : 'Unknown error'
31
- }, { status: 500 });
27
+ }, 500);
32
28
  }
33
- };
34
- // DELETE /api/organizations/members - Remove a member
35
- export const DELETE = async ({ request, locals }) => {
29
+ })
30
+ .delete('/members', zValidator('json', removeMemberRequest, (result, c) => {
31
+ if (!result.success) {
32
+ return c.json({
33
+ success: false,
34
+ error: 'Missing required field',
35
+ message: 'userId is required',
36
+ issues: result.error.issues
37
+ }, 400);
38
+ }
39
+ }), async (c) => {
36
40
  try {
37
- const { databaseAdapter } = locals.aphexCMS;
38
- const auth = locals.auth;
41
+ const { databaseAdapter } = c.var.aphexCMS;
42
+ const auth = c.var.auth;
39
43
  if (!auth || auth.type !== 'session') {
40
- return json({
44
+ return c.json({
41
45
  success: false,
42
46
  error: 'Unauthorized',
43
47
  message: 'Session authentication required'
44
- }, { status: 401 });
48
+ }, 401);
45
49
  }
46
50
  if (!hasCapability(auth, 'member.remove')) {
47
- return json({
51
+ return c.json({
48
52
  success: false,
49
53
  error: 'Forbidden',
50
54
  message: 'You do not have permission to remove members'
51
- }, { status: 403 });
55
+ }, 403);
52
56
  }
53
- const rawBody = await request.json();
54
- const parsed = removeMemberRequest.safeParse(rawBody);
55
- if (!parsed.success) {
56
- return json({
57
- success: false,
58
- error: 'Missing required field',
59
- message: 'userId is required',
60
- issues: parsed.error.issues
61
- }, { status: 400 });
62
- }
63
- const body = parsed.data;
64
- // Prevent removing yourself
57
+ const body = c.req.valid('json');
65
58
  if (body.userId === auth.user.id) {
66
- return json({
59
+ return c.json({
67
60
  success: false,
68
61
  error: 'Invalid operation',
69
62
  message: 'You cannot remove yourself from the organization'
70
- }, { status: 400 });
63
+ }, 400);
71
64
  }
72
- // Get the target member's role
73
65
  const targetMember = await databaseAdapter.findUserMembership(body.userId, auth.organizationId);
74
66
  if (!targetMember) {
75
- return json({
67
+ return c.json({
76
68
  success: false,
77
69
  error: 'Member not found',
78
70
  message: 'User is not a member of this organization'
79
- }, { status: 404 });
71
+ }, 404);
80
72
  }
81
- // Admins cannot remove owners
82
73
  if (auth.organizationRole === 'admin' && targetMember.role === 'owner') {
83
- return json({
74
+ return c.json({
84
75
  success: false,
85
76
  error: 'Forbidden',
86
77
  message: 'Admins cannot remove owners'
87
- }, { status: 403 });
78
+ }, 403);
88
79
  }
89
- // Remove the member
90
80
  const removed = await databaseAdapter.removeMember(auth.organizationId, body.userId);
91
81
  if (!removed) {
92
- return json({
93
- success: false,
94
- error: 'Failed to remove member'
95
- }, { status: 500 });
82
+ return c.json({ success: false, error: 'Failed to remove member' }, 500);
96
83
  }
97
- // Clear the user's session if their active org is the one they were removed from
98
84
  const userSession = await databaseAdapter.findUserSession(body.userId);
99
85
  if (userSession?.activeOrganizationId === auth.organizationId) {
100
86
  cmsLogger.debug(`[Organizations]: Clearing user session for ${body.userId} - removed from active org ${auth.organizationId}`);
101
- // Check if user has other organizations
102
87
  const otherOrgs = await databaseAdapter.findUserOrganizations(body.userId);
103
88
  if (otherOrgs.length > 0 && otherOrgs[0]) {
104
- // Set their first remaining org as active
105
89
  await databaseAdapter.updateUserSession(body.userId, otherOrgs[0].organization.id);
106
90
  cmsLogger.debug(`[Organizations]: Set org ${otherOrgs[0].organization.id} as new active org for ${body.userId}`);
107
91
  }
108
92
  else {
109
- // No other orgs - delete the session so invitations can be processed on next login
110
93
  await databaseAdapter.deleteUserSession(body.userId);
111
94
  cmsLogger.debug(`[Organizations]: Deleted user session for ${body.userId} - no remaining organizations`);
112
95
  }
113
96
  }
114
- return json({
115
- success: true,
116
- message: 'Member removed successfully'
117
- });
97
+ return c.json({ success: true, message: 'Member removed successfully' });
118
98
  }
119
99
  catch (error) {
120
100
  cmsLogger.error('Failed to remove member:', error);
121
- return json({
101
+ return c.json({
122
102
  success: false,
123
103
  error: 'Failed to remove member',
124
104
  message: error instanceof Error ? error.message : 'Unknown error'
125
- }, { status: 500 });
105
+ }, 500);
126
106
  }
127
- };
128
- // PATCH /api/organizations/members - Update member role
129
- export const PATCH = async ({ request, locals }) => {
107
+ })
108
+ .patch('/members', zValidator('json', updateMemberRoleRequest, (result, c) => {
109
+ if (!result.success) {
110
+ return c.json({
111
+ success: false,
112
+ error: 'Invalid request body',
113
+ message: 'userId and role are required',
114
+ issues: result.error.issues
115
+ }, 400);
116
+ }
117
+ }), async (c) => {
130
118
  try {
131
- const { databaseAdapter } = locals.aphexCMS;
132
- const auth = locals.auth;
119
+ const { databaseAdapter } = c.var.aphexCMS;
120
+ const auth = c.var.auth;
133
121
  if (!auth || auth.type !== 'session') {
134
- return json({
122
+ return c.json({
135
123
  success: false,
136
124
  error: 'Unauthorized',
137
125
  message: 'Session authentication required'
138
- }, { status: 401 });
126
+ }, 401);
139
127
  }
140
128
  if (!hasCapability(auth, 'member.changeRole')) {
141
- return json({
129
+ return c.json({
142
130
  success: false,
143
131
  error: 'Forbidden',
144
132
  message: 'You do not have permission to change member roles'
145
- }, { status: 403 });
133
+ }, 403);
146
134
  }
147
- const rawBody = await request.json();
148
- const parsed = updateMemberRoleRequest.safeParse(rawBody);
149
- if (!parsed.success) {
150
- return json({
151
- success: false,
152
- error: 'Invalid request body',
153
- message: 'userId and role are required',
154
- issues: parsed.error.issues
155
- }, { status: 400 });
156
- }
157
- const body = parsed.data;
158
- // Verify the target role exists in this organization.
135
+ const body = c.req.valid('json');
159
136
  const roleRow = await databaseAdapter.findRoleByName(auth.organizationId, body.role);
160
137
  if (!roleRow) {
161
- return json({
138
+ return c.json({
162
139
  success: false,
163
140
  error: 'Unknown role',
164
141
  message: `No role named "${body.role}" in this organization`
165
- }, { status: 400 });
142
+ }, 400);
166
143
  }
167
- // Prevent changing your own role
168
144
  if (body.userId === auth.user.id) {
169
- return json({
145
+ return c.json({
170
146
  success: false,
171
147
  error: 'Invalid operation',
172
148
  message: 'You cannot change your own role'
173
- }, { status: 400 });
149
+ }, 400);
174
150
  }
175
- // Get the target member's current role
176
151
  const targetMember = await databaseAdapter.findUserMembership(body.userId, auth.organizationId);
177
152
  if (!targetMember) {
178
- return json({
153
+ return c.json({
179
154
  success: false,
180
155
  error: 'Member not found',
181
156
  message: 'User is not a member of this organization'
182
- }, { status: 404 });
157
+ }, 404);
183
158
  }
184
- // Admins cannot modify owners
185
159
  if (auth.organizationRole === 'admin' && targetMember.role === 'owner') {
186
- return json({
160
+ return c.json({
187
161
  success: false,
188
162
  error: 'Forbidden',
189
163
  message: 'Admins cannot modify owner roles'
190
- }, { status: 403 });
164
+ }, 403);
191
165
  }
192
- // Update the role
193
166
  const updatedMember = await databaseAdapter.updateMemberRole(auth.organizationId, body.userId, body.role);
194
167
  if (!updatedMember) {
195
- return json({
196
- success: false,
197
- error: 'Failed to update role'
198
- }, { status: 500 });
168
+ return c.json({ success: false, error: 'Failed to update role' }, 500);
199
169
  }
200
- return json({
201
- success: true,
202
- data: updatedMember
203
- });
170
+ return c.json({ success: true, data: updatedMember });
204
171
  }
205
172
  catch (error) {
206
173
  cmsLogger.error('Failed to update member role:', error);
207
- return json({
174
+ return c.json({
208
175
  success: false,
209
176
  error: 'Failed to update role',
210
177
  message: error instanceof Error ? error.message : 'Unknown error'
211
- }, { status: 500 });
178
+ }, 500);
212
179
  }
213
- };
214
- //# sourceMappingURL=organizations-members.js.map
180
+ });
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ import type { AphexEnv } from '../index.js';
3
+ export declare const organizationsSwitchRouter: Hono<AphexEnv>;
4
+ //# sourceMappingURL=organizations-switch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organizations-switch.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations-switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,yBAAyB,EAAE,IAAI,CAAC,QAAQ,CAwEpD,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { Hono } from 'hono';
2
+ import { zValidator } from '@hono/zod-validator';
3
+ import { cmsLogger } from '../../../utils/logger.js';
4
+ import { switchOrganizationRequest } from '../../../api/schemas/organizations.js';
5
+ export const organizationsSwitchRouter = new Hono().post('/switch', zValidator('json', switchOrganizationRequest, (result, c) => {
6
+ if (!result.success) {
7
+ return c.json({
8
+ success: false,
9
+ error: 'Missing required field',
10
+ message: 'organizationId is required',
11
+ issues: result.error.issues
12
+ }, 400);
13
+ }
14
+ }), async (c) => {
15
+ try {
16
+ const { databaseAdapter } = c.var.aphexCMS;
17
+ const auth = c.var.auth;
18
+ if (!auth || auth.type !== 'session') {
19
+ return c.json({
20
+ success: false,
21
+ error: 'Unauthorized',
22
+ message: 'Session authentication required'
23
+ }, 401);
24
+ }
25
+ const body = c.req.valid('json');
26
+ const membership = await databaseAdapter.findUserMembership(auth.user.id, body.organizationId);
27
+ if (!membership) {
28
+ return c.json({
29
+ success: false,
30
+ error: 'Access denied',
31
+ message: 'You are not a member of this organization'
32
+ }, 403);
33
+ }
34
+ await databaseAdapter.updateUserSession(auth.user.id, body.organizationId);
35
+ const organization = await databaseAdapter.findOrganizationById(body.organizationId);
36
+ return c.json({
37
+ success: true,
38
+ data: {
39
+ organizationId: body.organizationId,
40
+ organizationName: organization?.name,
41
+ role: membership.role
42
+ }
43
+ });
44
+ }
45
+ catch (error) {
46
+ cmsLogger.error('Failed to switch organization:', error);
47
+ return c.json({
48
+ success: false,
49
+ error: 'Failed to switch organization',
50
+ message: error instanceof Error ? error.message : 'Unknown error'
51
+ }, 500);
52
+ }
53
+ });
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ import type { AphexEnv } from '../index.js';
3
+ export declare const organizationsRouter: Hono<AphexEnv>;
4
+ //# sourceMappingURL=organizations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organizations.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CA8H7C,CAAC"}