diff --git a/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx b/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx index b3268fcda..317c03d19 100644 --- a/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx +++ b/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx @@ -23,7 +23,7 @@ class ErrorBoundary extends React.Component { componentDidCatch(error, info) { this.setState({ - error: error, + error, errorInfo: info, }); diff --git a/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx b/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx index 960194f33..2947ab64f 100644 --- a/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx +++ b/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx @@ -12,7 +12,7 @@ import { useDisclosure, } from '@chakra-ui/react'; -import { useLocalStorage } from '../../../common/hooks/useLocalStorage'; +import { useLocalStorage } from '../../hooks/useLocalStorage'; import ParamInput from './ParamInput'; import { ParamField } from './types'; diff --git a/apps/client/src/features/menu/RundownMenu.tsx b/apps/client/src/features/menu/RundownMenu.tsx index 0b3a30240..b1bf937e1 100644 --- a/apps/client/src/features/menu/RundownMenu.tsx +++ b/apps/client/src/features/menu/RundownMenu.tsx @@ -7,7 +7,7 @@ import { IoTrashOutline } from '@react-icons/all-files/io5/IoTrashOutline'; import { SupportedEvent } from 'ontime-types'; import { useEventAction } from '../../common/hooks/useEventAction'; -import { useEventSelection } from '../../features/rundown/useEventSelection'; +import { useEventSelection } from '../rundown/useEventSelection'; const RundownMenu = ({ children }: { children: ReactNode }) => { const { clearSelectedEvents } = useEventSelection(); diff --git a/apps/client/src/features/operator/Operator.tsx b/apps/client/src/features/operator/Operator.tsx index 9a9b40b66..6a50f6328 100644 --- a/apps/client/src/features/operator/Operator.tsx +++ b/apps/client/src/features/operator/Operator.tsx @@ -52,7 +52,7 @@ export default function Operator() { const scrollRef = useRef(null); const scrollToComponent = useFollowComponent({ followRef: selectedRef, - scrollRef: scrollRef, + scrollRef, doFollow: !lockAutoScroll, topOffset: selectedOffset, }); diff --git a/apps/client/src/features/rundown/useEventSelection.ts b/apps/client/src/features/rundown/useEventSelection.ts index fad93bffd..7308266a1 100644 --- a/apps/client/src/features/rundown/useEventSelection.ts +++ b/apps/client/src/features/rundown/useEventSelection.ts @@ -44,7 +44,7 @@ export const useEventSelection = create()((set, get) => ({ selectedEvents.delete(id); return set({ - selectedEvents: selectedEvents, + selectedEvents, anchoredIndex: newAnchoredIndex?.index ?? 0, }); } diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 425bd6346..406ae2d97 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -200,7 +200,7 @@ export const startServer = async () => { * @param overrideConfig * @return {Promise} */ -export const startOSCServer = async (overrideConfig = null) => { +export const startOSCServer = async (overrideConfig?: { port: number }) => { checkStart(OntimeStartOrder.InitIO); const { osc } = DataProvider.getData(); diff --git a/apps/server/src/classes/simple-timer/SimpleTimer.ts b/apps/server/src/classes/simple-timer/SimpleTimer.ts index d6a5b4181..baea1e712 100644 --- a/apps/server/src/classes/simple-timer/SimpleTimer.ts +++ b/apps/server/src/classes/simple-timer/SimpleTimer.ts @@ -10,8 +10,6 @@ export class SimpleTimer { private startedAt: number | null = null; private pausedAt: number | null = null; - constructor() {} - public reset() { this.state = { duration: 0, diff --git a/apps/server/src/classes/simple-timer/__tests__/SimpleTimer.test.ts b/apps/server/src/classes/simple-timer/__tests__/SimpleTimer.test.ts index 9575a0213..7409ff6f9 100644 --- a/apps/server/src/classes/simple-timer/__tests__/SimpleTimer.test.ts +++ b/apps/server/src/classes/simple-timer/__tests__/SimpleTimer.test.ts @@ -72,7 +72,8 @@ describe('SimpleTimer count-down', () => { expect(newState).toStrictEqual(expected); newState = timer.update(1800); - (expected.current = initialTime - 1800 + pausedTime), expect(newState).toStrictEqual(expected); + expected.current = initialTime - 1800 + pausedTime; + expect(newState).toStrictEqual(expected); }); test('stopping the timer clears the running data', () => { diff --git a/apps/server/src/controllers/integrationController.config.ts b/apps/server/src/controllers/integrationController.config.ts index 32ad21543..d65562dd5 100644 --- a/apps/server/src/controllers/integrationController.config.ts +++ b/apps/server/src/controllers/integrationController.config.ts @@ -52,7 +52,7 @@ export function updateEvent( const event = EventLoader.getEventWithId(eventId); if (event) { if (!isOntimeEvent(event)) { - throw new Error(`Can only update events`); + throw new Error('Can only update events'); } const propertiesToUpdate = { [propertyName]: newValue }; diff --git a/apps/server/src/controllers/ontimeController.ts b/apps/server/src/controllers/ontimeController.ts index ce1e1ec19..f0aa3d5bb 100644 --- a/apps/server/src/controllers/ontimeController.ts +++ b/apps/server/src/controllers/ontimeController.ts @@ -115,7 +115,7 @@ const parseAndApply = async (file, _req, res, options) => { */ const getNetworkInterfaces = () => { const nets = networkInterfaces(); - const results = []; + const results: { name: string; address: string }[] = []; for (const name of Object.keys(nets)) { for (const net of nets[name]) { diff --git a/apps/server/src/modules/loadDemo.ts b/apps/server/src/modules/loadDemo.ts index 84d4361bf..b94bf28cd 100644 --- a/apps/server/src/modules/loadDemo.ts +++ b/apps/server/src/modules/loadDemo.ts @@ -12,7 +12,7 @@ export const populateDemo = () => { Promise.all( resolveDemoPath.map((to, index) => { const from = pathToStartDemo[index]; - copyFile(from, to); + return copyFile(from, to); }), ); } catch (_) { diff --git a/apps/server/src/services/integration-service/HttpIntegration.ts b/apps/server/src/services/integration-service/HttpIntegration.ts index 755fa50b4..f325eddb7 100644 --- a/apps/server/src/services/integration-service/HttpIntegration.ts +++ b/apps/server/src/services/integration-service/HttpIntegration.ts @@ -34,18 +34,10 @@ export class HttpIntegration implements IIntegration { } this.initSubscriptions(subscriptions); - - try { - return { - success: true, - message: `HTTP integration client ready`, - }; - } catch (error) { - return { - success: false, - message: `Failed initialising HTTP integration: ${error}`, - }; - } + return { + success: true, + message: 'HTTP integration client ready', + }; } initSubscriptions(subscriptionOptions: HttpSubscription) { diff --git a/apps/server/src/services/integration-service/OscIntegration.ts b/apps/server/src/services/integration-service/OscIntegration.ts index 6cf8fe958..f1652e704 100644 --- a/apps/server/src/services/integration-service/OscIntegration.ts +++ b/apps/server/src/services/integration-service/OscIntegration.ts @@ -99,6 +99,10 @@ export class OscIntegration implements IIntegration { } emit(path: string, payload?: ArgumentType) { + if (!this.oscClient) { + return; + } + const message = new Message(path); if (payload) { try { diff --git a/apps/server/src/services/runtime-service/RuntimeService.ts b/apps/server/src/services/runtime-service/RuntimeService.ts index aa55b48c7..1573b41e6 100644 --- a/apps/server/src/services/runtime-service/RuntimeService.ts +++ b/apps/server/src/services/runtime-service/RuntimeService.ts @@ -14,8 +14,6 @@ import * as runtimeState from '../../stores/runtimeState.js'; class RuntimeService { private eventTimer: TimerService | null = null; - constructor() {} - init(resumable: RestorePoint | null) { logger.info(LogOrigin.Server, 'Runtime service started'); // TODO: refresh at 32ms, slowing down now to keep UI responsive while we dont have granular updates @@ -339,6 +337,11 @@ class RuntimeService { const { selectedEventId, playback } = restorePoint; if (playback === Playback.Roll) { this.roll(); + return; + } + + if (!selectedEventId) { + return; } // the db would have to change for the event not to exist diff --git a/apps/server/src/services/timerUtils.ts b/apps/server/src/services/timerUtils.ts index b80e0027f..695b71ce4 100644 --- a/apps/server/src/services/timerUtils.ts +++ b/apps/server/src/services/timerUtils.ts @@ -1,4 +1,4 @@ -import { MaybeNumber, OntimeEvent, TimerType } from 'ontime-types'; +import { MaybeNumber, MaybeString, OntimeEvent, TimerType } from 'ontime-types'; import { dayInMs } from 'ontime-utils'; import { RuntimeState } from '../stores/runtimeState.js'; import { sortArrayByProperty } from '../utils/arrayUtils.js'; @@ -94,13 +94,26 @@ export function skippedOutOfEvent(state: RuntimeState, previousTime: number, ski return hasSkipped && (adjustedClock > adjustedExpectedFinish || adjustedClock < startedAt); } +type RollTimers = { + nowIndex: MaybeNumber; + nowId: MaybeString; + publicIndex: MaybeNumber; + nextIndex: MaybeNumber; + publicNextIndex: MaybeNumber; + timeToNext: MaybeNumber; + nextEvent: OntimeEvent | null; + nextPublicEvent: OntimeEvent | null; + currentEvent: OntimeEvent | null; + currentPublicEvent: OntimeEvent | null; +}; + /** * Finds loading information given a current rundown and time * @param {OntimeEvent[]} rundown - List of playable events * @param {number} timeNow - time now in ms * @returns {{}} */ -export const getRollTimers = (rundown: OntimeEvent[], timeNow: number) => { +export const getRollTimers = (rundown: OntimeEvent[], timeNow: number): RollTimers => { let nowIndex: number | null = null; // index of event now let nowId: string | null = null; // id of event now let publicIndex: number | null = null; // index of public event now diff --git a/apps/server/src/utils/sheetsAuth.ts b/apps/server/src/utils/sheetsAuth.ts index d0f0553b7..64d98193c 100644 --- a/apps/server/src/utils/sheetsAuth.ts +++ b/apps/server/src/utils/sheetsAuth.ts @@ -100,7 +100,7 @@ class Sheet { this.authServerTimeout = setTimeout( () => { Sheet.authUrl = null; - server.unref; + server.unref(); }, 2 * 60 * 1000, ); @@ -140,7 +140,7 @@ class Sheet { } if (!searchParams.has('code')) { res.end('No authentication code provided.'); - logger.info(LogOrigin.Server, `Sheet: Cannot read authentication code`); + logger.info(LogOrigin.Server, 'Sheet: Cannot read authentication code'); return; } const code = searchParams.get('code'); @@ -151,7 +151,7 @@ class Sheet { client.credentials = tokens; Sheet.client = client; res.end('Authentication successful! Please close this tab and return to OnTime.'); - logger.info(LogOrigin.Server, `Sheet: Authentication successful`); + logger.info(LogOrigin.Server, 'Sheet: Authentication successful'); } catch (e) { logger.error(LogOrigin.Server, `Sheet: ${e}`); } finally { @@ -277,7 +277,7 @@ class Sheet { spreadsheetId: id, valueRenderOption: 'FORMATTED_VALUE', majorDimension: 'ROWS', - range: range, + range, }); if (readResponse.status === 200) { const { rundownMetadata } = parseExcel(readResponse.data.values, options); @@ -364,7 +364,7 @@ class Sheet { const dataFromSheet = parseExcel(googleResponse.data.values, options); res.data.rundown = parseRundown(dataFromSheet); if (res.data.rundown.length < 1) { - throw new Error(`Sheet: Could not find data to import in the worksheet`); + throw new Error('Sheet: Could not find data to import in the worksheet'); } res.data.userFields = parseUserFields(dataFromSheet); return res; diff --git a/apps/server/src/utils/upload.js b/apps/server/src/utils/upload.ts similarity index 90% rename from apps/server/src/utils/upload.js rename to apps/server/src/utils/upload.ts index c9b7ff5cd..58144f72c 100644 --- a/apps/server/src/utils/upload.js +++ b/apps/server/src/utils/upload.ts @@ -7,8 +7,8 @@ import { ensureDirectory } from './fileManagement.js'; import { getAppDataPath } from '../setup.js'; function generateNewFileName(filePath, callback) { - let baseName = path.basename(filePath, path.extname(filePath)); - let extension = path.extname(filePath); + const baseName = path.basename(filePath, path.extname(filePath)); + const extension = path.extname(filePath); let counter = 1; const checkExistence = (newPath) => { @@ -24,7 +24,7 @@ function generateNewFileName(filePath, callback) { }); }; - let newPath = path.join(path.dirname(filePath), `${baseName} (${counter})${extension}`); + const newPath = path.join(path.dirname(filePath), `${baseName} (${counter})${extension}`); checkExistence(newPath); } @@ -75,6 +75,6 @@ const filterAllowed = (req, file, cb) => { // Build multer uploader for a single file export const uploadFile = multer({ - storage: storage, + storage, fileFilter: filterAllowed, }).single('userFile');