@intlayer/backend 5.4.1 → 5.5.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/cjs/controllers/ai.controller.cjs +60 -52
  2. package/dist/cjs/controllers/ai.controller.cjs.map +1 -1
  3. package/dist/cjs/controllers/dictionary.controller.cjs +5 -0
  4. package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
  5. package/dist/cjs/export.cjs +4 -2
  6. package/dist/cjs/export.cjs.map +1 -1
  7. package/dist/cjs/routes/ai.routes.cjs +6 -0
  8. package/dist/cjs/routes/ai.routes.cjs.map +1 -1
  9. package/dist/cjs/services/dictionary.service.cjs +6 -1
  10. package/dist/cjs/services/dictionary.service.cjs.map +1 -1
  11. package/dist/cjs/services/sessionAuth.service.cjs +7 -7
  12. package/dist/cjs/services/sessionAuth.service.cjs.map +1 -1
  13. package/dist/cjs/utils/AI/aiSdk.cjs +140 -0
  14. package/dist/cjs/utils/AI/aiSdk.cjs.map +1 -0
  15. package/dist/cjs/utils/AI/askDocQuestion/PROMPT.md +2 -1
  16. package/dist/cjs/utils/AI/askDocQuestion/askDocQuestion.cjs +32 -27
  17. package/dist/cjs/utils/AI/askDocQuestion/askDocQuestion.cjs.map +1 -1
  18. package/dist/cjs/utils/AI/askDocQuestion/embeddings.json +7374 -0
  19. package/dist/cjs/utils/AI/auditDictionary/PROMPT.md +4 -0
  20. package/dist/cjs/utils/AI/auditDictionary/index.cjs +36 -43
  21. package/dist/cjs/utils/AI/auditDictionary/index.cjs.map +1 -1
  22. package/dist/cjs/utils/AI/auditDictionaryField/PROMPT.md +4 -0
  23. package/dist/cjs/utils/AI/auditDictionaryField/index.cjs +34 -28
  24. package/dist/cjs/utils/AI/auditDictionaryField/index.cjs.map +1 -1
  25. package/dist/cjs/utils/AI/auditDictionaryMetadata/PROMPT.md +4 -0
  26. package/dist/cjs/utils/AI/auditDictionaryMetadata/index.cjs +23 -23
  27. package/dist/cjs/utils/AI/auditDictionaryMetadata/index.cjs.map +1 -1
  28. package/dist/cjs/utils/{auditTag → AI/auditTag}/PROMPT.md +4 -0
  29. package/dist/cjs/utils/{auditTag → AI/auditTag}/index.cjs +27 -27
  30. package/dist/cjs/utils/AI/auditTag/index.cjs.map +1 -0
  31. package/dist/cjs/utils/AI/autocomplete/PROMPT.md +4 -0
  32. package/dist/cjs/utils/AI/autocomplete/index.cjs +25 -22
  33. package/dist/cjs/utils/AI/autocomplete/index.cjs.map +1 -1
  34. package/dist/cjs/utils/AI/translateJSON/PROMPT.md +53 -0
  35. package/dist/cjs/utils/AI/translateJSON/index.cjs +106 -0
  36. package/dist/cjs/utils/AI/translateJSON/index.cjs.map +1 -0
  37. package/dist/cjs/utils/extractJSON.cjs +52 -0
  38. package/dist/cjs/utils/extractJSON.cjs.map +1 -0
  39. package/dist/esm/controllers/ai.controller.mjs +58 -51
  40. package/dist/esm/controllers/ai.controller.mjs.map +1 -1
  41. package/dist/esm/controllers/dictionary.controller.mjs +5 -0
  42. package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
  43. package/dist/esm/export.mjs +3 -2
  44. package/dist/esm/export.mjs.map +1 -1
  45. package/dist/esm/routes/ai.routes.mjs +8 -1
  46. package/dist/esm/routes/ai.routes.mjs.map +1 -1
  47. package/dist/esm/services/dictionary.service.mjs +6 -1
  48. package/dist/esm/services/dictionary.service.mjs.map +1 -1
  49. package/dist/esm/services/sessionAuth.service.mjs +2 -2
  50. package/dist/esm/services/sessionAuth.service.mjs.map +1 -1
  51. package/dist/esm/utils/AI/aiSdk.mjs +115 -0
  52. package/dist/esm/utils/AI/aiSdk.mjs.map +1 -0
  53. package/dist/esm/utils/AI/askDocQuestion/PROMPT.md +2 -1
  54. package/dist/esm/utils/AI/askDocQuestion/askDocQuestion.mjs +32 -27
  55. package/dist/esm/utils/AI/askDocQuestion/askDocQuestion.mjs.map +1 -1
  56. package/dist/esm/utils/AI/askDocQuestion/embeddings.json +7374 -0
  57. package/dist/esm/utils/AI/auditDictionary/PROMPT.md +4 -0
  58. package/dist/esm/utils/AI/auditDictionary/index.mjs +36 -43
  59. package/dist/esm/utils/AI/auditDictionary/index.mjs.map +1 -1
  60. package/dist/esm/utils/AI/auditDictionaryField/PROMPT.md +4 -0
  61. package/dist/esm/utils/AI/auditDictionaryField/index.mjs +34 -28
  62. package/dist/esm/utils/AI/auditDictionaryField/index.mjs.map +1 -1
  63. package/dist/esm/utils/AI/auditDictionaryMetadata/PROMPT.md +4 -0
  64. package/dist/esm/utils/AI/auditDictionaryMetadata/index.mjs +23 -23
  65. package/dist/esm/utils/AI/auditDictionaryMetadata/index.mjs.map +1 -1
  66. package/dist/esm/utils/{auditTag → AI/auditTag}/PROMPT.md +4 -0
  67. package/dist/esm/utils/AI/auditTag/index.mjs +49 -0
  68. package/dist/esm/utils/AI/auditTag/index.mjs.map +1 -0
  69. package/dist/esm/utils/AI/autocomplete/PROMPT.md +4 -0
  70. package/dist/esm/utils/AI/autocomplete/index.mjs +25 -22
  71. package/dist/esm/utils/AI/autocomplete/index.mjs.map +1 -1
  72. package/dist/esm/utils/AI/translateJSON/PROMPT.md +53 -0
  73. package/dist/esm/utils/AI/translateJSON/index.mjs +81 -0
  74. package/dist/esm/utils/AI/translateJSON/index.mjs.map +1 -0
  75. package/dist/esm/utils/extractJSON.mjs +28 -0
  76. package/dist/esm/utils/extractJSON.mjs.map +1 -0
  77. package/dist/types/controllers/ai.controller.d.ts +12 -21
  78. package/dist/types/controllers/ai.controller.d.ts.map +1 -1
  79. package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
  80. package/dist/types/export.d.ts +12 -11
  81. package/dist/types/export.d.ts.map +1 -1
  82. package/dist/types/routes/ai.routes.d.ts +5 -0
  83. package/dist/types/routes/ai.routes.d.ts.map +1 -1
  84. package/dist/types/services/dictionary.service.d.ts +2 -2
  85. package/dist/types/services/dictionary.service.d.ts.map +1 -1
  86. package/dist/types/services/sessionAuth.service.d.ts +2 -2
  87. package/dist/types/services/sessionAuth.service.d.ts.map +1 -1
  88. package/dist/types/utils/AI/aiSdk.d.ts +41 -0
  89. package/dist/types/utils/AI/aiSdk.d.ts.map +1 -0
  90. package/dist/types/utils/AI/askDocQuestion/askDocQuestion.d.ts +1 -1
  91. package/dist/types/utils/AI/askDocQuestion/askDocQuestion.d.ts.map +1 -1
  92. package/dist/types/utils/AI/auditDictionary/index.d.ts +10 -15
  93. package/dist/types/utils/AI/auditDictionary/index.d.ts.map +1 -1
  94. package/dist/types/utils/AI/auditDictionaryField/index.d.ts +9 -14
  95. package/dist/types/utils/AI/auditDictionaryField/index.d.ts.map +1 -1
  96. package/dist/types/utils/AI/auditDictionaryMetadata/index.d.ts +7 -13
  97. package/dist/types/utils/AI/auditDictionaryMetadata/index.d.ts.map +1 -1
  98. package/dist/types/utils/AI/auditTag/index.d.ts +18 -0
  99. package/dist/types/utils/AI/auditTag/index.d.ts.map +1 -0
  100. package/dist/types/utils/AI/autocomplete/index.d.ts +6 -12
  101. package/dist/types/utils/AI/autocomplete/index.d.ts.map +1 -1
  102. package/dist/types/utils/AI/translateJSON/index.d.ts +24 -0
  103. package/dist/types/utils/AI/translateJSON/index.d.ts.map +1 -0
  104. package/dist/types/utils/extractJSON.d.ts +6 -0
  105. package/dist/types/utils/extractJSON.d.ts.map +1 -0
  106. package/package.json +15 -11
  107. package/dist/cjs/utils/auditTag/index.cjs.map +0 -1
  108. package/dist/esm/utils/auditTag/index.mjs +0 -49
  109. package/dist/esm/utils/auditTag/index.mjs.map +0 -1
  110. package/dist/types/utils/auditTag/index.d.ts +0 -30
  111. package/dist/types/utils/auditTag/index.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["import type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\nimport * as eventListener from '@controllers/eventListener.controller';\nimport type {\n ContentNode,\n Dictionary as LocalDictionary,\n} from '@intlayer/core';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } 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 {\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';\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: ResponseWithInformation<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, organization, dictionaryRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req);\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 if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\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 );\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) =>\n mapDictionaryToAPI(el, project._id)\n );\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: ResponseWithInformation<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, dictionaryRights } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionariesKeys = await dictionaryService.getDictionariesKeys(\n project._id\n );\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 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: ResponseWithInformation<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = 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 if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project._id\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, project._id, 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: ResponseWithInformation<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = 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 if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\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 filePath: {\n [String(project._id)]: dictionaryData.filePath ?? '',\n },\n projectIds: dictionaryData.projectIds ?? [String(project._id)],\n };\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary, project._id);\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, project._id),\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: ResponseWithInformation<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = 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 (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\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 filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(\n mapDictionaryToAPI(newDictionary, project._id)\n );\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 filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\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(\n mapDictionaryToAPI(updatedDictionary, project._id)\n );\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: ResponseWithInformation<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, dictionaryRights } = 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 (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary, project._id);\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: ResponseWithInformation<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, dictionaryRights } = 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 (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\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, project._id);\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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","names":[]}
1
+ {"version":3,"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["import type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\nimport * as eventListener from '@controllers/eventListener.controller';\nimport type {\n ContentNode,\n Dictionary as LocalDictionary,\n} from '@intlayer/core';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } 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 {\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';\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: ResponseWithInformation<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, organization, dictionaryRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req);\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 if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\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 );\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) =>\n mapDictionaryToAPI(el, project._id)\n );\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: ResponseWithInformation<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, dictionaryRights } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionariesKeys = await dictionaryService.getDictionariesKeys(\n project._id\n );\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 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: ResponseWithInformation<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = 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 if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project._id\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, project._id, 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: ResponseWithInformation<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = 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 if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\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 filePath: {\n [String(project._id)]: dictionaryData.filePath ?? '',\n },\n projectIds: dictionaryData.projectIds ?? [String(project._id)],\n };\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary, project._id);\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, project._id),\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: ResponseWithInformation<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = 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 (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\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 filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(\n mapDictionaryToAPI(newDictionary, project._id)\n );\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 filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\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(\n mapDictionaryToAPI(updatedDictionary, project._id)\n );\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: ResponseWithInformation<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, dictionaryRights } = 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 (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary, project._id);\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: ResponseWithInformation<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, dictionaryRights } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n console.log('dictionaryId1', dictionaryId);\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n console.log('dictionaryId2', dictionaryId);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n console.log('dictionaryId3', dictionaryId);\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n console.log('dictionaryId4', dictionaryId);\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n console.log('dictionaryToDelete', dictionaryToDelete);\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, project._id);\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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","names":[]}
@@ -1,8 +1,9 @@
1
- import { getUserRoutes } from "./routes/user.routes.mjs";
1
+ import { getDictionaryRoutes } from "./routes/dictionary.routes.mjs";
2
2
  import { getOrganizationRoutes } from "./routes/organization.routes.mjs";
3
3
  import { getProjectRoutes } from "./routes/project.routes.mjs";
4
- import { getDictionaryRoutes } from "./routes/dictionary.routes.mjs";
5
4
  import { getSessionAuthRoutes } from "./routes/sessionAuth.routes.mjs";
5
+ import { getUserRoutes } from "./routes/user.routes.mjs";
6
+ export * from "./utils/AI/aiSdk.mjs";
6
7
  export * from "./utils/cookies.mjs";
7
8
  export * from "./utils/httpStatusCodes.mjs";
8
9
  export * from "./utils/responseData.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/export.ts"],"sourcesContent":["// Routes\nexport { getUserRoutes } from '@routes/user.routes';\nexport { getOrganizationRoutes } from '@routes/organization.routes';\nexport { getProjectRoutes } from '@routes/project.routes';\nexport { getDictionaryRoutes } from '@routes/dictionary.routes';\nexport { getSessionAuthRoutes } from '@routes/sessionAuth.routes';\n\n// Controllers types\nexport type * from '@controllers/sessionAuth.controller';\nexport type * from '@controllers/oAuth2.controller';\nexport type * from '@controllers/organization.controller';\nexport type * from '@controllers/eventListener.controller';\nexport type * from '@controllers/project.controller';\nexport type * from '@controllers/projectAccessKey.controller';\nexport type * from '@controllers/user.controller';\nexport type * from '@controllers/dictionary.controller';\nexport type * from '@controllers/stripe.controller';\nexport type * from '@controllers/ai.controller';\nexport type * from '@controllers/tag.controller';\n\n// Objects types\nexport type * from '@/types/organization.types';\nexport type * from '@/types/project.types';\nexport type * from '@/types/user.types';\nexport type * from '@/types/dictionary.types';\nexport type * from '@/types/plan.types';\nexport type * from '@/types/tag.types';\nexport type * from '@/types/oAuth2.types';\n\n// Utils\nexport * from '@utils/cookies';\nexport * from '@utils/httpStatusCodes';\nexport * from '@utils/responseData';\n"],"mappings":"AACA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,wBAAwB;AACjC,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AAyBrC,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../src/export.ts"],"sourcesContent":["// Routes\nexport { getDictionaryRoutes } from '@routes/dictionary.routes';\nexport { getOrganizationRoutes } from '@routes/organization.routes';\nexport { getProjectRoutes } from '@routes/project.routes';\nexport { getSessionAuthRoutes } from '@routes/sessionAuth.routes';\nexport { getUserRoutes } from '@routes/user.routes';\n\n// Controllers types\nexport type * from '@controllers/ai.controller';\nexport type * from '@controllers/dictionary.controller';\nexport type * from '@controllers/eventListener.controller';\nexport type * from '@controllers/oAuth2.controller';\nexport type * from '@controllers/organization.controller';\nexport type * from '@controllers/project.controller';\nexport type * from '@controllers/projectAccessKey.controller';\nexport type * from '@controllers/sessionAuth.controller';\nexport type * from '@controllers/stripe.controller';\nexport type * from '@controllers/tag.controller';\nexport type * from '@controllers/user.controller';\n\n// Objects types\nexport type * from '@/types/dictionary.types';\nexport type * from '@/types/oAuth2.types';\nexport type * from '@/types/organization.types';\nexport type * from '@/types/plan.types';\nexport type * from '@/types/project.types';\nexport type * from '@/types/tag.types';\nexport type * from '@/types/user.types';\n\n// Utils\nexport * from '@utils/AI/aiSdk';\nexport * from '@utils/cookies';\nexport * from '@utils/httpStatusCodes';\nexport * from '@utils/responseData';\n"],"mappings":"AACA,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,wBAAwB;AACjC,SAAS,4BAA4B;AACrC,SAAS,qBAAqB;AAyB9B,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -4,12 +4,18 @@ import {
4
4
  auditContentDeclarationField,
5
5
  auditContentDeclarationMetadata,
6
6
  auditTag,
7
- autocomplete
7
+ autocomplete,
8
+ translateJSON
8
9
  } from "./../controllers/ai.controller.mjs";
9
10
  import { Router } from "express";
10
11
  const aiRouter = Router();
11
12
  const baseURL = () => `${process.env.BACKEND_URL}/api/ai`;
12
13
  const getAiRoutes = () => ({
14
+ translateJSON: {
15
+ urlModel: "/translate/json",
16
+ url: `${baseURL()}/translate/json`,
17
+ method: "POST"
18
+ },
13
19
  auditContentDeclaration: {
14
20
  urlModel: "/audit/dictionary",
15
21
  url: `${baseURL()}/audit/dictionary`,
@@ -41,6 +47,7 @@ const getAiRoutes = () => ({
41
47
  method: "POST"
42
48
  }
43
49
  });
50
+ aiRouter.post(getAiRoutes().translateJSON.urlModel, translateJSON);
44
51
  aiRouter.post(
45
52
  getAiRoutes().auditContentDeclaration.urlModel,
46
53
  auditContentDeclaration
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/routes/ai.routes.ts"],"sourcesContent":["import {\n askDocQuestion,\n auditContentDeclaration,\n auditContentDeclarationField,\n auditContentDeclarationMetadata,\n auditTag,\n autocomplete,\n} from '@controllers/ai.controller';\nimport { Router } from 'express';\nimport type { Routes } from '@/types/Routes';\n\nexport const aiRouter: Router = Router();\n\nconst baseURL = () => `${process.env.BACKEND_URL}/api/ai`;\n\nexport const getAiRoutes = () =>\n ({\n auditContentDeclaration: {\n urlModel: '/audit/dictionary',\n url: `${baseURL()}/audit/dictionary`,\n method: 'POST',\n },\n auditContentDeclarationField: {\n urlModel: '/audit/dictionary/field',\n url: `${baseURL()}/audit/dictionary/field`,\n method: 'POST',\n },\n auditContentDeclarationMetadata: {\n urlModel: '/audit/dictionary/metadata',\n url: `${baseURL()}/audit/dictionary/metadata`,\n method: 'POST',\n },\n auditTag: {\n urlModel: '/audit/tag',\n url: `${baseURL()}/audit/tag`,\n method: 'POST',\n },\n ask: {\n urlModel: '/ask',\n url: `${baseURL()}/ask`,\n method: 'POST',\n },\n autocomplete: {\n urlModel: '/autocomplete',\n url: `${baseURL()}/autocomplete`,\n method: 'POST',\n },\n }) satisfies Routes;\n\naiRouter.post(\n getAiRoutes().auditContentDeclaration.urlModel,\n auditContentDeclaration\n);\naiRouter.post(\n getAiRoutes().auditContentDeclarationField.urlModel,\n auditContentDeclarationField\n);\naiRouter.post(\n getAiRoutes().auditContentDeclarationMetadata.urlModel,\n auditContentDeclarationMetadata\n);\naiRouter.post(getAiRoutes().ask.urlModel, askDocQuestion);\n\naiRouter.post(getAiRoutes().auditTag.urlModel, auditTag);\n\naiRouter.post(getAiRoutes().autocomplete.urlModel, autocomplete);\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAGhB,MAAM,WAAmB,OAAO;AAEvC,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW;AAEzC,MAAM,cAAc,OACxB;AAAA,EACC,yBAAyB;AAAA,IACvB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,8BAA8B;AAAA,IAC5B,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,iCAAiC;AAAA,IAC/B,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,KAAK;AAAA,IACH,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,cAAc;AAAA,IACZ,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,SAAS;AAAA,EACP,YAAY,EAAE,wBAAwB;AAAA,EACtC;AACF;AACA,SAAS;AAAA,EACP,YAAY,EAAE,6BAA6B;AAAA,EAC3C;AACF;AACA,SAAS;AAAA,EACP,YAAY,EAAE,gCAAgC;AAAA,EAC9C;AACF;AACA,SAAS,KAAK,YAAY,EAAE,IAAI,UAAU,cAAc;AAExD,SAAS,KAAK,YAAY,EAAE,SAAS,UAAU,QAAQ;AAEvD,SAAS,KAAK,YAAY,EAAE,aAAa,UAAU,YAAY;","names":[]}
1
+ {"version":3,"sources":["../../../src/routes/ai.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n askDocQuestion,\n auditContentDeclaration,\n auditContentDeclarationField,\n auditContentDeclarationMetadata,\n auditTag,\n autocomplete,\n translateJSON,\n} from '@controllers/ai.controller';\nimport { Router } from 'express';\n\nexport const aiRouter: Router = Router();\n\nconst baseURL = () => `${process.env.BACKEND_URL}/api/ai`;\n\nexport const getAiRoutes = () =>\n ({\n translateJSON: {\n urlModel: '/translate/json',\n url: `${baseURL()}/translate/json`,\n method: 'POST',\n },\n auditContentDeclaration: {\n urlModel: '/audit/dictionary',\n url: `${baseURL()}/audit/dictionary`,\n method: 'POST',\n },\n auditContentDeclarationField: {\n urlModel: '/audit/dictionary/field',\n url: `${baseURL()}/audit/dictionary/field`,\n method: 'POST',\n },\n auditContentDeclarationMetadata: {\n urlModel: '/audit/dictionary/metadata',\n url: `${baseURL()}/audit/dictionary/metadata`,\n method: 'POST',\n },\n auditTag: {\n urlModel: '/audit/tag',\n url: `${baseURL()}/audit/tag`,\n method: 'POST',\n },\n ask: {\n urlModel: '/ask',\n url: `${baseURL()}/ask`,\n method: 'POST',\n },\n autocomplete: {\n urlModel: '/autocomplete',\n url: `${baseURL()}/autocomplete`,\n method: 'POST',\n },\n }) satisfies Routes;\n\naiRouter.post(getAiRoutes().translateJSON.urlModel, translateJSON);\n\naiRouter.post(\n getAiRoutes().auditContentDeclaration.urlModel,\n auditContentDeclaration\n);\naiRouter.post(\n getAiRoutes().auditContentDeclarationField.urlModel,\n auditContentDeclarationField\n);\naiRouter.post(\n getAiRoutes().auditContentDeclarationMetadata.urlModel,\n auditContentDeclarationMetadata\n);\naiRouter.post(getAiRoutes().ask.urlModel, askDocQuestion);\n\naiRouter.post(getAiRoutes().auditTag.urlModel, auditTag);\n\naiRouter.post(getAiRoutes().autocomplete.urlModel, autocomplete);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,WAAmB,OAAO;AAEvC,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW;AAEzC,MAAM,cAAc,OACxB;AAAA,EACC,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,yBAAyB;AAAA,IACvB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,8BAA8B;AAAA,IAC5B,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,iCAAiC;AAAA,IAC/B,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,KAAK;AAAA,IACH,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,cAAc;AAAA,IACZ,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,SAAS,KAAK,YAAY,EAAE,cAAc,UAAU,aAAa;AAEjE,SAAS;AAAA,EACP,YAAY,EAAE,wBAAwB;AAAA,EACtC;AACF;AACA,SAAS;AAAA,EACP,YAAY,EAAE,6BAA6B;AAAA,EAC3C;AACF;AACA,SAAS;AAAA,EACP,YAAY,EAAE,gCAAgC;AAAA,EAC9C;AACF;AACA,SAAS,KAAK,YAAY,EAAE,IAAI,UAAU,cAAc;AAExD,SAAS,KAAK,YAAY,EAAE,SAAS,UAAU,QAAQ;AAEvD,SAAS,KAAK,YAAY,EAAE,aAAa,UAAU,YAAY;","names":[]}
@@ -5,6 +5,7 @@ import { removeObjectKeys } from "./../utils/removeObjectKeys.mjs";
5
5
  import {
6
6
  validateDictionary
7
7
  } from "./../utils/validation/validateDictionary.mjs";
8
+ import { Types } from "mongoose";
8
9
  const findDictionaries = async (filters, skip = 0, limit = 100) => {
9
10
  try {
10
11
  const dictionaries = await DictionaryModel.aggregate([
@@ -25,9 +26,10 @@ const findDictionaries = async (filters, skip = 0, limit = 100) => {
25
26
  }
26
27
  };
27
28
  const getDictionaryById = async (dictionaryId) => {
29
+ const id = Types.ObjectId.isValid(dictionaryId) ? new Types.ObjectId(dictionaryId) : dictionaryId;
28
30
  const dictionaries = await DictionaryModel.aggregate([
29
31
  // Stage 1: Match the document by ID
30
- { $match: { _id: dictionaryId } },
32
+ { $match: { _id: id } },
31
33
  // Stage 2: Add the 'availableVersions' field
32
34
  {
33
35
  $addFields: {
@@ -41,6 +43,7 @@ const getDictionaryById = async (dictionaryId) => {
41
43
  }
42
44
  }
43
45
  ]);
46
+ console.log("dictionaries", dictionaries);
44
47
  if (!dictionaries.length) {
45
48
  throw new GenericError("DICTIONARY_NOT_FOUND", { dictionaryId });
46
49
  }
@@ -190,7 +193,9 @@ const updateDictionaryByKey = async (dictionaryKey, dictionary, projectId) => {
190
193
  return updatedDictionary;
191
194
  };
192
195
  const deleteDictionaryById = async (dictionaryId) => {
196
+ console.log("dictionaryId", dictionaryId);
193
197
  const dictionary = await DictionaryModel.findByIdAndDelete(dictionaryId);
198
+ console.log("dictionary", dictionary);
194
199
  if (!dictionary) {
195
200
  throw new GenericError("DICTIONARY_NOT_FOUND", { dictionaryId });
196
201
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/dictionary.service.ts"],"sourcesContent":["import { DictionaryModel } from '@models/dictionary.model';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport type { DictionaryFilters } from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport { removeObjectKeys } from '@utils/removeObjectKeys';\nimport {\n type DictionaryFields,\n validateDictionary,\n} from '@utils/validation/validateDictionary';\nimport type { ObjectId } from 'mongoose';\nimport type {\n Dictionary,\n DictionaryData,\n DictionaryDocument,\n} from '@/types/dictionary.types';\nimport type { Project } from '@/types/project.types';\n\n/**\n * Finds dictionaries based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of dictionaries matching the filters.\n */\nexport const findDictionaries = async (\n filters: DictionaryFilters,\n skip = 0,\n limit = 100\n): Promise<DictionaryDocument[]> => {\n try {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the filters\n { $match: filters },\n\n // Stage 2: Skip for pagination\n { $skip: skip },\n\n // Stage 3: Limit the number of documents\n { $limit: limit },\n ]);\n\n const formattedResults = dictionaries.map(\n (result) => new DictionaryModel(result)\n );\n\n return formattedResults;\n } catch (error) {\n console.error('Error fetching dictionaries:', error);\n throw error;\n }\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\n/**\n * Finds a dictionary by its ID and includes the 'availableVersions' field.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID with available versions.\n */\nexport const getDictionaryById = async (\n dictionaryId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by ID\n { $match: { _id: dictionaryId } },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n if (!dictionaries.length) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return new DictionaryModel(dictionaries[0]);\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryKey - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\nexport const getDictionaryByKey = async (\n dictionaryKey: string,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaries = await getDictionariesByKeys([dictionaryKey], projectId);\n\n return dictionaries[0];\n};\n\nexport const getDictionariesByKeys = async (\n dictionaryKeys: string[],\n projectId: string | ObjectId\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by key\n { $match: { key: { $in: dictionaryKeys }, projectIds: projectId } },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n if (!dictionaries) {\n throw new GenericError('DICTIONARY_NOT_FOUND', {\n dictionaryKeys,\n projectId,\n });\n }\n\n const formattedResults = dictionaries.map(\n (result) => new DictionaryModel(result)\n );\n\n return formattedResults;\n};\n\nexport const getDictionariesKeys = async (\n projectId: string | ObjectId\n): Promise<string[]> => {\n const dictionaries = await DictionaryModel.find({\n projectIds: projectId,\n }).select('key');\n\n return dictionaries.map((dictionary) => dictionary.key);\n};\n\nexport const getDictionariesByTags = async (\n tags: string[],\n projectId: string | Project['_id']\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by tags\n {\n $match: {\n tags: { $in: tags },\n projectIds: projectId,\n },\n },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n const formattedResults = dictionaries.map(\n (result) => new DictionaryModel(result)\n );\n\n return formattedResults;\n};\n\n/**\n * Counts the total number of dictionaries that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of dictionaries.\n */\nexport const countDictionaries = async (\n filters: DictionaryFilters\n): Promise<number> => {\n const result = await DictionaryModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('DICTIONARY_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new dictionary in the database.\n * @param dictionary - The dictionary data to create.\n * @returns The created dictionary.\n */\nexport const createDictionary = async (\n dictionary: DictionaryData\n): Promise<DictionaryDocument> => {\n const errors = await validateDictionary(dictionary);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n errors,\n });\n }\n\n return await DictionaryModel.create(dictionary);\n};\n\ntype GetExistingDictionaryResult = {\n existingDictionariesKey: string[];\n newDictionariesKey: string[];\n};\n\n/**\n * Gets the existing dictionaries from the provided list of keys.\n * @param dictionariesKeys - List of dictionary keys to check.\n * @param projectId - The ID of the project to check the dictionaries against.\n * @returns The existing dictionaries and the new dictionaries.\n */\nexport const getExistingDictionaryKey = async (\n dictionariesKeys: string[],\n projectId: string | ObjectId\n): Promise<GetExistingDictionaryResult> => {\n // Fetch dictionaries from the database where the key is in the provided list\n const existingDictionaries = await DictionaryModel.find({\n key: { $in: dictionariesKeys },\n projectIds: projectId,\n });\n\n // Map existing dictionaries to a LocalDictionary object\n const existingDictionariesKey: string[] = [];\n const newDictionariesKey: string[] = [];\n\n for (const key of dictionariesKeys) {\n const isDictionaryExist = existingDictionaries.some(\n (dictionary) => dictionary.key === key\n );\n\n if (isDictionaryExist) {\n existingDictionariesKey.push(key);\n } else {\n newDictionariesKey.push(key);\n }\n }\n\n return { existingDictionariesKey, newDictionariesKey };\n};\n\n/**\n * Updates an existing dictionary in the database by its ID.\n * @param dictionaryId - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryById = async (\n dictionaryId: string | ObjectId,\n dictionary: Partial<Dictionary>\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ['_id']);\n\n const updatedKeys = Object.keys(dictionaryToUpdate) as DictionaryFields;\n const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryId,\n errors,\n });\n }\n\n const result = await DictionaryModel.updateOne(\n { _id: dictionaryId },\n dictionaryToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryId });\n }\n\n const updatedDictionary = await getDictionaryById(dictionaryId);\n\n return updatedDictionary;\n};\n\n/**\n * Updates an existing dictionary in the database by its key.\n * @param dictionaryKey - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryByKey = async (\n dictionaryKey: string,\n dictionary: Partial<Dictionary>,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ['_id']);\n\n const updatedKeys = Object.keys(dictionaryToUpdate) as DictionaryFields;\n const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryKey,\n projectId,\n errors,\n });\n }\n\n const result = await DictionaryModel.updateOne(\n { key: dictionaryKey, projectIds: projectId },\n dictionaryToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryKey });\n }\n\n const updatedDictionary = await getDictionaryByKey(dictionaryKey, projectId);\n\n return updatedDictionary;\n};\n\n/**\n * Deletes a dictionary from the database by its ID.\n * @param dictionaryId - The ID of the dictionary to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteDictionaryById = async (\n dictionaryId: string\n): Promise<DictionaryDocument> => {\n const dictionary = await DictionaryModel.findByIdAndDelete(dictionaryId);\n\n if (!dictionary) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return dictionary;\n};\n\n// Function to extract the numeric part of the version\nconst getVersionNumber = (version: string): number => {\n const match = version.match(/^v(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid version format: ${version}`);\n }\n return parseInt(match[1], 10);\n};\n\nexport const incrementVersion = (dictionary: Dictionary): string => {\n const VERSION_PREFIX = 'v';\n\n const availableVersions = [...(dictionary.content.keys() ?? [])];\n const lastVersion = availableVersions[availableVersions.length - 1];\n\n // Start with the next version number\n let newNumber = getVersionNumber(lastVersion) + 1;\n let newVersion = `${VERSION_PREFIX}${newNumber}`;\n\n // Loop until a unique version is found\n while (availableVersions.includes(newVersion)) {\n newNumber += 1;\n newVersion = `${VERSION_PREFIX}${newNumber}`;\n }\n\n return newVersion;\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/services/dictionary.service.ts"],"sourcesContent":["import type {\n Dictionary,\n DictionaryData,\n DictionaryDocument,\n} from '@/types/dictionary.types';\nimport type { Project } from '@/types/project.types';\nimport { DictionaryModel } from '@models/dictionary.model';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport type { DictionaryFilters } from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport { removeObjectKeys } from '@utils/removeObjectKeys';\nimport {\n validateDictionary,\n type DictionaryFields,\n} from '@utils/validation/validateDictionary';\nimport { Types, type ObjectId } from 'mongoose';\n\n/**\n * Finds dictionaries based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of dictionaries matching the filters.\n */\nexport const findDictionaries = async (\n filters: DictionaryFilters,\n skip = 0,\n limit = 100\n): Promise<DictionaryDocument[]> => {\n try {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the filters\n { $match: filters },\n\n // Stage 2: Skip for pagination\n { $skip: skip },\n\n // Stage 3: Limit the number of documents\n { $limit: limit },\n ]);\n\n const formattedResults = dictionaries.map(\n (result) => new DictionaryModel(result)\n );\n\n return formattedResults;\n } catch (error) {\n console.error('Error fetching dictionaries:', error);\n throw error;\n }\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\n/**\n * Finds a dictionary by its ID and includes the 'availableVersions' field.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID with available versions.\n */\nexport const getDictionaryById = async (\n dictionaryId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const id = Types.ObjectId.isValid(dictionaryId as string)\n ? new Types.ObjectId(dictionaryId as string)\n : dictionaryId;\n\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by ID\n { $match: { _id: id } },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n console.log('dictionaries', dictionaries);\n\n if (!dictionaries.length) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return new DictionaryModel(dictionaries[0]);\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryKey - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\nexport const getDictionaryByKey = async (\n dictionaryKey: string,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaries = await getDictionariesByKeys([dictionaryKey], projectId);\n\n return dictionaries[0];\n};\n\nexport const getDictionariesByKeys = async (\n dictionaryKeys: string[],\n projectId: string | ObjectId\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by key\n { $match: { key: { $in: dictionaryKeys }, projectIds: projectId } },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n if (!dictionaries) {\n throw new GenericError('DICTIONARY_NOT_FOUND', {\n dictionaryKeys,\n projectId,\n });\n }\n\n const formattedResults = dictionaries.map(\n (result) => new DictionaryModel(result)\n );\n\n return formattedResults;\n};\n\nexport const getDictionariesKeys = async (\n projectId: string | ObjectId\n): Promise<string[]> => {\n const dictionaries = await DictionaryModel.find({\n projectIds: projectId,\n }).select('key');\n\n return dictionaries.map((dictionary) => dictionary.key);\n};\n\nexport const getDictionariesByTags = async (\n tags: string[],\n projectId: string | Project['_id']\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by tags\n {\n $match: {\n tags: { $in: tags },\n projectIds: projectId,\n },\n },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n const formattedResults = dictionaries.map(\n (result) => new DictionaryModel(result)\n );\n\n return formattedResults;\n};\n\n/**\n * Counts the total number of dictionaries that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of dictionaries.\n */\nexport const countDictionaries = async (\n filters: DictionaryFilters\n): Promise<number> => {\n const result = await DictionaryModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('DICTIONARY_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new dictionary in the database.\n * @param dictionary - The dictionary data to create.\n * @returns The created dictionary.\n */\nexport const createDictionary = async (\n dictionary: DictionaryData\n): Promise<DictionaryDocument> => {\n const errors = await validateDictionary(dictionary);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n errors,\n });\n }\n\n return await DictionaryModel.create(dictionary);\n};\n\ntype GetExistingDictionaryResult = {\n existingDictionariesKey: string[];\n newDictionariesKey: string[];\n};\n\n/**\n * Gets the existing dictionaries from the provided list of keys.\n * @param dictionariesKeys - List of dictionary keys to check.\n * @param projectId - The ID of the project to check the dictionaries against.\n * @returns The existing dictionaries and the new dictionaries.\n */\nexport const getExistingDictionaryKey = async (\n dictionariesKeys: string[],\n projectId: string | ObjectId\n): Promise<GetExistingDictionaryResult> => {\n // Fetch dictionaries from the database where the key is in the provided list\n const existingDictionaries = await DictionaryModel.find({\n key: { $in: dictionariesKeys },\n projectIds: projectId,\n });\n\n // Map existing dictionaries to a LocalDictionary object\n const existingDictionariesKey: string[] = [];\n const newDictionariesKey: string[] = [];\n\n for (const key of dictionariesKeys) {\n const isDictionaryExist = existingDictionaries.some(\n (dictionary) => dictionary.key === key\n );\n\n if (isDictionaryExist) {\n existingDictionariesKey.push(key);\n } else {\n newDictionariesKey.push(key);\n }\n }\n\n return { existingDictionariesKey, newDictionariesKey };\n};\n\n/**\n * Updates an existing dictionary in the database by its ID.\n * @param dictionaryId - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryById = async (\n dictionaryId: string | ObjectId,\n dictionary: Partial<Dictionary>\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ['_id']);\n\n const updatedKeys = Object.keys(dictionaryToUpdate) as DictionaryFields;\n const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryId,\n errors,\n });\n }\n\n const result = await DictionaryModel.updateOne(\n { _id: dictionaryId },\n dictionaryToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryId });\n }\n\n const updatedDictionary = await getDictionaryById(dictionaryId);\n\n return updatedDictionary;\n};\n\n/**\n * Updates an existing dictionary in the database by its key.\n * @param dictionaryKey - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryByKey = async (\n dictionaryKey: string,\n dictionary: Partial<Dictionary>,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ['_id']);\n\n const updatedKeys = Object.keys(dictionaryToUpdate) as DictionaryFields;\n const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryKey,\n projectId,\n errors,\n });\n }\n\n const result = await DictionaryModel.updateOne(\n { key: dictionaryKey, projectIds: projectId },\n dictionaryToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryKey });\n }\n\n const updatedDictionary = await getDictionaryByKey(dictionaryKey, projectId);\n\n return updatedDictionary;\n};\n\n/**\n * Deletes a dictionary from the database by its ID.\n * @param dictionaryId - The ID of the dictionary to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteDictionaryById = async (\n dictionaryId: string\n): Promise<DictionaryDocument> => {\n console.log('dictionaryId', dictionaryId);\n\n const dictionary = await DictionaryModel.findByIdAndDelete(dictionaryId);\n\n console.log('dictionary', dictionary);\n\n if (!dictionary) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return dictionary;\n};\n\n// Function to extract the numeric part of the version\nconst getVersionNumber = (version: string): number => {\n const match = version.match(/^v(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid version format: ${version}`);\n }\n return parseInt(match[1], 10);\n};\n\nexport const incrementVersion = (dictionary: Dictionary): string => {\n const VERSION_PREFIX = 'v';\n\n const availableVersions = [...(dictionary.content.keys() ?? [])];\n const lastVersion = availableVersions[availableVersions.length - 1];\n\n // Start with the next version number\n let newNumber = getVersionNumber(lastVersion) + 1;\n let newVersion = `${VERSION_PREFIX}${newNumber}`;\n\n // Loop until a unique version is found\n while (availableVersions.includes(newVersion)) {\n newNumber += 1;\n newVersion = `${VERSION_PREFIX}${newNumber}`;\n }\n\n return newVersion;\n};\n"],"mappings":"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","names":[]}
@@ -1,4 +1,3 @@
1
- import crypto from "crypto";
2
1
  import { logger } from "./../logger/index.mjs";
3
2
  import {
4
3
  Cookies,
@@ -9,7 +8,8 @@ import {
9
8
  import { ensureMongoDocumentToObject } from "./../utils/ensureMongoDocumentToObject.mjs";
10
9
  import { GenericError } from "./../utils/errors/index.mjs";
11
10
  import { mapUserToAPI } from "./../utils/mapper/user.mjs";
12
- import { hash, genSalt, compare } from "bcrypt";
11
+ import { compare, genSalt, hash } from "bcryptjs";
12
+ import crypto from "crypto";
13
13
  import { t } from "express-intlayer";
14
14
  import jwt from "jsonwebtoken";
15
15
  import { v4 as uuidv4 } from "uuid";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/sessionAuth.service.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport {\n Cookies,\n getClearCookieOptions,\n getCookieOptions,\n MAX_AGE,\n} from '@utils/cookies';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hash, genSalt, compare } from 'bcrypt';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t } from 'express-intlayer';\nimport jwt from 'jsonwebtoken';\nimport type { ObjectId } from 'mongoose';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getUserByEmail, getUserById, updateUserById } from './user.service';\nimport type { Organization } from '@/types/organization.types';\nimport type { Project } from '@/types/project.types';\nimport type {\n SessionProviders,\n EmailPasswordSessionProvider,\n GoogleSessionProvider,\n GithubSessionProvider,\n Session,\n} from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Adds a session to a user or updates the existing one.\n * @param user - User object.\n * @returns Updated user object.\n */\nexport const addSession = async (user: User): Promise<UserDocument> => {\n const userSessionToken = uuidv4();\n\n const session: Session = {\n sessionToken: userSessionToken,\n expires: new Date(Date.now() + MAX_AGE),\n };\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\nexport const removeSession = async (user: User): Promise<UserDocument> => {\n const session = undefined;\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\n/**\n * Set user auth locals object\n * @param res - Express response object.\n * @param user - User object.\n */\nexport const setUserAuth = async (res: Response, user: User) => {\n const formattedUser = mapUserToAPI(user);\n\n const userToken = jwt.sign(formattedUser, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!userToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_USER', { user });\n }\n\n const cookieOptions = getCookieOptions();\n\n res.cookie(Cookies.JWT_USER, userToken, cookieOptions);\n\n const userWithSession: UserDocument = await addSession(user);\n\n const userSessionToken = userWithSession.session?.sessionToken;\n\n res.cookie(Cookies.JWT_AUTH, userSessionToken, cookieOptions);\n\n res.locals.user = user;\n logger.info(\n `User logged in - User: Name: ${user.name}, id: ${String(user._id)}`\n );\n};\n\n/**\n * Clears the JWT auth cookies and user locals object.\n * @param res - Express response object.\n */\nexport const clearUserAuth = async (res: ResponseWithInformation) => {\n const { user } = res.locals;\n const cookiesOptions = getClearCookieOptions();\n\n if (user) {\n await removeSession(user);\n }\n\n res.cookie(Cookies.JWT_AUTH, '', cookiesOptions);\n res.cookie(Cookies.JWT_USER, '', cookiesOptions);\n\n res.locals.user = null;\n res.locals.authType = null;\n};\n\n/**\n *\n * @param res\n * @param organization\n * @returns\n */\nexport const setOrganizationAuth = (\n res: ResponseWithInformation,\n organization: Organization\n) => {\n const organizationData = {\n _id: organization._id,\n name: organization.name,\n };\n\n const organizationToken = jwt.sign(\n organizationData,\n process.env.JWT_TOKEN_SECRET!,\n {\n expiresIn: MAX_AGE,\n }\n );\n\n if (!organizationToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_ORGANIZATION', {\n organization,\n });\n }\n\n res.cookie(Cookies.JWT_ORGANIZATION, organizationToken, getCookieOptions());\n\n res.locals.organization = organization;\n};\n\n/**\n * Clears the JWT organization cookies and organization locals object.\n * @param res - Express response object.\n */\nexport const clearOrganizationAuth = (res: ResponseWithInformation) => {\n res.locals.organization = null;\n\n res.cookie(Cookies.JWT_ORGANIZATION, '', getClearCookieOptions());\n};\n\n/**\n * Set project auth locals object\n * @param res - Express response object.\n * @param project - Project object.\n */\nexport const setProjectAuth = (\n res: ResponseWithInformation,\n project: Project\n) => {\n const { organization } = res.locals;\n const projectData = {\n _id: project._id,\n name: project.name,\n };\n\n const projectToken = jwt.sign(projectData, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!projectToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_PROJECT', {\n project,\n });\n }\n\n res.cookie(Cookies.JWT_PROJECT, projectToken, getCookieOptions());\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n project,\n });\n }\n\n if (\n // if the project is not in the organization's projects\n String(organization._id) !== String(project.organizationId)\n ) {\n throw new GenericError('JWT_TOKEN_ORGANIZATION_MISMATCH_PROJECT', {\n project,\n });\n }\n\n res.locals.project = project;\n};\n\n/**\n * Clears the JWT project cookies and project locals object.\n * @param res - Express response object.\n */\nexport const clearProjectAuth = (res: Response) => {\n res.locals.project = null;\n\n res.cookie(Cookies.JWT_PROJECT, '', getClearCookieOptions());\n};\n\n/**\n * Generates a random secret string of a specified length.\n * @param length - The length of the secret.\n * @returns The generated secret string.\n */\nexport const generateSecret = (length: number): string => {\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n characters.charAt(Math.floor(Math.random() * characters.length))\n ).join('');\n};\n\n/**\n * Handles a password reset request for a user.\n * @param email - The user's email.\n * @param organization - The organization associated with the user.\n * @returns The user object or null if no user was found.\n */\nexport const requestPasswordReset = async (\n email: string\n): Promise<User | null> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { email });\n }\n\n return updateUserProvider(user._id as unknown as string, 'email', {\n secret: generateSecret(35),\n });\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetUserPassword = async (\n userId: string | ObjectId,\n secret: string,\n newPassword: string\n): Promise<User> => {\n const emailAndPasswordProvider = await getUserProvider(userId, 'email');\n\n if (!emailAndPasswordProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', { userId });\n }\n\n if (!emailAndPasswordProvider.secret) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_DEFINED', { userId });\n }\n\n if (\n !crypto.timingSafeEqual(\n Buffer.from(emailAndPasswordProvider.secret),\n Buffer.from(secret)\n )\n ) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_VALID', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n secret,\n });\n\n return updatedUser;\n};\n\ntype UserProvider<T extends SessionProviders['provider']> = T extends 'email'\n ? EmailPasswordSessionProvider\n : T extends 'google'\n ? GoogleSessionProvider\n : T extends 'github'\n ? GithubSessionProvider\n : SessionProviders;\n\n/**\n * Gets a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to get.\n * @returns The user's provider.\n */\nexport const getUserProvider = async <T extends SessionProviders['provider']>(\n userId: string | ObjectId,\n provider: T,\n providerAccountId?: string\n): Promise<UserProvider<T> | null> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const userProvider = user.provider?.find(\n (providerEl) =>\n (providerEl.provider === provider && !providerAccountId) ||\n (providerAccountId &&\n (providerEl as GithubSessionProvider).providerAccountId ===\n providerAccountId)\n );\n\n return (userProvider as UserProvider<T>) ?? null;\n};\n\n/**\n * Formats the given fields of a user's provider.\n * @param provider - The provider to update.\n * @param user - The user object.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user provider.\n */\nexport const formatUserProviderUpdate = <\n T extends SessionProviders['provider'],\n>(\n provider: T,\n user: Partial<User>,\n providerUpdate: Partial<UserProvider<T>>\n): User['provider'] => {\n const userProvider: SessionProviders[] = ensureMongoDocumentToObject<\n SessionProviders[]\n >(user.provider ?? []);\n\n const userProviderToUpdate = userProvider?.find(\n (providerEl) => providerEl.provider === provider\n );\n\n let updatedProvider: User['provider'];\n\n if (userProviderToUpdate) {\n const otherProviders =\n user.provider?.filter((p) => p.provider !== provider) ?? [];\n\n updatedProvider = [\n ...otherProviders,\n { ...userProviderToUpdate, ...providerUpdate, provider },\n ];\n } else {\n updatedProvider = [\n ...(user.provider ?? []),\n { ...providerUpdate, provider } as SessionProviders,\n ];\n }\n\n return updatedProvider;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to update.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const updateUserProvider = async <\n T extends SessionProviders['provider'],\n>(\n userId: string | ObjectId,\n provider: T,\n providerUpdate: Partial<UserProvider<T>>\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const formattedProviderToUpdate = formatUserProviderUpdate(\n provider,\n user,\n providerUpdate\n );\n\n const updatedUser: UserDocument = await updateUserById(userId, {\n provider: formattedProviderToUpdate,\n });\n\n logger.info(\n `User provider updated - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const addUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(userId, provider.provider);\n\n if (existingProvider) {\n throw new GenericError('USER_PROVIDER_ALREADY_EXISTS', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = [...(user.provider ?? []), provider];\n\n const updatedUser = await updateUserById(userId, {\n provider: updatedProvider,\n });\n\n logger.info(\n `User provider added - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider.provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Removes a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to remove.\n * @returns The updated user.\n */\nexport const removeUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders['provider'],\n providerAccountId?: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(\n userId,\n provider,\n providerAccountId\n );\n\n if (!existingProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = user.provider?.filter(\n (p) =>\n p.provider !== provider &&\n (!providerAccountId ||\n (providerAccountId &&\n (p as GithubSessionProvider).providerAccountId !== providerAccountId))\n );\n\n return await updateUserById(userId, {\n provider: updatedProvider,\n });\n};\n\ntype TestUserPasswordResult = { user: User | null; error?: string };\n\n/**\n * Logs in a user.\n * @param email - The user's email.\n * @param password - The user's password.\n * @returns The user object.\n */\nexport const testUserPassword = async (\n email: string,\n password: string\n): Promise<TestUserPasswordResult> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n const errorMessages = {\n en: `User not found - ${email}`,\n fr: `Utilisateur non trouvé - ${email}`,\n es: `Usuario no encontrado - ${email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const userEmailPasswordProvider = user.provider?.find(\n (provider) => provider.provider === 'email'\n );\n\n if (!userEmailPasswordProvider?.passwordHash) {\n const errorMessages = {\n en: `User request to login but no password defined: ${user.email}`,\n fr: `Demande de connexion d'utilisateur mais pas de mot de passe défini : ${user.email}`,\n es: `Solicitud de inicio de sesión de usuario pero no se define la contraseña : ${user.email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const isMatch = await compare(\n password,\n userEmailPasswordProvider.passwordHash\n );\n\n if (!isMatch) {\n const errorMessages = {\n en: `Incorrect email or password: ${email}`,\n fr: `Email ou mot de passe incorrect : ${email}`,\n es: `Correo electrónico o contraseña incorrecta : ${email}`,\n };\n\n logger.error(errorMessages.en);\n\n // Await a random time to prevent brute force attacks\n const randomNumber = Math.floor(Math.random() * 1000) + 1000;\n await new Promise((resolve) => setTimeout(resolve, randomNumber));\n\n return { user: null, error: t(errorMessages) };\n }\n\n return { user };\n};\n\n/**\n * Hashes a user's password.\n * @param userWithPasswordNotHashed - The user object with password not hashed.\n * @returns The user object with hashed password.\n */\nexport const hashUserPassword = async (\n userWithPasswordNotHashed: UserWithPasswordNotHashed\n): Promise<Partial<UserDocument>> => {\n const { password, ...user } = userWithPasswordNotHashed;\n\n if (!password) {\n throw new GenericError('USER_PASSWORD_NOT_DEFINED', { user });\n }\n\n const userProvider = formatUserProviderUpdate('email', user, {\n passwordHash: await hash(password, await genSalt()),\n secret: generateSecret(35),\n });\n\n return { ...user, provider: userProvider };\n};\n\n/**\n * Changes a user's password.\n * @param userId - The ID of the user.\n * @param newPassword - The user's new password.\n * @returns The updated user or null if the password change failed.\n */\nexport const changeUserPassword = async (\n userId: string | ObjectId,\n newPassword: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n });\n\n return updatedUser;\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetPassword = async (userId: string, password: string) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: UserDocument = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(password, await genSalt()),\n });\n\n return updatedUser;\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/services/sessionAuth.service.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport {\n Cookies,\n getClearCookieOptions,\n getCookieOptions,\n MAX_AGE,\n} from '@utils/cookies';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { compare, genSalt, hash } from 'bcryptjs';\nimport crypto from 'crypto';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport type { Organization } from '@/types/organization.types';\nimport type { Project } from '@/types/project.types';\nimport type {\n EmailPasswordSessionProvider,\n GithubSessionProvider,\n GoogleSessionProvider,\n Session,\n SessionProviders,\n} from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\nimport { t } from 'express-intlayer';\nimport jwt from 'jsonwebtoken';\nimport type { ObjectId } from 'mongoose';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getUserByEmail, getUserById, updateUserById } from './user.service';\n\n/**\n * Adds a session to a user or updates the existing one.\n * @param user - User object.\n * @returns Updated user object.\n */\nexport const addSession = async (user: User): Promise<UserDocument> => {\n const userSessionToken = uuidv4();\n\n const session: Session = {\n sessionToken: userSessionToken,\n expires: new Date(Date.now() + MAX_AGE),\n };\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\nexport const removeSession = async (user: User): Promise<UserDocument> => {\n const session = undefined;\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\n/**\n * Set user auth locals object\n * @param res - Express response object.\n * @param user - User object.\n */\nexport const setUserAuth = async (res: Response, user: User) => {\n const formattedUser = mapUserToAPI(user);\n\n const userToken = jwt.sign(formattedUser, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!userToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_USER', { user });\n }\n\n const cookieOptions = getCookieOptions();\n\n res.cookie(Cookies.JWT_USER, userToken, cookieOptions);\n\n const userWithSession: UserDocument = await addSession(user);\n\n const userSessionToken = userWithSession.session?.sessionToken;\n\n res.cookie(Cookies.JWT_AUTH, userSessionToken, cookieOptions);\n\n res.locals.user = user;\n logger.info(\n `User logged in - User: Name: ${user.name}, id: ${String(user._id)}`\n );\n};\n\n/**\n * Clears the JWT auth cookies and user locals object.\n * @param res - Express response object.\n */\nexport const clearUserAuth = async (res: ResponseWithInformation) => {\n const { user } = res.locals;\n const cookiesOptions = getClearCookieOptions();\n\n if (user) {\n await removeSession(user);\n }\n\n res.cookie(Cookies.JWT_AUTH, '', cookiesOptions);\n res.cookie(Cookies.JWT_USER, '', cookiesOptions);\n\n res.locals.user = null;\n res.locals.authType = null;\n};\n\n/**\n *\n * @param res\n * @param organization\n * @returns\n */\nexport const setOrganizationAuth = (\n res: ResponseWithInformation,\n organization: Organization\n) => {\n const organizationData = {\n _id: organization._id,\n name: organization.name,\n };\n\n const organizationToken = jwt.sign(\n organizationData,\n process.env.JWT_TOKEN_SECRET!,\n {\n expiresIn: MAX_AGE,\n }\n );\n\n if (!organizationToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_ORGANIZATION', {\n organization,\n });\n }\n\n res.cookie(Cookies.JWT_ORGANIZATION, organizationToken, getCookieOptions());\n\n res.locals.organization = organization;\n};\n\n/**\n * Clears the JWT organization cookies and organization locals object.\n * @param res - Express response object.\n */\nexport const clearOrganizationAuth = (res: ResponseWithInformation) => {\n res.locals.organization = null;\n\n res.cookie(Cookies.JWT_ORGANIZATION, '', getClearCookieOptions());\n};\n\n/**\n * Set project auth locals object\n * @param res - Express response object.\n * @param project - Project object.\n */\nexport const setProjectAuth = (\n res: ResponseWithInformation,\n project: Project\n) => {\n const { organization } = res.locals;\n const projectData = {\n _id: project._id,\n name: project.name,\n };\n\n const projectToken = jwt.sign(projectData, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!projectToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_PROJECT', {\n project,\n });\n }\n\n res.cookie(Cookies.JWT_PROJECT, projectToken, getCookieOptions());\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n project,\n });\n }\n\n if (\n // if the project is not in the organization's projects\n String(organization._id) !== String(project.organizationId)\n ) {\n throw new GenericError('JWT_TOKEN_ORGANIZATION_MISMATCH_PROJECT', {\n project,\n });\n }\n\n res.locals.project = project;\n};\n\n/**\n * Clears the JWT project cookies and project locals object.\n * @param res - Express response object.\n */\nexport const clearProjectAuth = (res: Response) => {\n res.locals.project = null;\n\n res.cookie(Cookies.JWT_PROJECT, '', getClearCookieOptions());\n};\n\n/**\n * Generates a random secret string of a specified length.\n * @param length - The length of the secret.\n * @returns The generated secret string.\n */\nexport const generateSecret = (length: number): string => {\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n characters.charAt(Math.floor(Math.random() * characters.length))\n ).join('');\n};\n\n/**\n * Handles a password reset request for a user.\n * @param email - The user's email.\n * @param organization - The organization associated with the user.\n * @returns The user object or null if no user was found.\n */\nexport const requestPasswordReset = async (\n email: string\n): Promise<User | null> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { email });\n }\n\n return updateUserProvider(user._id as unknown as string, 'email', {\n secret: generateSecret(35),\n });\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetUserPassword = async (\n userId: string | ObjectId,\n secret: string,\n newPassword: string\n): Promise<User> => {\n const emailAndPasswordProvider = await getUserProvider(userId, 'email');\n\n if (!emailAndPasswordProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', { userId });\n }\n\n if (!emailAndPasswordProvider.secret) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_DEFINED', { userId });\n }\n\n if (\n !crypto.timingSafeEqual(\n Buffer.from(emailAndPasswordProvider.secret),\n Buffer.from(secret)\n )\n ) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_VALID', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n secret,\n });\n\n return updatedUser;\n};\n\ntype UserProvider<T extends SessionProviders['provider']> = T extends 'email'\n ? EmailPasswordSessionProvider\n : T extends 'google'\n ? GoogleSessionProvider\n : T extends 'github'\n ? GithubSessionProvider\n : SessionProviders;\n\n/**\n * Gets a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to get.\n * @returns The user's provider.\n */\nexport const getUserProvider = async <T extends SessionProviders['provider']>(\n userId: string | ObjectId,\n provider: T,\n providerAccountId?: string\n): Promise<UserProvider<T> | null> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const userProvider = user.provider?.find(\n (providerEl) =>\n (providerEl.provider === provider && !providerAccountId) ||\n (providerAccountId &&\n (providerEl as GithubSessionProvider).providerAccountId ===\n providerAccountId)\n );\n\n return (userProvider as UserProvider<T>) ?? null;\n};\n\n/**\n * Formats the given fields of a user's provider.\n * @param provider - The provider to update.\n * @param user - The user object.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user provider.\n */\nexport const formatUserProviderUpdate = <\n T extends SessionProviders['provider'],\n>(\n provider: T,\n user: Partial<User>,\n providerUpdate: Partial<UserProvider<T>>\n): User['provider'] => {\n const userProvider: SessionProviders[] = ensureMongoDocumentToObject<\n SessionProviders[]\n >(user.provider ?? []);\n\n const userProviderToUpdate = userProvider?.find(\n (providerEl) => providerEl.provider === provider\n );\n\n let updatedProvider: User['provider'];\n\n if (userProviderToUpdate) {\n const otherProviders =\n user.provider?.filter((p) => p.provider !== provider) ?? [];\n\n updatedProvider = [\n ...otherProviders,\n { ...userProviderToUpdate, ...providerUpdate, provider },\n ];\n } else {\n updatedProvider = [\n ...(user.provider ?? []),\n { ...providerUpdate, provider } as SessionProviders,\n ];\n }\n\n return updatedProvider;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to update.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const updateUserProvider = async <\n T extends SessionProviders['provider'],\n>(\n userId: string | ObjectId,\n provider: T,\n providerUpdate: Partial<UserProvider<T>>\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const formattedProviderToUpdate = formatUserProviderUpdate(\n provider,\n user,\n providerUpdate\n );\n\n const updatedUser: UserDocument = await updateUserById(userId, {\n provider: formattedProviderToUpdate,\n });\n\n logger.info(\n `User provider updated - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const addUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(userId, provider.provider);\n\n if (existingProvider) {\n throw new GenericError('USER_PROVIDER_ALREADY_EXISTS', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = [...(user.provider ?? []), provider];\n\n const updatedUser = await updateUserById(userId, {\n provider: updatedProvider,\n });\n\n logger.info(\n `User provider added - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider.provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Removes a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to remove.\n * @returns The updated user.\n */\nexport const removeUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders['provider'],\n providerAccountId?: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(\n userId,\n provider,\n providerAccountId\n );\n\n if (!existingProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = user.provider?.filter(\n (p) =>\n p.provider !== provider &&\n (!providerAccountId ||\n (providerAccountId &&\n (p as GithubSessionProvider).providerAccountId !== providerAccountId))\n );\n\n return await updateUserById(userId, {\n provider: updatedProvider,\n });\n};\n\ntype TestUserPasswordResult = { user: User | null; error?: string };\n\n/**\n * Logs in a user.\n * @param email - The user's email.\n * @param password - The user's password.\n * @returns The user object.\n */\nexport const testUserPassword = async (\n email: string,\n password: string\n): Promise<TestUserPasswordResult> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n const errorMessages = {\n en: `User not found - ${email}`,\n fr: `Utilisateur non trouvé - ${email}`,\n es: `Usuario no encontrado - ${email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const userEmailPasswordProvider = user.provider?.find(\n (provider) => provider.provider === 'email'\n );\n\n if (!userEmailPasswordProvider?.passwordHash) {\n const errorMessages = {\n en: `User request to login but no password defined: ${user.email}`,\n fr: `Demande de connexion d'utilisateur mais pas de mot de passe défini : ${user.email}`,\n es: `Solicitud de inicio de sesión de usuario pero no se define la contraseña : ${user.email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const isMatch = await compare(\n password,\n userEmailPasswordProvider.passwordHash\n );\n\n if (!isMatch) {\n const errorMessages = {\n en: `Incorrect email or password: ${email}`,\n fr: `Email ou mot de passe incorrect : ${email}`,\n es: `Correo electrónico o contraseña incorrecta : ${email}`,\n };\n\n logger.error(errorMessages.en);\n\n // Await a random time to prevent brute force attacks\n const randomNumber = Math.floor(Math.random() * 1000) + 1000;\n await new Promise((resolve) => setTimeout(resolve, randomNumber));\n\n return { user: null, error: t(errorMessages) };\n }\n\n return { user };\n};\n\n/**\n * Hashes a user's password.\n * @param userWithPasswordNotHashed - The user object with password not hashed.\n * @returns The user object with hashed password.\n */\nexport const hashUserPassword = async (\n userWithPasswordNotHashed: UserWithPasswordNotHashed\n): Promise<Partial<UserDocument>> => {\n const { password, ...user } = userWithPasswordNotHashed;\n\n if (!password) {\n throw new GenericError('USER_PASSWORD_NOT_DEFINED', { user });\n }\n\n const userProvider = formatUserProviderUpdate('email', user, {\n passwordHash: await hash(password, await genSalt()),\n secret: generateSecret(35),\n });\n\n return { ...user, provider: userProvider };\n};\n\n/**\n * Changes a user's password.\n * @param userId - The ID of the user.\n * @param newPassword - The user's new password.\n * @returns The updated user or null if the password change failed.\n */\nexport const changeUserPassword = async (\n userId: string | ObjectId,\n newPassword: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n });\n\n return updatedUser;\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetPassword = async (userId: string, password: string) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: UserDocument = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(password, await genSalt()),\n });\n\n return updatedUser;\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,115 @@
1
+ import { anthropic } from "@ai-sdk/anthropic";
2
+ import { deepseek } from "@ai-sdk/deepseek";
3
+ import { google } from "@ai-sdk/google";
4
+ import { mistral } from "@ai-sdk/mistral";
5
+ import { openai } from "@ai-sdk/openai";
6
+ import { logger } from "./../../logger/index.mjs";
7
+ var AIProvider = /* @__PURE__ */ ((AIProvider2) => {
8
+ AIProvider2["OPENAI"] = "openai";
9
+ AIProvider2["ANTHROPIC"] = "anthropic";
10
+ AIProvider2["MISTRAL"] = "mistral";
11
+ AIProvider2["DEEPSEEK"] = "deepseek";
12
+ AIProvider2["GEMINI"] = "gemini";
13
+ return AIProvider2;
14
+ })(AIProvider || {});
15
+ const getAIConfig = async (options) => {
16
+ try {
17
+ const {
18
+ provider = "openai" /* OPENAI */,
19
+ model,
20
+ temperature = 0.1
21
+ } = options ?? {};
22
+ let defaultModel;
23
+ switch (provider) {
24
+ case "openai" /* OPENAI */:
25
+ defaultModel = "gpt-4o-mini";
26
+ break;
27
+ case "anthropic" /* ANTHROPIC */:
28
+ defaultModel = "claude-3-haiku-20240307";
29
+ break;
30
+ case "mistral" /* MISTRAL */:
31
+ defaultModel = "mistral-large-latest";
32
+ break;
33
+ case "deepseek" /* DEEPSEEK */:
34
+ defaultModel = "deepseek-coder";
35
+ break;
36
+ case "gemini" /* GEMINI */:
37
+ defaultModel = "gemini-1.5-pro";
38
+ break;
39
+ default:
40
+ defaultModel = "gpt-4o-mini";
41
+ }
42
+ if (!options?.apiKey) {
43
+ logger.error(`API key for ${provider} is missing`);
44
+ return void 0;
45
+ }
46
+ if (provider === "openai" /* OPENAI */) {
47
+ return {
48
+ model: openai(model ?? defaultModel),
49
+ temperature
50
+ };
51
+ } else {
52
+ try {
53
+ switch (provider) {
54
+ case "anthropic" /* ANTHROPIC */:
55
+ try {
56
+ return {
57
+ model: anthropic(model ?? defaultModel),
58
+ temperature
59
+ };
60
+ } catch (err) {
61
+ throw new Error(
62
+ "Failed to load @ai-sdk/anthropic. Please install it with: npm install @ai-sdk/anthropic"
63
+ );
64
+ }
65
+ case "mistral" /* MISTRAL */:
66
+ try {
67
+ return {
68
+ model: mistral(model ?? defaultModel),
69
+ temperature
70
+ };
71
+ } catch (err) {
72
+ throw new Error(
73
+ "Failed to load @ai-sdk/mistral. Please install it with: npm install @ai-sdk/mistral"
74
+ );
75
+ }
76
+ case "deepseek" /* DEEPSEEK */:
77
+ try {
78
+ return {
79
+ model: deepseek(model ?? defaultModel),
80
+ temperature
81
+ };
82
+ } catch (err) {
83
+ throw new Error(
84
+ "Failed to load @ai-sdk/deepseek. Please install it with: npm install @ai-sdk/deepseek"
85
+ );
86
+ }
87
+ case "gemini" /* GEMINI */:
88
+ try {
89
+ return {
90
+ model: google(model ?? defaultModel),
91
+ temperature
92
+ };
93
+ } catch (err) {
94
+ throw new Error(
95
+ "Failed to load @ai-sdk/google. Please install it with: npm install @ai-sdk/google"
96
+ );
97
+ }
98
+ default:
99
+ throw new Error(`Provider ${provider} not supported`);
100
+ }
101
+ } catch (error) {
102
+ logger.error(`Error loading SDK for provider ${provider}:`, error);
103
+ return void 0;
104
+ }
105
+ }
106
+ } catch (error) {
107
+ logger.error("Error configuring AI model:", error);
108
+ return void 0;
109
+ }
110
+ };
111
+ export {
112
+ AIProvider,
113
+ getAIConfig
114
+ };
115
+ //# sourceMappingURL=aiSdk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/utils/AI/aiSdk.ts"],"sourcesContent":["import { anthropic } from '@ai-sdk/anthropic';\nimport { deepseek } from '@ai-sdk/deepseek';\nimport { google } from '@ai-sdk/google';\nimport { mistral } from '@ai-sdk/mistral';\nimport { openai } from '@ai-sdk/openai';\nimport { logger } from '@logger';\n\n/**\n * Supported AI models\n */\nexport type Model =\n // OpenAI Models\n | 'gpt-4o-mini'\n | 'gpt-4o'\n | 'gpt-4.1'\n | 'gpt-4.1-mini'\n | 'gpt-4.1-nano'\n | 'gpt-4.5'\n | 'gpt-3.5-turbo'\n | 'gpt-4-turbo-preview'\n | 'gpt-4-vision-preview'\n | 'gpt-4o-audio-preview'\n | 'gpt-4o-mini-audio-preview'\n | 'o1-mini'\n | 'o1'\n | 'o1-pro'\n | 'o3-mini'\n | 'o3-mini-high'\n | 'o3'\n | 'o4-mini'\n | 'o4-mini-high'\n // Anthropic Models\n | 'claude-3-haiku-20240307'\n | 'claude-3-sonnet-20240229'\n | 'claude-3-opus-20240229'\n // Mistral Models\n | 'mistral-tiny'\n | 'mistral-small'\n | 'mistral-small-3.1'\n | 'mistral-medium'\n | 'mistral-medium-3'\n | 'mistral-large'\n | 'mistral-large-2'\n | 'mistral-large-latest'\n | 'codestral'\n | 'codestral-mamba'\n | 'mixtral-8x7b'\n | 'mixtral-8x22b'\n | 'mathstral-7b'\n | 'pixtral-large'\n // DeepSeek Models\n | 'deepseek-coder'\n | 'deepseek-chat'\n | 'deepseek-v3'\n // Google Models\n | 'gemini-1.0-pro'\n | 'gemini-1.5-pro'\n | 'gemini-1.5-flash'\n | (string & {});\n\n/**\n * Supported AI SDK providers\n */\nexport enum AIProvider {\n OPENAI = 'openai',\n ANTHROPIC = 'anthropic',\n MISTRAL = 'mistral',\n DEEPSEEK = 'deepseek',\n GEMINI = 'gemini',\n}\n\n/**\n * Common options for all AI providers\n */\nexport type AIOptions = {\n provider?: AIProvider;\n model?: Model;\n temperature?: number;\n apiKey?: string;\n customPrompt?: string;\n applicationContext?: string;\n};\n\n/**\n * Configuration for AI model based on provider\n */\nexport type AIModelConfig = {\n model: any; // Using any to handle different provider model types\n temperature?: number;\n};\n\n/**\n * Get AI model configuration based on the selected provider and options\n * This function handles the configuration for different AI providers\n *\n * @param options Configuration options including provider, API keys, models and temperature\n * @returns Configured AI model ready to use with generateText\n */\nexport const getAIConfig = async (\n options?: AIOptions\n): Promise<AIModelConfig | undefined> => {\n try {\n const {\n provider = AIProvider.OPENAI,\n model,\n temperature = 0.1,\n } = options ?? {};\n\n // Set default models based on provider\n let defaultModel: string;\n switch (provider) {\n case AIProvider.OPENAI:\n defaultModel = 'gpt-4o-mini';\n break;\n case AIProvider.ANTHROPIC:\n defaultModel = 'claude-3-haiku-20240307';\n break;\n case AIProvider.MISTRAL:\n defaultModel = 'mistral-large-latest';\n break;\n case AIProvider.DEEPSEEK:\n defaultModel = 'deepseek-coder';\n break;\n case AIProvider.GEMINI:\n defaultModel = 'gemini-1.5-pro';\n break;\n default:\n defaultModel = 'gpt-4o-mini';\n }\n\n // Check if API key is provided\n if (!options?.apiKey) {\n logger.error(`API key for ${provider} is missing`);\n return undefined;\n }\n\n // Handle each provider with appropriate model loading\n if (provider === AIProvider.OPENAI) {\n // OpenAI is imported statically at the top\n return {\n model: openai(model ?? defaultModel),\n temperature,\n };\n } else {\n // For other providers, attempt to load using require\n try {\n switch (provider) {\n case AIProvider.ANTHROPIC:\n try {\n return {\n model: anthropic(model ?? defaultModel),\n temperature,\n };\n } catch (err) {\n throw new Error(\n 'Failed to load @ai-sdk/anthropic. Please install it with: npm install @ai-sdk/anthropic'\n );\n }\n\n case AIProvider.MISTRAL:\n try {\n return {\n model: mistral(model ?? defaultModel),\n temperature,\n };\n } catch (err) {\n throw new Error(\n 'Failed to load @ai-sdk/mistral. Please install it with: npm install @ai-sdk/mistral'\n );\n }\n\n case AIProvider.DEEPSEEK:\n try {\n return {\n model: deepseek(model ?? defaultModel),\n temperature,\n };\n } catch (err) {\n throw new Error(\n 'Failed to load @ai-sdk/deepseek. Please install it with: npm install @ai-sdk/deepseek'\n );\n }\n\n case AIProvider.GEMINI:\n try {\n return {\n model: google(model ?? defaultModel),\n temperature,\n };\n } catch (err) {\n throw new Error(\n 'Failed to load @ai-sdk/google. Please install it with: npm install @ai-sdk/google'\n );\n }\n\n default:\n throw new Error(`Provider ${provider} not supported`);\n }\n } catch (error) {\n logger.error(`Error loading SDK for provider ${provider}:`, error);\n return undefined;\n }\n }\n } catch (error) {\n logger.error('Error configuring AI model:', error);\n return undefined;\n }\n};\n"],"mappings":"AAAA,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AACzB,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,cAAc;AA0DhB,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,aAAU;AACV,EAAAA,YAAA,cAAW;AACX,EAAAA,YAAA,YAAS;AALC,SAAAA;AAAA,GAAA;AAmCL,MAAM,cAAc,OACzB,YACuC;AACvC,MAAI;AACF,UAAM;AAAA,MACJ,WAAW;AAAA,MACX;AAAA,MACA,cAAc;AAAA,IAChB,IAAI,WAAW,CAAC;AAGhB,QAAI;AACJ,YAAQ,UAAU;AAAA,MAChB,KAAK;AACH,uBAAe;AACf;AAAA,MACF,KAAK;AACH,uBAAe;AACf;AAAA,MACF,KAAK;AACH,uBAAe;AACf;AAAA,MACF,KAAK;AACH,uBAAe;AACf;AAAA,MACF,KAAK;AACH,uBAAe;AACf;AAAA,MACF;AACE,uBAAe;AAAA,IACnB;AAGA,QAAI,CAAC,SAAS,QAAQ;AACpB,aAAO,MAAM,eAAe,QAAQ,aAAa;AACjD,aAAO;AAAA,IACT;AAGA,QAAI,aAAa,uBAAmB;AAElC,aAAO;AAAA,QACL,OAAO,OAAO,SAAS,YAAY;AAAA,QACnC;AAAA,MACF;AAAA,IACF,OAAO;AAEL,UAAI;AACF,gBAAQ,UAAU;AAAA,UAChB,KAAK;AACH,gBAAI;AACF,qBAAO;AAAA,gBACL,OAAO,UAAU,SAAS,YAAY;AAAA,gBACtC;AAAA,cACF;AAAA,YACF,SAAS,KAAK;AACZ,oBAAM,IAAI;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,UAEF,KAAK;AACH,gBAAI;AACF,qBAAO;AAAA,gBACL,OAAO,QAAQ,SAAS,YAAY;AAAA,gBACpC;AAAA,cACF;AAAA,YACF,SAAS,KAAK;AACZ,oBAAM,IAAI;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,UAEF,KAAK;AACH,gBAAI;AACF,qBAAO;AAAA,gBACL,OAAO,SAAS,SAAS,YAAY;AAAA,gBACrC;AAAA,cACF;AAAA,YACF,SAAS,KAAK;AACZ,oBAAM,IAAI;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,UAEF,KAAK;AACH,gBAAI;AACF,qBAAO;AAAA,gBACL,OAAO,OAAO,SAAS,YAAY;AAAA,gBACnC;AAAA,cACF;AAAA,YACF,SAAS,KAAK;AACZ,oBAAM,IAAI;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,UAEF;AACE,kBAAM,IAAI,MAAM,YAAY,QAAQ,gBAAgB;AAAA,QACxD;AAAA,MACF,SAAS,OAAO;AACd,eAAO,MAAM,kCAAkC,QAAQ,KAAK,KAAK;AACjE,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,WAAO,MAAM,+BAA+B,KAAK;AACjD,WAAO;AAAA,EACT;AACF;","names":["AIProvider"]}