From 7c1d2f4554658dfdc34ced2ca788c7ece67ce017 Mon Sep 17 00:00:00 2001 From: Alex Christoffer Rasmussen Date: Sun, 26 Apr 2026 17:32:50 +0200 Subject: [PATCH] refactor: small cleanups (#2059) * refactor: remove unneeded async * chore: add express Router type to all routes * refactor: don't use index in react key * refactor: correctly get error message in excel route * refactor: avoid exporting muteable values --- .../components/error-boundary/ErrorBoundary.jsx | 5 ++--- .../view-params-editor/ViewParamsSection.tsx | 4 ++-- apps/client/src/common/utils/socket.ts | 6 ++++-- .../src/views/project-info/ProjectInfo.tsx | 1 + .../src/api-data/automation/automation.router.ts | 4 ++-- .../custom-fields/customFields.router.ts | 6 +++--- .../api-data/custom-views/customViews.router.ts | 4 ++-- apps/server/src/api-data/db/db.router.ts | 4 ++-- apps/server/src/api-data/excel/excel.router.ts | 16 ++++++++++------ apps/server/src/api-data/index.ts | 4 ++-- .../api-data/project-data/projectData.router.ts | 4 ++-- apps/server/src/api-data/report/report.router.ts | 4 ++-- .../src/api-data/rundown/rundown.router.ts | 4 ++-- .../src/api-data/session/session.router.ts | 8 ++++---- .../src/api-data/session/session.service.ts | 2 +- .../src/api-data/settings/settings.router.ts | 4 ++-- .../src/api-data/sheets/sheets.controller.ts | 4 ++-- apps/server/src/api-data/sheets/sheets.router.ts | 4 ++-- .../api-data/url-presets/urlPresets.router.ts | 4 ++-- .../view-settings/viewSettings.router.ts | 4 ++-- .../src/api-integration/integration.router.ts | 4 ++-- apps/server/src/middleware/authenticate.ts | 4 ++-- 22 files changed, 55 insertions(+), 49 deletions(-) diff --git a/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx b/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx index bda907ddc..e6cfeb918 100644 --- a/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx +++ b/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx @@ -1,10 +1,9 @@ // skipcq: JS-C1003 - sentry does not expose itself as an ES Module. import * as Sentry from '@sentry/react'; -/* eslint-disable react/destructuring-assignment */ import React from 'react'; -import { hasConnected, reconnectAttempts } from '../../../common/utils/socket'; import { runtimeStore } from '../../stores/runtime'; +import { getConnectionState, getReconnectAttempts } from '../../utils/socket'; import style from './ErrorBoundary.module.scss'; @@ -37,7 +36,7 @@ class ErrorBoundary extends React.Component { scope.setExtras({ error, store: appState, - hasSocket: { hasConnected, reconnectAttempts }, + hasSocket: { hasConnected: getConnectionState(), reconnectAttempts: getReconnectAttempts() }, }); const eventId = Sentry.captureException(error); this.setState({ eventId, info }); diff --git a/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx b/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx index fe1b73e3c..28e5ea134 100644 --- a/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx +++ b/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx @@ -64,8 +64,8 @@ function SectionContents({ options, collapsed }: SectionContentsProps) { function HiddenContents({ options }: { options: ParamField[] }) { return ( <> - {options.map((option, index) => { - return ; + {options.map((option) => { + return ; })} ); diff --git a/apps/client/src/common/utils/socket.ts b/apps/client/src/common/utils/socket.ts index b000f935f..3c1068048 100644 --- a/apps/client/src/common/utils/socket.ts +++ b/apps/client/src/common/utils/socket.ts @@ -51,8 +51,10 @@ const socketConfig = { offlineAttemptsThreshold: 2, // when we consider the client disconnected } as const; -export let hasConnected = false; -export let reconnectAttempts = 0; +export const getConnectionState = () => hasConnected; +export const getReconnectAttempts = () => reconnectAttempts; +let hasConnected = false; +let reconnectAttempts = 0; export const connectSocket = () => { websocket = new WebSocket(websocketUrl); diff --git a/apps/client/src/views/project-info/ProjectInfo.tsx b/apps/client/src/views/project-info/ProjectInfo.tsx index bae7d896a..fed8b32c1 100644 --- a/apps/client/src/views/project-info/ProjectInfo.tsx +++ b/apps/client/src/views/project-info/ProjectInfo.tsx @@ -80,6 +80,7 @@ function ProjectInfo({ projectData, isMirrored }: ProjectInfoData) { {projectData.custom.map((info, idx) => { const hasUrl = Boolean(info.url); return ( + // oxlint-disable-next-line react/no-array-index-key - we only have the index to go of here
{hasUrl && (
diff --git a/apps/server/src/api-data/automation/automation.router.ts b/apps/server/src/api-data/automation/automation.router.ts index a46ac684e..5d91fc683 100644 --- a/apps/server/src/api-data/automation/automation.router.ts +++ b/apps/server/src/api-data/automation/automation.router.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import express, { Router } from 'express'; import { paramsWithId } from '../validation-utils/validationFunction.js'; import { @@ -21,7 +21,7 @@ import { validateTriggerPatch, } from './automation.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', getAutomationSettings); router.post('/', validateAutomationSettings, postAutomationSettings); diff --git a/apps/server/src/api-data/custom-fields/customFields.router.ts b/apps/server/src/api-data/custom-fields/customFields.router.ts index e955ae2d7..2bb989a9d 100644 --- a/apps/server/src/api-data/custom-fields/customFields.router.ts +++ b/apps/server/src/api-data/custom-fields/customFields.router.ts @@ -1,5 +1,5 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import { CustomField, CustomFields, ErrorResponse } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; @@ -8,12 +8,12 @@ import { getProjectCustomFields } from '../rundown/rundown.dao.js'; import { createCustomField, deleteCustomField, editCustomField } from '../rundown/rundown.service.js'; import { validateCustomField, validateDeleteCustomField, validateEditCustomField } from './customFields.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); /** * Gets all the custom fields for the project */ -router.get('/', async (_req: Request, res: Response) => { +router.get('/', (_req: Request, res: Response) => { const customFields = getProjectCustomFields(); res.status(200).json(customFields); }); diff --git a/apps/server/src/api-data/custom-views/customViews.router.ts b/apps/server/src/api-data/custom-views/customViews.router.ts index 50e9fe2a8..7f220b346 100644 --- a/apps/server/src/api-data/custom-views/customViews.router.ts +++ b/apps/server/src/api-data/custom-views/customViews.router.ts @@ -1,5 +1,5 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import { type CustomViewsListResponse, type ErrorResponse, type MessageResponse } from 'ontime-types'; import { handleCustomViewsError } from './customViews.errors.js'; @@ -13,7 +13,7 @@ import { } from './customViews.service.js'; import { validateCustomViewSlugParam } from './customViews.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', async (_req: Request, res: Response) => { try { diff --git a/apps/server/src/api-data/db/db.router.ts b/apps/server/src/api-data/db/db.router.ts index 3ce4b1d3f..cdac334c3 100644 --- a/apps/server/src/api-data/db/db.router.ts +++ b/apps/server/src/api-data/db/db.router.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import express, { Router } from 'express'; import { createProjectFile, @@ -24,7 +24,7 @@ import { validateQuickProject, } from './db.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', currentProjectDownload); router.post('/download', validateFilenameBody, projectDownload); diff --git a/apps/server/src/api-data/excel/excel.router.ts b/apps/server/src/api-data/excel/excel.router.ts index fd08c950b..43dfc0223 100644 --- a/apps/server/src/api-data/excel/excel.router.ts +++ b/apps/server/src/api-data/excel/excel.router.ts @@ -1,11 +1,12 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import type { ErrorResponse, SpreadsheetPreviewResponse, SpreadsheetWorksheetMetadata, SpreadsheetWorksheetOptions, } from 'ontime-types'; +import { getErrorMessage } from 'ontime-utils'; import { getDataProvider } from '../../classes/data-provider/DataProvider.js'; import { getProjectCustomFields } from '../rundown/rundown.dao.js'; @@ -19,7 +20,7 @@ import { validateWorksheetMetadataRequest, } from './excel.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.post( '/upload', @@ -32,7 +33,8 @@ router.post( const worksheetOptions = await readExcelFile(filePath); res.status(200).send(worksheetOptions); } catch (error) { - res.status(500).send({ message: String(error) }); + const message = getErrorMessage(error); + res.status(500).send({ message }); } }, ); @@ -46,7 +48,8 @@ router.post( const data = generateRundownPreview(options); res.status(200).send(data); } catch (error) { - res.status(500).send({ message: String(error) }); + const message = getErrorMessage(error); + res.status(500).send({ message }); } }, ); @@ -60,7 +63,8 @@ router.post( const data = getWorksheetMetadata(worksheet); res.status(200).send(data); } catch (error) { - res.status(500).send({ message: String(error) }); + const message = getErrorMessage(error); + res.status(500).send({ message }); } }, ); @@ -75,7 +79,7 @@ router.get('/:rundownId/export', validateRundownExport, (req: Request, res: Resp res.setHeader('Content-Type', EXCEL_MIME); res.setHeader('Content-Length', buffer.length.toString()); res.status(200).send(buffer); - } catch (error) { + } catch (_error) { res.status(500).send({ message: 'Failed to generate Excel file' }); } }); diff --git a/apps/server/src/api-data/index.ts b/apps/server/src/api-data/index.ts index ecbf5e7e3..66803ff1d 100644 --- a/apps/server/src/api-data/index.ts +++ b/apps/server/src/api-data/index.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import express, { Router } from 'express'; import { router as assetsRouter } from './assets/assets.router.js'; import { router as automationsRouter } from './automation/automation.router.js'; @@ -15,7 +15,7 @@ import { router as sheetsRouter } from './sheets/sheets.router.js'; import { router as urlPresetsRouter } from './url-presets/urlPresets.router.js'; import { router as viewSettingsRouter } from './view-settings/viewSettings.router.js'; -export const appRouter = express.Router(); +export const appRouter: Router = express.Router(); appRouter.use('/automations', automationsRouter); appRouter.use('/custom-fields', customFieldsRouter); diff --git a/apps/server/src/api-data/project-data/projectData.router.ts b/apps/server/src/api-data/project-data/projectData.router.ts index 4e2951951..117f0bd8d 100644 --- a/apps/server/src/api-data/project-data/projectData.router.ts +++ b/apps/server/src/api-data/project-data/projectData.router.ts @@ -1,5 +1,5 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import type { ErrorResponse, ProjectData } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; @@ -9,7 +9,7 @@ import { uploadImageFile } from '../db/db.middleware.js'; import * as projectDao from './projectData.dao.js'; import { projectSanitiser } from './projectData.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', (_req: Request, res: Response) => { res.status(200).json(projectDao.getProjectData()); diff --git a/apps/server/src/api-data/report/report.router.ts b/apps/server/src/api-data/report/report.router.ts index 62864c033..94b35dc42 100644 --- a/apps/server/src/api-data/report/report.router.ts +++ b/apps/server/src/api-data/report/report.router.ts @@ -1,10 +1,10 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import { paramsWithId } from '../validation-utils/validationFunction.js'; import * as report from './report.service.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', (_req: Request, res: Response) => { res.status(200).json(report.generate()); diff --git a/apps/server/src/api-data/rundown/rundown.router.ts b/apps/server/src/api-data/rundown/rundown.router.ts index 996900c59..46e33c675 100644 --- a/apps/server/src/api-data/rundown/rundown.router.ts +++ b/apps/server/src/api-data/rundown/rundown.router.ts @@ -1,4 +1,4 @@ -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import express from 'express'; import { ErrorResponse, OntimeEntry, ProjectRundownsList, Rundown } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; @@ -35,7 +35,7 @@ import { validateRundownMutation, } from './rundown.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); // #region operations on project rundowns ========================= diff --git a/apps/server/src/api-data/session/session.router.ts b/apps/server/src/api-data/session/session.router.ts index d4f98c7dd..7627d3058 100644 --- a/apps/server/src/api-data/session/session.router.ts +++ b/apps/server/src/api-data/session/session.router.ts @@ -1,12 +1,12 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import type { ErrorResponse, GetInfo, GetUrl, SessionStats } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; import * as sessionService from './session.service.js'; import { validateGenerateUrl } from './session.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', async (_req: Request, res: Response) => { try { @@ -18,9 +18,9 @@ router.get('/', async (_req: Request, res: Response) => { +router.get('/info', (_req: Request, res: Response) => { try { - const info = await sessionService.getInfo(); + const info = sessionService.getInfo(); res.status(200).send(info); } catch (error) { const message = getErrorMessage(error); diff --git a/apps/server/src/api-data/session/session.service.ts b/apps/server/src/api-data/session/session.service.ts index 884b0cee9..bf67c32bd 100644 --- a/apps/server/src/api-data/session/session.service.ts +++ b/apps/server/src/api-data/session/session.service.ts @@ -37,7 +37,7 @@ export async function getSessionStats(): Promise { /** * Adds business logic to gathering data for the info endpoint */ -export async function getInfo(): Promise { +export function getInfo(): GetInfo { const { version } = getDataProvider().getSettings(); const { port } = portManager.getPort(); diff --git a/apps/server/src/api-data/settings/settings.router.ts b/apps/server/src/api-data/settings/settings.router.ts index 767c72e06..51cbb3d09 100644 --- a/apps/server/src/api-data/settings/settings.router.ts +++ b/apps/server/src/api-data/settings/settings.router.ts @@ -1,5 +1,5 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import { matchedData } from 'express-validator'; import { deepEqual } from 'fast-equals'; import { ErrorResponse, PortInfo, RefetchKey, Settings } from 'ontime-types'; @@ -11,7 +11,7 @@ import { portManager } from '../../classes/port-manager/PortManager.js'; import * as appState from '../../services/app-state-service/AppStateService.js'; import { validateSettings, validateWelcomeDialog, validateServerPort } from './settings.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.post('/welcomedialog', validateWelcomeDialog, async (req: Request, res: Response) => { const show = await appState.setShowWelcomeDialog(req.body.show); diff --git a/apps/server/src/api-data/sheets/sheets.controller.ts b/apps/server/src/api-data/sheets/sheets.controller.ts index e8ac59cd8..2ee1f2255 100644 --- a/apps/server/src/api-data/sheets/sheets.controller.ts +++ b/apps/server/src/api-data/sheets/sheets.controller.ts @@ -56,7 +56,7 @@ export async function requestConnection( /** * Returns the current Google Sheets authentication status for this server session. */ -export async function verifyAuthentication( +export function verifyAuthentication( _req: Request, res: Response<{ authenticated: AuthenticationStatus } | ErrorResponse>, ) { @@ -72,7 +72,7 @@ export async function verifyAuthentication( /** * Clears the current Google Sheets authentication session. */ -export async function revokeAuthentication( +export function revokeAuthentication( _req: Request, res: Response<{ authenticated: AuthenticationStatus } | ErrorResponse>, ) { diff --git a/apps/server/src/api-data/sheets/sheets.router.ts b/apps/server/src/api-data/sheets/sheets.router.ts index d91314ef9..c6c1abe28 100644 --- a/apps/server/src/api-data/sheets/sheets.router.ts +++ b/apps/server/src/api-data/sheets/sheets.router.ts @@ -2,7 +2,7 @@ * This is a feature specific router for integration with google sheets */ -import express from 'express'; +import express, { Router } from 'express'; import { getWorksheetMetadataFromSheet, @@ -21,7 +21,7 @@ import { validateWorksheetMetadata, } from './sheets.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/connect', verifyAuthentication); router.post('/:sheetId/connect', uploadClientSecret, validateRequestConnection, requestConnection); diff --git a/apps/server/src/api-data/url-presets/urlPresets.router.ts b/apps/server/src/api-data/url-presets/urlPresets.router.ts index 6de6fd9a0..81d3ac7f1 100644 --- a/apps/server/src/api-data/url-presets/urlPresets.router.ts +++ b/apps/server/src/api-data/url-presets/urlPresets.router.ts @@ -1,5 +1,5 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import { type ErrorResponse, RefetchKey, type URLPreset } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; @@ -7,7 +7,7 @@ import { sendRefetch } from '../../adapters/WebsocketAdapter.js'; import { getDataProvider } from '../../classes/data-provider/DataProvider.js'; import { validateNewPreset, validatePresetParam, validateUpdatePreset } from './urlPresets.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', (_req: Request, res: Response) => { const presets = getDataProvider().getUrlPresets(); diff --git a/apps/server/src/api-data/view-settings/viewSettings.router.ts b/apps/server/src/api-data/view-settings/viewSettings.router.ts index c15ce646c..9be861544 100644 --- a/apps/server/src/api-data/view-settings/viewSettings.router.ts +++ b/apps/server/src/api-data/view-settings/viewSettings.router.ts @@ -1,5 +1,5 @@ import express from 'express'; -import type { Request, Response } from 'express'; +import type { Request, Response, Router } from 'express'; import { type ErrorResponse, RefetchKey, type ViewSettings } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; @@ -7,7 +7,7 @@ import { sendRefetch } from '../../adapters/WebsocketAdapter.js'; import { getDataProvider } from '../../classes/data-provider/DataProvider.js'; import { validateViewSettings } from './viewSettings.validation.js'; -export const router = express.Router(); +export const router: Router = express.Router(); router.get('/', (_req: Request, res: Response) => { const views = getDataProvider().getViewSettings(); diff --git a/apps/server/src/api-integration/integration.router.ts b/apps/server/src/api-integration/integration.router.ts index 22857427e..b5543cd17 100644 --- a/apps/server/src/api-integration/integration.router.ts +++ b/apps/server/src/api-integration/integration.router.ts @@ -5,7 +5,7 @@ * */ -import express, { type Request, type Response } from 'express'; +import express, { Router, type Request, type Response } from 'express'; import { ErrorResponse, LogOrigin } from 'ontime-types'; import { getErrorMessage } from 'ontime-utils'; @@ -14,7 +14,7 @@ import { logger } from '../classes/Logger.js'; import { isEmptyObject } from '../utils/parserUtils.js'; import { dispatchFromAdapter } from './integration.controller.js'; -export const integrationRouter = express.Router(); +export const integrationRouter: Router = express.Router(); const helloMessage = 'You have reached Ontime API server'; diff --git a/apps/server/src/middleware/authenticate.ts b/apps/server/src/middleware/authenticate.ts index 74b6f9ddf..3b28b23cd 100644 --- a/apps/server/src/middleware/authenticate.ts +++ b/apps/server/src/middleware/authenticate.ts @@ -1,7 +1,7 @@ import type { IncomingMessage } from 'node:http'; import { parse as parseCookie } from 'cookie'; -import express, { type NextFunction, type Request, type Response } from 'express'; +import express, { Router, type NextFunction, type Request, type Response } from 'express'; import type { WebSocket } from 'ws'; import { hasPassword, hashedPassword } from '../api-data/session/session.service.js'; @@ -40,7 +40,7 @@ export function isPublicAssetRequest(originalUrl: string, prefix: string): boole * @param {string} prefix - Prefix is used for the client hashes in Ontime Cloud */ export function makeLoginRouter(prefix: string) { - const router = express.Router(); + const router: Router = express.Router(); // serve static files at root router.use('/', express.static(srcFiles.login));