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
This commit is contained in:
Alex Christoffer Rasmussen
2026-04-26 17:32:50 +02:00
committed by GitHub
parent 23a44b2f04
commit 7c1d2f4554
22 changed files with 55 additions and 49 deletions
@@ -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 });
@@ -64,8 +64,8 @@ function SectionContents({ options, collapsed }: SectionContentsProps) {
function HiddenContents({ options }: { options: ParamField[] }) {
return (
<>
{options.map((option, index) => {
return <ParamInput key={option.title + index} paramField={option} />;
{options.map((option) => {
return <ParamInput key={option.id} paramField={option} />;
})}
</>
);
+4 -2
View File
@@ -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);
@@ -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
<div key={`${info.title}-${idx}`} className='info__custom'>
{hasUrl && (
<div className='info__image-container'>
@@ -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);
@@ -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<CustomFields>) => {
router.get('/', (_req: Request, res: Response<CustomFields>) => {
const customFields = getProjectCustomFields();
res.status(200).json(customFields);
});
@@ -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<CustomViewsListResponse | ErrorResponse>) => {
try {
+2 -2
View File
@@ -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);
+10 -6
View File
@@ -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' });
}
});
+2 -2
View File
@@ -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);
@@ -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<ProjectData>) => {
res.status(200).json(projectDao.getProjectData());
@@ -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());
@@ -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 =========================
@@ -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<SessionStats | ErrorResponse>) => {
try {
@@ -18,9 +18,9 @@ router.get('/', async (_req: Request, res: Response<SessionStats | ErrorResponse
}
});
router.get('/info', async (_req: Request, res: Response<GetInfo | ErrorResponse>) => {
router.get('/info', (_req: Request, res: Response<GetInfo | ErrorResponse>) => {
try {
const info = await sessionService.getInfo();
const info = sessionService.getInfo();
res.status(200).send(info);
} catch (error) {
const message = getErrorMessage(error);
@@ -37,7 +37,7 @@ export async function getSessionStats(): Promise<SessionStats> {
/**
* Adds business logic to gathering data for the info endpoint
*/
export async function getInfo(): Promise<GetInfo> {
export function getInfo(): GetInfo {
const { version } = getDataProvider().getSettings();
const { port } = portManager.getPort();
@@ -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);
@@ -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>,
) {
@@ -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);
@@ -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<URLPreset[]>) => {
const presets = getDataProvider().getUrlPresets();
@@ -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<ViewSettings>) => {
const views = getDataProvider().getViewSettings();
@@ -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';
+2 -2
View File
@@ -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));