@intlayer/backend 5.7.2-canary.3 → 5.7.3
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.
- package/dist/cjs/controllers/ai.controller.cjs.map +1 -1
- package/dist/cjs/controllers/dictionary.controller.cjs +39 -20
- package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
- package/dist/cjs/controllers/newsletter.controller.cjs.map +1 -1
- package/dist/cjs/controllers/organization.controller.cjs +51 -19
- package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
- package/dist/cjs/controllers/project.controller.cjs +42 -12
- package/dist/cjs/controllers/project.controller.cjs.map +1 -1
- package/dist/cjs/controllers/projectAccessKey.controller.cjs +21 -3
- package/dist/cjs/controllers/projectAccessKey.controller.cjs.map +1 -1
- package/dist/cjs/controllers/search.controller.cjs.map +1 -1
- package/dist/cjs/controllers/stripe.controller.cjs.map +1 -1
- package/dist/cjs/controllers/tag.controller.cjs +48 -17
- package/dist/cjs/controllers/tag.controller.cjs.map +1 -1
- package/dist/cjs/controllers/user.controller.cjs +7 -1
- package/dist/cjs/controllers/user.controller.cjs.map +1 -1
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
- package/dist/cjs/routes/ai.routes.cjs.map +1 -1
- package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
- package/dist/cjs/routes/eventListener.routes.cjs.map +1 -1
- package/dist/cjs/routes/newsletter.routes.cjs.map +1 -1
- package/dist/cjs/routes/organization.routes.cjs.map +1 -1
- package/dist/cjs/routes/project.routes.cjs +3 -12
- package/dist/cjs/routes/project.routes.cjs.map +1 -1
- package/dist/cjs/routes/search.routes.cjs.map +1 -1
- package/dist/cjs/routes/stripe.routes.cjs.map +1 -1
- package/dist/cjs/routes/tags.routes.cjs.map +1 -1
- package/dist/cjs/routes/user.routes.cjs.map +1 -1
- package/dist/cjs/schemas/tag.schema.cjs +5 -0
- package/dist/cjs/schemas/tag.schema.cjs.map +1 -1
- package/dist/cjs/services/dictionary.service.cjs +0 -8
- package/dist/cjs/services/dictionary.service.cjs.map +1 -1
- package/dist/cjs/services/organization.service.cjs +0 -9
- package/dist/cjs/services/organization.service.cjs.map +1 -1
- package/dist/cjs/types/tag.types.cjs.map +1 -1
- package/dist/cjs/utils/auth/getAuth.cjs +1 -0
- package/dist/cjs/utils/auth/getAuth.cjs.map +1 -1
- package/dist/cjs/utils/permissions.cjs +100 -22
- package/dist/cjs/utils/permissions.cjs.map +1 -1
- package/dist/esm/controllers/ai.controller.mjs.map +1 -1
- package/dist/esm/controllers/dictionary.controller.mjs +39 -20
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/newsletter.controller.mjs.map +1 -1
- package/dist/esm/controllers/organization.controller.mjs +51 -19
- package/dist/esm/controllers/organization.controller.mjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs +42 -12
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/controllers/projectAccessKey.controller.mjs +21 -3
- package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
- package/dist/esm/controllers/search.controller.mjs.map +1 -1
- package/dist/esm/controllers/stripe.controller.mjs.map +1 -1
- package/dist/esm/controllers/tag.controller.mjs +48 -17
- package/dist/esm/controllers/tag.controller.mjs.map +1 -1
- package/dist/esm/controllers/user.controller.mjs +7 -1
- package/dist/esm/controllers/user.controller.mjs.map +1 -1
- package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
- package/dist/esm/routes/ai.routes.mjs.map +1 -1
- package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
- package/dist/esm/routes/eventListener.routes.mjs.map +1 -1
- package/dist/esm/routes/newsletter.routes.mjs.map +1 -1
- package/dist/esm/routes/organization.routes.mjs.map +1 -1
- package/dist/esm/routes/project.routes.mjs +3 -12
- package/dist/esm/routes/project.routes.mjs.map +1 -1
- package/dist/esm/routes/search.routes.mjs.map +1 -1
- package/dist/esm/routes/stripe.routes.mjs.map +1 -1
- package/dist/esm/routes/tags.routes.mjs.map +1 -1
- package/dist/esm/routes/user.routes.mjs.map +1 -1
- package/dist/esm/schemas/tag.schema.mjs +5 -0
- package/dist/esm/schemas/tag.schema.mjs.map +1 -1
- package/dist/esm/services/dictionary.service.mjs +0 -7
- package/dist/esm/services/dictionary.service.mjs.map +1 -1
- package/dist/esm/services/organization.service.mjs +0 -9
- package/dist/esm/services/organization.service.mjs.map +1 -1
- package/dist/esm/utils/auth/getAuth.mjs +1 -0
- package/dist/esm/utils/auth/getAuth.mjs.map +1 -1
- package/dist/esm/utils/permissions.mjs +100 -22
- package/dist/esm/utils/permissions.mjs.map +1 -1
- package/dist/types/controllers/ai.controller.d.ts +10 -9
- package/dist/types/controllers/ai.controller.d.ts.map +1 -1
- package/dist/types/controllers/dictionary.controller.d.ts +9 -8
- package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
- package/dist/types/controllers/newsletter.controller.d.ts +5 -4
- package/dist/types/controllers/newsletter.controller.d.ts.map +1 -1
- package/dist/types/controllers/organization.controller.d.ts +11 -10
- package/dist/types/controllers/organization.controller.d.ts.map +1 -1
- package/dist/types/controllers/project.controller.d.ts +10 -9
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/controllers/projectAccessKey.controller.d.ts +5 -4
- package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
- package/dist/types/controllers/search.controller.d.ts.map +1 -1
- package/dist/types/controllers/stripe.controller.d.ts +5 -4
- package/dist/types/controllers/stripe.controller.d.ts.map +1 -1
- package/dist/types/controllers/tag.controller.d.ts +6 -5
- package/dist/types/controllers/tag.controller.d.ts.map +1 -1
- package/dist/types/controllers/user.controller.d.ts +9 -8
- package/dist/types/controllers/user.controller.d.ts.map +1 -1
- package/dist/types/middlewares/sessionAuth.middleware.d.ts +2 -0
- package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
- package/dist/types/schemas/tag.schema.d.ts.map +1 -1
- package/dist/types/services/dictionary.service.d.ts +0 -1
- package/dist/types/services/dictionary.service.d.ts.map +1 -1
- package/dist/types/services/organization.service.d.ts.map +1 -1
- package/dist/types/types/tag.types.d.ts +2 -0
- package/dist/types/types/tag.types.d.ts.map +1 -1
- package/dist/types/utils/auth/getAuth.d.ts.map +1 -1
- package/dist/types/utils/permissions.d.ts +67 -26
- package/dist/types/utils/permissions.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/user.controller.ts"],"sourcesContent":["import type { User, UserAPI } from '@/types/user.types';\nimport { logger } from '@logger';\nimport { sendEmail } from '@services/email.service';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { getOrganizationFiltersAndPagination } from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport type { UserFiltersParam } from '@utils/filtersAndPagination/getUserFiltersAndPagination';\nimport { mapUsersToAPI, mapUserToAPI } from '@utils/mapper/user';\nimport { hasPermission } from '@utils/permissions';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request, Response } from 'express';\nimport { t } from 'express-intlayer';\n\nexport type CreateUserBody = { email: string; password?: string };\nexport type CreateUserResult = ResponseData<UserAPI>;\n\n/**\n * Creates a new user.\n */\nexport const createUser = async (\n req: Request<any, any, User>,\n res: Response<CreateUserResult>,\n _next: NextFunction\n): Promise<void> => {\n const user: User | undefined = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newUser = await userService.createUser(user);\n\n await sendEmail({\n type: 'welcome',\n to: newUser.email,\n username: newUser.name,\n loginLink: `${process.env.CLIENT_URL}/auth/login`,\n });\n\n const formattedUser = mapUserToAPI(newUser);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'User created',\n fr: 'Utilisateur créé',\n es: 'Usuario creado',\n }),\n description: t({\n en: 'User created successfully',\n fr: 'Utilisateur créé avec succès',\n es: 'Usuario creado con éxito',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetUsersParams = FiltersAndPagination<UserFiltersParam>;\nexport type GetUsersResult = PaginatedResponse<UserAPI>;\n\n/**\n * Retrieves a list of users based on filters and pagination.\n */\nexport const getUsers = async (\n req: Request<GetUsersParams>,\n res: Response<GetUsersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, roles } = res.locals;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req);\n\n try {\n const users = await userService.findUsers(filters, skip, pageSize);\n\n if (\n !hasPermission(\n roles,\n 'user:read'\n )({\n ...res.locals,\n targetUserIds: users.map((user) => user.id),\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const totalItems = await userService.countUsers(filters);\n\n const formattedUsers = mapUsersToAPI(users);\n\n const responseData = formatPaginatedResponse<UserAPI>({\n data: formattedUsers,\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 GetUserByIdParams = { userId: string };\nexport type GetUserByIdResult = ResponseData<UserAPI>;\n\nexport const getUserById = async (\n req: Request<GetUserByIdParams>,\n res: Response<GetUserByIdResult>,\n _next: NextFunction\n): Promise<void> => {\n const { userId } = req.params;\n\n try {\n const user = await userService.getUserById(userId);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n const formattedUser = mapUserToAPI(user);\n const responseData = formatResponse<UserAPI>({ data: formattedUser });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetUserByEmailParams = { email: string };\nexport type GetUserByEmailResult = ResponseData<UserAPI>;\n\nexport const getUserByEmail = async (\n req: Request<GetUserByEmailParams>,\n res: Response<GetUserByEmailResult>,\n _next: NextFunction\n): Promise<void> => {\n const { email } = req.params;\n const { roles } = res.locals;\n\n try {\n const user = await userService.getUserByEmail(email);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'user:read'\n )({\n ...res.locals,\n targetUserIds: [user.id],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const formattedUser = mapUserToAPI(user);\n const responseData = formatResponse<UserAPI>({ data: formattedUser });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateUserBody = Partial<User>;\nexport type UpdateUserResult = ResponseData<UserAPI>;\n\n/**\n * Updates user information (phone number, date of birth).\n */\nexport const updateUser = async (\n req: Request<any, any, UpdateUserBody | undefined>,\n res: Response<UpdateUserResult>,\n _next: NextFunction\n): Promise<void> => {\n const userData = req.body;\n const { user, roles } = res.locals;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (typeof userData !== 'object') {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_DATA_NOT_FOUND');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'user:write'\n )({\n ...res.locals,\n targetUserIds: [user.id],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const updatedUser = await userService.updateUserById(user.id, userData);\n\n logger.info(\n `User updated: Name: ${updatedUser.name}, id: ${String(updatedUser.id)}`\n );\n\n const formattedUser = mapUserToAPI(updatedUser);\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'User updated',\n fr: 'Utilisateur mis à jour',\n es: 'Usuario actualizado',\n }),\n description: t({\n en: 'User updated successfully',\n fr: 'Utilisateur mis à jour avec succès',\n es: 'Usuario actualizado con éxito',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteUserParams = { userId: string };\nexport type DeleteUserResult = ResponseData<UserAPI>;\n\n/**\n * Deletes a user based on the provided ID.\n */\nexport const deleteUser = async (\n req: Request<any, any, DeleteUserParams>,\n res: Response<DeleteUserResult>,\n _next: NextFunction\n): Promise<void> => {\n const { userId } = req.params;\n const { roles } = res.locals;\n\n if (!hasPermission(roles, 'user:admin')()) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const user = await userService.deleteUser(userId);\n\n const formattedUser = mapUserToAPI(user);\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'User deleted',\n fr: 'Utilisateur supprimé',\n es: 'Usuario eliminado',\n }),\n description: t({\n en: 'User deleted successfully',\n fr: 'Utilisateur supprimé avec succès',\n es: 'Usuario eliminado con éxito',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nlet clients: Array<{ id: number; userId: string; res: Response }> = [];\n\nexport const sendVerificationUpdate = (user: User) => {\n const filteredClients = clients.filter(\n (client) => String(client.userId) === String(user.id)\n );\n\n for (const client of filteredClients) {\n if (user.emailVerified) {\n client.res.write(\n `data: ${JSON.stringify({ userId: user.id, status: 'verified' })}\\n\\n`\n );\n }\n }\n};\n\nexport type VerifyEmailStatusSSEParams = { userId: string };\n\n/**\n * SSE to check the email verification status\n */\nexport const verifyEmailStatusSSE = async (\n req: Request<VerifyEmailStatusSSEParams, any, any>,\n res: Response\n) => {\n // Set headers for SSE\n res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no'); // For Nginx buffering\n\n // Send initial data to ensure the connection is open\n res.write(':\\n\\n'); // Comment to keep connection alive\n res.flushHeaders();\n\n const { userId } = req.params; // Get user ID from query parameters\n const clientId = Date.now();\n\n const user = await userService.getUserById(userId);\n\n if (!user) {\n logger.error(`User not found - User ID: ${userId}`);\n res.write(`data: ${JSON.stringify({ userId, status: 'error' })}\\n\\n`);\n res.end();\n return;\n }\n\n // Add client to the list\n const newClient = { id: clientId, userId, res };\n clients.push(newClient);\n\n sendVerificationUpdate(user);\n\n // Remove client on connection close\n req.on('close', () => {\n clients = clients.filter((client) => client.id !== clientId);\n });\n};\n"],"mappings":"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","names":["user"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/user.controller.ts"],"sourcesContent":["import type { User, UserAPI } from '@/types/user.types';\nimport { logger } from '@logger';\nimport type { ResponseWithSession } from '@middlewares/sessionAuth.middleware';\nimport { sendEmail } from '@services/email.service';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { getOrganizationFiltersAndPagination } from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport type { UserFiltersParam } from '@utils/filtersAndPagination/getUserFiltersAndPagination';\nimport { mapUsersToAPI, mapUserToAPI } from '@utils/mapper/user';\nimport { hasPermission } from '@utils/permissions';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\n\nexport type CreateUserBody = { email: string; password?: string };\nexport type CreateUserResult = ResponseData<UserAPI>;\n\n/**\n * Creates a new user.\n */\nexport const createUser = async (\n req: Request<any, any, User>,\n res: ResponseWithSession<CreateUserResult>,\n _next: NextFunction\n): Promise<void> => {\n const user: User | undefined = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newUser = await userService.createUser(user);\n\n await sendEmail({\n type: 'welcome',\n to: newUser.email,\n username: newUser.name,\n loginLink: `${process.env.CLIENT_URL}/auth/login`,\n });\n\n const formattedUser = mapUserToAPI(newUser);\n\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'User created',\n fr: 'Utilisateur créé',\n es: 'Usuario creado',\n }),\n description: t({\n en: 'User created successfully',\n fr: 'Utilisateur créé avec succès',\n es: 'Usuario creado con éxito',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetUsersParams = FiltersAndPagination<UserFiltersParam>;\nexport type GetUsersResult = PaginatedResponse<UserAPI>;\n\n/**\n * Retrieves a list of users based on filters and pagination.\n */\nexport const getUsers = async (\n req: Request<GetUsersParams>,\n res: ResponseWithSession<GetUsersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, roles } = res.locals;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req);\n\n try {\n const users = await userService.findUsers(filters, skip, pageSize);\n\n if (\n !hasPermission(\n roles,\n 'user:read'\n )({\n ...res.locals,\n targetUserIds: users.map((user) => user.id),\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const totalItems = await userService.countUsers(filters);\n\n const formattedUsers = mapUsersToAPI(users);\n\n const responseData = formatPaginatedResponse<UserAPI>({\n data: formattedUsers,\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 GetUserByIdParams = { userId: string };\nexport type GetUserByIdResult = ResponseData<UserAPI>;\n\nexport const getUserById = async (\n req: Request<GetUserByIdParams>,\n res: ResponseWithSession<GetUserByIdResult>,\n _next: NextFunction\n): Promise<void> => {\n const { userId } = req.params;\n\n try {\n const user = await userService.getUserById(userId);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n const formattedUser = mapUserToAPI(user);\n const responseData = formatResponse<UserAPI>({ data: formattedUser });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetUserByEmailParams = { email: string };\nexport type GetUserByEmailResult = ResponseData<UserAPI>;\n\nexport const getUserByEmail = async (\n req: Request<GetUserByEmailParams>,\n res: ResponseWithSession<GetUserByEmailResult>,\n _next: NextFunction\n): Promise<void> => {\n const { email } = req.params;\n const { roles } = res.locals;\n\n try {\n const user = await userService.getUserByEmail(email);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'user:read'\n )({\n ...res.locals,\n targetUserIds: [user.id],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n const formattedUser = mapUserToAPI(user);\n const responseData = formatResponse<UserAPI>({ data: formattedUser });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateUserBody = Partial<User>;\nexport type UpdateUserResult = ResponseData<UserAPI>;\n\n/**\n * Updates user information (phone number, date of birth).\n */\nexport const updateUser = async (\n req: Request<any, any, UpdateUserBody | undefined>,\n res: ResponseWithSession<UpdateUserResult>,\n _next: NextFunction\n): Promise<void> => {\n const userData = req.body;\n const { user, roles } = res.locals;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (typeof userData !== 'object') {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_DATA_NOT_FOUND');\n return;\n }\n\n if (\n !hasPermission(\n roles,\n 'user:write'\n )({\n ...res.locals,\n targetUserIds: [user.id],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const updatedUser = await userService.updateUserById(user.id, userData);\n\n logger.info(\n `User updated: Name: ${updatedUser.name}, id: ${String(updatedUser.id)}`\n );\n\n const formattedUser = mapUserToAPI(updatedUser);\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'User updated',\n fr: 'Utilisateur mis à jour',\n es: 'Usuario actualizado',\n }),\n description: t({\n en: 'User updated successfully',\n fr: 'Utilisateur mis à jour avec succès',\n es: 'Usuario actualizado con éxito',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteUserParams = { userId: string };\nexport type DeleteUserResult = ResponseData<UserAPI>;\n\n/**\n * Deletes a user based on the provided ID.\n */\nexport const deleteUser = async (\n req: Request<DeleteUserParams>,\n res: ResponseWithSession<DeleteUserResult>,\n _next: NextFunction\n): Promise<void> => {\n const { userId } = req.params;\n const { roles } = res.locals;\n\n if (\n !hasPermission(\n roles,\n 'user:admin'\n )({\n ...res.locals,\n targetUserIds: [userId],\n })\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PERMISSION_DENIED');\n return;\n }\n\n try {\n const user = await userService.deleteUser(userId);\n\n const formattedUser = mapUserToAPI(user);\n const responseData = formatResponse<UserAPI>({\n message: t({\n en: 'User deleted',\n fr: 'Utilisateur supprimé',\n es: 'Usuario eliminado',\n }),\n description: t({\n en: 'User deleted successfully',\n fr: 'Utilisateur supprimé avec succès',\n es: 'Usuario eliminado con éxito',\n }),\n data: formattedUser,\n });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nlet clients: Array<{ id: number; userId: string; res: ResponseWithSession }> =\n [];\n\nexport const sendVerificationUpdate = (user: User) => {\n const filteredClients = clients.filter(\n (client) => String(client.userId) === String(user.id)\n );\n\n for (const client of filteredClients) {\n if (user.emailVerified) {\n client.res.write(\n `data: ${JSON.stringify({ userId: user.id, status: 'verified' })}\\n\\n`\n );\n }\n }\n};\n\nexport type VerifyEmailStatusSSEParams = { userId: string };\n\n/**\n * SSE to check the email verification status\n */\nexport const verifyEmailStatusSSE = async (\n req: Request<VerifyEmailStatusSSEParams, any, any>,\n res: ResponseWithSession\n) => {\n // Set headers for SSE\n res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no'); // For Nginx buffering\n\n // Send initial data to ensure the connection is open\n res.write(':\\n\\n'); // Comment to keep connection alive\n res.flushHeaders();\n\n const { userId } = req.params; // Get user ID from query parameters\n const clientId = Date.now();\n\n const user = await userService.getUserById(userId);\n\n if (!user) {\n logger.error(`User not found - User ID: ${userId}`);\n res.write(`data: ${JSON.stringify({ userId, status: 'error' })}\\n\\n`);\n res.end();\n return;\n }\n\n // Add client to the list\n const newClient = { id: clientId, userId, res };\n clients.push(newClient);\n\n sendVerificationUpdate(user);\n\n // Remove client on connection close\n req.on('close', () => {\n clients = clients.filter((client) => client.id !== clientId);\n });\n};\n"],"mappings":"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","names":["user"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/middlewares/sessionAuth.middleware.ts"],"sourcesContent":["import { formatSession, type Auth } from '@utils/auth/getAuth';\nimport { fromNodeHeaders } from 'better-auth/node';\nimport type { NextFunction, Request, Response } from 'express';\n\nexport const authMiddleware =\n (auth: Auth) => async (req: Request, res: Response, next: NextFunction) => {\n if (typeof res.locals.authType !== 'undefined') {\n // Skip if user is already authenticated (ex: oAuth2)\n return next();\n }\n\n const session = await auth.api.getSession({\n headers: fromNodeHeaders(req.headers),\n });\n\n if (session) {\n const formattedSession = formatSession(session);\n res.locals.authType = 'session';\n\n // Attach the session to the response locals\n Object.entries(formattedSession).forEach(([key, value]) => {\n (res.locals as any)[key] = value;\n });\n\n return next();\n }\n\n next();\n };\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/middlewares/sessionAuth.middleware.ts"],"sourcesContent":["import { Session } from '@/types/session.types';\nimport { formatSession, type Auth } from '@utils/auth/getAuth';\nimport { fromNodeHeaders } from 'better-auth/node';\nimport type { NextFunction, Request, Response } from 'express';\n\nexport type ResponseWithSession<\n ResBody = any,\n Locals extends Record<string, any> = Record<string, any> & Session,\n> = Response<ResBody, Locals>;\n\nexport const authMiddleware =\n (auth: Auth) => async (req: Request, res: Response, next: NextFunction) => {\n if (typeof res.locals.authType !== 'undefined') {\n // Skip if user is already authenticated (ex: oAuth2)\n return next();\n }\n\n const session = await auth.api.getSession({\n headers: fromNodeHeaders(req.headers),\n });\n\n if (session) {\n const formattedSession = formatSession(session);\n res.locals.authType = 'session';\n\n // Attach the session to the response locals\n Object.entries(formattedSession).forEach(([key, value]) => {\n (res.locals as any)[key] = value;\n });\n\n return next();\n }\n\n next();\n };\n"],"mappings":"AACA,SAAS,qBAAgC;AACzC,SAAS,uBAAuB;AAQzB,MAAM,iBACX,CAAC,SAAe,OAAO,KAAc,KAAe,SAAuB;AACzE,MAAI,OAAO,IAAI,OAAO,aAAa,aAAa;AAE9C,WAAO,KAAK;AAAA,EACd;AAEA,QAAM,UAAU,MAAM,KAAK,IAAI,WAAW;AAAA,IACxC,SAAS,gBAAgB,IAAI,OAAO;AAAA,EACtC,CAAC;AAED,MAAI,SAAS;AACX,UAAM,mBAAmB,cAAc,OAAO;AAC9C,QAAI,OAAO,WAAW;AAGtB,WAAO,QAAQ,gBAAgB,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACzD,MAAC,IAAI,OAAe,GAAG,IAAI;AAAA,IAC7B,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAEA,OAAK;AACP;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
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 customQuery,\n translateJSON,\n} from '@controllers/ai.controller';\nimport { unauthenticatedChatBotLimiter } from '@utils/rateLimiter';\nimport { Router } from 'express';\n\nexport const aiRouter: Router = Router();\n\nexport const aiRoute = '/api/ai';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${aiRoute}`;\n\nexport const getAiRoutes = () =>\n ({\n customQuery: {\n urlModel: '/',\n url: `${baseURL()}/`,\n method: 'POST',\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().customQuery.urlModel, customQuery
|
|
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 customQuery,\n translateJSON,\n} from '@controllers/ai.controller';\nimport { unauthenticatedChatBotLimiter } from '@utils/rateLimiter';\nimport { Router } from 'express';\n\nexport const aiRouter: Router = Router();\n\nexport const aiRoute = '/api/ai';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${aiRoute}`;\n\nexport const getAiRoutes = () =>\n ({\n customQuery: {\n urlModel: '/',\n url: `${baseURL()}/`,\n method: 'POST',\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().customQuery.urlModel, customQuery);\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);\n\naiRouter.post(getAiRoutes().auditTag.urlModel, auditTag);\n\naiRouter.post(getAiRoutes().autocomplete.urlModel, autocomplete);\n\n/**\n * This route number of requests is limited for unauthenticated users\n */\naiRouter.use(/(.*)/, unauthenticatedChatBotLimiter);\naiRouter.post(getAiRoutes().ask.urlModel, askDocQuestion);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qCAAqC;AAC9C,SAAS,cAAc;AAEhB,MAAM,WAAmB,OAAO;AAEhC,MAAM,UAAU;AAEvB,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,OAAO;AAEnD,MAAM,cAAc,OACxB;AAAA,EACC,aAAa;AAAA,IACX,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,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,YAAY,UAAU,WAAW;AAE7D,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;AAEA,SAAS,KAAK,YAAY,EAAE,SAAS,UAAU,QAAQ;AAEvD,SAAS,KAAK,YAAY,EAAE,aAAa,UAAU,YAAY;AAK/D,SAAS,IAAI,QAAQ,6BAA6B;AAClD,SAAS,KAAK,YAAY,EAAE,IAAI,UAAU,cAAc;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/dictionary.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addDictionary,\n deleteDictionary,\n getDictionaries,\n getDictionariesKeys,\n getDictionaryByKey,\n pushDictionaries,\n updateDictionary,\n} from '@controllers/dictionary.controller';\nimport { Router } from 'express';\n\nexport const dictionaryRouter: Router = Router();\n\nexport const dictionaryRoute = '/api/dictionary';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${dictionaryRoute}`;\n\nexport const getDictionaryRoutes = () =>\n ({\n getDictionaries: {\n urlModel: '/',\n url: baseURL,\n method: 'GET',\n },\n getDictionariesKeys: {\n urlModel: '/keys',\n url: `${baseURL}/keys`,\n method: 'GET',\n },\n getDictionary: {\n urlModel: '/:dictionaryKey',\n url: ({ dictionaryKey }: { dictionaryKey: string }) =>\n `${baseURL}/${dictionaryKey}`,\n method: 'GET',\n },\n addDictionary: {\n urlModel: '/',\n url: baseURL,\n method: 'POST',\n },\n pushDictionaries: {\n urlModel: '/',\n url: baseURL,\n method: 'PATCH',\n },\n updateDictionary: {\n urlModel: '/:dictionaryId',\n url: ({ dictionaryId }: { dictionaryId: string }) =>\n `${baseURL}/${dictionaryId}`,\n method: 'PUT',\n },\n deleteDictionary: {\n urlModel: '/:dictionaryId',\n url: ({ dictionaryId }: { dictionaryId: string }) =>\n `${baseURL}/${dictionaryId}`,\n method: 'DELETE',\n },\n }) satisfies Routes;\n\ndictionaryRouter.get(\n getDictionaryRoutes().getDictionaries.urlModel,\n getDictionaries
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/dictionary.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addDictionary,\n deleteDictionary,\n getDictionaries,\n getDictionariesKeys,\n getDictionaryByKey,\n pushDictionaries,\n updateDictionary,\n} from '@controllers/dictionary.controller';\nimport { Router } from 'express';\n\nexport const dictionaryRouter: Router = Router();\n\nexport const dictionaryRoute = '/api/dictionary';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${dictionaryRoute}`;\n\nexport const getDictionaryRoutes = () =>\n ({\n getDictionaries: {\n urlModel: '/',\n url: baseURL,\n method: 'GET',\n },\n getDictionariesKeys: {\n urlModel: '/keys',\n url: `${baseURL}/keys`,\n method: 'GET',\n },\n getDictionary: {\n urlModel: '/:dictionaryKey',\n url: ({ dictionaryKey }: { dictionaryKey: string }) =>\n `${baseURL}/${dictionaryKey}`,\n method: 'GET',\n },\n addDictionary: {\n urlModel: '/',\n url: baseURL,\n method: 'POST',\n },\n pushDictionaries: {\n urlModel: '/',\n url: baseURL,\n method: 'PATCH',\n },\n updateDictionary: {\n urlModel: '/:dictionaryId',\n url: ({ dictionaryId }: { dictionaryId: string }) =>\n `${baseURL}/${dictionaryId}`,\n method: 'PUT',\n },\n deleteDictionary: {\n urlModel: '/:dictionaryId',\n url: ({ dictionaryId }: { dictionaryId: string }) =>\n `${baseURL}/${dictionaryId}`,\n method: 'DELETE',\n },\n }) satisfies Routes;\n\ndictionaryRouter.get(\n getDictionaryRoutes().getDictionaries.urlModel,\n getDictionaries\n);\n\ndictionaryRouter.get(\n getDictionaryRoutes().getDictionariesKeys.urlModel,\n getDictionariesKeys\n);\n\ndictionaryRouter.get(\n getDictionaryRoutes().getDictionary.urlModel,\n getDictionaryByKey\n);\n\ndictionaryRouter.post(\n getDictionaryRoutes().addDictionary.urlModel,\n addDictionary\n);\ndictionaryRouter.patch(\n getDictionaryRoutes().pushDictionaries.urlModel,\n pushDictionaries\n);\ndictionaryRouter.put(\n getDictionaryRoutes().updateDictionary.urlModel,\n updateDictionary\n);\ndictionaryRouter.delete(\n getDictionaryRoutes().deleteDictionary.urlModel,\n deleteDictionary\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,mBAA2B,OAAO;AAExC,MAAM,kBAAkB;AAE/B,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,eAAe;AAE3D,MAAM,sBAAsB,OAChC;AAAA,EACC,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,qBAAqB;AAAA,IACnB,UAAU;AAAA,IACV,KAAK,GAAG,OAAO;AAAA,IACf,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,cAAc,MACpB,GAAG,OAAO,IAAI,aAAa;AAAA,IAC7B,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,aAAa,MACnB,GAAG,OAAO,IAAI,YAAY;AAAA,IAC5B,QAAQ;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,aAAa,MACnB,GAAG,OAAO,IAAI,YAAY;AAAA,IAC5B,QAAQ;AAAA,EACV;AACF;AAEF,iBAAiB;AAAA,EACf,oBAAoB,EAAE,gBAAgB;AAAA,EACtC;AACF;AAEA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,oBAAoB;AAAA,EAC1C;AACF;AAEA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,cAAc;AAAA,EACpC;AACF;AAEA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,cAAc;AAAA,EACpC;AACF;AACA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,iBAAiB;AAAA,EACvC;AACF;AACA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,iBAAiB;AAAA,EACvC;AACF;AACA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,iBAAiB;AAAA,EACvC;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/eventListener.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport { listenChangeSSE } from '@controllers/eventListener.controller';\nimport { Router } from 'express';\n\nexport const eventListenerRouter: Router = Router();\n\nexport const eventListenerRoute = '/api/event-listener';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${eventListenerRoute}`;\n\nexport const eventListenerRoutes = () =>\n ({\n checkDictionaryChangeSSE: {\n urlModel: '/:accessToken',\n url: ({ accessToken }: { accessToken: string }) =>\n `${baseURL()}/${accessToken}`,\n method: 'GET',\n },\n }) satisfies Routes;\n\neventListenerRouter.get(\n eventListenerRoutes().checkDictionaryChangeSSE.urlModel,\n listenChangeSSE
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/eventListener.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport { listenChangeSSE } from '@controllers/eventListener.controller';\nimport { Router } from 'express';\n\nexport const eventListenerRouter: Router = Router();\n\nexport const eventListenerRoute = '/api/event-listener';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${eventListenerRoute}`;\n\nexport const eventListenerRoutes = () =>\n ({\n checkDictionaryChangeSSE: {\n urlModel: '/:accessToken',\n url: ({ accessToken }: { accessToken: string }) =>\n `${baseURL()}/${accessToken}`,\n method: 'GET',\n },\n }) satisfies Routes;\n\neventListenerRouter.get(\n eventListenerRoutes().checkDictionaryChangeSSE.urlModel,\n listenChangeSSE\n);\n"],"mappings":"AACA,SAAS,uBAAuB;AAChC,SAAS,cAAc;AAEhB,MAAM,sBAA8B,OAAO;AAE3C,MAAM,qBAAqB;AAElC,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,kBAAkB;AAE9D,MAAM,sBAAsB,OAChC;AAAA,EACC,0BAA0B;AAAA,IACxB,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,YAAY,MAClB,GAAG,QAAQ,CAAC,IAAI,WAAW;AAAA,IAC7B,QAAQ;AAAA,EACV;AACF;AAEF,oBAAoB;AAAA,EAClB,oBAAoB,EAAE,yBAAyB;AAAA,EAC/C;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/newsletter.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n getNewsletterStatus,\n subscribeToNewsletter,\n unsubscribeFromNewsletter,\n} from '@controllers/newsletter.controller';\nimport { Router } from 'express';\n\nexport const newsletterRouter: Router = Router();\n\nexport const newsletterRoute = '/api/newsletter';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${newsletterRoute}`;\n\nexport const getNewsletterRoutes = () =>\n ({\n subscribeToNewsletter: {\n urlModel: '/subscribe',\n url: `${baseURL()}/subscribe`,\n method: 'POST',\n },\n unsubscribeFromNewsletter: {\n urlModel: '/unsubscribe',\n url: `${baseURL()}/unsubscribe`,\n method: 'POST',\n },\n getNewsletterStatus: {\n urlModel: '/status',\n url: `${baseURL()}/status`,\n method: 'GET',\n },\n }) satisfies Routes;\n\nnewsletterRouter.post(\n getNewsletterRoutes().subscribeToNewsletter.urlModel,\n subscribeToNewsletter
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/newsletter.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n getNewsletterStatus,\n subscribeToNewsletter,\n unsubscribeFromNewsletter,\n} from '@controllers/newsletter.controller';\nimport { Router } from 'express';\n\nexport const newsletterRouter: Router = Router();\n\nexport const newsletterRoute = '/api/newsletter';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${newsletterRoute}`;\n\nexport const getNewsletterRoutes = () =>\n ({\n subscribeToNewsletter: {\n urlModel: '/subscribe',\n url: `${baseURL()}/subscribe`,\n method: 'POST',\n },\n unsubscribeFromNewsletter: {\n urlModel: '/unsubscribe',\n url: `${baseURL()}/unsubscribe`,\n method: 'POST',\n },\n getNewsletterStatus: {\n urlModel: '/status',\n url: `${baseURL()}/status`,\n method: 'GET',\n },\n }) satisfies Routes;\n\nnewsletterRouter.post(\n getNewsletterRoutes().subscribeToNewsletter.urlModel,\n subscribeToNewsletter\n);\nnewsletterRouter.post(\n getNewsletterRoutes().unsubscribeFromNewsletter.urlModel,\n unsubscribeFromNewsletter\n);\nnewsletterRouter.get(\n getNewsletterRoutes().getNewsletterStatus.urlModel,\n getNewsletterStatus\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,mBAA2B,OAAO;AAExC,MAAM,kBAAkB;AAE/B,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,eAAe;AAE3D,MAAM,sBAAsB,OAChC;AAAA,EACC,uBAAuB;AAAA,IACrB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,2BAA2B;AAAA,IACzB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,qBAAqB;AAAA,IACnB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,iBAAiB;AAAA,EACf,oBAAoB,EAAE,sBAAsB;AAAA,EAC5C;AACF;AACA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,0BAA0B;AAAA,EAChD;AACF;AACA,iBAAiB;AAAA,EACf,oBAAoB,EAAE,oBAAoB;AAAA,EAC1C;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/organization.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addOrganization,\n addOrganizationMember,\n deleteOrganization,\n getOrganizations,\n selectOrganization,\n unselectOrganization,\n updateOrganization,\n updateOrganizationMembers,\n} from '@controllers/organization.controller';\nimport { Router } from 'express';\n\nexport const organizationRouter: Router = Router();\n\nexport const organizationRoute = '/api/organization';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${organizationRoute}`;\n\nexport const getOrganizationRoutes = () =>\n ({\n getOrganizations: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n addOrganization: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n updateOrganization: {\n urlModel: '/',\n url: baseURL(),\n\n method: 'PUT',\n },\n updateOrganizationMembers: {\n urlModel: '/members',\n url: `${baseURL()}/members`,\n method: 'PUT',\n },\n addOrganizationMember: {\n urlModel: '/member',\n url: `${baseURL()}/member`,\n method: 'POST',\n },\n deleteOrganization: {\n urlModel: '/',\n url: baseURL(),\n method: 'DELETE',\n },\n selectOrganization: {\n urlModel: '/:organizationId',\n url: ({ organizationId }: { organizationId: string }) =>\n `${baseURL()}/${organizationId}`,\n method: 'PUT',\n },\n unselectOrganization: {\n urlModel: '/logout',\n url: `${baseURL()}/logout`,\n method: 'POST',\n },\n }) satisfies Routes;\n\norganizationRouter.get(\n getOrganizationRoutes().getOrganizations.urlModel,\n getOrganizations
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/organization.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addOrganization,\n addOrganizationMember,\n deleteOrganization,\n getOrganizations,\n selectOrganization,\n unselectOrganization,\n updateOrganization,\n updateOrganizationMembers,\n} from '@controllers/organization.controller';\nimport { Router } from 'express';\n\nexport const organizationRouter: Router = Router();\n\nexport const organizationRoute = '/api/organization';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${organizationRoute}`;\n\nexport const getOrganizationRoutes = () =>\n ({\n getOrganizations: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n addOrganization: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n updateOrganization: {\n urlModel: '/',\n url: baseURL(),\n\n method: 'PUT',\n },\n updateOrganizationMembers: {\n urlModel: '/members',\n url: `${baseURL()}/members`,\n method: 'PUT',\n },\n addOrganizationMember: {\n urlModel: '/member',\n url: `${baseURL()}/member`,\n method: 'POST',\n },\n deleteOrganization: {\n urlModel: '/',\n url: baseURL(),\n method: 'DELETE',\n },\n selectOrganization: {\n urlModel: '/:organizationId',\n url: ({ organizationId }: { organizationId: string }) =>\n `${baseURL()}/${organizationId}`,\n method: 'PUT',\n },\n unselectOrganization: {\n urlModel: '/logout',\n url: `${baseURL()}/logout`,\n method: 'POST',\n },\n }) satisfies Routes;\n\norganizationRouter.get(\n getOrganizationRoutes().getOrganizations.urlModel,\n getOrganizations\n);\n\norganizationRouter.post(\n getOrganizationRoutes().addOrganization.urlModel,\n addOrganization\n);\norganizationRouter.put(\n getOrganizationRoutes().updateOrganization.urlModel,\n updateOrganization\n);\norganizationRouter.put(\n getOrganizationRoutes().updateOrganizationMembers.urlModel,\n updateOrganizationMembers\n);\norganizationRouter.post(\n getOrganizationRoutes().addOrganizationMember.urlModel,\n addOrganizationMember\n);\norganizationRouter.delete(\n getOrganizationRoutes().deleteOrganization.urlModel,\n deleteOrganization\n);\norganizationRouter.put(\n getOrganizationRoutes().selectOrganization.urlModel,\n selectOrganization\n);\n\norganizationRouter.post(\n getOrganizationRoutes().unselectOrganization.urlModel,\n unselectOrganization\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,qBAA6B,OAAO;AAE1C,MAAM,oBAAoB;AAEjC,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,iBAAiB;AAE7D,MAAM,wBAAwB,OAClC;AAAA,EACC,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IAEb,QAAQ;AAAA,EACV;AAAA,EACA,2BAA2B;AAAA,IACzB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,uBAAuB;AAAA,IACrB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,eAAe,MACrB,GAAG,QAAQ,CAAC,IAAI,cAAc;AAAA,IAChC,QAAQ;AAAA,EACV;AAAA,EACA,sBAAsB;AAAA,IACpB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,iBAAiB;AAAA,EACzC;AACF;AAEA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,gBAAgB;AAAA,EACxC;AACF;AACA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,mBAAmB;AAAA,EAC3C;AACF;AACA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,0BAA0B;AAAA,EAClD;AACF;AACA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,sBAAsB;AAAA,EAC9C;AACF;AACA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,mBAAmB;AAAA,EAC3C;AACF;AACA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,mBAAmB;AAAA,EAC3C;AACF;AAEA,mBAAmB;AAAA,EACjB,sBAAsB,EAAE,qBAAqB;AAAA,EAC7C;AACF;","names":[]}
|
|
@@ -76,10 +76,7 @@ const getProjectRoutes = () => ({
|
|
|
76
76
|
});
|
|
77
77
|
projectRouter.get(getProjectRoutes().getProjects.urlModel, getProjects);
|
|
78
78
|
projectRouter.post(getProjectRoutes().addProject.urlModel, addProject);
|
|
79
|
-
projectRouter.put(
|
|
80
|
-
getProjectRoutes().updateProject.urlModel,
|
|
81
|
-
updateProject
|
|
82
|
-
);
|
|
79
|
+
projectRouter.put(getProjectRoutes().updateProject.urlModel, updateProject);
|
|
83
80
|
projectRouter.put(
|
|
84
81
|
getProjectRoutes().updateProjectMembers.urlModel,
|
|
85
82
|
updateProjectMembers
|
|
@@ -88,10 +85,7 @@ projectRouter.put(
|
|
|
88
85
|
getProjectRoutes().pushProjectConfiguration.urlModel,
|
|
89
86
|
pushProjectConfiguration
|
|
90
87
|
);
|
|
91
|
-
projectRouter.delete(
|
|
92
|
-
getProjectRoutes().deleteProject.urlModel,
|
|
93
|
-
deleteProject
|
|
94
|
-
);
|
|
88
|
+
projectRouter.delete(getProjectRoutes().deleteProject.urlModel, deleteProject);
|
|
95
89
|
projectRouter.post(
|
|
96
90
|
getProjectRoutes().addNewAccessKey.urlModel,
|
|
97
91
|
addNewAccessKey
|
|
@@ -108,10 +102,7 @@ projectRouter.post(
|
|
|
108
102
|
getProjectRoutes().unselectProject.urlModel,
|
|
109
103
|
unselectProject
|
|
110
104
|
);
|
|
111
|
-
projectRouter.put(
|
|
112
|
-
getProjectRoutes().selectProject.urlModel,
|
|
113
|
-
selectProject
|
|
114
|
-
);
|
|
105
|
+
projectRouter.put(getProjectRoutes().selectProject.urlModel, selectProject);
|
|
115
106
|
export {
|
|
116
107
|
getProjectRoutes,
|
|
117
108
|
projectRoute,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/project.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addProject,\n deleteProject,\n getProjects,\n pushProjectConfiguration,\n selectProject,\n unselectProject,\n updateProject,\n updateProjectMembers,\n} from '@controllers/project.controller';\nimport {\n addNewAccessKey,\n deleteAccessKey,\n refreshAccessKey,\n} from '@controllers/projectAccessKey.controller';\nimport { Router } from 'express';\n\nexport const projectRouter: Router = Router();\n\nexport const projectRoute = '/api/project';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${projectRoute}`;\n\nexport const getProjectRoutes = () =>\n ({\n getProjects: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n addProject: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n updateProject: {\n urlModel: '/',\n url: baseURL(),\n method: 'PUT',\n },\n updateProjectMembers: {\n urlModel: '/members',\n url: `${baseURL()}/members`,\n method: 'PUT',\n },\n pushProjectConfiguration: {\n urlModel: '/configuration',\n url: `${baseURL()}/configuration`,\n method: 'PUT',\n },\n deleteProject: {\n urlModel: '/',\n url: baseURL(),\n method: 'DELETE',\n },\n selectProject: {\n urlModel: '/:projectId',\n url: ({ projectId }: { projectId: string }) =>\n `${baseURL()}/${projectId}`,\n method: 'PUT',\n },\n unselectProject: {\n urlModel: '/logout',\n url: `${baseURL()}/logout`,\n method: 'POST',\n },\n addNewAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL()}/access_key`,\n method: 'POST',\n },\n refreshAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL()}/access_key`,\n method: 'PATCH',\n },\n deleteAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL()}/access_key`,\n method: 'DELETE',\n },\n }) satisfies Routes;\n\nprojectRouter.get(getProjectRoutes().getProjects.urlModel, getProjects
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/project.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addProject,\n deleteProject,\n getProjects,\n pushProjectConfiguration,\n selectProject,\n unselectProject,\n updateProject,\n updateProjectMembers,\n} from '@controllers/project.controller';\nimport {\n addNewAccessKey,\n deleteAccessKey,\n refreshAccessKey,\n} from '@controllers/projectAccessKey.controller';\nimport { Router } from 'express';\n\nexport const projectRouter: Router = Router();\n\nexport const projectRoute = '/api/project';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${projectRoute}`;\n\nexport const getProjectRoutes = () =>\n ({\n getProjects: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n addProject: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n updateProject: {\n urlModel: '/',\n url: baseURL(),\n method: 'PUT',\n },\n updateProjectMembers: {\n urlModel: '/members',\n url: `${baseURL()}/members`,\n method: 'PUT',\n },\n pushProjectConfiguration: {\n urlModel: '/configuration',\n url: `${baseURL()}/configuration`,\n method: 'PUT',\n },\n deleteProject: {\n urlModel: '/',\n url: baseURL(),\n method: 'DELETE',\n },\n selectProject: {\n urlModel: '/:projectId',\n url: ({ projectId }: { projectId: string }) =>\n `${baseURL()}/${projectId}`,\n method: 'PUT',\n },\n unselectProject: {\n urlModel: '/logout',\n url: `${baseURL()}/logout`,\n method: 'POST',\n },\n addNewAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL()}/access_key`,\n method: 'POST',\n },\n refreshAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL()}/access_key`,\n method: 'PATCH',\n },\n deleteAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL()}/access_key`,\n method: 'DELETE',\n },\n }) satisfies Routes;\n\nprojectRouter.get(getProjectRoutes().getProjects.urlModel, getProjects);\n\nprojectRouter.post(getProjectRoutes().addProject.urlModel, addProject);\nprojectRouter.put(getProjectRoutes().updateProject.urlModel, updateProject);\nprojectRouter.put(\n getProjectRoutes().updateProjectMembers.urlModel,\n updateProjectMembers\n);\nprojectRouter.put(\n getProjectRoutes().pushProjectConfiguration.urlModel,\n pushProjectConfiguration\n);\nprojectRouter.delete(getProjectRoutes().deleteProject.urlModel, deleteProject);\n\nprojectRouter.post(\n getProjectRoutes().addNewAccessKey.urlModel,\n addNewAccessKey\n);\n\nprojectRouter.patch(\n getProjectRoutes().refreshAccessKey.urlModel,\n refreshAccessKey\n);\n\nprojectRouter.delete(\n getProjectRoutes().deleteAccessKey.urlModel,\n deleteAccessKey\n);\n\nprojectRouter.post(\n getProjectRoutes().unselectProject.urlModel,\n unselectProject\n);\n\nprojectRouter.put(getProjectRoutes().selectProject.urlModel, selectProject);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,gBAAwB,OAAO;AAErC,MAAM,eAAe;AAE5B,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,YAAY;AAExD,MAAM,mBAAmB,OAC7B;AAAA,EACC,aAAa;AAAA,IACX,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,sBAAsB;AAAA,IACpB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,0BAA0B;AAAA,IACxB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,UAAU,MAChB,GAAG,QAAQ,CAAC,IAAI,SAAS;AAAA,IAC3B,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,cAAc,IAAI,iBAAiB,EAAE,YAAY,UAAU,WAAW;AAEtE,cAAc,KAAK,iBAAiB,EAAE,WAAW,UAAU,UAAU;AACrE,cAAc,IAAI,iBAAiB,EAAE,cAAc,UAAU,aAAa;AAC1E,cAAc;AAAA,EACZ,iBAAiB,EAAE,qBAAqB;AAAA,EACxC;AACF;AACA,cAAc;AAAA,EACZ,iBAAiB,EAAE,yBAAyB;AAAA,EAC5C;AACF;AACA,cAAc,OAAO,iBAAiB,EAAE,cAAc,UAAU,aAAa;AAE7E,cAAc;AAAA,EACZ,iBAAiB,EAAE,gBAAgB;AAAA,EACnC;AACF;AAEA,cAAc;AAAA,EACZ,iBAAiB,EAAE,iBAAiB;AAAA,EACpC;AACF;AAEA,cAAc;AAAA,EACZ,iBAAiB,EAAE,gBAAgB;AAAA,EACnC;AACF;AAEA,cAAc;AAAA,EACZ,iBAAiB,EAAE,gBAAgB;AAAA,EACnC;AACF;AAEA,cAAc,IAAI,iBAAiB,EAAE,cAAc,UAAU,aAAa;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/search.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport { searchDocUtil } from '@controllers/search.controller';\nimport { Router } from 'express';\n\nexport const searchRouter: Router = Router();\n\nexport const searchRoute = '/api/search';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${searchRoute}`;\n\nexport const getSearchRoutes = () =>\n ({\n doc: {\n urlModel: '/doc',\n url: `${baseURL()}/doc`,\n method: 'GET',\n },\n }) satisfies Routes;\n\nsearchRouter.get(getSearchRoutes().doc.urlModel, searchDocUtil
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/search.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport { searchDocUtil } from '@controllers/search.controller';\nimport { Router } from 'express';\n\nexport const searchRouter: Router = Router();\n\nexport const searchRoute = '/api/search';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${searchRoute}`;\n\nexport const getSearchRoutes = () =>\n ({\n doc: {\n urlModel: '/doc',\n url: `${baseURL()}/doc`,\n method: 'GET',\n },\n }) satisfies Routes;\n\nsearchRouter.get(getSearchRoutes().doc.urlModel, searchDocUtil);\n"],"mappings":"AACA,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AAEhB,MAAM,eAAuB,OAAO;AAEpC,MAAM,cAAc;AAE3B,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,WAAW;AAEvD,MAAM,kBAAkB,OAC5B;AAAA,EACC,KAAK;AAAA,IACH,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,aAAa,IAAI,gBAAgB,EAAE,IAAI,UAAU,aAAa;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/stripe.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n cancelSubscription,\n getPricing,\n getSubscription,\n} from '@controllers/stripe.controller';\nimport { Router } from 'express';\n\nexport const stripeRouter: Router = Router();\n\nexport const stripeRoute = '/api/stripe';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${stripeRoute}`;\n\nexport const getStripeRoutes = () =>\n ({\n getPricing: {\n urlModel: '/pricing',\n url: `${baseURL()}/pricing`,\n method: 'POST',\n },\n createSubscription: {\n urlModel: '/create-subscription',\n url: `${baseURL()}/create-subscription`,\n method: 'POST',\n },\n cancelSubscription: {\n urlModel: '/cancel-subscription',\n url: `${baseURL()}/cancel-subscription`,\n method: 'POST',\n },\n }) satisfies Routes;\n\nstripeRouter.post(getStripeRoutes().getPricing.urlModel, getPricing
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/stripe.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n cancelSubscription,\n getPricing,\n getSubscription,\n} from '@controllers/stripe.controller';\nimport { Router } from 'express';\n\nexport const stripeRouter: Router = Router();\n\nexport const stripeRoute = '/api/stripe';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${stripeRoute}`;\n\nexport const getStripeRoutes = () =>\n ({\n getPricing: {\n urlModel: '/pricing',\n url: `${baseURL()}/pricing`,\n method: 'POST',\n },\n createSubscription: {\n urlModel: '/create-subscription',\n url: `${baseURL()}/create-subscription`,\n method: 'POST',\n },\n cancelSubscription: {\n urlModel: '/cancel-subscription',\n url: `${baseURL()}/cancel-subscription`,\n method: 'POST',\n },\n }) satisfies Routes;\n\nstripeRouter.post(getStripeRoutes().getPricing.urlModel, getPricing);\n\nstripeRouter.post(\n getStripeRoutes().createSubscription.urlModel,\n getSubscription\n);\n\nstripeRouter.post(\n getStripeRoutes().cancelSubscription.urlModel,\n cancelSubscription\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,eAAuB,OAAO;AAEpC,MAAM,cAAc;AAE3B,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,WAAW;AAEvD,MAAM,kBAAkB,OAC5B;AAAA,EACC,YAAY;AAAA,IACV,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,CAAC;AAAA,IACjB,QAAQ;AAAA,EACV;AACF;AAEF,aAAa,KAAK,gBAAgB,EAAE,WAAW,UAAU,UAAU;AAEnE,aAAa;AAAA,EACX,gBAAgB,EAAE,mBAAmB;AAAA,EACrC;AACF;AAEA,aAAa;AAAA,EACX,gBAAgB,EAAE,mBAAmB;AAAA,EACrC;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/tags.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addTag,\n deleteTag,\n getTags,\n updateTag,\n} from '@controllers/tag.controller';\nimport { Router } from 'express';\n\nexport const tagRouter: Router = Router();\n\nexport const tagRoute = '/api/tag';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${tagRoute}`;\n\nexport const getTagRoutes = () =>\n ({\n getTags: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n addTag: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n updateTag: {\n urlModel: '/:tagId',\n url: ({ tagId }: { tagId: string }) => `${baseURL()}/${tagId}`,\n method: 'PUT',\n },\n deleteTag: {\n urlModel: '/:tagId',\n url: ({ tagId }: { tagId: string }) => `${baseURL()}/${tagId}`,\n method: 'DELETE',\n },\n }) satisfies Routes;\n\ntagRouter.get(getTagRoutes().getTags.urlModel, getTags
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/tags.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n addTag,\n deleteTag,\n getTags,\n updateTag,\n} from '@controllers/tag.controller';\nimport { Router } from 'express';\n\nexport const tagRouter: Router = Router();\n\nexport const tagRoute = '/api/tag';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${tagRoute}`;\n\nexport const getTagRoutes = () =>\n ({\n getTags: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n addTag: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n updateTag: {\n urlModel: '/:tagId',\n url: ({ tagId }: { tagId: string }) => `${baseURL()}/${tagId}`,\n method: 'PUT',\n },\n deleteTag: {\n urlModel: '/:tagId',\n url: ({ tagId }: { tagId: string }) => `${baseURL()}/${tagId}`,\n method: 'DELETE',\n },\n }) satisfies Routes;\n\ntagRouter.get(getTagRoutes().getTags.urlModel, getTags);\ntagRouter.post(getTagRoutes().addTag.urlModel, addTag);\ntagRouter.put(getTagRoutes().updateTag.urlModel, updateTag);\ntagRouter.delete(getTagRoutes().deleteTag.urlModel, deleteTag);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,YAAoB,OAAO;AAEjC,MAAM,WAAW;AAExB,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,QAAQ;AAEpD,MAAM,eAAe,OACzB;AAAA,EACC,SAAS;AAAA,IACP,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,WAAW;AAAA,IACT,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,MAAM,MAAyB,GAAG,QAAQ,CAAC,IAAI,KAAK;AAAA,IAC5D,QAAQ;AAAA,EACV;AAAA,EACA,WAAW;AAAA,IACT,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,MAAM,MAAyB,GAAG,QAAQ,CAAC,IAAI,KAAK;AAAA,IAC5D,QAAQ;AAAA,EACV;AACF;AAEF,UAAU,IAAI,aAAa,EAAE,QAAQ,UAAU,OAAO;AACtD,UAAU,KAAK,aAAa,EAAE,OAAO,UAAU,MAAM;AACrD,UAAU,IAAI,aAAa,EAAE,UAAU,UAAU,SAAS;AAC1D,UAAU,OAAO,aAAa,EAAE,UAAU,UAAU,SAAS;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/user.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n createUser,\n getUserByEmail,\n getUserById,\n getUsers,\n updateUser,\n verifyEmailStatusSSE,\n} from '@controllers/user.controller';\nimport { Router } from 'express';\n\nexport const userRouter: Router = Router();\n\nexport const userRoute = '/api/user';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${userRoute}`;\n\nexport const getUserRoutes = () =>\n ({\n getUsers: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n updateUser: {\n urlModel: '/',\n url: baseURL(),\n method: 'PUT',\n },\n createUser: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n getUserById: {\n urlModel: '/:userId',\n url: ({ userId }: { userId: string }) => `${baseURL()}/${userId}`,\n method: 'GET',\n },\n getUserByEmail: {\n urlModel: '/email/:email',\n url: ({ email }: { email: string }) => `${baseURL()}/email/${email}`,\n method: 'GET',\n },\n verifyEmailStatusSSE: {\n urlModel: '/verify-email-status/:userId',\n url: ({ userId }: { userId: string }) =>\n `${baseURL()}/verify-email-status/${userId}`,\n method: 'GET',\n },\n }) satisfies Routes;\n\nuserRouter.get(getUserRoutes().getUsers.urlModel, getUsers
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/user.routes.ts"],"sourcesContent":["import type { Routes } from '@/types/Routes';\nimport {\n createUser,\n getUserByEmail,\n getUserById,\n getUsers,\n updateUser,\n verifyEmailStatusSSE,\n} from '@controllers/user.controller';\nimport { Router } from 'express';\n\nexport const userRouter: Router = Router();\n\nexport const userRoute = '/api/user';\n\nconst baseURL = () => `${process.env.BACKEND_URL}${userRoute}`;\n\nexport const getUserRoutes = () =>\n ({\n getUsers: {\n urlModel: '/',\n url: baseURL(),\n method: 'GET',\n },\n updateUser: {\n urlModel: '/',\n url: baseURL(),\n method: 'PUT',\n },\n createUser: {\n urlModel: '/',\n url: baseURL(),\n method: 'POST',\n },\n getUserById: {\n urlModel: '/:userId',\n url: ({ userId }: { userId: string }) => `${baseURL()}/${userId}`,\n method: 'GET',\n },\n getUserByEmail: {\n urlModel: '/email/:email',\n url: ({ email }: { email: string }) => `${baseURL()}/email/${email}`,\n method: 'GET',\n },\n verifyEmailStatusSSE: {\n urlModel: '/verify-email-status/:userId',\n url: ({ userId }: { userId: string }) =>\n `${baseURL()}/verify-email-status/${userId}`,\n method: 'GET',\n },\n }) satisfies Routes;\n\nuserRouter.get(getUserRoutes().getUsers.urlModel, getUsers);\nuserRouter.put(getUserRoutes().updateUser.urlModel, updateUser);\nuserRouter.post(getUserRoutes().createUser.urlModel, createUser);\nuserRouter.get(getUserRoutes().getUserById.urlModel, getUserById);\nuserRouter.get(getUserRoutes().getUserByEmail.urlModel, getUserByEmail);\nuserRouter.get(\n getUserRoutes().verifyEmailStatusSSE.urlModel,\n verifyEmailStatusSSE\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,aAAqB,OAAO;AAElC,MAAM,YAAY;AAEzB,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI,WAAW,GAAG,SAAS;AAErD,MAAM,gBAAgB,OAC1B;AAAA,EACC,UAAU;AAAA,IACR,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,KAAK,QAAQ;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,aAAa;AAAA,IACX,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,OAAO,MAA0B,GAAG,QAAQ,CAAC,IAAI,MAAM;AAAA,IAC/D,QAAQ;AAAA,EACV;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,MAAM,MAAyB,GAAG,QAAQ,CAAC,UAAU,KAAK;AAAA,IAClE,QAAQ;AAAA,EACV;AAAA,EACA,sBAAsB;AAAA,IACpB,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,OAAO,MACb,GAAG,QAAQ,CAAC,wBAAwB,MAAM;AAAA,IAC5C,QAAQ;AAAA,EACV;AACF;AAEF,WAAW,IAAI,cAAc,EAAE,SAAS,UAAU,QAAQ;AAC1D,WAAW,IAAI,cAAc,EAAE,WAAW,UAAU,UAAU;AAC9D,WAAW,KAAK,cAAc,EAAE,WAAW,UAAU,UAAU;AAC/D,WAAW,IAAI,cAAc,EAAE,YAAY,UAAU,WAAW;AAChE,WAAW,IAAI,cAAc,EAAE,eAAe,UAAU,cAAc;AACtE,WAAW;AAAA,EACT,cAAc,EAAE,qBAAqB;AAAA,EACrC;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/schemas/tag.schema.ts"],"sourcesContent":["import type { TagSchema } from '@/types/tag.types';\nimport {\n KEY_MAX_LENGTH,\n KEY_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateTag';\nimport { Schema } from 'mongoose';\n\nexport const tagSchema = new Schema<TagSchema>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n key: {\n type: String,\n required: true,\n minlength: KEY_MIN_LENGTH,\n maxlength: KEY_MAX_LENGTH,\n },\n name: {\n type: String,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n description: {\n type: String,\n },\n instructions: {\n type: String,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(doc, ret) {\n ret.id = ret._id.toString(); // convert _id to id\n delete ret._id; // remove _id\n },\n },\n toObject: {\n virtuals: true,\n transform(doc, ret) {\n ret.id = ret._id.toString(); // convert _id to id\n delete ret._id; // remove _id\n },\n },\n }\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,YAAY,IAAI;AAAA,EAC3B;AAAA,IACE,gBAAgB;AAAA,MACd,MAAM,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,KAAK;AAAA,MACH,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,IACR;AAAA,IACA,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IACA,WAAW;AAAA,MACT,MAAM,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA;AAAA,IACE,YAAY;AAAA,IAEZ,QAAQ;AAAA,MACN,UAAU;AAAA;AAAA,MACV,YAAY;AAAA;AAAA,MACZ,UAAU,KAAK,KAAK;AAClB,YAAI,KAAK,IAAI,IAAI,SAAS;AAC1B,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,UAAU;AAAA,MACV,UAAU,KAAK,KAAK;AAClB,YAAI,KAAK,IAAI,IAAI,SAAS;AAC1B,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/schemas/tag.schema.ts"],"sourcesContent":["import type { TagSchema } from '@/types/tag.types';\nimport {\n KEY_MAX_LENGTH,\n KEY_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateTag';\nimport { Schema } from 'mongoose';\n\nexport const tagSchema = new Schema<TagSchema>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n projectId: {\n type: Schema.Types.ObjectId,\n ref: 'Project',\n required: true,\n },\n key: {\n type: String,\n required: true,\n minlength: KEY_MIN_LENGTH,\n maxlength: KEY_MAX_LENGTH,\n },\n name: {\n type: String,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n description: {\n type: String,\n },\n instructions: {\n type: String,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(doc, ret) {\n ret.id = ret._id.toString(); // convert _id to id\n delete ret._id; // remove _id\n },\n },\n toObject: {\n virtuals: true,\n transform(doc, ret) {\n ret.id = ret._id.toString(); // convert _id to id\n delete ret._id; // remove _id\n },\n },\n }\n);\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAEhB,MAAM,YAAY,IAAI;AAAA,EAC3B;AAAA,IACE,gBAAgB;AAAA,MACd,MAAM,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,WAAW;AAAA,MACT,MAAM,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,KAAK;AAAA,MACH,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,IACR;AAAA,IACA,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IACA,WAAW;AAAA,MACT,MAAM,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA;AAAA,IACE,YAAY;AAAA,IAEZ,QAAQ;AAAA,MACN,UAAU;AAAA;AAAA,MACV,YAAY;AAAA;AAAA,MACZ,UAAU,KAAK,KAAK;AAClB,YAAI,KAAK,IAAI,IAAI,SAAS;AAC1B,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,UAAU;AAAA,MACV,UAAU,KAAK,KAAK;AAClB,YAAI,KAAK,IAAI,IAAI,SAAS;AAC1B,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -80,12 +80,6 @@ const getDictionariesByKeys = async (dictionaryKeys, projectId) => {
|
|
|
80
80
|
);
|
|
81
81
|
return formattedResults;
|
|
82
82
|
};
|
|
83
|
-
const getDictionariesKeys = async (projectId) => {
|
|
84
|
-
const dictionaries = await DictionaryModel.find({
|
|
85
|
-
projectIds: projectId
|
|
86
|
-
}).select("key");
|
|
87
|
-
return dictionaries.map((dictionary) => dictionary.key);
|
|
88
|
-
};
|
|
89
83
|
const getDictionariesByTags = async (tags, projectId) => {
|
|
90
84
|
const dictionaries = await DictionaryModel.aggregate([
|
|
91
85
|
// Stage 1: Match the document by tags
|
|
@@ -228,7 +222,6 @@ export {
|
|
|
228
222
|
findDictionaries,
|
|
229
223
|
getDictionariesByKeys,
|
|
230
224
|
getDictionariesByTags,
|
|
231
|
-
getDictionariesKeys,
|
|
232
225
|
getDictionaryById,
|
|
233
226
|
getDictionaryByKey,
|
|
234
227
|
getExistingDictionaryKey,
|
|
@@ -1 +1 @@
|
|
|
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 } 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 | Types.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 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 | Types.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 | Types.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 | Types.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 | Types.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 | Types.ObjectId,\n dictionary: Partial<Dictionary>\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, [\n 'id',\n ]) as unknown as Partial<Dictionary>;\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 | Types.ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, [\n 'id',\n ]) as unknown as Partial<Dictionary>;\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":"AAMA,SAAS,uBAAuB;AAChC,SAAS,mCAAmC;AAC5C,SAAS,oBAAoB;AAE7B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,aAAa;AASf,MAAM,mBAAmB,OAC9B,SACA,OAAO,GACP,QAAQ,QAC0B;AAClC,MAAI;AACF,UAAM,eAAe,MAAM,gBAAgB,UAA8B;AAAA;AAAA,MAEvE,EAAE,QAAQ,QAAQ;AAAA;AAAA,MAGlB,EAAE,OAAO,KAAK;AAAA;AAAA,MAGd,EAAE,QAAQ,MAAM;AAAA,IAClB,CAAC;AAED,UAAM,mBAAmB,aAAa;AAAA,MACpC,CAAC,WAAW,IAAI,gBAAgB,MAAM;AAAA,IACxC;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,gCAAgC,KAAK;AACnD,UAAM;AAAA,EACR;AACF;AAYO,MAAM,oBAAoB,OAC/B,iBACgC;AAChC,QAAM,KAAK,MAAM,SAAS,QAAQ,YAAsB,IACpD,IAAI,MAAM,SAAS,YAAsB,IACzC;AAEJ,QAAM,eAAe,MAAM,gBAAgB,UAA8B;AAAA;AAAA,IAEvE,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE;AAAA;AAAA,IAGtB;AAAA,MACE,YAAY;AAAA,QACV,mBAAmB;AAAA,UACjB,MAAM;AAAA,YACJ,OAAO,EAAE,gBAAgB,WAAW;AAAA,YACpC,IAAI;AAAA,YACJ,IAAI;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,CAAC,aAAa,QAAQ;AACxB,UAAM,IAAI,aAAa,wBAAwB,EAAE,aAAa,CAAC;AAAA,EACjE;AAEA,SAAO,IAAI,gBAAgB,aAAa,CAAC,CAAC;AAC5C;AAOO,MAAM,qBAAqB,OAChC,eACA,cACgC;AAChC,QAAM,eAAe,MAAM,sBAAsB,CAAC,aAAa,GAAG,SAAS;AAE3E,SAAO,aAAa,CAAC;AACvB;AAEO,MAAM,wBAAwB,OACnC,gBACA,cACkC;AAClC,QAAM,eAAe,MAAM,gBAAgB,UAA8B;AAAA;AAAA,IAEvE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,eAAe,GAAG,YAAY,UAAU,EAAE;AAAA;AAAA,IAGlE;AAAA,MACE,YAAY;AAAA,QACV,mBAAmB;AAAA,UACjB,MAAM;AAAA,YACJ,OAAO,EAAE,gBAAgB,WAAW;AAAA,YACpC,IAAI;AAAA,YACJ,IAAI;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,aAAa,wBAAwB;AAAA,MAC7C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,aAAa;AAAA,IACpC,CAAC,WAAW,IAAI,gBAAgB,MAAM;AAAA,EACxC;AAEA,SAAO;AACT;AAEO,MAAM,sBAAsB,OACjC,cACsB;AACtB,QAAM,eAAe,MAAM,gBAAgB,KAAK;AAAA,IAC9C,YAAY;AAAA,EACd,CAAC,EAAE,OAAO,KAAK;AAEf,SAAO,aAAa,IAAI,CAAC,eAAe,WAAW,GAAG;AACxD;AAEO,MAAM,wBAAwB,OACnC,MACA,cACkC;AAClC,QAAM,eAAe,MAAM,gBAAgB,UAA8B;AAAA;AAAA,IAEvE;AAAA,MACE,QAAQ;AAAA,QACN,MAAM,EAAE,KAAK,KAAK;AAAA,QAClB,YAAY;AAAA,MACd;AAAA,IACF;AAAA;AAAA,IAGA;AAAA,MACE,YAAY;AAAA,QACV,mBAAmB;AAAA,UACjB,MAAM;AAAA,YACJ,OAAO,EAAE,gBAAgB,WAAW;AAAA,YACpC,IAAI;AAAA,YACJ,IAAI;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,mBAAmB,aAAa;AAAA,IACpC,CAAC,WAAW,IAAI,gBAAgB,MAAM;AAAA,EACxC;AAEA,SAAO;AACT;AAOO,MAAM,oBAAoB,OAC/B,YACoB;AACpB,QAAM,SAAS,MAAM,gBAAgB,eAAe,OAAO;AAE3D,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,IAAI,aAAa,2BAA2B,EAAE,QAAQ,CAAC;AAAA,EAC/D;AAEA,SAAO;AACT;AAOO,MAAM,mBAAmB,OAC9B,eACgC;AAChC,QAAM,SAAS,MAAM,mBAAmB,UAAU;AAElD,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,6BAA6B;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,MAAM,gBAAgB,OAAO,UAAU;AAChD;AAaO,MAAM,2BAA2B,OACtC,kBACA,cACyC;AAEzC,QAAM,uBAAuB,MAAM,gBAAgB,KAAK;AAAA,IACtD,KAAK,EAAE,KAAK,iBAAiB;AAAA,IAC7B,YAAY;AAAA,EACd,CAAC;AAGD,QAAM,0BAAoC,CAAC;AAC3C,QAAM,qBAA+B,CAAC;AAEtC,aAAW,OAAO,kBAAkB;AAClC,UAAM,oBAAoB,qBAAqB;AAAA,MAC7C,CAAC,eAAe,WAAW,QAAQ;AAAA,IACrC;AAEA,QAAI,mBAAmB;AACrB,8BAAwB,KAAK,GAAG;AAAA,IAClC,OAAO;AACL,yBAAmB,KAAK,GAAG;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO,EAAE,yBAAyB,mBAAmB;AACvD;AAQO,MAAM,uBAAuB,OAClC,cACA,eACgC;AAChC,QAAM,mBAAmB,4BAA4B,UAAU;AAC/D,QAAM,qBAAqB,iBAAiB,kBAAkB;AAAA,IAC5D;AAAA,EACF,CAAC;AAED,QAAM,cAAc,OAAO,KAAK,kBAAkB;AAClD,QAAM,SAAS,MAAM,mBAAmB,oBAAoB,WAAW;AAEvE,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,6BAA6B;AAAA,MAClD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM,gBAAgB;AAAA,IACnC,EAAE,KAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,IAAI,aAAa,4BAA4B,EAAE,aAAa,CAAC;AAAA,EACrE;AAEA,QAAM,oBAAoB,MAAM,kBAAkB,YAAY;AAE9D,SAAO;AACT;AAQO,MAAM,wBAAwB,OACnC,eACA,YACA,cACgC;AAChC,QAAM,mBAAmB,4BAA4B,UAAU;AAC/D,QAAM,qBAAqB,iBAAiB,kBAAkB;AAAA,IAC5D;AAAA,EACF,CAAC;AAED,QAAM,cAAc,OAAO,KAAK,kBAAkB;AAClD,QAAM,SAAS,MAAM,mBAAmB,oBAAoB,WAAW;AAEvE,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,6BAA6B;AAAA,MAClD;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM,gBAAgB;AAAA,IACnC,EAAE,KAAK,eAAe,YAAY,UAAU;AAAA,IAC5C;AAAA,EACF;AAEA,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,IAAI,aAAa,4BAA4B,EAAE,cAAc,CAAC;AAAA,EACtE;AAEA,QAAM,oBAAoB,MAAM,mBAAmB,eAAe,SAAS;AAE3E,SAAO;AACT;AAOO,MAAM,uBAAuB,OAClC,iBACgC;AAChC,QAAM,aAAa,MAAM,gBAAgB,kBAAkB,YAAY;AAEvE,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,aAAa,wBAAwB,EAAE,aAAa,CAAC;AAAA,EACjE;AAEA,SAAO;AACT;AAGA,MAAM,mBAAmB,CAAC,YAA4B;AACpD,QAAM,QAAQ,QAAQ,MAAM,UAAU;AACtC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,2BAA2B,OAAO,EAAE;AAAA,EACtD;AACA,SAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAC9B;AAEO,MAAM,mBAAmB,CAAC,eAAmC;AAClE,QAAM,iBAAiB;AAEvB,QAAM,oBAAoB,CAAC,GAAI,WAAW,QAAQ,KAAK,KAAK,CAAC,CAAE;AAC/D,QAAM,cAAc,kBAAkB,kBAAkB,SAAS,CAAC;AAGlE,MAAI,YAAY,iBAAiB,WAAW,IAAI;AAChD,MAAI,aAAa,GAAG,cAAc,GAAG,SAAS;AAG9C,SAAO,kBAAkB,SAAS,UAAU,GAAG;AAC7C,iBAAa;AACb,iBAAa,GAAG,cAAc,GAAG,SAAS;AAAA,EAC5C;AAEA,SAAO;AACT;","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 } 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 | Types.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 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 | Types.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 | Types.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 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 | Types.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 | Types.ObjectId,\n dictionary: Partial<Dictionary>\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, [\n 'id',\n ]) as unknown as Partial<Dictionary>;\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 | Types.ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, [\n 'id',\n ]) as unknown as Partial<Dictionary>;\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":[]}
|
|
@@ -24,14 +24,6 @@ const createOrganization = async (organization, userId) => {
|
|
|
24
24
|
throw new GenericError("ORGANIZATION_INVALID_FIELDS", { errors });
|
|
25
25
|
}
|
|
26
26
|
try {
|
|
27
|
-
console.log({
|
|
28
|
-
organization: {
|
|
29
|
-
creatorId: userId,
|
|
30
|
-
membersIds: [userId],
|
|
31
|
-
adminsIds: [userId],
|
|
32
|
-
...organization
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
27
|
const result = await OrganizationModel.create({
|
|
36
28
|
creatorId: userId,
|
|
37
29
|
membersIds: [userId],
|
|
@@ -40,7 +32,6 @@ const createOrganization = async (organization, userId) => {
|
|
|
40
32
|
});
|
|
41
33
|
return result;
|
|
42
34
|
} catch (error) {
|
|
43
|
-
console.error("Organization creation failed:", error);
|
|
44
35
|
throw new GenericError("ORGANIZATION_CREATION_FAILED", {
|
|
45
36
|
error: error.message
|
|
46
37
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/services/organization.service.ts"],"sourcesContent":["import type {\n Organization,\n OrganizationCreationData,\n OrganizationDocument,\n} from '@/types/organization.types';\nimport type { Plan, PlanDocument } from '@/types/plan.types';\nimport { OrganizationModel } from '@models/organization.model';\nimport { GenericError } from '@utils/errors';\nimport type { OrganizationFilters } from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport {\n type OrganizationFields,\n validateOrganization,\n} from '@utils/validation/validateOrganization';\nimport type { Types } from 'mongoose';\n\n/**\n * Finds organizations 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 organizations matching the filters.\n */\nexport const findOrganizations = async (\n filters: OrganizationFilters,\n skip: number,\n limit: number\n): Promise<OrganizationDocument[]> =>\n await OrganizationModel.find(filters).skip(skip).limit(limit);\n\n/**\n * Finds an organization by its ID.\n * @param organizationId - The ID of the organization to find.\n * @returns The organization matching the ID.\n */\nexport const getOrganizationById = async (\n organizationId: string | Types.ObjectId\n): Promise<OrganizationDocument> => {\n const organization = await OrganizationModel.findById(organizationId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', { organizationId });\n }\n\n return organization;\n};\n\n/**\n * Counts the total number of organizations that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of organizations.\n */\nexport const countOrganizations = async (\n filters: OrganizationFilters\n): Promise<number> => {\n const result = await OrganizationModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('ORGANIZATION_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new organization in the database.\n * @param organization - The organization data to create.\n * @returns The created organization.\n */\nexport const createOrganization = async (\n organization: OrganizationCreationData,\n userId: string | Types.ObjectId\n): Promise<OrganizationDocument> => {\n const errors = validateOrganization(organization, ['name']);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('ORGANIZATION_INVALID_FIELDS', { errors });\n }\n\n try {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/services/organization.service.ts"],"sourcesContent":["import type {\n Organization,\n OrganizationCreationData,\n OrganizationDocument,\n} from '@/types/organization.types';\nimport type { Plan, PlanDocument } from '@/types/plan.types';\nimport { OrganizationModel } from '@models/organization.model';\nimport { GenericError } from '@utils/errors';\nimport type { OrganizationFilters } from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport {\n type OrganizationFields,\n validateOrganization,\n} from '@utils/validation/validateOrganization';\nimport type { Types } from 'mongoose';\n\n/**\n * Finds organizations 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 organizations matching the filters.\n */\nexport const findOrganizations = async (\n filters: OrganizationFilters,\n skip: number,\n limit: number\n): Promise<OrganizationDocument[]> =>\n await OrganizationModel.find(filters).skip(skip).limit(limit);\n\n/**\n * Finds an organization by its ID.\n * @param organizationId - The ID of the organization to find.\n * @returns The organization matching the ID.\n */\nexport const getOrganizationById = async (\n organizationId: string | Types.ObjectId\n): Promise<OrganizationDocument> => {\n const organization = await OrganizationModel.findById(organizationId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', { organizationId });\n }\n\n return organization;\n};\n\n/**\n * Counts the total number of organizations that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of organizations.\n */\nexport const countOrganizations = async (\n filters: OrganizationFilters\n): Promise<number> => {\n const result = await OrganizationModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('ORGANIZATION_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new organization in the database.\n * @param organization - The organization data to create.\n * @returns The created organization.\n */\nexport const createOrganization = async (\n organization: OrganizationCreationData,\n userId: string | Types.ObjectId\n): Promise<OrganizationDocument> => {\n const errors = validateOrganization(organization, ['name']);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('ORGANIZATION_INVALID_FIELDS', { errors });\n }\n\n try {\n const result = await OrganizationModel.create({\n creatorId: userId,\n membersIds: [userId],\n adminsIds: [userId],\n ...organization,\n });\n\n return result;\n } catch (error) {\n throw new GenericError('ORGANIZATION_CREATION_FAILED', {\n error: (error as Error).message,\n });\n }\n};\n\n/**\n * Updates an existing organization in the database by its ID.\n * @param organizationId - The ID of the organization to update.\n * @param organization - The updated organization data.\n * @returns The updated organization.\n */\nexport const updateOrganizationById = async (\n organizationId: string | Types.ObjectId,\n organization: Partial<Organization>\n): Promise<OrganizationDocument> => {\n const updatedKeys = Object.keys(organization) as OrganizationFields;\n const errors = validateOrganization(organization, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('ORGANIZATION_INVALID_FIELDS', {\n organizationId,\n errors,\n });\n }\n\n const result = await OrganizationModel.updateOne(\n { _id: organizationId },\n organization\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', { organizationId });\n }\n\n return await getOrganizationById(organizationId);\n};\n\n/**\n * Deletes an organization from the database by its ID.\n * @param organizationId - The ID of the organization to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteOrganizationById = async (\n organizationId: string | Types.ObjectId\n): Promise<OrganizationDocument> => {\n const organization =\n await OrganizationModel.findByIdAndDelete(organizationId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', { organizationId });\n }\n\n return organization;\n};\n\n/**\n * Updates an existing plan in the database by its ID.\n * @param planId - The ID of the plan to update.\n * @param plan - The updated plan data.\n * @returns The updated plan.\n */\nexport const updatePlan = async (\n organization: Organization | OrganizationDocument,\n plan: Partial<Plan>\n): Promise<OrganizationDocument | null> => {\n let prevPlan = organization.plan ?? {};\n\n if (typeof (prevPlan as PlanDocument)?.toObject === 'function') {\n prevPlan = (prevPlan as PlanDocument).toObject();\n }\n\n const updateOrganizationResult = await OrganizationModel.updateOne(\n { _id: organization.id },\n { $set: { plan: { ...prevPlan, ...plan } } },\n { new: true }\n );\n\n if (updateOrganizationResult.matchedCount === 0) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization.id,\n });\n }\n\n const updatedOrganization = await getOrganizationById(organization.id);\n\n return updatedOrganization;\n};\n"],"mappings":"AAMA,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAE7B;AAAA,EAEE;AAAA,OACK;AAUA,MAAM,oBAAoB,OAC/B,SACA,MACA,UAEA,MAAM,kBAAkB,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK;AAOvD,MAAM,sBAAsB,OACjC,mBACkC;AAClC,QAAM,eAAe,MAAM,kBAAkB,SAAS,cAAc;AAEpE,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,aAAa,0BAA0B,EAAE,eAAe,CAAC;AAAA,EACrE;AAEA,SAAO;AACT;AAOO,MAAM,qBAAqB,OAChC,YACoB;AACpB,QAAM,SAAS,MAAM,kBAAkB,eAAe,OAAO;AAE7D,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,IAAI,aAAa,6BAA6B,EAAE,QAAQ,CAAC;AAAA,EACjE;AAEA,SAAO;AACT;AAOO,MAAM,qBAAqB,OAChC,cACA,WACkC;AAClC,QAAM,SAAS,qBAAqB,cAAc,CAAC,MAAM,CAAC;AAE1D,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,+BAA+B,EAAE,OAAO,CAAC;AAAA,EAClE;AAEA,MAAI;AACF,UAAM,SAAS,MAAM,kBAAkB,OAAO;AAAA,MAC5C,WAAW;AAAA,MACX,YAAY,CAAC,MAAM;AAAA,MACnB,WAAW,CAAC,MAAM;AAAA,MAClB,GAAG;AAAA,IACL,CAAC;AAED,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,IAAI,aAAa,gCAAgC;AAAA,MACrD,OAAQ,MAAgB;AAAA,IAC1B,CAAC;AAAA,EACH;AACF;AAQO,MAAM,yBAAyB,OACpC,gBACA,iBACkC;AAClC,QAAM,cAAc,OAAO,KAAK,YAAY;AAC5C,QAAM,SAAS,qBAAqB,cAAc,WAAW;AAE7D,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,+BAA+B;AAAA,MACpD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM,kBAAkB;AAAA,IACrC,EAAE,KAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,IAAI,aAAa,8BAA8B,EAAE,eAAe,CAAC;AAAA,EACzE;AAEA,SAAO,MAAM,oBAAoB,cAAc;AACjD;AAOO,MAAM,yBAAyB,OACpC,mBACkC;AAClC,QAAM,eACJ,MAAM,kBAAkB,kBAAkB,cAAc;AAE1D,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,aAAa,0BAA0B,EAAE,eAAe,CAAC;AAAA,EACrE;AAEA,SAAO;AACT;AAQO,MAAM,aAAa,OACxB,cACA,SACyC;AACzC,MAAI,WAAW,aAAa,QAAQ,CAAC;AAErC,MAAI,OAAQ,UAA2B,aAAa,YAAY;AAC9D,eAAY,SAA0B,SAAS;AAAA,EACjD;AAEA,QAAM,2BAA2B,MAAM,kBAAkB;AAAA,IACvD,EAAE,KAAK,aAAa,GAAG;AAAA,IACvB,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,KAAK,EAAE,EAAE;AAAA,IAC3C,EAAE,KAAK,KAAK;AAAA,EACd;AAEA,MAAI,yBAAyB,iBAAiB,GAAG;AAC/C,UAAM,IAAI,aAAa,8BAA8B;AAAA,MACnD,gBAAgB,aAAa;AAAA,IAC/B,CAAC;AAAA,EACH;AAEA,QAAM,sBAAsB,MAAM,oBAAoB,aAAa,EAAE;AAErE,SAAO;AACT;","names":[]}
|
|
@@ -23,6 +23,7 @@ const formatSession = (session) => {
|
|
|
23
23
|
permissions = intersectPermissions(permissions, session.permissions);
|
|
24
24
|
}
|
|
25
25
|
const resultSession = {
|
|
26
|
+
session: session.session,
|
|
26
27
|
user: mapUserToAPI(session.user),
|
|
27
28
|
organization: mapOrganizationToAPI(session.organization),
|
|
28
29
|
project: mapProjectToAPI(session.project),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/auth/getAuth.ts"],"sourcesContent":["import type { OrganizationAPI } from '@/types/organization.types';\nimport type { ProjectAPI } from '@/types/project.types';\nimport type {\n SessionAPI,\n SessionContext,\n SessionDataApi,\n} from '@/types/session.types';\nimport type { User, UserAPI } from '@/types/user.types';\nimport { sendVerificationUpdate } from '@controllers/user.controller';\nimport { logger } from '@logger';\nimport { sendEmail } from '@services/email.service';\nimport { getOrganizationById } from '@services/organization.service';\nimport { getProjectById } from '@services/project.service';\nimport { getUserById } from '@services/user.service';\nimport { mapOrganizationToAPI } from '@utils/mapper/organization';\nimport { mapProjectToAPI } from '@utils/mapper/project';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport {\n computeEffectivePermission,\n getSessionRoles,\n intersectPermissions,\n} from '@utils/permissions';\nimport { betterAuth, OmitId } from 'better-auth';\nimport { mongodbAdapter } from 'better-auth/adapters/mongodb';\nimport { createAuthMiddleware } from 'better-auth/api';\nimport { customSession } from 'better-auth/plugins';\nimport type { MongoClient } from 'mongodb';\n\nexport type Auth = ReturnType<typeof betterAuth>;\n\nexport const formatSession = (session: SessionContext): OmitId<SessionAPI> => {\n const roles = getSessionRoles(session);\n let permissions = computeEffectivePermission(roles);\n\n // Intersect in the case a Access Token try to override the permissions\n if (session.permissions) {\n permissions = intersectPermissions(permissions, session.permissions);\n }\n\n const resultSession = {\n user: mapUserToAPI(session.user),\n organization: mapOrganizationToAPI(session.organization),\n project: mapProjectToAPI(session.project),\n authType: 'session',\n permissions,\n roles,\n } as OmitId<SessionAPI>;\n\n return resultSession;\n};\n\nexport const getAuth = (dbClient: MongoClient): Auth => {\n if (!dbClient) {\n throw new Error('MongoDB connection not established');\n }\n\n const auth = betterAuth({\n appName: 'Intlayer',\n\n database: mongodbAdapter(dbClient.db()),\n\n /**\n * User model\n */\n user: {\n modelName: 'users',\n },\n\n databaseHooks: {\n user: {\n create: {\n // Runs once, immediately after the INSERT\n after: async (user) => {\n if (!user?.emailVerified) return;\n\n await sendEmail({\n type: 'welcome',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n loginLink: `${process.env.CLIENT_URL}/auth/login`,\n locale: (user as any).lang,\n });\n logger.info('Welcome e‑mail delivered', {\n email: user.email,\n });\n },\n },\n },\n },\n\n hooks: {\n after: createAuthMiddleware(async (ctx) => {\n const { path, context } = ctx;\n\n const newUser = context.newSession?.user;\n const existingUser = context.session?.user;\n const user = newUser ?? existingUser;\n\n if (!user) return;\n\n if (['/verify-email'].includes(path)) {\n sendVerificationUpdate(user as unknown as User);\n logger.info('SSE verification update sent', {\n email: user.email,\n userId: user.id,\n });\n\n await sendEmail({\n type: 'welcome',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n loginLink: `${process.env.CLIENT_URL}/auth/login`,\n locale: (user as any).lang,\n });\n logger.info('Welcome e‑mail delivered', {\n email: user.email,\n });\n }\n }),\n },\n\n advanced: {\n // 1️⃣ Change or drop the global prefix\n // cookiePrefix: \"intlayer\", // => intlayer.session_token\n cookiePrefix: 'intlayer', // => session_token (no prefix)\n\n // 2️⃣ Override just the session‑token cookie\n cookies: {\n session_token: {\n // name: 'intlayer_session_token', // final name depends on the prefix above\n // attributes: { sameSite: \"lax\", maxAge: 60 * 60 * 24 } // optional\n },\n },\n\n // 3️⃣ (optional) turn off the automatic __Secure‑ prefix in non‑prod\n // useSecureCookies: false,\n },\n\n session: {\n modelName: 'sessions',\n id: 'id',\n\n additionalFields: {\n activeOrganizationId: { type: 'string', nullable: true, input: false },\n activeProjectId: { type: 'string', nullable: true, input: false },\n },\n },\n\n plugins: [\n customSession(async ({ session }) => {\n const typedSession = session as unknown as SessionDataApi;\n\n let userAPI: UserAPI | null = null;\n let organizationAPI: OrganizationAPI | null = null;\n let projectAPI: ProjectAPI | null = null;\n\n if (typedSession.userId) {\n const userData = await getUserById(typedSession.userId);\n\n if (userData) {\n userAPI = mapUserToAPI(userData);\n }\n }\n\n if (typedSession.activeOrganizationId) {\n const orgData = await getOrganizationById(\n typedSession.activeOrganizationId\n );\n\n if (orgData) {\n organizationAPI = mapOrganizationToAPI(orgData);\n }\n }\n if (typedSession.activeProjectId) {\n const projectData = await getProjectById(\n typedSession.activeProjectId\n );\n\n if (projectData) {\n projectAPI = mapProjectToAPI(projectData);\n }\n }\n\n const sessionWithNoPermission: SessionContext = {\n session: typedSession,\n user: userAPI!,\n organization: organizationAPI ?? null,\n project: projectAPI ?? null,\n authType: 'session',\n };\n\n return formatSession(sessionWithNoPermission);\n }),\n ],\n\n emailAndPassword: {\n enabled: true,\n disableSignUp: false,\n requireEmailVerification: true,\n minPasswordLength: 8,\n maxPasswordLength: 128,\n autoSignIn: true,\n sendResetPassword: async ({ user, url }) => {\n logger.info('sending reset password email', { email: user.email });\n await sendEmail({\n type: 'resetPassword',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n resetLink: url,\n });\n },\n resetPasswordTokenExpiresIn: 3600,\n },\n accountLinking: {\n enabled: true, // allow linking in general\n trustedProviders: ['google', 'github'], // optional: auto‑link when Google verifies the e‑mail\n },\n emailVerification: {\n autoSignInAfterVerification: true,\n sendVerificationEmail: async ({ user, url }) => {\n logger.info('sending verification email', { email: user.email });\n await sendEmail({\n type: 'validate',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n validationLink: url,\n });\n },\n },\n\n crossSubDomainCookies: {\n enabled: true,\n additionalCookies: ['session_token'],\n domain: process.env.CLIENT_URL as string,\n },\n cookiePrefix: 'intlayer',\n cookies: {\n session_token: {\n name: 'session_token',\n attributes: {\n httpOnly: true,\n secure: true,\n },\n },\n },\n\n trustedOrigins: [process.env.CLIENT_URL as string],\n\n socialProviders: {\n google: {\n clientId: process.env.GOOGLE_CLIENT_ID as string,\n clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,\n },\n github: {\n clientId: process.env.GITHUB_CLIENT_ID as string,\n clientSecret: process.env.GITHUB_CLIENT_SECRET as string,\n },\n },\n\n logger: {\n log: (level, message, ...args) => logger[level](message, ...args),\n },\n });\n\n return auth;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/auth/getAuth.ts"],"sourcesContent":["import type { OrganizationAPI } from '@/types/organization.types';\nimport type { ProjectAPI } from '@/types/project.types';\nimport type {\n SessionAPI,\n SessionContext,\n SessionDataApi,\n} from '@/types/session.types';\nimport type { User, UserAPI } from '@/types/user.types';\nimport { sendVerificationUpdate } from '@controllers/user.controller';\nimport { logger } from '@logger';\nimport { sendEmail } from '@services/email.service';\nimport { getOrganizationById } from '@services/organization.service';\nimport { getProjectById } from '@services/project.service';\nimport { getUserById } from '@services/user.service';\nimport { mapOrganizationToAPI } from '@utils/mapper/organization';\nimport { mapProjectToAPI } from '@utils/mapper/project';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport {\n computeEffectivePermission,\n getSessionRoles,\n intersectPermissions,\n} from '@utils/permissions';\nimport { betterAuth, OmitId } from 'better-auth';\nimport { mongodbAdapter } from 'better-auth/adapters/mongodb';\nimport { createAuthMiddleware } from 'better-auth/api';\nimport { customSession } from 'better-auth/plugins';\nimport type { MongoClient } from 'mongodb';\n\nexport type Auth = ReturnType<typeof betterAuth>;\n\nexport const formatSession = (session: SessionContext): OmitId<SessionAPI> => {\n const roles = getSessionRoles(session);\n let permissions = computeEffectivePermission(roles);\n\n // Intersect in the case a Access Token try to override the permissions\n if (session.permissions) {\n permissions = intersectPermissions(permissions, session.permissions);\n }\n\n const resultSession = {\n session: session.session,\n user: mapUserToAPI(session.user),\n organization: mapOrganizationToAPI(session.organization),\n project: mapProjectToAPI(session.project),\n authType: 'session',\n permissions,\n roles,\n } as OmitId<SessionAPI>;\n\n return resultSession;\n};\n\nexport const getAuth = (dbClient: MongoClient): Auth => {\n if (!dbClient) {\n throw new Error('MongoDB connection not established');\n }\n\n const auth = betterAuth({\n appName: 'Intlayer',\n\n database: mongodbAdapter(dbClient.db()),\n\n /**\n * User model\n */\n user: {\n modelName: 'users',\n },\n\n databaseHooks: {\n user: {\n create: {\n // Runs once, immediately after the INSERT\n after: async (user) => {\n if (!user?.emailVerified) return;\n\n await sendEmail({\n type: 'welcome',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n loginLink: `${process.env.CLIENT_URL}/auth/login`,\n locale: (user as any).lang,\n });\n logger.info('Welcome e‑mail delivered', {\n email: user.email,\n });\n },\n },\n },\n },\n\n hooks: {\n after: createAuthMiddleware(async (ctx) => {\n const { path, context } = ctx;\n\n const newUser = context.newSession?.user;\n const existingUser = context.session?.user;\n const user = newUser ?? existingUser;\n\n if (!user) return;\n\n if (['/verify-email'].includes(path)) {\n sendVerificationUpdate(user as unknown as User);\n logger.info('SSE verification update sent', {\n email: user.email,\n userId: user.id,\n });\n\n await sendEmail({\n type: 'welcome',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n loginLink: `${process.env.CLIENT_URL}/auth/login`,\n locale: (user as any).lang,\n });\n logger.info('Welcome e‑mail delivered', {\n email: user.email,\n });\n }\n }),\n },\n\n advanced: {\n // 1️⃣ Change or drop the global prefix\n // cookiePrefix: \"intlayer\", // => intlayer.session_token\n cookiePrefix: 'intlayer', // => session_token (no prefix)\n\n // 2️⃣ Override just the session‑token cookie\n cookies: {\n session_token: {\n // name: 'intlayer_session_token', // final name depends on the prefix above\n // attributes: { sameSite: \"lax\", maxAge: 60 * 60 * 24 } // optional\n },\n },\n\n // 3️⃣ (optional) turn off the automatic __Secure‑ prefix in non‑prod\n // useSecureCookies: false,\n },\n\n session: {\n modelName: 'sessions',\n id: 'id',\n\n additionalFields: {\n activeOrganizationId: { type: 'string', nullable: true, input: false },\n activeProjectId: { type: 'string', nullable: true, input: false },\n },\n },\n\n plugins: [\n customSession(async ({ session }) => {\n const typedSession = session as unknown as SessionDataApi;\n\n let userAPI: UserAPI | null = null;\n let organizationAPI: OrganizationAPI | null = null;\n let projectAPI: ProjectAPI | null = null;\n\n if (typedSession.userId) {\n const userData = await getUserById(typedSession.userId);\n\n if (userData) {\n userAPI = mapUserToAPI(userData);\n }\n }\n\n if (typedSession.activeOrganizationId) {\n const orgData = await getOrganizationById(\n typedSession.activeOrganizationId\n );\n\n if (orgData) {\n organizationAPI = mapOrganizationToAPI(orgData);\n }\n }\n if (typedSession.activeProjectId) {\n const projectData = await getProjectById(\n typedSession.activeProjectId\n );\n\n if (projectData) {\n projectAPI = mapProjectToAPI(projectData);\n }\n }\n\n const sessionWithNoPermission: SessionContext = {\n session: typedSession,\n user: userAPI!,\n organization: organizationAPI ?? null,\n project: projectAPI ?? null,\n authType: 'session',\n };\n\n return formatSession(sessionWithNoPermission);\n }),\n ],\n\n emailAndPassword: {\n enabled: true,\n disableSignUp: false,\n requireEmailVerification: true,\n minPasswordLength: 8,\n maxPasswordLength: 128,\n autoSignIn: true,\n sendResetPassword: async ({ user, url }) => {\n logger.info('sending reset password email', { email: user.email });\n await sendEmail({\n type: 'resetPassword',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n resetLink: url,\n });\n },\n resetPasswordTokenExpiresIn: 3600,\n },\n accountLinking: {\n enabled: true, // allow linking in general\n trustedProviders: ['google', 'github'], // optional: auto‑link when Google verifies the e‑mail\n },\n emailVerification: {\n autoSignInAfterVerification: true,\n sendVerificationEmail: async ({ user, url }) => {\n logger.info('sending verification email', { email: user.email });\n await sendEmail({\n type: 'validate',\n to: user.email,\n username: user.name ?? user.email.split('@')[0],\n validationLink: url,\n });\n },\n },\n\n crossSubDomainCookies: {\n enabled: true,\n additionalCookies: ['session_token'],\n domain: process.env.CLIENT_URL as string,\n },\n cookiePrefix: 'intlayer',\n cookies: {\n session_token: {\n name: 'session_token',\n attributes: {\n httpOnly: true,\n secure: true,\n },\n },\n },\n\n trustedOrigins: [process.env.CLIENT_URL as string],\n\n socialProviders: {\n google: {\n clientId: process.env.GOOGLE_CLIENT_ID as string,\n clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,\n },\n github: {\n clientId: process.env.GITHUB_CLIENT_ID as string,\n clientSecret: process.env.GITHUB_CLIENT_SECRET as string,\n },\n },\n\n logger: {\n log: (level, message, ...args) => logger[level](message, ...args),\n },\n });\n\n return auth;\n};\n"],"mappings":"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","names":[]}
|