refactor: migrate custom fields to transactions

refactor: extract functions to api domain

refactor: strict custom field parsing

refactor: remove rundown cache utilities

refactor: directory restructure
This commit is contained in:
Carlos Valente
2025-06-06 21:08:30 +02:00
committed by arc-alex
parent f3b4ea0155
commit 2498e59156
75 changed files with 2060 additions and 2480 deletions
@@ -0,0 +1,56 @@
/* eslint-disable no-console -- we are mocking the console */
import { demoDb } from '../../../models/demoProject.js';
import { parseDatabaseModel } from '../db.parser.js';
// mock data provider
beforeAll(() => {
vi.mock('../../classes/data-provider/DataProvider.js', () => {
return {
getDataProvider: vi.fn().mockImplementation(() => {
return {
setRundown: vi.fn().mockImplementation((newData) => newData),
setCustomFields: vi.fn().mockImplementation((newData) => newData),
};
}),
};
});
});
describe('test parseDatabaseModel() with demo project (valid)', () => {
const filteredDemoProject = structuredClone(demoDb);
const { data } = parseDatabaseModel(filteredDemoProject);
it('has 17 events with 12 top level events', () => {
expect(data.rundowns.default.order.length).toBe(12);
expect(Object.keys(data.rundowns.default.entries).length).toBe(17);
});
it('is the same as the demo project since all data is valid', () => {
// @ts-expect-error -- its ok
delete filteredDemoProject.settings.version;
// @ts-expect-error -- its ok
delete data.settings.version;
expect(data).toMatchObject(filteredDemoProject);
});
});
describe('test parseDatabaseModel() edge cases', () => {
it('skips unknown app and version settings', () => {
console.log = vi.fn();
const testData = {
settings: {
osc_port: 8888,
},
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
expect(() => parseDatabaseModel(testData)).toThrow();
});
it('fails with invalid JSON', () => {
// @ts-expect-error -- we know this is wrong, testing imports outside domain
expect(() => parseDatabaseModel('some random dataset')).toThrow();
});
});
+1 -2
View File
@@ -1,11 +1,10 @@
import type { Request } from 'express';
import multer, { type FileFilterCallback } from 'multer';
import { JSON_MIME } from '../../utils/parser.js';
import { storage } from '../../utils/upload.js';
const filterProjectFile = (_req: Request, file: Express.Multer.File, cb: FileFilterCallback) => {
if (file.mimetype.includes(JSON_MIME)) {
if (file.mimetype.includes('application/json')) {
cb(null, true);
} else {
cb(null, false);
+49
View File
@@ -0,0 +1,49 @@
import { DatabaseModel, LogOrigin } from 'ontime-types';
import { logger } from '../../classes/Logger.js';
import { parseAutomationSettings } from '../automation/automation.parser.js';
import { parseProjectData } from '../project-data/projectData.parser.js';
import { parseRundowns } from '../rundown/rundown.parser.js';
import { parseSettings } from '../settings/settings.parser.js';
import { parseUrlPresets } from '../url-presets/urlPresets.parser.js';
import { parseViewSettings } from '../view-settings/viewSettings.parser.js';
import { parseCustomFields } from '../custom-fields/customFields.parser.js';
type ParsingError = {
context: string;
message: string;
};
/**
* @description handles parsing of ontime project file
* @param {object} jsonData - project file to be parsed
* @returns {object} - parsed object
*/
export function parseDatabaseModel(jsonData: Partial<DatabaseModel>): { data: DatabaseModel; errors: ParsingError[] } {
// we need to parse settings first to make sure the data is ours
// this may throw
const settings = parseSettings(jsonData);
const errors: ParsingError[] = [];
const makeEmitError = (context: string) => (message: string) => {
logger.error(LogOrigin.Server, `Error parsing ${context}: ${message}`);
errors.push({ context, message });
};
// we need to parse the custom fields first so they can be used in validating events
const customFields = parseCustomFields(jsonData, makeEmitError('Custom Fields'));
const rundowns = parseRundowns(jsonData, customFields, makeEmitError('Rundowns'));
const data: DatabaseModel = {
rundowns,
project: parseProjectData(jsonData, makeEmitError('Project')),
settings,
viewSettings: parseViewSettings(jsonData, makeEmitError('View Settings')),
urlPresets: parseUrlPresets(jsonData, makeEmitError('URL Presets')),
customFields,
automation: parseAutomationSettings(jsonData),
};
return { data, errors };
}