@intlayer/backend 4.1.8 → 4.1.10
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 +5 -5
- package/dist/cjs/controllers/dictionary.controller.cjs +53 -9
- package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
- package/dist/cjs/controllers/event-listener.cjs +80 -0
- package/dist/cjs/controllers/event-listener.cjs.map +1 -0
- package/dist/cjs/controllers/oAuth2.controller.cjs +1 -1
- package/dist/cjs/controllers/oAuth2.controller.cjs.map +1 -1
- package/dist/cjs/controllers/organization.controller.cjs +1 -1
- package/dist/cjs/controllers/project.controller.cjs +1 -1
- package/dist/cjs/controllers/projectAccessKey.controller.cjs +1 -1
- package/dist/cjs/controllers/sessionAuth.controller.cjs +1 -1
- package/dist/cjs/controllers/stripe.controller.cjs +3 -2
- package/dist/cjs/controllers/stripe.controller.cjs.map +1 -1
- package/dist/cjs/controllers/tag.controller.cjs +1 -1
- package/dist/cjs/controllers/user.controller.cjs +1 -1
- package/dist/cjs/index.cjs +7 -6
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/routes/event-listener.routes.cjs +45 -0
- package/dist/cjs/routes/event-listener.routes.cjs.map +1 -0
- package/dist/cjs/services/dictionary.service.cjs +1 -1
- package/dist/cjs/services/oAuth2.service.cjs +13 -10
- package/dist/cjs/services/oAuth2.service.cjs.map +1 -1
- package/dist/cjs/services/organization.service.cjs +1 -1
- package/dist/cjs/services/project.service.cjs +1 -1
- package/dist/cjs/services/projectAccessKey.service.cjs +2 -2
- package/dist/cjs/services/projectAccessKey.service.cjs.map +1 -1
- package/dist/cjs/services/sessionAuth.service.cjs +1 -1
- package/dist/cjs/services/subscription.service.cjs +6 -6
- package/dist/cjs/services/subscription.service.cjs.map +1 -1
- package/dist/cjs/services/tag.service.cjs +1 -1
- package/dist/cjs/services/user.service.cjs +1 -1
- package/dist/cjs/types/oAuth2.types.cjs +17 -0
- package/dist/cjs/types/oAuth2.types.cjs.map +1 -0
- package/dist/cjs/utils/AI/askDocQuestion.cjs +7 -1
- package/dist/cjs/utils/AI/askDocQuestion.cjs.map +1 -1
- package/dist/cjs/utils/AI/embeddings.json +1845 -0
- package/dist/cjs/utils/errors/errorCodes.cjs +23 -1
- package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
- package/dist/cjs/webhooks/stripe.webhook.cjs +3 -3
- package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -1
- package/dist/esm/controllers/ai.controller.mjs +5 -5
- package/dist/esm/controllers/dictionary.controller.mjs +53 -9
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/event-listener.mjs +45 -0
- package/dist/esm/controllers/event-listener.mjs.map +1 -0
- package/dist/esm/controllers/oAuth2.controller.mjs +1 -1
- package/dist/esm/controllers/oAuth2.controller.mjs.map +1 -1
- package/dist/esm/controllers/organization.controller.mjs +1 -1
- package/dist/esm/controllers/project.controller.mjs +1 -1
- package/dist/esm/controllers/projectAccessKey.controller.mjs +1 -1
- package/dist/esm/controllers/sessionAuth.controller.mjs +1 -1
- package/dist/esm/controllers/stripe.controller.mjs +3 -2
- package/dist/esm/controllers/stripe.controller.mjs.map +1 -1
- package/dist/esm/controllers/tag.controller.mjs +1 -1
- package/dist/esm/controllers/user.controller.mjs +1 -1
- package/dist/esm/index.mjs +7 -6
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/routes/event-listener.routes.mjs +20 -0
- package/dist/esm/routes/event-listener.routes.mjs.map +1 -0
- package/dist/esm/services/dictionary.service.mjs +1 -1
- package/dist/esm/services/oAuth2.service.mjs +7 -4
- package/dist/esm/services/oAuth2.service.mjs.map +1 -1
- package/dist/esm/services/organization.service.mjs +1 -1
- package/dist/esm/services/project.service.mjs +1 -1
- package/dist/esm/services/projectAccessKey.service.mjs +2 -2
- package/dist/esm/services/projectAccessKey.service.mjs.map +1 -1
- package/dist/esm/services/sessionAuth.service.mjs +1 -1
- package/dist/esm/services/subscription.service.mjs +6 -6
- package/dist/esm/services/subscription.service.mjs.map +1 -1
- package/dist/esm/services/tag.service.mjs +1 -1
- package/dist/esm/services/user.service.mjs +1 -1
- package/dist/esm/types/oAuth2.types.mjs +1 -0
- package/dist/esm/types/oAuth2.types.mjs.map +1 -0
- package/dist/esm/utils/AI/askDocQuestion.mjs +7 -1
- package/dist/esm/utils/AI/askDocQuestion.mjs.map +1 -1
- package/dist/esm/utils/AI/embeddings.json +1845 -0
- package/dist/esm/utils/errors/errorCodes.mjs +23 -1
- package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
- package/dist/esm/webhooks/stripe.webhook.mjs +3 -3
- package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -1
- package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
- package/dist/types/controllers/event-listener.d.ts +16 -0
- package/dist/types/controllers/event-listener.d.ts.map +1 -0
- package/dist/types/controllers/oAuth2.controller.d.ts +2 -5
- package/dist/types/controllers/oAuth2.controller.d.ts.map +1 -1
- package/dist/types/controllers/stripe.controller.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/routes/event-listener.routes.d.ts +12 -0
- package/dist/types/routes/event-listener.routes.d.ts.map +1 -0
- package/dist/types/services/oAuth2.service.d.ts +6 -5
- package/dist/types/services/oAuth2.service.d.ts.map +1 -1
- package/dist/types/services/subscription.service.d.ts.map +1 -1
- package/dist/types/types/oAuth2.types.d.ts +11 -0
- package/dist/types/types/oAuth2.types.d.ts.map +1 -0
- package/dist/types/utils/AI/askDocQuestion.d.ts.map +1 -1
- package/dist/types/utils/errors/errorCodes.d.ts +23 -1
- package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
- package/dist/types/webhooks/stripe.webhook.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -39,11 +39,11 @@ var import_dictionary = require('./../services/dictionary.service.cjs');
|
|
|
39
39
|
var import_tag = require('./../services/tag.service.cjs');
|
|
40
40
|
var tagService = __toESM(require('./../services/tag.service.cjs'), 1);
|
|
41
41
|
var askDocQuestionUtil = __toESM(require('./../utils/AI/askDocQuestion.cjs'), 1);
|
|
42
|
-
var auditContentDeclarationUtil = __toESM(require('./../utils/auditDictionary.cjs'), 1);
|
|
43
|
-
var auditContentDeclarationFieldUtil = __toESM(require('./../utils/auditDictionaryField.cjs'), 1);
|
|
44
|
-
var auditContentDeclarationMetadataUtil = __toESM(require('./../utils/auditDictionaryMetadata.cjs'), 1);
|
|
45
|
-
var auditTagUtil = __toESM(require('./../utils/auditTag.cjs'), 1);
|
|
46
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
42
|
+
var auditContentDeclarationUtil = __toESM(require('./../utils/auditDictionary/index.cjs'), 1);
|
|
43
|
+
var auditContentDeclarationFieldUtil = __toESM(require('./../utils/auditDictionaryField/index.cjs'), 1);
|
|
44
|
+
var auditContentDeclarationMetadataUtil = __toESM(require('./../utils/auditDictionaryMetadata/index.cjs'), 1);
|
|
45
|
+
var auditTagUtil = __toESM(require('./../utils/auditTag/index.cjs'), 1);
|
|
46
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
47
47
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
48
48
|
const auditContentDeclaration = async (req, res, _next) => {
|
|
49
49
|
const { user, project } = res.locals;
|
|
@@ -39,11 +39,12 @@ __export(dictionary_controller_exports, {
|
|
|
39
39
|
module.exports = __toCommonJS(dictionary_controller_exports);
|
|
40
40
|
var import_logger = require('./../logger/index.cjs');
|
|
41
41
|
var dictionaryService = __toESM(require('./../services/dictionary.service.cjs'), 1);
|
|
42
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
42
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
43
43
|
var import_getDictionaryFiltersAndPagination = require('./../utils/filtersAndPagination/getDictionaryFiltersAndPagination.cjs');
|
|
44
44
|
var import_dictionary = require('./../utils/mapper/dictionary.cjs');
|
|
45
45
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
46
46
|
var import_express_intlayer = require("express-intlayer");
|
|
47
|
+
var eventListener = __toESM(require('./../controllers/event-listener.cjs'), 1);
|
|
47
48
|
const getDictionaries = async (req, res, _next) => {
|
|
48
49
|
const { user, project, dictionaryRights } = res.locals;
|
|
49
50
|
const { filters, pageSize, skip, page, getNumberOfPages } = (0, import_getDictionaryFiltersAndPagination.getDictionaryFiltersAndPagination)(req);
|
|
@@ -201,6 +202,12 @@ const addDictionary = async (req, res, _next) => {
|
|
|
201
202
|
data: apiResult
|
|
202
203
|
});
|
|
203
204
|
res.json(responseData);
|
|
205
|
+
eventListener.sendDictionaryUpdate([
|
|
206
|
+
{
|
|
207
|
+
dictionary: (0, import_dictionary.mapDictionaryToAPI)(newDictionary, project._id),
|
|
208
|
+
status: "ADDED"
|
|
209
|
+
}
|
|
210
|
+
]);
|
|
204
211
|
return;
|
|
205
212
|
} catch (error) {
|
|
206
213
|
import_errors.ErrorHandler.handleAppErrorResponse(res, error);
|
|
@@ -245,11 +252,9 @@ const pushDictionaries = async (req, res, _next) => {
|
|
|
245
252
|
const newDictionaries = dictionaryData.filter(
|
|
246
253
|
(dictionary) => newDictionariesKey.includes(dictionary.key)
|
|
247
254
|
);
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
error: []
|
|
252
|
-
};
|
|
255
|
+
const newDictionariesResult = [];
|
|
256
|
+
const updatedDictionariesResult = [];
|
|
257
|
+
const errorResult = [];
|
|
253
258
|
for (const dictionaryDataEl of newDictionaries) {
|
|
254
259
|
const publishedVersion = dictionaryDataEl.publishedVersion ? dictionaryDataEl.publishedVersion === "-1" ? null : dictionaryDataEl.publishedVersion : null;
|
|
255
260
|
const dictionary = {
|
|
@@ -270,7 +275,9 @@ const pushDictionaries = async (req, res, _next) => {
|
|
|
270
275
|
};
|
|
271
276
|
try {
|
|
272
277
|
const newDictionary = await dictionaryService.createDictionary(dictionary);
|
|
273
|
-
|
|
278
|
+
newDictionariesResult.push(
|
|
279
|
+
(0, import_dictionary.mapDictionaryToAPI)(newDictionary, project._id)
|
|
280
|
+
);
|
|
274
281
|
} catch (error) {
|
|
275
282
|
import_errors.ErrorHandler.handleAppErrorResponse(res, error);
|
|
276
283
|
return;
|
|
@@ -314,18 +321,29 @@ const pushDictionaries = async (req, res, _next) => {
|
|
|
314
321
|
key: dictionaryDataEl.key
|
|
315
322
|
};
|
|
316
323
|
try {
|
|
317
|
-
const
|
|
324
|
+
const updatedDictionary = await dictionaryService.updateDictionaryByKey(
|
|
318
325
|
dictionaryDataEl.key,
|
|
319
326
|
dictionary,
|
|
320
327
|
project._id
|
|
321
328
|
);
|
|
322
|
-
|
|
329
|
+
updatedDictionariesResult.push(
|
|
330
|
+
(0, import_dictionary.mapDictionaryToAPI)(updatedDictionary, project._id)
|
|
331
|
+
);
|
|
323
332
|
} catch (error) {
|
|
324
333
|
import_errors.ErrorHandler.handleAppErrorResponse(res, error);
|
|
325
334
|
return;
|
|
326
335
|
}
|
|
327
336
|
}
|
|
328
337
|
}
|
|
338
|
+
const result = {
|
|
339
|
+
newDictionaries: newDictionariesResult.map(
|
|
340
|
+
(dictionary) => dictionary.key
|
|
341
|
+
),
|
|
342
|
+
updatedDictionaries: updatedDictionariesResult.map(
|
|
343
|
+
(dictionary) => dictionary.key
|
|
344
|
+
),
|
|
345
|
+
error: errorResult
|
|
346
|
+
};
|
|
329
347
|
const responseData = (0, import_responseData.formatResponse)({
|
|
330
348
|
message: (0, import_express_intlayer.t)({
|
|
331
349
|
en: "Dictionaries updated successfully",
|
|
@@ -339,6 +357,20 @@ const pushDictionaries = async (req, res, _next) => {
|
|
|
339
357
|
}),
|
|
340
358
|
data: result
|
|
341
359
|
});
|
|
360
|
+
eventListener.sendDictionaryUpdate([
|
|
361
|
+
...newDictionariesResult.map(
|
|
362
|
+
(dictionary) => ({
|
|
363
|
+
dictionary,
|
|
364
|
+
status: "ADDED"
|
|
365
|
+
})
|
|
366
|
+
),
|
|
367
|
+
...updatedDictionariesResult.map(
|
|
368
|
+
(dictionary) => ({
|
|
369
|
+
dictionary,
|
|
370
|
+
status: "UPDATED"
|
|
371
|
+
})
|
|
372
|
+
)
|
|
373
|
+
]);
|
|
342
374
|
res.json(responseData);
|
|
343
375
|
return;
|
|
344
376
|
} catch (error) {
|
|
@@ -389,6 +421,12 @@ const updateDictionary = async (req, res, _next) => {
|
|
|
389
421
|
}),
|
|
390
422
|
data: apiResult
|
|
391
423
|
});
|
|
424
|
+
eventListener.sendDictionaryUpdate([
|
|
425
|
+
{
|
|
426
|
+
dictionary: apiResult,
|
|
427
|
+
status: "UPDATED"
|
|
428
|
+
}
|
|
429
|
+
]);
|
|
392
430
|
res.json(responseData);
|
|
393
431
|
return;
|
|
394
432
|
} catch (error) {
|
|
@@ -443,6 +481,12 @@ const deleteDictionary = async (req, res, _next) => {
|
|
|
443
481
|
data: apiResult
|
|
444
482
|
});
|
|
445
483
|
res.json(responseData);
|
|
484
|
+
eventListener.sendDictionaryUpdate([
|
|
485
|
+
{
|
|
486
|
+
dictionary: apiResult,
|
|
487
|
+
status: "DELETED"
|
|
488
|
+
}
|
|
489
|
+
]);
|
|
446
490
|
return;
|
|
447
491
|
} catch (error) {
|
|
448
492
|
import_errors.ErrorHandler.handleAppErrorResponse(res, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type Dictionary as LocalDictionary } from '@intlayer/core';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as dictionaryService from '@services/dictionary.service';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport {\n type DictionaryFiltersParams,\n getDictionaryFiltersAndPagination,\n} from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { mapDictionaryToAPI } from '@utils/mapper/dictionary';\nimport {\n formatPaginatedResponse,\n type ResponseData,\n type PaginatedResponse,\n formatResponse,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\n\nexport type GetDictionariesParams =\n FiltersAndPagination<DictionaryFiltersParams>;\nexport type GetDictionariesResult = PaginatedResponse<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaries = async (\n req: Request<GetDictionariesParams>,\n res: ResponseWithInformation<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, dictionaryRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries(\n filters,\n skip,\n pageSize\n );\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) =>\n mapDictionaryToAPI(el, project._id, el.publishedVersion ?? undefined)\n );\n\n const responseData = formatPaginatedResponse<DictionaryAPI>({\n data: dictionariesAPI,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetDictionariesKeysResult = ResponseData<string[]>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesKeys = async (\n _req: Request,\n res: ResponseWithInformation<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, dictionaryRights } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionariesKeys = await dictionaryService.getDictionariesKeys(\n project._id\n );\n\n const responseData = formatResponse<string[]>({\n data: dictionariesKeys,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetDictionaryParams = { dictionaryKey: string };\nexport type GetDictionaryQuery = { version?: string };\nexport type GetDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaryByKey = async (\n req: Request<GetDictionaryParams, any, any, GetDictionaryQuery>,\n res: ResponseWithInformation<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const { dictionaryKey } = req.params;\n const version = req.query.version;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project._id\n );\n\n if (!dictionary.projectIds.map(String).includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const apiResult = mapDictionaryToAPI(dictionary, project._id, version);\n\n const responseData = formatResponse<DictionaryAPI>({\n data: apiResult,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddDictionaryBody = DictionaryCreationData;\nexport type AddDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Adds a new dictionary to the database.\n */\nexport const addDictionary = async (\n req: Request<any, any, AddDictionaryBody>,\n res: ResponseWithInformation<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n const dictionary: DictionaryData = {\n key: dictionaryData.key,\n title: dictionaryData.title,\n description: dictionaryData.description,\n content: {\n v1: {\n content: dictionaryData.content,\n },\n },\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryData.filePath ?? '',\n },\n projectIds: dictionaryData.projectIds ?? [String(project._id)],\n };\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary created successfully',\n fr: 'Dictionnaire créé avec succès',\n es: 'Diccionario creado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been created successfully',\n fr: 'Votre dictionnaire a été créé avec succès',\n es: 'Su diccionario ha sido creado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type PushDictionariesBody = {\n dictionaries: LocalDictionary[];\n};\ntype PushDictionariesResultData = {\n newDictionaries: string[];\n updatedDictionaries: string[];\n error: { dictionaryId: string; message: string }[];\n};\nexport type PushDictionariesResult = ResponseData<PushDictionariesResultData>;\n\n/**\n * Check each dictionaries, add the new ones and update the existing ones.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response containing the created dictionary.\n */\nexport const pushDictionaries = async (\n req: Request<any, any, PushDictionariesBody>,\n res: ResponseWithInformation<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body.dictionaries;\n const dictionariesKeys = dictionaryData.map((dictionary) => dictionary.key);\n\n if (\n typeof dictionaryData === 'object' &&\n Array.isArray(dictionaryData) &&\n dictionaryData.length === 0\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARIES_NOT_PROVIDED');\n return;\n } else if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const { existingDictionariesKey, newDictionariesKey } =\n await dictionaryService.getExistingDictionaryKey(\n dictionariesKeys,\n project._id\n );\n\n const existingDictionaries = dictionaryData.filter((dictionary) =>\n existingDictionariesKey.includes(dictionary.key)\n );\n const newDictionaries = dictionaryData.filter((dictionary) =>\n newDictionariesKey.includes(dictionary.key)\n );\n\n const result: PushDictionariesResultData = {\n newDictionaries: [],\n updatedDictionaries: [],\n error: [],\n };\n\n for (const dictionaryDataEl of newDictionaries) {\n const publishedVersion = dictionaryDataEl.publishedVersion\n ? dictionaryDataEl.publishedVersion === '-1'\n ? null\n : dictionaryDataEl.publishedVersion\n : null;\n\n const dictionary: DictionaryData = {\n title: dictionaryDataEl.title,\n description: dictionaryDataEl.description,\n projectIds: [String(project._id)],\n creatorId: user._id,\n content: {\n v1: {\n content: dictionaryDataEl.content,\n },\n },\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n publishedVersion,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n result.newDictionaries.push(newDictionary.key);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n\n if (existingDictionariesKey.length >= 0) {\n const existingDictionariesDB =\n await dictionaryService.getDictionariesByKeys(\n existingDictionariesKey,\n project._id\n );\n\n for (const dictionaryDataEl of existingDictionaries) {\n const existingDictionaryDB = existingDictionariesDB.find(\n (dictionaryDB) => dictionaryDB.key === dictionaryDataEl.key\n )!;\n\n const existingContentArray = Object.values(\n existingDictionaryDB.content\n );\n\n const lastContent =\n existingContentArray[existingContentArray.length - 1].content;\n\n const isSameContent =\n JSON.stringify(lastContent) ===\n JSON.stringify(dictionaryDataEl.content);\n\n let newContent: VersionedContent = existingDictionaryDB.content;\n\n if (!isSameContent) {\n const newContentVersion =\n dictionaryService.incrementVersion(existingDictionaryDB);\n\n newContent = {\n ...newContent,\n [newContentVersion]: {\n content: dictionaryDataEl.content,\n },\n };\n }\n\n const publishedVersion = dictionaryDataEl.publishedVersion\n ? dictionaryDataEl.publishedVersion === '-1'\n ? null\n : dictionaryDataEl.publishedVersion\n : null;\n\n const dictionary: DictionaryData = {\n ...existingDictionaryDB,\n ...dictionaryDataEl,\n content: newContent,\n projectIds: [String(project._id)],\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n publishedVersion,\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary = await dictionaryService.updateDictionaryByKey(\n dictionaryDataEl.key,\n dictionary,\n project._id\n );\n result.updatedDictionaries.push(newDictionary.key);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n }\n\n const responseData = formatResponse<PushDictionariesResultData>({\n message: t({\n en: 'Dictionaries updated successfully',\n fr: 'Dictionnaires mis à jour avec succès',\n es: 'Diccionarios actualizados con éxito',\n }),\n description: t({\n en: 'Your dictionaries have been updated successfully',\n fr: 'Vos dictionnaires ont été mis à jour avec succès',\n es: 'Sus diccionarios han sido actualizados con éxito',\n }),\n data: result,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateDictionaryParam = { dictionaryId: string };\nexport type UpdateDictionaryBody = Partial<Dictionary>;\nexport type UpdateDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Updates an existing dictionary in the database.\n */\nexport const updateDictionary = async (\n req: Request<UpdateDictionaryParam, any, UpdateDictionaryBody>,\n res: ResponseWithInformation<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, dictionaryRights } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (typeof dictionaryId === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary updated successfully',\n fr: 'Dictionnaire mis à jour avec succès',\n es: 'Diccionario actualizado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been updated successfully',\n fr: 'Votre dictionnaire a été mis à jour avec succès',\n es: 'Su diccionario ha sido actualizado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteDictionaryParam = { dictionaryId: string };\nexport type DeleteDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Deletes a dictionary from the database by its ID.\n */\nexport const deleteDictionary = async (\n req: Request<DeleteDictionaryParam>,\n res: ResponseWithInformation<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, dictionaryRights } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n if (!dictionaryToDelete.projectIds.includes(project._id)) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const deletedDictionary =\n await dictionaryService.deleteDictionaryById(dictionaryId);\n\n if (!deletedDictionary) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_NOT_FOUND', {\n dictionaryId,\n });\n return;\n }\n\n logger.info(`Dictionary deleted: ${String(deletedDictionary._id)}`);\n\n const apiResult = mapDictionaryToAPI(deletedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary deleted successfully',\n fr: 'Dictionnaire supprimé avec succès',\n es: 'Diccionario eliminado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been deleted successfully',\n fr: 'Votre dictionnaire a été supprimé avec succès',\n es: 'Su diccionario ha sido eliminado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type Dictionary as LocalDictionary } from '@intlayer/core';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as dictionaryService from '@services/dictionary.service';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport {\n type DictionaryFiltersParams,\n getDictionaryFiltersAndPagination,\n} from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { mapDictionaryToAPI } from '@utils/mapper/dictionary';\nimport {\n formatPaginatedResponse,\n type ResponseData,\n type PaginatedResponse,\n formatResponse,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport * as eventListener from '@/controllers/event-listener';\nimport type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\n\nexport type GetDictionariesParams =\n FiltersAndPagination<DictionaryFiltersParams>;\nexport type GetDictionariesResult = PaginatedResponse<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaries = async (\n req: Request<GetDictionariesParams>,\n res: ResponseWithInformation<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, dictionaryRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries(\n filters,\n skip,\n pageSize\n );\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) =>\n mapDictionaryToAPI(el, project._id, el.publishedVersion ?? undefined)\n );\n\n const responseData = formatPaginatedResponse<DictionaryAPI>({\n data: dictionariesAPI,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetDictionariesKeysResult = ResponseData<string[]>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesKeys = async (\n _req: Request,\n res: ResponseWithInformation<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, dictionaryRights } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionariesKeys = await dictionaryService.getDictionariesKeys(\n project._id\n );\n\n const responseData = formatResponse<string[]>({\n data: dictionariesKeys,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetDictionaryParams = { dictionaryKey: string };\nexport type GetDictionaryQuery = { version?: string };\nexport type GetDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaryByKey = async (\n req: Request<GetDictionaryParams, any, any, GetDictionaryQuery>,\n res: ResponseWithInformation<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const { dictionaryKey } = req.params;\n const version = req.query.version;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project._id\n );\n\n if (!dictionary.projectIds.map(String).includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const apiResult = mapDictionaryToAPI(dictionary, project._id, version);\n\n const responseData = formatResponse<DictionaryAPI>({\n data: apiResult,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddDictionaryBody = DictionaryCreationData;\nexport type AddDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Adds a new dictionary to the database.\n */\nexport const addDictionary = async (\n req: Request<any, any, AddDictionaryBody>,\n res: ResponseWithInformation<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n const dictionary: DictionaryData = {\n key: dictionaryData.key,\n title: dictionaryData.title,\n description: dictionaryData.description,\n content: {\n v1: {\n content: dictionaryData.content,\n },\n },\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryData.filePath ?? '',\n },\n projectIds: dictionaryData.projectIds ?? [String(project._id)],\n };\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary created successfully',\n fr: 'Dictionnaire créé avec succès',\n es: 'Diccionario creado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been created successfully',\n fr: 'Votre dictionnaire a été créé avec succès',\n es: 'Su diccionario ha sido creado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: mapDictionaryToAPI(newDictionary, project._id),\n status: 'ADDED',\n },\n ]);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type PushDictionariesBody = {\n dictionaries: LocalDictionary[];\n};\ntype PushDictionariesResultData = {\n newDictionaries: string[];\n updatedDictionaries: string[];\n error: { dictionaryId: string; message: string }[];\n};\nexport type PushDictionariesResult = ResponseData<PushDictionariesResultData>;\n\n/**\n * Check each dictionaries, add the new ones and update the existing ones.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response containing the created dictionary.\n */\nexport const pushDictionaries = async (\n req: Request<any, any, PushDictionariesBody>,\n res: ResponseWithInformation<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body.dictionaries;\n const dictionariesKeys = dictionaryData.map((dictionary) => dictionary.key);\n\n if (\n typeof dictionaryData === 'object' &&\n Array.isArray(dictionaryData) &&\n dictionaryData.length === 0\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARIES_NOT_PROVIDED');\n return;\n } else if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const { existingDictionariesKey, newDictionariesKey } =\n await dictionaryService.getExistingDictionaryKey(\n dictionariesKeys,\n project._id\n );\n\n const existingDictionaries = dictionaryData.filter((dictionary) =>\n existingDictionariesKey.includes(dictionary.key)\n );\n const newDictionaries = dictionaryData.filter((dictionary) =>\n newDictionariesKey.includes(dictionary.key)\n );\n\n const newDictionariesResult: DictionaryAPI[] = [];\n const updatedDictionariesResult: DictionaryAPI[] = [];\n const errorResult: PushDictionariesResultData['error'] = [];\n\n for (const dictionaryDataEl of newDictionaries) {\n const publishedVersion = dictionaryDataEl.publishedVersion\n ? dictionaryDataEl.publishedVersion === '-1'\n ? null\n : dictionaryDataEl.publishedVersion\n : null;\n\n const dictionary: DictionaryData = {\n title: dictionaryDataEl.title,\n description: dictionaryDataEl.description,\n projectIds: [String(project._id)],\n creatorId: user._id,\n content: {\n v1: {\n content: dictionaryDataEl.content,\n },\n },\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n publishedVersion,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(\n mapDictionaryToAPI(newDictionary, project._id)\n );\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n\n if (existingDictionariesKey.length >= 0) {\n const existingDictionariesDB =\n await dictionaryService.getDictionariesByKeys(\n existingDictionariesKey,\n project._id\n );\n\n for (const dictionaryDataEl of existingDictionaries) {\n const existingDictionaryDB = existingDictionariesDB.find(\n (dictionaryDB) => dictionaryDB.key === dictionaryDataEl.key\n )!;\n\n const existingContentArray = Object.values(\n existingDictionaryDB.content\n );\n\n const lastContent =\n existingContentArray[existingContentArray.length - 1].content;\n\n const isSameContent =\n JSON.stringify(lastContent) ===\n JSON.stringify(dictionaryDataEl.content);\n\n let newContent: VersionedContent = existingDictionaryDB.content;\n\n if (!isSameContent) {\n const newContentVersion =\n dictionaryService.incrementVersion(existingDictionaryDB);\n\n newContent = {\n ...newContent,\n [newContentVersion]: {\n content: dictionaryDataEl.content,\n },\n };\n }\n\n const publishedVersion = dictionaryDataEl.publishedVersion\n ? dictionaryDataEl.publishedVersion === '-1'\n ? null\n : dictionaryDataEl.publishedVersion\n : null;\n\n const dictionary: DictionaryData = {\n ...existingDictionaryDB,\n ...dictionaryDataEl,\n content: newContent,\n projectIds: [String(project._id)],\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n publishedVersion,\n key: dictionaryDataEl.key,\n };\n\n try {\n const updatedDictionary =\n await dictionaryService.updateDictionaryByKey(\n dictionaryDataEl.key,\n dictionary,\n project._id\n );\n updatedDictionariesResult.push(\n mapDictionaryToAPI(updatedDictionary, project._id)\n );\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n }\n\n const result: PushDictionariesResultData = {\n newDictionaries: newDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n updatedDictionaries: updatedDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n error: errorResult,\n };\n\n const responseData = formatResponse<PushDictionariesResultData>({\n message: t({\n en: 'Dictionaries updated successfully',\n fr: 'Dictionnaires mis à jour avec succès',\n es: 'Diccionarios actualizados con éxito',\n }),\n description: t({\n en: 'Your dictionaries have been updated successfully',\n fr: 'Vos dictionnaires ont été mis à jour avec succès',\n es: 'Sus diccionarios han sido actualizados con éxito',\n }),\n data: result,\n });\n\n eventListener.sendDictionaryUpdate([\n ...newDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'ADDED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\n ...updatedDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'UPDATED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\n ]);\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateDictionaryParam = { dictionaryId: string };\nexport type UpdateDictionaryBody = Partial<Dictionary>;\nexport type UpdateDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Updates an existing dictionary in the database.\n */\nexport const updateDictionary = async (\n req: Request<UpdateDictionaryParam, any, UpdateDictionaryBody>,\n res: ResponseWithInformation<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, dictionaryRights } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (typeof dictionaryId === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary updated successfully',\n fr: 'Dictionnaire mis à jour avec succès',\n es: 'Diccionario actualizado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been updated successfully',\n fr: 'Votre dictionnaire a été mis à jour avec succès',\n es: 'Su diccionario ha sido actualizado con éxito',\n }),\n data: apiResult,\n });\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'UPDATED',\n },\n ]);\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteDictionaryParam = { dictionaryId: string };\nexport type DeleteDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Deletes a dictionary from the database by its ID.\n */\nexport const deleteDictionary = async (\n req: Request<DeleteDictionaryParam>,\n res: ResponseWithInformation<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, dictionaryRights } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n if (!dictionaryToDelete.projectIds.includes(project._id)) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const deletedDictionary =\n await dictionaryService.deleteDictionaryById(dictionaryId);\n\n if (!deletedDictionary) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_NOT_FOUND', {\n dictionaryId,\n });\n return;\n }\n\n logger.info(`Dictionary deleted: ${String(deletedDictionary._id)}`);\n\n const apiResult = mapDictionaryToAPI(deletedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary deleted successfully',\n fr: 'Dictionnaire supprimé avec succès',\n es: 'Diccionario eliminado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been deleted successfully',\n fr: 'Votre dictionnaire a été supprimé avec succès',\n es: 'Su diccionario ha sido eliminado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'DELETED',\n },\n ]);\n\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var event_listener_exports = {};
|
|
30
|
+
__export(event_listener_exports, {
|
|
31
|
+
listenChangeSSE: () => listenChangeSSE,
|
|
32
|
+
sendDictionaryUpdate: () => sendDictionaryUpdate
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(event_listener_exports);
|
|
35
|
+
var oAuth2Service = __toESM(require('./../services/oAuth2.service.cjs'), 1);
|
|
36
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
37
|
+
let clients = [];
|
|
38
|
+
const sendDictionaryUpdate = (args) => {
|
|
39
|
+
const projectIds = args.flatMap((arg) => arg.dictionary.projectIds);
|
|
40
|
+
const filteredClients = clients.filter(
|
|
41
|
+
(client) => projectIds.map((id) => String(id)).includes(String(client.projectId))
|
|
42
|
+
);
|
|
43
|
+
for (const client of filteredClients) {
|
|
44
|
+
client.res.write(`data: ${JSON.stringify(args)}
|
|
45
|
+
|
|
46
|
+
`);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const listenChangeSSE = async (req, res) => {
|
|
50
|
+
const { accessToken } = req.params;
|
|
51
|
+
if (!accessToken) {
|
|
52
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_AUTHENTICATED");
|
|
53
|
+
}
|
|
54
|
+
const tokenInformation = await oAuth2Service.getAccessToken(accessToken);
|
|
55
|
+
if (!tokenInformation) {
|
|
56
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "AUTH_ERROR");
|
|
57
|
+
}
|
|
58
|
+
res.setHeader("Content-Type", "text/event-stream;charset=utf-8");
|
|
59
|
+
res.setHeader("Cache-Control", "no-cache, no-transform");
|
|
60
|
+
res.setHeader("Connection", "keep-alive");
|
|
61
|
+
res.setHeader("X-Accel-Buffering", "no");
|
|
62
|
+
res.write(":\n\n");
|
|
63
|
+
res.flushHeaders();
|
|
64
|
+
const clientId = Date.now();
|
|
65
|
+
const newClient = {
|
|
66
|
+
id: clientId,
|
|
67
|
+
projectId: String(tokenInformation.project._id),
|
|
68
|
+
res
|
|
69
|
+
};
|
|
70
|
+
clients.push(newClient);
|
|
71
|
+
req.on("close", () => {
|
|
72
|
+
clients = clients.filter((client) => client.id !== clientId);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
76
|
+
0 && (module.exports = {
|
|
77
|
+
listenChangeSSE,
|
|
78
|
+
sendDictionaryUpdate
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=event-listener.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/event-listener.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { Token } from '@schemas/oAuth2.schema';\nimport * as oAuth2Service from '@services/oAuth2.service';\nimport { ErrorHandler } from '@utils/errors';\nimport { Response, Request } from 'express';\nimport { DictionaryAPI } from '@/types/dictionary.types';\n\nlet clients: Array<{ id: number; projectId: string; res: Response }> = [];\n\nexport type SendDictionaryUpdateArg = {\n dictionary: DictionaryAPI;\n status: 'ADDED' | 'UPDATED' | 'DELETED' | 'CREATED';\n};\n\nexport const sendDictionaryUpdate = (args: SendDictionaryUpdateArg[]) => {\n const projectIds = args.flatMap((arg) => arg.dictionary.projectIds);\n\n const filteredClients = clients.filter((client) =>\n projectIds.map((id) => String(id)).includes(String(client.projectId))\n );\n\n for (const client of filteredClients) {\n client.res.write(`data: ${JSON.stringify(args)}\\n\\n`);\n }\n};\n\nexport type CheckDictionaryChangeSSEParams = { accessToken: string };\n\n/**\n * SSE to check the email verification status\n */\nexport const listenChangeSSE = async (\n req: Request<CheckDictionaryChangeSSEParams, any, any>,\n res: ResponseWithInformation\n) => {\n const { accessToken } = req.params;\n\n if (!accessToken) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_AUTHENTICATED');\n }\n\n const tokenInformation = await oAuth2Service.getAccessToken(accessToken);\n\n if (!tokenInformation) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUTH_ERROR');\n }\n\n // Set headers for SSE\n res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no'); // For Nginx buffering\n\n // Send initial data to ensure the connection is open\n res.write(':\\n\\n'); // Comment to keep connection alive\n res.flushHeaders();\n\n const clientId = Date.now();\n\n // Add client to the list\n const newClient = {\n id: clientId,\n projectId: String((tokenInformation as unknown as Token).project._id),\n res,\n };\n clients.push(newClient);\n\n // Remove client on connection close\n req.on('close', () => {\n clients = clients.filter((client) => client.id !== clientId);\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAA+B;AAC/B,oBAA6B;AAI7B,IAAI,UAAmE,CAAC;AAOjE,MAAM,uBAAuB,CAAC,SAAoC;AACvE,QAAM,aAAa,KAAK,QAAQ,CAAC,QAAQ,IAAI,WAAW,UAAU;AAElE,QAAM,kBAAkB,QAAQ;AAAA,IAAO,CAAC,WACtC,WAAW,IAAI,CAAC,OAAO,OAAO,EAAE,CAAC,EAAE,SAAS,OAAO,OAAO,SAAS,CAAC;AAAA,EACtE;AAEA,aAAW,UAAU,iBAAiB;AACpC,WAAO,IAAI,MAAM,SAAS,KAAK,UAAU,IAAI,CAAC;AAAA;AAAA,CAAM;AAAA,EACtD;AACF;AAOO,MAAM,kBAAkB,OAC7B,KACA,QACG;AACH,QAAM,EAAE,YAAY,IAAI,IAAI;AAE5B,MAAI,CAAC,aAAa;AAChB,+BAAa,2BAA2B,KAAK,wBAAwB;AAAA,EACvE;AAEA,QAAM,mBAAmB,MAAM,cAAc,eAAe,WAAW;AAEvE,MAAI,CAAC,kBAAkB;AACrB,+BAAa,2BAA2B,KAAK,YAAY;AAAA,EAC3D;AAGA,MAAI,UAAU,gBAAgB,iCAAiC;AAC/D,MAAI,UAAU,iBAAiB,wBAAwB;AACvD,MAAI,UAAU,cAAc,YAAY;AACxC,MAAI,UAAU,qBAAqB,IAAI;AAGvC,MAAI,MAAM,OAAO;AACjB,MAAI,aAAa;AAEjB,QAAM,WAAW,KAAK,IAAI;AAG1B,QAAM,YAAY;AAAA,IAChB,IAAI;AAAA,IACJ,WAAW,OAAQ,iBAAsC,QAAQ,GAAG;AAAA,IACpE;AAAA,EACF;AACA,UAAQ,KAAK,SAAS;AAGtB,MAAI,GAAG,SAAS,MAAM;AACpB,cAAU,QAAQ,OAAO,CAAC,WAAW,OAAO,OAAO,QAAQ;AAAA,EAC7D,CAAC;AACH;","names":[]}
|
|
@@ -21,7 +21,7 @@ __export(oAuth2_controller_exports, {
|
|
|
21
21
|
getOAuth2Token: () => getOAuth2Token
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(oAuth2_controller_exports);
|
|
24
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
24
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
25
25
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
26
26
|
var import_oauth2_server = require("oauth2-server");
|
|
27
27
|
const getOAuth2Token = async (req, res, _next) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/oAuth2.controller.ts"],"sourcesContent":["import { RequestWithOAuth2Information } from '@middlewares/oAuth2.middleware';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, ResponseData } from '@utils/responseData';\nimport { Response, Request, NextFunction } from 'express';\nimport {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/oAuth2.controller.ts"],"sourcesContent":["import { RequestWithOAuth2Information } from '@middlewares/oAuth2.middleware';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, ResponseData } from '@utils/responseData';\nimport { Response, Request, NextFunction } from 'express';\nimport {\n Request as OAuthRequest,\n Response as OAuthResponse,\n} from 'oauth2-server';\nimport { OAuth2Token } from '@/types/oAuth2.types';\n\nexport type GetOAuth2TokenBody = {\n grant_type: 'client_credentials';\n client_id: string;\n client_secret: string;\n};\nexport type GetOAuth2TokenResult = ResponseData<OAuth2Token>;\n\n// Method to get the token\nexport const getOAuth2Token = async (\n req: Request,\n res: Response<GetOAuth2TokenResult>,\n _next: NextFunction\n): Promise<void> => {\n const oauthRequest = new OAuthRequest(req);\n const oauthResponse = new OAuthResponse(res);\n\n try {\n const token: OAuth2Token = (await (\n req as unknown as RequestWithOAuth2Information<\n undefined,\n undefined,\n GetOAuth2TokenBody\n >\n ).oauth.token(oauthRequest, oauthResponse)) as OAuth2Token;\n\n const responseData = formatResponse<OAuth2Token>({\n data: token,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,oBAAuC;AACvC,0BAA6C;AAE7C,2BAGO;AAWA,MAAM,iBAAiB,OAC5B,KACA,KACA,UACkB;AAClB,QAAM,eAAe,IAAI,qBAAAA,QAAa,GAAG;AACzC,QAAM,gBAAgB,IAAI,qBAAAC,SAAc,GAAG;AAE3C,MAAI;AACF,UAAM,QAAsB,MAC1B,IAKA,MAAM,MAAM,cAAc,aAAa;AAEzC,UAAM,mBAAe,oCAA4B;AAAA,MAC/C,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;","names":["OAuthRequest","OAuthResponse"]}
|
|
@@ -44,7 +44,7 @@ var import_sessionAuth = require('./../routes/sessionAuth.routes.cjs');
|
|
|
44
44
|
var import_email = require('./../services/email.service.cjs');
|
|
45
45
|
var sessionAuthService = __toESM(require('./../services/sessionAuth.service.cjs'), 1);
|
|
46
46
|
var userService = __toESM(require('./../services/user.service.cjs'), 1);
|
|
47
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
47
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
48
48
|
var import_getOrganizationFiltersAndPagination = require('./../utils/filtersAndPagination/getOrganizationFiltersAndPagination.cjs');
|
|
49
49
|
var import_plan = require('./../utils/plan.cjs');
|
|
50
50
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
@@ -42,7 +42,7 @@ var import_logger = require('./../logger/index.cjs');
|
|
|
42
42
|
var projectService = __toESM(require('./../services/project.service.cjs'), 1);
|
|
43
43
|
var sessionAuthService = __toESM(require('./../services/sessionAuth.service.cjs'), 1);
|
|
44
44
|
var userService = __toESM(require('./../services/user.service.cjs'), 1);
|
|
45
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
45
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
46
46
|
var import_getProjectFiltersAndPagination = require('./../utils/filtersAndPagination/getProjectFiltersAndPagination.cjs');
|
|
47
47
|
var import_project = require('./../utils/mapper/project.cjs');
|
|
48
48
|
var import_plan = require('./../utils/plan.cjs');
|
|
@@ -34,7 +34,7 @@ __export(projectAccessKey_controller_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(projectAccessKey_controller_exports);
|
|
36
36
|
var projectAccessKeyService = __toESM(require('./../services/projectAccessKey.service.cjs'), 1);
|
|
37
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
37
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
38
38
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
39
39
|
var import_express_intlayer = require("express-intlayer");
|
|
40
40
|
const addNewAccessKey = async (req, res, _next) => {
|
|
@@ -53,7 +53,7 @@ var import_email = require('./../services/email.service.cjs');
|
|
|
53
53
|
var sessionAuthService = __toESM(require('./../services/sessionAuth.service.cjs'), 1);
|
|
54
54
|
var userService = __toESM(require('./../services/user.service.cjs'), 1);
|
|
55
55
|
var import_CSRF = require('./../utils/CSRF.cjs');
|
|
56
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
56
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
57
57
|
var import_httpStatusCodes = require('./../utils/httpStatusCodes.cjs');
|
|
58
58
|
var import_organization = require('./../utils/mapper/organization.cjs');
|
|
59
59
|
var import_project = require('./../utils/mapper/project.cjs');
|
|
@@ -33,14 +33,14 @@ __export(stripe_controller_exports, {
|
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(stripe_controller_exports);
|
|
35
35
|
var subscriptionService = __toESM(require('./../services/subscription.service.cjs'), 1);
|
|
36
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
36
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
37
37
|
var import_plan = require('./../utils/plan.cjs');
|
|
38
38
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
39
39
|
var import_express_intlayer = require("express-intlayer");
|
|
40
40
|
var import_stripe = require("stripe");
|
|
41
|
-
const stripe = new import_stripe.Stripe(process.env.STRIPE_SECRET_KEY);
|
|
42
41
|
const getSubscription = async (req, res) => {
|
|
43
42
|
try {
|
|
43
|
+
const stripe = new import_stripe.Stripe(process.env.STRIPE_SECRET_KEY);
|
|
44
44
|
const { organization, user } = res.locals;
|
|
45
45
|
const { priceId } = req.body;
|
|
46
46
|
if (!organization) {
|
|
@@ -127,6 +127,7 @@ const getSubscription = async (req, res) => {
|
|
|
127
127
|
}
|
|
128
128
|
};
|
|
129
129
|
const cancelSubscription = async (_req, res) => {
|
|
130
|
+
const stripe = new import_stripe.Stripe(process.env.STRIPE_SECRET_KEY);
|
|
130
131
|
try {
|
|
131
132
|
const { organization, user } = res.locals;
|
|
132
133
|
if (!organization) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/stripe.controller.ts"],"sourcesContent":["import { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as subscriptionService from '@services/subscription.service';\nimport { ErrorHandler, AppError } from '@utils/errors';\nimport { retrievePlanInformation } from '@utils/plan';\nimport { formatResponse, ResponseData } from '@utils/responseData';\nimport { Request } from 'express';\nimport { t } from 'express-intlayer';\nimport { Locales } from 'intlayer';\nimport { Stripe } from 'stripe';\nimport type { Organization } from '@/types/organization.types';\n\nconst stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\nexport type GetCheckoutSessionBody = {\n organizationId: string;\n priceId: string;\n};\n\ntype CheckoutSessionData = {\n subscriptionId: string;\n clientSecret: string;\n status: Stripe.Subscription.Status;\n};\n\nexport type GetCheckoutSessionResult = ResponseData<CheckoutSessionData>;\n\n/**\n * Handles subscription creation or update with Stripe and returns a ClientSecret.\n * @param req - Express request object.\n * @param res - Express response object.\n */\nexport const getSubscription = async (\n req: Request<undefined, undefined, GetCheckoutSessionBody>,\n res: ResponseWithInformation<GetCheckoutSessionResult>\n): Promise<void> => {\n try {\n // Extract organization and user from response locals (set by authentication middleware)\n const { organization, user } = res.locals;\n // Get the price ID (Stripe Price ID) from the request body\n const { priceId } = req.body;\n\n // Validate that the organization exists\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n // Validate that the user exists\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n // Ensure the user is a member of the organization\n if (!organization.membersIds.map(String).includes(String(user._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_NOT_ORGANIZATION_MEMBER'\n );\n return;\n }\n\n // Ensure the user is an admin of the organization\n if (!organization.adminsIds.map(String).includes(String(user._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_NOT_ORGANIZATION_ADMIN'\n );\n return;\n }\n\n const { period, type } = retrievePlanInformation(priceId);\n\n if (\n organization.plan?.subscriptionId ||\n (organization.plan?.type === type && organization.plan?.period === period)\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'ALREADY_SUBSCRIBED', {\n organizationId: organization._id,\n });\n return;\n }\n\n // Attempt to retrieve the Stripe customer ID from the organization's plan\n let customerId = organization.plan?.customerId;\n\n if (!customerId) {\n // If no customer ID exists, create a new Stripe customer for the organization\n const customer = await stripe.customers.create({\n metadata: {\n organizationId: String(organization._id),\n userId: String(user._id),\n // Include the locale for potential localization\n locale: (res.locals as unknown as { locale: Locales }).locale,\n },\n });\n customerId = customer.id;\n }\n\n // If no subscription exists, create a new one\n const subscription = await stripe.subscriptions.create({\n customer: customerId, // Associate the subscription with the customer\n items: [{ price: priceId }], // Set the price ID for the subscription\n expand: ['latest_invoice.payment_intent'], // Expand to get payment intent details\n payment_settings: {\n payment_method_types: ['card'], // Specify payment method types\n },\n payment_behavior: 'default_incomplete', // Create the subscription in an incomplete state until payment is confirmed\n });\n\n // Handle subscription creation failure\n if (!subscription) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'SUBSCRIPTION_CREATION_FAILED',\n {\n user,\n organization,\n priceId,\n }\n );\n return;\n }\n\n // Prepare the response data with subscription details\n const responseData = formatResponse<CheckoutSessionData>({\n data: {\n subscriptionId: subscription.id,\n // Retrieve the client secret from the payment intent to complete payment on the client side\n clientSecret:\n (\n (subscription.latest_invoice as Stripe.Invoice)\n .payment_intent as Stripe.PaymentIntent\n )?.client_secret ?? '',\n status: subscription.status, // Subscription status (e.g., 'incomplete', 'active')\n },\n });\n\n // Send the response back to the client\n res.json(responseData);\n\n return;\n } catch (error) {\n // Handle any errors that occur during the process\n\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype CancelSubscriptionData = Organization['plan'];\n\ntype CancelSubscriptionResult = ResponseData<CancelSubscriptionData>;\n\n/**\n * Cancels a subscription for an organization.\n * @param _req - Express request object.\n * @param res - Express response object.\n */\nexport const cancelSubscription = async (\n _req: Request,\n res: ResponseWithInformation<CancelSubscriptionResult>\n): Promise<void> => {\n try {\n // Extract the organization and user from the response locals\n // These are typically set by authentication middleware earlier in the request pipeline\n const { organization, user } = res.locals;\n\n // Validate that the organization exists\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n // Validate that the user exists\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n // Check if the user is an admin of the organization\n if (!organization.adminsIds.map(String).includes(String(user._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_NOT_ORGANIZATION_ADMIN'\n );\n return;\n }\n\n // Check if the organization has an active subscription to cancel\n if (!organization.plan?.subscriptionId) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_PLAN_NOT_FOUND'\n );\n return;\n }\n\n // Cancel the subscription on Stripe immediately using the subscription ID\n await stripe.subscriptions.cancel(organization.plan.subscriptionId);\n\n // Update the organization's plan in the database to reflect the cancellation\n const plan = await subscriptionService.cancelSubscription(\n organization.plan.subscriptionId,\n String(organization._id)\n );\n\n // If the plan could not be updated in the database, handle the error\n if (!plan) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_PLAN_NOT_FOUND'\n );\n return;\n }\n\n // Prepare a formatted response with a success message and the updated plan data\n const formattedPlan = formatResponse<CancelSubscriptionData>({\n message: t({\n en: 'Subscription cancelled successfully',\n fr: 'Souscription annulée avec succès',\n es: 'Suscripción cancelada con éxito',\n }),\n description: t({\n en: 'Your subscription has been cancelled successfully',\n fr: 'Votre souscription a été annulée avec succès',\n es: 'Su suscripción ha sido cancelada con éxito',\n }),\n data: plan!,\n });\n\n // Send the response back to the client\n res.json(formattedPlan);\n } catch (error) {\n // Handle any errors that occur during the cancellation process\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAqC;AACrC,oBAAuC;AACvC,kBAAwC;AACxC,0BAA6C;AAE7C,8BAAkB;AAElB,oBAAuB;AAGvB,MAAM,SAAS,IAAI,qBAAO,QAAQ,IAAI,iBAAkB;AAoBjD,MAAM,kBAAkB,OAC7B,KACA,QACkB;AAClB,MAAI;AAEF,UAAM,EAAE,cAAc,KAAK,IAAI,IAAI;AAEnC,UAAM,EAAE,QAAQ,IAAI,IAAI;AAGxB,QAAI,CAAC,cAAc;AACjB,iCAAa,2BAA2B,KAAK,wBAAwB;AACrE;AAAA,IACF;AAGA,QAAI,CAAC,MAAM;AACT,iCAAa,2BAA2B,KAAK,gBAAgB;AAC7D;AAAA,IACF;AAGA,QAAI,CAAC,aAAa,WAAW,IAAI,MAAM,EAAE,SAAS,OAAO,KAAK,GAAG,CAAC,GAAG;AACnE,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,CAAC,aAAa,UAAU,IAAI,MAAM,EAAE,SAAS,OAAO,KAAK,GAAG,CAAC,GAAG;AAClE,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,EAAE,QAAQ,KAAK,QAAI,qCAAwB,OAAO;AAExD,QACE,aAAa,MAAM,kBAClB,aAAa,MAAM,SAAS,QAAQ,aAAa,MAAM,WAAW,QACnE;AACA,iCAAa,2BAA2B,KAAK,sBAAsB;AAAA,QACjE,gBAAgB,aAAa;AAAA,MAC/B,CAAC;AACD;AAAA,IACF;AAGA,QAAI,aAAa,aAAa,MAAM;AAEpC,QAAI,CAAC,YAAY;AAEf,YAAM,WAAW,MAAM,OAAO,UAAU,OAAO;AAAA,QAC7C,UAAU;AAAA,UACR,gBAAgB,OAAO,aAAa,GAAG;AAAA,UACvC,QAAQ,OAAO,KAAK,GAAG;AAAA;AAAA,UAEvB,QAAS,IAAI,OAA0C;AAAA,QACzD;AAAA,MACF,CAAC;AACD,mBAAa,SAAS;AAAA,IACxB;AAGA,UAAM,eAAe,MAAM,OAAO,cAAc,OAAO;AAAA,MACrD,UAAU;AAAA;AAAA,MACV,OAAO,CAAC,EAAE,OAAO,QAAQ,CAAC;AAAA;AAAA,MAC1B,QAAQ,CAAC,+BAA+B;AAAA;AAAA,MACxC,kBAAkB;AAAA,QAChB,sBAAsB,CAAC,MAAM;AAAA;AAAA,MAC/B;AAAA,MACA,kBAAkB;AAAA;AAAA,IACpB,CAAC;AAGD,QAAI,CAAC,cAAc;AACjB,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAGA,UAAM,mBAAe,oCAAoC;AAAA,MACvD,MAAM;AAAA,QACJ,gBAAgB,aAAa;AAAA;AAAA,QAE7B,cAEK,aAAa,eACX,gBACF,iBAAiB;AAAA,QACtB,QAAQ,aAAa;AAAA;AAAA,MACvB;AAAA,IACF,CAAC;AAGD,QAAI,KAAK,YAAY;AAErB;AAAA,EACF,SAAS,OAAO;AAGd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAWO,MAAM,qBAAqB,OAChC,MACA,QACkB;AAClB,MAAI;AAGF,UAAM,EAAE,cAAc,KAAK,IAAI,IAAI;AAGnC,QAAI,CAAC,cAAc;AACjB,iCAAa,2BAA2B,KAAK,wBAAwB;AACrE;AAAA,IACF;AAGA,QAAI,CAAC,MAAM;AACT,iCAAa,2BAA2B,KAAK,gBAAgB;AAC7D;AAAA,IACF;AAGA,QAAI,CAAC,aAAa,UAAU,IAAI,MAAM,EAAE,SAAS,OAAO,KAAK,GAAG,CAAC,GAAG;AAClE,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,CAAC,aAAa,MAAM,gBAAgB;AACtC,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAGA,UAAM,OAAO,cAAc,OAAO,aAAa,KAAK,cAAc;AAGlE,UAAM,OAAO,MAAM,oBAAoB;AAAA,MACrC,aAAa,KAAK;AAAA,MAClB,OAAO,aAAa,GAAG;AAAA,IACzB;AAGA,QAAI,CAAC,MAAM;AACT,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAGA,UAAM,oBAAgB,oCAAuC;AAAA,MAC3D,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAGD,QAAI,KAAK,aAAa;AAAA,EACxB,SAAS,OAAO;AAEd,+BAAa,uBAAuB,KAAK,KAAiB;AAAA,EAC5D;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/stripe.controller.ts"],"sourcesContent":["import { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as subscriptionService from '@services/subscription.service';\nimport { ErrorHandler, AppError } from '@utils/errors';\nimport { retrievePlanInformation } from '@utils/plan';\nimport { formatResponse, ResponseData } from '@utils/responseData';\nimport { Request } from 'express';\nimport { t } from 'express-intlayer';\nimport { Locales } from 'intlayer';\nimport { Stripe } from 'stripe';\nimport type { Organization } from '@/types/organization.types';\n\nexport type GetCheckoutSessionBody = {\n organizationId: string;\n priceId: string;\n};\n\ntype CheckoutSessionData = {\n subscriptionId: string;\n clientSecret: string;\n status: Stripe.Subscription.Status;\n};\n\nexport type GetCheckoutSessionResult = ResponseData<CheckoutSessionData>;\n\n/**\n * Handles subscription creation or update with Stripe and returns a ClientSecret.\n * @param req - Express request object.\n * @param res - Express response object.\n */\nexport const getSubscription = async (\n req: Request<undefined, undefined, GetCheckoutSessionBody>,\n res: ResponseWithInformation<GetCheckoutSessionResult>\n): Promise<void> => {\n try {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n // Extract organization and user from response locals (set by authentication middleware)\n const { organization, user } = res.locals;\n // Get the price ID (Stripe Price ID) from the request body\n const { priceId } = req.body;\n\n // Validate that the organization exists\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n // Validate that the user exists\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n // Ensure the user is a member of the organization\n if (!organization.membersIds.map(String).includes(String(user._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_NOT_ORGANIZATION_MEMBER'\n );\n return;\n }\n\n // Ensure the user is an admin of the organization\n if (!organization.adminsIds.map(String).includes(String(user._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_NOT_ORGANIZATION_ADMIN'\n );\n return;\n }\n\n const { period, type } = retrievePlanInformation(priceId);\n\n if (\n organization.plan?.subscriptionId ||\n (organization.plan?.type === type && organization.plan?.period === period)\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'ALREADY_SUBSCRIBED', {\n organizationId: organization._id,\n });\n return;\n }\n\n // Attempt to retrieve the Stripe customer ID from the organization's plan\n let customerId = organization.plan?.customerId;\n\n if (!customerId) {\n // If no customer ID exists, create a new Stripe customer for the organization\n const customer = await stripe.customers.create({\n metadata: {\n organizationId: String(organization._id),\n userId: String(user._id),\n // Include the locale for potential localization\n locale: (res.locals as unknown as { locale: Locales }).locale,\n },\n });\n customerId = customer.id;\n }\n\n // If no subscription exists, create a new one\n const subscription = await stripe.subscriptions.create({\n customer: customerId, // Associate the subscription with the customer\n items: [{ price: priceId }], // Set the price ID for the subscription\n expand: ['latest_invoice.payment_intent'], // Expand to get payment intent details\n payment_settings: {\n payment_method_types: ['card'], // Specify payment method types\n },\n payment_behavior: 'default_incomplete', // Create the subscription in an incomplete state until payment is confirmed\n });\n\n // Handle subscription creation failure\n if (!subscription) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'SUBSCRIPTION_CREATION_FAILED',\n {\n user,\n organization,\n priceId,\n }\n );\n return;\n }\n\n // Prepare the response data with subscription details\n const responseData = formatResponse<CheckoutSessionData>({\n data: {\n subscriptionId: subscription.id,\n // Retrieve the client secret from the payment intent to complete payment on the client side\n clientSecret:\n (\n (subscription.latest_invoice as Stripe.Invoice)\n .payment_intent as Stripe.PaymentIntent\n )?.client_secret ?? '',\n status: subscription.status, // Subscription status (e.g., 'incomplete', 'active')\n },\n });\n\n // Send the response back to the client\n res.json(responseData);\n\n return;\n } catch (error) {\n // Handle any errors that occur during the process\n\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype CancelSubscriptionData = Organization['plan'];\n\ntype CancelSubscriptionResult = ResponseData<CancelSubscriptionData>;\n\n/**\n * Cancels a subscription for an organization.\n * @param _req - Express request object.\n * @param res - Express response object.\n */\nexport const cancelSubscription = async (\n _req: Request,\n res: ResponseWithInformation<CancelSubscriptionResult>\n): Promise<void> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n try {\n // Extract the organization and user from the response locals\n // These are typically set by authentication middleware earlier in the request pipeline\n const { organization, user } = res.locals;\n\n // Validate that the organization exists\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n // Validate that the user exists\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n // Check if the user is an admin of the organization\n if (!organization.adminsIds.map(String).includes(String(user._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_NOT_ORGANIZATION_ADMIN'\n );\n return;\n }\n\n // Check if the organization has an active subscription to cancel\n if (!organization.plan?.subscriptionId) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_PLAN_NOT_FOUND'\n );\n return;\n }\n\n // Cancel the subscription on Stripe immediately using the subscription ID\n await stripe.subscriptions.cancel(organization.plan.subscriptionId);\n\n // Update the organization's plan in the database to reflect the cancellation\n const plan = await subscriptionService.cancelSubscription(\n organization.plan.subscriptionId,\n String(organization._id)\n );\n\n // If the plan could not be updated in the database, handle the error\n if (!plan) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_PLAN_NOT_FOUND'\n );\n return;\n }\n\n // Prepare a formatted response with a success message and the updated plan data\n const formattedPlan = formatResponse<CancelSubscriptionData>({\n message: t({\n en: 'Subscription cancelled successfully',\n fr: 'Souscription annulée avec succès',\n es: 'Suscripción cancelada con éxito',\n }),\n description: t({\n en: 'Your subscription has been cancelled successfully',\n fr: 'Votre souscription a été annulée avec succès',\n es: 'Su suscripción ha sido cancelada con éxito',\n }),\n data: plan!,\n });\n\n // Send the response back to the client\n res.json(formattedPlan);\n } catch (error) {\n // Handle any errors that occur during the cancellation process\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n }\n};\n"],"mappings":"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","names":[]}
|
|
@@ -36,7 +36,7 @@ __export(tag_controller_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(tag_controller_exports);
|
|
37
37
|
var import_logger = require('./../logger/index.cjs');
|
|
38
38
|
var tagService = __toESM(require('./../services/tag.service.cjs'), 1);
|
|
39
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
39
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
40
40
|
var import_getTagFiltersAndPagination = require('./../utils/filtersAndPagination/getTagFiltersAndPagination.cjs');
|
|
41
41
|
var import_tag = require('./../utils/mapper/tag.cjs');
|
|
42
42
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
@@ -41,7 +41,7 @@ var import_logger = require('./../logger/index.cjs');
|
|
|
41
41
|
var import_sessionAuth = require('./../routes/sessionAuth.routes.cjs');
|
|
42
42
|
var import_email = require('./../services/email.service.cjs');
|
|
43
43
|
var userService = __toESM(require('./../services/user.service.cjs'), 1);
|
|
44
|
-
var import_errors = require('./../utils/errors.cjs');
|
|
44
|
+
var import_errors = require('./../utils/errors/index.cjs');
|
|
45
45
|
var import_getOrganizationFiltersAndPagination = require('./../utils/filtersAndPagination/getOrganizationFiltersAndPagination.cjs');
|
|
46
46
|
var import_user = require('./../utils/mapper/user.cjs');
|
|
47
47
|
var import_responseData = require('./../utils/responseData.cjs');
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -49,18 +49,21 @@ var import_sessionAuth2 = require('./routes/sessionAuth.routes.cjs');
|
|
|
49
49
|
var import_user = require('./routes/user.routes.cjs');
|
|
50
50
|
var import_stripe = require('./routes/stripe.routes.cjs');
|
|
51
51
|
var import_ai = require('./routes/ai.routes.cjs');
|
|
52
|
+
var import_event_listener = require('./routes/event-listener.routes.cjs');
|
|
52
53
|
var import_stripe2 = require('./webhooks/stripe.webhook.cjs');
|
|
53
54
|
var import_oAuth22 = require('./controllers/oAuth2.controller.cjs');
|
|
54
55
|
var import_sessionAuth3 = require('./controllers/sessionAuth.controller.cjs');
|
|
55
56
|
var import_CSRF = require('./utils/CSRF.cjs');
|
|
56
57
|
var import_connectDB = require('./utils/mongoDB/connectDB.cjs');
|
|
57
|
-
var import_logger = require('./logger.cjs');
|
|
58
|
+
var import_logger = require('./logger/index.cjs');
|
|
58
59
|
const app = (0, import_express.default)();
|
|
59
60
|
app.disable("x-powered-by");
|
|
60
61
|
app.use((0, import_helmet.default)());
|
|
61
62
|
const env = app.get("env");
|
|
62
63
|
import_logger.logger.info(`run as ${env}`);
|
|
63
|
-
import_dotenv.default.config({
|
|
64
|
+
import_dotenv.default.config({
|
|
65
|
+
path: [`.env.${env}.local`, `.env.${env}`, ".env.local", ".env"]
|
|
66
|
+
});
|
|
64
67
|
app.use((0, import_cookie_parser.default)());
|
|
65
68
|
app.use((0, import_express_intlayer.intlayer)());
|
|
66
69
|
const isDev = env === "development";
|
|
@@ -73,10 +76,8 @@ app.post(
|
|
|
73
76
|
app.use((0, import_compression.default)());
|
|
74
77
|
app.use(import_express.default.json({ limit: "50mb" }));
|
|
75
78
|
app.use(import_express.default.urlencoded({ extended: true }));
|
|
76
|
-
const whitelist = [process.env.CLIENT_URL];
|
|
77
79
|
const corsOptions = {
|
|
78
|
-
origin:
|
|
79
|
-
credentials: true,
|
|
80
|
+
origin: "*",
|
|
80
81
|
allowedHeaders: [
|
|
81
82
|
"authorization",
|
|
82
83
|
"Content-Type",
|
|
@@ -92,7 +93,6 @@ const corsOptions = {
|
|
|
92
93
|
methods: "GET,HEAD,PUT,PATCH,POST,DELETE"
|
|
93
94
|
};
|
|
94
95
|
app.use((0, import_cors.default)(corsOptions));
|
|
95
|
-
import_logger.logger.info("url whitelist : ", whitelist.join(", "));
|
|
96
96
|
app.get("/", (_req, res) => {
|
|
97
97
|
res.send(
|
|
98
98
|
(0, import_express_intlayer.t)({
|
|
@@ -137,6 +137,7 @@ app.use("/api/tag", import_tags.tagRouter);
|
|
|
137
137
|
app.use("/api/dictionary", import_dictionary.dictionaryRouter);
|
|
138
138
|
app.use("/api/stripe", import_stripe.stripeRouter);
|
|
139
139
|
app.use("/api/ai", import_ai.aiRouter);
|
|
140
|
+
app.use("/api/event-listener", import_event_listener.eventListenerRouter);
|
|
140
141
|
app.listen(process.env.PORT, () => {
|
|
141
142
|
import_logger.logger.info(`Listening on port ${process.env.PORT}`);
|
|
142
143
|
});
|