event cucle (#76)

* install sass
* refact: integration settings
- OSC in its own HTTP endpoint
- OSC settings have own object in db
* refact: simplify event cycle
* refact: restructure external triggers http
* refact: restructure external triggers osc+socket
* refact: restructure data updates
* feat: osc integration class
* IO improvements
- timer uses osc integration
- create trigger handler to manage external triggers
* refact: refract state machine update
* Integration: simple HTTP Client
* Integration: http options in datamodel
* Integration: call http send on life cycle
* feat/62-logging: fix issue #71
This commit is contained in:
Carlos Valente
2021-12-22 18:17:48 +01:00
committed by GitHub
parent 2b2bafa8c6
commit ac0d5832b6
53 changed files with 2041 additions and 1948 deletions
+9 -22
View File
@@ -6,7 +6,6 @@ import {
validateEventv1,
} from '../parser.js';
import { dbModelv1 as dbModel } from '../../models/dataModel.js';
import { describe } from 'jest-circus';
describe('test json parser with valid def', () => {
const testData = {
@@ -133,6 +132,7 @@ describe('test json parser with valid def', () => {
revision: 0,
id: '4b31',
};
expect(first).toStrictEqual(expected);
});
it('loaded event settings', () => {
@@ -192,7 +192,7 @@ describe('test parser edge cases', () => {
const parseResponse = await parseJsonv1(testData);
expect(console.log).toHaveBeenCalledWith(
'ERROR: ID colision on import, skipping'
'ERROR: ID collision on import, skipping'
);
expect(parseResponse?.events.length).toBe(1);
});
@@ -267,11 +267,7 @@ describe('test corrupt data', () => {
app: 'ontime',
version: 1,
serverPort: 4001,
oscInPort: 8888,
oscOutPort: 9999,
oscOutIP: '127.0.0.1',
oscEnabled: false,
lock: false,
lock: null,
},
};
@@ -293,11 +289,7 @@ describe('test corrupt data', () => {
app: 'ontime',
version: 1,
serverPort: 4001,
oscInPort: 8888,
oscOutPort: 9999,
oscOutIP: '127.0.0.1',
oscEnabled: false,
lock: false,
lock: null,
},
};
@@ -313,11 +305,7 @@ describe('test corrupt data', () => {
app: 'ontime',
version: 1,
serverPort: 4001,
oscInPort: 8888,
oscOutPort: 9999,
oscOutIP: '127.0.0.1',
oscEnabled: false,
lock: false,
lock: null,
},
};
@@ -430,7 +418,6 @@ describe('test makeString function', () => {
expect(converted).toBe(expected);
val = { doing: 'testing' };
expected = 'testing';
converted = makeString(val, 'fallback');
expect(converted).toBe('fallback');
});
@@ -477,8 +464,8 @@ describe('test parseExcel function', () => {
const expectedParsedEvents = [
{
timeStart: 28800000,
timeEnd: 32410000,
timeStart: 25200000,
timeEnd: 28810000,
title: 'Guest Welcome',
presenter: 'Carlos',
subtitle: 'Getting things started',
@@ -487,8 +474,8 @@ describe('test parseExcel function', () => {
type: 'event',
},
{
timeStart: 32400000,
timeEnd: 34200000,
timeStart: 28800000,
timeEnd: 30600000,
title: 'A song from the hearth',
presenter: 'Still Carlos',
subtitle: 'Derailing early',
+3 -1
View File
@@ -1,4 +1,3 @@
import { describe } from 'jest-circus';
import { excelDateStringToMillis, stringFromMillis } from '../time.js';
describe('test string to milis function', () => {
@@ -60,12 +59,15 @@ describe('test string to milis function', () => {
describe('test excel date parser', () => {
it('parses the given dates correctly', () => {
const d0 = '1899-12-30T00:00:00.000Z';
const d1 = '1899-12-30T08:00:00.000Z';
const d2 = '1899-12-30T08:30:00.000Z';
const d0Millis = 0;
const d1Millis = 28800000;
const d2Millis = 30600000;
expect(excelDateStringToMillis(d0)).toBe(d0Millis);
expect(excelDateStringToMillis(d1)).toBe(d1Millis);
expect(excelDateStringToMillis(d2)).toBe(d2Millis);
});
+36
View File
@@ -0,0 +1,36 @@
// test cleanURL()
import {cleanURL} from "../url";
describe('url is correctly formatted', () => {
it('has no leading spaces', () => {
const test = ' http://testing';
const expected = 'http://testing';
expect(cleanURL(test)).toBe(expected);
});
it('has no trailing spaces', () => {
const test = 'http://testing ';
const expected = 'http://testing';
expect(cleanURL(test)).toBe(expected);
});
it('doesnt contain spaces', () => {
const test = 'http://t e s t i n g';
const expected = 'http://t%20e%20s%20t%20i%20n%20g';
expect(cleanURL(test)).toBe(expected);
});
it('only contains allowed characters', () => {
const test = 'http://<>[]{}|\^';
const expected = 'http://';
expect(cleanURL(test)).toBe(expected);
});
it('begins with http://', () => {
const test = 'ontime.com';
const expected = 'http://ontime.com';
expect(cleanURL(test)).toBe(expected);
});
});
+66 -19
View File
@@ -16,7 +16,7 @@ export const ALLOWED_TYPES = ['JSON', 'EXCEL'];
/**
* @description Middleware function that checks file type and calls relevant parser
* @argument {string} file - reference to file
* @param {string} file - reference to file
* @return {object} - parse result message
*/
export const fileHandler = async (file) => {
@@ -82,7 +82,7 @@ export const fileHandler = async (file) => {
/**
* @description Excel array parser
* @argument {array} excelData - array with excel sheet
* @param {array} excelData - array with excel sheet
* @returns {object} - parsed object
*/
export const parseExcelv1 = async (excelData) => {
@@ -196,11 +196,12 @@ export const parseExcelv1 = async (excelData) => {
/**
* @description JSON parser function for v1 of data system
* @argument {object} jsonData - json data JSON object to be parsed
* @param {object} jsonData - json data JSON object to be parsed
* @param {boolean} [enforce=false] - flag, tells to create an object anyway
* @returns {object} - parsed object
*/
export const parseJsonv1 = async (jsonData) => {
export const parseJsonv1 = async (jsonData, enforce=false) => {
if (!jsonData || typeof jsonData !== 'object') {
console.log('ERROR: Invalid JSON format');
return -1;
@@ -213,9 +214,9 @@ export const parseJsonv1 = async (jsonData) => {
let events = [];
let ids = [];
for (const e of jsonData.events) {
// doublecheck unique ids
// double check unique ids
if (ids.indexOf(e?.id) !== -1) {
console.log('ERROR: ID colision on import, skipping');
console.log('ERROR: ID collision on import, skipping');
continue;
}
@@ -243,13 +244,17 @@ export const parseJsonv1 = async (jsonData) => {
// write to db
returnData.events = events;
console.log(`Uploaded file with ${numEntries} entries`);
} else if (enforce) {
returnData.events = [];
console.log(`Created events object in db`);
}
if ('event' in jsonData) {
console.log('Found event data, importing...');
const e = jsonData.event;
// filter known properties
const event = {
// filter known properties and write to db
returnData.event = {
...dbModelv1.event,
title: e.title || dbModelv1.event.title,
url: e.url || dbModelv1.event.url,
@@ -257,9 +262,9 @@ export const parseJsonv1 = async (jsonData) => {
backstageInfo: e.backstageInfo || dbModelv1.event.backstageInfo,
endMessage: e.endMessage || dbModelv1.event.endMessage,
};
// write to db
returnData.event = event;
} else if (enforce) {
returnData.event = dbModelv1.event;
console.log(`Created event object in db`);
}
// Settings handled partially
@@ -271,11 +276,9 @@ export const parseJsonv1 = async (jsonData) => {
if (s.app == null || s.version == null) {
console.log('ERROR: unknown app version, skipping');
} else {
let settings = {};
if (s.oscInPort) settings.oscInPort = s.oscInPort;
if (s.oscOutPort) settings.oscOutPort = s.oscOutPort;
if (s.oscOutIP) settings.oscOutIP = s.oscOutIP;
let settings = {
lock: s.lock || null,
};
// write to db
returnData.settings = {
@@ -283,6 +286,49 @@ export const parseJsonv1 = async (jsonData) => {
...settings,
};
}
} else if (enforce) {
returnData.settings = dbModelv1.settings;
console.log(`Created settings object in db`);
}
// Import OSC settings if any
if ('osc' in jsonData) {
console.log('Found OSC definition, importing...');
const s = jsonData.osc;
let osc = {};
if (s.port) osc.port = s.port;
if (s.portOut) osc.portOut = s.portOut;
if (s.targetIP) osc.targetIP = s.targetIP;
if (s.enabled) osc.enabled = s.enabled;
// write to db
returnData.osc = {
...dbModelv1.osc,
...osc,
};
} else if (enforce) {
returnData.osc = dbModelv1.osc;
console.log(`Created osc object in db`);
}
// Import HTTP settings if any
if ('http' in jsonData) {
console.log('Found HTTP definition, importing...');
const h = jsonData.osc;
let http = {};
if (h.user) http.user = h.user;
if (h.pwd) http.pwd = h.pwd;
// write to db
returnData.http = {
...dbModelv1.http,
...http,
};
} else if (enforce) {
returnData.http = dbModelv1.http;
console.log(`Created http object in db`);
}
return returnData;
@@ -292,7 +338,7 @@ export const parseJsonv1 = async (jsonData) => {
* @description Ensures variable is string, it skips object types
* @param {any} val - variable to convert
* @param {string} [fallback=''] - fallback value
* @returns {string} - value as string or fallback if not possibe
* @returns {string} - value as string or fallback if not possible
*/
export const makeString = (val, fallback = '') => {
if (typeof val === 'string') return val;
@@ -348,7 +394,7 @@ export const validateEventv1 = (eventArgs) => {
/**
* @description Delete file from system
* @argument {string} file - reference to file
* @param {string} file - reference to file
*/
const deleteFile = async (file) => {
// delete a file
@@ -361,7 +407,8 @@ const deleteFile = async (file) => {
/**
* @description Delete file from system
* @argument {string} file - reference to file
* @param {string} file - reference to file
* @returns {boolean} - whether file is valid JSON
*/
export const validateFile = (file) => {
try {
+1 -2
View File
@@ -40,9 +40,8 @@ export const stringFromMillis = (
*/
export const excelDateStringToMillis = (excelDate) => {
const date = new Date(excelDate);
if (date instanceof Date && !isNaN(date)) {
const h = date.getHours();
const h = date.getUTCHours();
const m = date.getMinutes();
const s = date.getSeconds();
+21
View File
@@ -0,0 +1,21 @@
/**
* @description Cleans given url
* @param {string} url - URL to be checked
* @returns {string} Sanitized url
*/
export const cleanURL = (url) => {
// trim whitespaces
let r = url.trim();
// clear any whitespaces
r = r.split(' ').join('%20');
// contain only allowed characters
r = r.replace(/([^\x00-\x7F]|[@\s<>\[\]{}|\\^])+/g, '')
// starts with http://
if (!r.startsWith('http://')) r = `http://${r}`
return r;
}