From dae32e89a305fd9d49528a881e0b661664eeb969 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Tue, 2 Jul 2024 18:19:50 +0200 Subject: [PATCH] refactor: patch project --- apps/server/src/api-data/db/db.controller.ts | 9 +-------- apps/server/src/api-data/db/db.validation.ts | 11 ++++++++++- .../src/services/project-service/ProjectService.ts | 13 ++++++++----- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/server/src/api-data/db/db.controller.ts b/apps/server/src/api-data/db/db.controller.ts index 1ec6084d1..78a63be27 100644 --- a/apps/server/src/api-data/db/db.controller.ts +++ b/apps/server/src/api-data/db/db.controller.ts @@ -10,22 +10,15 @@ import { getErrorMessage } from 'ontime-utils'; import type { Request, Response } from 'express'; -import { failEmptyObjects } from '../../utils/routerUtils.js'; import { doesProjectExist, handleUploaded } from '../../services/project-service/projectServiceUtils.js'; import * as projectService from '../../services/project-service/ProjectService.js'; export async function patchPartialProjectFile(req: Request, res: Response) { - // all fields are optional in validation - if (failEmptyObjects(req.body, res)) { - res.status(400).send({ message: 'No field found to patch' }); - return; - } - try { const { rundown, project, settings, viewSettings, urlPresets, customFields, osc, http } = req.body; const patchDb: DatabaseModel = { rundown, project, settings, viewSettings, urlPresets, customFields, osc, http }; - const newData = await projectService.applyDataModel(patchDb); + const newData = await projectService.patchCurrentProject(patchDb); res.status(200).send(newData); } catch (error) { diff --git a/apps/server/src/api-data/db/db.validation.ts b/apps/server/src/api-data/db/db.validation.ts index 019c7f96b..8d160d2e4 100644 --- a/apps/server/src/api-data/db/db.validation.ts +++ b/apps/server/src/api-data/db/db.validation.ts @@ -26,13 +26,22 @@ export const validateNewProject = [ * @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('rundown').isArray().optional({ nullable: false }), body('project').isObject().optional({ nullable: false }), body('settings').isObject().optional({ nullable: false }), body('viewSettings').isObject().optional({ nullable: false }), - body('aliases').isArray().optional({ nullable: false }), + body('urlPresets').isArray().optional({ nullable: false }), body('customFields').isObject().optional({ nullable: false }), body('osc').isObject().optional({ nullable: false }), + body('http').isObject().optional({ nullable: false }), (req: Request, res: Response, next: NextFunction) => { const errors = validationResult(req); diff --git a/apps/server/src/services/project-service/ProjectService.ts b/apps/server/src/services/project-service/ProjectService.ts index d7e1abd52..9a5987a52 100644 --- a/apps/server/src/services/project-service/ProjectService.ts +++ b/apps/server/src/services/project-service/ProjectService.ts @@ -22,6 +22,7 @@ import { httpIntegration } from '../integration-service/HttpIntegration.js'; import { parseProjectFile } from './projectFileUtils.js'; import { doesProjectExist, getPathToProject, getProjectFiles } from './projectServiceUtils.js'; +import { parseRundown } from '../../utils/parserFunctions.js'; // init dependencies init(); @@ -173,7 +174,7 @@ export async function createProject(filename: string, projectData: ProjectData) // apply data to running services // we dont need to parse since we are creating a new file - await applyDataModel(data); + await patchCurrentProject(data); // update app state to point to new value appStateProvider.setLastLoadedProject(uniqueFileName); @@ -222,16 +223,18 @@ export async function getInfo(): Promise { /** * applies a partial database model */ -// TODO: should be private as part of a load -export async function applyDataModel(data: Partial) { +export async function patchCurrentProject(data: Partial) { runtimeService.stop(); - // TODO: allow partial project merge from options + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- we need to remove the fields before meging const { rundown, customFields, ...rest } = data; + // we can pass some stuff straight to the data provider const newData = await DataProvider.mergeIntoData(rest); + // ... but rundown and custom fields need to be checked if (rundown != null) { - initRundown(rundown, customFields ?? {}); + const result = parseRundown(data); + initRundown(result.rundown, result.customFields); } return newData;