@intlayer/backend 7.5.9 → 7.5.11

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 (247) hide show
  1. package/README.md +9 -2
  2. package/dist/assets/utils/AI/askDocQuestion/PROMPT.md +1 -1
  3. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/cli/ci.json +3080 -0
  4. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/cli/list_projects.json +1 -0
  5. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/intlayer_with_fastify.json +9 -0
  6. package/dist/esm/controllers/ai.controller.mjs +95 -128
  7. package/dist/esm/controllers/ai.controller.mjs.map +1 -1
  8. package/dist/esm/controllers/bitbucket.controller.mjs +77 -0
  9. package/dist/esm/controllers/bitbucket.controller.mjs.map +1 -0
  10. package/dist/esm/controllers/dictionary.controller.mjs +106 -198
  11. package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
  12. package/dist/esm/controllers/eventListener.controller.mjs +13 -19
  13. package/dist/esm/controllers/eventListener.controller.mjs.map +1 -1
  14. package/dist/esm/controllers/github.controller.mjs +77 -0
  15. package/dist/esm/controllers/github.controller.mjs.map +1 -0
  16. package/dist/esm/controllers/gitlab.controller.mjs +77 -0
  17. package/dist/esm/controllers/gitlab.controller.mjs.map +1 -0
  18. package/dist/esm/controllers/newsletter.controller.mjs +30 -60
  19. package/dist/esm/controllers/newsletter.controller.mjs.map +1 -1
  20. package/dist/esm/controllers/oAuth2.controller.mjs +11 -8
  21. package/dist/esm/controllers/oAuth2.controller.mjs.map +1 -1
  22. package/dist/esm/controllers/organization.controller.mjs +100 -225
  23. package/dist/esm/controllers/organization.controller.mjs.map +1 -1
  24. package/dist/esm/controllers/project.controller.mjs +194 -204
  25. package/dist/esm/controllers/project.controller.mjs.map +1 -1
  26. package/dist/esm/controllers/projectAccessKey.controller.mjs +38 -71
  27. package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
  28. package/dist/esm/controllers/search.controller.mjs +3 -3
  29. package/dist/esm/controllers/search.controller.mjs.map +1 -1
  30. package/dist/esm/controllers/stripe.controller.mjs +34 -67
  31. package/dist/esm/controllers/stripe.controller.mjs.map +1 -1
  32. package/dist/esm/controllers/tag.controller.mjs +51 -113
  33. package/dist/esm/controllers/tag.controller.mjs.map +1 -1
  34. package/dist/esm/controllers/user.controller.mjs +64 -113
  35. package/dist/esm/controllers/user.controller.mjs.map +1 -1
  36. package/dist/esm/export.mjs +4 -1
  37. package/dist/esm/index.mjs +105 -41
  38. package/dist/esm/index.mjs.map +1 -1
  39. package/dist/esm/middlewares/oAuth2.middleware.mjs +19 -14
  40. package/dist/esm/middlewares/oAuth2.middleware.mjs.map +1 -1
  41. package/dist/esm/middlewares/sessionAuth.middleware.mjs +6 -7
  42. package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
  43. package/dist/esm/routes/ai.routes.mjs +19 -15
  44. package/dist/esm/routes/ai.routes.mjs.map +1 -1
  45. package/dist/esm/routes/bitbucket.routes.mjs +43 -0
  46. package/dist/esm/routes/bitbucket.routes.mjs.map +1 -0
  47. package/dist/esm/routes/dictionary.routes.mjs +10 -10
  48. package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
  49. package/dist/esm/routes/eventListener.routes.mjs +3 -3
  50. package/dist/esm/routes/eventListener.routes.mjs.map +1 -1
  51. package/dist/esm/routes/github.routes.mjs +43 -0
  52. package/dist/esm/routes/github.routes.mjs.map +1 -0
  53. package/dist/esm/routes/gitlab.routes.mjs +43 -0
  54. package/dist/esm/routes/gitlab.routes.mjs.map +1 -0
  55. package/dist/esm/routes/newsletter.routes.mjs +5 -5
  56. package/dist/esm/routes/newsletter.routes.mjs.map +1 -1
  57. package/dist/esm/routes/organization.routes.mjs +11 -11
  58. package/dist/esm/routes/organization.routes.mjs.map +1 -1
  59. package/dist/esm/routes/project.routes.mjs +38 -14
  60. package/dist/esm/routes/project.routes.mjs.map +1 -1
  61. package/dist/esm/routes/search.routes.mjs +3 -3
  62. package/dist/esm/routes/search.routes.mjs.map +1 -1
  63. package/dist/esm/routes/stripe.routes.mjs +5 -5
  64. package/dist/esm/routes/stripe.routes.mjs.map +1 -1
  65. package/dist/esm/routes/tags.routes.mjs +6 -6
  66. package/dist/esm/routes/tags.routes.mjs.map +1 -1
  67. package/dist/esm/routes/user.routes.mjs +9 -9
  68. package/dist/esm/routes/user.routes.mjs.map +1 -1
  69. package/dist/esm/schemas/project.schema.mjs +70 -1
  70. package/dist/esm/schemas/project.schema.mjs.map +1 -1
  71. package/dist/esm/services/bitbucket.service.mjs +173 -0
  72. package/dist/esm/services/bitbucket.service.mjs.map +1 -0
  73. package/dist/esm/services/ci.service.mjs +134 -0
  74. package/dist/esm/services/ci.service.mjs.map +1 -0
  75. package/dist/esm/services/email.service.mjs +1 -1
  76. package/dist/esm/services/email.service.mjs.map +1 -1
  77. package/dist/esm/services/github.service.mjs +218 -0
  78. package/dist/esm/services/github.service.mjs.map +1 -0
  79. package/dist/esm/services/gitlab.service.mjs +217 -0
  80. package/dist/esm/services/gitlab.service.mjs.map +1 -0
  81. package/dist/esm/services/oAuth2.service.mjs +1 -1
  82. package/dist/esm/services/subscription.service.mjs +1 -1
  83. package/dist/esm/services/subscription.service.mjs.map +1 -1
  84. package/dist/esm/services/webhook.service.mjs +164 -0
  85. package/dist/esm/services/webhook.service.mjs.map +1 -0
  86. package/dist/esm/utils/auth/getAuth.mjs +28 -16
  87. package/dist/esm/utils/auth/getAuth.mjs.map +1 -1
  88. package/dist/esm/utils/cors.mjs +15 -5
  89. package/dist/esm/utils/cors.mjs.map +1 -1
  90. package/dist/esm/utils/errors/ErrorHandler.mjs +32 -4
  91. package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
  92. package/dist/esm/utils/errors/ErrorsClass.mjs +1 -1
  93. package/dist/esm/utils/errors/ErrorsClass.mjs.map +1 -1
  94. package/dist/esm/utils/errors/errorCodes.mjs +234 -0
  95. package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
  96. package/dist/esm/utils/filtersAndPagination/getDictionaryFiltersAndPagination.mjs +3 -2
  97. package/dist/esm/utils/filtersAndPagination/getDictionaryFiltersAndPagination.mjs.map +1 -1
  98. package/dist/esm/utils/filtersAndPagination/getDiscussionFiltersAndPagination.mjs +1 -1
  99. package/dist/esm/utils/filtersAndPagination/getDiscussionFiltersAndPagination.mjs.map +1 -1
  100. package/dist/esm/utils/filtersAndPagination/getFiltersAndPaginationFromBody.mjs +1 -1
  101. package/dist/esm/utils/filtersAndPagination/getFiltersAndPaginationFromBody.mjs.map +1 -1
  102. package/dist/esm/utils/filtersAndPagination/getOrganizationFiltersAndPagination.mjs +3 -2
  103. package/dist/esm/utils/filtersAndPagination/getOrganizationFiltersAndPagination.mjs.map +1 -1
  104. package/dist/esm/utils/filtersAndPagination/getProjectFiltersAndPagination.mjs +3 -2
  105. package/dist/esm/utils/filtersAndPagination/getProjectFiltersAndPagination.mjs.map +1 -1
  106. package/dist/esm/utils/filtersAndPagination/getTagFiltersAndPagination.mjs +3 -2
  107. package/dist/esm/utils/filtersAndPagination/getTagFiltersAndPagination.mjs.map +1 -1
  108. package/dist/esm/utils/filtersAndPagination/getUserFiltersAndPagination.mjs +3 -2
  109. package/dist/esm/utils/filtersAndPagination/getUserFiltersAndPagination.mjs.map +1 -1
  110. package/dist/esm/utils/mapper/project.mjs +28 -1
  111. package/dist/esm/utils/mapper/project.mjs.map +1 -1
  112. package/dist/esm/utils/mongoDB/connectDB.mjs +1 -1
  113. package/dist/esm/utils/rateLimiter.mjs +40 -30
  114. package/dist/esm/utils/rateLimiter.mjs.map +1 -1
  115. package/dist/esm/webhooks/stripe.webhook.mjs +2 -2
  116. package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -1
  117. package/dist/types/controllers/ai.controller.d.ts +29 -12
  118. package/dist/types/controllers/ai.controller.d.ts.map +1 -1
  119. package/dist/types/controllers/bitbucket.controller.d.ts +62 -0
  120. package/dist/types/controllers/bitbucket.controller.d.ts.map +1 -0
  121. package/dist/types/controllers/dictionary.controller.d.ts +23 -13
  122. package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
  123. package/dist/types/controllers/eventListener.controller.d.ts +4 -2
  124. package/dist/types/controllers/eventListener.controller.d.ts.map +1 -1
  125. package/dist/types/controllers/github.controller.d.ts +63 -0
  126. package/dist/types/controllers/github.controller.d.ts.map +1 -0
  127. package/dist/types/controllers/gitlab.controller.d.ts +67 -0
  128. package/dist/types/controllers/gitlab.controller.d.ts.map +1 -0
  129. package/dist/types/controllers/newsletter.controller.d.ts +8 -7
  130. package/dist/types/controllers/newsletter.controller.d.ts.map +1 -1
  131. package/dist/types/controllers/oAuth2.controller.d.ts +4 -2
  132. package/dist/types/controllers/oAuth2.controller.d.ts.map +1 -1
  133. package/dist/types/controllers/organization.controller.d.ts +28 -12
  134. package/dist/types/controllers/organization.controller.d.ts.map +1 -1
  135. package/dist/types/controllers/project.controller.d.ts +60 -17
  136. package/dist/types/controllers/project.controller.d.ts.map +1 -1
  137. package/dist/types/controllers/projectAccessKey.controller.d.ts +10 -5
  138. package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
  139. package/dist/types/controllers/search.controller.d.ts +4 -2
  140. package/dist/types/controllers/search.controller.d.ts.map +1 -1
  141. package/dist/types/controllers/stripe.controller.d.ts +11 -12
  142. package/dist/types/controllers/stripe.controller.d.ts.map +1 -1
  143. package/dist/types/controllers/tag.controller.d.ts +14 -9
  144. package/dist/types/controllers/tag.controller.d.ts.map +1 -1
  145. package/dist/types/controllers/user.controller.d.ts +22 -9
  146. package/dist/types/controllers/user.controller.d.ts.map +1 -1
  147. package/dist/types/emails/InviteUserEmail.d.ts +4 -4
  148. package/dist/types/emails/MagicLinkEmail.d.ts +4 -4
  149. package/dist/types/emails/OAuthTokenCreatedEmail.d.ts +4 -4
  150. package/dist/types/emails/OAuthTokenCreatedEmail.d.ts.map +1 -1
  151. package/dist/types/emails/PasswordChangeConfirmation.d.ts +4 -4
  152. package/dist/types/emails/ResetUserPassword.d.ts +4 -4
  153. package/dist/types/emails/ResetUserPassword.d.ts.map +1 -1
  154. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +4 -4
  155. package/dist/types/emails/SubscriptionPaymentError.d.ts +4 -4
  156. package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +4 -4
  157. package/dist/types/emails/ValidateUserEmail.d.ts +4 -4
  158. package/dist/types/emails/Welcome.d.ts +4 -4
  159. package/dist/types/export.d.ts +11 -5
  160. package/dist/types/middlewares/oAuth2.middleware.d.ts +9 -4
  161. package/dist/types/middlewares/oAuth2.middleware.d.ts.map +1 -1
  162. package/dist/types/middlewares/sessionAuth.middleware.d.ts +13 -3
  163. package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
  164. package/dist/types/models/discussion.model.d.ts +3 -3
  165. package/dist/types/models/oAuth2.model.d.ts +3 -3
  166. package/dist/types/routes/ai.routes.d.ts +2 -2
  167. package/dist/types/routes/ai.routes.d.ts.map +1 -1
  168. package/dist/types/routes/bitbucket.routes.d.ts +35 -0
  169. package/dist/types/routes/bitbucket.routes.d.ts.map +1 -0
  170. package/dist/types/routes/dictionary.routes.d.ts +2 -2
  171. package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
  172. package/dist/types/routes/eventListener.routes.d.ts +2 -2
  173. package/dist/types/routes/eventListener.routes.d.ts.map +1 -1
  174. package/dist/types/routes/github.routes.d.ts +35 -0
  175. package/dist/types/routes/github.routes.d.ts.map +1 -0
  176. package/dist/types/routes/gitlab.routes.d.ts +35 -0
  177. package/dist/types/routes/gitlab.routes.d.ts.map +1 -0
  178. package/dist/types/routes/newsletter.routes.d.ts +2 -2
  179. package/dist/types/routes/newsletter.routes.d.ts.map +1 -1
  180. package/dist/types/routes/organization.routes.d.ts +2 -2
  181. package/dist/types/routes/organization.routes.d.ts.map +1 -1
  182. package/dist/types/routes/project.routes.d.ts +22 -2
  183. package/dist/types/routes/project.routes.d.ts.map +1 -1
  184. package/dist/types/routes/search.routes.d.ts +2 -2
  185. package/dist/types/routes/search.routes.d.ts.map +1 -1
  186. package/dist/types/routes/stripe.routes.d.ts +2 -2
  187. package/dist/types/routes/stripe.routes.d.ts.map +1 -1
  188. package/dist/types/routes/tags.routes.d.ts +2 -2
  189. package/dist/types/routes/tags.routes.d.ts.map +1 -1
  190. package/dist/types/routes/user.routes.d.ts +2 -2
  191. package/dist/types/routes/user.routes.d.ts.map +1 -1
  192. package/dist/types/schemas/dictionary.schema.d.ts +6 -6
  193. package/dist/types/schemas/discussion.schema.d.ts +6 -6
  194. package/dist/types/schemas/oAuth2.schema.d.ts +5 -5
  195. package/dist/types/schemas/oAuth2.schema.d.ts.map +1 -1
  196. package/dist/types/schemas/plans.schema.d.ts +6 -6
  197. package/dist/types/schemas/project.schema.d.ts +6 -6
  198. package/dist/types/schemas/project.schema.d.ts.map +1 -1
  199. package/dist/types/schemas/session.schema.d.ts +6 -6
  200. package/dist/types/schemas/tag.schema.d.ts +6 -6
  201. package/dist/types/schemas/user.schema.d.ts +6 -6
  202. package/dist/types/schemas/user.schema.d.ts.map +1 -1
  203. package/dist/types/services/bitbucket.service.d.ts +71 -0
  204. package/dist/types/services/bitbucket.service.d.ts.map +1 -0
  205. package/dist/types/services/ci.service.d.ts +27 -0
  206. package/dist/types/services/ci.service.d.ts.map +1 -0
  207. package/dist/types/services/github.service.d.ts +40 -0
  208. package/dist/types/services/github.service.d.ts.map +1 -0
  209. package/dist/types/services/gitlab.service.d.ts +58 -0
  210. package/dist/types/services/gitlab.service.d.ts.map +1 -0
  211. package/dist/types/services/webhook.service.d.ts +19 -0
  212. package/dist/types/services/webhook.service.d.ts.map +1 -0
  213. package/dist/types/types/project.types.d.ts +46 -5
  214. package/dist/types/types/project.types.d.ts.map +1 -1
  215. package/dist/types/types/session.types.d.ts +1 -1
  216. package/dist/types/types/user.types.d.ts +1 -1
  217. package/dist/types/utils/AI/auditTag/index.d.ts +1 -1
  218. package/dist/types/utils/auth/getAuth.d.ts.map +1 -1
  219. package/dist/types/utils/cors.d.ts +2 -2
  220. package/dist/types/utils/errors/ErrorHandler.d.ts +31 -3
  221. package/dist/types/utils/errors/ErrorHandler.d.ts.map +1 -1
  222. package/dist/types/utils/errors/ErrorsClass.d.ts +1 -1
  223. package/dist/types/utils/errors/errorCodes.d.ts +234 -0
  224. package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
  225. package/dist/types/utils/filtersAndPagination/getDictionaryFiltersAndPagination.d.ts +8 -4
  226. package/dist/types/utils/filtersAndPagination/getDictionaryFiltersAndPagination.d.ts.map +1 -1
  227. package/dist/types/utils/filtersAndPagination/getDiscussionFiltersAndPagination.d.ts +6 -3
  228. package/dist/types/utils/filtersAndPagination/getDiscussionFiltersAndPagination.d.ts.map +1 -1
  229. package/dist/types/utils/filtersAndPagination/getFiltersAndPaginationFromBody.d.ts +6 -2
  230. package/dist/types/utils/filtersAndPagination/getFiltersAndPaginationFromBody.d.ts.map +1 -1
  231. package/dist/types/utils/filtersAndPagination/getOrganizationFiltersAndPagination.d.ts +8 -4
  232. package/dist/types/utils/filtersAndPagination/getOrganizationFiltersAndPagination.d.ts.map +1 -1
  233. package/dist/types/utils/filtersAndPagination/getProjectFiltersAndPagination.d.ts +6 -2
  234. package/dist/types/utils/filtersAndPagination/getProjectFiltersAndPagination.d.ts.map +1 -1
  235. package/dist/types/utils/filtersAndPagination/getTagFiltersAndPagination.d.ts +8 -4
  236. package/dist/types/utils/filtersAndPagination/getTagFiltersAndPagination.d.ts.map +1 -1
  237. package/dist/types/utils/filtersAndPagination/getUserFiltersAndPagination.d.ts +6 -2
  238. package/dist/types/utils/filtersAndPagination/getUserFiltersAndPagination.d.ts.map +1 -1
  239. package/dist/types/utils/mapper/project.d.ts.map +1 -1
  240. package/dist/types/utils/permissions.d.ts +1 -1
  241. package/dist/types/utils/rateLimiter.d.ts +4 -2
  242. package/dist/types/utils/rateLimiter.d.ts.map +1 -1
  243. package/package.json +24 -28
  244. package/dist/esm/middlewares/request.middleware.mjs +0 -17
  245. package/dist/esm/middlewares/request.middleware.mjs.map +0 -1
  246. package/dist/types/middlewares/request.middleware.d.ts +0 -7
  247. package/dist/types/middlewares/request.middleware.d.ts.map +0 -1
@@ -13,36 +13,30 @@ const sendDictionaryUpdate = (args) => {
13
13
  data: arg.dictionary
14
14
  }));
15
15
  process.nextTick(() => {
16
- for (const client of filteredClients) {
17
- client.res.write(`data: ${JSON.stringify(data)}\n\n`);
18
- client.res.flush?.();
19
- }
16
+ for (const client of filteredClients) client.res.raw.write(`data: ${JSON.stringify(data)}\n\n`);
20
17
  });
21
18
  };
22
19
  /**
23
20
  * SSE to check the email verification status
24
21
  */
25
- const listenChangeSSE = async (req, res) => {
26
- const { project } = res.locals;
27
- if (clients.length >= MAX_SSE_CONNECTIONS) {
28
- ErrorHandler.handleGenericErrorResponse(res, "TOO_MANY_CONNECTIONS");
29
- return;
30
- }
31
- res.setHeader("Content-Type", "text/event-stream;charset=utf-8");
32
- res.setHeader("Cache-Control", "no-cache, no-transform");
33
- res.setHeader("Connection", "keep-alive");
34
- res.setHeader("X-Accel-Buffering", "no");
35
- res.write(":\n\n");
36
- res.flushHeaders?.();
22
+ const listenChangeSSE = async (request, reply) => {
23
+ const { project } = request.locals || {};
24
+ if (clients.length >= MAX_SSE_CONNECTIONS) return ErrorHandler.handleGenericErrorResponse(reply, "TOO_MANY_CONNECTIONS");
25
+ reply.raw.setHeader("Content-Type", "text/event-stream;charset=utf-8");
26
+ reply.raw.setHeader("Cache-Control", "no-cache, no-transform");
27
+ reply.raw.setHeader("Connection", "keep-alive");
28
+ reply.raw.setHeader("X-Accel-Buffering", "no");
29
+ reply.raw.write(":\n\n");
30
+ reply.raw.flushHeaders?.();
37
31
  const clientId = Date.now();
38
32
  const newClient = {
39
33
  id: clientId,
40
- projectId: String(project.id),
41
- res
34
+ projectId: String(project?.id),
35
+ res: { raw: reply.raw }
42
36
  };
43
37
  clients.push(newClient);
44
38
  logger.info(`New client connected to SSE. Total clients: ${clients.length ?? 0}`);
45
- req.on("close", () => {
39
+ request.raw.on("close", () => {
46
40
  clients = clients.filter((client) => client.id !== clientId);
47
41
  });
48
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"eventListener.controller.mjs","names":["clients: Array<{ id: number; projectId: string; res: Response }>","data: MessageEventData[]"],"sources":["../../../src/controllers/eventListener.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport { ErrorHandler } from '@utils/errors';\nimport type { Request, Response } from 'express';\nimport type { DictionaryAPI } from '@/types/dictionary.types';\n\nexport type Object = 'DICTIONARY';\nexport type Status = 'ADDED' | 'UPDATED' | 'DELETED' | 'CREATED';\n\nexport type MessageEventData = {\n object: Object;\n status: Status;\n data: any;\n};\n\nlet clients: Array<{ id: number; projectId: string; res: Response }> = [];\nconst MAX_SSE_CONNECTIONS = 10;\n\nexport type SendDictionaryUpdateArg = {\n dictionary: DictionaryAPI;\n status: 'ADDED' | 'UPDATED' | 'DELETED' | 'CREATED';\n};\n\nexport const sendDictionaryUpdate = (args: SendDictionaryUpdateArg[]) => {\n const projectIds = args.flatMap((arg) => arg.dictionary.projectIds);\n\n const filteredClients = clients.filter((client) =>\n projectIds.map((id) => String(id)).includes(String(client.projectId))\n );\n\n const data: MessageEventData[] = args.map((arg) => ({\n object: 'DICTIONARY',\n status: arg.status,\n data: arg.dictionary,\n }));\n\n process.nextTick(() => {\n for (const client of filteredClients) {\n client.res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n client.res.flush?.(); // Ensure the data is sent immediately\n }\n });\n};\n\nexport type CheckDictionaryChangeSSEParams = { accessToken: string };\n\n/**\n * SSE to check the email verification status\n */\nexport const listenChangeSSE = async (\n req: Request<CheckDictionaryChangeSSEParams, any, any>,\n res: Response\n) => {\n const { project } = res.locals;\n\n if (clients.length >= MAX_SSE_CONNECTIONS) {\n ErrorHandler.handleGenericErrorResponse(res, 'TOO_MANY_CONNECTIONS');\n return;\n }\n\n // Set headers for SSE\n res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no'); // For Nginx buffering\n\n // Send initial data to ensure the connection is open\n res.write(':\\n\\n'); // Comment to keep connection alive\n res.flushHeaders?.();\n\n const clientId = Date.now();\n\n // Add client to the list\n const newClient = {\n id: clientId,\n projectId: String(project.id),\n res,\n };\n clients.push(newClient);\n\n logger.info(\n `New client connected to SSE. Total clients: ${clients.length ?? 0}`\n );\n\n // Remove client on connection close\n req.on('close', () => {\n clients = clients.filter((client) => client.id !== clientId);\n });\n};\n"],"mappings":";;;;AAcA,IAAIA,UAAmE,EAAE;AACzE,MAAM,sBAAsB;AAO5B,MAAa,wBAAwB,SAAoC;CACvE,MAAM,aAAa,KAAK,SAAS,QAAQ,IAAI,WAAW,WAAW;CAEnE,MAAM,kBAAkB,QAAQ,QAAQ,WACtC,WAAW,KAAK,OAAO,OAAO,GAAG,CAAC,CAAC,SAAS,OAAO,OAAO,UAAU,CAAC,CACtE;CAED,MAAMC,OAA2B,KAAK,KAAK,SAAS;EAClD,QAAQ;EACR,QAAQ,IAAI;EACZ,MAAM,IAAI;EACX,EAAE;AAEH,SAAQ,eAAe;AACrB,OAAK,MAAM,UAAU,iBAAiB;AACpC,UAAO,IAAI,MAAM,SAAS,KAAK,UAAU,KAAK,CAAC,MAAM;AACrD,UAAO,IAAI,SAAS;;GAEtB;;;;;AAQJ,MAAa,kBAAkB,OAC7B,KACA,QACG;CACH,MAAM,EAAE,YAAY,IAAI;AAExB,KAAI,QAAQ,UAAU,qBAAqB;AACzC,eAAa,2BAA2B,KAAK,uBAAuB;AACpE;;AAIF,KAAI,UAAU,gBAAgB,kCAAkC;AAChE,KAAI,UAAU,iBAAiB,yBAAyB;AACxD,KAAI,UAAU,cAAc,aAAa;AACzC,KAAI,UAAU,qBAAqB,KAAK;AAGxC,KAAI,MAAM,QAAQ;AAClB,KAAI,gBAAgB;CAEpB,MAAM,WAAW,KAAK,KAAK;CAG3B,MAAM,YAAY;EAChB,IAAI;EACJ,WAAW,OAAO,QAAQ,GAAG;EAC7B;EACD;AACD,SAAQ,KAAK,UAAU;AAEvB,QAAO,KACL,+CAA+C,QAAQ,UAAU,IAClE;AAGD,KAAI,GAAG,eAAe;AACpB,YAAU,QAAQ,QAAQ,WAAW,OAAO,OAAO,SAAS;GAC5D"}
1
+ {"version":3,"file":"eventListener.controller.mjs","names":["clients: Array<{\n id: number;\n projectId: string;\n res: { raw: FastifyReply['raw'] };\n}>","data: MessageEventData[]"],"sources":["../../../src/controllers/eventListener.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport { ErrorHandler } from '@utils/errors';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport type { DictionaryAPI } from '@/types/dictionary.types';\n\nexport type Object = 'DICTIONARY';\nexport type Status = 'ADDED' | 'UPDATED' | 'DELETED' | 'CREATED';\n\nexport type MessageEventData = {\n object: Object;\n status: Status;\n data: any;\n};\n\nlet clients: Array<{\n id: number;\n projectId: string;\n res: { raw: FastifyReply['raw'] };\n}> = [];\nconst MAX_SSE_CONNECTIONS = 10;\n\nexport type SendDictionaryUpdateArg = {\n dictionary: DictionaryAPI;\n status: 'ADDED' | 'UPDATED' | 'DELETED' | 'CREATED';\n};\n\nexport const sendDictionaryUpdate = (args: SendDictionaryUpdateArg[]) => {\n const projectIds = args.flatMap((arg) => arg.dictionary.projectIds);\n\n const filteredClients = clients.filter((client) =>\n projectIds.map((id) => String(id)).includes(String(client.projectId))\n );\n\n const data: MessageEventData[] = args.map((arg) => ({\n object: 'DICTIONARY',\n status: arg.status,\n data: arg.dictionary,\n }));\n\n process.nextTick(() => {\n for (const client of filteredClients) {\n client.res.raw.write(`data: ${JSON.stringify(data)}\\n\\n`);\n }\n });\n};\n\nexport type CheckDictionaryChangeSSEParams = { accessToken: string };\n\n/**\n * SSE to check the email verification status\n */\nexport const listenChangeSSE = async (\n request: FastifyRequest<{ Params: CheckDictionaryChangeSSEParams }>,\n reply: FastifyReply\n) => {\n const { project } = request.locals || {};\n\n if (clients.length >= MAX_SSE_CONNECTIONS) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'TOO_MANY_CONNECTIONS'\n );\n }\n\n // Set headers for SSE\n reply.raw.setHeader('Content-Type', 'text/event-stream;charset=utf-8');\n reply.raw.setHeader('Cache-Control', 'no-cache, no-transform');\n reply.raw.setHeader('Connection', 'keep-alive');\n reply.raw.setHeader('X-Accel-Buffering', 'no'); // For Nginx buffering\n\n // Send initial data to ensure the connection is open\n reply.raw.write(':\\n\\n'); // Comment to keep connection alive\n reply.raw.flushHeaders?.();\n\n const clientId = Date.now();\n\n // Add client to the list\n const newClient = {\n id: clientId,\n projectId: String(project?.id),\n res: { raw: reply.raw },\n };\n clients.push(newClient);\n\n logger.info(\n `New client connected to SSE. Total clients: ${clients.length ?? 0}`\n );\n\n // Remove client on connection close\n request.raw.on('close', () => {\n clients = clients.filter((client) => client.id !== clientId);\n });\n};\n"],"mappings":";;;;AAcA,IAAIA,UAIC,EAAE;AACP,MAAM,sBAAsB;AAO5B,MAAa,wBAAwB,SAAoC;CACvE,MAAM,aAAa,KAAK,SAAS,QAAQ,IAAI,WAAW,WAAW;CAEnE,MAAM,kBAAkB,QAAQ,QAAQ,WACtC,WAAW,KAAK,OAAO,OAAO,GAAG,CAAC,CAAC,SAAS,OAAO,OAAO,UAAU,CAAC,CACtE;CAED,MAAMC,OAA2B,KAAK,KAAK,SAAS;EAClD,QAAQ;EACR,QAAQ,IAAI;EACZ,MAAM,IAAI;EACX,EAAE;AAEH,SAAQ,eAAe;AACrB,OAAK,MAAM,UAAU,gBACnB,QAAO,IAAI,IAAI,MAAM,SAAS,KAAK,UAAU,KAAK,CAAC,MAAM;GAE3D;;;;;AAQJ,MAAa,kBAAkB,OAC7B,SACA,UACG;CACH,MAAM,EAAE,YAAY,QAAQ,UAAU,EAAE;AAExC,KAAI,QAAQ,UAAU,oBACpB,QAAO,aAAa,2BAClB,OACA,uBACD;AAIH,OAAM,IAAI,UAAU,gBAAgB,kCAAkC;AACtE,OAAM,IAAI,UAAU,iBAAiB,yBAAyB;AAC9D,OAAM,IAAI,UAAU,cAAc,aAAa;AAC/C,OAAM,IAAI,UAAU,qBAAqB,KAAK;AAG9C,OAAM,IAAI,MAAM,QAAQ;AACxB,OAAM,IAAI,gBAAgB;CAE1B,MAAM,WAAW,KAAK,KAAK;CAG3B,MAAM,YAAY;EAChB,IAAI;EACJ,WAAW,OAAO,SAAS,GAAG;EAC9B,KAAK,EAAE,KAAK,MAAM,KAAK;EACxB;AACD,SAAQ,KAAK,UAAU;AAEvB,QAAO,KACL,+CAA+C,QAAQ,UAAU,IAClE;AAGD,SAAQ,IAAI,GAAG,eAAe;AAC5B,YAAU,QAAQ,QAAQ,WAAW,OAAO,OAAO,SAAS;GAC5D"}
@@ -0,0 +1,77 @@
1
+ import { formatResponse } from "../utils/responseData.mjs";
2
+ import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
3
+ import { checkIntlayerConfig, exchangeCodeForToken, getAuthorizationUrl, getGitHubTokenFromUser, getRepositoryFileContents, getUserRepos } from "../services/github.service.mjs";
4
+
5
+ //#region src/controllers/github.controller.ts
6
+ const getAuthUrl = async (request, reply) => {
7
+ const { redirectUri, login } = request.query;
8
+ if (!redirectUri) return ErrorHandler.handleGenericErrorResponse(reply, "GITHUB_REDIRECT_URI_MISSING");
9
+ try {
10
+ const responseData = formatResponse({ data: { authUrl: getAuthorizationUrl(redirectUri, login) } });
11
+ return reply.send(responseData);
12
+ } catch (error) {
13
+ return ErrorHandler.handleAppErrorResponse(reply, error);
14
+ }
15
+ };
16
+ const authCallback = async (request, reply) => {
17
+ const { code } = request.body;
18
+ if (!code) return ErrorHandler.handleGenericErrorResponse(reply, "GITHUB_CODE_MISSING");
19
+ try {
20
+ const responseData = formatResponse({ data: { token: await exchangeCodeForToken(code) } });
21
+ return reply.send(responseData);
22
+ } catch (error) {
23
+ return ErrorHandler.handleAppErrorResponse(reply, error);
24
+ }
25
+ };
26
+ const listRepos = async (request, reply) => {
27
+ const { token } = request.query;
28
+ const userId = request.locals?.user?.id;
29
+ try {
30
+ let accessToken = token;
31
+ if (!accessToken && userId) accessToken = await getGitHubTokenFromUser(String(userId)) ?? void 0;
32
+ if (!accessToken) return ErrorHandler.handleGenericErrorResponse(reply, "GITHUB_TOKEN_MISSING");
33
+ const responseData = formatResponse({ data: await getUserRepos(accessToken) });
34
+ return reply.send(responseData);
35
+ } catch (error) {
36
+ return ErrorHandler.handleAppErrorResponse(reply, error);
37
+ }
38
+ };
39
+ /**
40
+ * Check if intlayer.config.ts (or candidates) exists in a repository
41
+ */
42
+ const checkConfig = async (request, reply) => {
43
+ const { token, owner, repository, branch = "main" } = request.body;
44
+ const userId = request.locals?.user?.id;
45
+ try {
46
+ let accessToken = token;
47
+ if (!accessToken && userId) accessToken = await getGitHubTokenFromUser(String(userId)) ?? void 0;
48
+ if (!accessToken || !owner || !repository) return ErrorHandler.handleGenericErrorResponse(reply, "GITHUB_CHECK_CONFIG_MISSING_PARAMS");
49
+ const configPaths = await checkIntlayerConfig(accessToken, owner, repository, branch);
50
+ const responseData = formatResponse({ data: {
51
+ hasConfig: configPaths.length > 0,
52
+ configPaths
53
+ } });
54
+ return reply.send(responseData);
55
+ } catch (error) {
56
+ return ErrorHandler.handleAppErrorResponse(reply, error);
57
+ }
58
+ };
59
+ const getConfigFile = async (request, reply) => {
60
+ const { token, owner, repository, branch = "main", path = "intlayer.config.ts" } = request.body;
61
+ const userId = request.locals?.user?.id;
62
+ try {
63
+ let accessToken = token;
64
+ if (!accessToken && userId) accessToken = await getGitHubTokenFromUser(String(userId)) ?? void 0;
65
+ if (!accessToken || !owner || !repository) return ErrorHandler.handleGenericErrorResponse(reply, "GITHUB_GET_CONFIG_FILE_MISSING_PARAMS");
66
+ const content = await getRepositoryFileContents(accessToken, owner, repository, path, branch);
67
+ if (!content) return ErrorHandler.handleGenericErrorResponse(reply, "GITHUB_CONFIG_FILE_NOT_FOUND");
68
+ const responseData = formatResponse({ data: { content } });
69
+ return reply.send(responseData);
70
+ } catch (error) {
71
+ return ErrorHandler.handleAppErrorResponse(reply, error);
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ export { authCallback, checkConfig, getAuthUrl, getConfigFile, listRepos };
77
+ //# sourceMappingURL=github.controller.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.controller.mjs","names":["githubService.getAuthorizationUrl","githubService.exchangeCodeForToken","accessToken: string | undefined","githubService.getUserRepos","githubService.checkIntlayerConfig","githubService.getRepositoryFileContents"],"sources":["../../../src/controllers/github.controller.ts"],"sourcesContent":["import * as githubService from '@services/github.service';\nimport { getGitHubTokenFromUser } from '@services/github.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\n\nexport type GitHubGetAuthUrlQuerystring = {\n redirectUri: string;\n login?: string;\n};\n\nexport type GitHubGetAuthUrlResult = ResponseData<{\n authUrl: string;\n}>;\n\nexport const getAuthUrl = async (\n request: FastifyRequest<{ Querystring: GitHubGetAuthUrlQuerystring }>,\n reply: FastifyReply\n): Promise<void> => {\n const { redirectUri, login } = request.query;\n\n if (!redirectUri) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITHUB_REDIRECT_URI_MISSING'\n );\n }\n\n try {\n const authUrl = githubService.getAuthorizationUrl(redirectUri, login);\n const responseData = formatResponse<{ authUrl: string }>({\n data: { authUrl },\n });\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitHubAuthCallbackBody = {\n code: string;\n};\n\nexport type GitHubAuthCallbackResult = ResponseData<{\n token: string;\n}>;\n\nexport const authCallback = async (\n request: FastifyRequest<{ Body: GitHubAuthCallbackBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const { code } = request.body;\n\n if (!code) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITHUB_CODE_MISSING'\n );\n }\n\n try {\n const token = await githubService.exchangeCodeForToken(code);\n const responseData = formatResponse<{ token: string }>({\n data: { token },\n });\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitHubListReposQuerystring = {\n token?: string;\n};\n\nexport type GitHubListReposResult = ResponseData<\n githubService.GitHubRepository[]\n>;\n\nexport const listRepos = async (\n request: FastifyRequest<{ Querystring: GitHubListReposQuerystring }>,\n reply: FastifyReply\n): Promise<void> => {\n const { token } = request.query;\n const userId = request.locals?.user?.id;\n\n try {\n let accessToken: string | undefined = token;\n\n if (!accessToken && userId) {\n accessToken = (await getGitHubTokenFromUser(String(userId))) ?? undefined;\n }\n\n if (!accessToken) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITHUB_TOKEN_MISSING'\n );\n }\n\n const repos = await githubService.getUserRepos(accessToken);\n const responseData = formatResponse<githubService.GitHubRepository[]>({\n data: repos,\n });\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitHubCheckConfigBody = {\n token?: string;\n owner: string;\n repository: string;\n branch?: string;\n};\n\nexport type GitHubCheckConfigResult = ResponseData<{\n hasConfig: boolean;\n configPaths: string[]; // Changed from single path to array\n}>;\n\n/**\n * Check if intlayer.config.ts (or candidates) exists in a repository\n */\nexport const checkConfig = async (\n request: FastifyRequest<{ Body: GitHubCheckConfigBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const { token, owner, repository, branch = 'main' } = request.body;\n const userId = request.locals?.user?.id;\n\n try {\n let accessToken: string | undefined = token;\n\n if (!accessToken && userId) {\n accessToken = (await getGitHubTokenFromUser(String(userId))) ?? undefined;\n }\n\n if (!accessToken || !owner || !repository) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITHUB_CHECK_CONFIG_MISSING_PARAMS'\n );\n }\n\n // Returns array of strings\n const configPaths = await githubService.checkIntlayerConfig(\n accessToken,\n owner,\n repository,\n branch\n );\n\n const responseData = formatResponse<{\n hasConfig: boolean;\n configPaths: string[];\n }>({\n data: {\n hasConfig: configPaths.length > 0,\n configPaths: configPaths,\n },\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitHubGetConfigFileBody = {\n token?: string;\n owner: string;\n repository: string;\n branch?: string;\n path?: string;\n};\n\nexport type GitHubGetConfigFileResult = ResponseData<{\n content: string;\n}>;\n\nexport const getConfigFile = async (\n request: FastifyRequest<{ Body: GitHubGetConfigFileBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const {\n token,\n owner,\n repository,\n branch = 'main',\n path = 'intlayer.config.ts',\n } = request.body;\n const userId = request.locals?.user?.id;\n\n try {\n let accessToken: string | undefined = token;\n\n if (!accessToken && userId) {\n accessToken = (await getGitHubTokenFromUser(String(userId))) ?? undefined;\n }\n\n if (!accessToken || !owner || !repository) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITHUB_GET_CONFIG_FILE_MISSING_PARAMS'\n );\n }\n\n const content = await githubService.getRepositoryFileContents(\n accessToken,\n owner,\n repository,\n path,\n branch\n );\n\n if (!content) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITHUB_CONFIG_FILE_NOT_FOUND'\n );\n }\n\n const responseData = formatResponse<{ content: string }>({\n data: { content },\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n"],"mappings":";;;;;AAeA,MAAa,aAAa,OACxB,SACA,UACkB;CAClB,MAAM,EAAE,aAAa,UAAU,QAAQ;AAEvC,KAAI,CAAC,YACH,QAAO,aAAa,2BAClB,OACA,8BACD;AAGH,KAAI;EAEF,MAAM,eAAe,eAAoC,EACvD,MAAM,EAAE,SAFMA,oBAAkC,aAAa,MAAM,EAElD,EAClB,CAAC;AACF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;AAYxE,MAAa,eAAe,OAC1B,SACA,UACkB;CAClB,MAAM,EAAE,SAAS,QAAQ;AAEzB,KAAI,CAAC,KACH,QAAO,aAAa,2BAClB,OACA,sBACD;AAGH,KAAI;EAEF,MAAM,eAAe,eAAkC,EACrD,MAAM,EAAE,OAFI,MAAMC,qBAAmC,KAAK,EAE3C,EAChB,CAAC;AACF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;AAYxE,MAAa,YAAY,OACvB,SACA,UACkB;CAClB,MAAM,EAAE,UAAU,QAAQ;CAC1B,MAAM,SAAS,QAAQ,QAAQ,MAAM;AAErC,KAAI;EACF,IAAIC,cAAkC;AAEtC,MAAI,CAAC,eAAe,OAClB,eAAe,MAAM,uBAAuB,OAAO,OAAO,CAAC,IAAK;AAGlE,MAAI,CAAC,YACH,QAAO,aAAa,2BAClB,OACA,uBACD;EAIH,MAAM,eAAe,eAAiD,EACpE,MAFY,MAAMC,aAA2B,YAAY,EAG1D,CAAC;AACF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;;;;AAmBxE,MAAa,cAAc,OACzB,SACA,UACkB;CAClB,MAAM,EAAE,OAAO,OAAO,YAAY,SAAS,WAAW,QAAQ;CAC9D,MAAM,SAAS,QAAQ,QAAQ,MAAM;AAErC,KAAI;EACF,IAAID,cAAkC;AAEtC,MAAI,CAAC,eAAe,OAClB,eAAe,MAAM,uBAAuB,OAAO,OAAO,CAAC,IAAK;AAGlE,MAAI,CAAC,eAAe,CAAC,SAAS,CAAC,WAC7B,QAAO,aAAa,2BAClB,OACA,qCACD;EAIH,MAAM,cAAc,MAAME,oBACxB,aACA,OACA,YACA,OACD;EAED,MAAM,eAAe,eAGlB,EACD,MAAM;GACJ,WAAW,YAAY,SAAS;GACnB;GACd,EACF,CAAC;AAEF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;AAgBxE,MAAa,gBAAgB,OAC3B,SACA,UACkB;CAClB,MAAM,EACJ,OACA,OACA,YACA,SAAS,QACT,OAAO,yBACL,QAAQ;CACZ,MAAM,SAAS,QAAQ,QAAQ,MAAM;AAErC,KAAI;EACF,IAAIF,cAAkC;AAEtC,MAAI,CAAC,eAAe,OAClB,eAAe,MAAM,uBAAuB,OAAO,OAAO,CAAC,IAAK;AAGlE,MAAI,CAAC,eAAe,CAAC,SAAS,CAAC,WAC7B,QAAO,aAAa,2BAClB,OACA,wCACD;EAGH,MAAM,UAAU,MAAMG,0BACpB,aACA,OACA,YACA,MACA,OACD;AAED,MAAI,CAAC,QACH,QAAO,aAAa,2BAClB,OACA,+BACD;EAGH,MAAM,eAAe,eAAoC,EACvD,MAAM,EAAE,SAAS,EAClB,CAAC;AAEF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB"}
@@ -0,0 +1,77 @@
1
+ import { formatResponse } from "../utils/responseData.mjs";
2
+ import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
3
+ import { checkIntlayerConfig, exchangeCodeForToken, getAuthorizationUrl, getGitLabTokenFromUser, getRepositoryFileContents, getUserProjects } from "../services/gitlab.service.mjs";
4
+
5
+ //#region src/controllers/gitlab.controller.ts
6
+ const getAuthUrl = async (request, reply) => {
7
+ const { redirectUri, instanceUrl, login } = request.query;
8
+ if (!redirectUri) return ErrorHandler.handleGenericErrorResponse(reply, "GITLAB_REDIRECT_URI_MISSING");
9
+ try {
10
+ const responseData = formatResponse({ data: { authUrl: getAuthorizationUrl(redirectUri, instanceUrl, login) } });
11
+ return reply.send(responseData);
12
+ } catch (error) {
13
+ return ErrorHandler.handleAppErrorResponse(reply, error);
14
+ }
15
+ };
16
+ const authCallback = async (request, reply) => {
17
+ const { code, redirectUri, instanceUrl } = request.body;
18
+ if (!code || !redirectUri) return ErrorHandler.handleGenericErrorResponse(reply, "GITLAB_CODE_MISSING");
19
+ try {
20
+ const responseData = formatResponse({ data: { token: await exchangeCodeForToken(code, redirectUri, instanceUrl) } });
21
+ return reply.send(responseData);
22
+ } catch (error) {
23
+ return ErrorHandler.handleAppErrorResponse(reply, error);
24
+ }
25
+ };
26
+ const listProjects = async (request, reply) => {
27
+ const { token, instanceUrl } = request.query;
28
+ const userId = request.locals?.user?.id;
29
+ try {
30
+ let accessToken = token;
31
+ if (!accessToken && userId) accessToken = await getGitLabTokenFromUser(String(userId)) ?? void 0;
32
+ if (!accessToken) return ErrorHandler.handleGenericErrorResponse(reply, "GITLAB_TOKEN_MISSING");
33
+ const responseData = formatResponse({ data: await getUserProjects(accessToken, instanceUrl) });
34
+ return reply.send(responseData);
35
+ } catch (error) {
36
+ return ErrorHandler.handleAppErrorResponse(reply, error);
37
+ }
38
+ };
39
+ /**
40
+ * Check if intlayer.config.ts (or candidates) exists in a GitLab repository
41
+ */
42
+ const checkConfig = async (request, reply) => {
43
+ const { token, projectId, branch = "main", instanceUrl } = request.body;
44
+ const userId = request.locals?.user?.id;
45
+ try {
46
+ let accessToken = token;
47
+ if (!accessToken && userId) accessToken = await getGitLabTokenFromUser(String(userId)) ?? void 0;
48
+ if (!accessToken || !projectId) return ErrorHandler.handleGenericErrorResponse(reply, "GITLAB_CHECK_CONFIG_MISSING_PARAMS");
49
+ const configPaths = await checkIntlayerConfig(accessToken, projectId, branch, instanceUrl);
50
+ const responseData = formatResponse({ data: {
51
+ hasConfig: configPaths.length > 0,
52
+ configPaths
53
+ } });
54
+ return reply.send(responseData);
55
+ } catch (error) {
56
+ return ErrorHandler.handleAppErrorResponse(reply, error);
57
+ }
58
+ };
59
+ const getConfigFile = async (request, reply) => {
60
+ const { token, projectId, branch = "main", path = "intlayer.config.ts", instanceUrl } = request.body;
61
+ const userId = request.locals?.user?.id;
62
+ try {
63
+ let accessToken = token;
64
+ if (!accessToken && userId) accessToken = await getGitLabTokenFromUser(String(userId)) ?? void 0;
65
+ if (!accessToken || !projectId) return ErrorHandler.handleGenericErrorResponse(reply, "GITLAB_GET_CONFIG_FILE_MISSING_PARAMS");
66
+ const content = await getRepositoryFileContents(accessToken, projectId, path, branch, instanceUrl);
67
+ if (!content) return ErrorHandler.handleGenericErrorResponse(reply, "GITLAB_CONFIG_FILE_NOT_FOUND");
68
+ const responseData = formatResponse({ data: { content } });
69
+ return reply.send(responseData);
70
+ } catch (error) {
71
+ return ErrorHandler.handleAppErrorResponse(reply, error);
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ export { authCallback, checkConfig, getAuthUrl, getConfigFile, listProjects };
77
+ //# sourceMappingURL=gitlab.controller.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab.controller.mjs","names":["gitlabService.getAuthorizationUrl","gitlabService.exchangeCodeForToken","accessToken: string | undefined","gitlabService.getUserProjects","gitlabService.checkIntlayerConfig","gitlabService.getRepositoryFileContents"],"sources":["../../../src/controllers/gitlab.controller.ts"],"sourcesContent":["import * as gitlabService from '@services/gitlab.service';\nimport { getGitLabTokenFromUser } from '@services/gitlab.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\n\nexport type GitLabGetAuthUrlQuerystring = {\n redirectUri: string;\n instanceUrl?: string;\n login?: string;\n};\n\nexport type GitLabGetAuthUrlResult = ResponseData<{\n authUrl: string;\n}>;\n\nexport const getAuthUrl = async (\n request: FastifyRequest<{ Querystring: GitLabGetAuthUrlQuerystring }>,\n reply: FastifyReply\n): Promise<void> => {\n const { redirectUri, instanceUrl, login } = request.query;\n\n if (!redirectUri) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITLAB_REDIRECT_URI_MISSING'\n );\n }\n\n try {\n const authUrl = gitlabService.getAuthorizationUrl(\n redirectUri,\n instanceUrl,\n login\n );\n const responseData = formatResponse<{ authUrl: string }>({\n data: { authUrl },\n });\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitLabAuthCallbackBody = {\n code: string;\n redirectUri: string;\n instanceUrl?: string;\n};\n\nexport type GitLabAuthCallbackResult = ResponseData<{\n token: string;\n}>;\n\nexport const authCallback = async (\n request: FastifyRequest<{ Body: GitLabAuthCallbackBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const { code, redirectUri, instanceUrl } = request.body;\n\n if (!code || !redirectUri) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITLAB_CODE_MISSING'\n );\n }\n\n try {\n const token = await gitlabService.exchangeCodeForToken(\n code,\n redirectUri,\n instanceUrl\n );\n const responseData = formatResponse<{ token: string }>({\n data: { token },\n });\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitLabListProjectsQuerystring = {\n token?: string;\n instanceUrl?: string;\n};\n\nexport type GitLabListProjectsResult = ResponseData<\n gitlabService.GitLabProject[]\n>;\n\nexport const listProjects = async (\n request: FastifyRequest<{ Querystring: GitLabListProjectsQuerystring }>,\n reply: FastifyReply\n): Promise<void> => {\n const { token, instanceUrl } = request.query;\n const userId = request.locals?.user?.id;\n\n try {\n let accessToken: string | undefined = token;\n\n if (!accessToken && userId) {\n accessToken = (await getGitLabTokenFromUser(String(userId))) ?? undefined;\n }\n\n if (!accessToken) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITLAB_TOKEN_MISSING'\n );\n }\n\n const projects = await gitlabService.getUserProjects(\n accessToken,\n instanceUrl\n );\n const responseData = formatResponse<gitlabService.GitLabProject[]>({\n data: projects,\n });\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitLabCheckConfigBody = {\n token?: string;\n projectId: number;\n branch?: string;\n instanceUrl?: string;\n};\n\nexport type GitLabCheckConfigResult = ResponseData<{\n hasConfig: boolean;\n configPaths: string[];\n}>;\n\n/**\n * Check if intlayer.config.ts (or candidates) exists in a GitLab repository\n */\nexport const checkConfig = async (\n request: FastifyRequest<{ Body: GitLabCheckConfigBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const { token, projectId, branch = 'main', instanceUrl } = request.body;\n const userId = request.locals?.user?.id;\n\n try {\n let accessToken: string | undefined = token;\n\n if (!accessToken && userId) {\n accessToken = (await getGitLabTokenFromUser(String(userId))) ?? undefined;\n }\n\n if (!accessToken || !projectId) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITLAB_CHECK_CONFIG_MISSING_PARAMS'\n );\n }\n\n const configPaths = await gitlabService.checkIntlayerConfig(\n accessToken,\n projectId,\n branch,\n instanceUrl\n );\n\n const responseData = formatResponse<{\n hasConfig: boolean;\n configPaths: string[];\n }>({\n data: {\n hasConfig: configPaths.length > 0,\n configPaths: configPaths,\n },\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type GitLabGetConfigFileBody = {\n token?: string;\n projectId: number;\n branch?: string;\n path?: string;\n instanceUrl?: string;\n};\n\nexport type GitLabGetConfigFileResult = ResponseData<{\n content: string;\n}>;\n\nexport const getConfigFile = async (\n request: FastifyRequest<{ Body: GitLabGetConfigFileBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const {\n token,\n projectId,\n branch = 'main',\n path = 'intlayer.config.ts',\n instanceUrl,\n } = request.body;\n const userId = request.locals?.user?.id;\n\n try {\n let accessToken: string | undefined = token;\n\n if (!accessToken && userId) {\n accessToken = (await getGitLabTokenFromUser(String(userId))) ?? undefined;\n }\n\n if (!accessToken || !projectId) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITLAB_GET_CONFIG_FILE_MISSING_PARAMS'\n );\n }\n\n const content = await gitlabService.getRepositoryFileContents(\n accessToken,\n projectId,\n path,\n branch,\n instanceUrl\n );\n\n if (!content) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'GITLAB_CONFIG_FILE_NOT_FOUND'\n );\n }\n\n const responseData = formatResponse<{ content: string }>({\n data: { content },\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n"],"mappings":";;;;;AAgBA,MAAa,aAAa,OACxB,SACA,UACkB;CAClB,MAAM,EAAE,aAAa,aAAa,UAAU,QAAQ;AAEpD,KAAI,CAAC,YACH,QAAO,aAAa,2BAClB,OACA,8BACD;AAGH,KAAI;EAMF,MAAM,eAAe,eAAoC,EACvD,MAAM,EAAE,SANMA,oBACd,aACA,aACA,MACD,EAEkB,EAClB,CAAC;AACF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;AAcxE,MAAa,eAAe,OAC1B,SACA,UACkB;CAClB,MAAM,EAAE,MAAM,aAAa,gBAAgB,QAAQ;AAEnD,KAAI,CAAC,QAAQ,CAAC,YACZ,QAAO,aAAa,2BAClB,OACA,sBACD;AAGH,KAAI;EAMF,MAAM,eAAe,eAAkC,EACrD,MAAM,EAAE,OANI,MAAMC,qBAClB,MACA,aACA,YACD,EAEgB,EAChB,CAAC;AACF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;AAaxE,MAAa,eAAe,OAC1B,SACA,UACkB;CAClB,MAAM,EAAE,OAAO,gBAAgB,QAAQ;CACvC,MAAM,SAAS,QAAQ,QAAQ,MAAM;AAErC,KAAI;EACF,IAAIC,cAAkC;AAEtC,MAAI,CAAC,eAAe,OAClB,eAAe,MAAM,uBAAuB,OAAO,OAAO,CAAC,IAAK;AAGlE,MAAI,CAAC,YACH,QAAO,aAAa,2BAClB,OACA,uBACD;EAOH,MAAM,eAAe,eAA8C,EACjE,MALe,MAAMC,gBACrB,aACA,YACD,EAGA,CAAC;AACF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;;;;AAmBxE,MAAa,cAAc,OACzB,SACA,UACkB;CAClB,MAAM,EAAE,OAAO,WAAW,SAAS,QAAQ,gBAAgB,QAAQ;CACnE,MAAM,SAAS,QAAQ,QAAQ,MAAM;AAErC,KAAI;EACF,IAAID,cAAkC;AAEtC,MAAI,CAAC,eAAe,OAClB,eAAe,MAAM,uBAAuB,OAAO,OAAO,CAAC,IAAK;AAGlE,MAAI,CAAC,eAAe,CAAC,UACnB,QAAO,aAAa,2BAClB,OACA,qCACD;EAGH,MAAM,cAAc,MAAME,oBACxB,aACA,WACA,QACA,YACD;EAED,MAAM,eAAe,eAGlB,EACD,MAAM;GACJ,WAAW,YAAY,SAAS;GACnB;GACd,EACF,CAAC;AAEF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB;;;AAgBxE,MAAa,gBAAgB,OAC3B,SACA,UACkB;CAClB,MAAM,EACJ,OACA,WACA,SAAS,QACT,OAAO,sBACP,gBACE,QAAQ;CACZ,MAAM,SAAS,QAAQ,QAAQ,MAAM;AAErC,KAAI;EACF,IAAIF,cAAkC;AAEtC,MAAI,CAAC,eAAe,OAClB,eAAe,MAAM,uBAAuB,OAAO,OAAO,CAAC,IAAK;AAGlE,MAAI,CAAC,eAAe,CAAC,UACnB,QAAO,aAAa,2BAClB,OACA,wCACD;EAGH,MAAM,UAAU,MAAMG,0BACpB,aACA,WACA,MACA,QACA,YACD;AAED,MAAI,CAAC,QACH,QAAO,aAAa,2BAClB,OACA,+BACD;EAGH,MAAM,eAAe,eAAoC,EACvD,MAAM,EAAE,SAAS,EAClB,CAAC;AAEF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB"}
@@ -4,7 +4,7 @@ import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
4
4
  import { hasPermission } from "../utils/permissions.mjs";
5
5
  import { createUser, getUserByEmail, getUserById, updateUserById } from "../services/user.service.mjs";
6
6
  import { mapUserToAPI } from "../utils/mapper/user.mjs";
7
- import { t } from "express-intlayer";
7
+ import { t } from "fastify-intlayer";
8
8
 
9
9
  //#region src/controllers/newsletter.controller.ts
10
10
  /**
@@ -12,13 +12,10 @@ import { t } from "express-intlayer";
12
12
  * If the user doesn't exist, creates a new user.
13
13
  * If the user exists, updates their newsletter subscription to true.
14
14
  */
15
- const subscribeToNewsletter = async (req, res, _next) => {
16
- const { roles } = res.locals;
17
- const { email, emailList } = req.body;
18
- if (!email) {
19
- ErrorHandler.handleGenericErrorResponse(res, "USER_DATA_NOT_FOUND");
20
- return;
21
- }
15
+ const subscribeToNewsletter = async (request, reply) => {
16
+ const { roles } = request.locals || {};
17
+ const { email, emailList } = request.body;
18
+ if (!email) return ErrorHandler.handleGenericErrorResponse(reply, "USER_DATA_NOT_FOUND");
22
19
  const emailLists = Array.isArray(emailList) ? emailList : [emailList];
23
20
  const emailsListObject = Object.fromEntries(emailLists.map((list) => [list, true]));
24
21
  try {
@@ -30,13 +27,10 @@ const subscribeToNewsletter = async (req, res, _next) => {
30
27
  });
31
28
  logger.info(`New user created and subscribed to newsletter: ${email}`);
32
29
  } else {
33
- if (!hasPermission(roles, "user:write")({
34
- ...res.locals,
30
+ if (!hasPermission(roles || [], "user:write")({
31
+ ...request.locals,
35
32
  targetUsers: [user]
36
- })) {
37
- ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
38
- return;
39
- }
33
+ })) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
40
34
  user = await updateUserById(user.id, { emailsList: {
41
35
  ...user.emailsList,
42
36
  ...emailsListObject
@@ -57,37 +51,26 @@ const subscribeToNewsletter = async (req, res, _next) => {
57
51
  }),
58
52
  data: formattedUser
59
53
  });
60
- res.json(responseData);
61
- return;
54
+ return reply.send(responseData);
62
55
  } catch (error) {
63
- ErrorHandler.handleAppErrorResponse(res, error);
64
- return;
56
+ return ErrorHandler.handleAppErrorResponse(reply, error);
65
57
  }
66
58
  };
67
59
  /**
68
60
  * Unsubscribes a user from the newsletter.
69
61
  * Only works if the user exists.
70
62
  */
71
- const unsubscribeFromNewsletter = async (req, res, _next) => {
72
- const { userId, emailList } = req.body;
73
- const { roles } = res.locals;
74
- if (!userId) {
75
- ErrorHandler.handleGenericErrorResponse(res, "USER_DATA_NOT_FOUND");
76
- return;
77
- }
63
+ const unsubscribeFromNewsletter = async (request, reply) => {
64
+ const { userId, emailList } = request.body;
65
+ const { roles } = request.locals || {};
66
+ if (!userId) return ErrorHandler.handleGenericErrorResponse(reply, "USER_DATA_NOT_FOUND");
78
67
  try {
79
68
  const user = await getUserById(userId);
80
- if (!user) {
81
- ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_FOUND");
82
- return;
83
- }
84
- if (!hasPermission(roles, "user:write")({
85
- ...res.locals,
69
+ if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_FOUND");
70
+ if (!hasPermission(roles || [], "user:write")({
71
+ ...request.locals,
86
72
  targetUsers: [user]
87
- })) {
88
- ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
89
- return;
90
- }
73
+ })) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
91
74
  const emailLists = Array.isArray(emailList) ? emailList : [emailList];
92
75
  const emailsListObject = Object.fromEntries(emailLists.map((list) => [list, false]));
93
76
  const updatedUser = await updateUserById(user.id, { emailsList: {
@@ -109,36 +92,25 @@ const unsubscribeFromNewsletter = async (req, res, _next) => {
109
92
  }),
110
93
  data: formattedUser
111
94
  });
112
- res.json(responseData);
113
- return;
95
+ return reply.send(responseData);
114
96
  } catch (error) {
115
- ErrorHandler.handleAppErrorResponse(res, error);
116
- return;
97
+ return ErrorHandler.handleAppErrorResponse(reply, error);
117
98
  }
118
99
  };
119
100
  /**
120
101
  * Gets the newsletter subscription status for a user.
121
102
  */
122
- const getNewsletterStatus = async (_req, res, _next) => {
123
- const email = res.locals.user?.email;
124
- const { roles } = res.locals;
125
- if (!email) {
126
- ErrorHandler.handleGenericErrorResponse(res, "USER_DATA_NOT_FOUND");
127
- return;
128
- }
103
+ const getNewsletterStatus = async (_request, reply) => {
104
+ const email = _request.locals?.user?.email;
105
+ const { roles } = _request.locals || {};
106
+ if (!email) return ErrorHandler.handleGenericErrorResponse(reply, "USER_DATA_NOT_FOUND");
129
107
  try {
130
108
  const user = await getUserByEmail(email);
131
- if (!user) {
132
- ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_FOUND");
133
- return;
134
- }
135
- if (!hasPermission(roles, "user:read")({
136
- ...res.locals,
109
+ if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_FOUND");
110
+ if (!hasPermission(roles || [], "user:read")({
111
+ ..._request.locals,
137
112
  targetUsers: [user]
138
- })) {
139
- ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
140
- return;
141
- }
113
+ })) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
142
114
  const formattedUser = mapUserToAPI(user);
143
115
  const responseData = formatResponse({
144
116
  message: t({
@@ -148,11 +120,9 @@ const getNewsletterStatus = async (_req, res, _next) => {
148
120
  }),
149
121
  data: formattedUser
150
122
  });
151
- res.json(responseData);
152
- return;
123
+ return reply.send(responseData);
153
124
  } catch (error) {
154
- ErrorHandler.handleAppErrorResponse(res, error);
155
- return;
125
+ return ErrorHandler.handleAppErrorResponse(reply, error);
156
126
  }
157
127
  };
158
128
 
@@ -1 +1 @@
1
- {"version":3,"file":"newsletter.controller.mjs","names":["userService.getUserByEmail","userService.createUser","userService.updateUserById","userService.getUserById"],"sources":["../../../src/controllers/newsletter.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hasPermission } from '@utils/permissions';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { EmailsList, UserAPI } from '@/types/user.types';\n\nexport type NewsletterSubscriptionBody = {\n email: string;\n emailList: EmailsList | EmailsList[];\n};\nexport type NewsletterSubscriptionResult = ResponseData<UserAPI>;\n\n/**\n * Subscribes a user to the newsletter.\n * If the user doesn't exist, creates a new user.\n * If the user exists, updates their newsletter subscription to true.\n */\nexport const subscribeToNewsletter = async (\n req: Request<any, any, NewsletterSubscriptionBody>,\n res: ResponseWithSession<NewsletterSubscriptionResult>,\n _next: NextFunction\n): Promise<void> => {\n const { roles } = res.locals;\n const { email, emailList } = req.body;\n\n if (!email) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_DATA_NOT_FOUND');\n return;\n }\n\n const emailLists = Array.isArray(emailList) ? emailList : [emailList];\n\n // Create new user with newsletter subscription enabled\n const emailsListObject = Object.fromEntries(\n emailLists.map((list) => [list, true])\n ) as Record<EmailsList, boolean>;\n\n try {\n // Check if user exists\n let user = await userService.getUserByEmail(email);\n\n if (!user) {\n user = await userService.createUser({\n email,\n emailsList: emailsListObject,\n });\n\n logger.info(`New user created and subscribed to newsletter: ${email}`);\n } else {\n if (\n !hasPermission(\n roles,\n 'user:write'\n )({\n ...res.locals,\n targetUsers: [user],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n // Update existing user's newsletter subscription\n user = await userService.updateUserById(user.id, {\n emailsList: { ...user.emailsList, ...emailsListObject },\n });\n\n logger.info(`User subscribed to newsletter: ${email}`);\n }\n\n const formattedUser = mapUserToAPI(user);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'Successfully subscribed to newsletter',\n fr: 'Abonnement à la newsletter réussi',\n es: 'Suscripción al boletín exitosa',\n }),\n description: t({\n en: 'You have been successfully subscribed to our newsletter',\n fr: 'Vous avez été abonné avec succès à notre newsletter',\n es: 'Te has suscrito exitosamente a nuestro boletín',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type NewsletterUnsubscriptionBody = {\n userId: string;\n emailList: EmailsList | EmailsList[];\n};\n\n/**\n * Unsubscribes a user from the newsletter.\n * Only works if the user exists.\n */\nexport const unsubscribeFromNewsletter = async (\n req: Request<any, any, NewsletterUnsubscriptionBody>,\n res: ResponseWithSession<NewsletterSubscriptionResult>,\n _next: NextFunction\n): Promise<void> => {\n const { userId, emailList } = req.body;\n const { roles } = res.locals;\n\n if (!userId) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_DATA_NOT_FOUND');\n return;\n }\n\n try {\n // Check if user exists\n const user = await userService.getUserById(userId);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'user:write'\n )({\n ...res.locals,\n targetUsers: [user],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const emailLists = Array.isArray(emailList) ? emailList : [emailList];\n\n // Create new user with newsletter subscription enabled\n const emailsListObject = Object.fromEntries(\n emailLists.map((list) => [list, false])\n ) as Record<EmailsList, boolean>;\n\n // Update user's newsletter subscription to false\n const updatedUser = await userService.updateUserById(user.id, {\n emailsList: { ...user.emailsList, ...emailsListObject },\n });\n\n logger.info(`User unsubscribed from newsletter: ${updatedUser.email}`);\n\n const formattedUser = mapUserToAPI(updatedUser);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'Successfully unsubscribed from newsletter',\n fr: 'Désabonnement de la newsletter réussi',\n es: 'Cancelación de suscripción al boletín exitosa',\n }),\n description: t({\n en: 'You have been successfully unsubscribed from our newsletter',\n fr: 'Vous avez été désabonné avec succès de notre newsletter',\n es: 'Te has desuscrito exitosamente de nuestro boletín',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\n/**\n * Gets the newsletter subscription status for a user.\n */\nexport const getNewsletterStatus = async (\n _req: Request<{ email: string }>,\n res: ResponseWithSession<NewsletterSubscriptionResult>,\n _next: NextFunction\n): Promise<void> => {\n const email = res.locals.user?.email;\n const { roles } = res.locals;\n\n if (!email) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_DATA_NOT_FOUND');\n return;\n }\n\n try {\n const user = await userService.getUserByEmail(email);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'user:read'\n )({\n ...res.locals,\n targetUsers: [user],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const formattedUser = mapUserToAPI(user);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'Newsletter subscription status retrieved',\n fr: \"Statut d'abonnement à la newsletter récupéré\",\n es: 'Estado de suscripción al boletín obtenido',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"newsletter.controller.mjs","names":["userService.getUserByEmail","userService.createUser","userService.updateUserById","userService.getUserById"],"sources":["../../../src/controllers/newsletter.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hasPermission } from '@utils/permissions';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport { t } from 'fastify-intlayer';\nimport type { EmailsList, UserAPI } from '@/types/user.types';\n\nexport type NewsletterSubscriptionBody = {\n email: string;\n emailList: EmailsList | EmailsList[];\n};\nexport type NewsletterSubscriptionResult = ResponseData<UserAPI>;\n\n/**\n * Subscribes a user to the newsletter.\n * If the user doesn't exist, creates a new user.\n * If the user exists, updates their newsletter subscription to true.\n */\nexport const subscribeToNewsletter = async (\n request: FastifyRequest<{ Body: NewsletterSubscriptionBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const { roles } = request.locals || {};\n const { email, emailList } = request.body;\n\n if (!email) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'USER_DATA_NOT_FOUND'\n );\n }\n\n const emailLists = Array.isArray(emailList) ? emailList : [emailList];\n\n // Create new user with newsletter subscription enabled\n const emailsListObject = Object.fromEntries(\n emailLists.map((list) => [list, true])\n ) as Record<EmailsList, boolean>;\n\n try {\n // Check if user exists\n let user = await userService.getUserByEmail(email);\n\n if (!user) {\n user = await userService.createUser({\n email,\n emailsList: emailsListObject,\n });\n\n logger.info(`New user created and subscribed to newsletter: ${email}`);\n } else {\n if (\n !hasPermission(\n roles || [],\n 'user:write'\n )({\n ...request.locals,\n targetUsers: [user],\n })\n ) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'PERMISSION_DENIED'\n );\n }\n\n // Update existing user's newsletter subscription\n user = await userService.updateUserById(user.id, {\n emailsList: { ...user.emailsList, ...emailsListObject },\n });\n\n logger.info(`User subscribed to newsletter: ${email}`);\n }\n\n const formattedUser = mapUserToAPI(user);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'Successfully subscribed to newsletter',\n fr: 'Abonnement à la newsletter réussi',\n es: 'Suscripción al boletín exitosa',\n }),\n description: t({\n en: 'You have been successfully subscribed to our newsletter',\n fr: 'Vous avez été abonné avec succès à notre newsletter',\n es: 'Te has suscrito exitosamente a nuestro boletín',\n }),\n data: formattedUser,\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\nexport type NewsletterUnsubscriptionBody = {\n userId: string;\n emailList: EmailsList | EmailsList[];\n};\n\n/**\n * Unsubscribes a user from the newsletter.\n * Only works if the user exists.\n */\nexport const unsubscribeFromNewsletter = async (\n request: FastifyRequest<{ Body: NewsletterUnsubscriptionBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const { userId, emailList } = request.body;\n const { roles } = request.locals || {};\n\n if (!userId) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'USER_DATA_NOT_FOUND'\n );\n }\n\n try {\n // Check if user exists\n const user = await userService.getUserById(userId);\n\n if (!user) {\n return ErrorHandler.handleGenericErrorResponse(reply, 'USER_NOT_FOUND');\n }\n\n if (\n !hasPermission(\n roles || [],\n 'user:write'\n )({\n ...request.locals,\n targetUsers: [user],\n })\n ) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'PERMISSION_DENIED'\n );\n }\n\n const emailLists = Array.isArray(emailList) ? emailList : [emailList];\n\n // Create new user with newsletter subscription enabled\n const emailsListObject = Object.fromEntries(\n emailLists.map((list) => [list, false])\n ) as Record<EmailsList, boolean>;\n\n // Update user's newsletter subscription to false\n const updatedUser = await userService.updateUserById(user.id, {\n emailsList: { ...user.emailsList, ...emailsListObject },\n });\n\n logger.info(`User unsubscribed from newsletter: ${updatedUser.email}`);\n\n const formattedUser = mapUserToAPI(updatedUser);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'Successfully unsubscribed from newsletter',\n fr: 'Désabonnement de la newsletter réussi',\n es: 'Cancelación de suscripción al boletín exitosa',\n }),\n description: t({\n en: 'You have been successfully unsubscribed from our newsletter',\n fr: 'Vous avez été désabonné avec succès de notre newsletter',\n es: 'Te has desuscrito exitosamente de nuestro boletín',\n }),\n data: formattedUser,\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n\n/**\n * Gets the newsletter subscription status for a user.\n */\nexport const getNewsletterStatus = async (\n _request: FastifyRequest,\n reply: FastifyReply\n): Promise<void> => {\n const email = _request.locals?.user?.email;\n const { roles } = _request.locals || {};\n\n if (!email) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'USER_DATA_NOT_FOUND'\n );\n }\n\n try {\n const user = await userService.getUserByEmail(email);\n\n if (!user) {\n return ErrorHandler.handleGenericErrorResponse(reply, 'USER_NOT_FOUND');\n }\n\n if (\n !hasPermission(\n roles || [],\n 'user:read'\n )({\n ..._request.locals,\n targetUsers: [user],\n })\n ) {\n return ErrorHandler.handleGenericErrorResponse(\n reply,\n 'PERMISSION_DENIED'\n );\n }\n\n const formattedUser = mapUserToAPI(user);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'Newsletter subscription status retrieved',\n fr: \"Statut d'abonnement à la newsletter récupéré\",\n es: 'Estado de suscripción al boletín obtenido',\n }),\n data: formattedUser,\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n"],"mappings":"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"}
@@ -3,16 +3,19 @@ import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
3
3
  import { Request, Response } from "oauth2-server";
4
4
 
5
5
  //#region src/controllers/oAuth2.controller.ts
6
- const getOAuth2AccessToken = async (req, res, _next) => {
7
- const oauthRequest = new Request(req);
8
- const oauthResponse = new Response(res);
6
+ const getOAuth2AccessToken = async (request, reply) => {
7
+ const oauthRequest = new Request({
8
+ headers: request.headers,
9
+ method: request.method,
10
+ query: request.query,
11
+ body: request.body
12
+ });
13
+ const oauthResponse = new Response(reply.raw);
9
14
  try {
10
- const responseData = formatResponse({ data: await req.oauth.token(oauthRequest, oauthResponse) });
11
- res.json(responseData);
12
- return;
15
+ const responseData = formatResponse({ data: await request.oauth.token(oauthRequest, oauthResponse) });
16
+ return reply.send(responseData);
13
17
  } catch (error) {
14
- ErrorHandler.handleAppErrorResponse(res, error);
15
- return;
18
+ return ErrorHandler.handleAppErrorResponse(reply, error);
16
19
  }
17
20
  };
18
21
 
@@ -1 +1 @@
1
- {"version":3,"file":"oAuth2.controller.mjs","names":["OAuthRequest","OAuthResponse"],"sources":["../../../src/controllers/oAuth2.controller.ts"],"sourcesContent":["import type { RequestWithOAuth2Information } from '@middlewares/oAuth2.middleware';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { NextFunction, Request, Response } from 'express';\nimport {\n Request as OAuthRequest,\n Response as OAuthResponse,\n} from 'oauth2-server';\nimport type { OAuth2Token } from '@/types/oAuth2.types';\n\nexport type GetOAuth2TokenBody = {\n grant_type: 'client_credentials';\n client_id: string;\n client_secret: string;\n};\nexport type GetOAuth2TokenResult = ResponseData<OAuth2Token>;\n\n// Method to get the token\nexport const getOAuth2AccessToken = async (\n req: Request,\n res: Response<GetOAuth2TokenResult>,\n _next: NextFunction\n): Promise<void> => {\n const oauthRequest = new OAuthRequest(req);\n const oauthResponse = new OAuthResponse(res);\n\n try {\n const token: OAuth2Token = (await (\n req as unknown as RequestWithOAuth2Information<\n undefined,\n undefined,\n GetOAuth2TokenBody\n >\n ).oauth.token(oauthRequest, oauthResponse)) as OAuth2Token;\n\n const responseData = formatResponse<OAuth2Token>({\n data: token,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":";;;;;AAkBA,MAAa,uBAAuB,OAClC,KACA,KACA,UACkB;CAClB,MAAM,eAAe,IAAIA,QAAa,IAAI;CAC1C,MAAM,gBAAgB,IAAIC,SAAc,IAAI;AAE5C,KAAI;EASF,MAAM,eAAe,eAA4B,EAC/C,MAT0B,MAC1B,IAKA,MAAM,MAAM,cAAc,cAAc,EAIzC,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,eAAa,uBAAuB,KAAK,MAAkB;AAC3D"}
1
+ {"version":3,"file":"oAuth2.controller.mjs","names":["OAuthRequest","OAuthResponse"],"sources":["../../../src/controllers/oAuth2.controller.ts"],"sourcesContent":["import type { RequestWithOAuth2Information } from '@middlewares/oAuth2.middleware';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport {\n Request as OAuthRequest,\n Response as OAuthResponse,\n} from 'oauth2-server';\nimport type { OAuth2Token } from '@/types/oAuth2.types';\n\nexport type GetOAuth2TokenBody = {\n grant_type: 'client_credentials';\n client_id: string;\n client_secret: string;\n};\nexport type GetOAuth2TokenResult = ResponseData<OAuth2Token>;\n\n// Method to get the token\nexport const getOAuth2AccessToken = async (\n request: FastifyRequest<{ Body: GetOAuth2TokenBody }>,\n reply: FastifyReply\n): Promise<void> => {\n const oauthRequest = new OAuthRequest({\n headers: request.headers,\n method: request.method,\n query: request.query as any,\n body: request.body as any,\n });\n const oauthResponse = new OAuthResponse(reply.raw);\n\n try {\n const token: OAuth2Token = (await (\n request as unknown as RequestWithOAuth2Information\n ).oauth.token(oauthRequest, oauthResponse)) as OAuth2Token;\n\n const responseData = formatResponse<OAuth2Token>({\n data: token,\n });\n\n return reply.send(responseData);\n } catch (error) {\n return ErrorHandler.handleAppErrorResponse(reply, error as AppError);\n }\n};\n"],"mappings":";;;;;AAkBA,MAAa,uBAAuB,OAClC,SACA,UACkB;CAClB,MAAM,eAAe,IAAIA,QAAa;EACpC,SAAS,QAAQ;EACjB,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,MAAM,QAAQ;EACf,CAAC;CACF,MAAM,gBAAgB,IAAIC,SAAc,MAAM,IAAI;AAElD,KAAI;EAKF,MAAM,eAAe,eAA4B,EAC/C,MAL0B,MAC1B,QACA,MAAM,MAAM,cAAc,cAAc,EAIzC,CAAC;AAEF,SAAO,MAAM,KAAK,aAAa;UACxB,OAAO;AACd,SAAO,aAAa,uBAAuB,OAAO,MAAkB"}