From 2ff7019783e55bd1e7de5f00aaef97a6d8622833 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Sun, 13 Oct 2024 13:53:55 +0200 Subject: [PATCH] refactor: simplify setup of asset paths --- .../api-data/settings/settings.controller.ts | 2 +- apps/server/src/app.ts | 26 +-- apps/server/src/classes/Logger.ts | 2 +- .../src/classes/data-provider/DataProvider.ts | 4 +- apps/server/src/externals.ts | 12 ++ apps/server/src/services/RestoreService.ts | 5 +- .../app-state-service/AppStateService.ts | 5 +- .../project-service/ProjectService.ts | 15 +- .../project-service/projectServiceUtils.ts | 14 +- .../services/sheet-service/SheetService.ts | 4 +- apps/server/src/setup/index.ts | 160 +++++++++--------- apps/server/src/setup/loadDemo.ts | 16 +- apps/server/src/setup/loadStyles.ts | 13 +- apps/server/src/utils/development.ts | 2 +- apps/server/src/utils/fileManagement.ts | 24 ++- apps/server/src/utils/generateCrashReport.ts | 6 +- apps/server/src/utils/upload.ts | 13 +- 17 files changed, 178 insertions(+), 145 deletions(-) create mode 100644 apps/server/src/externals.ts diff --git a/apps/server/src/api-data/settings/settings.controller.ts b/apps/server/src/api-data/settings/settings.controller.ts index 035f92c39f..7880f632b0 100644 --- a/apps/server/src/api-data/settings/settings.controller.ts +++ b/apps/server/src/api-data/settings/settings.controller.ts @@ -3,8 +3,8 @@ import { getErrorMessage, obfuscate } from 'ontime-utils'; import type { Request, Response } from 'express'; +import { isDocker } from '../../externals.js'; import { failEmptyObjects } from '../../utils/routerUtils.js'; -import { isDocker } from '../../setup/index.js'; import { getDataProvider } from '../../classes/data-provider/DataProvider.js'; import { extractPin } from './settings.utils.js'; diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 278176efe1..affe77fe1f 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -9,15 +9,8 @@ import serverTiming from 'server-timing'; // import utils import { resolve } from 'path'; -import { - srcDirectory, - environment, - isProduction, - resolveExternalsDirectory, - resolveStylesDirectory, - resolvedPath, - resolvePublicDirectoy, -} from './setup/index.js'; +import { publicDir, srcDir } from './setup/index.js'; +import { environment, isProduction } from './externals.js'; import { ONTIME_VERSION } from './ONTIME_VERSION.js'; import { consoleSuccess, consoleHighlight, consoleError } from './utils/console.js'; @@ -56,8 +49,8 @@ consoleHighlight(`Starting Ontime version ${ONTIME_VERSION}`); const canLog = isProduction; if (!canLog) { console.log(`Ontime running in ${environment} environment`); - console.log(`Ontime source directory at ${srcDirectory} `); - console.log(`Ontime public directory at ${resolvePublicDirectoy} `); + console.log(`Ontime source directory at ${srcDir.root} `); + console.log(`Ontime public directory at ${publicDir.root} `); } // Create express APP @@ -82,17 +75,16 @@ app.use(express.json({ limit: '1mb' })); app.use('/data', appRouter); // router for application data app.use('/api', integrationRouter); // router for integrations -// serve static - css -app.use('/external/styles', express.static(resolveStylesDirectory)); -app.use('/external/', express.static(resolveExternalsDirectory)); +// serve static external files +app.use('/external/', express.static(publicDir.externalDir)); +// if the user reaches to the root, we show a 404 app.use('/external', (req, res) => { res.status(404).send(`${req.originalUrl} not found`); }); // serve static - react, in dev/test mode we fetch the React app from module -const reactAppPath = resolvedPath(); app.use( - expressStaticGzip(reactAppPath, { + expressStaticGzip(srcDir.clientDir, { enableBrotli: true, orderPreference: ['br'], // when we build the client all the react subfiles will get a hashed name we can the immutable tag @@ -103,7 +95,7 @@ app.use( ); app.get('*', (_req, res) => { - res.sendFile(resolve(reactAppPath, 'index.html')); + res.sendFile(resolve(srcDir.clientDir, 'index.html')); }); // Implement catch all diff --git a/apps/server/src/classes/Logger.ts b/apps/server/src/classes/Logger.ts index 32f1c4c14d..715b3c9a91 100644 --- a/apps/server/src/classes/Logger.ts +++ b/apps/server/src/classes/Logger.ts @@ -2,9 +2,9 @@ import { Log, LogLevel } from 'ontime-types'; import { generateId, millisToString } from 'ontime-utils'; import { clock } from '../services/Clock.js'; -import { isProduction } from '../setup/index.js'; import { socket } from '../adapters/WebsocketAdapter.js'; import { consoleSubdued, consoleError } from '../utils/console.js'; +import { isProduction } from '../externals.js'; class Logger { private queue: Log[]; diff --git a/apps/server/src/classes/data-provider/DataProvider.ts b/apps/server/src/classes/data-provider/DataProvider.ts index 2645dc145f..5dc6fdea28 100644 --- a/apps/server/src/classes/data-provider/DataProvider.ts +++ b/apps/server/src/classes/data-provider/DataProvider.ts @@ -13,11 +13,11 @@ import { import type { Low } from 'lowdb'; import { JSONFilePreset } from 'lowdb/node'; -import { isTest } from '../../setup/index.js'; import { isPath } from '../../utils/fileManagement.js'; +import { shouldCrashDev } from '../../utils/development.js'; +import { isTest } from '../../externals.js'; import { safeMerge } from './DataProvider.utils.js'; -import { shouldCrashDev } from '../../utils/development.js'; type ReadonlyPromise = Promise>; diff --git a/apps/server/src/externals.ts b/apps/server/src/externals.ts new file mode 100644 index 0000000000..36bccf3f2c --- /dev/null +++ b/apps/server/src/externals.ts @@ -0,0 +1,12 @@ +/** + * This file contains a list of constants that may need to be resolved at runtime + */ + +// ================================================= +// resolve running environment +const env = process.env.NODE_ENV || 'production'; + +export const isTest = Boolean(process.env.IS_TEST); +export const environment = isTest ? 'test' : env; +export const isDocker = env === 'docker'; +export const isProduction = isDocker || (env === 'production' && !isTest); diff --git a/apps/server/src/services/RestoreService.ts b/apps/server/src/services/RestoreService.ts index 5a7676f38f..99d401abbf 100644 --- a/apps/server/src/services/RestoreService.ts +++ b/apps/server/src/services/RestoreService.ts @@ -1,9 +1,10 @@ import { MaybeNumber, MaybeString, Playback } from 'ontime-types'; import { JSONFile } from 'lowdb/node'; -import { resolveRestoreFile } from '../setup/index.js'; import { deepEqual } from 'fast-equals'; +import { publicFiles } from '../setup/index.js'; + export type RestorePoint = { playback: Playback; selectedEventId: MaybeString; @@ -147,4 +148,4 @@ export class RestoreService { } } -export const restoreService = new RestoreService(resolveRestoreFile); +export const restoreService = new RestoreService(publicFiles.restoreFile); diff --git a/apps/server/src/services/app-state-service/AppStateService.ts b/apps/server/src/services/app-state-service/AppStateService.ts index a6728d342e..aa0b5fdb25 100644 --- a/apps/server/src/services/app-state-service/AppStateService.ts +++ b/apps/server/src/services/app-state-service/AppStateService.ts @@ -1,7 +1,8 @@ import { Low } from 'lowdb'; import { JSONFile } from 'lowdb/node'; -import { appStatePath, isTest } from '../../setup/index.js'; +import { publicFiles } from '../../setup/index.js'; +import { isTest } from '../../externals.js'; import { isPath } from '../../utils/fileManagement.js'; import { shouldCrashDev } from '../../utils/development.js'; @@ -9,7 +10,7 @@ interface AppState { lastLoadedProject?: string; } -const adapter = new JSONFile(appStatePath); +const adapter = new JSONFile(publicFiles.appState); const config = new Low(adapter, {}); export async function isLastLoadedProject(projectName: string): Promise { diff --git a/apps/server/src/services/project-service/ProjectService.ts b/apps/server/src/services/project-service/ProjectService.ts index 0e43288726..d6a7c90440 100644 --- a/apps/server/src/services/project-service/ProjectService.ts +++ b/apps/server/src/services/project-service/ProjectService.ts @@ -5,7 +5,7 @@ import { copyFile, rename } from 'fs/promises'; import { logger } from '../../classes/Logger.js'; import { getNetworkInterfaces } from '../../utils/networkInterfaces.js'; -import { resolveCorruptDirectory, resolveProjectsDirectory, resolveStylesPath } from '../../setup/index.js'; +import { publicDir } from '../../setup/index.js'; import { appendToName, ensureDirectory, @@ -47,8 +47,8 @@ init(); * Ensure services has its dependencies initialized */ function init() { - ensureDirectory(resolveProjectsDirectory); - ensureDirectory(resolveCorruptDirectory); + ensureDirectory(publicDir.projectsDir); + ensureDirectory(publicDir.corruptDir); } export async function getCurrentProject() { @@ -63,7 +63,7 @@ export async function getCurrentProject() { * to be composed in the loading functions */ async function loadDemoProject(): Promise { - const pathToNewFile = generateUniqueFileName(resolveProjectsDirectory, config.demoProject); + const pathToNewFile = generateUniqueFileName(publicDir.projectsDir, config.demoProject); await initPersistence(getPathToProject(pathToNewFile), demoDb); const newName = getFileNameFromPath(pathToNewFile); await setLastLoadedProject(newName); @@ -75,7 +75,7 @@ async function loadDemoProject(): Promise { * to be composed in the loading functions */ async function loadNewProject(): Promise { - const pathToNewFile = generateUniqueFileName(resolveProjectsDirectory, config.newProject); + const pathToNewFile = generateUniqueFileName(publicDir.projectsDir, config.newProject); await initPersistence(getPathToProject(pathToNewFile), dbModel); const newName = getFileNameFromPath(pathToNewFile); await setLastLoadedProject(newName); @@ -273,7 +273,7 @@ export async function createProject(filename: string, projectData: ProjectData) }, }; - const uniqueFileName = generateUniqueFileName(resolveProjectsDirectory, filename); + const uniqueFileName = generateUniqueFileName(publicDir.projectsDir, filename); const newFile = getPathToProject(uniqueFileName); // change LowDB to point to new file @@ -316,14 +316,13 @@ export async function getInfo(): Promise { // get nif and inject localhost const ni = getNetworkInterfaces(); ni.unshift({ name: 'localhost', address: '127.0.0.1' }); - const cssOverride = resolveStylesPath; return { networkInterfaces: ni, version, serverPort, osc, - cssOverride, + cssOverride: publicDir.stylesDir, }; } diff --git a/apps/server/src/services/project-service/projectServiceUtils.ts b/apps/server/src/services/project-service/projectServiceUtils.ts index 4145c95d13..8e99de4c28 100644 --- a/apps/server/src/services/project-service/projectServiceUtils.ts +++ b/apps/server/src/services/project-service/projectServiceUtils.ts @@ -4,7 +4,7 @@ import { existsSync } from 'fs'; import { copyFile, readFile, rename, stat } from 'fs/promises'; import { extname, join } from 'path'; -import { resolveCorruptDirectory, resolveProjectsDirectory } from '../../setup/index.js'; +import { publicDir } from '../../setup/index.js'; import { getFilesFromFolder, removeFileExtension } from '../../utils/fileManagement.js'; /** @@ -13,7 +13,7 @@ import { getFilesFromFolder, removeFileExtension } from '../../utils/fileManagem * @param name */ export async function handleUploaded(filePath: string, name: string) { - const newFilePath = join(resolveProjectsDirectory, name); + const newFilePath = join(publicDir.projectsDir, name); await rename(filePath, newFilePath); } @@ -29,12 +29,12 @@ export async function handleUploaded(filePath: string, name: string) { * @throws {Error} Throws an error if there is an issue in reading the directory or fetching file statistics. */ export async function getProjectFiles(): Promise { - const allFiles = await getFilesFromFolder(resolveProjectsDirectory); + const allFiles = await getFilesFromFolder(publicDir.projectsDir); const filteredFiles = filterProjectFiles(allFiles); const projectFiles: ProjectFile[] = []; for (const file of filteredFiles) { - const filePath = join(resolveProjectsDirectory, file); + const filePath = join(publicDir.projectsDir, file); const stats = await stat(filePath); projectFiles.push({ @@ -62,14 +62,14 @@ export function doesProjectExist(name: string): MaybeString { * Returns the absolute path to a project file */ export function getPathToProject(name: string): string { - return join(resolveProjectsDirectory, name); + return join(publicDir.projectsDir, name); } /** * Makes a copy of a given project to the corrupted directory */ export async function copyCorruptFile(filePath: string, name: string): Promise { - const newPath = join(resolveCorruptDirectory, name); + const newPath = join(publicDir.corruptDir, name); return copyFile(filePath, newPath); } @@ -77,7 +77,7 @@ export async function copyCorruptFile(filePath: string, name: string): Promise { - const newPath = join(resolveCorruptDirectory, name); + const newPath = join(publicDir.corruptDir, name); return rename(filePath, newPath); } diff --git a/apps/server/src/services/sheet-service/SheetService.ts b/apps/server/src/services/sheet-service/SheetService.ts index 82d52311e8..02016bf70d 100644 --- a/apps/server/src/services/sheet-service/SheetService.ts +++ b/apps/server/src/services/sheet-service/SheetService.ts @@ -11,7 +11,7 @@ import { sheets, sheets_v4 } from '@googleapis/sheets'; import { Credentials, OAuth2Client } from 'google-auth-library'; import got from 'got'; -import { resolveSheetsDirectory } from '../../setup/index.js'; +import { publicDir } from '../../setup/index.js'; import { ensureDirectory } from '../../utils/fileManagement.js'; import { cellRequestFromEvent, type ClientSecret, getA1Notation, validateClientSecret } from './sheetUtils.js'; import { parseExcel } from '../../utils/parser.js'; @@ -57,7 +57,7 @@ function reset() { */ export function init() { reset(); - ensureDirectory(resolveSheetsDirectory); + ensureDirectory(publicDir.sheetsDir); } /** diff --git a/apps/server/src/setup/index.ts b/apps/server/src/setup/index.ts index d121108a5a..0699532552 100644 --- a/apps/server/src/setup/index.ts +++ b/apps/server/src/setup/index.ts @@ -1,18 +1,26 @@ +/** + * This file handles resolving paths for the server resources + * There are two main directories + * - 1. the installation directory, exposed by __dirname + * - 2. the public directory, exposed by getAppDataPath() + */ + import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { config } from './config.js'; import { ensureDirectory } from '../utils/fileManagement.js'; - -// ================================================= -// resolve public path +import { isProduction } from '../externals.js'; /** - * @description Returns public path depending on OS + * Returns public path depending on OS * This is the correct path for the app running in production mode */ export function getAppDataPath(): string { - // handle docker + /** + * If we are running in docker, the ONTIME_DATA environment variable + * allows moving the public directory to a user defined location + */ if (process.env.ONTIME_DATA) { return join(process.env.ONTIME_DATA); } @@ -33,86 +41,86 @@ export function getAppDataPath(): string { } } -// ================================================= -// resolve running environment -const env = process.env.NODE_ENV || 'production'; - -export const isTest = Boolean(process.env.IS_TEST); -export const environment = isTest ? 'test' : env; -export const isDocker = env === 'docker'; -export const isProduction = isDocker || (env === 'production' && !isTest); - -// ================================================= -// Resolve directory paths +/** + * 1. Paths relative to the installation (or source in development) + * ------------------------------------------------------------------ + */ -// resolve file URL in both CJS and ESM (build and dev) +/** resolve file URL in both CJS and ESM (build and dev) */ if (import.meta.url) { globalThis.__dirname = fileURLToPath(import.meta.url); } -// path to server src folder const currentDir = dirname(__dirname); -// locally we are in src/setup, in the production build, this is a single file at src -export const srcDirectory = isProduction ? currentDir : join(currentDir, '../'); -// TODO: simplify logic -// resolve path to client -const productionPath = join(srcDirectory, 'client/'); -const devPath = join(srcDirectory, '../../client/build/'); -export const resolvedPath = (): string => { - if (isTest) { - return devPath; - } - if (isProduction) { - return productionPath; - } - return devPath; +/** + * path to server src folder + * when running in dev, this file is located in src/setup, so we go one level up + * */ +const srcDirectory = isProduction ? currentDir : join(currentDir, '../'); + +export const srcDir = { + root: srcDirectory, + /** Path to the react app */ + clientDir: isProduction ? join(srcDirectory, 'client/') : join(srcDirectory, '../../client/build/'), + /** Path to the demo app */ + demoDir: join(srcDirectory, '/external/demo/'), +} as const; + +export const srcFiles = { + /** Path to bundled CSS */ + cssOverride: join(srcDir.root, '/external/styles/', config.styles.filename), }; -// resolve public directory -export const resolvePublicDirectoy = getAppDataPath(); -ensureDirectory(resolvePublicDirectoy); - -export const externalsStartDirectory = isProduction ? resolvePublicDirectoy : join(srcDirectory, 'external'); -// TODO: we only need one when they are all in the same folder -export const resolveExternalsDirectory = join(isProduction ? resolvePublicDirectoy : srcDirectory, 'external'); - -// project files -export const appStatePath = join(resolvePublicDirectoy, config.appState); -export const uploadsFolderPath = join(resolvePublicDirectoy, config.uploads); - -// path to public styles -export const resolveStylesDirectory = join(externalsStartDirectory, config.styles.directory); -export const resolveStylesPath = join(resolveStylesDirectory, config.styles.filename); - -export const pathToStartStyles = join(srcDirectory, '/external/styles/', config.styles.filename); - -// path to public demo -export const resolveDemoDirectory = join( - externalsStartDirectory, - isProduction ? '/external/' : '', // move to external folder in production - config.demo.directory, -); -export const resolveDemoPath = config.demo.filename.map((file) => { - return join(resolveDemoDirectory, file); -}); - -// path to demo project -export const pathToStartDemo = config.demo.filename.map((file) => { - return join(srcDirectory, '/external/demo/', file); -}); - -// path to restore file -export const resolveRestoreFile = join(resolvePublicDirectoy, config.restoreFile); - -// path to sheets folder -export const resolveSheetsDirectory = join(resolvePublicDirectoy, config.sheets.directory); +/** + * 2. Paths relative to the user public directory + * ------------------------------------------------ + */ -// path to crash reports -export const resolveCrashReportDirectory = join(resolvePublicDirectoy, config.crash); +/** Resolve root to public directory */ +const resolvePublicDirectory = getAppDataPath(); +// Ensure directory tree is created +ensureDirectory(resolvePublicDirectory); -// path to projects -export const resolveProjectsDirectory = join(resolvePublicDirectoy, config.projects); +/** + * Path to external + * This is unique in the way that we use the src directory in development + * For simplicity we still bundle this in the public directory object + */ +const externalsStartDirectory = isProduction ? resolvePublicDirectory : join(srcDirectory, 'external'); + +export const publicDir = { + root: resolvePublicDirectory, + /** path to sheets folder */ + sheetsDir: join(resolvePublicDirectory, config.sheets.directory), + /** path to crash reports folder */ + crashDir: join(resolvePublicDirectory, config.crash), + /** path to projects folder */ + projectsDir: join(resolvePublicDirectory, config.projects), + /** path to corrupt folder */ + corruptDir: join(resolvePublicDirectory, config.corrupt), + /** path to uploads folder */ + uploadsDir: join(resolvePublicDirectory, config.uploads), + /** path to external folder */ + externalDir: externalsStartDirectory, + /** path to demo project folder */ + demoDir: join( + externalsStartDirectory, + isProduction ? '/external/' : '', // move to external folder in production + config.demo.directory, + ), + /** path to external styles override */ + stylesDir: join(externalsStartDirectory, config.styles.directory), +} as const; -// path to corrupt files -export const resolveCorruptDirectory = join(resolvePublicDirectoy, config.corrupt); +/** + * Resolve path to specific files + */ +export const publicFiles = { + /** path to app state file */ + appState: join(publicDir.root, config.appState), + /** path to restore file */ + restoreFile: join(publicDir.root, config.restoreFile), + /** path to CSS override file */ + cssOverride: join(publicDir.stylesDir, config.styles.filename), +}; diff --git a/apps/server/src/setup/loadDemo.ts b/apps/server/src/setup/loadDemo.ts index b44842542b..44aac18505 100644 --- a/apps/server/src/setup/loadDemo.ts +++ b/apps/server/src/setup/loadDemo.ts @@ -1,20 +1,16 @@ -import { copyFile } from 'fs/promises'; -import { pathToStartDemo, resolveDemoDirectory, resolveDemoPath } from './index.js'; -import { ensureDirectory } from '../utils/fileManagement.js'; +import { copyDirectory, ensureDirectory } from '../utils/fileManagement.js'; + +import { publicDir, srcDir } from './index.js'; /** * @description ensures directories exist and populates demo folder */ export const populateDemo = () => { - ensureDirectory(resolveDemoDirectory); + ensureDirectory(publicDir.demoDir); + // even if demo exist we want to use startup demo try { - Promise.all( - resolveDemoPath.map((to, index) => { - const from = pathToStartDemo[index]; - return copyFile(from, to); - }), - ); + copyDirectory(srcDir.demoDir, publicDir.demoDir); } catch (_) { /* we do not handle this */ } diff --git a/apps/server/src/setup/loadStyles.ts b/apps/server/src/setup/loadStyles.ts index c55a412061..3fceb10647 100644 --- a/apps/server/src/setup/loadStyles.ts +++ b/apps/server/src/setup/loadStyles.ts @@ -1,16 +1,19 @@ import { copyFileSync, existsSync } from 'fs'; -import { pathToStartStyles, resolveStylesDirectory, resolveStylesPath } from './index.js'; + import { ensureDirectory } from '../utils/fileManagement.js'; +import { publicDir, publicFiles, srcFiles } from './index.js'; + /** - * @description ensures directories exist and populates stylesheet + * ensures directories exist and populates stylesheet */ export const populateStyles = () => { - ensureDirectory(resolveStylesDirectory); + ensureDirectory(publicDir.stylesDir); // if styles doesn't exist we want to use startup stylesheet - if (!existsSync(resolveStylesPath)) { + if (!existsSync(publicFiles.cssOverride)) { try { - copyFileSync(pathToStartStyles, resolveStylesPath); + // copy the startup stylesheet to the public directory + copyFileSync(srcFiles.cssOverride, publicFiles.cssOverride); } catch (_) { /* we do not handle this */ } diff --git a/apps/server/src/utils/development.ts b/apps/server/src/utils/development.ts index acaab902b9..048a30e425 100644 --- a/apps/server/src/utils/development.ts +++ b/apps/server/src/utils/development.ts @@ -1,4 +1,4 @@ -import { isProduction } from '../setup/index.js'; +import { isProduction } from '../externals.js'; import { consoleError } from '../utils/console.js'; /** diff --git a/apps/server/src/utils/fileManagement.ts b/apps/server/src/utils/fileManagement.ts index 8f006afb10..5a2d361ddc 100644 --- a/apps/server/src/utils/fileManagement.ts +++ b/apps/server/src/utils/fileManagement.ts @@ -1,5 +1,5 @@ import { existsSync, mkdirSync } from 'fs'; -import { readdir } from 'fs/promises'; +import { readdir, copyFile } from 'fs/promises'; import { basename, extname, join, parse } from 'path'; /** @@ -80,8 +80,28 @@ export function getFileNameFromPath(filePath: string): string { } /** - * Utility naivly checks for paths on whether it includes directories + * Utility naively checks for paths on whether it includes directories */ export function isPath(filePath: string): boolean { return filePath !== basename(filePath); } + +/** + * Recursively copies a directory and its contents. + * @param {string} src - The source directory. + * @param {string} dest - The destination directory. + */ +export async function copyDirectory(src: string, dest: string) { + const entries = await readdir(src, { withFileTypes: true }); + + for (const entry of entries) { + const srcPath = join(src, entry.name); + const destPath = join(dest, entry.name); + + if (entry.isDirectory()) { + await copyDirectory(srcPath, destPath); + } else { + await copyFile(srcPath, destPath); + } + } +} diff --git a/apps/server/src/utils/generateCrashReport.ts b/apps/server/src/utils/generateCrashReport.ts index e71d48b152..37efc21379 100644 --- a/apps/server/src/utils/generateCrashReport.ts +++ b/apps/server/src/utils/generateCrashReport.ts @@ -4,7 +4,7 @@ import { join } from 'path'; import { ONTIME_VERSION } from '../ONTIME_VERSION.js'; import { get } from '../services/rundown-service/rundownCache.js'; import { getState } from '../stores/runtimeState.js'; -import { resolveCrashReportDirectory } from '../setup/index.js'; +import { publicDir } from '../setup/index.js'; import { ensureDirectory } from './fileManagement.js'; /** @@ -13,8 +13,8 @@ import { ensureDirectory } from './fileManagement.js'; * @param content */ function writeToFile(fileName: string, content: object) { - const path = join(resolveCrashReportDirectory, fileName); - ensureDirectory(resolveCrashReportDirectory); + const path = join(publicDir.crashDir, fileName); + ensureDirectory(publicDir.crashDir); try { const textContent = JSON.stringify(content, null, 2); diff --git a/apps/server/src/utils/upload.ts b/apps/server/src/utils/upload.ts index 194b48d14b..f45ed60bdd 100644 --- a/apps/server/src/utils/upload.ts +++ b/apps/server/src/utils/upload.ts @@ -3,8 +3,9 @@ import path from 'path'; import fs from 'fs'; import { rm } from 'fs/promises'; +import { getAppDataPath, publicDir } from '../setup/index.js'; + import { ensureDirectory } from './fileManagement.js'; -import { getAppDataPath, uploadsFolderPath } from '../setup/index.js'; function generateNewFileName(filePath: string, callback: (newName: string) => void) { const baseName = path.basename(filePath, path.extname(filePath)); @@ -36,19 +37,19 @@ export const storage = multer.diskStorage({ throw new Error('Could not resolve public folder for platform'); } - ensureDirectory(uploadsFolderPath); + ensureDirectory(publicDir.uploadsDir); - const filePath = path.join(uploadsFolderPath, file.originalname); + const filePath = path.join(publicDir.uploadsDir, file.originalname); // Check if file already exists fs.access(filePath, fs.constants.F_OK, (err) => { if (err) { // File does not exist, can safely proceed to this destination - cb(null, uploadsFolderPath); + cb(null, publicDir.uploadsDir); } else { generateNewFileName(filePath, (newName) => { file.originalname = newName; - cb(null, uploadsFolderPath); + cb(null, publicDir.uploadsDir); }); } }); @@ -63,7 +64,7 @@ export const storage = multer.diskStorage({ */ export async function clearUploadfolder() { try { - await rm(uploadsFolderPath, { recursive: true }); + await rm(publicDir.uploadsDir, { recursive: true }); } catch (_) { // we dont care that there was no folder }