refactor: small type improvements (#759)

This commit is contained in:
Carlos Valente
2024-02-03 23:17:36 +01:00
committed by GitHub
parent 1890fc49d7
commit 212e5f9e68
23 changed files with 143 additions and 91 deletions
+2
View File
@@ -27,7 +27,9 @@
"ws": "^8.13.0"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.17",
"@types/multer": "^1.4.11",
"@types/node": "^18.11.18",
"@types/node-osc": "^6.0.2",
"@types/websocket": "^1.0.5",
+3 -3
View File
@@ -25,7 +25,7 @@ import { eventStore } from '../stores/EventStore.js';
import { dispatchFromAdapter } from '../controllers/integrationController.js';
import { logger } from '../classes/Logger.js';
let instance;
let instance: SocketServer | null = null;
export class SocketServer implements IAdapter {
private readonly MAX_PAYLOAD = 1024 * 256; // 256Kb
@@ -50,7 +50,7 @@ export class SocketServer implements IAdapter {
this.wss.on('connection', (ws) => {
let clientId = getRandomName();
this.clientIds.add(clientId);
logger.info(LogOrigin.Client, `${this.wss.clients.size} Connections with new: ${clientId}`);
logger.info(LogOrigin.Client, `${this.clientIds.size} Connections with new: ${clientId}`);
// send store payload on connect
ws.send(
@@ -70,8 +70,8 @@ export class SocketServer implements IAdapter {
ws.on('error', console.error);
ws.on('close', () => {
logger.info(LogOrigin.Client, `${this.wss.clients.size} Connections with disconnected: ${clientId}`);
this.clientIds.delete(clientId);
logger.info(LogOrigin.Client, `${this.clientIds.size} Connections with disconnected: ${clientId}`);
});
ws.on('message', (data) => {
@@ -33,8 +33,8 @@ describe('objectFromPath()', () => {
const obj = objectFromPath(arr);
expect(obj).toStrictEqual(objExpected);
});
it('empty array creates undefinde object', () => {
const arr = [];
it('empty array creates undefined object', () => {
const arr: string[] = [];
const value = '1234567890';
const objExpected = null;
+2 -2
View File
@@ -170,8 +170,8 @@ export const startServer = async () => {
eventNext: state.eventNext,
publicEventNext: state.publicEventNext,
timer1: {
duration: null,
current: null,
duration: 0,
current: 0,
playback: SimplePlayback.Stop,
direction: SimpleDirection.CountDown,
},
@@ -11,6 +11,7 @@ import {
UserFields,
Alias,
Settings,
HttpSettings,
} from 'ontime-types';
import { data, db } from '../../modules/loadDb.js';
@@ -98,7 +99,7 @@ export class DataProvider {
await this.persist();
}
static async setHttp(newData) {
static async setHttp(newData: HttpSettings) {
data.http = { ...newData };
await this.persist();
}
@@ -38,7 +38,8 @@ export class SimpleTimer {
public start(timeNow: number): SimpleTimerState {
if (this.state.playback === SimplePlayback.Pause) {
const elapsedSincePause = this.pausedAt - this.startedAt;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know these are not null in a timer that is paused
const elapsedSincePause = this.pausedAt! - this.startedAt!;
this.startedAt = timeNow - elapsedSincePause;
} else if (this.state.playback === SimplePlayback.Stop) {
this.startedAt = timeNow;
+62 -59
View File
@@ -8,7 +8,7 @@ import type {
ErrorResponse,
ProjectFileListResponse,
} from 'ontime-types';
import { deepmerge } from 'ontime-utils';
import { ExcelImportOptions, deepmerge } from 'ontime-utils';
import { RequestHandler, Request, Response } from 'express';
import fs from 'fs';
@@ -44,7 +44,7 @@ import { removeFileExtension } from '../utils/removeFileExtension.js';
// Create controller for GET request to '/ontime/poll'
// Returns data for current state
export const poll = async (_req, res) => {
export const poll = async (_req: Request, res: Response) => {
try {
const state = eventStore.poll();
res.status(200).send(state);
@@ -57,7 +57,7 @@ export const poll = async (_req, res) => {
// Create controller for GET request to '/ontime/db'
// Returns -
export const dbDownload = async (req, res) => {
export const dbDownload = async (_req: Request, res: Response) => {
const { title } = DataProvider.getProjectData();
const fileTitle = title || 'ontime data';
@@ -77,7 +77,7 @@ export const dbDownload = async (req, res) => {
* @param _res
* @param options
*/
async function parseFile(file, _req, _res, options) {
async function parseFile(file, _req: Request, _res: Response, options: ExcelImportOptions) {
if (!fs.existsSync(file)) {
throw new Error('Upload failed');
}
@@ -85,6 +85,10 @@ async function parseFile(file, _req, _res, options) {
return result.data;
}
export type ParsingOptions = {
onlyRundown?: 'true' | 'false';
};
/**
* parse an uploaded file and apply its parsed objects
* @param file
@@ -93,7 +97,7 @@ async function parseFile(file, _req, _res, options) {
* @param [options]
* @returns {Promise<void>}
*/
const parseAndApply = async (file, _req, res, options) => {
const parseAndApply = async (file, _req: Request, res: Response, options) => {
const result = await parseFile(file, _req, res, options);
runtimeService.stop();
@@ -134,7 +138,7 @@ const getNetworkInterfaces = () => {
// Create controller for GET request to '/ontime/info'
// Returns -
export const getInfo = async (req: Request, res: Response<GetInfo>) => {
export const getInfo = async (_req: Request, res: Response<GetInfo>) => {
const { version, serverPort } = DataProvider.getSettings();
const osc = DataProvider.getOsc();
@@ -155,14 +159,14 @@ export const getInfo = async (req: Request, res: Response<GetInfo>) => {
// Create controller for POST request to '/ontime/aliases'
// Returns -
export const getAliases = async (req, res) => {
export const getAliases = async (_req: Request, res: Response) => {
const aliases = DataProvider.getAliases();
res.status(200).send(aliases);
};
// Create controller for POST request to '/ontime/aliases'
// Returns ACK message
export const postAliases = async (req, res) => {
export const postAliases = async (req: Request, res: Response) => {
if (failIsNotArray(req.body, res)) {
return;
}
@@ -178,20 +182,20 @@ export const postAliases = async (req, res) => {
await DataProvider.setAliases(newAliases);
res.status(200).send(newAliases);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
// Create controller for GET request to '/ontime/userfields'
// Returns -
export const getUserFields = async (req, res) => {
export const getUserFields = async (_req: Request, res: Response) => {
const userFields = DataProvider.getUserFields();
res.status(200).send(userFields);
};
// Create controller for POST request to '/ontime/userfields'
// Returns ACK message
export const postUserFields = async (req, res) => {
export const postUserFields = async (req: Request, res: Response) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -201,13 +205,13 @@ export const postUserFields = async (req, res) => {
await DataProvider.setUserFields(newData);
res.status(200).send(newData);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
// Create controller for POST request to '/ontime/settings'
// Returns -
export const getSettings = async (req, res) => {
export const getSettings = async (_req: Request, res: Response) => {
const settings = DataProvider.getSettings();
res.status(200).send(settings);
};
@@ -227,7 +231,7 @@ function extractPin(value: string | undefined | null, fallback: string | null):
// Create controller for POST request to '/ontime/settings'
// Returns ACK message
export const postSettings = async (req, res) => {
export const postSettings = async (req: Request, res: Response) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -264,7 +268,7 @@ export const postSettings = async (req, res) => {
await DataProvider.setSettings(newData);
res.status(200).send(newData);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
@@ -272,7 +276,7 @@ export const postSettings = async (req, res) => {
* @description Get view Settings
* @method GET
*/
export const getViewSettings = async (req, res) => {
export const getViewSettings = async (_req: Request, res: Response) => {
const views = DataProvider.getViewSettings();
res.status(200).send(views);
};
@@ -281,7 +285,7 @@ export const getViewSettings = async (req, res) => {
* @description Change view Settings
* @method POST
*/
export const postViewSettings = async (req, res) => {
export const postViewSettings = async (req: Request, res: Response) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -299,20 +303,20 @@ export const postViewSettings = async (req, res) => {
await DataProvider.setViewSettings(newData);
res.status(200).send(newData);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
// Create controller for GET request to '/ontime/osc'
// Returns -
export const getOSC = async (req, res) => {
export const getOSC = async (_req: Request, res: Response) => {
const osc = DataProvider.getOsc();
res.status(200).send(osc);
};
// Create controller for POST request to '/ontime/osc'
// Returns ACK message
export const postOSC = async (req, res) => {
export const postOSC = async (req: Request, res: Response) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -333,11 +337,11 @@ export const postOSC = async (req, res) => {
res.send(oscSettings).status(200);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
export const postOscSubscriptions = async (req, res) => {
export const postOscSubscriptions = async (req: Request, res: Response) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -354,18 +358,18 @@ export const postOscSubscriptions = async (req, res) => {
res.send(oscSettings).status(200);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
// Create controller for GET request to '/ontime/http'
export const getHTTP = async (_req, res: Response<HttpSettings>) => {
export const getHTTP = async (_req: Request, res: Response<HttpSettings>) => {
const http = DataProvider.getHttp();
res.status(200).send(http);
};
// Create controller for POST request to '/ontime/http'
export const postHTTP = async (req, res) => {
export const postHTTP = async (req: Request, res: Response) => {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -386,11 +390,11 @@ export const postHTTP = async (req, res) => {
res.send(httpSettings).status(200);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
export async function patchPartialProjectFile(req, res) {
export async function patchPartialProjectFile(req: Request, res: Response) {
if (failEmptyObjects(req.body, res)) {
return;
}
@@ -414,14 +418,14 @@ export async function patchPartialProjectFile(req, res) {
}
res.status(200).send();
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
}
/**
* uploads, parses and applies the data from a given file
*/
export const dbUpload = async (req, res) => {
export const dbUpload = async (req: Request, res: Response) => {
if (!req.file) {
res.status(400).send({ message: 'File not found' });
return;
@@ -440,7 +444,7 @@ export const dbUpload = async (req, res) => {
* uploads and parses an excel file
* @returns parsed result
*/
export async function previewExcel(req, res) {
export async function previewExcel(req, res: Response) {
if (!req.file) {
res.status(400).send({ message: 'File not found' });
return;
@@ -452,7 +456,7 @@ export async function previewExcel(req, res) {
const data = await parseFile(file, req, res, options);
res.status(200).send(data);
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
}
@@ -475,7 +479,7 @@ export const postNew: RequestHandler = async (req, res) => {
await deleteAllEvents();
res.status(201).send(newData);
} catch (error) {
res.status(400).send({ message: error.toString() });
res.status(400).send({ message: String(error) });
}
};
@@ -497,7 +501,7 @@ export const listProjects: RequestHandler = async (_, res: Response<ProjectFileL
lastLoadedProject: lastLoadedProjectName,
});
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -523,7 +527,7 @@ export const loadProject: RequestHandler = async (req, res) => {
message: `Loaded project ${filename}`,
});
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -537,7 +541,7 @@ export const loadProject: RequestHandler = async (req, res) => {
* a 409 status if there are validation errors,
* or a 500 status with an error message in case of an exception.
*/
export const duplicateProjectFile: RequestHandler = async (req, res) => {
export const duplicateProjectFile: RequestHandler = async (req: Request, res: Response) => {
try {
const { filename } = req.params;
const { newFilename } = req.body;
@@ -557,7 +561,7 @@ export const duplicateProjectFile: RequestHandler = async (req, res) => {
message: `Duplicated project ${filename} to ${newFilename}`,
});
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -571,7 +575,7 @@ export const duplicateProjectFile: RequestHandler = async (req, res) => {
* a 409 status if there are validation errors,
* or a 500 status with an error message in case of an exception.
*/
export const renameProjectFile: RequestHandler = async (req, res) => {
export const renameProjectFile: RequestHandler = async (req: Request, res: Response) => {
try {
const { newFilename } = req.body;
const { filename } = req.params;
@@ -599,7 +603,7 @@ export const renameProjectFile: RequestHandler = async (req, res) => {
message: `Renamed project ${filename} to ${newFilename}`,
});
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -612,7 +616,7 @@ export const renameProjectFile: RequestHandler = async (req, res) => {
* a 409 status if there are validation errors,
* or a 500 status with an error message in case of an exception.
*/
export const createProjectFile: RequestHandler = async (req, res) => {
export const createProjectFile: RequestHandler = async (req: Request, res: Response) => {
try {
const { filename } = req.body;
@@ -624,14 +628,13 @@ export const createProjectFile: RequestHandler = async (req, res) => {
return res.status(409).send({ message: errors.join(', ') });
}
console.log(`----------------> Creating directory createProjectFile: ${projectFilePath}`);
await writeFile(projectFilePath, JSON.stringify(dbModel));
res.status(200).send({
message: `Created project ${filename}`,
});
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -645,7 +648,7 @@ export const createProjectFile: RequestHandler = async (req, res) => {
* a 409 status if there are validation errors,
* or a 500 status with an error message in case of an exception.
*/
export const deleteProjectFile: RequestHandler = async (req, res) => {
export const deleteProjectFile: RequestHandler = async (req: Request, res: Response) => {
try {
const { filename } = req.params;
@@ -669,7 +672,7 @@ export const deleteProjectFile: RequestHandler = async (req, res) => {
message: `Deleted project ${filename}`,
});
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -678,7 +681,7 @@ export const deleteProjectFile: RequestHandler = async (req, res) => {
* @description SETP-1 POST Client Secrect
* @returns parsed result
*/
export async function uploadSheetClientFile(req, res) {
export async function uploadSheetClientFile(req, res: Response) {
if (!req.file.path) {
res.status(400).send({ message: 'File not found' });
return;
@@ -688,7 +691,7 @@ export async function uploadSheetClientFile(req, res) {
await sheet.saveClientSecrets(client);
res.status(200).send('OK');
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
fs.unlink(req.file.path, (err) => {
if (err) logger.error(LogOrigin.Server, err.message);
@@ -698,7 +701,7 @@ export async function uploadSheetClientFile(req, res) {
/**
* @description STEP-1 GET Client Secrect status
*/
export const getClientSecrect = async (req, res) => {
export const getClientSecrect = async (req: Request, res: Response) => {
try {
const clientSecrectExists = await sheet.testClientSecret();
if (clientSecrectExists) {
@@ -707,31 +710,31 @@ export const getClientSecrect = async (req, res) => {
res.status(500).send({ message: 'The Client ID does not exist' });
}
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
/**
* @description STEP-2 GET sheet authentication url
*/
export async function getAuthenticationUrl(req, res) {
export async function getAuthenticationUrl(_req: Request, res: Response) {
try {
const authUrl = await sheet.openAuthServer();
res.status(200).send(authUrl);
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
}
/**
* @description STEP-2 GET sheet authentication status
*/
export const getAuthentication = async (req, res) => {
export const getAuthentication = async (_req: Request, res: Response) => {
try {
await sheet.testAuthentication();
res.status(200).send();
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -739,7 +742,7 @@ export const getAuthentication = async (req, res) => {
* @description STEP-3 POST sheet id
* @returns list of worksheets
*/
export const postId = async (req, res) => {
export const postId = async (req: Request, res: Response) => {
try {
const { id } = req.body;
if (id.lenght < 40) {
@@ -748,20 +751,20 @@ export const postId = async (req, res) => {
const state = await sheet.testSheetId(id);
res.status(200).send(state);
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
/**
* @description STEP-4 POST worksheet
*/
export const postWorksheet = async (req, res) => {
export const postWorksheet = async (req: Request, res: Response) => {
try {
const { worksheet, id } = req.body;
const state = await sheet.testWorksheet(worksheet, id);
res.status(200).send(state);
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
};
@@ -769,25 +772,25 @@ export const postWorksheet = async (req, res) => {
* @description STEP-5 POST download undown to sheet
* @returns parsed result
*/
export async function pullSheet(req, res) {
export async function pullSheet(req: Request, res: Response) {
try {
const { id, options } = req.body;
const data = await sheet.pull(id, options);
res.status(200).send(data);
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
}
/**
* @description STEP-5 POST upload rundown to sheet
*/
export async function pushSheet(req, res) {
export async function pushSheet(req: Request, res: Response) {
try {
const { id, options } = req.body;
await sheet.push(id, options);
res.status(200).send();
} catch (error) {
res.status(500).send({ message: error.toString() });
res.status(500).send({ message: String(error) });
}
}
@@ -255,7 +255,7 @@ export const validateProjectCreate = [
*
*/
export const validateProjectFiles = (projectFiles: { filename?: string; newFilename?: string }): Array<string> => {
const errors = [];
const errors: string[] = [];
if (projectFiles.filename) {
const projectFilePath = join(uploadsFolderPath, projectFiles.filename);
+1 -1
View File
@@ -35,7 +35,7 @@ const populateDb = () => {
* @param adapterToUse
* @return {Promise<number|*>}
*/
const parseDb = async (fileToRead, adapterToUse) => {
const parseDb = async (fileToRead: string, adapterToUse: Low<DatabaseModel>) => {
if (validateFile(fileToRead)) {
await adapterToUse.read();
} else {
+1 -1
View File
@@ -81,7 +81,7 @@ export class TimerService {
const newState = runtimeState.getState();
// handle end action if there was a timer playing
if (newState.timer.playback === Playback.Play) {
if (newState.timer.playback === Playback.Play && newState.eventNow) {
if (newState.eventNow.endAction === EndAction.Stop) {
runtimeState.stop();
} else if (newState.eventNow.endAction === EndAction.LoadNext) {
@@ -860,7 +860,7 @@ describe('getRollTimers()', () => {
publicIndex: null,
nextIndex: 0,
publicNextIndex: 4,
timeToNext: dayInMs - now + eventlist[0].timeStart,
timeToNext: dayInMs - now + eventlist[0].timeStart!,
nextEvent: eventlist[0],
nextPublicEvent: eventlist[4],
currentEvent: null,
@@ -887,7 +887,7 @@ describe('getRollTimers()', () => {
publicIndex: null,
nextIndex: 0,
publicNextIndex: 0,
timeToNext: dayInMs - now + singleEventList[0].timeStart,
timeToNext: dayInMs - now + singleEventList[0].timeStart!,
nextEvent: singleEventList[0],
nextPublicEvent: singleEventList[0],
currentEvent: null,
@@ -1,10 +1,11 @@
import { MaybeNumber } from 'ontime-types';
import { millisToString, removeLeadingZero } from 'ontime-utils';
// any value inside double curly braces {{val}}
const placeholderRegex = /{{(.*?)}}/g;
function formatDisplayFromString(value: string, hideZero = false): string {
let valueInNumber = null;
let valueInNumber: MaybeNumber = null;
if (value !== 'null') {
const parsedValue = Number(value);
@@ -48,7 +49,7 @@ export function parseTemplateNested(template: string, state: object, humanReadab
for (const match of matches) {
const variableName = match[1];
const variableParts = variableName.split('.');
let value = undefined;
let value: string | undefined = undefined;
if (variableParts[0] === 'human') {
const lookupKey = variableParts[1];
@@ -4,7 +4,7 @@ import { throttle } from '../../utils/throttle.js';
import type { PublishFn } from '../../stores/EventStore.js';
let instance;
let instance: MessageService | null = null;
class MessageService {
timer: TimerMessage;
@@ -56,7 +56,7 @@ class MessageService {
init(publish: PublishFn) {
this.publish = publish;
this.throttledSet = throttle((key, value) => this.publish(key, value), 100);
this.throttledSet = throttle((key, value) => this.publish?.(key, value), 100);
}
getState(): MessageState {
@@ -104,7 +104,8 @@ export async function editEvent(patch: Partial<OntimeEvent> | Partial<OntimeBloc
}
const scopedMutation = cache.mutateCache(cache.edit);
const { newEvent } = await scopedMutation({ patch, eventId: patch.id });
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know patch has an id
const { newEvent } = await scopedMutation({ patch, eventId: patch.id! });
notifyChanges({ timer: [patch.id], external: true });
@@ -104,7 +104,7 @@ export function get(): Readonly<RundownCache> {
}
type CommonParams = { persistedRundown: OntimeRundown };
type MutationParams<T> = T & Partial<CommonParams>;
type MutationParams<T> = T & CommonParams;
type MutatingReturn = {
newRundown: OntimeRundown;
newEvent?: OntimeRundownEntry;
@@ -166,6 +166,9 @@ class RuntimeService {
*/
startById(eventId: string): boolean {
const event = getEventWithId(eventId);
if (!event) {
return false;
}
const success = this.loadEvent(event);
if (success) {
this.start();
@@ -180,6 +183,9 @@ class RuntimeService {
*/
startByIndex(eventIndex: number): boolean {
const event = getEventAtIndex(eventIndex);
if (!event) {
return false;
}
const success = this.loadEvent(event);
if (success) {
this.start();
@@ -194,6 +200,9 @@ class RuntimeService {
*/
startByCue(cue: string): boolean {
const event = getEventWithCue(cue);
if (!event) {
return false;
}
const success = this.loadEvent(event);
if (success) {
this.start();
@@ -208,6 +217,9 @@ class RuntimeService {
*/
loadById(eventId: string): boolean {
const event = getEventWithId(eventId);
if (!event) {
return false;
}
const success = this.loadEvent(event);
return success;
}
@@ -219,6 +231,9 @@ class RuntimeService {
*/
loadByIndex(eventIndex: number): boolean {
const event = getEventAtIndex(eventIndex);
if (!event) {
return false;
}
const success = this.loadEvent(event);
return success;
}
@@ -230,6 +245,9 @@ class RuntimeService {
*/
loadByCue(cue: string): boolean {
const event = getEventWithCue(cue);
if (!event) {
return false;
}
const success = this.loadEvent(event);
return success;
}
+7 -1
View File
@@ -14,6 +14,11 @@ export const normaliseEndTime = (start: number, end: number) => (end < start ? e
*/
export function getExpectedFinish(state: RuntimeState): MaybeNumber {
const { startedAt, finishedAt, duration, addedTime } = state.timer;
if (state.eventNow === null) {
return null;
}
const { timerType, timeEnd } = state.eventNow;
const { pausedAt } = state._timer;
const { clock } = state;
@@ -33,7 +38,8 @@ export function getExpectedFinish(state: RuntimeState): MaybeNumber {
}
// handle events that finish the day after
const expectedFinish = startedAt + duration + addedTime + pausedTime;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- duration exists if ther eis a timer
const expectedFinish = startedAt + duration! + addedTime + pausedTime;
if (expectedFinish > dayInMs) {
return expectedFinish - dayInMs;
}
+3 -3
View File
@@ -19,13 +19,13 @@ export function getAppDataPath(): string {
switch (process.platform) {
case 'darwin': {
return path.join(process.env.HOME, 'Library', 'Application Support', 'Ontime');
return path.join(process.env.HOME!, 'Library', 'Application Support', 'Ontime');
}
case 'win32': {
return path.join(process.env.APPDATA, 'Ontime');
return path.join(process.env.APPDATA!, 'Ontime');
}
case 'linux': {
return path.join(process.env.HOME, '.Ontime');
return path.join(process.env.HOME!, '.Ontime');
}
default: {
throw new Error('Could not resolve public folder for platform');
@@ -77,7 +77,7 @@ describe('mutation on runtimeState', () => {
// 1. Load event
load(mockEvent, [mockEvent]);
let newState = getState();
expect(newState.eventNow.id).toBe(mockEvent.id);
expect(newState.eventNow?.id).toBe(mockEvent.id);
expect(newState.timer.playback).toBe(Playback.Armed);
expect(newState.clock).not.toBe(666);
+1 -1
View File
@@ -8,7 +8,7 @@
*/
export function throttle<T extends any[], U>(cb: (...args: T) => U, delay: number) {
let shouldWait = false;
let waitingArgs;
let waitingArgs: T | null = null;
const timeoutFunc = () => {
if (waitingArgs == null) {
shouldWait = false;
+5 -4
View File
@@ -1,4 +1,5 @@
import multer from 'multer';
import { Request } from 'express';
import multer, { FileFilterCallback } from 'multer';
import path from 'path';
import fs from 'fs';
@@ -6,12 +7,12 @@ import { EXCEL_MIME, JSON_MIME } from './parser.js';
import { ensureDirectory } from './fileManagement.js';
import { getAppDataPath } from '../setup.js';
function generateNewFileName(filePath, callback) {
function generateNewFileName(filePath: string, callback: (newName: string) => void) {
const baseName = path.basename(filePath, path.extname(filePath));
const extension = path.extname(filePath);
let counter = 1;
const checkExistence = (newPath) => {
const checkExistence = (newPath: string) => {
fs.access(newPath, fs.constants.F_OK, (err) => {
if (err) {
// File with the new name does not exist, use this name
@@ -64,7 +65,7 @@ const storage = multer.diskStorage({
* @argument file - reference to file
* @return {boolean} - file allowed
*/
const filterAllowed = (req, file, cb) => {
const filterAllowed = (_req: Request, file: Express.Multer.File, cb: FileFilterCallback) => {
if (file.mimetype.includes(JSON_MIME) || file.mimetype.includes(EXCEL_MIME)) {
cb(null, true);
} else {
+2 -2
View File
@@ -12,7 +12,7 @@
"experimentalDecorators": true,
},
"include": [
"src/**/*"
"src/**/*.ts",
"src/**/*.js",
],
"exclude": ["node_modules", "build"],
}
+18
View File
@@ -304,9 +304,15 @@ importers:
specifier: ^8.13.0
version: 8.13.0
devDependencies:
'@types/cors':
specifier: ^2.8.17
version: 2.8.17
'@types/express':
specifier: ^4.17.17
version: 4.17.17
'@types/multer':
specifier: ^1.4.11
version: 1.4.11
'@types/node':
specifier: ^18.11.18
version: 18.11.18
@@ -3161,6 +3167,12 @@ packages:
'@types/node': 18.19.3
dev: true
/@types/cors@2.8.17:
resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==}
dependencies:
'@types/node': 18.19.3
dev: true
/@types/debug@4.1.12:
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
dependencies:
@@ -3252,6 +3264,12 @@ packages:
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
dev: true
/@types/multer@1.4.11:
resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==}
dependencies:
'@types/express': 4.17.17
dev: true
/@types/node-osc@6.0.2:
resolution: {integrity: sha512-/TxCH+NlDoI3hFA6b2O91dpnPAqBDkLb2HEIv5hMVdKnCiWTdJJv2sVnQdX38sBgnals8TjCQEGii+OcMVf2fg==}
dependencies: