From 177134d2a6a71ab81c6ddef8d7e87679b1ef5bf9 Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Tue, 24 Feb 2026 11:54:43 +0100 Subject: [PATCH] Updates to Express v5 (#7) Updates the Express dependency to version 5.2.1 and its corresponding types. This change also adapts the request validator middleware to extract validated query parameters and store them in `res.locals` instead of modifying `req.query` to align with Express v5's intended usage and prevent potential conflicts. Includes a fix for a server startup error, logging the error and exiting the process, and adds a type definition file for Express locals. --- meet-ce/backend/package.json | 4 +- .../src/controllers/recording.controller.ts | 17 ++-- .../src/controllers/room-member.controller.ts | 4 +- .../src/controllers/room.controller.ts | 12 +-- .../src/controllers/user.controller.ts | 6 +- .../recording-validator.middleware.ts | 32 ++++---- .../room-member-validator.middleware.ts | 4 +- .../room-validator.middleware.ts | 35 ++++---- .../user-validator.middleware.ts | 4 +- meet-ce/backend/src/server.ts | 7 +- meet-ce/backend/src/types/express-locals.d.ts | 9 ++ .../api/recordings/get-recordings.test.ts | 5 -- .../integration/api/rooms/get-rooms.test.ts | 5 -- pnpm-lock.yaml | 82 ++++--------------- 14 files changed, 93 insertions(+), 133 deletions(-) create mode 100644 meet-ce/backend/src/types/express-locals.d.ts diff --git a/meet-ce/backend/package.json b/meet-ce/backend/package.json index dc424657..3cc674f3 100644 --- a/meet-ce/backend/package.json +++ b/meet-ce/backend/package.json @@ -68,7 +68,7 @@ "cors": "2.8.6", "cron": "4.4.0", "dotenv": "16.6.1", - "express": "4.22.1", + "express": "5.2.1", "express-rate-limit": "7.5.1", "inversify": "6.2.2", "ioredis": "5.6.1", @@ -87,7 +87,7 @@ "@types/bcrypt": "5.0.2", "@types/cookie-parser": "1.4.9", "@types/cors": "2.8.19", - "@types/express": "4.17.25", + "@types/express": "5.0.6", "@types/jest": "29.5.14", "@types/lodash.merge": "4.6.9", "@types/ms": "2.1.0", diff --git a/meet-ce/backend/src/controllers/recording.controller.ts b/meet-ce/backend/src/controllers/recording.controller.ts index b506dc43..547ae4ac 100644 --- a/meet-ce/backend/src/controllers/recording.controller.ts +++ b/meet-ce/backend/src/controllers/recording.controller.ts @@ -19,7 +19,7 @@ export const startRecording = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingService = container.get(RecordingService); const { roomId, config } = req.body; - const { fields } = req.query as { fields?: MeetRecordingField[] }; + const { fields } = res.locals.validatedQuery as { fields?: MeetRecordingField[] }; logger.info(`Starting recording in room '${roomId}'`); try { @@ -39,7 +39,7 @@ export const startRecording = async (req: Request, res: Response) => { export const stopRecording = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingId = req.params.recordingId; - const { fields } = req.query as { fields?: MeetRecordingField[] }; + const { fields } = res.locals.validatedQuery as { fields?: MeetRecordingField[] }; try { logger.info(`Stopping recording '${recordingId}'`); @@ -58,7 +58,7 @@ export const stopRecording = async (req: Request, res: Response) => { export const getRecordings = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingService = container.get(RecordingService); - const queryParams = req.query; + const queryParams = res.locals.validatedQuery ?? {}; logger.info('Getting all recordings'); @@ -82,7 +82,7 @@ export const getRecordings = async (req: Request, res: Response) => { export const bulkDeleteRecordings = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingService = container.get(RecordingService); - const { recordingIds } = req.query as { recordingIds: string[] }; + const { recordingIds } = res.locals.validatedQuery as { recordingIds: string[] }; logger.info(`Deleting recordings: ${recordingIds}`); @@ -105,7 +105,7 @@ export const getRecording = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingService = container.get(RecordingService); const recordingId = req.params.recordingId; - const { fields } = req.query as { fields?: MeetRecordingField[] }; + const { fields } = res.locals.validatedQuery as { fields?: MeetRecordingField[] }; logger.info(`Getting recording '${recordingId}'`); @@ -220,13 +220,14 @@ export const getRecordingUrl = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingService = container.get(RecordingService); const recordingId = req.params.recordingId; - const privateAccess = req.query.privateAccess === 'true'; + const { privateAccess } = res.locals.validatedQuery as { privateAccess: string }; + const isPrivateAccess = privateAccess === 'true'; logger.info(`Getting URL for recording '${recordingId}'`); try { const recordingSecrets = await recordingService.getRecordingAccessSecrets(recordingId); - const secret = privateAccess ? recordingSecrets.privateAccessSecret : recordingSecrets.publicAccessSecret; + const secret = isPrivateAccess ? recordingSecrets.privateAccessSecret : recordingSecrets.publicAccessSecret; const recordingUrl = `${getBaseUrl()}/recording/${recordingId}?secret=${secret}`; return res.status(200).json({ url: recordingUrl }); @@ -239,7 +240,7 @@ export const downloadRecordingsZip = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const recordingService = container.get(RecordingService); - const { recordingIds } = req.query as { recordingIds: string[] }; + const { recordingIds } = res.locals.validatedQuery as { recordingIds: string[] }; const validRecordings: MeetRecordingInfo[] = []; logger.info(`Preparing ZIP download for recordings: ${recordingIds}`); diff --git a/meet-ce/backend/src/controllers/room-member.controller.ts b/meet-ce/backend/src/controllers/room-member.controller.ts index 754526e1..0f74e291 100644 --- a/meet-ce/backend/src/controllers/room-member.controller.ts +++ b/meet-ce/backend/src/controllers/room-member.controller.ts @@ -32,7 +32,7 @@ export const getRoomMembers = async (req: Request, res: Response) => { const roomMemberService = container.get(RoomMemberService); const { roomId } = req.params; - const filters = req.query as MeetRoomMemberFilters; + const filters = res.locals.validatedQuery as MeetRoomMemberFilters; try { logger.verbose(`Getting members for room '${roomId}'`); @@ -100,7 +100,7 @@ export const bulkDeleteRoomMembers = async (req: Request, res: Response) => { const roomMemberService = container.get(RoomMemberService); const { roomId } = req.params; - const { memberIds } = req.query as { memberIds: string[] }; + const { memberIds } = res.locals.validatedQuery as { memberIds: string[] }; try { logger.verbose(`Deleting members from room '${roomId}' with IDs: ${memberIds}`); diff --git a/meet-ce/backend/src/controllers/room.controller.ts b/meet-ce/backend/src/controllers/room.controller.ts index 3901fa80..bccc213c 100644 --- a/meet-ce/backend/src/controllers/room.controller.ts +++ b/meet-ce/backend/src/controllers/room.controller.ts @@ -22,7 +22,7 @@ export const createRoom = async (req: Request, res: Response) => { const roomService = container.get(RoomService); const options: MeetRoomOptions = req.body; // Fields are merged from headers into req.query by the middleware - const { fields, extraFields } = req.query as { + const { fields, extraFields } = res.locals.validatedQuery as { fields?: MeetRoomField[]; extraFields?: MeetRoomExtraField[]; }; @@ -46,7 +46,7 @@ export const createRoom = async (req: Request, res: Response) => { export const getRooms = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const roomService = container.get(RoomService); - const queryParams = req.query as MeetRoomFilters; + const queryParams = res.locals.validatedQuery as MeetRoomFilters; logger.verbose(`Getting all rooms with filters: ${JSON.stringify(queryParams)}`); @@ -71,7 +71,7 @@ export const getRoom = async (req: Request, res: Response) => { const { roomId } = req.params; // Zod already validated and transformed to typed arrays - const { fields, extraFields } = req.query as { + const { fields, extraFields } = res.locals.validatedQuery as { fields?: MeetRoomField[]; extraFields?: MeetRoomExtraField[]; }; @@ -101,7 +101,7 @@ export const deleteRoom = async (req: Request, res: Response) => { const roomService = container.get(RoomService); const { roomId } = req.params; - const { fields, extraFields, withMeeting, withRecordings } = req.query as { + const { fields, extraFields, withMeeting, withRecordings } = res.locals.validatedQuery as { fields?: MeetRoomField[]; extraFields?: MeetRoomExtraField[]; withMeeting: MeetRoomDeletionPolicyWithMeeting; @@ -141,7 +141,7 @@ export const bulkDeleteRooms = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const roomService = container.get(RoomService); - const { roomIds, fields, extraFields, withMeeting, withRecordings } = req.query as { + const { roomIds, fields, extraFields, withMeeting, withRecordings } = res.locals.validatedQuery as { roomIds: string[]; fields?: MeetRoomField[]; extraFields?: MeetRoomExtraField[]; @@ -150,7 +150,7 @@ export const bulkDeleteRooms = async (req: Request, res: Response) => { }; try { - logger.verbose(`Deleting rooms: ${roomIds} with options: ${JSON.stringify(req.query)}`); + logger.verbose(`Deleting rooms: ${roomIds} with options: ${JSON.stringify(res.locals.validatedQuery)}`); const deleteOpts: MeetRoomDeletionOptions = { withMeeting, diff --git a/meet-ce/backend/src/controllers/user.controller.ts b/meet-ce/backend/src/controllers/user.controller.ts index 5670d6f4..efb39673 100644 --- a/meet-ce/backend/src/controllers/user.controller.ts +++ b/meet-ce/backend/src/controllers/user.controller.ts @@ -10,9 +10,9 @@ import { } from '../models/error.model.js'; import { LoggerService } from '../services/logger.service.js'; import { RequestSessionService } from '../services/request-session.service.js'; +import { TokenService } from '../services/token.service.js'; import { UserService } from '../services/user.service.js'; import { getBaseUrl } from '../utils/url.utils.js'; -import { TokenService } from '../services/token.service.js'; export const createUser = async (req: Request, res: Response) => { const userOptions = req.body as MeetUserOptions; @@ -31,7 +31,7 @@ export const createUser = async (req: Request, res: Response) => { }; export const getUsers = async (req: Request, res: Response) => { - const queryParams = req.query as MeetUserFilters; + const queryParams = res.locals.validatedQuery as MeetUserFilters; const logger = container.get(LoggerService); logger.verbose(`Getting all users`); @@ -186,7 +186,7 @@ export const deleteUser = async (req: Request, res: Response) => { }; export const bulkDeleteUsers = async (req: Request, res: Response) => { - const { userIds } = req.query as { userIds: string[] }; + const { userIds } = res.locals.validatedQuery as { userIds: string[] }; const logger = container.get(LoggerService); logger.verbose(`Deleting users: ${userIds}`); diff --git a/meet-ce/backend/src/middlewares/request-validators/recording-validator.middleware.ts b/meet-ce/backend/src/middlewares/request-validators/recording-validator.middleware.ts index d789ee23..89da001e 100644 --- a/meet-ce/backend/src/middlewares/request-validators/recording-validator.middleware.ts +++ b/meet-ce/backend/src/middlewares/request-validators/recording-validator.middleware.ts @@ -15,7 +15,8 @@ import { export const validateStartRecordingReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields header into query params before validation - mergeRecordingHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeRecordingHeaderFieldsIntoQuery(req.headers, query); const bodyResult = StartRecordingReqSchema.safeParse(req.body); @@ -25,27 +26,28 @@ export const validateStartRecordingReq = (req: Request, res: Response, next: Nex req.body = bodyResult.data; - const queryResult = RecordingQueryFieldsSchema.safeParse(req.query); + const queryResult = RecordingQueryFieldsSchema.safeParse(query); if (!queryResult.success) { return rejectUnprocessableRequest(res, queryResult.error); } - req.query = queryResult.data; + res.locals.validatedQuery = queryResult.data; next(); }; export const validateGetRecordingsReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields header into query params before validation - mergeRecordingHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeRecordingHeaderFieldsIntoQuery(req.headers, query); - const { success, error, data } = RecordingFiltersSchema.safeParse(req.query); + const { success, error, data } = RecordingFiltersSchema.safeParse(query); if (!success) { return rejectUnprocessableRequest(res, error); } - req.query = { + res.locals.validatedQuery = { ...data, maxItems: data.maxItems?.toString() }; @@ -59,7 +61,7 @@ export const validateBulkDeleteRecordingsReq = (req: Request, res: Response, nex return rejectUnprocessableRequest(res, error); } - req.query = data; + res.locals.validatedQuery = data; next(); }; @@ -77,11 +79,12 @@ export const withValidRecordingId = (req: Request, res: Response, next: NextFunc export const validateGetRecordingReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields header into query params before validation - mergeRecordingHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeRecordingHeaderFieldsIntoQuery(req.headers, query); const { success, error, data } = GetRecordingReqSchema.safeParse({ params: req.params, - query: req.query + query }); if (!success) { @@ -89,17 +92,18 @@ export const validateGetRecordingReq = (req: Request, res: Response, next: NextF } req.params.recordingId = data.params.recordingId; - req.query = data.query; + res.locals.validatedQuery = data.query; next(); }; export const validateStopRecordingReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields header into query params before validation - mergeRecordingHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeRecordingHeaderFieldsIntoQuery(req.headers, query); const { success, error, data } = StopRecordingReqSchema.safeParse({ params: req.params, - query: req.query + query }); if (!success) { @@ -107,7 +111,7 @@ export const validateStopRecordingReq = (req: Request, res: Response, next: Next } req.params.recordingId = data.params.recordingId; - req.query = data.query; + res.locals.validatedQuery = data.query; next(); }; @@ -139,6 +143,6 @@ export const validateGetRecordingUrlReq = (req: Request, res: Response, next: Ne } req.params.recordingId = data.params.recordingId; - req.query.privateAccess = data.query.privateAccess ? 'true' : 'false'; + res.locals.validatedQuery = { privateAccess: data.query.privateAccess ? 'true' : 'false' }; next(); }; diff --git a/meet-ce/backend/src/middlewares/request-validators/room-member-validator.middleware.ts b/meet-ce/backend/src/middlewares/request-validators/room-member-validator.middleware.ts index 764bead6..be1140d6 100644 --- a/meet-ce/backend/src/middlewares/request-validators/room-member-validator.middleware.ts +++ b/meet-ce/backend/src/middlewares/request-validators/room-member-validator.middleware.ts @@ -28,7 +28,7 @@ export const validateGetRoomMembersReq = (req: Request, res: Response, next: Nex return rejectUnprocessableRequest(res, error); } - req.query = { + res.locals.validatedQuery = { ...data, maxItems: data.maxItems?.toString() }; @@ -42,7 +42,7 @@ export const validateBulkDeleteRoomMembersReq = (req: Request, res: Response, ne return rejectUnprocessableRequest(res, error); } - req.query = data; + res.locals.validatedQuery = data; next(); }; diff --git a/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts b/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts index 84122857..c6837434 100644 --- a/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts +++ b/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts @@ -15,7 +15,8 @@ import { } from '../../models/zod-schemas/room.schema.js'; export const validateCreateRoomReq = (req: Request, res: Response, next: NextFunction) => { - mergeHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeHeaderFieldsIntoQuery(req.headers, query); const bodyResult = RoomOptionsSchema.safeParse(req.body); @@ -25,27 +26,28 @@ export const validateCreateRoomReq = (req: Request, res: Response, next: NextFun req.body = bodyResult.data; - const { success, error, data } = RoomQueryFieldsSchema.safeParse(req.query); + const { success, error, data } = RoomQueryFieldsSchema.safeParse(query); if (!success) { return rejectUnprocessableRequest(res, error); } - req.query = data; + res.locals.validatedQuery = data; next(); }; export const validateGetRoomsReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields and X-ExtraFields headers into query params before validation - mergeHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeHeaderFieldsIntoQuery(req.headers, query); - const { success, error, data } = RoomFiltersSchema.safeParse(req.query); + const { success, error, data } = RoomFiltersSchema.safeParse(query); if (!success) { return rejectUnprocessableRequest(res, error); } - req.query = { + res.locals.validatedQuery = { ...data, maxItems: data.maxItems?.toString() }; @@ -54,15 +56,16 @@ export const validateGetRoomsReq = (req: Request, res: Response, next: NextFunct export const validateBulkDeleteRoomsReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields and X-ExtraFields headers into query params before validation - mergeHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeHeaderFieldsIntoQuery(req.headers, query); - const { success, error, data } = BulkDeleteRoomsReqSchema.safeParse(req.query); + const { success, error, data } = BulkDeleteRoomsReqSchema.safeParse(query); if (!success) { return rejectUnprocessableRequest(res, error); } - req.query = data; + res.locals.validatedQuery = data; next(); }; @@ -80,15 +83,16 @@ export const withValidRoomId = (req: Request, res: Response, next: NextFunction) export const validateGetRoomReq = (req: Request, res: Response, next: NextFunction) => { // Merge X-Fields and X-ExtraFields headers into query params before validation - mergeHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeHeaderFieldsIntoQuery(req.headers, query); - const { success, error, data } = RoomQueryFieldsSchema.safeParse(req.query); + const { success, error, data } = RoomQueryFieldsSchema.safeParse(query); if (!success) { return rejectUnprocessableRequest(res, error); } - req.query = data; + res.locals.validatedQuery = data; next(); }; @@ -102,15 +106,16 @@ export const validateDeleteRoomReq = (req: Request, res: Response, next: NextFun req.params.roomId = roomIdResult.data; // Merge X-Fields and X-ExtraFields headers into query params before validation - mergeHeaderFieldsIntoQuery(req.headers, req.query); + const query = req.query; + mergeHeaderFieldsIntoQuery(req.headers, query); - const queryParamsResult = DeleteRoomReqSchema.safeParse(req.query); + const queryParamsResult = DeleteRoomReqSchema.safeParse(query); if (!queryParamsResult.success) { return rejectUnprocessableRequest(res, queryParamsResult.error); } - req.query = queryParamsResult.data; + res.locals.validatedQuery = queryParamsResult.data; next(); }; diff --git a/meet-ce/backend/src/middlewares/request-validators/user-validator.middleware.ts b/meet-ce/backend/src/middlewares/request-validators/user-validator.middleware.ts index 0134fad4..1799306f 100644 --- a/meet-ce/backend/src/middlewares/request-validators/user-validator.middleware.ts +++ b/meet-ce/backend/src/middlewares/request-validators/user-validator.middleware.ts @@ -27,7 +27,7 @@ export const validateGetUsersReq = (req: Request, res: Response, next: NextFunct return rejectUnprocessableRequest(res, error); } - req.query = { + res.locals.validatedQuery = { ...data, maxItems: data.maxItems?.toString() }; @@ -41,7 +41,7 @@ export const validateBulkDeleteUsersReq = (req: Request, res: Response, next: Ne return rejectUnprocessableRequest(res, error); } - req.query = data; + res.locals.validatedQuery = data; next(); }; diff --git a/meet-ce/backend/src/server.ts b/meet-ce/backend/src/server.ts index 1fefb73b..eb1e1c3e 100644 --- a/meet-ce/backend/src/server.ts +++ b/meet-ce/backend/src/server.ts @@ -127,7 +127,7 @@ const startServer = (app: express.Application) => { const basePath = getBasePath(); const basePathDisplay = basePath === '/' ? '' : basePath.slice(0, -1); - app.listen(MEET_ENV.SERVER_PORT, async () => { + const server = app.listen(MEET_ENV.SERVER_PORT, () => { console.log(' '); console.log('---------------------------------------------------------'); console.log(' '); @@ -145,6 +145,11 @@ const startServer = (app: express.Application) => { ); logEnvVars(); }); + + server.on('error', (error: Error) => { + console.error('Server failed to start:', error.message); + process.exit(1); + }); }; /** diff --git a/meet-ce/backend/src/types/express-locals.d.ts b/meet-ce/backend/src/types/express-locals.d.ts new file mode 100644 index 00000000..7e602279 --- /dev/null +++ b/meet-ce/backend/src/types/express-locals.d.ts @@ -0,0 +1,9 @@ +declare global { + namespace Express { + interface Locals { + validatedQuery?: Record; + } + } +} + +export {}; diff --git a/meet-ce/backend/tests/integration/api/recordings/get-recordings.test.ts b/meet-ce/backend/tests/integration/api/recordings/get-recordings.test.ts index d5c5fe75..bd695ae1 100644 --- a/meet-ce/backend/tests/integration/api/recordings/get-recordings.test.ts +++ b/meet-ce/backend/tests/integration/api/recordings/get-recordings.test.ts @@ -380,11 +380,6 @@ describe('Recordings API Tests', () => { expectValidationError(response, 'maxItems', 'must be a positive number'); }); - it('should fail when fields is not a string', async () => { - const response = await getAllRecordings({ fields: { invalid: 'object' } }); - expectValidationError(response, 'fields', 'Expected string'); - }); - it('should fail when sortField is invalid', async () => { const response = await getAllRecordings({ sortField: 'invalidField' }); expectValidationError(response, 'sortField', 'Invalid enum value'); diff --git a/meet-ce/backend/tests/integration/api/rooms/get-rooms.test.ts b/meet-ce/backend/tests/integration/api/rooms/get-rooms.test.ts index ffb7a289..3cb3af79 100644 --- a/meet-ce/backend/tests/integration/api/rooms/get-rooms.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/get-rooms.test.ts @@ -229,11 +229,6 @@ describe('Room API Tests', () => { expectValidationError(response, 'maxItems', 'must be a positive number'); }); - it('should fail when fields is not a string', async () => { - const response = await getRooms({ fields: { invalid: 'data' } }); - expectValidationError(response, 'fields', 'Expected string'); - }); - it('should fail when sortField is invalid', async () => { const response = await getRooms({ sortField: 'invalidField' }); expectValidationError(response, 'sortField', 'Invalid enum value'); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66eca497..d08d1d3b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,11 +105,11 @@ importers: specifier: 16.6.1 version: 16.6.1 express: - specifier: 4.22.1 - version: 4.22.1 + specifier: 5.2.1 + version: 5.2.1 express-rate-limit: specifier: 7.5.1 - version: 7.5.1(express@4.22.1) + version: 7.5.1(express@5.2.1) inversify: specifier: 6.2.2 version: 6.2.2(reflect-metadata@0.2.2) @@ -152,13 +152,13 @@ importers: version: 5.0.2 '@types/cookie-parser': specifier: 1.4.9 - version: 1.4.9(@types/express@4.17.25) + version: 1.4.9(@types/express@5.0.6) '@types/cors': specifier: 2.8.19 version: 2.8.19 '@types/express': - specifier: 4.17.25 - version: 4.17.25 + specifier: 5.0.6 + version: 5.0.6 '@types/jest': specifier: 29.5.14 version: 29.5.14 @@ -4133,9 +4133,6 @@ packages: '@types/express@4.17.23': resolution: {integrity: sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==} - '@types/express@4.17.25': - resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/express@5.0.6': resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} @@ -6080,10 +6077,6 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} - express@4.22.1: - resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} - engines: {node: '>= 0.10.0'} - express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -14834,9 +14827,9 @@ snapshots: dependencies: '@types/express': 4.17.23 - '@types/cookie-parser@1.4.9(@types/express@4.17.25)': + '@types/cookie-parser@1.4.9(@types/express@5.0.6)': dependencies: - '@types/express': 4.17.25 + '@types/express': 5.0.6 '@types/cookiejar@2.1.5': {} @@ -14887,13 +14880,6 @@ snapshots: '@types/qs': 6.14.0 '@types/serve-static': 2.2.0 - '@types/express@4.17.25': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 4.19.7 - '@types/qs': 6.14.0 - '@types/serve-static': 1.15.10 - '@types/express@5.0.6': dependencies: '@types/body-parser': 1.19.6 @@ -17375,10 +17361,6 @@ snapshots: dependencies: express: 4.21.2 - express-rate-limit@7.5.1(express@4.22.1): - dependencies: - express: 4.22.1 - express-rate-limit@7.5.1(express@5.2.1): dependencies: express: 5.2.1 @@ -17419,42 +17401,6 @@ snapshots: transitivePeerDependencies: - supports-color - express@4.22.1: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.4 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.1 - fresh: 0.5.2 - http-errors: 2.0.1 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.12 - proxy-addr: 2.0.7 - qs: 6.14.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.2 - serve-static: 1.16.3 - setprototypeof: 1.2.0 - statuses: 2.0.2 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - express@5.2.1: dependencies: accepts: 2.0.0 @@ -17477,7 +17423,7 @@ snapshots: once: 1.4.0 parseurl: 1.3.3 proxy-addr: 2.0.7 - qs: 6.14.0 + qs: 6.15.0 range-parser: 1.2.1 router: 2.2.0 send: 1.2.1 @@ -18028,7 +17974,7 @@ snapshots: transitivePeerDependencies: - supports-color - http-proxy-middleware@2.0.9(@types/express@4.17.25): + http-proxy-middleware@2.0.9(@types/express@4.17.23): dependencies: '@types/http-proxy': 1.17.17 http-proxy: 1.18.1(debug@4.4.3) @@ -18036,7 +17982,7 @@ snapshots: is-plain-obj: 3.0.0 micromatch: 4.0.8 optionalDependencies: - '@types/express': 4.17.25 + '@types/express': 4.17.23 transitivePeerDependencies: - debug @@ -22109,7 +22055,7 @@ snapshots: dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 - '@types/express': 4.17.25 + '@types/express': 4.17.23 '@types/express-serve-static-core': 4.19.7 '@types/serve-index': 1.9.4 '@types/serve-static': 1.15.10 @@ -22121,9 +22067,9 @@ snapshots: colorette: 2.0.20 compression: 1.8.1 connect-history-api-fallback: 2.0.0 - express: 4.22.1 + express: 4.21.2 graceful-fs: 4.2.11 - http-proxy-middleware: 2.0.9(@types/express@4.17.25) + http-proxy-middleware: 2.0.9(@types/express@4.17.23) ipaddr.js: 2.3.0 launch-editor: 2.12.0 open: 10.2.0