@intlayer/backend 7.0.7 → 7.0.8

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 (206) hide show
  1. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/intlayer_with_i18next.json +5122 -4096
  2. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/intlayer_with_next-i18next.json +5122 -4096
  3. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/intlayer_with_next-intl.json +5122 -4096
  4. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/intlayer_with_react-i18next.json +5122 -4096
  5. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/intlayer_with_react-intl.json +5122 -4096
  6. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/intlayer_with_vue-i18n.json +5122 -4096
  7. package/dist/assets/utils/AI/askDocQuestion/embeddings/blog/en/react-i18next_vs_react-intl_vs_intlayer.json +8194 -7168
  8. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/intlayer_with_nextjs_16.json +1 -1
  9. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/intlayer_with_nuxt.json +11266 -10240
  10. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/intlayer_with_tanstack.json +9218 -8192
  11. package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/intlayer_with_vite+react.json +1 -1
  12. package/dist/cjs/_virtual/_utils_asset.cjs +0 -3
  13. package/dist/cjs/controllers/audit.controller.cjs +0 -1
  14. package/dist/cjs/controllers/audit.controller.cjs.map +1 -1
  15. package/dist/cjs/controllers/dictionary.controller.cjs +0 -1
  16. package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
  17. package/dist/cjs/controllers/newsletter.controller.cjs +0 -1
  18. package/dist/cjs/controllers/newsletter.controller.cjs.map +1 -1
  19. package/dist/cjs/controllers/oAuth2.controller.cjs +0 -1
  20. package/dist/cjs/controllers/oAuth2.controller.cjs.map +1 -1
  21. package/dist/cjs/controllers/organization.controller.cjs +0 -2
  22. package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
  23. package/dist/cjs/controllers/project.controller.cjs +0 -1
  24. package/dist/cjs/controllers/project.controller.cjs.map +1 -1
  25. package/dist/cjs/controllers/projectAccessKey.controller.cjs +0 -1
  26. package/dist/cjs/controllers/projectAccessKey.controller.cjs.map +1 -1
  27. package/dist/cjs/controllers/stripe.controller.cjs +0 -2
  28. package/dist/cjs/controllers/stripe.controller.cjs.map +1 -1
  29. package/dist/cjs/controllers/tag.controller.cjs +0 -1
  30. package/dist/cjs/controllers/tag.controller.cjs.map +1 -1
  31. package/dist/cjs/controllers/user.controller.cjs +0 -1
  32. package/dist/cjs/controllers/user.controller.cjs.map +1 -1
  33. package/dist/cjs/emails/InviteUserEmail.cjs +0 -2
  34. package/dist/cjs/emails/InviteUserEmail.cjs.map +1 -1
  35. package/dist/cjs/emails/OAuthTokenCreatedEmail.cjs +0 -2
  36. package/dist/cjs/emails/OAuthTokenCreatedEmail.cjs.map +1 -1
  37. package/dist/cjs/emails/PasswordChangeConfirmation.cjs +0 -2
  38. package/dist/cjs/emails/PasswordChangeConfirmation.cjs.map +1 -1
  39. package/dist/cjs/emails/ResetUserPassword.cjs +0 -2
  40. package/dist/cjs/emails/ResetUserPassword.cjs.map +1 -1
  41. package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs +0 -2
  42. package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs.map +1 -1
  43. package/dist/cjs/emails/SubscriptionPaymentError.cjs +0 -2
  44. package/dist/cjs/emails/SubscriptionPaymentError.cjs.map +1 -1
  45. package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs +0 -2
  46. package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs.map +1 -1
  47. package/dist/cjs/emails/ValidateUserEmail.cjs +0 -2
  48. package/dist/cjs/emails/ValidateUserEmail.cjs.map +1 -1
  49. package/dist/cjs/emails/Welcome.cjs +0 -2
  50. package/dist/cjs/emails/Welcome.cjs.map +1 -1
  51. package/dist/cjs/index.cjs +0 -2
  52. package/dist/cjs/index.cjs.map +1 -1
  53. package/dist/cjs/logger/index.cjs +0 -1
  54. package/dist/cjs/logger/index.cjs.map +1 -1
  55. package/dist/cjs/middlewares/sessionAuth.middleware.cjs +0 -1
  56. package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
  57. package/dist/cjs/models/audit.model.cjs +0 -2
  58. package/dist/cjs/models/audit.model.cjs.map +1 -1
  59. package/dist/cjs/models/dictionary.model.cjs +0 -1
  60. package/dist/cjs/models/dictionary.model.cjs.map +1 -1
  61. package/dist/cjs/models/discussion.model.cjs +0 -1
  62. package/dist/cjs/models/discussion.model.cjs.map +1 -1
  63. package/dist/cjs/models/oAuth2.model.cjs +0 -1
  64. package/dist/cjs/models/oAuth2.model.cjs.map +1 -1
  65. package/dist/cjs/models/organization.model.cjs +0 -1
  66. package/dist/cjs/models/organization.model.cjs.map +1 -1
  67. package/dist/cjs/models/project.model.cjs +0 -1
  68. package/dist/cjs/models/project.model.cjs.map +1 -1
  69. package/dist/cjs/models/session.model.cjs +0 -1
  70. package/dist/cjs/models/session.model.cjs.map +1 -1
  71. package/dist/cjs/models/tag.model.cjs +0 -1
  72. package/dist/cjs/models/tag.model.cjs.map +1 -1
  73. package/dist/cjs/models/user.model.cjs +0 -1
  74. package/dist/cjs/models/user.model.cjs.map +1 -1
  75. package/dist/cjs/routes/ai.routes.cjs +0 -1
  76. package/dist/cjs/routes/ai.routes.cjs.map +1 -1
  77. package/dist/cjs/routes/dictionary.routes.cjs +0 -1
  78. package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
  79. package/dist/cjs/routes/eventListener.routes.cjs +0 -1
  80. package/dist/cjs/routes/eventListener.routes.cjs.map +1 -1
  81. package/dist/cjs/routes/newsletter.routes.cjs +0 -1
  82. package/dist/cjs/routes/newsletter.routes.cjs.map +1 -1
  83. package/dist/cjs/routes/organization.routes.cjs +0 -1
  84. package/dist/cjs/routes/organization.routes.cjs.map +1 -1
  85. package/dist/cjs/routes/project.routes.cjs +0 -1
  86. package/dist/cjs/routes/project.routes.cjs.map +1 -1
  87. package/dist/cjs/routes/search.routes.cjs +0 -1
  88. package/dist/cjs/routes/search.routes.cjs.map +1 -1
  89. package/dist/cjs/routes/stripe.routes.cjs +0 -1
  90. package/dist/cjs/routes/stripe.routes.cjs.map +1 -1
  91. package/dist/cjs/routes/tags.routes.cjs +0 -1
  92. package/dist/cjs/routes/tags.routes.cjs.map +1 -1
  93. package/dist/cjs/routes/user.routes.cjs +0 -1
  94. package/dist/cjs/routes/user.routes.cjs.map +1 -1
  95. package/dist/cjs/schemas/dictionary.schema.cjs +0 -1
  96. package/dist/cjs/schemas/dictionary.schema.cjs.map +1 -1
  97. package/dist/cjs/schemas/discussion.schema.cjs +0 -1
  98. package/dist/cjs/schemas/discussion.schema.cjs.map +1 -1
  99. package/dist/cjs/schemas/oAuth2.schema.cjs +0 -1
  100. package/dist/cjs/schemas/oAuth2.schema.cjs.map +1 -1
  101. package/dist/cjs/schemas/organization.schema.cjs +0 -1
  102. package/dist/cjs/schemas/organization.schema.cjs.map +1 -1
  103. package/dist/cjs/schemas/plans.schema.cjs +0 -1
  104. package/dist/cjs/schemas/plans.schema.cjs.map +1 -1
  105. package/dist/cjs/schemas/project.schema.cjs +0 -2
  106. package/dist/cjs/schemas/project.schema.cjs.map +1 -1
  107. package/dist/cjs/schemas/session.schema.cjs +0 -1
  108. package/dist/cjs/schemas/session.schema.cjs.map +1 -1
  109. package/dist/cjs/schemas/tag.schema.cjs +0 -1
  110. package/dist/cjs/schemas/tag.schema.cjs.map +1 -1
  111. package/dist/cjs/schemas/user.schema.cjs +0 -1
  112. package/dist/cjs/schemas/user.schema.cjs.map +1 -1
  113. package/dist/cjs/services/dictionary.service.cjs +0 -1
  114. package/dist/cjs/services/dictionary.service.cjs.map +1 -1
  115. package/dist/cjs/services/email.service.cjs +0 -3
  116. package/dist/cjs/services/email.service.cjs.map +1 -1
  117. package/dist/cjs/services/oAuth2.service.cjs +0 -1
  118. package/dist/cjs/services/oAuth2.service.cjs.map +1 -1
  119. package/dist/cjs/services/projectAccessKey.service.cjs +0 -1
  120. package/dist/cjs/services/projectAccessKey.service.cjs.map +1 -1
  121. package/dist/cjs/utils/AI/aiSdk.cjs +0 -5
  122. package/dist/cjs/utils/AI/aiSdk.cjs.map +1 -1
  123. package/dist/cjs/utils/AI/askDocQuestion/askDocQuestion.cjs +0 -4
  124. package/dist/cjs/utils/AI/askDocQuestion/askDocQuestion.cjs.map +1 -1
  125. package/dist/cjs/utils/AI/askDocQuestion/indexMarkdownFiles.cjs +0 -6
  126. package/dist/cjs/utils/AI/askDocQuestion/indexMarkdownFiles.cjs.map +1 -1
  127. package/dist/cjs/utils/AI/auditDictionary/index.cjs +0 -3
  128. package/dist/cjs/utils/AI/auditDictionary/index.cjs.map +1 -1
  129. package/dist/cjs/utils/AI/auditDictionaryField/index.cjs +0 -3
  130. package/dist/cjs/utils/AI/auditDictionaryField/index.cjs.map +1 -1
  131. package/dist/cjs/utils/AI/auditDictionaryMetadata/index.cjs +0 -1
  132. package/dist/cjs/utils/AI/auditDictionaryMetadata/index.cjs.map +1 -1
  133. package/dist/cjs/utils/AI/auditTag/index.cjs +0 -1
  134. package/dist/cjs/utils/AI/auditTag/index.cjs.map +1 -1
  135. package/dist/cjs/utils/AI/autocomplete/index.cjs +0 -1
  136. package/dist/cjs/utils/AI/autocomplete/index.cjs.map +1 -1
  137. package/dist/cjs/utils/AI/customQuery/index.cjs +0 -1
  138. package/dist/cjs/utils/AI/customQuery/index.cjs.map +1 -1
  139. package/dist/cjs/utils/AI/translateJSON/index.cjs +0 -3
  140. package/dist/cjs/utils/AI/translateJSON/index.cjs.map +1 -1
  141. package/dist/cjs/utils/accessControl.cjs +1 -1
  142. package/dist/cjs/utils/accessControl.cjs.map +1 -1
  143. package/dist/cjs/utils/auth/getAuth.cjs +0 -4
  144. package/dist/cjs/utils/auth/getAuth.cjs.map +1 -1
  145. package/dist/cjs/utils/errors/ErrorHandler.cjs +0 -2
  146. package/dist/cjs/utils/errors/ErrorHandler.cjs.map +1 -1
  147. package/dist/cjs/utils/errors/ErrorsClass.cjs +0 -1
  148. package/dist/cjs/utils/errors/ErrorsClass.cjs.map +1 -1
  149. package/dist/cjs/utils/mongoDB/connectDB.cjs +1 -2
  150. package/dist/cjs/utils/mongoDB/connectDB.cjs.map +1 -1
  151. package/dist/cjs/webhooks/stripe.webhook.cjs +0 -1
  152. package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -1
  153. package/dist/esm/index.mjs.map +1 -1
  154. package/dist/esm/utils/accessControl.mjs +1 -1
  155. package/dist/esm/utils/accessControl.mjs.map +1 -1
  156. package/dist/esm/utils/mongoDB/connectDB.mjs +2 -2
  157. package/dist/esm/utils/mongoDB/connectDB.mjs.map +1 -1
  158. package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
  159. package/dist/types/emails/InviteUserEmail.d.ts +4 -4
  160. package/dist/types/emails/OAuthTokenCreatedEmail.d.ts +4 -4
  161. package/dist/types/emails/OAuthTokenCreatedEmail.d.ts.map +1 -1
  162. package/dist/types/emails/PasswordChangeConfirmation.d.ts +4 -4
  163. package/dist/types/emails/PasswordChangeConfirmation.d.ts.map +1 -1
  164. package/dist/types/emails/ResetUserPassword.d.ts +4 -4
  165. package/dist/types/emails/ResetUserPassword.d.ts.map +1 -1
  166. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +4 -4
  167. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -1
  168. package/dist/types/emails/SubscriptionPaymentError.d.ts +4 -4
  169. package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -1
  170. package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +4 -4
  171. package/dist/types/emails/Welcome.d.ts +4 -4
  172. package/dist/types/emails/Welcome.d.ts.map +1 -1
  173. package/dist/types/export.d.ts +3 -1
  174. package/dist/types/models/dictionary.model.d.ts +4 -4
  175. package/dist/types/models/dictionary.model.d.ts.map +1 -1
  176. package/dist/types/models/discussion.model.d.ts +2 -2
  177. package/dist/types/models/discussion.model.d.ts.map +1 -1
  178. package/dist/types/models/oAuth2.model.d.ts +4 -3
  179. package/dist/types/models/oAuth2.model.d.ts.map +1 -1
  180. package/dist/types/routes/ai.routes.d.ts.map +1 -1
  181. package/dist/types/routes/eventListener.routes.d.ts.map +1 -1
  182. package/dist/types/routes/newsletter.routes.d.ts.map +1 -1
  183. package/dist/types/routes/organization.routes.d.ts.map +1 -1
  184. package/dist/types/routes/project.routes.d.ts.map +1 -1
  185. package/dist/types/schemas/dictionary.schema.d.ts +6 -6
  186. package/dist/types/schemas/discussion.schema.d.ts +6 -6
  187. package/dist/types/schemas/discussion.schema.d.ts.map +1 -1
  188. package/dist/types/schemas/oAuth2.schema.d.ts +5 -5
  189. package/dist/types/schemas/oAuth2.schema.d.ts.map +1 -1
  190. package/dist/types/schemas/organization.schema.d.ts +6 -6
  191. package/dist/types/schemas/plans.schema.d.ts +6 -6
  192. package/dist/types/schemas/plans.schema.d.ts.map +1 -1
  193. package/dist/types/schemas/project.schema.d.ts +6 -6
  194. package/dist/types/schemas/session.schema.d.ts +6 -6
  195. package/dist/types/schemas/tag.schema.d.ts +6 -6
  196. package/dist/types/schemas/user.schema.d.ts +6 -6
  197. package/dist/types/services/email.service.d.ts +10 -10
  198. package/dist/types/utils/accessControl.d.ts +1 -1
  199. package/dist/types/utils/accessControl.d.ts.map +1 -1
  200. package/dist/types/utils/filtersAndPagination/getDictionaryFiltersAndPagination.d.ts +2 -2
  201. package/dist/types/utils/filtersAndPagination/getOrganizationFiltersAndPagination.d.ts +2 -2
  202. package/dist/types/utils/filtersAndPagination/getProjectFiltersAndPagination.d.ts +2 -2
  203. package/dist/types/utils/filtersAndPagination/getTagFiltersAndPagination.d.ts +2 -2
  204. package/dist/types/utils/mongoDB/connectDB.d.ts +2 -2
  205. package/dist/types/utils/mongoDB/connectDB.d.ts.map +1 -1
  206. package/package.json +15 -16
@@ -1,10 +1,7 @@
1
1
  const require_rolldown_runtime = require('./rolldown_runtime.cjs');
2
2
  let node_fs = require("node:fs");
3
- node_fs = require_rolldown_runtime.__toESM(node_fs);
4
3
  let node_path = require("node:path");
5
- node_path = require_rolldown_runtime.__toESM(node_path);
6
4
  let node_url = require("node:url");
7
- node_url = require_rolldown_runtime.__toESM(node_url);
8
5
 
9
6
  //#region \0utils:asset
10
7
  const hereDirname = () => {
@@ -3,7 +3,6 @@ const require_utils_httpStatusCodes = require('../utils/httpStatusCodes.cjs');
3
3
  const require_utils_responseData = require('../utils/responseData.cjs');
4
4
  const require_utils_errors_ErrorHandler = require('../utils/errors/ErrorHandler.cjs');
5
5
  let express_intlayer = require("express-intlayer");
6
- express_intlayer = require_rolldown_runtime.__toESM(express_intlayer);
7
6
  let __services_audit_service = require("@services/audit.service");
8
7
  __services_audit_service = require_rolldown_runtime.__toESM(__services_audit_service);
9
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"audit.controller.cjs","names":["HttpStatusCodes","audit: AuditData","auditService","formatResponse","audits: AuditDocument[]","formatPaginatedResponse"],"sources":["../../../src/controllers/audit.controller.ts"],"sourcesContent":["import type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport * as auditService from '@services/audit.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { HttpStatusCodes } from '@utils/httpStatusCodes';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { Types } from 'mongoose';\nimport type { AuditAPI, AuditData, AuditDocument } from '@/types/audit.types';\n\nexport type CreateAuditBody = AuditData;\nexport type CreateAuditResult = ResponseData<AuditAPI>;\n\n/**\n * Creates a new audit in the database.\n */\nexport const createAudit = async (\n req: Request<any, any, CreateAuditBody>,\n res: ResponseWithSession<CreateAuditResult>,\n _next: NextFunction\n): Promise<void> => {\n const auditData = req.body;\n const auditApiKey = req.headers['x-audit-api-key'];\n\n // Validate API key from environment variable\n if (!process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'AUDIT_API_KEY_NOT_CONFIGURED',\n {\n en: 'Audit API Key Not Configured',\n fr: \"Clé API d'audit non configurée\",\n es: 'Clave API de auditoría no configurada',\n },\n {\n en: 'AUDIT_API_KEY environment variable is not set on the server',\n fr: \"La variable d'environnement AUDIT_API_KEY n'est pas définie sur le serveur\",\n es: 'La variable de entorno AUDIT_API_KEY no está configurada en el servidor',\n },\n undefined,\n HttpStatusCodes.INTERNAL_SERVER_ERROR_500\n );\n return;\n }\n\n if (auditApiKey !== process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'INVALID_AUDIT_API_KEY',\n {\n en: 'Invalid Audit API Key',\n fr: \"Clé API d'audit invalide\",\n es: 'Clave API de auditoría inválida',\n },\n {\n en: 'The provided audit API key is invalid',\n fr: \"La clé API d'audit fournie est invalide\",\n es: 'La clave API de auditoría proporcionada es inválida',\n },\n undefined,\n HttpStatusCodes.UNAUTHORIZED_401\n );\n return;\n }\n\n if (!auditData) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n try {\n // user and project are optional - may be provided if authenticated\n const { user, project } = res.locals;\n const audit: AuditData = {\n ...auditData,\n userId: user?.id,\n projectId: project?.id as Types.ObjectId | undefined,\n };\n\n const newAudit = await auditService.createAudit(audit);\n\n const responseData = formatResponse<AuditAPI>({\n message: t({\n en: 'Audit created successfully',\n fr: 'Audit créé avec succès',\n es: 'Auditoría creada con éxito',\n }),\n description: t({\n en: 'Your audit has been saved successfully',\n fr: 'Votre audit a été enregistré avec succès',\n es: 'Su auditoría ha sido guardada con éxito',\n }),\n data: newAudit.toJSON() as unknown as AuditAPI,\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 GetAuditsParams = {\n page?: number;\n pageSize?: number;\n};\nexport type GetAuditsResult = PaginatedResponse<AuditAPI>;\n\n/**\n * Retrieves audits for the current user or project.\n */\nexport const getAudits = async (\n req: Request<any, any, any, GetAuditsParams>,\n res: ResponseWithSession<GetAuditsResult>,\n _next: NextFunction\n): Promise<void> => {\n const auditApiKey = req.headers['x-audit-api-key'];\n\n // Validate API key from environment variable\n if (!process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'AUDIT_API_KEY_NOT_CONFIGURED',\n {\n en: 'Audit API Key Not Configured',\n fr: \"Clé API d'audit non configurée\",\n es: 'Clave API de auditoría no configurada',\n },\n {\n en: 'AUDIT_API_KEY environment variable is not set on the server',\n fr: \"La variable d'environnement AUDIT_API_KEY n'est pas définie sur le serveur\",\n es: 'La variable de entorno AUDIT_API_KEY no está configurada en el servidor',\n },\n undefined,\n HttpStatusCodes.INTERNAL_SERVER_ERROR_500\n );\n return;\n }\n\n if (auditApiKey !== process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'INVALID_AUDIT_API_KEY',\n {\n en: 'Invalid Audit API Key',\n fr: \"Clé API d'audit invalide\",\n es: 'Clave API de auditoría inválida',\n },\n {\n en: 'The provided audit API key is invalid',\n fr: \"La clé API d'audit fournie est invalide\",\n es: 'La clave API de auditoría proporcionada es inválida',\n },\n undefined,\n HttpStatusCodes.UNAUTHORIZED_401\n );\n return;\n }\n\n try {\n const { user, project } = res.locals;\n const page = Number(req.query.page) || 1;\n const pageSize = Number(req.query.pageSize) || 20;\n const skip = (page - 1) * pageSize;\n\n // If user/project are available, filter by them, otherwise return all audits\n let audits: AuditDocument[];\n if (project) {\n audits = await auditService.findAuditsByProjectId(\n project.id,\n pageSize,\n skip\n );\n } else if (user) {\n audits = await auditService.findAuditsByUserId(user.id, pageSize, skip);\n } else {\n // Return empty array if no user/project context\n audits = [];\n }\n\n const totalItems = audits.length;\n\n const responseData = formatPaginatedResponse<AuditAPI>({\n data: audits.map((audit) => audit.toJSON() as unknown as AuditAPI),\n page,\n pageSize,\n totalPages: Math.ceil(totalItems / pageSize),\n totalItems,\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 GetAuditByIdParams = { auditId: string };\nexport type GetAuditByIdResult = ResponseData<AuditAPI>;\n\n/**\n * Retrieves an audit by its ID.\n */\nexport const getAuditById = async (\n req: Request<GetAuditByIdParams>,\n res: ResponseWithSession<GetAuditByIdResult>,\n _next: NextFunction\n): Promise<void> => {\n const { auditId } = req.params;\n const auditApiKey = req.headers['x-audit-api-key'];\n\n // Validate API key from environment variable\n if (!process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'AUDIT_API_KEY_NOT_CONFIGURED',\n {\n en: 'Audit API Key Not Configured',\n fr: \"Clé API d'audit non configurée\",\n es: 'Clave API de auditoría no configurada',\n },\n {\n en: 'AUDIT_API_KEY environment variable is not set on the server',\n fr: \"La variable d'environnement AUDIT_API_KEY n'est pas définie sur le serveur\",\n es: 'La variable de entorno AUDIT_API_KEY no está configurada en el servidor',\n },\n undefined,\n HttpStatusCodes.INTERNAL_SERVER_ERROR_500\n );\n return;\n }\n\n if (auditApiKey !== process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'INVALID_AUDIT_API_KEY',\n {\n en: 'Invalid Audit API Key',\n fr: \"Clé API d'audit invalide\",\n es: 'Clave API de auditoría inválida',\n },\n {\n en: 'The provided audit API key is invalid',\n fr: \"La clé API d'audit fournie est invalide\",\n es: 'La clave API de auditoría proporcionada es inválida',\n },\n undefined,\n HttpStatusCodes.UNAUTHORIZED_401\n );\n return;\n }\n\n if (!auditId) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n try {\n const audit = await auditService.getAuditById(auditId);\n\n const responseData = formatResponse<AuditAPI>({\n message: t({\n en: 'Audit retrieved successfully',\n fr: 'Audit récupéré avec succès',\n es: 'Auditoría recuperada con éxito',\n }),\n description: t({\n en: 'The audit has been retrieved successfully',\n fr: \"L'audit a été récupéré avec succès\",\n es: 'La auditoría ha sido recuperada con éxito',\n }),\n data: audit.toJSON() as unknown as AuditAPI,\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":"audit.controller.cjs","names":["HttpStatusCodes","audit: AuditData","auditService","formatResponse","audits: AuditDocument[]","formatPaginatedResponse"],"sources":["../../../src/controllers/audit.controller.ts"],"sourcesContent":["import type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport * as auditService from '@services/audit.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { HttpStatusCodes } from '@utils/httpStatusCodes';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { Types } from 'mongoose';\nimport type { AuditAPI, AuditData, AuditDocument } from '@/types/audit.types';\n\nexport type CreateAuditBody = AuditData;\nexport type CreateAuditResult = ResponseData<AuditAPI>;\n\n/**\n * Creates a new audit in the database.\n */\nexport const createAudit = async (\n req: Request<any, any, CreateAuditBody>,\n res: ResponseWithSession<CreateAuditResult>,\n _next: NextFunction\n): Promise<void> => {\n const auditData = req.body;\n const auditApiKey = req.headers['x-audit-api-key'];\n\n // Validate API key from environment variable\n if (!process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'AUDIT_API_KEY_NOT_CONFIGURED',\n {\n en: 'Audit API Key Not Configured',\n fr: \"Clé API d'audit non configurée\",\n es: 'Clave API de auditoría no configurada',\n },\n {\n en: 'AUDIT_API_KEY environment variable is not set on the server',\n fr: \"La variable d'environnement AUDIT_API_KEY n'est pas définie sur le serveur\",\n es: 'La variable de entorno AUDIT_API_KEY no está configurada en el servidor',\n },\n undefined,\n HttpStatusCodes.INTERNAL_SERVER_ERROR_500\n );\n return;\n }\n\n if (auditApiKey !== process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'INVALID_AUDIT_API_KEY',\n {\n en: 'Invalid Audit API Key',\n fr: \"Clé API d'audit invalide\",\n es: 'Clave API de auditoría inválida',\n },\n {\n en: 'The provided audit API key is invalid',\n fr: \"La clé API d'audit fournie est invalide\",\n es: 'La clave API de auditoría proporcionada es inválida',\n },\n undefined,\n HttpStatusCodes.UNAUTHORIZED_401\n );\n return;\n }\n\n if (!auditData) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n try {\n // user and project are optional - may be provided if authenticated\n const { user, project } = res.locals;\n const audit: AuditData = {\n ...auditData,\n userId: user?.id,\n projectId: project?.id as Types.ObjectId | undefined,\n };\n\n const newAudit = await auditService.createAudit(audit);\n\n const responseData = formatResponse<AuditAPI>({\n message: t({\n en: 'Audit created successfully',\n fr: 'Audit créé avec succès',\n es: 'Auditoría creada con éxito',\n }),\n description: t({\n en: 'Your audit has been saved successfully',\n fr: 'Votre audit a été enregistré avec succès',\n es: 'Su auditoría ha sido guardada con éxito',\n }),\n data: newAudit.toJSON() as unknown as AuditAPI,\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 GetAuditsParams = {\n page?: number;\n pageSize?: number;\n};\nexport type GetAuditsResult = PaginatedResponse<AuditAPI>;\n\n/**\n * Retrieves audits for the current user or project.\n */\nexport const getAudits = async (\n req: Request<any, any, any, GetAuditsParams>,\n res: ResponseWithSession<GetAuditsResult>,\n _next: NextFunction\n): Promise<void> => {\n const auditApiKey = req.headers['x-audit-api-key'];\n\n // Validate API key from environment variable\n if (!process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'AUDIT_API_KEY_NOT_CONFIGURED',\n {\n en: 'Audit API Key Not Configured',\n fr: \"Clé API d'audit non configurée\",\n es: 'Clave API de auditoría no configurada',\n },\n {\n en: 'AUDIT_API_KEY environment variable is not set on the server',\n fr: \"La variable d'environnement AUDIT_API_KEY n'est pas définie sur le serveur\",\n es: 'La variable de entorno AUDIT_API_KEY no está configurada en el servidor',\n },\n undefined,\n HttpStatusCodes.INTERNAL_SERVER_ERROR_500\n );\n return;\n }\n\n if (auditApiKey !== process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'INVALID_AUDIT_API_KEY',\n {\n en: 'Invalid Audit API Key',\n fr: \"Clé API d'audit invalide\",\n es: 'Clave API de auditoría inválida',\n },\n {\n en: 'The provided audit API key is invalid',\n fr: \"La clé API d'audit fournie est invalide\",\n es: 'La clave API de auditoría proporcionada es inválida',\n },\n undefined,\n HttpStatusCodes.UNAUTHORIZED_401\n );\n return;\n }\n\n try {\n const { user, project } = res.locals;\n const page = Number(req.query.page) || 1;\n const pageSize = Number(req.query.pageSize) || 20;\n const skip = (page - 1) * pageSize;\n\n // If user/project are available, filter by them, otherwise return all audits\n let audits: AuditDocument[];\n if (project) {\n audits = await auditService.findAuditsByProjectId(\n project.id,\n pageSize,\n skip\n );\n } else if (user) {\n audits = await auditService.findAuditsByUserId(user.id, pageSize, skip);\n } else {\n // Return empty array if no user/project context\n audits = [];\n }\n\n const totalItems = audits.length;\n\n const responseData = formatPaginatedResponse<AuditAPI>({\n data: audits.map((audit) => audit.toJSON() as unknown as AuditAPI),\n page,\n pageSize,\n totalPages: Math.ceil(totalItems / pageSize),\n totalItems,\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 GetAuditByIdParams = { auditId: string };\nexport type GetAuditByIdResult = ResponseData<AuditAPI>;\n\n/**\n * Retrieves an audit by its ID.\n */\nexport const getAuditById = async (\n req: Request<GetAuditByIdParams>,\n res: ResponseWithSession<GetAuditByIdResult>,\n _next: NextFunction\n): Promise<void> => {\n const { auditId } = req.params;\n const auditApiKey = req.headers['x-audit-api-key'];\n\n // Validate API key from environment variable\n if (!process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'AUDIT_API_KEY_NOT_CONFIGURED',\n {\n en: 'Audit API Key Not Configured',\n fr: \"Clé API d'audit non configurée\",\n es: 'Clave API de auditoría no configurada',\n },\n {\n en: 'AUDIT_API_KEY environment variable is not set on the server',\n fr: \"La variable d'environnement AUDIT_API_KEY n'est pas définie sur le serveur\",\n es: 'La variable de entorno AUDIT_API_KEY no está configurada en el servidor',\n },\n undefined,\n HttpStatusCodes.INTERNAL_SERVER_ERROR_500\n );\n return;\n }\n\n if (auditApiKey !== process.env.AUDIT_API_KEY) {\n ErrorHandler.handleCustomErrorResponse(\n res,\n 'INVALID_AUDIT_API_KEY',\n {\n en: 'Invalid Audit API Key',\n fr: \"Clé API d'audit invalide\",\n es: 'Clave API de auditoría inválida',\n },\n {\n en: 'The provided audit API key is invalid',\n fr: \"La clé API d'audit fournie est invalide\",\n es: 'La clave API de auditoría proporcionada es inválida',\n },\n undefined,\n HttpStatusCodes.UNAUTHORIZED_401\n );\n return;\n }\n\n if (!auditId) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n try {\n const audit = await auditService.getAuditById(auditId);\n\n const responseData = formatResponse<AuditAPI>({\n message: t({\n en: 'Audit retrieved successfully',\n fr: 'Audit récupéré avec succès',\n es: 'Auditoría recuperada con éxito',\n }),\n description: t({\n en: 'The audit has been retrieved successfully',\n fr: \"L'audit a été récupéré avec succès\",\n es: 'La auditoría ha sido recuperada con éxito',\n }),\n data: audit.toJSON() as unknown as AuditAPI,\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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"}
@@ -9,7 +9,6 @@ const require_utils_filtersAndPagination_getDictionaryFiltersAndPagination = req
9
9
  const require_utils_mapper_dictionary = require('../utils/mapper/dictionary.cjs');
10
10
  const require_utils_permissions = require('../utils/permissions.cjs');
11
11
  let express_intlayer = require("express-intlayer");
12
- express_intlayer = require_rolldown_runtime.__toESM(express_intlayer);
13
12
 
14
13
  //#region src/controllers/dictionary.controller.ts
15
14
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"dictionary.controller.cjs","names":["getDictionaryFiltersAndPagination","hasPermission","formatPaginatedResponse","mapDictionaryToAPI","formatResponse","dictionary: DictionaryData","newDictionariesResult: DictionaryAPI[]","updatedDictionariesResult: DictionaryAPI[]","errorResult: PushDictionariesResultData['error']","newContent: VersionedContent","ensureMongoDocumentToObject","result: PushDictionariesResultData"],"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["import * as eventListener from '@controllers/eventListener.controller';\nimport type {\n ContentNode,\n Dictionary as LocalDictionary,\n} from '@intlayer/types';\nimport { logger } from '@logger';\nimport type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport * as dictionaryService from '@services/dictionary.service';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport {\n type DictionaryFiltersParams,\n getDictionaryFiltersAndPagination,\n} from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { mapDictionaryToAPI } from '@utils/mapper/dictionary';\nimport { hasPermission } from '@utils/permissions';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\n\nexport type GetDictionariesParams =\n FiltersAndPagination<DictionaryFiltersParams>;\nexport type GetDictionariesResult = PaginatedResponse<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaries = async (\n req: Request<GetDictionariesParams>,\n res: ResponseWithSession<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, roles } = res.locals;\n const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req, res);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries(\n {\n ...filters,\n projectIds: project.id,\n },\n skip,\n pageSize,\n sortOptions\n );\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: dictionaries,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) => mapDictionaryToAPI(el));\n\n const responseData = formatPaginatedResponse<DictionaryAPI>({\n data: dictionariesAPI,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\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 GetDictionariesKeysResult = ResponseData<string[]>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesKeys = async (\n _req: Request,\n res: ResponseWithSession<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, roles } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries({\n projectIds: project.id,\n });\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: dictionaries,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const dictionariesKeys = dictionaries.map((dictionary) => dictionary.key);\n\n const responseData = formatResponse<string[]>({\n data: dictionariesKeys,\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 GetDictionariesUpdateTimestampResult = ResponseData<\n Record<string, number>\n>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesUpdateTimestamp = async (\n _req: Request,\n res: ResponseWithSession<GetDictionariesUpdateTimestampResult>,\n _next: NextFunction\n) => {\n const { project, roles } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries({\n projectIds: project.id,\n });\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: dictionaries,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const dictionariesUpdateTimestamp = dictionaries.reduce(\n (acc, dictionary) => ({\n ...acc,\n [dictionary.key]: new Date(dictionary.updatedAt).getTime(),\n }),\n {}\n );\n\n const responseData = formatResponse<Record<string, number>>({\n data: dictionariesUpdateTimestamp,\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 GetDictionaryParams = { dictionaryKey: string };\nexport type GetDictionaryQuery = { version?: string };\nexport type GetDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaryByKey = async (\n req: Request<GetDictionaryParams, any, any, GetDictionaryQuery>,\n res: ResponseWithSession<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, roles } = res.locals;\n const { dictionaryKey } = req.params;\n const version = req.query.version;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project.id\n );\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: [dictionary],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n if (!dictionary.projectIds.map(String).includes(String(project.id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const apiResult = mapDictionaryToAPI(dictionary, version);\n\n const responseData = formatResponse<DictionaryAPI>({\n data: apiResult,\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 AddDictionaryBody = { dictionary: DictionaryCreationData };\nexport type AddDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Adds a new dictionary to the database.\n */\nexport const addDictionary = async (\n req: Request<any, any, AddDictionaryBody>,\n res: ResponseWithSession<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, roles } = res.locals;\n const dictionaryData = req.body.dictionary;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project.id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n const dictionary: DictionaryData = {\n key: dictionaryData.key,\n title: dictionaryData.title,\n description: dictionaryData.description,\n content: new Map([\n ['v1', { content: dictionaryData.content ?? ({} as ContentNode) }],\n ]),\n creatorId: user.id,\n projectIds: dictionaryData.projectIds ?? [String(project.id)],\n };\n\n if (!hasPermission(roles, 'dictionary:write')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary created successfully',\n fr: 'Dictionnaire créé avec succès',\n es: 'Diccionario creado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been created successfully',\n fr: 'Votre dictionnaire a été créé avec succès',\n es: 'Su diccionario ha sido creado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: mapDictionaryToAPI(newDictionary),\n status: 'ADDED',\n },\n ]);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type PushDictionariesBody = {\n dictionaries: LocalDictionary[];\n};\ntype PushDictionariesResultData = {\n newDictionaries: string[];\n updatedDictionaries: string[];\n error: { dictionaryId: string; message: string }[];\n};\nexport type PushDictionariesResult = ResponseData<PushDictionariesResultData>;\n\n/**\n * Check each dictionaries, add the new ones and update the existing ones.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response containing the created dictionary.\n */\nexport const pushDictionaries = async (\n req: Request<any, any, PushDictionariesBody>,\n res: ResponseWithSession<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, roles } = res.locals;\n const dictionaryData = req.body.dictionaries;\n const dictionariesKeys = dictionaryData.map((dictionary) => dictionary.key);\n\n if (\n typeof dictionaryData === 'object' &&\n Array.isArray(dictionaryData) &&\n dictionaryData.length === 0\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARIES_NOT_PROVIDED');\n return;\n } else if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!hasPermission(roles, 'dictionary:write')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const { existingDictionariesKey, newDictionariesKey } =\n await dictionaryService.getExistingDictionaryKey(\n dictionariesKeys,\n project.id\n );\n\n const existingDictionaries = dictionaryData.filter((dictionary) =>\n existingDictionariesKey.includes(dictionary.key)\n );\n const newDictionaries = dictionaryData.filter((dictionary) =>\n newDictionariesKey.includes(dictionary.key)\n );\n\n const newDictionariesResult: DictionaryAPI[] = [];\n const updatedDictionariesResult: DictionaryAPI[] = [];\n const errorResult: PushDictionariesResultData['error'] = [];\n\n for (const dictionaryDataEl of newDictionaries) {\n const dictionary: DictionaryData = {\n title: dictionaryDataEl.title,\n description: dictionaryDataEl.description,\n projectIds: [String(project.id)],\n creatorId: user.id,\n content: new Map([\n ['v1', { content: dictionaryDataEl.content ?? ({} as ContentNode) }],\n ]),\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(mapDictionaryToAPI(newDictionary));\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n\n if (existingDictionariesKey.length >= 0) {\n const existingDictionariesDB =\n await dictionaryService.getDictionariesByKeys(\n existingDictionariesKey,\n project.id\n );\n\n for (const dictionaryDataEl of existingDictionaries) {\n const existingDictionaryDB = existingDictionariesDB.find(\n (dictionaryDB) => dictionaryDB.key === dictionaryDataEl.key\n )!;\n\n const versionList = [...(existingDictionaryDB.content.keys() ?? [])];\n const lastVersion = versionList[versionList.length - 1];\n\n const lastContent =\n (existingDictionaryDB.content.get(lastVersion)\n ?.content as DictionaryAPI['content']) ?? null;\n\n const isSameContent =\n JSON.stringify(lastContent) ===\n JSON.stringify(dictionaryDataEl.content);\n\n let newContent: VersionedContent = existingDictionaryDB.content;\n\n if (!isSameContent) {\n const newContentVersion =\n dictionaryService.incrementVersion(existingDictionaryDB);\n\n existingDictionaryDB.content.set(newContentVersion, {\n content: dictionaryDataEl.content ?? ({} as ContentNode),\n });\n\n newContent = existingDictionaryDB.content;\n }\n\n const dictionary: DictionaryData = {\n ...ensureMongoDocumentToObject(existingDictionaryDB),\n ...dictionaryDataEl,\n content: newContent,\n projectIds: [String(project.id)],\n creatorId: user.id,\n key: dictionaryDataEl.key,\n };\n\n try {\n const updatedDictionary =\n await dictionaryService.updateDictionaryByKey(\n dictionaryDataEl.key,\n dictionary,\n project.id\n );\n updatedDictionariesResult.push(mapDictionaryToAPI(updatedDictionary));\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n }\n\n const result: PushDictionariesResultData = {\n newDictionaries: newDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n updatedDictionaries: updatedDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n error: errorResult,\n };\n\n const responseData = formatResponse<PushDictionariesResultData>({\n message: t({\n en: 'Dictionaries updated successfully',\n fr: 'Dictionnaires mis à jour avec succès',\n es: 'Diccionarios actualizados con éxito',\n }),\n description: t({\n en: 'Your dictionaries have been updated successfully',\n fr: 'Vos dictionnaires ont été mis à jour avec succès',\n es: 'Sus diccionarios han sido actualizados con éxito',\n }),\n data: result,\n });\n\n eventListener.sendDictionaryUpdate([\n ...newDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'ADDED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\n ...updatedDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'UPDATED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\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 UpdateDictionaryParam = { dictionaryId: string };\nexport type UpdateDictionaryBody = Partial<Dictionary>;\nexport type UpdateDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Updates an existing dictionary in the database.\n */\nexport const updateDictionary = async (\n req: Request<UpdateDictionaryParam, any, UpdateDictionaryBody>,\n res: ResponseWithSession<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, roles } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project.id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (typeof dictionaryId === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!hasPermission(roles, 'dictionary:write')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary updated successfully',\n fr: 'Dictionnaire mis à jour avec succès',\n es: 'Diccionario actualizado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been updated successfully',\n fr: 'Votre dictionnaire a été mis à jour avec succès',\n es: 'Su diccionario ha sido actualizado con éxito',\n }),\n data: apiResult,\n });\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'UPDATED',\n },\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 DeleteDictionaryParam = { dictionaryId: string };\nexport type DeleteDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Deletes a dictionary from the database by its ID.\n */\nexport const deleteDictionary = async (\n req: Request<DeleteDictionaryParam>,\n res: ResponseWithSession<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, roles } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!hasPermission(roles, 'dictionary:admin')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n if (!dictionaryToDelete.projectIds.includes(project.id)) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const deletedDictionary =\n await dictionaryService.deleteDictionaryById(dictionaryId);\n\n if (!deletedDictionary) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_NOT_FOUND', {\n dictionaryId,\n });\n return;\n }\n\n logger.info(`Dictionary deleted: ${String(deletedDictionary.id)}`);\n\n const apiResult = mapDictionaryToAPI(deletedDictionary);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary deleted successfully',\n fr: 'Dictionnaire supprimé avec succès',\n es: 'Diccionario eliminado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been deleted successfully',\n fr: 'Votre dictionnaire a été supprimé avec succès',\n es: 'Su diccionario ha sido eliminado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'DELETED',\n },\n ]);\n\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":"dictionary.controller.cjs","names":["getDictionaryFiltersAndPagination","hasPermission","formatPaginatedResponse","mapDictionaryToAPI","formatResponse","dictionary: DictionaryData","newDictionariesResult: DictionaryAPI[]","updatedDictionariesResult: DictionaryAPI[]","errorResult: PushDictionariesResultData['error']","newContent: VersionedContent","ensureMongoDocumentToObject","result: PushDictionariesResultData"],"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["import * as eventListener from '@controllers/eventListener.controller';\nimport type {\n ContentNode,\n Dictionary as LocalDictionary,\n} from '@intlayer/types';\nimport { logger } from '@logger';\nimport type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport * as dictionaryService from '@services/dictionary.service';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport {\n type DictionaryFiltersParams,\n getDictionaryFiltersAndPagination,\n} from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { mapDictionaryToAPI } from '@utils/mapper/dictionary';\nimport { hasPermission } from '@utils/permissions';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\n\nexport type GetDictionariesParams =\n FiltersAndPagination<DictionaryFiltersParams>;\nexport type GetDictionariesResult = PaginatedResponse<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaries = async (\n req: Request<GetDictionariesParams>,\n res: ResponseWithSession<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, roles } = res.locals;\n const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req, res);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries(\n {\n ...filters,\n projectIds: project.id,\n },\n skip,\n pageSize,\n sortOptions\n );\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: dictionaries,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) => mapDictionaryToAPI(el));\n\n const responseData = formatPaginatedResponse<DictionaryAPI>({\n data: dictionariesAPI,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\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 GetDictionariesKeysResult = ResponseData<string[]>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesKeys = async (\n _req: Request,\n res: ResponseWithSession<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, roles } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries({\n projectIds: project.id,\n });\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: dictionaries,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const dictionariesKeys = dictionaries.map((dictionary) => dictionary.key);\n\n const responseData = formatResponse<string[]>({\n data: dictionariesKeys,\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 GetDictionariesUpdateTimestampResult = ResponseData<\n Record<string, number>\n>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesUpdateTimestamp = async (\n _req: Request,\n res: ResponseWithSession<GetDictionariesUpdateTimestampResult>,\n _next: NextFunction\n) => {\n const { project, roles } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries({\n projectIds: project.id,\n });\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: dictionaries,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const dictionariesUpdateTimestamp = dictionaries.reduce(\n (acc, dictionary) => ({\n ...acc,\n [dictionary.key]: new Date(dictionary.updatedAt).getTime(),\n }),\n {}\n );\n\n const responseData = formatResponse<Record<string, number>>({\n data: dictionariesUpdateTimestamp,\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 GetDictionaryParams = { dictionaryKey: string };\nexport type GetDictionaryQuery = { version?: string };\nexport type GetDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaryByKey = async (\n req: Request<GetDictionaryParams, any, any, GetDictionaryQuery>,\n res: ResponseWithSession<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, roles } = res.locals;\n const { dictionaryKey } = req.params;\n const version = req.query.version;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project.id\n );\n\n if (\n !hasPermission(\n roles,\n 'dictionary:read'\n )({\n ...res.locals,\n targetDictionaries: [dictionary],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n if (!dictionary.projectIds.map(String).includes(String(project.id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const apiResult = mapDictionaryToAPI(dictionary, version);\n\n const responseData = formatResponse<DictionaryAPI>({\n data: apiResult,\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 AddDictionaryBody = { dictionary: DictionaryCreationData };\nexport type AddDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Adds a new dictionary to the database.\n */\nexport const addDictionary = async (\n req: Request<any, any, AddDictionaryBody>,\n res: ResponseWithSession<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, roles } = res.locals;\n const dictionaryData = req.body.dictionary;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project.id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n const dictionary: DictionaryData = {\n key: dictionaryData.key,\n title: dictionaryData.title,\n description: dictionaryData.description,\n content: new Map([\n ['v1', { content: dictionaryData.content ?? ({} as ContentNode) }],\n ]),\n creatorId: user.id,\n projectIds: dictionaryData.projectIds ?? [String(project.id)],\n };\n\n if (!hasPermission(roles, 'dictionary:write')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary created successfully',\n fr: 'Dictionnaire créé avec succès',\n es: 'Diccionario creado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been created successfully',\n fr: 'Votre dictionnaire a été créé avec succès',\n es: 'Su diccionario ha sido creado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: mapDictionaryToAPI(newDictionary),\n status: 'ADDED',\n },\n ]);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type PushDictionariesBody = {\n dictionaries: LocalDictionary[];\n};\ntype PushDictionariesResultData = {\n newDictionaries: string[];\n updatedDictionaries: string[];\n error: { dictionaryId: string; message: string }[];\n};\nexport type PushDictionariesResult = ResponseData<PushDictionariesResultData>;\n\n/**\n * Check each dictionaries, add the new ones and update the existing ones.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response containing the created dictionary.\n */\nexport const pushDictionaries = async (\n req: Request<any, any, PushDictionariesBody>,\n res: ResponseWithSession<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, roles } = res.locals;\n const dictionaryData = req.body.dictionaries;\n const dictionariesKeys = dictionaryData.map((dictionary) => dictionary.key);\n\n if (\n typeof dictionaryData === 'object' &&\n Array.isArray(dictionaryData) &&\n dictionaryData.length === 0\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARIES_NOT_PROVIDED');\n return;\n } else if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!hasPermission(roles, 'dictionary:write')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const { existingDictionariesKey, newDictionariesKey } =\n await dictionaryService.getExistingDictionaryKey(\n dictionariesKeys,\n project.id\n );\n\n const existingDictionaries = dictionaryData.filter((dictionary) =>\n existingDictionariesKey.includes(dictionary.key)\n );\n const newDictionaries = dictionaryData.filter((dictionary) =>\n newDictionariesKey.includes(dictionary.key)\n );\n\n const newDictionariesResult: DictionaryAPI[] = [];\n const updatedDictionariesResult: DictionaryAPI[] = [];\n const errorResult: PushDictionariesResultData['error'] = [];\n\n for (const dictionaryDataEl of newDictionaries) {\n const dictionary: DictionaryData = {\n title: dictionaryDataEl.title,\n description: dictionaryDataEl.description,\n projectIds: [String(project.id)],\n creatorId: user.id,\n content: new Map([\n ['v1', { content: dictionaryDataEl.content ?? ({} as ContentNode) }],\n ]),\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(mapDictionaryToAPI(newDictionary));\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n\n if (existingDictionariesKey.length >= 0) {\n const existingDictionariesDB =\n await dictionaryService.getDictionariesByKeys(\n existingDictionariesKey,\n project.id\n );\n\n for (const dictionaryDataEl of existingDictionaries) {\n const existingDictionaryDB = existingDictionariesDB.find(\n (dictionaryDB) => dictionaryDB.key === dictionaryDataEl.key\n )!;\n\n const versionList = [...(existingDictionaryDB.content.keys() ?? [])];\n const lastVersion = versionList[versionList.length - 1];\n\n const lastContent =\n (existingDictionaryDB.content.get(lastVersion)\n ?.content as DictionaryAPI['content']) ?? null;\n\n const isSameContent =\n JSON.stringify(lastContent) ===\n JSON.stringify(dictionaryDataEl.content);\n\n let newContent: VersionedContent = existingDictionaryDB.content;\n\n if (!isSameContent) {\n const newContentVersion =\n dictionaryService.incrementVersion(existingDictionaryDB);\n\n existingDictionaryDB.content.set(newContentVersion, {\n content: dictionaryDataEl.content ?? ({} as ContentNode),\n });\n\n newContent = existingDictionaryDB.content;\n }\n\n const dictionary: DictionaryData = {\n ...ensureMongoDocumentToObject(existingDictionaryDB),\n ...dictionaryDataEl,\n content: newContent,\n projectIds: [String(project.id)],\n creatorId: user.id,\n key: dictionaryDataEl.key,\n };\n\n try {\n const updatedDictionary =\n await dictionaryService.updateDictionaryByKey(\n dictionaryDataEl.key,\n dictionary,\n project.id\n );\n updatedDictionariesResult.push(mapDictionaryToAPI(updatedDictionary));\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n }\n\n const result: PushDictionariesResultData = {\n newDictionaries: newDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n updatedDictionaries: updatedDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n error: errorResult,\n };\n\n const responseData = formatResponse<PushDictionariesResultData>({\n message: t({\n en: 'Dictionaries updated successfully',\n fr: 'Dictionnaires mis à jour avec succès',\n es: 'Diccionarios actualizados con éxito',\n }),\n description: t({\n en: 'Your dictionaries have been updated successfully',\n fr: 'Vos dictionnaires ont été mis à jour avec succès',\n es: 'Sus diccionarios han sido actualizados con éxito',\n }),\n data: result,\n });\n\n eventListener.sendDictionaryUpdate([\n ...newDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'ADDED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\n ...updatedDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'UPDATED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\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 UpdateDictionaryParam = { dictionaryId: string };\nexport type UpdateDictionaryBody = Partial<Dictionary>;\nexport type UpdateDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Updates an existing dictionary in the database.\n */\nexport const updateDictionary = async (\n req: Request<UpdateDictionaryParam, any, UpdateDictionaryBody>,\n res: ResponseWithSession<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, roles } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project.id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (typeof dictionaryId === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!hasPermission(roles, 'dictionary:write')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary updated successfully',\n fr: 'Dictionnaire mis à jour avec succès',\n es: 'Diccionario actualizado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been updated successfully',\n fr: 'Votre dictionnaire a été mis à jour avec succès',\n es: 'Su diccionario ha sido actualizado con éxito',\n }),\n data: apiResult,\n });\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'UPDATED',\n },\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 DeleteDictionaryParam = { dictionaryId: string };\nexport type DeleteDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Deletes a dictionary from the database by its ID.\n */\nexport const deleteDictionary = async (\n req: Request<DeleteDictionaryParam>,\n res: ResponseWithSession<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, roles } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!hasPermission(roles, 'dictionary:admin')(res.locals)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n if (!dictionaryToDelete.projectIds.includes(project.id)) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const deletedDictionary =\n await dictionaryService.deleteDictionaryById(dictionaryId);\n\n if (!deletedDictionary) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_NOT_FOUND', {\n dictionaryId,\n });\n return;\n }\n\n logger.info(`Dictionary deleted: ${String(deletedDictionary.id)}`);\n\n const apiResult = mapDictionaryToAPI(deletedDictionary);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary deleted successfully',\n fr: 'Dictionnaire supprimé avec succès',\n es: 'Diccionario eliminado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been deleted successfully',\n fr: 'Votre dictionnaire a été supprimé avec succès',\n es: 'Su diccionario ha sido eliminado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'DELETED',\n },\n ]);\n\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAwCA,MAAa,kBAAkB,OAC7B,KACA,KACA,UACkB;CAClB,MAAM,EAAE,MAAM,SAAS,UAAU,IAAI;CACrC,MAAM,EAAE,SAAS,aAAa,UAAU,MAAM,MAAM,qBAClDA,uGAAkC,KAAK,IAAI;AAE7C,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI,CAAC,MAAM;AACT,iDAAa,2BAA2B,KAAK,mBAAmB;AAChE;;AAGF,KAAI;EACF,MAAM,eAAe,2DACnB;GACE,GAAG;GACH,YAAY,QAAQ;GACrB,EACD,MACA,UACA,YACD;AAED,MACE,CAACC,wCACC,OACA,kBACD,CAAC;GACA,GAAG,IAAI;GACP,oBAAoB;GACrB,CAAC,EACF;AACA,kDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;EAGF,MAAM,aAAa,4DAA0C,QAAQ;EAIrE,MAAM,eAAeC,mDAAuC;GAC1D,MAHsB,aAAa,KAAK,OAAOC,mDAAmB,GAAG,CAAC;GAItE;GACA;GACA,YAAY,iBAAiB,WAAW;GACxC;GACD,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;AASJ,MAAa,sBAAsB,OACjC,MACA,KACA,UACG;CACH,MAAM,EAAE,SAAS,UAAU,IAAI;AAE/B,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI;EACF,MAAM,eAAe,2DAAyC,EAC5D,YAAY,QAAQ,IACrB,CAAC;AAEF,MACE,CAACF,wCACC,OACA,kBACD,CAAC;GACA,GAAG,IAAI;GACP,oBAAoB;GACrB,CAAC,EACF;AACA,kDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;EAKF,MAAM,eAAeG,0CAAyB,EAC5C,MAHuB,aAAa,KAAK,eAAe,WAAW,IAAI,EAIxE,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;AAWJ,MAAa,iCAAiC,OAC5C,MACA,KACA,UACG;CACH,MAAM,EAAE,SAAS,UAAU,IAAI;AAE/B,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI;EACF,MAAM,eAAe,2DAAyC,EAC5D,YAAY,QAAQ,IACrB,CAAC;AAEF,MACE,CAACH,wCACC,OACA,kBACD,CAAC;GACA,GAAG,IAAI;GACP,oBAAoB;GACrB,CAAC,EACF;AACA,kDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;EAWF,MAAM,eAAeG,0CAAuC,EAC1D,MATkC,aAAa,QAC9C,KAAK,gBAAgB;GACpB,GAAG;IACF,WAAW,MAAM,IAAI,KAAK,WAAW,UAAU,CAAC,SAAS;GAC3D,GACD,EAAE,CACH,EAIA,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;AAWJ,MAAa,qBAAqB,OAChC,KACA,KACA,UACkB;CAClB,MAAM,EAAE,SAAS,MAAM,UAAU,IAAI;CACrC,MAAM,EAAE,kBAAkB,IAAI;CAC9B,MAAM,UAAU,IAAI,MAAM;AAE1B,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAEF,KAAI,CAAC,MAAM;AACT,iDAAa,2BAA2B,KAAK,mBAAmB;AAChE;;AAGF,KAAI;EACF,MAAM,aAAa,6DACjB,eACA,QAAQ,GACT;AAED,MACE,CAACH,wCACC,OACA,kBACD,CAAC;GACA,GAAG,IAAI;GACP,oBAAoB,CAAC,WAAW;GACjC,CAAC,EACF;AACA,kDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;AAGF,MAAI,CAAC,WAAW,WAAW,IAAI,OAAO,CAAC,SAAS,OAAO,QAAQ,GAAG,CAAC,EAAE;AACnE,kDAAa,2BACX,KACA,8BACD;AACD;;EAKF,MAAM,eAAeG,0CAA8B,EACjD,MAHgBD,mDAAmB,YAAY,QAAQ,EAIxD,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;AAUJ,MAAa,gBAAgB,OAC3B,KACA,KACA,UACkB;CAClB,MAAM,EAAE,SAAS,MAAM,UAAU,IAAI;CACrC,MAAM,iBAAiB,IAAI,KAAK;AAEhC,KAAI,CAAC,gBAAgB;AACnB,iDAAa,2BAA2B,KAAK,4BAA4B;AACzE;;AAGF,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI,CAAC,MAAM;AACT,iDAAa,2BAA2B,KAAK,mBAAmB;AAChE;;AAGF,KAAI,CAAC,eAAe,YAAY,SAAS,OAAO,QAAQ,GAAG,CAAC,EAAE;AAC5D,iDAAa,2BAA2B,KAAK,8BAA8B;AAC3E;;CAGF,MAAME,aAA6B;EACjC,KAAK,eAAe;EACpB,OAAO,eAAe;EACtB,aAAa,eAAe;EAC5B,SAAS,IAAI,IAAI,CACf,CAAC,MAAM,EAAE,SAAS,eAAe,WAAY,EAAE,EAAkB,CAAC,CACnE,CAAC;EACF,WAAW,KAAK;EAChB,YAAY,eAAe,cAAc,CAAC,OAAO,QAAQ,GAAG,CAAC;EAC9D;AAED,KAAI,CAACJ,wCAAc,OAAO,mBAAmB,CAAC,IAAI,OAAO,EAAE;AACzD,iDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;AAGF,KAAI;EACF,MAAM,gBAAgB,2DAAyC,WAAW;EAE1E,MAAM,YAAYE,mDAAmB,cAAc;EAEnD,MAAM,eAAeC,0CAA8B;GACjD,iCAAW;IACT,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,qCAAe;IACb,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,MAAM;GACP,CAAC;AAEF,MAAI,KAAK,aAAa;AAEtB,oEAAmC,CACjC;GACE,YAAYD,mDAAmB,cAAc;GAC7C,QAAQ;GACT,CACF,CAAC;AACF;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;;;;AAoBJ,MAAa,mBAAmB,OAC9B,KACA,KACA,UACkB;CAClB,MAAM,EAAE,SAAS,MAAM,UAAU,IAAI;CACrC,MAAM,iBAAiB,IAAI,KAAK;CAChC,MAAM,mBAAmB,eAAe,KAAK,eAAe,WAAW,IAAI;AAE3E,KACE,OAAO,mBAAmB,YAC1B,MAAM,QAAQ,eAAe,IAC7B,eAAe,WAAW,GAC1B;AACA,iDAAa,2BAA2B,KAAK,4BAA4B;AACzE;YACS,CAAC,gBAAgB;AAC1B,iDAAa,2BAA2B,KAAK,4BAA4B;AACzE;;AAGF,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI,CAAC,MAAM;AACT,iDAAa,2BAA2B,KAAK,mBAAmB;AAChE;;AAGF,KAAI,CAACF,wCAAc,OAAO,mBAAmB,CAAC,IAAI,OAAO,EAAE;AACzD,iDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;AAGF,KAAI;EACF,MAAM,EAAE,yBAAyB,uBAC/B,mEACE,kBACA,QAAQ,GACT;EAEH,MAAM,uBAAuB,eAAe,QAAQ,eAClD,wBAAwB,SAAS,WAAW,IAAI,CACjD;EACD,MAAM,kBAAkB,eAAe,QAAQ,eAC7C,mBAAmB,SAAS,WAAW,IAAI,CAC5C;EAED,MAAMK,wBAAyC,EAAE;EACjD,MAAMC,4BAA6C,EAAE;EACrD,MAAMC,cAAmD,EAAE;AAE3D,OAAK,MAAM,oBAAoB,iBAAiB;GAC9C,MAAMH,aAA6B;IACjC,OAAO,iBAAiB;IACxB,aAAa,iBAAiB;IAC9B,YAAY,CAAC,OAAO,QAAQ,GAAG,CAAC;IAChC,WAAW,KAAK;IAChB,SAAS,IAAI,IAAI,CACf,CAAC,MAAM,EAAE,SAAS,iBAAiB,WAAY,EAAE,EAAkB,CAAC,CACrE,CAAC;IACF,KAAK,iBAAiB;IACvB;AAED,OAAI;IACF,MAAM,gBACJ,2DAAyC,WAAW;AACtD,0BAAsB,KAAKF,mDAAmB,cAAc,CAAC;YACtD,OAAO;AACd,mDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;AAIJ,MAAI,wBAAwB,UAAU,GAAG;GACvC,MAAM,yBACJ,gEACE,yBACA,QAAQ,GACT;AAEH,QAAK,MAAM,oBAAoB,sBAAsB;IACnD,MAAM,uBAAuB,uBAAuB,MACjD,iBAAiB,aAAa,QAAQ,iBAAiB,IACzD;IAED,MAAM,cAAc,CAAC,GAAI,qBAAqB,QAAQ,MAAM,IAAI,EAAE,CAAE;IACpE,MAAM,cAAc,YAAY,YAAY,SAAS;IAErD,MAAM,cACH,qBAAqB,QAAQ,IAAI,YAAY,EAC1C,WAAwC;IAE9C,MAAM,gBACJ,KAAK,UAAU,YAAY,KAC3B,KAAK,UAAU,iBAAiB,QAAQ;IAE1C,IAAIM,aAA+B,qBAAqB;AAExD,QAAI,CAAC,eAAe;KAClB,MAAM,yEAC+B,qBAAqB;AAE1D,0BAAqB,QAAQ,IAAI,mBAAmB,EAClD,SAAS,iBAAiB,WAAY,EAAE,EACzC,CAAC;AAEF,kBAAa,qBAAqB;;IAGpC,MAAMJ,aAA6B;KACjC,GAAGK,sEAA4B,qBAAqB;KACpD,GAAG;KACH,SAAS;KACT,YAAY,CAAC,OAAO,QAAQ,GAAG,CAAC;KAChC,WAAW,KAAK;KAChB,KAAK,iBAAiB;KACvB;AAED,QAAI;KACF,MAAM,oBACJ,gEACE,iBAAiB,KACjB,YACA,QAAQ,GACT;AACH,+BAA0B,KAAKP,mDAAmB,kBAAkB,CAAC;aAC9D,OAAO;AACd,oDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;EAKN,MAAMQ,SAAqC;GACzC,iBAAiB,sBAAsB,KACpC,eAAe,WAAW,IAC5B;GACD,qBAAqB,0BAA0B,KAC5C,eAAe,WAAW,IAC5B;GACD,OAAO;GACR;EAED,MAAM,eAAeP,0CAA2C;GAC9D,iCAAW;IACT,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,qCAAe;IACb,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,MAAM;GACP,CAAC;AAEF,oEAAmC,CACjC,GAAG,sBAAsB,KACtB,gBACE;GACC;GACA,QAAQ;GACT,EACJ,EACD,GAAG,0BAA0B,KAC1B,gBACE;GACC;GACA,QAAQ;GACT,EACJ,CACF,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;AAWJ,MAAa,mBAAmB,OAC9B,KACA,KACA,UACkB;CAClB,MAAM,EAAE,iBAAiB,IAAI;CAC7B,MAAM,EAAE,SAAS,UAAU,IAAI;CAC/B,MAAM,iBAAiB,IAAI;AAE3B,KAAI,CAAC,gBAAgB;AACnB,iDAAa,2BAA2B,KAAK,4BAA4B;AACzE;;AAGF,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI,CAAC,eAAe,YAAY,SAAS,OAAO,QAAQ,GAAG,CAAC,EAAE;AAC5D,iDAAa,2BAA2B,KAAK,8BAA8B;AAC3E;;AAGF,KAAI,OAAO,iBAAiB,aAAa;AACvC,iDAAa,2BAA2B,KAAK,0BAA0B;AACvE;;AAGF,KAAI,CAACH,wCAAc,OAAO,mBAAmB,CAAC,IAAI,OAAO,EAAE;AACzD,iDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;AAGF,KAAI;EAMF,MAAM,YAAYE,mDALQ,+DACxB,cACA,eACD,CAEsD;EAEvD,MAAM,eAAeC,0CAA8B;GACjD,iCAAW;IACT,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,qCAAe;IACb,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,MAAM;GACP,CAAC;AAEF,oEAAmC,CACjC;GACE,YAAY;GACZ,QAAQ;GACT,CACF,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D;;;;;;AAUJ,MAAa,mBAAmB,OAC9B,KACA,KACA,UACkB;CAClB,MAAM,EAAE,SAAS,UAAU,IAAI;CAC/B,MAAM,EAAE,iBAAiB,IAAI;AAE7B,KAAI,CAAC,cAAc;AACjB,iDAAa,2BAA2B,KAAK,0BAA0B;AACvE;;AAGF,KAAI,CAAC,SAAS;AACZ,iDAAa,2BAA2B,KAAK,sBAAsB;AACnE;;AAGF,KAAI,CAACH,wCAAc,OAAO,mBAAmB,CAAC,IAAI,OAAO,EAAE;AACzD,iDAAa,2BAA2B,KAAK,oBAAoB;AACjE;;AAGF,KAAI;AAIF,MAAI,EAFF,4DAA0C,aAAa,EAEjC,WAAW,SAAS,QAAQ,GAAG,EAAE;AACvD,kDAAa,2BACX,KACA,8BACD;AACD;;EAGF,MAAM,oBACJ,+DAA6C,aAAa;AAE5D,MAAI,CAAC,mBAAmB;AACtB,kDAAa,2BAA2B,KAAK,wBAAwB,EACnE,cACD,CAAC;AACF;;AAGF,8BAAO,KAAK,uBAAuB,OAAO,kBAAkB,GAAG,GAAG;EAElE,MAAM,YAAYE,mDAAmB,kBAAkB;EAEvD,MAAM,eAAeC,0CAA8B;GACjD,iCAAW;IACT,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,qCAAe;IACb,IAAI;IACJ,IAAI;IACJ,IAAI;IACL,CAAC;GACF,MAAM;GACP,CAAC;AAEF,MAAI,KAAK,aAAa;AAEtB,oEAAmC,CACjC;GACE,YAAY;GACZ,QAAQ;GACT,CACF,CAAC;AAEF;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D"}
@@ -6,7 +6,6 @@ const require_utils_permissions = require('../utils/permissions.cjs');
6
6
  const require_services_user_service = require('../services/user.service.cjs');
7
7
  const require_utils_mapper_user = require('../utils/mapper/user.cjs');
8
8
  let express_intlayer = require("express-intlayer");
9
- express_intlayer = require_rolldown_runtime.__toESM(express_intlayer);
10
9
 
11
10
  //#region src/controllers/newsletter.controller.ts
12
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"newsletter.controller.cjs","names":["hasPermission","mapUserToAPI","formatResponse"],"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.cjs","names":["hasPermission","mapUserToAPI","formatResponse"],"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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"}
@@ -2,7 +2,6 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
2
  const require_utils_responseData = require('../utils/responseData.cjs');
3
3
  const require_utils_errors_ErrorHandler = require('../utils/errors/ErrorHandler.cjs');
4
4
  let oauth2_server = require("oauth2-server");
5
- oauth2_server = require_rolldown_runtime.__toESM(oauth2_server);
6
5
 
7
6
  //#region src/controllers/oAuth2.controller.ts
8
7
  const getOAuth2AccessToken = async (req, res, _next) => {
@@ -1 +1 @@
1
- {"version":3,"file":"oAuth2.controller.cjs","names":["OAuthRequest","OAuthResponse","formatResponse"],"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,sBAAa,IAAI;CAC1C,MAAM,gBAAgB,IAAIC,uBAAc,IAAI;AAE5C,KAAI;EASF,MAAM,eAAeC,0CAA4B,EAC/C,MAT0B,MAC1B,IAKA,MAAM,MAAM,cAAc,cAAc,EAIzC,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D"}
1
+ {"version":3,"file":"oAuth2.controller.cjs","names":["OAuthRequest","OAuthResponse","formatResponse"],"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,sBAAa,IAAI;CAC1C,MAAM,gBAAgB,IAAIC,uBAAc,IAAI;AAE5C,KAAI;EASF,MAAM,eAAeC,0CAA4B,EAC/C,MAT0B,MAC1B,IAKA,MAAM,MAAM,cAAc,cAAc,EAIzC,CAAC;AAEF,MAAI,KAAK,aAAa;AACtB;UACO,OAAO;AACd,iDAAa,uBAAuB,KAAK,MAAkB;AAC3D"}
@@ -12,9 +12,7 @@ const require_utils_filtersAndPagination_getOrganizationFiltersAndPagination = r
12
12
  const require_utils_mapper_organization = require('../utils/mapper/organization.cjs');
13
13
  const require_utils_plan = require('../utils/plan.cjs');
14
14
  let express_intlayer = require("express-intlayer");
15
- express_intlayer = require_rolldown_runtime.__toESM(express_intlayer);
16
15
  let stripe = require("stripe");
17
- stripe = require_rolldown_runtime.__toESM(stripe);
18
16
 
19
17
  //#region src/controllers/organization.controller.ts
20
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"organization.controller.cjs","names":["getOrganizationFiltersAndPagination","hasPermission","formatPaginatedResponse","mapOrganizationsToAPI","formatResponse","mapOrganizationToAPI","getPlanDetails","sendEmail","user","stripe","Stripe","SessionModel"],"sources":["../../../src/controllers/organization.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport { SessionModel } from '@models/session.model';\nimport { sendEmail } from '@services/email.service';\nimport * as organizationService from '@services/organization.service';\nimport * as projectService from '@services/project.service';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getOrganizationFiltersAndPagination,\n type OrganizationFiltersParams,\n} from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport {\n mapOrganizationsToAPI,\n mapOrganizationToAPI,\n} from '@utils/mapper/organization';\nimport { hasPermission } from '@utils/permissions';\nimport { getPlanDetails } from '@utils/plan';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { Types } from 'mongoose';\nimport { Stripe } from 'stripe';\nimport type {\n Organization,\n OrganizationAPI,\n OrganizationCreationData,\n} from '@/types/organization.types';\nimport type { User, UserAPI } from '@/types/user.types';\n\nexport type GetOrganizationsParams =\n FiltersAndPagination<OrganizationFiltersParams>;\nexport type GetOrganizationsResult = PaginatedResponse<OrganizationAPI>;\n\n/**\n * Retrieves a list of organizations based on filters and pagination.\n */\nexport const getOrganizations = async (\n req: Request<GetOrganizationsParams>,\n res: ResponseWithSession<GetOrganizationsResult>,\n _next: NextFunction\n) => {\n const { user, roles } = res.locals;\n const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req, res);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const organizations = await organizationService.findOrganizations(\n filters,\n skip,\n pageSize,\n sortOptions\n );\n\n if (\n !hasPermission(\n roles,\n 'organization:read'\n )({\n ...res.locals,\n targetOrganizations: organizations,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const totalItems = await organizationService.countOrganizations(filters);\n\n const responseData = formatPaginatedResponse<OrganizationAPI>({\n data: mapOrganizationsToAPI(organizations),\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.status(200).json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetOrganizationParam = { organizationId: string };\nexport type GetOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Retrieves an organization by its ID.\n */\nexport const getOrganization = async (\n req: Request<GetOrganizationParam, any, any>,\n res: ResponseWithSession<GetOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { roles } = res.locals;\n const { organizationId } = req.params as Partial<GetOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n if (\n !hasPermission(\n roles,\n 'organization:read'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const responseData = formatResponse<OrganizationAPI>({\n data: mapOrganizationToAPI(organization),\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 AddOrganizationBody = OrganizationCreationData;\nexport type AddOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Adds a new organization to the database.\n */\nexport const addOrganization = async (\n req: Request<any, any, AddOrganizationBody>,\n res: ResponseWithSession<AddOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const organization = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newOrganization = await organizationService.createOrganization(\n organization,\n user.id\n );\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization created successfully',\n fr: 'Organisation créée avec succès',\n es: 'Organización creada con éxito',\n }),\n description: t({\n en: 'Your organization has been created successfully',\n fr: 'Votre organisation a été créée avec succès',\n es: 'Su organización ha sido creada con éxito',\n }),\n data: mapOrganizationToAPI(newOrganization),\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 UpdateOrganizationBody = Partial<Organization>;\nexport type UpdateOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Updates an existing organization in the database.\n */\nexport const updateOrganization = async (\n req: Request<undefined, undefined, UpdateOrganizationBody>,\n res: ResponseWithSession<UpdateOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, roles } = res.locals;\n const organizationFields = req.body;\n\n if (!organizationFields) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:write'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const updatedOrganization =\n await organizationService.updateOrganizationById(\n organization.id,\n organizationFields\n );\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\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 AddOrganizationMemberBody = {\n userEmail: string;\n};\nexport type AddOrganizationMemberResult = ResponseData<OrganizationAPI>;\n\n/**\n * Add member to the organization in the database.\n */\nexport const addOrganizationMember = async (\n req: Request<any, any, AddOrganizationMemberBody>,\n res: ResponseWithSession<AddOrganizationMemberResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, user, roles } = res.locals;\n const { userEmail } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:admin'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const planType = getPlanDetails(organization.plan);\n\n if (\n planType.numberOfOrganizationUsers &&\n organization.membersIds.length >= planType.numberOfOrganizationUsers\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_USER_LIMIT_REACHED', {\n organizationId: organization.id,\n });\n return;\n }\n\n try {\n let newMember = await userService.getUserByEmail(userEmail);\n\n if (!newMember) {\n // Create user if not found\n const newUser = await userService.createUser({ email: userEmail });\n if (!newUser) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_CREATION_FAILED', {\n email: userEmail,\n });\n return;\n }\n\n newMember = newUser;\n }\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization.id, {\n ...organization,\n membersIds: [...organization.membersIds, newMember.id],\n });\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\n });\n\n res.json(responseData);\n\n await sendEmail({\n type: 'invite',\n to: userEmail,\n username: newMember.email.slice(0, newMember.email.indexOf('@')),\n invitedByUsername: user.name,\n invitedByEmail: user.email,\n organizationName: organization.name,\n inviteLink: `${process.env.CLIENT_URL}/auth/login?email=${newMember.email}`,\n inviteFromIp: req.ip ?? '',\n inviteFromLocation: req.hostname,\n });\n\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationMembersBody = Partial<{\n membersIds: (User | UserAPI)['id'][];\n adminsIds: (User | UserAPI)['id'][];\n}>;\nexport type UpdateOrganizationMembersResult = ResponseData<OrganizationAPI>;\n\n/**\n * Update members to the organization in the database.\n */\nexport const updateOrganizationMembers = async (\n req: Request<any, any, UpdateOrganizationMembersBody>,\n res: ResponseWithSession<UpdateOrganizationMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, roles } = res.locals;\n const { membersIds, adminsIds } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:admin'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n if (!membersIds) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n if (adminsIds?.filter((id) => membersIds?.includes(id)).length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n try {\n const existingUsers = await userService.getUsersByIds(membersIds);\n\n if (!existingUsers) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const existingAdmins = await userService.getUsersByIds(adminsIds!);\n\n if (!existingAdmins) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization.id, {\n membersIds: existingUsers.map((user) => user.id),\n adminsIds: existingAdmins.map((user) => user.id),\n });\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\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 UpdateOrganizationMembersByIdParams = { organizationId: string };\nexport type UpdateOrganizationMembersByIdBody = Partial<{\n membersIds: (User | UserAPI)['id'][];\n adminsIds: (User | UserAPI)['id'][];\n}>;\nexport type UpdateOrganizationMembersByIdResult = ResponseData<OrganizationAPI>;\n\n/**\n * Admin-only: Update members of any organization by ID\n */\nexport const updateOrganizationMembersById = async (\n req: Request<\n UpdateOrganizationMembersByIdParams,\n any,\n UpdateOrganizationMembersByIdBody\n >,\n res: ResponseWithSession<UpdateOrganizationMembersByIdResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const { organizationId } = req.params;\n const { membersIds, adminsIds } = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (user.role !== 'admin') {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n if (!membersIds) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n try {\n const targetOrganization =\n await organizationService.getOrganizationById(organizationId);\n\n if (!targetOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n const existingUsers = await userService.getUsersByIds(membersIds);\n\n if (!existingUsers) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const finalAdminsIds =\n adminsIds && adminsIds.length > 0\n ? adminsIds\n : targetOrganization.adminsIds;\n const existingAdmins = finalAdminsIds\n ? await userService.getUsersByIds(finalAdminsIds)\n : [];\n\n if (!existingAdmins || existingAdmins.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(targetOrganization.id, {\n membersIds: existingUsers.map((user) => user.id),\n adminsIds: existingAdmins.map((user) => user.id),\n });\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization members updated successfully',\n fr: \"Membres de l'organisation mis à jour avec succès\",\n es: 'Miembros de la organización actualizados con éxito',\n }),\n description: t({\n en: 'Organization members have been updated successfully',\n fr: \"Les membres de l'organisation ont été mis à jour avec succès\",\n es: 'Los miembros de la organización han sido actualizados con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\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 DeleteOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Deletes an organization from the database by its ID.\n */\nexport const deleteOrganization = async (\n _req: Request,\n res: ResponseWithSession,\n _next: NextFunction\n): Promise<void> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const { organization, roles } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n const projects = await projectService.findProjects({\n organizationId: organization.id,\n });\n\n if (projects.length > 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECTS_EXIST', {\n organizationId: organization.id,\n });\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:admin'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n // Cancel the subscription on Stripe if it exists\n if (organization.plan?.subscriptionId) {\n await stripe.subscriptions.cancel(organization.plan.subscriptionId);\n }\n\n const deletedOrganization =\n await organizationService.deleteOrganizationById(organization.id);\n\n if (!deletedOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND', {\n organizationId: organization.id,\n });\n return;\n }\n\n logger.info(`Organization deleted: ${String(deletedOrganization.id)}`);\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization deleted successfully',\n fr: 'Organisation supprimée avec succès',\n es: 'Organización eliminada con éxito',\n }),\n description: t({\n en: 'Your organization has been deleted successfully',\n fr: 'Votre organisation a été supprimée avec succès',\n es: 'Su organización ha sido eliminada con éxito',\n }),\n data: mapOrganizationToAPI(deletedOrganization),\n });\n\n // No need to update session here, as it's a delete operation\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectOrganizationParam = {\n organizationId: string | Types.ObjectId;\n};\nexport type SelectOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Select an organization.\n */\nexport const selectOrganization = async (\n req: Request<SelectOrganizationParam>,\n res: ResponseWithSession<SelectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<SelectOrganizationParam>;\n const { session } = res.locals;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n if (typeof session === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'SESSION_NOT_DEFINED');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n // Update session to set activeOrganizationId\n await SessionModel.updateOne(\n { _id: session.id },\n {\n $set: {\n activeOrganizationId: String(organization.id),\n activeProjectId: null,\n },\n }\n );\n\n // No need to update session here, as it's a select operation\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization retrieved successfully',\n fr: 'Organisation récupérée avec succès',\n es: 'Organización recuperada con éxito',\n }),\n description: t({\n en: 'Your organization has been retrieved successfully',\n fr: 'Votre organisation a été récupérée avec succès',\n es: 'Su organización ha sido recuperada con éxito',\n }),\n data: mapOrganizationToAPI(organization),\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 UnselectOrganizationResult = ResponseData<null>;\n\n/**\n * Unselect an organization.\n */\nexport const unselectOrganization = async (\n _req: Request,\n res: ResponseWithSession<UnselectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { session } = res.locals;\n try {\n // Update session to clear activeOrganizationId and activeProjectId\n\n if (typeof session === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'SESSION_NOT_DEFINED');\n return;\n }\n\n await SessionModel.updateOne(\n { _id: session.id },\n {\n $set: {\n activeOrganizationId: null,\n activeProjectId: null,\n },\n }\n );\n\n const responseData = formatResponse<null>({\n message: t({\n en: 'Organization unselected successfully',\n fr: 'Organisation désélectionnée avec succès',\n es: 'Organización deseleccionada con éxito',\n }),\n description: t({\n en: 'Your organization has been unselected successfully',\n fr: 'Votre organisation a été désélectionnée avec succès',\n es: 'Su organización ha sido deseleccionada con éxito',\n }),\n data: null,\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":"organization.controller.cjs","names":["getOrganizationFiltersAndPagination","hasPermission","formatPaginatedResponse","mapOrganizationsToAPI","formatResponse","mapOrganizationToAPI","getPlanDetails","sendEmail","user","stripe","Stripe","SessionModel"],"sources":["../../../src/controllers/organization.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport { SessionModel } from '@models/session.model';\nimport { sendEmail } from '@services/email.service';\nimport * as organizationService from '@services/organization.service';\nimport * as projectService from '@services/project.service';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getOrganizationFiltersAndPagination,\n type OrganizationFiltersParams,\n} from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport {\n mapOrganizationsToAPI,\n mapOrganizationToAPI,\n} from '@utils/mapper/organization';\nimport { hasPermission } from '@utils/permissions';\nimport { getPlanDetails } from '@utils/plan';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { Types } from 'mongoose';\nimport { Stripe } from 'stripe';\nimport type {\n Organization,\n OrganizationAPI,\n OrganizationCreationData,\n} from '@/types/organization.types';\nimport type { User, UserAPI } from '@/types/user.types';\n\nexport type GetOrganizationsParams =\n FiltersAndPagination<OrganizationFiltersParams>;\nexport type GetOrganizationsResult = PaginatedResponse<OrganizationAPI>;\n\n/**\n * Retrieves a list of organizations based on filters and pagination.\n */\nexport const getOrganizations = async (\n req: Request<GetOrganizationsParams>,\n res: ResponseWithSession<GetOrganizationsResult>,\n _next: NextFunction\n) => {\n const { user, roles } = res.locals;\n const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req, res);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const organizations = await organizationService.findOrganizations(\n filters,\n skip,\n pageSize,\n sortOptions\n );\n\n if (\n !hasPermission(\n roles,\n 'organization:read'\n )({\n ...res.locals,\n targetOrganizations: organizations,\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const totalItems = await organizationService.countOrganizations(filters);\n\n const responseData = formatPaginatedResponse<OrganizationAPI>({\n data: mapOrganizationsToAPI(organizations),\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.status(200).json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetOrganizationParam = { organizationId: string };\nexport type GetOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Retrieves an organization by its ID.\n */\nexport const getOrganization = async (\n req: Request<GetOrganizationParam, any, any>,\n res: ResponseWithSession<GetOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { roles } = res.locals;\n const { organizationId } = req.params as Partial<GetOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n if (\n !hasPermission(\n roles,\n 'organization:read'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const responseData = formatResponse<OrganizationAPI>({\n data: mapOrganizationToAPI(organization),\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 AddOrganizationBody = OrganizationCreationData;\nexport type AddOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Adds a new organization to the database.\n */\nexport const addOrganization = async (\n req: Request<any, any, AddOrganizationBody>,\n res: ResponseWithSession<AddOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const organization = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newOrganization = await organizationService.createOrganization(\n organization,\n user.id\n );\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization created successfully',\n fr: 'Organisation créée avec succès',\n es: 'Organización creada con éxito',\n }),\n description: t({\n en: 'Your organization has been created successfully',\n fr: 'Votre organisation a été créée avec succès',\n es: 'Su organización ha sido creada con éxito',\n }),\n data: mapOrganizationToAPI(newOrganization),\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 UpdateOrganizationBody = Partial<Organization>;\nexport type UpdateOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Updates an existing organization in the database.\n */\nexport const updateOrganization = async (\n req: Request<undefined, undefined, UpdateOrganizationBody>,\n res: ResponseWithSession<UpdateOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, roles } = res.locals;\n const organizationFields = req.body;\n\n if (!organizationFields) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:write'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const updatedOrganization =\n await organizationService.updateOrganizationById(\n organization.id,\n organizationFields\n );\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\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 AddOrganizationMemberBody = {\n userEmail: string;\n};\nexport type AddOrganizationMemberResult = ResponseData<OrganizationAPI>;\n\n/**\n * Add member to the organization in the database.\n */\nexport const addOrganizationMember = async (\n req: Request<any, any, AddOrganizationMemberBody>,\n res: ResponseWithSession<AddOrganizationMemberResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, user, roles } = res.locals;\n const { userEmail } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:admin'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const planType = getPlanDetails(organization.plan);\n\n if (\n planType.numberOfOrganizationUsers &&\n organization.membersIds.length >= planType.numberOfOrganizationUsers\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_USER_LIMIT_REACHED', {\n organizationId: organization.id,\n });\n return;\n }\n\n try {\n let newMember = await userService.getUserByEmail(userEmail);\n\n if (!newMember) {\n // Create user if not found\n const newUser = await userService.createUser({ email: userEmail });\n if (!newUser) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_CREATION_FAILED', {\n email: userEmail,\n });\n return;\n }\n\n newMember = newUser;\n }\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization.id, {\n ...organization,\n membersIds: [...organization.membersIds, newMember.id],\n });\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\n });\n\n res.json(responseData);\n\n await sendEmail({\n type: 'invite',\n to: userEmail,\n username: newMember.email.slice(0, newMember.email.indexOf('@')),\n invitedByUsername: user.name,\n invitedByEmail: user.email,\n organizationName: organization.name,\n inviteLink: `${process.env.CLIENT_URL}/auth/login?email=${newMember.email}`,\n inviteFromIp: req.ip ?? '',\n inviteFromLocation: req.hostname,\n });\n\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationMembersBody = Partial<{\n membersIds: (User | UserAPI)['id'][];\n adminsIds: (User | UserAPI)['id'][];\n}>;\nexport type UpdateOrganizationMembersResult = ResponseData<OrganizationAPI>;\n\n/**\n * Update members to the organization in the database.\n */\nexport const updateOrganizationMembers = async (\n req: Request<any, any, UpdateOrganizationMembersBody>,\n res: ResponseWithSession<UpdateOrganizationMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, roles } = res.locals;\n const { membersIds, adminsIds } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:admin'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n if (!membersIds) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n if (adminsIds?.filter((id) => membersIds?.includes(id)).length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n try {\n const existingUsers = await userService.getUsersByIds(membersIds);\n\n if (!existingUsers) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const existingAdmins = await userService.getUsersByIds(adminsIds!);\n\n if (!existingAdmins) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization.id, {\n membersIds: existingUsers.map((user) => user.id),\n adminsIds: existingAdmins.map((user) => user.id),\n });\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\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 UpdateOrganizationMembersByIdParams = { organizationId: string };\nexport type UpdateOrganizationMembersByIdBody = Partial<{\n membersIds: (User | UserAPI)['id'][];\n adminsIds: (User | UserAPI)['id'][];\n}>;\nexport type UpdateOrganizationMembersByIdResult = ResponseData<OrganizationAPI>;\n\n/**\n * Admin-only: Update members of any organization by ID\n */\nexport const updateOrganizationMembersById = async (\n req: Request<\n UpdateOrganizationMembersByIdParams,\n any,\n UpdateOrganizationMembersByIdBody\n >,\n res: ResponseWithSession<UpdateOrganizationMembersByIdResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const { organizationId } = req.params;\n const { membersIds, adminsIds } = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (user.role !== 'admin') {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n if (!membersIds) {\n ErrorHandler.handleGenericErrorResponse(res, 'INVALID_REQUEST_BODY');\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n try {\n const targetOrganization =\n await organizationService.getOrganizationById(organizationId);\n\n if (!targetOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n const existingUsers = await userService.getUsersByIds(membersIds);\n\n if (!existingUsers) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const finalAdminsIds =\n adminsIds && adminsIds.length > 0\n ? adminsIds\n : targetOrganization.adminsIds;\n const existingAdmins = finalAdminsIds\n ? await userService.getUsersByIds(finalAdminsIds)\n : [];\n\n if (!existingAdmins || existingAdmins.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(targetOrganization.id, {\n membersIds: existingUsers.map((user) => user.id),\n adminsIds: existingAdmins.map((user) => user.id),\n });\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization members updated successfully',\n fr: \"Membres de l'organisation mis à jour avec succès\",\n es: 'Miembros de la organización actualizados con éxito',\n }),\n description: t({\n en: 'Organization members have been updated successfully',\n fr: \"Les membres de l'organisation ont été mis à jour avec succès\",\n es: 'Los miembros de la organización han sido actualizados con éxito',\n }),\n data: mapOrganizationToAPI(updatedOrganization),\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 DeleteOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Deletes an organization from the database by its ID.\n */\nexport const deleteOrganization = async (\n _req: Request,\n res: ResponseWithSession,\n _next: NextFunction\n): Promise<void> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const { organization, roles } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n const projects = await projectService.findProjects({\n organizationId: organization.id,\n });\n\n if (projects.length > 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECTS_EXIST', {\n organizationId: organization.id,\n });\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'organization:admin'\n )({\n ...res.locals,\n targetOrganizations: [organization],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n // Cancel the subscription on Stripe if it exists\n if (organization.plan?.subscriptionId) {\n await stripe.subscriptions.cancel(organization.plan.subscriptionId);\n }\n\n const deletedOrganization =\n await organizationService.deleteOrganizationById(organization.id);\n\n if (!deletedOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND', {\n organizationId: organization.id,\n });\n return;\n }\n\n logger.info(`Organization deleted: ${String(deletedOrganization.id)}`);\n\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization deleted successfully',\n fr: 'Organisation supprimée avec succès',\n es: 'Organización eliminada con éxito',\n }),\n description: t({\n en: 'Your organization has been deleted successfully',\n fr: 'Votre organisation a été supprimée avec succès',\n es: 'Su organización ha sido eliminada con éxito',\n }),\n data: mapOrganizationToAPI(deletedOrganization),\n });\n\n // No need to update session here, as it's a delete operation\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectOrganizationParam = {\n organizationId: string | Types.ObjectId;\n};\nexport type SelectOrganizationResult = ResponseData<OrganizationAPI>;\n\n/**\n * Select an organization.\n */\nexport const selectOrganization = async (\n req: Request<SelectOrganizationParam>,\n res: ResponseWithSession<SelectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<SelectOrganizationParam>;\n const { session } = res.locals;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n if (typeof session === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'SESSION_NOT_DEFINED');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n // Update session to set activeOrganizationId\n await SessionModel.updateOne(\n { _id: session.id },\n {\n $set: {\n activeOrganizationId: String(organization.id),\n activeProjectId: null,\n },\n }\n );\n\n // No need to update session here, as it's a select operation\n const responseData = formatResponse<OrganizationAPI>({\n message: t({\n en: 'Organization retrieved successfully',\n fr: 'Organisation récupérée avec succès',\n es: 'Organización recuperada con éxito',\n }),\n description: t({\n en: 'Your organization has been retrieved successfully',\n fr: 'Votre organisation a été récupérée avec succès',\n es: 'Su organización ha sido recuperada con éxito',\n }),\n data: mapOrganizationToAPI(organization),\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 UnselectOrganizationResult = ResponseData<null>;\n\n/**\n * Unselect an organization.\n */\nexport const unselectOrganization = async (\n _req: Request,\n res: ResponseWithSession<UnselectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { session } = res.locals;\n try {\n // Update session to clear activeOrganizationId and activeProjectId\n\n if (typeof session === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'SESSION_NOT_DEFINED');\n return;\n }\n\n await SessionModel.updateOne(\n { _id: session.id },\n {\n $set: {\n activeOrganizationId: null,\n activeProjectId: null,\n },\n }\n );\n\n const responseData = formatResponse<null>({\n message: t({\n en: 'Organization unselected successfully',\n fr: 'Organisation désélectionnée avec succès',\n es: 'Organización deseleccionada con éxito',\n }),\n description: t({\n en: 'Your organization has been unselected successfully',\n fr: 'Votre organisation a été désélectionnée avec succès',\n es: 'Su organización ha sido deseleccionada con éxito',\n }),\n data: null,\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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"}
@@ -10,7 +10,6 @@ const require_utils_plan = require('../utils/plan.cjs');
10
10
  const require_utils_filtersAndPagination_getProjectFiltersAndPagination = require('../utils/filtersAndPagination/getProjectFiltersAndPagination.cjs');
11
11
  const require_utils_mapper_project = require('../utils/mapper/project.cjs');
12
12
  let express_intlayer = require("express-intlayer");
13
- express_intlayer = require_rolldown_runtime.__toESM(express_intlayer);
14
13
 
15
14
  //#region src/controllers/project.controller.ts
16
15
  /**