@shipfox/api-workspaces 2.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 (284) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +97 -0
  5. package/LICENSE +21 -0
  6. package/README.md +87 -0
  7. package/dist/config.d.ts +12 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +58 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/core/entities/index.d.ts +4 -0
  12. package/dist/core/entities/index.d.ts.map +1 -0
  13. package/dist/core/entities/index.js +3 -0
  14. package/dist/core/entities/index.js.map +1 -0
  15. package/dist/core/entities/invitation.d.ts +14 -0
  16. package/dist/core/entities/invitation.d.ts.map +1 -0
  17. package/dist/core/entities/invitation.js +3 -0
  18. package/dist/core/entities/invitation.js.map +1 -0
  19. package/dist/core/entities/membership.d.ts +10 -0
  20. package/dist/core/entities/membership.d.ts.map +1 -0
  21. package/dist/core/entities/membership.js +3 -0
  22. package/dist/core/entities/membership.js.map +1 -0
  23. package/dist/core/entities/workspace.d.ts +10 -0
  24. package/dist/core/entities/workspace.d.ts.map +1 -0
  25. package/dist/core/entities/workspace.js +3 -0
  26. package/dist/core/entities/workspace.js.map +1 -0
  27. package/dist/core/errors.d.ts +52 -0
  28. package/dist/core/errors.d.ts.map +1 -0
  29. package/dist/core/errors.js +104 -0
  30. package/dist/core/errors.js.map +1 -0
  31. package/dist/core/index.d.ts +8 -0
  32. package/dist/core/index.d.ts.map +1 -0
  33. package/dist/core/index.js +6 -0
  34. package/dist/core/index.js.map +1 -0
  35. package/dist/core/invitations.d.ts +51 -0
  36. package/dist/core/invitations.d.ts.map +1 -0
  37. package/dist/core/invitations.js +136 -0
  38. package/dist/core/invitations.js.map +1 -0
  39. package/dist/core/memberships.d.ts +9 -0
  40. package/dist/core/memberships.d.ts.map +1 -0
  41. package/dist/core/memberships.js +13 -0
  42. package/dist/core/memberships.js.map +1 -0
  43. package/dist/core/workspaces.d.ts +40 -0
  44. package/dist/core/workspaces.d.ts.map +1 -0
  45. package/dist/core/workspaces.js +85 -0
  46. package/dist/core/workspaces.js.map +1 -0
  47. package/dist/db/db.d.ts +1253 -0
  48. package/dist/db/db.d.ts.map +1 -0
  49. package/dist/db/db.js +24 -0
  50. package/dist/db/db.js.map +1 -0
  51. package/dist/db/index.d.ts +10 -0
  52. package/dist/db/index.d.ts.map +1 -0
  53. package/dist/db/index.js +10 -0
  54. package/dist/db/index.js.map +1 -0
  55. package/dist/db/invitations.d.ts +47 -0
  56. package/dist/db/invitations.d.ts.map +1 -0
  57. package/dist/db/invitations.js +107 -0
  58. package/dist/db/invitations.js.map +1 -0
  59. package/dist/db/memberships.d.ts +44 -0
  60. package/dist/db/memberships.d.ts.map +1 -0
  61. package/dist/db/memberships.js +75 -0
  62. package/dist/db/memberships.js.map +1 -0
  63. package/dist/db/schema/common.d.ts +2 -0
  64. package/dist/db/schema/common.d.ts.map +1 -0
  65. package/dist/db/schema/common.js +4 -0
  66. package/dist/db/schema/common.js.map +1 -0
  67. package/dist/db/schema/invitations.d.ts +199 -0
  68. package/dist/db/schema/invitations.d.ts.map +1 -0
  69. package/dist/db/schema/invitations.js +47 -0
  70. package/dist/db/schema/invitations.js.map +1 -0
  71. package/dist/db/schema/memberships.d.ts +131 -0
  72. package/dist/db/schema/memberships.d.ts.map +1 -0
  73. package/dist/db/schema/memberships.js +35 -0
  74. package/dist/db/schema/memberships.js.map +1 -0
  75. package/dist/db/schema/outbox.d.ts +195 -0
  76. package/dist/db/schema/outbox.d.ts.map +1 -0
  77. package/dist/db/schema/outbox.js +5 -0
  78. package/dist/db/schema/outbox.js.map +1 -0
  79. package/dist/db/schema/workspaces.d.ts +115 -0
  80. package/dist/db/schema/workspaces.d.ts.map +1 -0
  81. package/dist/db/schema/workspaces.js +32 -0
  82. package/dist/db/schema/workspaces.js.map +1 -0
  83. package/dist/db/workspaces.d.ts +20 -0
  84. package/dist/db/workspaces.d.ts.map +1 -0
  85. package/dist/db/workspaces.js +53 -0
  86. package/dist/db/workspaces.js.map +1 -0
  87. package/dist/index.d.ts +13 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +40 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/metrics/index.d.ts +2 -0
  92. package/dist/metrics/index.d.ts.map +1 -0
  93. package/dist/metrics/index.js +3 -0
  94. package/dist/metrics/index.js.map +1 -0
  95. package/dist/metrics/instance.d.ts +8 -0
  96. package/dist/metrics/instance.d.ts.map +1 -0
  97. package/dist/metrics/instance.js +41 -0
  98. package/dist/metrics/instance.js.map +1 -0
  99. package/dist/metrics/service.d.ts +2 -0
  100. package/dist/metrics/service.d.ts.map +1 -0
  101. package/dist/metrics/service.js +26 -0
  102. package/dist/metrics/service.js.map +1 -0
  103. package/dist/presentation/dto/index.d.ts +4 -0
  104. package/dist/presentation/dto/index.d.ts.map +1 -0
  105. package/dist/presentation/dto/index.js +5 -0
  106. package/dist/presentation/dto/index.js.map +1 -0
  107. package/dist/presentation/dto/invitation.d.ts +4 -0
  108. package/dist/presentation/dto/invitation.d.ts.map +1 -0
  109. package/dist/presentation/dto/invitation.js +15 -0
  110. package/dist/presentation/dto/invitation.js.map +1 -0
  111. package/dist/presentation/dto/membership.d.ts +5 -0
  112. package/dist/presentation/dto/membership.d.ts.map +1 -0
  113. package/dist/presentation/dto/membership.js +23 -0
  114. package/dist/presentation/dto/membership.js.map +1 -0
  115. package/dist/presentation/dto/workspace.d.ts +4 -0
  116. package/dist/presentation/dto/workspace.d.ts.map +1 -0
  117. package/dist/presentation/dto/workspace.js +12 -0
  118. package/dist/presentation/dto/workspace.js.map +1 -0
  119. package/dist/presentation/e2eRoutes/create-invitation.d.ts +2 -0
  120. package/dist/presentation/e2eRoutes/create-invitation.d.ts.map +1 -0
  121. package/dist/presentation/e2eRoutes/create-invitation.js +39 -0
  122. package/dist/presentation/e2eRoutes/create-invitation.js.map +1 -0
  123. package/dist/presentation/e2eRoutes/create-workspace.d.ts +2 -0
  124. package/dist/presentation/e2eRoutes/create-workspace.d.ts.map +1 -0
  125. package/dist/presentation/e2eRoutes/create-workspace.js +27 -0
  126. package/dist/presentation/e2eRoutes/create-workspace.js.map +1 -0
  127. package/dist/presentation/e2eRoutes/index.d.ts +3 -0
  128. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
  129. package/dist/presentation/e2eRoutes/index.js +11 -0
  130. package/dist/presentation/e2eRoutes/index.js.map +1 -0
  131. package/dist/presentation/index.d.ts +2 -0
  132. package/dist/presentation/index.d.ts.map +1 -0
  133. package/dist/presentation/index.js +3 -0
  134. package/dist/presentation/index.js.map +1 -0
  135. package/dist/presentation/routes/index.d.ts +3 -0
  136. package/dist/presentation/routes/index.d.ts.map +1 -0
  137. package/dist/presentation/routes/index.js +23 -0
  138. package/dist/presentation/routes/index.js.map +1 -0
  139. package/dist/presentation/routes/invitations/accept.d.ts +2 -0
  140. package/dist/presentation/routes/invitations/accept.d.ts.map +1 -0
  141. package/dist/presentation/routes/invitations/accept.js +67 -0
  142. package/dist/presentation/routes/invitations/accept.js.map +1 -0
  143. package/dist/presentation/routes/invitations/create.d.ts +2 -0
  144. package/dist/presentation/routes/invitations/create.d.ts.map +1 -0
  145. package/dist/presentation/routes/invitations/create.js +66 -0
  146. package/dist/presentation/routes/invitations/create.js.map +1 -0
  147. package/dist/presentation/routes/invitations/index.d.ts +4 -0
  148. package/dist/presentation/routes/invitations/index.d.ts.map +1 -0
  149. package/dist/presentation/routes/invitations/index.js +19 -0
  150. package/dist/presentation/routes/invitations/index.js.map +1 -0
  151. package/dist/presentation/routes/invitations/list.d.ts +2 -0
  152. package/dist/presentation/routes/invitations/list.d.ts.map +1 -0
  153. package/dist/presentation/routes/invitations/list.js +58 -0
  154. package/dist/presentation/routes/invitations/list.js.map +1 -0
  155. package/dist/presentation/routes/invitations/preview.d.ts +2 -0
  156. package/dist/presentation/routes/invitations/preview.d.ts.map +1 -0
  157. package/dist/presentation/routes/invitations/preview.js +47 -0
  158. package/dist/presentation/routes/invitations/preview.js.map +1 -0
  159. package/dist/presentation/routes/invitations/revoke.d.ts +2 -0
  160. package/dist/presentation/routes/invitations/revoke.d.ts.map +1 -0
  161. package/dist/presentation/routes/invitations/revoke.js +66 -0
  162. package/dist/presentation/routes/invitations/revoke.js.map +1 -0
  163. package/dist/presentation/routes/members/index.d.ts +3 -0
  164. package/dist/presentation/routes/members/index.d.ts.map +1 -0
  165. package/dist/presentation/routes/members/index.js +8 -0
  166. package/dist/presentation/routes/members/index.js.map +1 -0
  167. package/dist/presentation/routes/members/list.d.ts +2 -0
  168. package/dist/presentation/routes/members/list.d.ts.map +1 -0
  169. package/dist/presentation/routes/members/list.js +58 -0
  170. package/dist/presentation/routes/members/list.js.map +1 -0
  171. package/dist/presentation/routes/members/remove.d.ts +2 -0
  172. package/dist/presentation/routes/members/remove.d.ts.map +1 -0
  173. package/dist/presentation/routes/members/remove.js +71 -0
  174. package/dist/presentation/routes/members/remove.js.map +1 -0
  175. package/dist/presentation/routes/workspaces/create.d.ts +2 -0
  176. package/dist/presentation/routes/workspaces/create.d.ts.map +1 -0
  177. package/dist/presentation/routes/workspaces/create.js +36 -0
  178. package/dist/presentation/routes/workspaces/create.js.map +1 -0
  179. package/dist/presentation/routes/workspaces/index.d.ts +3 -0
  180. package/dist/presentation/routes/workspaces/index.d.ts.map +1 -0
  181. package/dist/presentation/routes/workspaces/index.js +4 -0
  182. package/dist/presentation/routes/workspaces/index.js.map +1 -0
  183. package/dist/presentation/routes/workspaces/list.d.ts +2 -0
  184. package/dist/presentation/routes/workspaces/list.d.ts.map +1 -0
  185. package/dist/presentation/routes/workspaces/list.js +32 -0
  186. package/dist/presentation/routes/workspaces/list.js.map +1 -0
  187. package/dist/presentation/subscribers/index.d.ts +2 -0
  188. package/dist/presentation/subscribers/index.d.ts.map +1 -0
  189. package/dist/presentation/subscribers/index.js +3 -0
  190. package/dist/presentation/subscribers/index.js.map +1 -0
  191. package/dist/presentation/subscribers/on-invitation-send-requested.d.ts +3 -0
  192. package/dist/presentation/subscribers/on-invitation-send-requested.d.ts.map +1 -0
  193. package/dist/presentation/subscribers/on-invitation-send-requested.js +16 -0
  194. package/dist/presentation/subscribers/on-invitation-send-requested.js.map +1 -0
  195. package/dist/tsconfig.test.tsbuildinfo +1 -0
  196. package/drizzle/0000_initial.sql +9 -0
  197. package/drizzle/0001_memberships_invitations.sql +30 -0
  198. package/drizzle/0002_membership_user_snapshots.sql +40 -0
  199. package/drizzle/0003_outgoing_enchantress.sql +16 -0
  200. package/drizzle/meta/0000_snapshot.json +80 -0
  201. package/drizzle/meta/0001_snapshot.json +705 -0
  202. package/drizzle/meta/0003_snapshot.json +442 -0
  203. package/drizzle/meta/_journal.json +34 -0
  204. package/drizzle.config.ts +7 -0
  205. package/package.json +71 -0
  206. package/src/config.ts +51 -0
  207. package/src/core/entities/index.ts +3 -0
  208. package/src/core/entities/invitation.ts +13 -0
  209. package/src/core/entities/membership.ts +9 -0
  210. package/src/core/entities/workspace.ts +10 -0
  211. package/src/core/errors.ts +118 -0
  212. package/src/core/index.ts +35 -0
  213. package/src/core/invitations.test.ts +251 -0
  214. package/src/core/invitations.ts +191 -0
  215. package/src/core/memberships.test.ts +77 -0
  216. package/src/core/memberships.ts +17 -0
  217. package/src/core/workspaces.test.ts +72 -0
  218. package/src/core/workspaces.ts +126 -0
  219. package/src/db/db.ts +24 -0
  220. package/src/db/index.ts +43 -0
  221. package/src/db/invitations.test.ts +204 -0
  222. package/src/db/invitations.ts +235 -0
  223. package/src/db/memberships.test.ts +107 -0
  224. package/src/db/memberships.ts +139 -0
  225. package/src/db/schema/common.ts +5 -0
  226. package/src/db/schema/invitations.ts +47 -0
  227. package/src/db/schema/memberships.ts +39 -0
  228. package/src/db/schema/outbox.ts +4 -0
  229. package/src/db/schema/workspaces.ts +33 -0
  230. package/src/db/workspaces.test.ts +114 -0
  231. package/src/db/workspaces.ts +81 -0
  232. package/src/index.test.ts +25 -0
  233. package/src/index.ts +43 -0
  234. package/src/metrics/index.ts +1 -0
  235. package/src/metrics/instance.test.ts +74 -0
  236. package/src/metrics/instance.ts +57 -0
  237. package/src/metrics/service.ts +26 -0
  238. package/src/presentation/dto/index.ts +3 -0
  239. package/src/presentation/dto/invitation.ts +16 -0
  240. package/src/presentation/dto/membership.ts +27 -0
  241. package/src/presentation/dto/workspace.ts +13 -0
  242. package/src/presentation/e2eRoutes/create-invitation.ts +44 -0
  243. package/src/presentation/e2eRoutes/create-workspace.ts +30 -0
  244. package/src/presentation/e2eRoutes/index.ts +8 -0
  245. package/src/presentation/index.ts +1 -0
  246. package/src/presentation/routes/index.ts +23 -0
  247. package/src/presentation/routes/invitations/accept.test.ts +154 -0
  248. package/src/presentation/routes/invitations/accept.ts +70 -0
  249. package/src/presentation/routes/invitations/create.test.ts +99 -0
  250. package/src/presentation/routes/invitations/create.ts +60 -0
  251. package/src/presentation/routes/invitations/index.ts +17 -0
  252. package/src/presentation/routes/invitations/list.test.ts +94 -0
  253. package/src/presentation/routes/invitations/list.ts +53 -0
  254. package/src/presentation/routes/invitations/preview.test.ts +140 -0
  255. package/src/presentation/routes/invitations/preview.ts +46 -0
  256. package/src/presentation/routes/invitations/revoke.test.ts +99 -0
  257. package/src/presentation/routes/invitations/revoke.ts +64 -0
  258. package/src/presentation/routes/members/index.ts +5 -0
  259. package/src/presentation/routes/members/list.test.ts +95 -0
  260. package/src/presentation/routes/members/list.ts +53 -0
  261. package/src/presentation/routes/members/remove.test.ts +110 -0
  262. package/src/presentation/routes/members/remove.ts +66 -0
  263. package/src/presentation/routes/workspaces/create.test.ts +87 -0
  264. package/src/presentation/routes/workspaces/create.ts +36 -0
  265. package/src/presentation/routes/workspaces/index.ts +2 -0
  266. package/src/presentation/routes/workspaces/list.test.ts +56 -0
  267. package/src/presentation/routes/workspaces/list.ts +29 -0
  268. package/src/presentation/subscribers/index.ts +1 -0
  269. package/src/presentation/subscribers/invitation-send-requested.test.ts +64 -0
  270. package/src/presentation/subscribers/on-invitation-send-requested.ts +15 -0
  271. package/test/env.ts +8 -0
  272. package/test/factories/index.ts +3 -0
  273. package/test/factories/membership.ts +24 -0
  274. package/test/factories/user.ts +15 -0
  275. package/test/factories/workspace.ts +18 -0
  276. package/test/globalSetup.ts +15 -0
  277. package/test/index.ts +3 -0
  278. package/test/routes.ts +255 -0
  279. package/test/setup.ts +17 -0
  280. package/tsconfig.build.json +9 -0
  281. package/tsconfig.build.tsbuildinfo +1 -0
  282. package/tsconfig.json +3 -0
  283. package/tsconfig.test.json +8 -0
  284. package/vitest.config.ts +11 -0
@@ -0,0 +1,67 @@
1
+ import { AUTH_USER, getUserContext } from '@shipfox/api-auth-context';
2
+ import { acceptInvitationBodySchema, acceptInvitationResponseSchema } from '@shipfox/api-workspaces-dto';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { InvitationEmailMismatchError, TokenAlreadyUsedError, TokenExpiredError, TokenInvalidError } from '#core/errors.js';
5
+ import { acceptWorkspaceInvitation } from '#core/index.js';
6
+ export const acceptInvitationRoute = defineRoute({
7
+ method: 'POST',
8
+ path: '/accept',
9
+ description: 'Accept an invitation to join a workspace.',
10
+ auth: AUTH_USER,
11
+ schema: {
12
+ body: acceptInvitationBodySchema,
13
+ response: {
14
+ 200: acceptInvitationResponseSchema,
15
+ 201: acceptInvitationResponseSchema
16
+ }
17
+ },
18
+ errorHandler: (error)=>{
19
+ if (error instanceof TokenInvalidError) {
20
+ throw new ClientError('Invitation token is invalid', 'token-invalid', {
21
+ status: 410
22
+ });
23
+ }
24
+ if (error instanceof TokenAlreadyUsedError) {
25
+ throw new ClientError('Invitation has already been accepted', 'token-already-used', {
26
+ status: 410
27
+ });
28
+ }
29
+ if (error instanceof TokenExpiredError) {
30
+ throw new ClientError('Invitation has expired', 'token-expired', {
31
+ status: 410
32
+ });
33
+ }
34
+ if (error instanceof InvitationEmailMismatchError) {
35
+ throw new ClientError('Invitation email does not match authenticated user', 'forbidden', {
36
+ status: 403
37
+ });
38
+ }
39
+ throw error;
40
+ },
41
+ handler: async (request, reply)=>{
42
+ const client = getUserContext(request);
43
+ if (!client) {
44
+ throw new ClientError('Authentication required', 'unauthorized', {
45
+ status: 401
46
+ });
47
+ }
48
+ const { token } = request.body;
49
+ const result = await acceptWorkspaceInvitation({
50
+ token,
51
+ userId: client.userId,
52
+ email: client.email,
53
+ name: client.name
54
+ });
55
+ reply.code(result.alreadyMember ? 200 : 201);
56
+ return {
57
+ membership: {
58
+ id: result.membership.id,
59
+ user_id: result.membership.userId,
60
+ workspace_id: result.membership.workspaceId
61
+ },
62
+ already_member: result.alreadyMember
63
+ };
64
+ }
65
+ });
66
+
67
+ //# sourceMappingURL=accept.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/invitations/accept.ts"],"sourcesContent":["import {AUTH_USER, getUserContext} from '@shipfox/api-auth-context';\nimport {\n acceptInvitationBodySchema,\n acceptInvitationResponseSchema,\n} from '@shipfox/api-workspaces-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {\n InvitationEmailMismatchError,\n TokenAlreadyUsedError,\n TokenExpiredError,\n TokenInvalidError,\n} from '#core/errors.js';\nimport {acceptWorkspaceInvitation} from '#core/index.js';\n\nexport const acceptInvitationRoute = defineRoute({\n method: 'POST',\n path: '/accept',\n description: 'Accept an invitation to join a workspace.',\n auth: AUTH_USER,\n schema: {\n body: acceptInvitationBodySchema,\n response: {\n 200: acceptInvitationResponseSchema,\n 201: acceptInvitationResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof TokenInvalidError) {\n throw new ClientError('Invitation token is invalid', 'token-invalid', {status: 410});\n }\n if (error instanceof TokenAlreadyUsedError) {\n throw new ClientError('Invitation has already been accepted', 'token-already-used', {\n status: 410,\n });\n }\n if (error instanceof TokenExpiredError) {\n throw new ClientError('Invitation has expired', 'token-expired', {status: 410});\n }\n if (error instanceof InvitationEmailMismatchError) {\n throw new ClientError('Invitation email does not match authenticated user', 'forbidden', {\n status: 403,\n });\n }\n throw error;\n },\n handler: async (request, reply) => {\n const client = getUserContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n const {token} = request.body;\n const result = await acceptWorkspaceInvitation({\n token,\n userId: client.userId,\n email: client.email,\n name: client.name,\n });\n\n reply.code(result.alreadyMember ? 200 : 201);\n return {\n membership: {\n id: result.membership.id,\n user_id: result.membership.userId,\n workspace_id: result.membership.workspaceId,\n },\n already_member: result.alreadyMember,\n };\n },\n});\n"],"names":["AUTH_USER","getUserContext","acceptInvitationBodySchema","acceptInvitationResponseSchema","ClientError","defineRoute","InvitationEmailMismatchError","TokenAlreadyUsedError","TokenExpiredError","TokenInvalidError","acceptWorkspaceInvitation","acceptInvitationRoute","method","path","description","auth","schema","body","response","errorHandler","error","status","handler","request","reply","client","token","result","userId","email","name","code","alreadyMember","membership","id","user_id","workspace_id","workspaceId","already_member"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,cAAc,QAAO,4BAA4B;AACpE,SACEC,0BAA0B,EAC1BC,8BAA8B,QACzB,8BAA8B;AACrC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SACEC,4BAA4B,EAC5BC,qBAAqB,EACrBC,iBAAiB,EACjBC,iBAAiB,QACZ,kBAAkB;AACzB,SAAQC,yBAAyB,QAAO,iBAAiB;AAEzD,OAAO,MAAMC,wBAAwBN,YAAY;IAC/CO,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMf;IACNgB,QAAQ;QACNC,MAAMf;QACNgB,UAAU;YACR,KAAKf;YACL,KAAKA;QACP;IACF;IACAgB,cAAc,CAACC;QACb,IAAIA,iBAAiBX,mBAAmB;YACtC,MAAM,IAAIL,YAAY,+BAA+B,iBAAiB;gBAACiB,QAAQ;YAAG;QACpF;QACA,IAAID,iBAAiBb,uBAAuB;YAC1C,MAAM,IAAIH,YAAY,wCAAwC,sBAAsB;gBAClFiB,QAAQ;YACV;QACF;QACA,IAAID,iBAAiBZ,mBAAmB;YACtC,MAAM,IAAIJ,YAAY,0BAA0B,iBAAiB;gBAACiB,QAAQ;YAAG;QAC/E;QACA,IAAID,iBAAiBd,8BAA8B;YACjD,MAAM,IAAIF,YAAY,sDAAsD,aAAa;gBACvFiB,QAAQ;YACV;QACF;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC,SAASC;QACvB,MAAMC,SAASxB,eAAesB;QAC9B,IAAI,CAACE,QAAQ;YACX,MAAM,IAAIrB,YAAY,2BAA2B,gBAAgB;gBAACiB,QAAQ;YAAG;QAC/E;QAEA,MAAM,EAACK,KAAK,EAAC,GAAGH,QAAQN,IAAI;QAC5B,MAAMU,SAAS,MAAMjB,0BAA0B;YAC7CgB;YACAE,QAAQH,OAAOG,MAAM;YACrBC,OAAOJ,OAAOI,KAAK;YACnBC,MAAML,OAAOK,IAAI;QACnB;QAEAN,MAAMO,IAAI,CAACJ,OAAOK,aAAa,GAAG,MAAM;QACxC,OAAO;YACLC,YAAY;gBACVC,IAAIP,OAAOM,UAAU,CAACC,EAAE;gBACxBC,SAASR,OAAOM,UAAU,CAACL,MAAM;gBACjCQ,cAAcT,OAAOM,UAAU,CAACI,WAAW;YAC7C;YACAC,gBAAgBX,OAAOK,aAAa;QACtC;IACF;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const createInvitationRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/invitations/create.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,qBAAqB,iDA8ChC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { AUTH_USER, getUserContext } from '@shipfox/api-auth-context';
2
+ import { createInvitationBodySchema, invitationDtoSchema } from '@shipfox/api-workspaces-dto';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { z } from 'zod';
5
+ import { MembershipRequiredError, OpenInvitationExistsError, WorkspaceInactiveError, WorkspaceNotFoundError } from '#core/errors.js';
6
+ import { createWorkspaceInvitation } from '#core/index.js';
7
+ import { toInvitationDto } from '#presentation/dto/index.js';
8
+ export const createInvitationRoute = defineRoute({
9
+ method: 'POST',
10
+ path: '/',
11
+ description: 'Invite someone to join a workspace by email.',
12
+ auth: AUTH_USER,
13
+ schema: {
14
+ params: z.object({
15
+ workspaceId: z.string().uuid()
16
+ }),
17
+ body: createInvitationBodySchema,
18
+ response: {
19
+ 201: invitationDtoSchema
20
+ }
21
+ },
22
+ errorHandler: (error)=>{
23
+ if (error instanceof WorkspaceNotFoundError) {
24
+ throw new ClientError('Workspace not found', 'not-found', {
25
+ status: 404
26
+ });
27
+ }
28
+ if (error instanceof MembershipRequiredError) {
29
+ throw new ClientError('Not a member of this workspace', 'forbidden', {
30
+ status: 403
31
+ });
32
+ }
33
+ if (error instanceof OpenInvitationExistsError) {
34
+ throw new ClientError(error.message, 'open-invitation-exists', {
35
+ status: 409
36
+ });
37
+ }
38
+ if (error instanceof WorkspaceInactiveError) {
39
+ throw new ClientError('Workspace is not active', 'workspace-inactive', {
40
+ status: 403
41
+ });
42
+ }
43
+ throw error;
44
+ },
45
+ handler: async (request, reply)=>{
46
+ const client = getUserContext(request);
47
+ if (!client) {
48
+ throw new ClientError('Authentication required', 'unauthorized', {
49
+ status: 401
50
+ });
51
+ }
52
+ const { workspaceId } = request.params;
53
+ const { email } = request.body;
54
+ const invitation = await createWorkspaceInvitation({
55
+ workspaceId,
56
+ email,
57
+ invitedByUserId: client.userId,
58
+ invitedByDisplay: client.name ?? 'A workspace admin',
59
+ invitedByMemberships: client.memberships
60
+ });
61
+ reply.code(201);
62
+ return toInvitationDto(invitation);
63
+ }
64
+ });
65
+
66
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/invitations/create.ts"],"sourcesContent":["import {AUTH_USER, getUserContext} from '@shipfox/api-auth-context';\nimport {createInvitationBodySchema, invitationDtoSchema} from '@shipfox/api-workspaces-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n MembershipRequiredError,\n OpenInvitationExistsError,\n WorkspaceInactiveError,\n WorkspaceNotFoundError,\n} from '#core/errors.js';\nimport {createWorkspaceInvitation} from '#core/index.js';\nimport {toInvitationDto} from '#presentation/dto/index.js';\n\nexport const createInvitationRoute = defineRoute({\n method: 'POST',\n path: '/',\n description: 'Invite someone to join a workspace by email.',\n auth: AUTH_USER,\n schema: {\n params: z.object({workspaceId: z.string().uuid()}),\n body: createInvitationBodySchema,\n response: {\n 201: invitationDtoSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof WorkspaceNotFoundError) {\n throw new ClientError('Workspace not found', 'not-found', {status: 404});\n }\n if (error instanceof MembershipRequiredError) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n if (error instanceof OpenInvitationExistsError) {\n throw new ClientError(error.message, 'open-invitation-exists', {status: 409});\n }\n if (error instanceof WorkspaceInactiveError) {\n throw new ClientError('Workspace is not active', 'workspace-inactive', {status: 403});\n }\n throw error;\n },\n handler: async (request, reply) => {\n const client = getUserContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n const {workspaceId} = request.params;\n const {email} = request.body;\n const invitation = await createWorkspaceInvitation({\n workspaceId,\n email,\n invitedByUserId: client.userId,\n invitedByDisplay: client.name ?? 'A workspace admin',\n invitedByMemberships: client.memberships,\n });\n\n reply.code(201);\n return toInvitationDto(invitation);\n },\n});\n"],"names":["AUTH_USER","getUserContext","createInvitationBodySchema","invitationDtoSchema","ClientError","defineRoute","z","MembershipRequiredError","OpenInvitationExistsError","WorkspaceInactiveError","WorkspaceNotFoundError","createWorkspaceInvitation","toInvitationDto","createInvitationRoute","method","path","description","auth","schema","params","object","workspaceId","string","uuid","body","response","errorHandler","error","status","message","handler","request","reply","client","email","invitation","invitedByUserId","userId","invitedByDisplay","name","invitedByMemberships","memberships","code"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,cAAc,QAAO,4BAA4B;AACpE,SAAQC,0BAA0B,EAAEC,mBAAmB,QAAO,8BAA8B;AAC5F,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SACEC,uBAAuB,EACvBC,yBAAyB,EACzBC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AACzB,SAAQC,yBAAyB,QAAO,iBAAiB;AACzD,SAAQC,eAAe,QAAO,6BAA6B;AAE3D,OAAO,MAAMC,wBAAwBR,YAAY;IAC/CS,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMjB;IACNkB,QAAQ;QACNC,QAAQb,EAAEc,MAAM,CAAC;YAACC,aAAaf,EAAEgB,MAAM,GAAGC,IAAI;QAAE;QAChDC,MAAMtB;QACNuB,UAAU;YACR,KAAKtB;QACP;IACF;IACAuB,cAAc,CAACC;QACb,IAAIA,iBAAiBjB,wBAAwB;YAC3C,MAAM,IAAIN,YAAY,uBAAuB,aAAa;gBAACwB,QAAQ;YAAG;QACxE;QACA,IAAID,iBAAiBpB,yBAAyB;YAC5C,MAAM,IAAIH,YAAY,kCAAkC,aAAa;gBAACwB,QAAQ;YAAG;QACnF;QACA,IAAID,iBAAiBnB,2BAA2B;YAC9C,MAAM,IAAIJ,YAAYuB,MAAME,OAAO,EAAE,0BAA0B;gBAACD,QAAQ;YAAG;QAC7E;QACA,IAAID,iBAAiBlB,wBAAwB;YAC3C,MAAM,IAAIL,YAAY,2BAA2B,sBAAsB;gBAACwB,QAAQ;YAAG;QACrF;QACA,MAAMD;IACR;IACAG,SAAS,OAAOC,SAASC;QACvB,MAAMC,SAAShC,eAAe8B;QAC9B,IAAI,CAACE,QAAQ;YACX,MAAM,IAAI7B,YAAY,2BAA2B,gBAAgB;gBAACwB,QAAQ;YAAG;QAC/E;QAEA,MAAM,EAACP,WAAW,EAAC,GAAGU,QAAQZ,MAAM;QACpC,MAAM,EAACe,KAAK,EAAC,GAAGH,QAAQP,IAAI;QAC5B,MAAMW,aAAa,MAAMxB,0BAA0B;YACjDU;YACAa;YACAE,iBAAiBH,OAAOI,MAAM;YAC9BC,kBAAkBL,OAAOM,IAAI,IAAI;YACjCC,sBAAsBP,OAAOQ,WAAW;QAC1C;QAEAT,MAAMU,IAAI,CAAC;QACX,OAAO9B,gBAAgBuB;IACzB;AACF,GAAG"}
@@ -0,0 +1,4 @@
1
+ import type { RouteDefinition, RouteGroup } from '@shipfox/node-fastify';
2
+ export declare const invitationsWorkspaceScopedRoutes: RouteDefinition[];
3
+ export declare const invitationsAcceptGroup: RouteGroup;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/invitations/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAOvE,eAAO,MAAM,gCAAgC,EAAE,eAAe,EAI7D,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,UAGpC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { acceptInvitationRoute } from './accept.js';
2
+ import { createInvitationRoute } from './create.js';
3
+ import { listInvitationsRoute } from './list.js';
4
+ import { previewInvitationRoute } from './preview.js';
5
+ import { revokeInvitationRoute } from './revoke.js';
6
+ export const invitationsWorkspaceScopedRoutes = [
7
+ createInvitationRoute,
8
+ listInvitationsRoute,
9
+ revokeInvitationRoute
10
+ ];
11
+ export const invitationsAcceptGroup = {
12
+ prefix: '/invitations',
13
+ routes: [
14
+ acceptInvitationRoute,
15
+ previewInvitationRoute
16
+ ]
17
+ };
18
+
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/invitations/index.ts"],"sourcesContent":["import type {RouteDefinition, RouteGroup} from '@shipfox/node-fastify';\nimport {acceptInvitationRoute} from './accept.js';\nimport {createInvitationRoute} from './create.js';\nimport {listInvitationsRoute} from './list.js';\nimport {previewInvitationRoute} from './preview.js';\nimport {revokeInvitationRoute} from './revoke.js';\n\nexport const invitationsWorkspaceScopedRoutes: RouteDefinition[] = [\n createInvitationRoute,\n listInvitationsRoute,\n revokeInvitationRoute,\n];\n\nexport const invitationsAcceptGroup: RouteGroup = {\n prefix: '/invitations',\n routes: [acceptInvitationRoute, previewInvitationRoute],\n};\n"],"names":["acceptInvitationRoute","createInvitationRoute","listInvitationsRoute","previewInvitationRoute","revokeInvitationRoute","invitationsWorkspaceScopedRoutes","invitationsAcceptGroup","prefix","routes"],"mappings":"AACA,SAAQA,qBAAqB,QAAO,cAAc;AAClD,SAAQC,qBAAqB,QAAO,cAAc;AAClD,SAAQC,oBAAoB,QAAO,YAAY;AAC/C,SAAQC,sBAAsB,QAAO,eAAe;AACpD,SAAQC,qBAAqB,QAAO,cAAc;AAElD,OAAO,MAAMC,mCAAsD;IACjEJ;IACAC;IACAE;CACD,CAAC;AAEF,OAAO,MAAME,yBAAqC;IAChDC,QAAQ;IACRC,QAAQ;QAACR;QAAuBG;KAAuB;AACzD,EAAE"}
@@ -0,0 +1,2 @@
1
+ export declare const listInvitationsRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/invitations/list.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,oBAAoB,iDAwC/B,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { AUTH_USER, getUserContext } from '@shipfox/api-auth-context';
2
+ import { listInvitationsResponseSchema } from '@shipfox/api-workspaces-dto';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { z } from 'zod';
5
+ import { MembershipRequiredError, WorkspaceInactiveError, WorkspaceNotFoundError } from '#core/errors.js';
6
+ import { listWorkspaceInvitations } from '#core/index.js';
7
+ import { toInvitationDto } from '#presentation/dto/index.js';
8
+ export const listInvitationsRoute = defineRoute({
9
+ method: 'GET',
10
+ path: '/',
11
+ description: 'List pending invitations for a workspace.',
12
+ auth: AUTH_USER,
13
+ schema: {
14
+ params: z.object({
15
+ workspaceId: z.string().uuid()
16
+ }),
17
+ response: {
18
+ 200: listInvitationsResponseSchema
19
+ }
20
+ },
21
+ errorHandler: (error)=>{
22
+ if (error instanceof WorkspaceNotFoundError) {
23
+ throw new ClientError('Workspace not found', 'not-found', {
24
+ status: 404
25
+ });
26
+ }
27
+ if (error instanceof MembershipRequiredError) {
28
+ throw new ClientError('Not a member of this workspace', 'forbidden', {
29
+ status: 403
30
+ });
31
+ }
32
+ if (error instanceof WorkspaceInactiveError) {
33
+ throw new ClientError('Workspace is not active', 'workspace-inactive', {
34
+ status: 403
35
+ });
36
+ }
37
+ throw error;
38
+ },
39
+ handler: async (request)=>{
40
+ const client = getUserContext(request);
41
+ if (!client) {
42
+ throw new ClientError('Authentication required', 'unauthorized', {
43
+ status: 401
44
+ });
45
+ }
46
+ const { workspaceId } = request.params;
47
+ const invitations = await listWorkspaceInvitations({
48
+ workspaceId,
49
+ requesterUserId: client.userId,
50
+ requesterMemberships: client.memberships
51
+ });
52
+ return {
53
+ invitations: invitations.map(toInvitationDto)
54
+ };
55
+ }
56
+ });
57
+
58
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/invitations/list.ts"],"sourcesContent":["import {AUTH_USER, getUserContext} from '@shipfox/api-auth-context';\nimport {listInvitationsResponseSchema} from '@shipfox/api-workspaces-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n MembershipRequiredError,\n WorkspaceInactiveError,\n WorkspaceNotFoundError,\n} from '#core/errors.js';\nimport {listWorkspaceInvitations} from '#core/index.js';\nimport {toInvitationDto} from '#presentation/dto/index.js';\n\nexport const listInvitationsRoute = defineRoute({\n method: 'GET',\n path: '/',\n description: 'List pending invitations for a workspace.',\n auth: AUTH_USER,\n schema: {\n params: z.object({workspaceId: z.string().uuid()}),\n response: {\n 200: listInvitationsResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof WorkspaceNotFoundError) {\n throw new ClientError('Workspace not found', 'not-found', {status: 404});\n }\n if (error instanceof MembershipRequiredError) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n if (error instanceof WorkspaceInactiveError) {\n throw new ClientError('Workspace is not active', 'workspace-inactive', {status: 403});\n }\n throw error;\n },\n handler: async (request) => {\n const client = getUserContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n const {workspaceId} = request.params;\n const invitations = await listWorkspaceInvitations({\n workspaceId,\n requesterUserId: client.userId,\n requesterMemberships: client.memberships,\n });\n\n return {\n invitations: invitations.map(toInvitationDto),\n };\n },\n});\n"],"names":["AUTH_USER","getUserContext","listInvitationsResponseSchema","ClientError","defineRoute","z","MembershipRequiredError","WorkspaceInactiveError","WorkspaceNotFoundError","listWorkspaceInvitations","toInvitationDto","listInvitationsRoute","method","path","description","auth","schema","params","object","workspaceId","string","uuid","response","errorHandler","error","status","handler","request","client","invitations","requesterUserId","userId","requesterMemberships","memberships","map"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,cAAc,QAAO,4BAA4B;AACpE,SAAQC,6BAA6B,QAAO,8BAA8B;AAC1E,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SACEC,uBAAuB,EACvBC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AACzB,SAAQC,wBAAwB,QAAO,iBAAiB;AACxD,SAAQC,eAAe,QAAO,6BAA6B;AAE3D,OAAO,MAAMC,uBAAuBP,YAAY;IAC9CQ,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMf;IACNgB,QAAQ;QACNC,QAAQZ,EAAEa,MAAM,CAAC;YAACC,aAAad,EAAEe,MAAM,GAAGC,IAAI;QAAE;QAChDC,UAAU;YACR,KAAKpB;QACP;IACF;IACAqB,cAAc,CAACC;QACb,IAAIA,iBAAiBhB,wBAAwB;YAC3C,MAAM,IAAIL,YAAY,uBAAuB,aAAa;gBAACsB,QAAQ;YAAG;QACxE;QACA,IAAID,iBAAiBlB,yBAAyB;YAC5C,MAAM,IAAIH,YAAY,kCAAkC,aAAa;gBAACsB,QAAQ;YAAG;QACnF;QACA,IAAID,iBAAiBjB,wBAAwB;YAC3C,MAAM,IAAIJ,YAAY,2BAA2B,sBAAsB;gBAACsB,QAAQ;YAAG;QACrF;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC;QACd,MAAMC,SAAS3B,eAAe0B;QAC9B,IAAI,CAACC,QAAQ;YACX,MAAM,IAAIzB,YAAY,2BAA2B,gBAAgB;gBAACsB,QAAQ;YAAG;QAC/E;QAEA,MAAM,EAACN,WAAW,EAAC,GAAGQ,QAAQV,MAAM;QACpC,MAAMY,cAAc,MAAMpB,yBAAyB;YACjDU;YACAW,iBAAiBF,OAAOG,MAAM;YAC9BC,sBAAsBJ,OAAOK,WAAW;QAC1C;QAEA,OAAO;YACLJ,aAAaA,YAAYK,GAAG,CAACxB;QAC/B;IACF;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const previewInvitationRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/invitations/preview.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,iDAsCjC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { previewInvitationQuerySchema, previewInvitationResponseSchema } from '@shipfox/api-workspaces-dto';
2
+ import { defineRoute } from '@shipfox/node-fastify';
3
+ import { previewInvitation } from '#core/index.js';
4
+ export const previewInvitationRoute = defineRoute({
5
+ method: 'GET',
6
+ path: '/preview',
7
+ description: 'Preview an invitation by opaque token (public, no auth).',
8
+ schema: {
9
+ querystring: previewInvitationQuerySchema,
10
+ response: {
11
+ 200: previewInvitationResponseSchema
12
+ }
13
+ },
14
+ handler: async (request)=>{
15
+ const result = await previewInvitation({
16
+ token: request.query.token
17
+ });
18
+ switch(result.status){
19
+ case 'pending':
20
+ return {
21
+ status: 'pending',
22
+ workspace_id: result.workspaceId,
23
+ workspace_name: result.workspaceName,
24
+ email: result.email,
25
+ invited_by_display: result.invitedByDisplay,
26
+ expires_at: result.expiresAt.toISOString()
27
+ };
28
+ case 'expired':
29
+ return {
30
+ status: 'expired',
31
+ workspace_name: result.workspaceName,
32
+ expires_at: result.expiresAt.toISOString()
33
+ };
34
+ case 'already_used':
35
+ return {
36
+ status: 'already_used',
37
+ workspace_name: result.workspaceName
38
+ };
39
+ case 'invalid':
40
+ return {
41
+ status: 'invalid'
42
+ };
43
+ }
44
+ }
45
+ });
46
+
47
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/invitations/preview.ts"],"sourcesContent":["import {\n previewInvitationQuerySchema,\n previewInvitationResponseSchema,\n} from '@shipfox/api-workspaces-dto';\nimport {defineRoute} from '@shipfox/node-fastify';\nimport {previewInvitation} from '#core/index.js';\n\nexport const previewInvitationRoute = defineRoute({\n method: 'GET',\n path: '/preview',\n description: 'Preview an invitation by opaque token (public, no auth).',\n schema: {\n querystring: previewInvitationQuerySchema,\n response: {\n 200: previewInvitationResponseSchema,\n },\n },\n handler: async (request) => {\n const result = await previewInvitation({token: request.query.token});\n\n switch (result.status) {\n case 'pending':\n return {\n status: 'pending' as const,\n workspace_id: result.workspaceId,\n workspace_name: result.workspaceName,\n email: result.email,\n invited_by_display: result.invitedByDisplay,\n expires_at: result.expiresAt.toISOString(),\n };\n case 'expired':\n return {\n status: 'expired' as const,\n workspace_name: result.workspaceName,\n expires_at: result.expiresAt.toISOString(),\n };\n case 'already_used':\n return {\n status: 'already_used' as const,\n workspace_name: result.workspaceName,\n };\n case 'invalid':\n return {status: 'invalid' as const};\n }\n },\n});\n"],"names":["previewInvitationQuerySchema","previewInvitationResponseSchema","defineRoute","previewInvitation","previewInvitationRoute","method","path","description","schema","querystring","response","handler","request","result","token","query","status","workspace_id","workspaceId","workspace_name","workspaceName","email","invited_by_display","invitedByDisplay","expires_at","expiresAt","toISOString"],"mappings":"AAAA,SACEA,4BAA4B,EAC5BC,+BAA+B,QAC1B,8BAA8B;AACrC,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SAAQC,iBAAiB,QAAO,iBAAiB;AAEjD,OAAO,MAAMC,yBAAyBF,YAAY;IAChDG,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,aAAaT;QACbU,UAAU;YACR,KAAKT;QACP;IACF;IACAU,SAAS,OAAOC;QACd,MAAMC,SAAS,MAAMV,kBAAkB;YAACW,OAAOF,QAAQG,KAAK,CAACD,KAAK;QAAA;QAElE,OAAQD,OAAOG,MAAM;YACnB,KAAK;gBACH,OAAO;oBACLA,QAAQ;oBACRC,cAAcJ,OAAOK,WAAW;oBAChCC,gBAAgBN,OAAOO,aAAa;oBACpCC,OAAOR,OAAOQ,KAAK;oBACnBC,oBAAoBT,OAAOU,gBAAgB;oBAC3CC,YAAYX,OAAOY,SAAS,CAACC,WAAW;gBAC1C;YACF,KAAK;gBACH,OAAO;oBACLV,QAAQ;oBACRG,gBAAgBN,OAAOO,aAAa;oBACpCI,YAAYX,OAAOY,SAAS,CAACC,WAAW;gBAC1C;YACF,KAAK;gBACH,OAAO;oBACLV,QAAQ;oBACRG,gBAAgBN,OAAOO,aAAa;gBACtC;YACF,KAAK;gBACH,OAAO;oBAACJ,QAAQ;gBAAkB;QACtC;IACF;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const revokeInvitationRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=revoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revoke.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/invitations/revoke.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,qBAAqB,iDAmDhC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { AUTH_USER, getUserContext } from '@shipfox/api-auth-context';
2
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
3
+ import { z } from 'zod';
4
+ import { InvitationNotFoundError, InvitationWorkspaceMismatchError, MembershipRequiredError, WorkspaceInactiveError, WorkspaceNotFoundError } from '#core/errors.js';
5
+ import { revokeWorkspaceInvitation } from '#core/index.js';
6
+ export const revokeInvitationRoute = defineRoute({
7
+ method: 'DELETE',
8
+ path: '/:invitationId',
9
+ description: 'Cancel a pending invitation.',
10
+ auth: AUTH_USER,
11
+ schema: {
12
+ params: z.object({
13
+ workspaceId: z.string().uuid(),
14
+ invitationId: z.string().uuid()
15
+ }),
16
+ response: {
17
+ 204: z.void()
18
+ }
19
+ },
20
+ errorHandler: (error)=>{
21
+ if (error instanceof WorkspaceNotFoundError) {
22
+ throw new ClientError('Workspace not found', 'not-found', {
23
+ status: 404
24
+ });
25
+ }
26
+ if (error instanceof MembershipRequiredError) {
27
+ throw new ClientError('Not a member of this workspace', 'forbidden', {
28
+ status: 403
29
+ });
30
+ }
31
+ if (error instanceof InvitationNotFoundError) {
32
+ throw new ClientError('Invitation not found', 'not-found', {
33
+ status: 404
34
+ });
35
+ }
36
+ if (error instanceof InvitationWorkspaceMismatchError) {
37
+ throw new ClientError('Invitation does not belong to this workspace', 'forbidden', {
38
+ status: 403
39
+ });
40
+ }
41
+ if (error instanceof WorkspaceInactiveError) {
42
+ throw new ClientError('Workspace is not active', 'workspace-inactive', {
43
+ status: 403
44
+ });
45
+ }
46
+ throw error;
47
+ },
48
+ handler: async (request, reply)=>{
49
+ const client = getUserContext(request);
50
+ if (!client) {
51
+ throw new ClientError('Authentication required', 'unauthorized', {
52
+ status: 401
53
+ });
54
+ }
55
+ const { workspaceId, invitationId } = request.params;
56
+ await revokeWorkspaceInvitation({
57
+ workspaceId,
58
+ invitationId,
59
+ requesterUserId: client.userId,
60
+ requesterMemberships: client.memberships
61
+ });
62
+ reply.code(204);
63
+ }
64
+ });
65
+
66
+ //# sourceMappingURL=revoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/invitations/revoke.ts"],"sourcesContent":["import {AUTH_USER, getUserContext} from '@shipfox/api-auth-context';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n InvitationNotFoundError,\n InvitationWorkspaceMismatchError,\n MembershipRequiredError,\n WorkspaceInactiveError,\n WorkspaceNotFoundError,\n} from '#core/errors.js';\nimport {revokeWorkspaceInvitation} from '#core/index.js';\n\nexport const revokeInvitationRoute = defineRoute({\n method: 'DELETE',\n path: '/:invitationId',\n description: 'Cancel a pending invitation.',\n auth: AUTH_USER,\n schema: {\n params: z.object({\n workspaceId: z.string().uuid(),\n invitationId: z.string().uuid(),\n }),\n response: {\n 204: z.void(),\n },\n },\n errorHandler: (error) => {\n if (error instanceof WorkspaceNotFoundError) {\n throw new ClientError('Workspace not found', 'not-found', {status: 404});\n }\n if (error instanceof MembershipRequiredError) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n if (error instanceof InvitationNotFoundError) {\n throw new ClientError('Invitation not found', 'not-found', {status: 404});\n }\n if (error instanceof InvitationWorkspaceMismatchError) {\n throw new ClientError('Invitation does not belong to this workspace', 'forbidden', {\n status: 403,\n });\n }\n if (error instanceof WorkspaceInactiveError) {\n throw new ClientError('Workspace is not active', 'workspace-inactive', {status: 403});\n }\n throw error;\n },\n handler: async (request, reply) => {\n const client = getUserContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n const {workspaceId, invitationId} = request.params;\n\n await revokeWorkspaceInvitation({\n workspaceId,\n invitationId,\n requesterUserId: client.userId,\n requesterMemberships: client.memberships,\n });\n\n reply.code(204);\n },\n});\n"],"names":["AUTH_USER","getUserContext","ClientError","defineRoute","z","InvitationNotFoundError","InvitationWorkspaceMismatchError","MembershipRequiredError","WorkspaceInactiveError","WorkspaceNotFoundError","revokeWorkspaceInvitation","revokeInvitationRoute","method","path","description","auth","schema","params","object","workspaceId","string","uuid","invitationId","response","void","errorHandler","error","status","handler","request","reply","client","requesterUserId","userId","requesterMemberships","memberships","code"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,cAAc,QAAO,4BAA4B;AACpE,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SACEC,uBAAuB,EACvBC,gCAAgC,EAChCC,uBAAuB,EACvBC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AACzB,SAAQC,yBAAyB,QAAO,iBAAiB;AAEzD,OAAO,MAAMC,wBAAwBR,YAAY;IAC/CS,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMf;IACNgB,QAAQ;QACNC,QAAQb,EAAEc,MAAM,CAAC;YACfC,aAAaf,EAAEgB,MAAM,GAAGC,IAAI;YAC5BC,cAAclB,EAAEgB,MAAM,GAAGC,IAAI;QAC/B;QACAE,UAAU;YACR,KAAKnB,EAAEoB,IAAI;QACb;IACF;IACAC,cAAc,CAACC;QACb,IAAIA,iBAAiBjB,wBAAwB;YAC3C,MAAM,IAAIP,YAAY,uBAAuB,aAAa;gBAACyB,QAAQ;YAAG;QACxE;QACA,IAAID,iBAAiBnB,yBAAyB;YAC5C,MAAM,IAAIL,YAAY,kCAAkC,aAAa;gBAACyB,QAAQ;YAAG;QACnF;QACA,IAAID,iBAAiBrB,yBAAyB;YAC5C,MAAM,IAAIH,YAAY,wBAAwB,aAAa;gBAACyB,QAAQ;YAAG;QACzE;QACA,IAAID,iBAAiBpB,kCAAkC;YACrD,MAAM,IAAIJ,YAAY,gDAAgD,aAAa;gBACjFyB,QAAQ;YACV;QACF;QACA,IAAID,iBAAiBlB,wBAAwB;YAC3C,MAAM,IAAIN,YAAY,2BAA2B,sBAAsB;gBAACyB,QAAQ;YAAG;QACrF;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC,SAASC;QACvB,MAAMC,SAAS9B,eAAe4B;QAC9B,IAAI,CAACE,QAAQ;YACX,MAAM,IAAI7B,YAAY,2BAA2B,gBAAgB;gBAACyB,QAAQ;YAAG;QAC/E;QAEA,MAAM,EAACR,WAAW,EAAEG,YAAY,EAAC,GAAGO,QAAQZ,MAAM;QAElD,MAAMP,0BAA0B;YAC9BS;YACAG;YACAU,iBAAiBD,OAAOE,MAAM;YAC9BC,sBAAsBH,OAAOI,WAAW;QAC1C;QAEAL,MAAMM,IAAI,CAAC;IACb;AACF,GAAG"}
@@ -0,0 +1,3 @@
1
+ import type { RouteDefinition } from '@shipfox/node-fastify';
2
+ export declare const memberRoutes: RouteDefinition[];
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/members/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAI3D,eAAO,MAAM,YAAY,EAAE,eAAe,EAA0C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { listMembersRoute } from './list.js';
2
+ import { removeMemberRoute } from './remove.js';
3
+ export const memberRoutes = [
4
+ listMembersRoute,
5
+ removeMemberRoute
6
+ ];
7
+
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/members/index.ts"],"sourcesContent":["import type {RouteDefinition} from '@shipfox/node-fastify';\nimport {listMembersRoute} from './list.js';\nimport {removeMemberRoute} from './remove.js';\n\nexport const memberRoutes: RouteDefinition[] = [listMembersRoute, removeMemberRoute];\n"],"names":["listMembersRoute","removeMemberRoute","memberRoutes"],"mappings":"AACA,SAAQA,gBAAgB,QAAO,YAAY;AAC3C,SAAQC,iBAAiB,QAAO,cAAc;AAE9C,OAAO,MAAMC,eAAkC;IAACF;IAAkBC;CAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const listMembersRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/members/list.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,gBAAgB,iDAwC3B,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { AUTH_USER, getUserContext } from '@shipfox/api-auth-context';
2
+ import { listMembersResponseSchema } from '@shipfox/api-workspaces-dto';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { z } from 'zod';
5
+ import { MembershipRequiredError, WorkspaceInactiveError, WorkspaceNotFoundError } from '#core/errors.js';
6
+ import { listWorkspaceMembers } from '#core/index.js';
7
+ import { toMembershipWithUserDto } from '#presentation/dto/index.js';
8
+ export const listMembersRoute = defineRoute({
9
+ method: 'GET',
10
+ path: '/',
11
+ description: 'List the members of a workspace.',
12
+ auth: AUTH_USER,
13
+ schema: {
14
+ params: z.object({
15
+ workspaceId: z.string().uuid()
16
+ }),
17
+ response: {
18
+ 200: listMembersResponseSchema
19
+ }
20
+ },
21
+ errorHandler: (error)=>{
22
+ if (error instanceof WorkspaceNotFoundError) {
23
+ throw new ClientError('Workspace not found', 'not-found', {
24
+ status: 404
25
+ });
26
+ }
27
+ if (error instanceof MembershipRequiredError) {
28
+ throw new ClientError('Not a member of this workspace', 'forbidden', {
29
+ status: 403
30
+ });
31
+ }
32
+ if (error instanceof WorkspaceInactiveError) {
33
+ throw new ClientError('Workspace is not active', 'workspace-inactive', {
34
+ status: 403
35
+ });
36
+ }
37
+ throw error;
38
+ },
39
+ handler: async (request)=>{
40
+ const client = getUserContext(request);
41
+ if (!client) {
42
+ throw new ClientError('Authentication required', 'unauthorized', {
43
+ status: 401
44
+ });
45
+ }
46
+ const { workspaceId } = request.params;
47
+ const members = await listWorkspaceMembers({
48
+ workspaceId,
49
+ requesterUserId: client.userId,
50
+ requesterMemberships: client.memberships
51
+ });
52
+ return {
53
+ members: members.map(toMembershipWithUserDto)
54
+ };
55
+ }
56
+ });
57
+
58
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/members/list.ts"],"sourcesContent":["import {AUTH_USER, getUserContext} from '@shipfox/api-auth-context';\nimport {listMembersResponseSchema} from '@shipfox/api-workspaces-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n MembershipRequiredError,\n WorkspaceInactiveError,\n WorkspaceNotFoundError,\n} from '#core/errors.js';\nimport {listWorkspaceMembers} from '#core/index.js';\nimport {toMembershipWithUserDto} from '#presentation/dto/index.js';\n\nexport const listMembersRoute = defineRoute({\n method: 'GET',\n path: '/',\n description: 'List the members of a workspace.',\n auth: AUTH_USER,\n schema: {\n params: z.object({workspaceId: z.string().uuid()}),\n response: {\n 200: listMembersResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof WorkspaceNotFoundError) {\n throw new ClientError('Workspace not found', 'not-found', {status: 404});\n }\n if (error instanceof MembershipRequiredError) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n if (error instanceof WorkspaceInactiveError) {\n throw new ClientError('Workspace is not active', 'workspace-inactive', {status: 403});\n }\n throw error;\n },\n handler: async (request) => {\n const client = getUserContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n const {workspaceId} = request.params;\n const members = await listWorkspaceMembers({\n workspaceId,\n requesterUserId: client.userId,\n requesterMemberships: client.memberships,\n });\n\n return {\n members: members.map(toMembershipWithUserDto),\n };\n },\n});\n"],"names":["AUTH_USER","getUserContext","listMembersResponseSchema","ClientError","defineRoute","z","MembershipRequiredError","WorkspaceInactiveError","WorkspaceNotFoundError","listWorkspaceMembers","toMembershipWithUserDto","listMembersRoute","method","path","description","auth","schema","params","object","workspaceId","string","uuid","response","errorHandler","error","status","handler","request","client","members","requesterUserId","userId","requesterMemberships","memberships","map"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,cAAc,QAAO,4BAA4B;AACpE,SAAQC,yBAAyB,QAAO,8BAA8B;AACtE,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SACEC,uBAAuB,EACvBC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AACzB,SAAQC,oBAAoB,QAAO,iBAAiB;AACpD,SAAQC,uBAAuB,QAAO,6BAA6B;AAEnE,OAAO,MAAMC,mBAAmBP,YAAY;IAC1CQ,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMf;IACNgB,QAAQ;QACNC,QAAQZ,EAAEa,MAAM,CAAC;YAACC,aAAad,EAAEe,MAAM,GAAGC,IAAI;QAAE;QAChDC,UAAU;YACR,KAAKpB;QACP;IACF;IACAqB,cAAc,CAACC;QACb,IAAIA,iBAAiBhB,wBAAwB;YAC3C,MAAM,IAAIL,YAAY,uBAAuB,aAAa;gBAACsB,QAAQ;YAAG;QACxE;QACA,IAAID,iBAAiBlB,yBAAyB;YAC5C,MAAM,IAAIH,YAAY,kCAAkC,aAAa;gBAACsB,QAAQ;YAAG;QACnF;QACA,IAAID,iBAAiBjB,wBAAwB;YAC3C,MAAM,IAAIJ,YAAY,2BAA2B,sBAAsB;gBAACsB,QAAQ;YAAG;QACrF;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC;QACd,MAAMC,SAAS3B,eAAe0B;QAC9B,IAAI,CAACC,QAAQ;YACX,MAAM,IAAIzB,YAAY,2BAA2B,gBAAgB;gBAACsB,QAAQ;YAAG;QAC/E;QAEA,MAAM,EAACN,WAAW,EAAC,GAAGQ,QAAQV,MAAM;QACpC,MAAMY,UAAU,MAAMpB,qBAAqB;YACzCU;YACAW,iBAAiBF,OAAOG,MAAM;YAC9BC,sBAAsBJ,OAAOK,WAAW;QAC1C;QAEA,OAAO;YACLJ,SAASA,QAAQK,GAAG,CAACxB;QACvB;IACF;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const removeMemberRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/members/remove.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,iBAAiB,iDAoD5B,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { AUTH_USER, getUserContext } from '@shipfox/api-auth-context';
2
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
3
+ import { z } from 'zod';
4
+ import { LastMemberError, MembershipNotFoundError, MembershipRequiredError, SelfRemovalNotAllowedError, WorkspaceInactiveError, WorkspaceNotFoundError } from '#core/errors.js';
5
+ import { removeWorkspaceMember } from '#core/index.js';
6
+ export const removeMemberRoute = defineRoute({
7
+ method: 'DELETE',
8
+ path: '/:userId',
9
+ description: 'Remove a member from a workspace.',
10
+ auth: AUTH_USER,
11
+ schema: {
12
+ params: z.object({
13
+ workspaceId: z.string().uuid(),
14
+ userId: z.string().uuid()
15
+ }),
16
+ response: {
17
+ 204: z.void()
18
+ }
19
+ },
20
+ errorHandler: (error)=>{
21
+ if (error instanceof WorkspaceNotFoundError) {
22
+ throw new ClientError('Workspace not found', 'not-found', {
23
+ status: 404
24
+ });
25
+ }
26
+ if (error instanceof MembershipRequiredError) {
27
+ throw new ClientError('Not a member of this workspace', 'forbidden', {
28
+ status: 403
29
+ });
30
+ }
31
+ if (error instanceof MembershipNotFoundError) {
32
+ throw new ClientError('Member not found', 'not-found', {
33
+ status: 404
34
+ });
35
+ }
36
+ if (error instanceof LastMemberError) {
37
+ throw new ClientError(error.message, 'last-member', {
38
+ status: 409
39
+ });
40
+ }
41
+ if (error instanceof SelfRemovalNotAllowedError) {
42
+ throw new ClientError(error.message, 'self-removal-not-allowed', {
43
+ status: 409
44
+ });
45
+ }
46
+ if (error instanceof WorkspaceInactiveError) {
47
+ throw new ClientError('Workspace is not active', 'workspace-inactive', {
48
+ status: 403
49
+ });
50
+ }
51
+ throw error;
52
+ },
53
+ handler: async (request, reply)=>{
54
+ const client = getUserContext(request);
55
+ if (!client) {
56
+ throw new ClientError('Authentication required', 'unauthorized', {
57
+ status: 401
58
+ });
59
+ }
60
+ const { workspaceId, userId } = request.params;
61
+ await removeWorkspaceMember({
62
+ workspaceId,
63
+ userId,
64
+ requesterUserId: client.userId,
65
+ requesterMemberships: client.memberships
66
+ });
67
+ reply.code(204);
68
+ }
69
+ });
70
+
71
+ //# sourceMappingURL=remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/members/remove.ts"],"sourcesContent":["import {AUTH_USER, getUserContext} from '@shipfox/api-auth-context';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n LastMemberError,\n MembershipNotFoundError,\n MembershipRequiredError,\n SelfRemovalNotAllowedError,\n WorkspaceInactiveError,\n WorkspaceNotFoundError,\n} from '#core/errors.js';\nimport {removeWorkspaceMember} from '#core/index.js';\n\nexport const removeMemberRoute = defineRoute({\n method: 'DELETE',\n path: '/:userId',\n description: 'Remove a member from a workspace.',\n auth: AUTH_USER,\n schema: {\n params: z.object({\n workspaceId: z.string().uuid(),\n userId: z.string().uuid(),\n }),\n response: {\n 204: z.void(),\n },\n },\n errorHandler: (error) => {\n if (error instanceof WorkspaceNotFoundError) {\n throw new ClientError('Workspace not found', 'not-found', {status: 404});\n }\n if (error instanceof MembershipRequiredError) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n if (error instanceof MembershipNotFoundError) {\n throw new ClientError('Member not found', 'not-found', {status: 404});\n }\n if (error instanceof LastMemberError) {\n throw new ClientError(error.message, 'last-member', {status: 409});\n }\n if (error instanceof SelfRemovalNotAllowedError) {\n throw new ClientError(error.message, 'self-removal-not-allowed', {status: 409});\n }\n if (error instanceof WorkspaceInactiveError) {\n throw new ClientError('Workspace is not active', 'workspace-inactive', {status: 403});\n }\n throw error;\n },\n handler: async (request, reply) => {\n const client = getUserContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n const {workspaceId, userId} = request.params;\n\n await removeWorkspaceMember({\n workspaceId,\n userId,\n requesterUserId: client.userId,\n requesterMemberships: client.memberships,\n });\n\n reply.code(204);\n },\n});\n"],"names":["AUTH_USER","getUserContext","ClientError","defineRoute","z","LastMemberError","MembershipNotFoundError","MembershipRequiredError","SelfRemovalNotAllowedError","WorkspaceInactiveError","WorkspaceNotFoundError","removeWorkspaceMember","removeMemberRoute","method","path","description","auth","schema","params","object","workspaceId","string","uuid","userId","response","void","errorHandler","error","status","message","handler","request","reply","client","requesterUserId","requesterMemberships","memberships","code"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,cAAc,QAAO,4BAA4B;AACpE,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SACEC,eAAe,EACfC,uBAAuB,EACvBC,uBAAuB,EACvBC,0BAA0B,EAC1BC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AACzB,SAAQC,qBAAqB,QAAO,iBAAiB;AAErD,OAAO,MAAMC,oBAAoBT,YAAY;IAC3CU,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMhB;IACNiB,QAAQ;QACNC,QAAQd,EAAEe,MAAM,CAAC;YACfC,aAAahB,EAAEiB,MAAM,GAAGC,IAAI;YAC5BC,QAAQnB,EAAEiB,MAAM,GAAGC,IAAI;QACzB;QACAE,UAAU;YACR,KAAKpB,EAAEqB,IAAI;QACb;IACF;IACAC,cAAc,CAACC;QACb,IAAIA,iBAAiBjB,wBAAwB;YAC3C,MAAM,IAAIR,YAAY,uBAAuB,aAAa;gBAAC0B,QAAQ;YAAG;QACxE;QACA,IAAID,iBAAiBpB,yBAAyB;YAC5C,MAAM,IAAIL,YAAY,kCAAkC,aAAa;gBAAC0B,QAAQ;YAAG;QACnF;QACA,IAAID,iBAAiBrB,yBAAyB;YAC5C,MAAM,IAAIJ,YAAY,oBAAoB,aAAa;gBAAC0B,QAAQ;YAAG;QACrE;QACA,IAAID,iBAAiBtB,iBAAiB;YACpC,MAAM,IAAIH,YAAYyB,MAAME,OAAO,EAAE,eAAe;gBAACD,QAAQ;YAAG;QAClE;QACA,IAAID,iBAAiBnB,4BAA4B;YAC/C,MAAM,IAAIN,YAAYyB,MAAME,OAAO,EAAE,4BAA4B;gBAACD,QAAQ;YAAG;QAC/E;QACA,IAAID,iBAAiBlB,wBAAwB;YAC3C,MAAM,IAAIP,YAAY,2BAA2B,sBAAsB;gBAAC0B,QAAQ;YAAG;QACrF;QACA,MAAMD;IACR;IACAG,SAAS,OAAOC,SAASC;QACvB,MAAMC,SAAShC,eAAe8B;QAC9B,IAAI,CAACE,QAAQ;YACX,MAAM,IAAI/B,YAAY,2BAA2B,gBAAgB;gBAAC0B,QAAQ;YAAG;QAC/E;QAEA,MAAM,EAACR,WAAW,EAAEG,MAAM,EAAC,GAAGQ,QAAQb,MAAM;QAE5C,MAAMP,sBAAsB;YAC1BS;YACAG;YACAW,iBAAiBD,OAAOV,MAAM;YAC9BY,sBAAsBF,OAAOG,WAAW;QAC1C;QAEAJ,MAAMK,IAAI,CAAC;IACb;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const createWorkspaceRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/workspaces/create.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,iDA6B/B,CAAC"}