mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-08 17:03:53 +00:00
Upgrade expressjs (#1633)
* upgrade expressjs * migration * reenable test * extend timeout on download test * fixup! migration * move empty body test from controller to validator * enusre not empty * extract validation function * fixup! reenable test * remove thin controllers * disable e2e test of project file download
This commit is contained in:
committed by
GitHub
parent
2a5b053d97
commit
a4b15970de
+11
-11
@@ -6,18 +6,18 @@
|
||||
"exports": "./src/index.js",
|
||||
"dependencies": {
|
||||
"@googleapis/sheets": "^5.0.5",
|
||||
"cookie": "^1.0.2",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"cors": "^2.8.5",
|
||||
"cookie": "1.0.2",
|
||||
"cookie-parser": "1.4.7",
|
||||
"cors": "2.8.5",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.21.1",
|
||||
"express-static-gzip": "^2.2.0",
|
||||
"express-validator": "^7.2.0",
|
||||
"express": "5.1.0",
|
||||
"express-static-gzip": "3.0.0",
|
||||
"express-validator": "7.2.1",
|
||||
"multer": "2.0.1",
|
||||
"fast-equals": "^5.0.1",
|
||||
"google-auth-library": "^9.4.2",
|
||||
"got": "^14.4.5",
|
||||
"lowdb": "^7.0.1",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"ontime-utils": "workspace:*",
|
||||
"osc-min": "2.1.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
@@ -26,10 +26,10 @@
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cookie-parser": "^1.4.8",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/multer": "^1.4.11",
|
||||
"@types/cookie-parser": "1.4.9",
|
||||
"@types/cors": "2.8.19",
|
||||
"@types/express": "5.0.3",
|
||||
"@types/multer": "1.4.13",
|
||||
"@types/node": "catalog:",
|
||||
"@types/websocket": "^1.0.5",
|
||||
"@types/ws": "^8.5.10",
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { defaultCss } from '../../user/styles/bundledCss.js';
|
||||
import type { Request, Response } from 'express';
|
||||
import { readCssFile, writeCssFile } from './assets.service.js';
|
||||
|
||||
/**
|
||||
* Exposes the contents of the cssOverride.css file
|
||||
*/
|
||||
export async function getCssOverride(_req: Request, res: Response) {
|
||||
try {
|
||||
const data = await readCssFile();
|
||||
res.status(200).send(data);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: error });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows modifying the cssOverride.css file
|
||||
*/
|
||||
export async function postCssOverride(req: Request, res: Response) {
|
||||
const { css } = req.body;
|
||||
|
||||
try {
|
||||
await writeCssFile(css);
|
||||
res.status(204).send();
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: error });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the default cssOverride.css file
|
||||
*/
|
||||
export async function restoreCss(_req: Request, res: Response) {
|
||||
try {
|
||||
await writeCssFile(defaultCss);
|
||||
res.status(200).send(defaultCss);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: error });
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,40 @@
|
||||
import express from 'express';
|
||||
|
||||
import { getCssOverride, postCssOverride, restoreCss } from './assets.controller.js';
|
||||
import type { Request, Response } from 'express';
|
||||
import type { ErrorResponse } from 'ontime-types';
|
||||
import { validatePostCss } from './assets.validation.js';
|
||||
import { readCssFile, writeCssFile } from './assets.service.js';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
import { defaultCss } from '../../user/styles/bundledCss.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/css', getCssOverride);
|
||||
router.post('/css', validatePostCss, postCssOverride);
|
||||
router.post('/css/restore', restoreCss);
|
||||
router.get('/css', async (_req: Request, res: Response<string | ErrorResponse>) => {
|
||||
try {
|
||||
const data = await readCssFile();
|
||||
res.status(200).send(data);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/css', validatePostCss, async (req: Request, res: Response<never | ErrorResponse>) => {
|
||||
const { css } = req.body;
|
||||
try {
|
||||
await writeCssFile(css);
|
||||
res.status(204).send();
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/css/restore', async (_req: Request, res: Response<string | ErrorResponse>) => {
|
||||
try {
|
||||
await writeCssFile(defaultCss);
|
||||
res.status(200).send(defaultCss);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { body, validationResult } from 'express-validator';
|
||||
import { body } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const validatePostCss = [
|
||||
body('css').isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const validatePostCss = [body('css').isString().trim(), requestValidationFunction];
|
||||
|
||||
@@ -12,7 +12,7 @@ import * as automationService from './automation.service.js';
|
||||
import { parseOutput } from './automation.validation.js';
|
||||
|
||||
export function getAutomationSettings(_req: Request, res: Response<AutomationSettings>) {
|
||||
res.json(automationDao.getAutomationSettings());
|
||||
res.status(200).json(automationDao.getAutomationSettings());
|
||||
}
|
||||
|
||||
export async function postAutomationSettings(req: Request, res: Response<AutomationSettings | ErrorResponse>) {
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
testOutput,
|
||||
} from './automation.controller.js';
|
||||
import {
|
||||
paramContainsId,
|
||||
validateAutomationSettings,
|
||||
validateAutomation,
|
||||
validateAutomationPatch,
|
||||
@@ -20,6 +19,7 @@ import {
|
||||
validateTrigger,
|
||||
validateTriggerPatch,
|
||||
} from './automation.validation.js';
|
||||
import { paramsWithId } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
@@ -28,10 +28,10 @@ router.post('/', validateAutomationSettings, postAutomationSettings);
|
||||
|
||||
router.post('/trigger', validateTrigger, postTrigger);
|
||||
router.put('/trigger/:id', validateTriggerPatch, putTrigger);
|
||||
router.delete('/trigger/:id', paramContainsId, deleteTrigger);
|
||||
router.delete('/trigger/:id', paramsWithId, deleteTrigger);
|
||||
|
||||
router.post('/automation', validateAutomation, postAutomation);
|
||||
router.put('/automation/:id', validateAutomationPatch, editAutomation);
|
||||
router.delete('/automation/:id', paramContainsId, deleteAutomation);
|
||||
router.delete('/automation/:id', paramsWithId, deleteAutomation);
|
||||
|
||||
router.post('/test', validateTestPayload, testOutput);
|
||||
|
||||
@@ -10,22 +10,12 @@ import {
|
||||
} from 'ontime-types';
|
||||
import { parseUserTime } from 'ontime-utils';
|
||||
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body, oneOf, param, validationResult } from 'express-validator';
|
||||
import { body, oneOf, param } from 'express-validator';
|
||||
|
||||
import * as assert from '../../utils/assert.js';
|
||||
|
||||
import { isFilterOperator, isFilterRule, isOntimeActionAction } from './automation.utils.js';
|
||||
|
||||
export const paramContainsId = [
|
||||
param('id').isString().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const validateAutomationSettings = [
|
||||
body('enabledAutomations').isBoolean(),
|
||||
@@ -37,57 +27,33 @@ export const validateAutomationSettings = [
|
||||
body('triggers.*.automationId').optional().isString().trim(),
|
||||
body('automations').optional().custom(parseAutomation),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const validateTrigger = [
|
||||
body('title').isString().trim(),
|
||||
body('title').isString().trim().notEmpty(),
|
||||
body('trigger').isIn(timerLifecycleValues),
|
||||
body('automationId').isString().trim(),
|
||||
body('automationId').isString().trim().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const validateTriggerPatch = [
|
||||
param('id').isString().notEmpty(),
|
||||
body('title').optional().isString().trim(),
|
||||
body('title').optional().isString().trim().notEmpty(),
|
||||
body('trigger').optional().isIn(timerLifecycleValues),
|
||||
body('automationId').optional().isString().trim(),
|
||||
body('automationId').optional().isString().trim().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const validateAutomation = [
|
||||
body().custom(parseAutomation),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const validateAutomation = [body().custom(parseAutomation), requestValidationFunction];
|
||||
|
||||
export const validateAutomationPatch = [
|
||||
param('id').isString().notEmpty(),
|
||||
body().custom(parseAutomation),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -162,11 +128,7 @@ export const validateTestPayload = [
|
||||
body('visible').if(body('type').equals('ontime')).optional().isString().trim(),
|
||||
body('secondarySource').if(body('type').equals('ontime')).optional().isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,7 @@ export const router = express.Router();
|
||||
|
||||
router.get('/', async (_req: Request, res: Response<CustomFields>) => {
|
||||
const customFields = getProjectCustomFields();
|
||||
res.json(customFields);
|
||||
res.status(200).json(customFields);
|
||||
});
|
||||
|
||||
router.post('/', validateCustomField, async (req: Request, res: Response<CustomFields | ErrorResponse>) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { isAlphanumericWithSpace } from 'ontime-utils';
|
||||
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body, param, validationResult } from 'express-validator';
|
||||
import { body, param } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const validateCustomField = [
|
||||
body('label')
|
||||
@@ -14,11 +14,7 @@ export const validateCustomField = [
|
||||
body('type').isIn(['string', 'image']),
|
||||
body('colour').isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const validateEditCustomField = [
|
||||
@@ -33,19 +29,7 @@ export const validateEditCustomField = [
|
||||
body('type').isIn(['string', 'image']),
|
||||
body('colour').isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const validateDeleteCustomField = [
|
||||
param('key').isString().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const validateDeleteCustomField = [param('key').isString().notEmpty(), requestValidationFunction];
|
||||
|
||||
@@ -106,7 +106,8 @@ export async function projectDownload(req: Request, res: Response) {
|
||||
const { filename } = req.body;
|
||||
const pathToFile = doesProjectExist(filename);
|
||||
if (!pathToFile) {
|
||||
return res.status(404).send({ message: `Project ${filename} not found.` });
|
||||
res.status(404).send({ message: `Project ${filename} not found.` });
|
||||
return;
|
||||
}
|
||||
|
||||
res.download(pathToFile, filename, (error) => {
|
||||
@@ -138,7 +139,8 @@ export async function postProjectFile(req: Request, res: Response<MessageRespons
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message.startsWith('Project file')) {
|
||||
return res.status(403).send({ message });
|
||||
res.status(403).send({ message });
|
||||
return;
|
||||
}
|
||||
res.status(400).send({ message });
|
||||
}
|
||||
@@ -195,7 +197,8 @@ export async function loadProject(req: Request, res: Response<MessageResponse |
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message.startsWith('Project file')) {
|
||||
return res.status(403).send({ message });
|
||||
res.status(403).send({ message });
|
||||
return;
|
||||
}
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
@@ -214,7 +217,8 @@ export async function loadDemo(_req: Request, res: Response<MessageResponse | Er
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message.startsWith('Project file')) {
|
||||
return res.status(403).send({ message });
|
||||
res.status(403).send({ message });
|
||||
return;
|
||||
}
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
@@ -245,7 +249,8 @@ export async function duplicateProjectFile(req: Request, res: Response<MessageRe
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message.startsWith('Project file')) {
|
||||
return res.status(403).send({ message });
|
||||
res.status(403).send({ message });
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(500).send({ message });
|
||||
@@ -275,7 +280,8 @@ export async function renameProjectFile(req: Request, res: Response<MessageRespo
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message.startsWith('Project file')) {
|
||||
return res.status(403).send({ message });
|
||||
res.status(403).send({ message });
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(500).send({ message });
|
||||
@@ -303,10 +309,12 @@ export async function deleteProjectFile(req: Request, res: Response<MessageRespo
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message === 'Cannot delete currently loaded project') {
|
||||
return res.status(403).send({ message });
|
||||
res.status(403).send({ message });
|
||||
return;
|
||||
}
|
||||
if (message === 'Project file not found') {
|
||||
return res.status(404).send({ message });
|
||||
res.status(404).send({ message });
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(500).send({ message });
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body, param, validationResult } from 'express-validator';
|
||||
import { body, param } from 'express-validator';
|
||||
import sanitize from 'sanitize-filename';
|
||||
import { ensureJsonExtension } from '../../utils/fileManagement.js';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
/**
|
||||
* @description Validates request for a new project.
|
||||
*/
|
||||
export const validateNewProject = [
|
||||
body().notEmpty().withMessage('No object found in request'),
|
||||
body('filename').optional().isString().trim(),
|
||||
body('title').optional().isString().trim(),
|
||||
body('description').optional().isString().trim(),
|
||||
@@ -18,11 +19,7 @@ export const validateNewProject = [
|
||||
body('endMessage').optional().isString().trim(),
|
||||
body('custom').optional().isArray(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -40,25 +37,14 @@ export const validateQuickProject = [
|
||||
body('viewSettings.freezeEnd').optional().isBoolean(),
|
||||
body('viewSettings.endMessage').optional().isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Validates request for pathing data in the project.
|
||||
*/
|
||||
export const validatePatchProject = [
|
||||
// Custom validator to ensure the body is not empty
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
if (Object.keys(req.body).length === 0) {
|
||||
return res.status(422).json({ errors: [{ msg: 'Request body cannot be empty' }] });
|
||||
}
|
||||
next();
|
||||
},
|
||||
|
||||
body().notEmpty().withMessage('No object found in request'),
|
||||
body('rundowns').isObject().optional({ nullable: false }),
|
||||
body('project').isObject().optional({ nullable: false }),
|
||||
body('settings').isObject().optional({ nullable: false }),
|
||||
@@ -68,11 +54,7 @@ export const validatePatchProject = [
|
||||
body('osc').isObject().optional({ nullable: false }),
|
||||
body('http').isObject().optional({ nullable: false }),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -88,14 +70,7 @@ export const validateNewFilenameBody = [
|
||||
.withMessage('Filename was empty or contained only invalid characters')
|
||||
.customSanitizer((input: string) => ensureJsonExtension(input)),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -111,14 +86,7 @@ export const validateFilenameBody = [
|
||||
.withMessage('Filename was empty or contained only invalid characters')
|
||||
.customSanitizer((input: string) => ensureJsonExtension(input)),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -134,12 +102,5 @@ export const validateFilenameParam = [
|
||||
.withMessage('Filename was empty or contained only invalid characters')
|
||||
.customSanitizer((input: string) => ensureJsonExtension(input)),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* This module encapsulates logic related to
|
||||
* Google Sheets
|
||||
*/
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
import { generateRundownPreview, listWorksheets, saveExcelFile } from './excel.service.js';
|
||||
import { CustomFields, Rundown } from 'ontime-types';
|
||||
|
||||
export async function postExcel(req: Request, res: Response) {
|
||||
try {
|
||||
// file has been validated by middleware
|
||||
const filePath = (req.file as Express.Multer.File).path;
|
||||
await saveExcelFile(filePath);
|
||||
res.status(200).send();
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
}
|
||||
}
|
||||
|
||||
export async function getWorksheets(req: Request, res: Response) {
|
||||
try {
|
||||
const names = listWorksheets();
|
||||
res.status(200).send(names);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parses an Excel spreadsheet
|
||||
* @returns parsed result
|
||||
*/
|
||||
export async function previewExcel(
|
||||
req: Request,
|
||||
res: Response<{ rundown: Rundown; customFields: CustomFields } | { message: string }>,
|
||||
) {
|
||||
try {
|
||||
const { options } = req.body;
|
||||
const data = generateRundownPreview(options);
|
||||
res.status(200).send(data);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,42 @@
|
||||
/**
|
||||
* This is a feature specific router for integration with Excel
|
||||
*/
|
||||
|
||||
import express from 'express';
|
||||
import type { Request, Response } from 'express';
|
||||
import { uploadExcel } from './excel.middleware.js';
|
||||
import { getWorksheets, postExcel, previewExcel } from './excel.controller.js';
|
||||
import { validateFileExists, validateImportMapOptions } from './excel.validation.js';
|
||||
import { CustomFields, ErrorResponse, Rundown } from 'ontime-types';
|
||||
import { generateRundownPreview, listWorksheets, saveExcelFile } from './excel.service.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.post('/upload', uploadExcel, validateFileExists, postExcel);
|
||||
router.get('/worksheets', getWorksheets);
|
||||
router.post('/preview', validateImportMapOptions, previewExcel);
|
||||
router.post('/upload', uploadExcel, validateFileExists, async (req: Request, res: Response<never | ErrorResponse>) => {
|
||||
try {
|
||||
// file has been validated by middleware
|
||||
const filePath = (req.file as Express.Multer.File).path;
|
||||
await saveExcelFile(filePath);
|
||||
res.status(201).send();
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/worksheets', (_req: Request, res: Response<string[] | ErrorResponse>) => {
|
||||
try {
|
||||
const names = listWorksheets();
|
||||
res.status(200).send(names);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
}
|
||||
});
|
||||
|
||||
router.post(
|
||||
'/preview',
|
||||
validateImportMapOptions,
|
||||
(req: Request, res: Response<{ rundown: Rundown; customFields: CustomFields } | ErrorResponse>) => {
|
||||
try {
|
||||
const { options } = req.body;
|
||||
const data = generateRundownPreview(options);
|
||||
res.status(200).send(data);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import { isImportMap } from 'ontime-utils';
|
||||
|
||||
import { body, validationResult } from 'express-validator';
|
||||
import type { NextFunction, Request, Response } from 'express';
|
||||
import { body } from 'express-validator';
|
||||
import {
|
||||
requestValidationFunction,
|
||||
requestValidationFunctionWithFile,
|
||||
} from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const validateFileExists = [
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
if (!req.file) {
|
||||
return res.status(422).json({ errors: 'File not found' });
|
||||
}
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const validateFileExists = [requestValidationFunctionWithFile];
|
||||
|
||||
export const validateImportMapOptions = [
|
||||
body('options')
|
||||
@@ -19,9 +15,5 @@ export const validateImportMapOptions = [
|
||||
return isImportMap(content);
|
||||
}),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -31,6 +31,6 @@ appRouter.use('/report', reportRouter);
|
||||
appRouter.use('/assets', assetsRouter);
|
||||
|
||||
//we don't want to redirect to react index when using api routes
|
||||
appRouter.all('/*', (_req, res) => {
|
||||
res.status(404).send();
|
||||
appRouter.all('/*splat', (_req, res) => {
|
||||
res.status(404).send('data path not found');
|
||||
});
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { ErrorResponse, ProjectData } from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import { removeUndefined } from '../../utils/parserUtils.js';
|
||||
import { failEmptyObjects } from '../../utils/routerUtils.js';
|
||||
import { editCurrentProjectData } from '../../services/project-service/ProjectService.js';
|
||||
import * as projectDao from './projectData.dao.js';
|
||||
|
||||
export function getProjectData(_req: Request, res: Response<ProjectData>) {
|
||||
res.json(projectDao.getProjectData());
|
||||
}
|
||||
|
||||
export async function postProjectData(req: Request, res: Response<ProjectData | ErrorResponse>) {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const newData: Partial<ProjectData> = removeUndefined({
|
||||
title: req.body?.title,
|
||||
description: req.body?.description,
|
||||
publicUrl: req.body?.publicUrl,
|
||||
publicInfo: req.body?.publicInfo,
|
||||
backstageUrl: req.body?.backstageUrl,
|
||||
backstageInfo: req.body?.backstageInfo,
|
||||
endMessage: req.body?.endMessage,
|
||||
projectLogo: req.body?.projectLogo,
|
||||
custom: req.body?.custom,
|
||||
});
|
||||
|
||||
const updatedData = await editCurrentProjectData(newData);
|
||||
|
||||
res.status(200).send(updatedData);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(400).send({ message });
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,42 @@
|
||||
import express from 'express';
|
||||
import type { Request, Response } from 'express';
|
||||
import type { ErrorResponse, ProjectData } from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
import { getProjectData, postProjectData } from './projectData.controller.js';
|
||||
import { projectSanitiser } from './projectData.validation.js';
|
||||
import { uploadImageFile } from '../db/db.middleware.js';
|
||||
import { postProjectLogo } from '../db/db.controller.js';
|
||||
import * as projectDao from './projectData.dao.js';
|
||||
import { removeUndefined } from '../../utils/parserUtils.js';
|
||||
import { editCurrentProjectData } from '../../services/project-service/ProjectService.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', getProjectData);
|
||||
router.post('/', projectSanitiser, postProjectData);
|
||||
router.get('/', (_req: Request, res: Response<ProjectData>) => {
|
||||
res.status(200).json(projectDao.getProjectData());
|
||||
});
|
||||
|
||||
router.post('/', projectSanitiser, async (req: Request, res: Response<ProjectData | ErrorResponse>) => {
|
||||
try {
|
||||
const newData: Partial<ProjectData> = removeUndefined({
|
||||
title: req.body?.title,
|
||||
description: req.body?.description,
|
||||
publicUrl: req.body?.publicUrl,
|
||||
publicInfo: req.body?.publicInfo,
|
||||
backstageUrl: req.body?.backstageUrl,
|
||||
backstageInfo: req.body?.backstageInfo,
|
||||
endMessage: req.body?.endMessage,
|
||||
projectLogo: req.body?.projectLogo,
|
||||
custom: req.body?.custom,
|
||||
});
|
||||
|
||||
const updatedData = await editCurrentProjectData(newData);
|
||||
|
||||
res.status(200).send(updatedData);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(400).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/upload', uploadImageFile, postProjectLogo);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { body, validationResult } from 'express-validator';
|
||||
import { body } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const projectSanitiser = [
|
||||
body().notEmpty().withMessage('No object found in request'),
|
||||
body('title').optional().isString().trim(),
|
||||
body('description').optional().isString().trim(),
|
||||
body('publicUrl').optional().isString().trim(),
|
||||
@@ -9,14 +10,10 @@ export const projectSanitiser = [
|
||||
body('backstageUrl').optional().isString().trim(),
|
||||
body('backstageInfo').optional().isString().trim(),
|
||||
body('endMessage').optional().isString().trim(),
|
||||
body('projectLogo').optional({ nullable: true }).isString().trim(),
|
||||
body('projectLogo').optional({ nullable: true }).isString().trim().isBase64(),
|
||||
body('custom').optional().isArray(),
|
||||
body('custom.*.title').optional().isString().trim().notEmpty(),
|
||||
body('custom.*.value').optional().isString().trim().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import type { Request, Response } from 'express';
|
||||
import type { OntimeReport } from 'ontime-types';
|
||||
import * as report from './report.service.js';
|
||||
|
||||
export function getAll(_req: Request, res: Response<OntimeReport>) {
|
||||
res.json(report.generate());
|
||||
}
|
||||
|
||||
export function deleteAll(_req: Request, res: Response<OntimeReport>) {
|
||||
report.clear();
|
||||
res.status(200).send();
|
||||
}
|
||||
|
||||
export function deleteWithId(req: Request, res: Response<OntimeReport>) {
|
||||
const { eventId } = req.params;
|
||||
report.clear(eventId);
|
||||
res.status(200).send();
|
||||
}
|
||||
@@ -1,10 +1,21 @@
|
||||
import express from 'express';
|
||||
import { getAll, deleteWithId, deleteAll } from './report.controller.js';
|
||||
import { paramsMustHaveEntryId } from '../rundown/rundown.validation.js';
|
||||
import type { Request, Response } from 'express';
|
||||
import { paramsWithId } from '../validation-utils/validationFunction.js';
|
||||
import * as report from './report.service.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', getAll);
|
||||
router.get('/', (_req: Request, res: Response) => {
|
||||
res.status(200).json(report.generate());
|
||||
});
|
||||
|
||||
router.delete('/all', deleteAll);
|
||||
router.delete('/:eventId', paramsMustHaveEntryId, deleteWithId);
|
||||
router.delete('/all', (_req: Request, res: Response) => {
|
||||
report.clear();
|
||||
res.status(204).send();
|
||||
});
|
||||
|
||||
router.delete('/:id', paramsWithId, (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
report.clear(id);
|
||||
res.status(204).send();
|
||||
});
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
ungroupEntries,
|
||||
} from './rundown.service.js';
|
||||
import {
|
||||
paramsMustHaveEntryId,
|
||||
rundownArrayOfIds,
|
||||
rundownBatchPutValidator,
|
||||
rundownPostValidator,
|
||||
@@ -27,6 +26,7 @@ import {
|
||||
rundownReorderValidator,
|
||||
rundownSwapValidator,
|
||||
} from './rundown.validation.js';
|
||||
import { paramsWithId } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
@@ -100,11 +100,11 @@ router.patch('/swap', rundownSwapValidator, async (req: Request, res: Response<R
|
||||
});
|
||||
|
||||
router.patch(
|
||||
'/applydelay/:entryId',
|
||||
paramsMustHaveEntryId,
|
||||
'/applydelay/:id',
|
||||
paramsWithId,
|
||||
async (req: Request, res: Response<Rundown | ErrorResponse>) => {
|
||||
try {
|
||||
const newRundown = await applyDelay(req.params.entryId);
|
||||
const newRundown = await applyDelay(req.params.id);
|
||||
res.status(200).send(newRundown);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
@@ -113,9 +113,9 @@ router.patch(
|
||||
},
|
||||
);
|
||||
|
||||
router.post('/clone/:entryId', paramsMustHaveEntryId, async (req: Request, res: Response<Rundown | ErrorResponse>) => {
|
||||
router.post('/clone/:id', paramsWithId, async (req: Request, res: Response<Rundown | ErrorResponse>) => {
|
||||
try {
|
||||
const newRundown = await cloneEntry(req.params.entryId);
|
||||
const newRundown = await cloneEntry(req.params.id);
|
||||
res.status(200).send(newRundown);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
@@ -134,11 +134,11 @@ router.post('/group', rundownArrayOfIds, async (req: Request, res: Response<Rund
|
||||
});
|
||||
|
||||
router.post(
|
||||
'/ungroup/:entryId',
|
||||
paramsMustHaveEntryId,
|
||||
'/ungroup/:id',
|
||||
paramsWithId,
|
||||
async (req: Request, res: Response<Rundown | ErrorResponse>) => {
|
||||
try {
|
||||
const newRundown = await ungroupEntries(req.params.entryId);
|
||||
const newRundown = await ungroupEntries(req.params.id);
|
||||
res.status(200).send(newRundown);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
|
||||
@@ -1,38 +1,22 @@
|
||||
import { body, param, validationResult } from 'express-validator';
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body, param } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const rundownPostValidator = [
|
||||
body('type').isString().isIn(['event', 'delay', 'block']),
|
||||
body('after').optional().isString(),
|
||||
body('before').optional().isString(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const rundownPutValidator = [
|
||||
body('id').isString().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const rundownPutValidator = [body('id').isString().notEmpty(), requestValidationFunction];
|
||||
|
||||
export const rundownBatchPutValidator = [
|
||||
body('data').isObject(),
|
||||
body('ids').isArray().notEmpty(),
|
||||
body('ids.*').isString(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const rundownReorderValidator = [
|
||||
@@ -40,41 +24,21 @@ export const rundownReorderValidator = [
|
||||
body('destinationId').isString().notEmpty(),
|
||||
body('order').isIn(['before', 'after', 'insert']),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const rundownSwapValidator = [
|
||||
body('from').isString().notEmpty(),
|
||||
body('to').isString().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
export const paramsMustHaveEntryId = [
|
||||
param('entryId').isString().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const paramsMustHaveEntryId = [param('entryId').isString().notEmpty(), requestValidationFunction];
|
||||
|
||||
export const rundownArrayOfIds = [
|
||||
body('ids').isArray().notEmpty(),
|
||||
body('ids.*').isString(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
import { ErrorResponse, GetInfo, GetUrl, SessionStats } from 'ontime-types';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import * as sessionService from './session.service.js';
|
||||
|
||||
export async function getSessionStats(_req: Request, res: Response<SessionStats | ErrorResponse>) {
|
||||
try {
|
||||
const stats = await sessionService.getSessionStats();
|
||||
res.status(200).send(stats);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function getInfo(_req: Request, res: Response<GetInfo | ErrorResponse>) {
|
||||
try {
|
||||
const info = await sessionService.getInfo();
|
||||
res.status(200).send(info);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateUrl(req: Request, res: Response<GetUrl | ErrorResponse>) {
|
||||
try {
|
||||
const url = sessionService.generateAuthenticatedUrl(
|
||||
req.body.baseUrl,
|
||||
req.body.path,
|
||||
req.body.lock,
|
||||
req.body.authenticate,
|
||||
);
|
||||
res.status(200).send({ url: url.toString() });
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,43 @@
|
||||
import express from 'express';
|
||||
|
||||
import { getInfo, getSessionStats, generateUrl } from './session.controller.js';
|
||||
import type { Request, Response } from 'express';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
import type { ErrorResponse, GetInfo, GetUrl, SessionStats } from 'ontime-types';
|
||||
import { validateGenerateUrl } from './session.validation.js';
|
||||
import * as sessionService from './session.service.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', getSessionStats);
|
||||
router.get('/info', getInfo);
|
||||
router.post('/url', validateGenerateUrl, generateUrl);
|
||||
router.get('/', async (_req: Request, res: Response<SessionStats | ErrorResponse>) => {
|
||||
try {
|
||||
const stats = await sessionService.getSessionStats();
|
||||
res.status(200).send(stats);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/info', async (_req: Request, res: Response<GetInfo | ErrorResponse>) => {
|
||||
try {
|
||||
const info = await sessionService.getInfo();
|
||||
res.status(200).send(info);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/url', validateGenerateUrl, (req: Request, res: Response<GetUrl | ErrorResponse>) => {
|
||||
try {
|
||||
const url = sessionService.generateAuthenticatedUrl(
|
||||
req.body.baseUrl,
|
||||
req.body.path,
|
||||
req.body.lock,
|
||||
req.body.authenticate,
|
||||
);
|
||||
res.status(200).send({ url: url.toString() });
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body, validationResult } from 'express-validator';
|
||||
|
||||
import { body } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const validateGenerateUrl = [
|
||||
body('baseUrl').isString().trim().notEmpty(),
|
||||
@@ -7,9 +8,5 @@ export const validateGenerateUrl = [
|
||||
body('lock').isBoolean(),
|
||||
body('authenticate').isBoolean(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -4,7 +4,6 @@ import { getErrorMessage, obfuscate } from 'ontime-utils';
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import { isDocker } from '../../setup/environment.js';
|
||||
import { failEmptyObjects } from '../../utils/routerUtils.js';
|
||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||
import * as appState from '../../services/app-state-service/AppStateService.js';
|
||||
|
||||
@@ -25,9 +24,6 @@ export async function getSettings(_req: Request, res: Response<Settings>) {
|
||||
}
|
||||
|
||||
export async function postSettings(req: Request, res: Response<Settings | ErrorResponse>) {
|
||||
if (failEmptyObjects(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const settings = getDataProvider().getSettings();
|
||||
const editorKey = extractPin(req.body?.editorKey, settings.editorKey);
|
||||
@@ -35,13 +31,15 @@ export async function postSettings(req: Request, res: Response<Settings | ErrorR
|
||||
const serverPort = Number(req.body?.serverPort);
|
||||
//TODO: should this not be part of the validator?
|
||||
if (isNaN(serverPort)) {
|
||||
return res.status(400).send({ message: `Invalid value found for server port: ${req.body?.serverPort}` });
|
||||
res.status(400).send({ message: `Invalid value found for server port: ${req.body?.serverPort}` });
|
||||
return;
|
||||
}
|
||||
|
||||
const hasChangedPort = settings.serverPort !== serverPort;
|
||||
|
||||
if (isDocker && hasChangedPort) {
|
||||
return res.status(403).json({ message: 'Can`t change port when running inside docker' });
|
||||
res.status(403).json({ message: 'Can`t change port when running inside docker' });
|
||||
return;
|
||||
}
|
||||
|
||||
let timeFormat = settings.timeFormat;
|
||||
|
||||
@@ -1,31 +1,21 @@
|
||||
import { body, validationResult } from 'express-validator';
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/settings/welcomedialog
|
||||
*/
|
||||
export const validateWelcomeDialog = [
|
||||
body('show').isBoolean(),
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const validateWelcomeDialog = [body('show').isBoolean(), requestValidationFunction];
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/settings
|
||||
*/
|
||||
export const validateSettings = [
|
||||
body().notEmpty().withMessage('No object found in request'),
|
||||
body('editorKey').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }),
|
||||
body('operatorKey').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }),
|
||||
body('timeFormat').isString().isIn(['12', '24']),
|
||||
body('language').isString(),
|
||||
body('serverPort').isPort().optional(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -2,6 +2,7 @@ import { isImportMap } from 'ontime-utils';
|
||||
|
||||
import { body, param, validationResult } from 'express-validator';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
export const validateRequestConnection = [
|
||||
param('sheetId')
|
||||
@@ -14,27 +15,23 @@ export const validateRequestConnection = [
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
if (!errors.isEmpty()) {
|
||||
res.status(422).json({ errors: errors.array() });
|
||||
return;
|
||||
}
|
||||
// check that the file exists
|
||||
if (!req.file) {
|
||||
return res.status(422).json({ errors: 'File not found' });
|
||||
res.status(422).json({ errors: 'File not found' });
|
||||
return;
|
||||
}
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
export const validateSheetId = [
|
||||
param('sheetId').isString(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
export const validateSheetId = [param('sheetId').isString().trim().notEmpty(), requestValidationFunction];
|
||||
|
||||
export const validateSheetOptions = [
|
||||
param('sheetId').isString(),
|
||||
param('sheetId').isString().trim().notEmpty(),
|
||||
body('options')
|
||||
.isObject()
|
||||
.custom((content) => {
|
||||
@@ -42,9 +39,5 @@ export const validateSheetOptions = [
|
||||
return isValid;
|
||||
}),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import type { ErrorResponse, URLPreset } from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import { failIsNotArray } from '../../utils/routerUtils.js';
|
||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||
|
||||
export async function getUrlPresets(_req: Request, res: Response<URLPreset[]>) {
|
||||
const presets = getDataProvider().getUrlPresets();
|
||||
res.status(200).send(presets as URLPreset[]);
|
||||
}
|
||||
|
||||
export async function postUrlPresets(req: Request, res: Response<URLPreset[] | ErrorResponse>) {
|
||||
if (failIsNotArray(req.body, res)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const newPresets: URLPreset[] = req.body.map((preset: URLPreset) => ({
|
||||
enabled: preset.enabled,
|
||||
alias: preset.alias,
|
||||
pathAndParams: preset.pathAndParams,
|
||||
}));
|
||||
await getDataProvider().setUrlPresets(newPresets);
|
||||
res.status(200).send(newPresets);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(400).send({ message });
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,28 @@
|
||||
import express from 'express';
|
||||
import { getUrlPresets, postUrlPresets } from './urlPresets.controller.js';
|
||||
import type { Request, Response } from 'express';
|
||||
import type { ErrorResponse, URLPreset } from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
import { validateUrlPresets } from './urlPresets.validation.js';
|
||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', getUrlPresets);
|
||||
router.post('/', validateUrlPresets, postUrlPresets);
|
||||
router.get('/', (_req: Request, res: Response<URLPreset[]>) => {
|
||||
const presets = getDataProvider().getUrlPresets();
|
||||
res.status(200).send(presets as URLPreset[]);
|
||||
});
|
||||
|
||||
router.post('/', validateUrlPresets, async (req: Request, res: Response<URLPreset[] | ErrorResponse>) => {
|
||||
try {
|
||||
const newPresets: URLPreset[] = req.body.map((preset: URLPreset) => ({
|
||||
enabled: preset.enabled,
|
||||
alias: preset.alias,
|
||||
pathAndParams: preset.pathAndParams,
|
||||
}));
|
||||
await getDataProvider().setUrlPresets(newPresets);
|
||||
res.status(200).send(newPresets);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(400).send({ message });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { body, validationResult } from 'express-validator';
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { body } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
/**
|
||||
* validate array of URL preset objects
|
||||
*/
|
||||
export const validateUrlPresets = [
|
||||
body().isArray(),
|
||||
body().isArray().withMessage('No array found in request'),
|
||||
body('*.enabled').isBoolean(),
|
||||
body('*.alias').isString().trim(),
|
||||
body('*.pathAndParams').isString().trim(),
|
||||
body('*.alias').isString().trim().notEmpty(),
|
||||
body('*.pathAndParams').isString().trim().notEmpty(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { param, validationResult } from 'express-validator';
|
||||
|
||||
/**
|
||||
* Runs validation and any error are sent with status 422
|
||||
*/
|
||||
export function requestValidationFunction(req: Request, res: Response, next: NextFunction) {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
res.status(422).json({ errors: errors.array() });
|
||||
return;
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs validation and any error are sent with status 422
|
||||
* Also checks for the presses of a `file` in the body
|
||||
*/
|
||||
export function requestValidationFunctionWithFile(req: Request, res: Response, next: NextFunction) {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
res.status(422).json({ errors: errors.array() });
|
||||
return;
|
||||
}
|
||||
// check that the file exists
|
||||
if (!req.file) {
|
||||
res.status(422).json({ errors: 'File not found' });
|
||||
return;
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
export const paramsWithId = [param('id').isString().trim().notEmpty(), requestValidationFunction];
|
||||
@@ -1,20 +1,16 @@
|
||||
import { check, validationResult } from 'express-validator';
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { body } from 'express-validator';
|
||||
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
|
||||
|
||||
/**
|
||||
* @description Validates object for POST /ontime/views
|
||||
*/
|
||||
export const validateViewSettings = [
|
||||
check('dangerColor').isString().trim().withMessage('dangerColor value must be string'),
|
||||
check('endMessage').isString().trim().withMessage('endMessage value must be string'),
|
||||
check('freezeEnd').isBoolean().withMessage('freezeEnd value must be boolean'),
|
||||
check('normalColor').isString().trim().withMessage('normalColor value must be string'),
|
||||
check('overrideStyles').isBoolean().withMessage('overrideStyles value must be boolean'),
|
||||
check('warningColor').isString().trim().withMessage('warningColor value must be string'),
|
||||
body('dangerColor').isString().trim().withMessage('dangerColor value must be string'),
|
||||
body('endMessage').isString().trim().withMessage('endMessage value must be string'),
|
||||
body('freezeEnd').isBoolean().withMessage('freezeEnd value must be boolean'),
|
||||
body('normalColor').isString().trim().withMessage('normalColor value must be string'),
|
||||
body('overrideStyles').isBoolean().withMessage('overrideStyles value must be boolean'),
|
||||
body('warningColor').isString().trim().withMessage('warningColor value must be string'),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
requestValidationFunction,
|
||||
];
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import { LogOrigin } from 'ontime-types';
|
||||
import { ErrorResponse, LogOrigin } from 'ontime-types';
|
||||
|
||||
import express, { type Request, type Response } from 'express';
|
||||
|
||||
@@ -27,10 +27,11 @@ integrationRouter.get('/', (_req: Request, res: Response<{ message: string }>) =
|
||||
/**
|
||||
* All calls are sent to the dispatcher
|
||||
*/
|
||||
integrationRouter.get('/*', (req: Request, res: Response) => {
|
||||
integrationRouter.get('/*splat', (req: Request, res: Response<ErrorResponse | { payload: unknown }>) => {
|
||||
let action = req.path.substring(1);
|
||||
if (!action) {
|
||||
return res.status(400).json({ error: 'No action found' });
|
||||
res.status(400).json({ message: 'No action found' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -76,7 +76,7 @@ app.disable('x-powered-by');
|
||||
|
||||
// Implement middleware
|
||||
app.use(cors()); // setup cors for all routes
|
||||
app.options('*', cors()); // enable pre-flight cors
|
||||
app.options('*splat', cors()); // enable pre-flight cors
|
||||
|
||||
app.use(bodyParser);
|
||||
app.use(cookieParser());
|
||||
@@ -97,7 +97,7 @@ app.use(`${prefix}/user`, express.static(publicDir.userDir));
|
||||
|
||||
// Base route for static files
|
||||
app.use(`${prefix}`, authenticateAndRedirect, compressedStatic);
|
||||
app.use(`${prefix}/*`, authenticateAndRedirect, compressedStatic);
|
||||
app.use(`${prefix}/*splat`, authenticateAndRedirect, compressedStatic);
|
||||
|
||||
// Implement catch all
|
||||
app.use((_error, response) => {
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import type { Response } from 'express';
|
||||
|
||||
import { isEmptyObject } from './parserUtils.js';
|
||||
|
||||
/**
|
||||
* @description initial checks for an empty of malformed request object
|
||||
* @param obj
|
||||
* @param res
|
||||
*/
|
||||
export const failEmptyObjects = (obj: object, res: Response): boolean => {
|
||||
try {
|
||||
if (isEmptyObject(obj)) {
|
||||
res.status(400).send('No object found in request');
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description initial checks for an empty of malformed request object
|
||||
* @param obj
|
||||
* @param res
|
||||
*/
|
||||
export const failIsNotArray = (obj: object, res: Response): boolean => {
|
||||
try {
|
||||
if (!Array.isArray(obj)) {
|
||||
res.status(400).send('No array found in request');
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -1,9 +1,10 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
import { readFile } from 'fs/promises';
|
||||
import { readFile, unlink } from 'fs/promises';
|
||||
|
||||
const fileToUpload = 'e2e/tests/fixtures/e2e-test-db.json';
|
||||
const fileToDownload = 'e2e/tests/fixtures/tmp/e2e-test-db.json';
|
||||
const fileToDownload = 'e2e/tests/fixtures/tmp/';
|
||||
|
||||
test('project file upload', async ({ page }) => {
|
||||
await page.goto('http://localhost:4001/editor');
|
||||
@@ -35,30 +36,30 @@ test('project file upload', async ({ page }) => {
|
||||
await expect(thirdTitle).toHaveValue('Lithuania');
|
||||
});
|
||||
|
||||
//TODO: this works when testing locally, but not in github actions
|
||||
test.fixme('project file download', async ({ page }) => {
|
||||
await page.goto('http://localhost:4001/editor');
|
||||
|
||||
await page.getByRole('button', { name: 'toggle settings' }).click();
|
||||
await page.getByRole('button', { name: 'Manage projects' }).click();
|
||||
|
||||
// workaround to download
|
||||
// https://playwright.dev/docs/api/class-download
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
await page.goto('http://localhost:4001/editor/?settings=project__manage');
|
||||
|
||||
await page
|
||||
.getByRole('row', { name: /.*currently loaded/i })
|
||||
.getByLabel('Options')
|
||||
.click();
|
||||
// workaround to download
|
||||
// https://playwright.dev/docs/api/class-download
|
||||
const downloadPromise = page.waitForEvent('download', { timeout: 10_000 });
|
||||
await page.getByRole('menuitem', { name: 'Download' }).click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
|
||||
// Wait for the download process to complete and save the downloaded file somewhere.
|
||||
await download.saveAs(fileToDownload);
|
||||
const uniqFileToDownload = fileToDownload + randomUUID() + '.json';
|
||||
await download.saveAs(uniqFileToDownload);
|
||||
expect(download.failure()).toMatchObject({});
|
||||
|
||||
const original = JSON.parse(await readFile(fileToUpload, { encoding: 'utf-8' }));
|
||||
const fromServer = JSON.parse(await readFile(fileToDownload, { encoding: 'utf-8' }));
|
||||
const fromServer = JSON.parse(await readFile(uniqFileToDownload, { encoding: 'utf-8' }));
|
||||
|
||||
await unlink(uniqFileToDownload);
|
||||
|
||||
// when a file is parsed, the server will write the version number to the project file
|
||||
original.settings.version = 'not-important';
|
||||
|
||||
Vendored
+22
-3
@@ -21,6 +21,24 @@
|
||||
"bab4a",
|
||||
"d3eb1"
|
||||
],
|
||||
"flatOrder": [
|
||||
"32d31",
|
||||
"21cd2",
|
||||
"0b371",
|
||||
"3cd28",
|
||||
"e457f",
|
||||
"01e85",
|
||||
"1c420",
|
||||
"b7737",
|
||||
"d3a80",
|
||||
"8276c",
|
||||
"2340b",
|
||||
"cb90b",
|
||||
"503c4",
|
||||
"5e965",
|
||||
"bab4a",
|
||||
"d3eb1"
|
||||
],
|
||||
"entries": {
|
||||
"32d31": {
|
||||
"type": "event",
|
||||
@@ -469,7 +487,8 @@
|
||||
"publicInfo": "Rehearsal Schedule - Turin 2022",
|
||||
"backstageUrl": "www.github.com/cpvalente/ontime",
|
||||
"backstageInfo": "Rehearsal Schedule - Turin 2022\nAll performers to wear full costumes for 1st rehearsal",
|
||||
"projectLogo": null
|
||||
"projectLogo": null,
|
||||
"custom": []
|
||||
},
|
||||
"settings": {
|
||||
"app": "ontime",
|
||||
@@ -489,12 +508,12 @@
|
||||
"warningColor": "#FFAB33"
|
||||
},
|
||||
"customFields": {
|
||||
"song": {
|
||||
"Song": {
|
||||
"label": "Song",
|
||||
"type": "string",
|
||||
"colour": "#339E4E"
|
||||
},
|
||||
"artist": {
|
||||
"Artist": {
|
||||
"label": "Artist",
|
||||
"type": "string",
|
||||
"colour": "#3E75E8"
|
||||
|
||||
Generated
+202
-236
@@ -289,26 +289,26 @@ importers:
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.5(encoding@0.1.13)
|
||||
cookie:
|
||||
specifier: ^1.0.2
|
||||
specifier: 1.0.2
|
||||
version: 1.0.2
|
||||
cookie-parser:
|
||||
specifier: ^1.4.7
|
||||
specifier: 1.4.7
|
||||
version: 1.4.7
|
||||
cors:
|
||||
specifier: ^2.8.5
|
||||
specifier: 2.8.5
|
||||
version: 2.8.5
|
||||
dotenv:
|
||||
specifier: ^16.0.1
|
||||
version: 16.3.1
|
||||
express:
|
||||
specifier: ^4.21.1
|
||||
version: 4.21.2
|
||||
specifier: 5.1.0
|
||||
version: 5.1.0
|
||||
express-static-gzip:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
specifier: 3.0.0
|
||||
version: 3.0.0
|
||||
express-validator:
|
||||
specifier: ^7.2.0
|
||||
version: 7.2.0
|
||||
specifier: 7.2.1
|
||||
version: 7.2.1
|
||||
fast-equals:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1
|
||||
@@ -322,8 +322,8 @@ importers:
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1
|
||||
multer:
|
||||
specifier: ^1.4.5-lts.1
|
||||
version: 1.4.5-lts.1
|
||||
specifier: 2.0.1
|
||||
version: 2.0.1
|
||||
ontime-utils:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/utils
|
||||
@@ -344,17 +344,17 @@ importers:
|
||||
version: 0.18.5
|
||||
devDependencies:
|
||||
'@types/cookie-parser':
|
||||
specifier: ^1.4.8
|
||||
version: 1.4.8(@types/express@4.17.17)
|
||||
specifier: 1.4.9
|
||||
version: 1.4.9(@types/express@5.0.3)
|
||||
'@types/cors':
|
||||
specifier: ^2.8.17
|
||||
version: 2.8.17
|
||||
specifier: 2.8.19
|
||||
version: 2.8.19
|
||||
'@types/express':
|
||||
specifier: ^4.17.17
|
||||
version: 4.17.17
|
||||
specifier: 5.0.3
|
||||
version: 5.0.3
|
||||
'@types/multer':
|
||||
specifier: ^1.4.11
|
||||
version: 1.4.11
|
||||
specifier: 1.4.13
|
||||
version: 1.4.13
|
||||
'@types/node':
|
||||
specifier: 'catalog:'
|
||||
version: 22.15.26
|
||||
@@ -2207,13 +2207,13 @@ packages:
|
||||
'@types/connect@3.4.35':
|
||||
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
|
||||
|
||||
'@types/cookie-parser@1.4.8':
|
||||
resolution: {integrity: sha512-l37JqFrOJ9yQfRQkljb41l0xVphc7kg5JTjjr+pLRZ0IyZ49V4BQ8vbF4Ut2C2e+WH4al3xD3ZwYwIUfnbT4NQ==}
|
||||
'@types/cookie-parser@1.4.9':
|
||||
resolution: {integrity: sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==}
|
||||
peerDependencies:
|
||||
'@types/express': '*'
|
||||
|
||||
'@types/cors@2.8.17':
|
||||
resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==}
|
||||
'@types/cors@2.8.19':
|
||||
resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
@@ -2227,11 +2227,11 @@ packages:
|
||||
'@types/estree@1.0.7':
|
||||
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
|
||||
|
||||
'@types/express-serve-static-core@4.17.33':
|
||||
resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==}
|
||||
'@types/express-serve-static-core@5.0.6':
|
||||
resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==}
|
||||
|
||||
'@types/express@4.17.17':
|
||||
resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==}
|
||||
'@types/express@5.0.3':
|
||||
resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==}
|
||||
|
||||
'@types/fs-extra@9.0.13':
|
||||
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
|
||||
@@ -2251,14 +2251,17 @@ packages:
|
||||
'@types/lodash@4.14.191':
|
||||
resolution: {integrity: sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==}
|
||||
|
||||
'@types/mime@1.3.5':
|
||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||
|
||||
'@types/mime@3.0.1':
|
||||
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
||||
|
||||
'@types/ms@0.7.34':
|
||||
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
|
||||
|
||||
'@types/multer@1.4.11':
|
||||
resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==}
|
||||
'@types/multer@1.4.13':
|
||||
resolution: {integrity: sha512-bhhdtPw7JqCiEfC9Jimx5LqX9BDIPJEh2q/fQ4bqbBPtyEZYr3cvF22NwG0DmPZNYA0CAf2CnqDB4KIGGpJcaw==}
|
||||
|
||||
'@types/node@22.15.26':
|
||||
resolution: {integrity: sha512-lgISkNrqdQ5DAzjBhnDNGKDuXDNo7/1V4FhNzsKREhWLZTOELQAptuAnJMzHtUl1qyEBBy9lNBKQ9WjyiSloTw==}
|
||||
@@ -2296,6 +2299,9 @@ packages:
|
||||
'@types/semver@7.5.5':
|
||||
resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==}
|
||||
|
||||
'@types/send@0.17.5':
|
||||
resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==}
|
||||
|
||||
'@types/serve-static@1.15.0':
|
||||
resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==}
|
||||
|
||||
@@ -2451,8 +2457,8 @@ packages:
|
||||
abbrev@1.1.1:
|
||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||
|
||||
accepts@1.3.8:
|
||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||
accepts@2.0.0:
|
||||
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
acorn-globals@7.0.1:
|
||||
@@ -2571,9 +2577,6 @@ packages:
|
||||
resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
array-flatten@1.1.1:
|
||||
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
|
||||
|
||||
array-includes@3.1.6:
|
||||
resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2651,9 +2654,9 @@ packages:
|
||||
bluebird@3.7.2:
|
||||
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
|
||||
|
||||
body-parser@1.20.3:
|
||||
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
body-parser@2.2.0:
|
||||
resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
boolean@3.2.0:
|
||||
resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
|
||||
@@ -2741,10 +2744,6 @@ packages:
|
||||
resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2881,9 +2880,9 @@ packages:
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
concat-stream@1.6.2:
|
||||
resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==}
|
||||
engines: {'0': node >= 0.8}
|
||||
concat-stream@2.0.0:
|
||||
resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==}
|
||||
engines: {'0': node >= 6.0}
|
||||
|
||||
config-file-ts@0.2.4:
|
||||
resolution: {integrity: sha512-cKSW0BfrSaAUnxpgvpXPLaaW/umg4bqg4k3GO1JqlRfpx+d5W0GDXznCMkWotJQek5Mmz1MJVChQnz3IVaeMZQ==}
|
||||
@@ -2891,8 +2890,8 @@ packages:
|
||||
config-file-ts@0.2.8-rc1:
|
||||
resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==}
|
||||
|
||||
content-disposition@0.5.4:
|
||||
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
|
||||
content-disposition@1.0.0:
|
||||
resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
content-type@1.0.5:
|
||||
@@ -2912,9 +2911,9 @@ packages:
|
||||
cookie-signature@1.0.6:
|
||||
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
|
||||
|
||||
cookie@0.7.1:
|
||||
resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
|
||||
engines: {node: '>= 0.6'}
|
||||
cookie-signature@1.2.2:
|
||||
resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
|
||||
engines: {node: '>=6.6.0'}
|
||||
|
||||
cookie@0.7.2:
|
||||
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
|
||||
@@ -2998,14 +2997,6 @@ packages:
|
||||
resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
debug@2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.3.7:
|
||||
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@@ -3065,10 +3056,6 @@ packages:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
destroy@1.2.0:
|
||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
|
||||
detect-libc@2.0.4:
|
||||
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -3182,10 +3169,6 @@ packages:
|
||||
emoji-regex@9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
||||
encodeurl@1.0.2:
|
||||
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
encodeurl@2.0.0:
|
||||
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -3225,10 +3208,6 @@ packages:
|
||||
es-module-lexer@1.7.0:
|
||||
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
|
||||
|
||||
es-object-atoms@1.0.0:
|
||||
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3410,16 +3389,16 @@ packages:
|
||||
exponential-backoff@3.1.2:
|
||||
resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==}
|
||||
|
||||
express-static-gzip@2.2.0:
|
||||
resolution: {integrity: sha512-4ZQ0pHX0CAauxmzry2/8XFLM6aZA4NBvg9QezSlsEO1zLnl7vMFa48/WIcjzdfOiEUS4S1npPPKP2NHHYAp6qg==}
|
||||
express-static-gzip@3.0.0:
|
||||
resolution: {integrity: sha512-36O10S0asHl3QojOBQQ0ZjXNtElmhgPS6erSUCCZymXkB/CK1mnGqOj4BTJN+FYRDIzVFnzo3wLFCZJvAk6rQQ==}
|
||||
|
||||
express-validator@7.2.0:
|
||||
resolution: {integrity: sha512-I2ByKD8panjtr8Y05l21Wph9xk7kk64UMyvJCl/fFM/3CTJq8isXYPLeKW/aZBCdb/LYNv63PwhY8khw8VWocA==}
|
||||
express-validator@7.2.1:
|
||||
resolution: {integrity: sha512-CjNE6aakfpuwGaHQZ3m8ltCG2Qvivd7RHtVMS/6nVxOM7xVGqr4bhflsm4+N5FP5zI7Zxp+Hae+9RE+o8e3ZOQ==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
|
||||
express@4.21.2:
|
||||
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
express@5.1.0:
|
||||
resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
extend@3.0.2:
|
||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||
@@ -3478,8 +3457,8 @@ packages:
|
||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
finalhandler@1.3.1:
|
||||
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
|
||||
finalhandler@2.1.0:
|
||||
resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
find-root@1.1.0:
|
||||
@@ -3546,9 +3525,9 @@ packages:
|
||||
framesync@6.1.2:
|
||||
resolution: {integrity: sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==}
|
||||
|
||||
fresh@0.5.2:
|
||||
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
|
||||
engines: {node: '>= 0.6'}
|
||||
fresh@2.0.0:
|
||||
resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
fs-constants@1.0.0:
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
@@ -3615,10 +3594,6 @@ packages:
|
||||
get-intrinsic@1.2.2:
|
||||
resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
|
||||
|
||||
get-intrinsic@1.2.6:
|
||||
resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-intrinsic@1.2.7:
|
||||
resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3827,10 +3802,6 @@ packages:
|
||||
engines: {node: ^8.11.2 || >=10}
|
||||
os: [darwin]
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -3959,6 +3930,9 @@ packages:
|
||||
is-potential-custom-element-name@1.0.1:
|
||||
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
|
||||
|
||||
is-promise@4.0.0:
|
||||
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
|
||||
|
||||
is-regex@1.1.4:
|
||||
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -4198,17 +4172,18 @@ packages:
|
||||
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
merge-descriptors@1.0.3:
|
||||
resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
|
||||
media-typer@1.1.0:
|
||||
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
merge-descriptors@2.0.0:
|
||||
resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
methods@1.1.2:
|
||||
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
micromatch@4.0.5:
|
||||
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
|
||||
engines: {node: '>=8.6'}
|
||||
@@ -4217,14 +4192,17 @@ packages:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-db@1.54.0:
|
||||
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime@1.6.0:
|
||||
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
mime-types@3.0.1:
|
||||
resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime@2.6.0:
|
||||
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
|
||||
@@ -4322,15 +4300,12 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
multer@1.4.5-lts.1:
|
||||
resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
multer@2.0.1:
|
||||
resolution: {integrity: sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==}
|
||||
engines: {node: '>= 10.16.0'}
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
@@ -4349,6 +4324,10 @@ packages:
|
||||
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
negotiator@1.0.0:
|
||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
no-case@3.0.4:
|
||||
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
|
||||
|
||||
@@ -4519,8 +4498,9 @@ packages:
|
||||
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
|
||||
engines: {node: '>=16 || 14 >=14.18'}
|
||||
|
||||
path-to-regexp@0.1.12:
|
||||
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
|
||||
path-to-regexp@8.2.0:
|
||||
resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
path-type@4.0.0:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
@@ -4639,8 +4619,8 @@ packages:
|
||||
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
qs@6.13.0:
|
||||
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
|
||||
qs@6.14.0:
|
||||
resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
querystringify@2.2.0:
|
||||
@@ -4657,8 +4637,8 @@ packages:
|
||||
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
raw-body@2.5.2:
|
||||
resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
|
||||
raw-body@3.0.0:
|
||||
resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
react-clientside-effect@1.2.6:
|
||||
@@ -4867,6 +4847,10 @@ packages:
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
router@2.2.0:
|
||||
resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
@@ -4919,17 +4903,17 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
send@0.19.0:
|
||||
resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
send@1.2.0:
|
||||
resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
serialize-error@7.0.1:
|
||||
resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
serve-static@1.16.2:
|
||||
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
serve-static@2.2.0:
|
||||
resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
server-timing@3.3.3:
|
||||
resolution: {integrity: sha512-TP0xWAca4oM8H/PSdeaGgp2qm+HrZ2cWCRcMXS2t500a7Wum/hSojlpTW43VZsIUSVNlKPFGDknH34IqF+mbBg==}
|
||||
@@ -5313,6 +5297,10 @@ packages:
|
||||
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
type-is@2.0.1:
|
||||
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
typed-array-length@1.0.4:
|
||||
resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
|
||||
|
||||
@@ -5414,10 +5402,6 @@ packages:
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
utils-merge@1.0.1:
|
||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
uuid@9.0.1:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
@@ -7600,11 +7584,11 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 22.15.26
|
||||
|
||||
'@types/cookie-parser@1.4.8(@types/express@4.17.17)':
|
||||
'@types/cookie-parser@1.4.9(@types/express@5.0.3)':
|
||||
dependencies:
|
||||
'@types/express': 4.17.17
|
||||
'@types/express': 5.0.3
|
||||
|
||||
'@types/cors@2.8.17':
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 22.15.26
|
||||
|
||||
@@ -7618,17 +7602,17 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.7': {}
|
||||
|
||||
'@types/express-serve-static-core@4.17.33':
|
||||
'@types/express-serve-static-core@5.0.6':
|
||||
dependencies:
|
||||
'@types/node': 22.15.26
|
||||
'@types/qs': 6.9.7
|
||||
'@types/range-parser': 1.2.4
|
||||
'@types/send': 0.17.5
|
||||
|
||||
'@types/express@4.17.17':
|
||||
'@types/express@5.0.3':
|
||||
dependencies:
|
||||
'@types/body-parser': 1.19.2
|
||||
'@types/express-serve-static-core': 4.17.33
|
||||
'@types/qs': 6.9.7
|
||||
'@types/express-serve-static-core': 5.0.6
|
||||
'@types/serve-static': 1.15.0
|
||||
|
||||
'@types/fs-extra@9.0.13':
|
||||
@@ -7649,13 +7633,15 @@ snapshots:
|
||||
|
||||
'@types/lodash@4.14.191': {}
|
||||
|
||||
'@types/mime@1.3.5': {}
|
||||
|
||||
'@types/mime@3.0.1': {}
|
||||
|
||||
'@types/ms@0.7.34': {}
|
||||
|
||||
'@types/multer@1.4.11':
|
||||
'@types/multer@1.4.13':
|
||||
dependencies:
|
||||
'@types/express': 4.17.17
|
||||
'@types/express': 5.0.3
|
||||
|
||||
'@types/node@22.15.26':
|
||||
dependencies:
|
||||
@@ -7695,6 +7681,11 @@ snapshots:
|
||||
|
||||
'@types/semver@7.5.5': {}
|
||||
|
||||
'@types/send@0.17.5':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 22.15.26
|
||||
|
||||
'@types/serve-static@1.15.0':
|
||||
dependencies:
|
||||
'@types/mime': 3.0.1
|
||||
@@ -7904,10 +7895,10 @@ snapshots:
|
||||
|
||||
abbrev@1.1.1: {}
|
||||
|
||||
accepts@1.3.8:
|
||||
accepts@2.0.0:
|
||||
dependencies:
|
||||
mime-types: 2.1.35
|
||||
negotiator: 0.6.3
|
||||
mime-types: 3.0.1
|
||||
negotiator: 1.0.0
|
||||
|
||||
acorn-globals@7.0.1:
|
||||
dependencies:
|
||||
@@ -8104,8 +8095,6 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.6.2
|
||||
|
||||
array-flatten@1.1.1: {}
|
||||
|
||||
array-includes@3.1.6:
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -8185,20 +8174,17 @@ snapshots:
|
||||
|
||||
bluebird@3.7.2: {}
|
||||
|
||||
body-parser@1.20.3:
|
||||
body-parser@2.2.0:
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
content-type: 1.0.5
|
||||
debug: 2.6.9
|
||||
depd: 2.0.0
|
||||
destroy: 1.2.0
|
||||
debug: 4.4.1
|
||||
http-errors: 2.0.0
|
||||
iconv-lite: 0.4.24
|
||||
iconv-lite: 0.6.3
|
||||
on-finished: 2.4.1
|
||||
qs: 6.13.0
|
||||
raw-body: 2.5.2
|
||||
type-is: 1.6.18
|
||||
unpipe: 1.0.0
|
||||
qs: 6.14.0
|
||||
raw-body: 3.0.0
|
||||
type-is: 2.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -8357,11 +8343,6 @@ snapshots:
|
||||
normalize-url: 6.1.0
|
||||
responselike: 2.0.1
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@@ -8374,7 +8355,7 @@ snapshots:
|
||||
|
||||
call-bound@1.0.3:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
get-intrinsic: 1.2.7
|
||||
|
||||
callsites@3.1.0: {}
|
||||
@@ -8500,11 +8481,11 @@ snapshots:
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
concat-stream@1.6.2:
|
||||
concat-stream@2.0.0:
|
||||
dependencies:
|
||||
buffer-from: 1.1.2
|
||||
inherits: 2.0.4
|
||||
readable-stream: 2.3.8
|
||||
readable-stream: 3.6.2
|
||||
typedarray: 0.0.6
|
||||
|
||||
config-file-ts@0.2.4:
|
||||
@@ -8517,7 +8498,7 @@ snapshots:
|
||||
glob: 10.4.5
|
||||
typescript: 5.5.3
|
||||
|
||||
content-disposition@0.5.4:
|
||||
content-disposition@1.0.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
@@ -8534,7 +8515,7 @@ snapshots:
|
||||
|
||||
cookie-signature@1.0.6: {}
|
||||
|
||||
cookie@0.7.1: {}
|
||||
cookie-signature@1.2.2: {}
|
||||
|
||||
cookie@0.7.2: {}
|
||||
|
||||
@@ -8625,10 +8606,6 @@ snapshots:
|
||||
whatwg-url: 11.0.0
|
||||
optional: true
|
||||
|
||||
debug@2.6.9:
|
||||
dependencies:
|
||||
ms: 2.0.0
|
||||
|
||||
debug@4.3.7:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
@@ -8672,8 +8649,6 @@ snapshots:
|
||||
|
||||
depd@2.0.0: {}
|
||||
|
||||
destroy@1.2.0: {}
|
||||
|
||||
detect-libc@2.0.4: {}
|
||||
|
||||
detect-node-es@1.1.0: {}
|
||||
@@ -8838,8 +8813,6 @@ snapshots:
|
||||
|
||||
emoji-regex@9.2.2: {}
|
||||
|
||||
encodeurl@1.0.2: {}
|
||||
|
||||
encodeurl@2.0.0: {}
|
||||
|
||||
encoding@0.1.13:
|
||||
@@ -8903,10 +8876,6 @@ snapshots:
|
||||
|
||||
es-module-lexer@1.7.0: {}
|
||||
|
||||
es-object-atoms@1.0.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@@ -9179,50 +9148,47 @@ snapshots:
|
||||
|
||||
exponential-backoff@3.1.2: {}
|
||||
|
||||
express-static-gzip@2.2.0:
|
||||
express-static-gzip@3.0.0:
|
||||
dependencies:
|
||||
mime-types: 3.0.1
|
||||
parseurl: 1.3.3
|
||||
serve-static: 1.16.2
|
||||
serve-static: 2.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
express-validator@7.2.0:
|
||||
express-validator@7.2.1:
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
validator: 13.12.0
|
||||
|
||||
express@4.21.2:
|
||||
express@5.1.0:
|
||||
dependencies:
|
||||
accepts: 1.3.8
|
||||
array-flatten: 1.1.1
|
||||
body-parser: 1.20.3
|
||||
content-disposition: 0.5.4
|
||||
accepts: 2.0.0
|
||||
body-parser: 2.2.0
|
||||
content-disposition: 1.0.0
|
||||
content-type: 1.0.5
|
||||
cookie: 0.7.1
|
||||
cookie-signature: 1.0.6
|
||||
debug: 2.6.9
|
||||
depd: 2.0.0
|
||||
cookie: 0.7.2
|
||||
cookie-signature: 1.2.2
|
||||
debug: 4.4.1
|
||||
encodeurl: 2.0.0
|
||||
escape-html: 1.0.3
|
||||
etag: 1.8.1
|
||||
finalhandler: 1.3.1
|
||||
fresh: 0.5.2
|
||||
finalhandler: 2.1.0
|
||||
fresh: 2.0.0
|
||||
http-errors: 2.0.0
|
||||
merge-descriptors: 1.0.3
|
||||
methods: 1.1.2
|
||||
merge-descriptors: 2.0.0
|
||||
mime-types: 3.0.1
|
||||
on-finished: 2.4.1
|
||||
once: 1.4.0
|
||||
parseurl: 1.3.3
|
||||
path-to-regexp: 0.1.12
|
||||
proxy-addr: 2.0.7
|
||||
qs: 6.13.0
|
||||
qs: 6.14.0
|
||||
range-parser: 1.2.1
|
||||
safe-buffer: 5.2.1
|
||||
send: 0.19.0
|
||||
serve-static: 1.16.2
|
||||
setprototypeof: 1.2.0
|
||||
router: 2.2.0
|
||||
send: 1.2.0
|
||||
serve-static: 2.2.0
|
||||
statuses: 2.0.1
|
||||
type-is: 1.6.18
|
||||
utils-merge: 1.0.1
|
||||
type-is: 2.0.1
|
||||
vary: 1.1.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -9284,15 +9250,14 @@ snapshots:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
finalhandler@1.3.1:
|
||||
finalhandler@2.1.0:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
debug: 4.4.1
|
||||
encodeurl: 2.0.0
|
||||
escape-html: 1.0.3
|
||||
on-finished: 2.4.1
|
||||
parseurl: 1.3.3
|
||||
statuses: 2.0.1
|
||||
unpipe: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -9351,7 +9316,7 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.4.0
|
||||
|
||||
fresh@0.5.2: {}
|
||||
fresh@2.0.0: {}
|
||||
|
||||
fs-constants@1.0.0: {}
|
||||
|
||||
@@ -9432,19 +9397,6 @@ snapshots:
|
||||
has-symbols: 1.0.3
|
||||
hasown: 2.0.0
|
||||
|
||||
get-intrinsic@1.2.6:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
dunder-proto: 1.0.1
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.0.0
|
||||
function-bind: 1.1.2
|
||||
gopd: 1.2.0
|
||||
has-symbols: 1.1.0
|
||||
hasown: 2.0.2
|
||||
math-intrinsics: 1.1.0
|
||||
|
||||
get-intrinsic@1.2.7:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -9738,10 +9690,6 @@ snapshots:
|
||||
node-addon-api: 1.7.2
|
||||
optional: true
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
@@ -9851,6 +9799,8 @@ snapshots:
|
||||
is-potential-custom-element-name@1.0.1:
|
||||
optional: true
|
||||
|
||||
is-promise@4.0.0: {}
|
||||
|
||||
is-regex@1.1.4:
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -10117,12 +10067,12 @@ snapshots:
|
||||
|
||||
media-typer@0.3.0: {}
|
||||
|
||||
merge-descriptors@1.0.3: {}
|
||||
media-typer@1.1.0: {}
|
||||
|
||||
merge-descriptors@2.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
methods@1.1.2: {}
|
||||
|
||||
micromatch@4.0.5:
|
||||
dependencies:
|
||||
braces: 3.0.2
|
||||
@@ -10130,11 +10080,15 @@ snapshots:
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-db@1.54.0: {}
|
||||
|
||||
mime-types@2.1.35:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
|
||||
mime@1.6.0: {}
|
||||
mime-types@3.0.1:
|
||||
dependencies:
|
||||
mime-db: 1.54.0
|
||||
|
||||
mime@2.6.0: {}
|
||||
|
||||
@@ -10215,15 +10169,13 @@ snapshots:
|
||||
|
||||
mkdirp@1.0.4: {}
|
||||
|
||||
ms@2.0.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
multer@1.4.5-lts.1:
|
||||
multer@2.0.1:
|
||||
dependencies:
|
||||
append-field: 1.0.0
|
||||
busboy: 1.6.0
|
||||
concat-stream: 1.6.2
|
||||
concat-stream: 2.0.0
|
||||
mkdirp: 0.5.6
|
||||
object-assign: 4.1.1
|
||||
type-is: 1.6.18
|
||||
@@ -10237,6 +10189,8 @@ snapshots:
|
||||
|
||||
negotiator@0.6.3: {}
|
||||
|
||||
negotiator@1.0.0: {}
|
||||
|
||||
no-case@3.0.4:
|
||||
dependencies:
|
||||
lower-case: 2.0.2
|
||||
@@ -10405,7 +10359,7 @@ snapshots:
|
||||
lru-cache: 10.4.3
|
||||
minipass: 7.1.2
|
||||
|
||||
path-to-regexp@0.1.12: {}
|
||||
path-to-regexp@8.2.0: {}
|
||||
|
||||
path-type@4.0.0: {}
|
||||
|
||||
@@ -10499,7 +10453,7 @@ snapshots:
|
||||
dependencies:
|
||||
side-channel: 1.0.4
|
||||
|
||||
qs@6.13.0:
|
||||
qs@6.14.0:
|
||||
dependencies:
|
||||
side-channel: 1.1.0
|
||||
|
||||
@@ -10512,11 +10466,11 @@ snapshots:
|
||||
|
||||
range-parser@1.2.1: {}
|
||||
|
||||
raw-body@2.5.2:
|
||||
raw-body@3.0.0:
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
http-errors: 2.0.0
|
||||
iconv-lite: 0.4.24
|
||||
iconv-lite: 0.6.3
|
||||
unpipe: 1.0.0
|
||||
|
||||
react-clientside-effect@1.2.6(react@18.3.1):
|
||||
@@ -10753,6 +10707,16 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc': 4.41.1
|
||||
fsevents: 2.3.3
|
||||
|
||||
router@2.2.0:
|
||||
dependencies:
|
||||
debug: 4.4.1
|
||||
depd: 2.0.0
|
||||
is-promise: 4.0.0
|
||||
parseurl: 1.3.3
|
||||
path-to-regexp: 8.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
run-parallel@1.2.0:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
@@ -10803,17 +10767,15 @@ snapshots:
|
||||
|
||||
semver@7.6.2: {}
|
||||
|
||||
send@0.19.0:
|
||||
send@1.2.0:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
depd: 2.0.0
|
||||
destroy: 1.2.0
|
||||
encodeurl: 1.0.2
|
||||
debug: 4.4.1
|
||||
encodeurl: 2.0.0
|
||||
escape-html: 1.0.3
|
||||
etag: 1.8.1
|
||||
fresh: 0.5.2
|
||||
fresh: 2.0.0
|
||||
http-errors: 2.0.0
|
||||
mime: 1.6.0
|
||||
mime-types: 3.0.1
|
||||
ms: 2.1.3
|
||||
on-finished: 2.4.1
|
||||
range-parser: 1.2.1
|
||||
@@ -10826,12 +10788,12 @@ snapshots:
|
||||
type-fest: 0.13.1
|
||||
optional: true
|
||||
|
||||
serve-static@1.16.2:
|
||||
serve-static@2.2.0:
|
||||
dependencies:
|
||||
encodeurl: 2.0.0
|
||||
escape-html: 1.0.3
|
||||
parseurl: 1.3.3
|
||||
send: 0.19.0
|
||||
send: 1.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -10868,14 +10830,14 @@ snapshots:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.6
|
||||
get-intrinsic: 1.2.7
|
||||
object-inspect: 1.13.3
|
||||
|
||||
side-channel-weakmap@1.0.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.6
|
||||
get-intrinsic: 1.2.7
|
||||
object-inspect: 1.13.3
|
||||
side-channel-map: 1.0.1
|
||||
|
||||
@@ -11218,6 +11180,12 @@ snapshots:
|
||||
media-typer: 0.3.0
|
||||
mime-types: 2.1.35
|
||||
|
||||
type-is@2.0.1:
|
||||
dependencies:
|
||||
content-type: 1.0.5
|
||||
media-typer: 1.1.0
|
||||
mime-types: 3.0.1
|
||||
|
||||
typed-array-length@1.0.4:
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -11311,8 +11279,6 @@ snapshots:
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
utils-merge@1.0.1: {}
|
||||
|
||||
uuid@9.0.1: {}
|
||||
|
||||
validator@13.12.0: {}
|
||||
|
||||
Reference in New Issue
Block a user