mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-10 00:29:41 +00:00
Validate project filename (#1046)
This commit is contained in:
committed by
GitHub
parent
edb48a2fc7
commit
c2fa115946
@@ -11,8 +11,8 @@ const dbPath = `${apiEntryUrl}/db`;
|
|||||||
/**
|
/**
|
||||||
* HTTP request to the current DB
|
* HTTP request to the current DB
|
||||||
*/
|
*/
|
||||||
async function getDb(fileName?: string): Promise<AxiosResponse<DatabaseModel>> {
|
async function getDb(filename: string): Promise<AxiosResponse<DatabaseModel>> {
|
||||||
return axios.post(`${dbPath}/download/`, { fileName });
|
return axios.post(`${dbPath}/download/`, { filename });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,7 +123,7 @@ export async function renameProject(filename: string, newFilename: string): Prom
|
|||||||
const url = `${dbPath}/${filename}/rename`;
|
const url = `${dbPath}/${filename}/rename`;
|
||||||
const decodedUrl = decodeURIComponent(url);
|
const decodedUrl = decodeURIComponent(url);
|
||||||
const res = await axios.put(decodedUrl, {
|
const res = await axios.put(decodedUrl, {
|
||||||
newFilename,
|
filename: newFilename,
|
||||||
});
|
});
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export default function ProjectCreateForm(props: ProjectCreateFromProps) {
|
|||||||
const handleSubmitCreate = async (values: ProjectCreateFormValues) => {
|
const handleSubmitCreate = async (values: ProjectCreateFormValues) => {
|
||||||
try {
|
try {
|
||||||
setError(null);
|
setError(null);
|
||||||
const filename = values.title?.trim();
|
|
||||||
|
const filename = values.title ?? 'untitled';
|
||||||
|
|
||||||
await createProject({
|
await createProject({
|
||||||
...values,
|
...values,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"node-osc": "^9.0.2",
|
"node-osc": "^9.0.2",
|
||||||
"node-xlsx": "^0.23.0",
|
"node-xlsx": "^0.23.0",
|
||||||
"ontime-utils": "workspace:*",
|
"ontime-utils": "workspace:*",
|
||||||
|
"sanitize-filename": "^1.6.3",
|
||||||
"steno": "^3.1.0",
|
"steno": "^3.1.0",
|
||||||
"ts-essentials": "^9.4.1",
|
"ts-essentials": "^9.4.1",
|
||||||
"ws": "^8.13.0"
|
"ws": "^8.13.0"
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import { failEmptyObjects } from '../../utils/routerUtils.js';
|
|||||||
import { resolveDbDirectory, resolveProjectsDirectory } from '../../setup/index.js';
|
import { resolveDbDirectory, resolveProjectsDirectory } from '../../setup/index.js';
|
||||||
|
|
||||||
import * as projectService from '../../services/project-service/ProjectService.js';
|
import * as projectService from '../../services/project-service/ProjectService.js';
|
||||||
import { ensureJsonExtension } from '../../utils/fileManagement.js';
|
|
||||||
import { generateUniqueFileName } from '../../utils/generateUniqueFilename.js';
|
import { generateUniqueFileName } from '../../utils/generateUniqueFilename.js';
|
||||||
import { appStateService } from '../../services/app-state-service/AppStateService.js';
|
import { appStateService } from '../../services/app-state-service/AppStateService.js';
|
||||||
import { oscIntegration } from '../../services/integration-service/OscIntegration.js';
|
import { oscIntegration } from '../../services/integration-service/OscIntegration.js';
|
||||||
@@ -54,8 +53,7 @@ export async function patchPartialProjectFile(req: Request, res: Response<Databa
|
|||||||
*/
|
*/
|
||||||
export async function createProjectFile(req: Request, res: Response<{ filename: string } | ErrorResponse>) {
|
export async function createProjectFile(req: Request, res: Response<{ filename: string } | ErrorResponse>) {
|
||||||
try {
|
try {
|
||||||
const originalFilename = ensureJsonExtension(req.body.title || 'Untitled');
|
const filename = generateUniqueFileName(resolveProjectsDirectory, req.body.filename);
|
||||||
const filename = generateUniqueFileName(resolveProjectsDirectory, originalFilename);
|
|
||||||
const errors = projectService.validateProjectFiles({ newFilename: filename });
|
const errors = projectService.validateProjectFiles({ newFilename: filename });
|
||||||
|
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
@@ -71,7 +69,7 @@ export async function createProjectFile(req: Request, res: Response<{ filename:
|
|||||||
backstageInfo: req.body?.backstageInfo ?? '',
|
backstageInfo: req.body?.backstageInfo ?? '',
|
||||||
};
|
};
|
||||||
|
|
||||||
projectService.createProjectFile(filename, newProjectData);
|
await projectService.createProjectFile(filename, newProjectData);
|
||||||
|
|
||||||
res.status(200).send({
|
res.status(200).send({
|
||||||
filename,
|
filename,
|
||||||
@@ -83,29 +81,18 @@ export async function createProjectFile(req: Request, res: Response<{ filename:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility function finds the correct project file to download
|
* Allows downloading of project files
|
||||||
*/
|
|
||||||
function selectProjectFile(fileName?: string) {
|
|
||||||
const projectsDirectory = resolveDbDirectory;
|
|
||||||
const fileToDownload = fileName ? ensureJsonExtension(fileName) : projectService.getProjectTitle();
|
|
||||||
const pathToFile = join(projectsDirectory, fileToDownload);
|
|
||||||
|
|
||||||
return { pathToFile, name: fileToDownload };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows downloading of a optionally given project files
|
|
||||||
* If no {filename} is provided, loaded file will be served
|
|
||||||
*/
|
*/
|
||||||
export async function projectDownload(req: Request, res: Response) {
|
export async function projectDownload(req: Request, res: Response) {
|
||||||
const { pathToFile, name } = selectProjectFile(req.body?.fileName);
|
const { filename } = req.body;
|
||||||
|
const pathToFile = join(resolveDbDirectory, filename);
|
||||||
|
|
||||||
// Check if the file exists before attempting to download
|
// Check if the file exists before attempting to download
|
||||||
if (!existsSync(pathToFile)) {
|
if (!existsSync(pathToFile)) {
|
||||||
return res.status(404).send({ message: `Project ${name} not found.` });
|
return res.status(404).send({ message: `Project ${filename} not found.` });
|
||||||
}
|
}
|
||||||
|
|
||||||
res.download(pathToFile, name, (error) => {
|
res.download(pathToFile, filename, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
const message = getErrorMessage(error);
|
const message = getErrorMessage(error);
|
||||||
res.status(500).send({ message });
|
res.status(500).send({ message });
|
||||||
@@ -228,7 +215,7 @@ export async function duplicateProjectFile(req: Request, res: Response<MessageRe
|
|||||||
*/
|
*/
|
||||||
export async function renameProjectFile(req: Request, res: Response<MessageResponse | ErrorResponse>) {
|
export async function renameProjectFile(req: Request, res: Response<MessageResponse | ErrorResponse>) {
|
||||||
try {
|
try {
|
||||||
const { newFilename } = req.body;
|
const { filename: newFilename } = req.body;
|
||||||
const { filename } = req.params;
|
const { filename } = req.params;
|
||||||
|
|
||||||
const errors = projectService.validateProjectFiles({ filename, newFilename });
|
const errors = projectService.validateProjectFiles({ filename, newFilename });
|
||||||
|
|||||||
@@ -14,28 +14,25 @@ import {
|
|||||||
} from './db.controller.js';
|
} from './db.controller.js';
|
||||||
import { uploadProjectFile } from './db.middleware.js';
|
import { uploadProjectFile } from './db.middleware.js';
|
||||||
import {
|
import {
|
||||||
projectSanitiser,
|
validateNewProject,
|
||||||
sanitizeProjectFilename,
|
validatePatchProject,
|
||||||
validateDownloadProject,
|
validateFilenameBody,
|
||||||
validateLoadProjectFile,
|
validateFilenameParam,
|
||||||
validatePatchProjectFile,
|
|
||||||
validateProjectDuplicate,
|
|
||||||
validateProjectRename,
|
|
||||||
} from './db.validation.js';
|
} from './db.validation.js';
|
||||||
|
|
||||||
export const router = express.Router();
|
export const router = express.Router();
|
||||||
|
|
||||||
router.post('/download', validateDownloadProject, projectDownload);
|
router.post('/download', validateFilenameBody, projectDownload);
|
||||||
router.post('/upload', uploadProjectFile, postProjectFile);
|
router.post('/upload', uploadProjectFile, postProjectFile);
|
||||||
|
|
||||||
router.patch('/', validatePatchProjectFile, patchPartialProjectFile);
|
router.patch('/', validatePatchProject, patchPartialProjectFile);
|
||||||
router.post('/new', projectSanitiser, createProjectFile);
|
router.post('/new', validateFilenameBody, validateNewProject, createProjectFile);
|
||||||
|
|
||||||
router.get('/all', listProjects);
|
router.get('/all', listProjects);
|
||||||
|
|
||||||
router.post('/load', validateLoadProjectFile, sanitizeProjectFilename, loadProject);
|
router.post('/load', validateFilenameBody, loadProject);
|
||||||
router.post('/:filename/duplicate', validateProjectDuplicate, sanitizeProjectFilename, duplicateProjectFile);
|
router.post('/:filename/duplicate', validateFilenameParam, validateFilenameBody, duplicateProjectFile);
|
||||||
router.put('/:filename/rename', validateProjectRename, sanitizeProjectFilename, renameProjectFile);
|
router.put('/:filename/rename', validateFilenameParam, validateFilenameBody, renameProjectFile);
|
||||||
router.delete('/:filename', sanitizeProjectFilename, deleteProjectFile);
|
router.delete('/:filename', validateFilenameParam, deleteProjectFile);
|
||||||
|
|
||||||
router.get('/info', getInfo);
|
router.get('/info', getInfo);
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { body, validationResult } from 'express-validator';
|
import { body, param, validationResult } from 'express-validator';
|
||||||
|
|
||||||
import { ensureJsonExtension } from '../../utils/fileManagement.js';
|
import { ensureJsonExtension } from '../../utils/fileManagement.js';
|
||||||
|
import sanitize from 'sanitize-filename';
|
||||||
|
|
||||||
export const projectSanitiser = [
|
/**
|
||||||
|
* @description Validates request for a new project.
|
||||||
|
*/
|
||||||
|
export const validateNewProject = [
|
||||||
body('title').optional().isString().trim(),
|
body('title').optional().isString().trim(),
|
||||||
body('description').optional().isString().trim(),
|
body('description').optional().isString().trim(),
|
||||||
body('publicUrl').optional().isString().trim(),
|
body('publicUrl').optional().isString().trim(),
|
||||||
@@ -19,18 +22,10 @@ export const projectSanitiser = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const sanitizeProjectFilename = (req: Request, _res: Response, next: NextFunction) => {
|
/**
|
||||||
const { filename, newFilename } = req.body;
|
* @description Validates request for pathing data in the project.
|
||||||
const { filename: projectName } = req.params;
|
*/
|
||||||
|
export const validatePatchProject = [
|
||||||
req.body.filename = ensureJsonExtension(filename);
|
|
||||||
req.body.newFilename = ensureJsonExtension(newFilename);
|
|
||||||
req.params.filename = ensureJsonExtension(projectName);
|
|
||||||
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const validatePatchProjectFile = [
|
|
||||||
body('rundown').isArray().optional({ nullable: false }),
|
body('rundown').isArray().optional({ nullable: false }),
|
||||||
body('project').isObject().optional({ nullable: false }),
|
body('project').isObject().optional({ nullable: false }),
|
||||||
body('settings').isObject().optional({ nullable: false }),
|
body('settings').isObject().optional({ nullable: false }),
|
||||||
@@ -47,31 +42,18 @@ export const validatePatchProjectFile = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Validates the filename for loading a project file.
|
* @description Validates request with filename in the body.
|
||||||
*/
|
*/
|
||||||
export const validateLoadProjectFile = [
|
export const validateFilenameBody = [
|
||||||
body('filename').exists().withMessage('Filename is required').isString().withMessage('Filename must be a string'),
|
body('filename')
|
||||||
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
|
||||||
const errors = validationResult(req);
|
|
||||||
if (!errors.isEmpty()) {
|
|
||||||
return res.status(422).json({ errors: errors.array() });
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Validates the filenames for duplicating a project.
|
|
||||||
*/
|
|
||||||
export const validateProjectDuplicate = [
|
|
||||||
body('newFilename')
|
|
||||||
.exists()
|
.exists()
|
||||||
.withMessage('New project filename is required')
|
|
||||||
.isString()
|
.isString()
|
||||||
.withMessage('New project filename must be a string')
|
.trim()
|
||||||
.isLength({ min: 1, max: 255 })
|
.customSanitizer((input: string) => sanitize(input))
|
||||||
.withMessage('New project filename must be between 1 and 255 characters'),
|
.withMessage('Failed to sanitize the filename')
|
||||||
|
.notEmpty()
|
||||||
|
.withMessage('Filename was empty or contained only invalid characters')
|
||||||
|
.customSanitizer((input: string) => ensureJsonExtension(input)),
|
||||||
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
const errors = validationResult(req);
|
const errors = validationResult(req);
|
||||||
@@ -84,32 +66,18 @@ export const validateProjectDuplicate = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Validates the filenames for renaming a project.
|
* @description Validates request with filename in the params.
|
||||||
*/
|
*/
|
||||||
export const validateProjectRename = [
|
export const validateFilenameParam = [
|
||||||
body('newFilename')
|
param('filename')
|
||||||
.exists()
|
.exists()
|
||||||
.withMessage('Duplicate project filename is required')
|
|
||||||
.isString()
|
.isString()
|
||||||
.withMessage('Duplicate project filename must be a string')
|
.trim()
|
||||||
.isLength({ min: 1, max: 255 })
|
.customSanitizer((input: string) => sanitize(input))
|
||||||
.withMessage('Duplicate project filename must be between 1 and 255 characters'),
|
.withMessage('Failed to sanitize the filename')
|
||||||
|
.notEmpty()
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
.withMessage('Filename was empty or contained only invalid characters')
|
||||||
const errors = validationResult(req);
|
.customSanitizer((input: string) => ensureJsonExtension(input)),
|
||||||
if (!errors.isEmpty()) {
|
|
||||||
return res.status(422).json({ errors: errors.array() });
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Validates a download request which can include an optional project name.
|
|
||||||
*/
|
|
||||||
export const validateDownloadProject = [
|
|
||||||
body('fileName').isString().optional(),
|
|
||||||
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
const errors = validationResult(req);
|
const errors = validationResult(req);
|
||||||
|
|||||||
Generated
+121
-8
@@ -212,7 +212,7 @@ importers:
|
|||||||
version: 5.4.3
|
version: 5.4.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^5.2.11
|
specifier: ^5.2.11
|
||||||
version: 5.2.11(@types/node@18.11.18)(sass@1.57.1)
|
version: 5.2.11(sass@1.57.1)
|
||||||
vite-plugin-compression2:
|
vite-plugin-compression2:
|
||||||
specifier: ^0.12.0
|
specifier: ^0.12.0
|
||||||
version: 0.12.0
|
version: 0.12.0
|
||||||
@@ -224,7 +224,7 @@ importers:
|
|||||||
version: 4.3.1(typescript@5.4.3)(vite@5.2.11)
|
version: 4.3.1(typescript@5.4.3)(vite@5.2.11)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^1.6.0
|
specifier: ^1.6.0
|
||||||
version: 1.6.0(@types/node@18.11.18)(jsdom@21.1.0)(sass@1.57.1)
|
version: 1.6.0(jsdom@21.1.0)(sass@1.57.1)
|
||||||
|
|
||||||
apps/electron:
|
apps/electron:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@@ -288,6 +288,9 @@ importers:
|
|||||||
ontime-utils:
|
ontime-utils:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/utils
|
version: link:../../packages/utils
|
||||||
|
sanitize-filename:
|
||||||
|
specifier: ^1.6.3
|
||||||
|
version: 1.6.3
|
||||||
steno:
|
steno:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.2.0
|
version: 3.2.0
|
||||||
@@ -3872,7 +3875,7 @@ packages:
|
|||||||
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.6)
|
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.6)
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
react-refresh: 0.14.0
|
react-refresh: 0.14.0
|
||||||
vite: 5.2.11(@types/node@18.11.18)(sass@1.57.1)
|
vite: 5.2.11(sass@1.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
@@ -8560,7 +8563,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==}
|
resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
truncate-utf8-bytes: 1.0.2
|
truncate-utf8-bytes: 1.0.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/sass@1.57.1:
|
/sass@1.57.1:
|
||||||
resolution: {integrity: sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==}
|
resolution: {integrity: sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==}
|
||||||
@@ -9146,7 +9148,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==}
|
resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
utf8-byte-length: 1.0.4
|
utf8-byte-length: 1.0.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ts-api-utils@1.0.3(typescript@5.4.3):
|
/ts-api-utils@1.0.3(typescript@5.4.3):
|
||||||
resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
|
resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
|
||||||
@@ -9488,7 +9489,6 @@ packages:
|
|||||||
|
|
||||||
/utf8-byte-length@1.0.4:
|
/utf8-byte-length@1.0.4:
|
||||||
resolution: {integrity: sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==}
|
resolution: {integrity: sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/util-deprecate@1.0.2:
|
/util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
@@ -9549,6 +9549,27 @@ packages:
|
|||||||
- terser
|
- terser
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vite-node@1.6.0(sass@1.57.1):
|
||||||
|
resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
cac: 6.7.14
|
||||||
|
debug: 4.3.4
|
||||||
|
pathe: 1.1.1
|
||||||
|
picocolors: 1.0.0
|
||||||
|
vite: 5.2.11(sass@1.57.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/node'
|
||||||
|
- less
|
||||||
|
- lightningcss
|
||||||
|
- sass
|
||||||
|
- stylus
|
||||||
|
- sugarss
|
||||||
|
- supports-color
|
||||||
|
- terser
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-compression2@0.12.0:
|
/vite-plugin-compression2@0.12.0:
|
||||||
resolution: {integrity: sha512-9zdEF9xKVezETSF1l1bHoOk8LNoKIHB+DZVgSIGuGWaYupwFmsAGh0uwRcmK6rVHacxQRBECVYdtfc65DPDRfg==}
|
resolution: {integrity: sha512-9zdEF9xKVezETSF1l1bHoOk8LNoKIHB+DZVgSIGuGWaYupwFmsAGh0uwRcmK6rVHacxQRBECVYdtfc65DPDRfg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9566,7 +9587,7 @@ packages:
|
|||||||
'@rollup/pluginutils': 5.1.0
|
'@rollup/pluginutils': 5.1.0
|
||||||
'@svgr/core': 8.1.0(typescript@5.4.3)
|
'@svgr/core': 8.1.0(typescript@5.4.3)
|
||||||
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0)
|
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0)
|
||||||
vite: 5.2.11(@types/node@18.11.18)(sass@1.57.1)
|
vite: 5.2.11(sass@1.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -9584,7 +9605,7 @@ packages:
|
|||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
globrex: 0.1.2
|
globrex: 0.1.2
|
||||||
tsconfck: 3.0.2(typescript@5.4.3)
|
tsconfck: 3.0.2(typescript@5.4.3)
|
||||||
vite: 5.2.11(@types/node@18.11.18)(sass@1.57.1)
|
vite: 5.2.11(sass@1.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
@@ -9627,6 +9648,42 @@ packages:
|
|||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vite@5.2.11(sass@1.57.1):
|
||||||
|
resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@types/node': ^18.0.0 || >=20.0.0
|
||||||
|
less: '*'
|
||||||
|
lightningcss: ^1.21.0
|
||||||
|
sass: '*'
|
||||||
|
stylus: '*'
|
||||||
|
sugarss: '*'
|
||||||
|
terser: ^5.4.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/node':
|
||||||
|
optional: true
|
||||||
|
less:
|
||||||
|
optional: true
|
||||||
|
lightningcss:
|
||||||
|
optional: true
|
||||||
|
sass:
|
||||||
|
optional: true
|
||||||
|
stylus:
|
||||||
|
optional: true
|
||||||
|
sugarss:
|
||||||
|
optional: true
|
||||||
|
terser:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
esbuild: 0.20.2
|
||||||
|
postcss: 8.4.38
|
||||||
|
rollup: 4.17.2
|
||||||
|
sass: 1.57.1
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vitest@1.6.0(@types/node@18.11.18)(jsdom@21.1.0)(sass@1.57.1):
|
/vitest@1.6.0(@types/node@18.11.18)(jsdom@21.1.0)(sass@1.57.1):
|
||||||
resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
|
resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
@@ -9684,6 +9741,62 @@ packages:
|
|||||||
- terser
|
- terser
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vitest@1.6.0(jsdom@21.1.0)(sass@1.57.1):
|
||||||
|
resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@edge-runtime/vm': '*'
|
||||||
|
'@types/node': ^18.0.0 || >=20.0.0
|
||||||
|
'@vitest/browser': 1.6.0
|
||||||
|
'@vitest/ui': 1.6.0
|
||||||
|
happy-dom: '*'
|
||||||
|
jsdom: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@edge-runtime/vm':
|
||||||
|
optional: true
|
||||||
|
'@types/node':
|
||||||
|
optional: true
|
||||||
|
'@vitest/browser':
|
||||||
|
optional: true
|
||||||
|
'@vitest/ui':
|
||||||
|
optional: true
|
||||||
|
happy-dom:
|
||||||
|
optional: true
|
||||||
|
jsdom:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@vitest/expect': 1.6.0
|
||||||
|
'@vitest/runner': 1.6.0
|
||||||
|
'@vitest/snapshot': 1.6.0
|
||||||
|
'@vitest/spy': 1.6.0
|
||||||
|
'@vitest/utils': 1.6.0
|
||||||
|
acorn-walk: 8.3.2
|
||||||
|
chai: 4.3.10
|
||||||
|
debug: 4.3.4
|
||||||
|
execa: 8.0.1
|
||||||
|
jsdom: 21.1.0
|
||||||
|
local-pkg: 0.5.0
|
||||||
|
magic-string: 0.30.5
|
||||||
|
pathe: 1.1.1
|
||||||
|
picocolors: 1.0.0
|
||||||
|
std-env: 3.6.0
|
||||||
|
strip-literal: 2.1.0
|
||||||
|
tinybench: 2.5.1
|
||||||
|
tinypool: 0.8.4
|
||||||
|
vite: 5.2.11(sass@1.57.1)
|
||||||
|
vite-node: 1.6.0(sass@1.57.1)
|
||||||
|
why-is-node-running: 2.2.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- less
|
||||||
|
- lightningcss
|
||||||
|
- sass
|
||||||
|
- stylus
|
||||||
|
- sugarss
|
||||||
|
- supports-color
|
||||||
|
- terser
|
||||||
|
dev: true
|
||||||
|
|
||||||
/w3c-xmlserializer@4.0.0:
|
/w3c-xmlserializer@4.0.0:
|
||||||
resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==}
|
resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|||||||
Reference in New Issue
Block a user