feat: improve preset building

This commit is contained in:
Carlos Valente
2025-07-20 07:37:54 +02:00
committed by Carlos Valente
parent 5bc286145d
commit a1fab10bfd
26 changed files with 614 additions and 299 deletions
@@ -12,13 +12,14 @@ describe('parseUrlPresets()', () => {
it('parses data, skipping invalid results', () => {
const errorEmitter = vi.fn();
const urlPresets = [{ enabled: true, alias: 'alias', pathAndParams: 'ss' }] as URLPreset[];
const urlPresets = [{ enabled: true, alias: 'alias', target: 'timer', search: 'ss' }] as URLPreset[];
const result = parseUrlPresets({ urlPresets }, errorEmitter);
expect(result.length).toEqual(1);
expect(result.at(0)).toMatchObject({
enabled: true,
alias: 'alias',
pathAndParams: 'ss',
target: 'timer',
search: 'ss',
});
expect(errorEmitter).not.toHaveBeenCalled();
});
@@ -33,7 +34,8 @@ describe('parseUrlPresets()', () => {
{
enabled: false,
alias: 'testalias',
pathAndParams: 'testpathAndParams',
target: 'timer',
search: 'testpathAndParams',
},
],
} as unknown as DatabaseModel;
@@ -16,10 +16,16 @@ export function parseUrlPresets(data: Partial<DatabaseModel>, emitError?: ErrorE
const newPresets: URLPreset[] = [];
for (const preset of data.urlPresets) {
if (!preset.alias || !preset.search || !preset.target) {
emitError?.(`Invalid URL preset: ${JSON.stringify(preset)}`);
continue;
}
const newPreset = {
enabled: preset.enabled ?? false,
alias: preset.alias ?? '',
pathAndParams: preset.pathAndParams ?? '',
alias: preset.alias,
target: preset.target,
search: preset.search,
};
newPresets.push(newPreset);
}
@@ -2,8 +2,8 @@ import express from 'express';
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';
import { validateNewPreset, validatePresetParam, validateUpdatePreset } from './urlPresets.validation.js';
export const router = express.Router();
@@ -12,13 +12,64 @@ router.get('/', (_req: Request, res: Response<URLPreset[]>) => {
res.status(200).send(presets as URLPreset[]);
});
router.post('/', validateUrlPresets, async (req: Request, res: Response<URLPreset[] | ErrorResponse>) => {
router.post('/', validateNewPreset, 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,
}));
const newPreset: URLPreset = {
enabled: req.body.enabled,
alias: req.body.alias,
target: req.body.target,
search: req.body.search,
};
const currentPresets = getDataProvider().getUrlPresets();
if (currentPresets.some((preset) => preset.alias === newPreset.alias)) {
throw new Error(`Preset with alias "${newPreset.alias}" already exists.`);
}
const newPresets = [...currentPresets, newPreset];
// Update the URL presets in the data provider
await getDataProvider().setUrlPresets(newPresets);
res.status(201).send(newPresets);
} catch (error) {
const message = getErrorMessage(error);
res.status(400).send({ message });
}
});
router.put('/:alias', validateUpdatePreset, async (req: Request, res: Response<URLPreset[] | ErrorResponse>) => {
try {
const alias = req.params.alias;
const updatedPreset: URLPreset = {
enabled: req.body.enabled,
alias: req.body.alias,
target: req.body.target,
search: req.body.search,
};
if (alias !== updatedPreset.alias) {
throw new Error(`Changing alias is not permitted`);
}
const currentPresets = getDataProvider().getUrlPresets();
const newPresets = currentPresets.map((preset) => (preset.alias === alias ? updatedPreset : preset));
// Update the URL presets in the data provider
await getDataProvider().setUrlPresets(newPresets);
res.status(200).send(newPresets);
} catch (error) {
const message = getErrorMessage(error);
res.status(400).send({ message });
}
});
router.delete('/:alias', validatePresetParam, async (req: Request, res: Response<URLPreset[] | ErrorResponse>) => {
try {
const alias = req.params.alias;
const currentPresets = getDataProvider().getUrlPresets();
const newPresets = currentPresets.filter((preset) => preset.alias !== alias);
// Update the URL presets in the data provider
await getDataProvider().setUrlPresets(newPresets);
res.status(200).send(newPresets);
} catch (error) {
@@ -1,14 +1,31 @@
import { body } from 'express-validator';
import { OntimeView } from 'ontime-types';
import { body, param } from 'express-validator';
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
/**
* validate array of URL preset objects
*/
export const validateUrlPresets = [
body().isArray().withMessage('No array found in request'),
body('*.enabled').isBoolean(),
body('*.alias').isString().trim().notEmpty(),
body('*.pathAndParams').isString().trim().notEmpty(),
export const validateNewPreset = [
body().isObject().withMessage('No data found in request'),
body('enabled').isBoolean(),
body('alias').isString().trim().notEmpty(),
body('target').isString().trim().notEmpty().isIn(Object.values(OntimeView)),
body('search').isString().trim(),
requestValidationFunction,
];
export const validateUpdatePreset = [
param('alias').isString().trim().notEmpty(),
body().isObject().withMessage('No data found in request'),
body('enabled').isBoolean(),
body('alias').isString().trim().notEmpty(),
body('target').isString().trim().notEmpty().isIn(Object.values(OntimeView)),
body('search').isString().trim(),
requestValidationFunction,
];
export const validatePresetParam = [param('alias').isString().trim().notEmpty(), requestValidationFunction];