From 9c5c7ee69aee6fd1f6b07944d2253f42dba50086 Mon Sep 17 00:00:00 2001 From: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Date: Wed, 8 Jun 2022 21:57:22 +0200 Subject: [PATCH] Docker (#146) * docker: initial config * docker: add entrypoint for headless run * docker: resolve path from env variable * docker: initial config * docker: rename preloaded data directories * docker: update README * docker: prevent issue with port mappings * docker: update README.md * docker: add docker-compose * docker: cleanup logs * docker: add CI * docker: cleanup unused * docker: use static port in development * refactor: isolate tasks * docker: add demo db * fix: download db resolves according to OS * docker: config build * fix: ensure db path exists * fix: add object type to block * docker: config build * docker: config build * docker: env is production * docker: preload db * fix: remove test dir * docker: graceful shutdown node app * docker: env is production * docker: add docker-compose * docker: remove unused mappings * docker: version bump --- .dockerignore | 14 +++ .github/workflows/autobuild.yml | 103 -------------------- .github/workflows/build.yml | 62 ++++++++++-- .gitignore | 3 +- Dockerfile | 20 ++++ README.md | 26 ++++- client/src/app/api/apiConstants.js | 17 ++-- client/src/app/api/ontimeApi.js | 4 +- client/src/features/viewers/ViewWrapper.jsx | 33 +++---- docker-compose.yml | 12 +++ server/{data => demo-db}/db.json | 0 server/main.js | 10 +- server/package.json | 4 +- server/src/app.js | 20 ++-- server/src/classes/EventTimer.js | 2 +- server/src/config/config.js | 1 + server/src/controllers/ontimeController.js | 12 +-- server/src/data/.keep | 0 server/src/modules/loadDb.js | 27 +++-- server/src/package.json | 3 +- server/{data => src/preloaded-db}/.keep | 0 server/src/run.js | 14 +++ server/src/utils/fileManagement.js | 14 +-- 23 files changed, 214 insertions(+), 187 deletions(-) create mode 100644 .dockerignore delete mode 100644 .github/workflows/autobuild.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml rename server/{data => demo-db}/db.json (100%) delete mode 100644 server/src/data/.keep rename server/{data => src/preloaded-db}/.keep (100%) create mode 100644 server/src/run.js diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..f14d5145f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +# Ignore config files +.prettier* + +# Ignore install stuff +**/yarn.lock +**/yarn-error.log + +# Ignore test files +**/__tests__/** +**/**.test.js + +# Ignore git and cache folders +.git +.cache diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml deleted file mode 100644 index 7d6d353ed..000000000 --- a/.github/workflows/autobuild.yml +++ /dev/null @@ -1,103 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI - -# Controls when the action will run. -on: - push: - # Pattern matched against refs/tags - tags: - # Push events to every tag not containing / - - '*' - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # build a file for windows - buildwin: - # The type of runner that the job will run on - runs-on: windows-latest - env: - CI: '' - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - - name: Use Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - - # install and build react - - name: Install React dependencies - run: yarn install - working-directory: ./client - - name: Build React App - run: yarn build - working-directory: ./client - - # install node dependencies - - name: Install nodejs dependencies - run: yarn install - working-directory: ./server/src - - # install and build electron - - name: Install Electron dependencies - run: yarn install - working-directory: ./server - - name: Build Electron App - run: yarn dist-win - working-directory: ./server - - # release - - name: Release - uses: softprops/action-gh-release@v1 - with: - files: ./server/dist/ontime-win64.exe - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # build a file for mac - # buildmac: - # The type of runner that the job will run on - # runs-on: macOS-latest - # env: - # CI: '' - - # Steps represent a sequence of tasks that will be executed as part of the job - # steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - # - uses: actions/checkout@v2 - - # - name: Use Node.js - # uses: actions/setup-node@v1 - # with: - # node-version: '14.x' - - # install and build react - # - name: Install React dependencies - # run: yarn install - # working-directory: ./client - # - name: Build React App - # run: yarn build - # working-directory: ./client - - # install and build electron - # - name: Install Electron + nodejs dependencies - # run: yarn install - # working-directory: ./server - # - name: Build Electron App - # run: yarn dist-win - # working-directory: ./server - - # release - # - name: Release - # uses: softprops/action-gh-release@v1 - # with: - # files: ./server/dist/ontime-macOS.dmg - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6667c3d86..01b724822 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: # React - name: React - Install dependencies - run: yarn install + run: yarn install --frozen-lockfile working-directory: ./client - name: React - Build project @@ -31,13 +31,13 @@ jobs: # Node server - name: Server - Install dependencies - run: yarn install + run: yarn install --frozen-lockfile --production working-directory: ./server/src # App - name: Electron - Install dependencies shell: bash - run: yarn install && yarn setdb + run: yarn install --frozen-lockfile && yarn setdb working-directory: ./server - name: Electron - Build app run: yarn dist-mac @@ -65,7 +65,7 @@ jobs: # React - name: React - Install dependencies - run: yarn install + run: yarn install --frozen-lockfile working-directory: ./client - name: React - Build project @@ -74,13 +74,13 @@ jobs: # Node server - name: Server - Install dependencies - run: yarn install + run: yarn install --frozen-lockfile --production working-directory: ./server/src # App - name: Electron - Install dependencies shell: bash - run: yarn install && yarn setdb + run: yarn install --frozen-lockfile && yarn setdb working-directory: ./server - name: Electron - Build app run: yarn dist-win @@ -108,7 +108,7 @@ jobs: # React - name: React - Install dependencies - run: yarn install + run: yarn install --frozen-lockfile working-directory: ./client - name: React - Build project @@ -117,7 +117,7 @@ jobs: # Node server - name: Server - Install dependencies - run: yarn install + run: yarn install --frozen-lockfile --production working-directory: ./server/src # App @@ -136,3 +136,49 @@ jobs: files: ./server/dist/ontime-linux.AppImage env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish_docker: + runs-on: ubuntu-latest + env: + CI: '' + + steps: + - uses: actions/checkout@v2 + - name: Setup env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '14.x' + + # React + - name: React - Install dependencies + run: yarn install + working-directory: ./client + + - name: React - Build project + run: yarn build + working-directory: ./client + + # Node server + - name: Server - Install dependencies + run: yarn install --frozen-lockfile --production + working-directory: ./server/src + + # Login to docker + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # Build and push + - name: Build and push + working-directory: ./ + id: docker_build + uses: docker/build-push-action@v2 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ secrets.DOCKERHUB_USERNAME }}/ontime:${{ env.RELEASE_VERSION }} diff --git a/.gitignore b/.gitignore index c4f3a891e..2f39aed86 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,10 @@ yarn-error.log* # working stuff _SS/ db backup.json -server/src/data/db.json +server/src/preloaded-db/db.json server/src/models/db.json TODO.md +ontime-db/ # vscode stuff .vscode/* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..81669ade1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM node:14-alpine + +WORKDIR /app/server + +# Prepare UI +COPY /client/build ../client/build + +# Prepare Backend +COPY /server/src ./ + +# Export default ports Main - OSC IN +EXPOSE 4001/tcp 8888/udp +ENV NODE_ENV=production +ENV ONTIME_DATA=/server/ + +CMD ["yarn", "start:headless"] + +# Build an run commandsN +# docker build -t getontime/ontime . +# docker run -p 4001:4001 -p 10.0.0.12:8888:8888/udp --mount type=bind,source="$(pwd)/ontime-db",target=/server/preloaded-db getontime/ontime diff --git a/README.md b/README.md index 650325cac..0af9486c3 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,8 @@ More documentation available [here](https://cpvalente.gitbook.io/ontime/) - [x] Logging view - [x] Edit anywhere: run ontime in your local network and use any machine to reach the editor page ( same as app) +- [x] Multi platform (available on Windows, MacOS and Linux) +- [x] [Headless run](#headless-run) (run server only, configure from a browser locally) ## Unopinionated @@ -115,6 +117,29 @@ See [this repository](https://github.com/cpvalente/ontime-viewer-template) with how to get you started and read the docs about the [Websocket API](https://app.gitbook.com/s/-Mc0giSOToAhq0ROd0CR/control-and-feedback/websocket-api) +### Headless runī¸ +You can self host and run ontime in a docker image, the run command should: +- expose the necessary ports (listen in Dockerfile) +- mount a local file to persist your data (in the example: ````$(pwd)/local-data````) +- the image name __getontime/ontime__ + +The docker image is in [available Docker Hub at getontime/ontime](https://hub.docker.com/r/getontime/ontime) +```bash +docker pull getontime/ontime +``` + +```bash +# Port 4001 - ontime server port +# Port 8888 - OSC input, bound to localhost IP Address +docker run -p 4001:4001 -p 127.0.0.1:8888:8888/udp --mount type=bind,source="$(pwd)/ontime-db",target=/server/preloaded-db getontime/ontime +``` + +or if running from the docker compose + +```bash +docker-compose up +``` + ## Roadmap ### Continued development @@ -126,7 +151,6 @@ friendly order unless there is user demand to bump any of them. - [ ] Improvement with event component design - [ ] New playback mode for [cumulative time keeping](https://github.com/cpvalente/ontime/issues/100) -- [ ] Headless version (run server only anywhere, configure from a browser locally) - [ ] Companion module - [ ] Lower Third Manager - [ ] Note only event diff --git a/client/src/app/api/apiConstants.js b/client/src/app/api/apiConstants.js index 066ee63b8..0548600fe 100644 --- a/client/src/app/api/apiConstants.js +++ b/client/src/app/api/apiConstants.js @@ -1,4 +1,4 @@ -export const NODE_PORT = 4001; +export const STATIC_PORT = 4001; export const EVENT_TABLE = 'event'; export const ALIASES = 'aliases'; export const USERFIELDS = 'userFields'; @@ -8,15 +8,18 @@ export const OSC_SETTINGS = 'oscSettings'; export const APP_SETTINGS = 'appSettings'; /** - * @description finds server path given the current location + * @description finds server path given the current location, it * @return {*} */ const calculateServer = () => { - return window.location.origin.replace(window.location.port, `${NODE_PORT}/`); + if (process.env?.NODE_ENV === 'development') { + return `http://localhost:${STATIC_PORT}`; + } + return window.location.origin; }; export const serverURL = calculateServer(); -export const eventURL = serverURL + EVENT_TABLE; -export const eventsURL = serverURL + EVENTS_TABLE; -export const playbackURL = `${serverURL}playback`; -export const ontimeURL = `${serverURL}ontime`; +export const eventURL = `${serverURL}/${EVENT_TABLE}`; +export const eventsURL = `${serverURL}/${EVENTS_TABLE}`; +export const playbackURL = `${serverURL}/playback`; +export const ontimeURL = `${serverURL}/ontime`; diff --git a/client/src/app/api/ontimeApi.js b/client/src/app/api/ontimeApi.js index c8da2b0fc..15a7c3a00 100644 --- a/client/src/app/api/ontimeApi.js +++ b/client/src/app/api/ontimeApi.js @@ -222,7 +222,9 @@ export const downloadEvents = async () => { filename = headerLine.substring(startFileNameIndex, endFileNameIndex); } - const url = window.URL.createObjectURL(new Blob([response.data])); + const url = window.URL.createObjectURL( + new Blob([response.data], { type: 'application/json' }) + ); const link = document.createElement('a'); link.href = url; link.setAttribute('download', filename); diff --git a/client/src/features/viewers/ViewWrapper.jsx b/client/src/features/viewers/ViewWrapper.jsx index 1850c3c16..43db2b761 100644 --- a/client/src/features/viewers/ViewWrapper.jsx +++ b/client/src/features/viewers/ViewWrapper.jsx @@ -154,15 +154,16 @@ const withSocket = (Component) => { // Filter events only to pass down useEffect(() => { if (eventsData == null) return; - // filter just events with title - const pe = eventsData.filter( - (d) => d.type === 'event' && d.title !== '' && d.isPublic === true - ); - setPublicEvents(pe); + if (Array.isArray(eventsData)) { + const pe = eventsData.filter( + (d) => d.type === 'event' && d.title !== '' && d.isPublic + ); + setPublicEvents(pe); - // everything goes backstage - setBackstageEvents(eventsData); + // everything goes backstage + setBackstageEvents(eventsData); + } }, [eventsData]); // Set general data @@ -178,13 +179,11 @@ const withSocket = (Component) => { /********************************************/ // is there a now field? let showNow = true; - if (!titles.titleNow && !titles.subtitleNow && !titles.presenterNow) - showNow = false; + if (!titles.titleNow && !titles.subtitleNow && !titles.presenterNow) showNow = false; // is there a next field? let showNext = true; - if (!titles.titleNext && !titles.subtitleNext && !titles.presenterNext) - showNext = false; + if (!titles.titleNext && !titles.subtitleNext && !titles.presenterNext) showNext = false; const titleManager = { ...titles, showNow: showNow, showNext: showNext }; @@ -195,20 +194,12 @@ const withSocket = (Component) => { /********************************************/ // is there a now field? let showPublicNow = true; - if ( - !publicTitles.titleNow && - !publicTitles.subtitleNow && - !publicTitles.presenterNow - ) + if (!publicTitles.titleNow && !publicTitles.subtitleNow && !publicTitles.presenterNow) showPublicNow = false; // is there a next field? let showPublicNext = true; - if ( - !publicTitles.titleNext && - !publicTitles.subtitleNext && - !publicTitles.presenterNext - ) + if (!publicTitles.titleNext && !publicTitles.subtitleNext && !publicTitles.presenterNext) showPublicNext = false; const publicTitleManager = { diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..5704580f3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3" + +services: + ontime: + container_name: ontime + image: getontime/ontime:test-alpine + ports: + - "4001:4001/tcp" + - "127.0.0.1:8888:8888/udp" + volumes: + - "./ontime-db:/server/preloaded-db" + restart: unless-stopped diff --git a/server/data/db.json b/server/demo-db/db.json similarity index 100% rename from server/data/db.json rename to server/demo-db/db.json diff --git a/server/main.js b/server/main.js index f04103fc4..6977b78d6 100644 --- a/server/main.js +++ b/server/main.js @@ -11,13 +11,16 @@ const { } = require('electron'); const path = require('path'); -const env = process.env.NODE_ENV || 'prod'; +if (process.env.NODE_ENV === undefined) { + process.env.NODE_ENV = 'production'; +} +const env = process.env.NODE_ENV; let loaded = 'Nothing loaded'; let isQuitting = false; const nodePath = - env !== 'prod' + env !== 'production' ? path.join('file://', __dirname, 'src/app.js') : path.join('file://', __dirname, '../', 'extraResources', 'src/app.js'); @@ -142,7 +145,7 @@ app.whenReady().then(() => { setTimeout(() => { // Load page served by node const reactApp = - env === 'prod' ? 'http://localhost:4001/editor' : 'http://localhost:3000/editor'; + env === 'development' ? 'http://localhost:3000/editor' : 'http://localhost:4001/editor'; win.loadURL(reactApp).then(() => { win.webContents.setBackgroundThrottling(false); @@ -154,7 +157,6 @@ app.whenReady().then(() => { splash.destroy(); // tray stuff - // TODO: get IP Address tray.setToolTip(loaded); }); }, 2000); diff --git a/server/package.json b/server/package.json index ea45fad37..61c5112fa 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "ontime", - "version": "1.1.1", + "version": "1.2.0", "author": "Carlos Valente", "description": "Time keeping for live events", "repository": "https://github.com/cpvalente/ontime", @@ -27,7 +27,7 @@ }, "scripts": { "nodestart": "NODE_ENV=development node src/app.js", - "setdb": "cp data/db.json src/data/db.json", + "setdb": "cp demo-db/db.json src/preloaded-db/db.json", "clean": "rm -rf ../client/build/ && rm -rf ../client/node_modules && rm -rf src/node_modules && rm -rf ./node_modules && rm -rf ./dist", "prep": "yarn clean && yarn setdb", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", diff --git a/server/src/app.js b/server/src/app.js index c25de8733..ceb84b766 100644 --- a/server/src/app.js +++ b/server/src/app.js @@ -26,7 +26,7 @@ import { initiateOSC, shutdownOSCServer } from './controllers/OscController.js'; import { fileURLToPath } from 'url'; // get environment -const env = process.env.NODE_ENV || 'prod'; +const env = process.env.NODE_ENV || 'production'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -56,11 +56,11 @@ app.use('/ontime', ontimeRouter); app.use('/playback', playbackRouter); // serve react -app.use(express.static(join(__dirname, env === 'prod' ? '../' : '../../', 'client/build'))); +app.use(express.static(join(__dirname, env === 'production' ? '../' : '../../', 'client/build'))); app.get('*', (req, res) => { res.sendFile( - resolve(__dirname, env === 'prod' ? '../' : '../../', 'client', 'build', 'index.html') + resolve(__dirname, env === 'production' ? '../' : '../../', 'client', 'build', 'index.html'), ); }); @@ -107,14 +107,7 @@ export const startOSCServer = async (overrideConfig = null) => { const server = http.createServer(app); export const startServer = async (overrideConfig = null) => { - // Setup default port - // const port = overrideConfig?.port || serverPort; - - /* Note: Port is hardcoded - * need to find a good solution for sharing - * the dynamic info with the frontend - */ - const port = 4001; + const port = 4001; // port hardcoded // Start server const returnMessage = `Ontime is listening on port ${port}`; @@ -145,4 +138,9 @@ export const shutdown = async () => { global.timer.shutdown(); }; +// register shutdown signals +process.once('SIGHUP', shutdown) +process.once('SIGINT', shutdown) +process.once('SIGTERM', shutdown) + export { server, app }; diff --git a/server/src/classes/EventTimer.js b/server/src/classes/EventTimer.js index 2fb8da6d0..c87cb87fc 100644 --- a/server/src/classes/EventTimer.js +++ b/server/src/classes/EventTimer.js @@ -1403,7 +1403,7 @@ export class EventTimer extends Timer { this.messageStack.unshift(m); this.io.emit('logger', m); - if (process.env.NODE_ENV !== 'prod') { + if (process.env.NODE_ENV !== 'production') { console.log(`[${m.level}] \t ${m.origin} \t ${m.text}`); } diff --git a/server/src/config/config.js b/server/src/config/config.js index 292e19084..9fe5d9815 100644 --- a/server/src/config/config.js +++ b/server/src/config/config.js @@ -6,6 +6,7 @@ export const config = { port: 4001, }, database: { + directory: 'preloaded-db', filename: 'db.json', tablename: 'events', }, diff --git a/server/src/controllers/ontimeController.js b/server/src/controllers/ontimeController.js index 651d4b181..3ca1c3bc2 100644 --- a/server/src/controllers/ontimeController.js +++ b/server/src/controllers/ontimeController.js @@ -1,15 +1,9 @@ import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -// get database import { data, db } from '../app.js'; import { networkInterfaces } from 'os'; import { fileHandler } from '../utils/parser.js'; import { generateId } from '../utils/generate_id.js'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import { resolveDbPath } from '../modules/loadDb.js'; // Create controller for GET request to '/ontime/poll' // Returns data for current state @@ -28,9 +22,9 @@ export const poll = async (req, res) => { // Returns - export const dbDownload = async (req, res) => { const fileTitle = data?.event?.title || 'ontime events'; - const dbFile = path.resolve(__dirname, '../', 'data/db.json'); + const dbInDisk = resolveDbPath(); - res.download(dbFile, `${fileTitle}.json`, (err) => { + res.download(dbInDisk, `${fileTitle}.json`, (err) => { if (err) { res.status(500).send({ message: 'Could not download the file. ' + err, diff --git a/server/src/data/.keep b/server/src/data/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/src/modules/loadDb.js b/server/src/modules/loadDb.js index 77c688219..4bbdb8efc 100644 --- a/server/src/modules/loadDb.js +++ b/server/src/modules/loadDb.js @@ -8,16 +8,27 @@ import { dbModelv1 as dbModel } from '../models/dataModel.js'; import { parseJson_v1 as parseJson } from '../utils/parser.js'; /** - * @description ensures directories exist and picks available db path + * @description Decides which path the database is in + * @param ensure - whether it should create directory if it doesnt exist + * @return {string} + */ +export const resolveDbPath = (ensure = true) => { + const appPath = getAppDataPath(); + const dbDirectory = join(appPath, config.database.directory); + if (ensure) { + ensureDirectory(dbDirectory); + } + return join(dbDirectory, config.database.filename); +}; + +/** + * @description ensures directories exist and populates database * @param runningDirectory * @return {string} */ -const checkDirectories = (runningDirectory) => { - const appPath = getAppDataPath(); - const dbDirectory = join(appPath, 'data'); - const dbInDisk = join(dbDirectory, config.database.filename); - const startupDb = join(runningDirectory, 'data', config.database.filename); - ensureDirectory(dbDirectory); +const populateDb = (runningDirectory) => { + const startupDb = join(runningDirectory, config.database.directory, config.database.filename); + const dbInDisk = resolveDbPath(); // if dbInDisk doesnt exist we want to use startup db if (!existsSync(dbInDisk)) { @@ -53,7 +64,7 @@ const parseDb = async (fileToRead, adapterToUse) => { * @return {Promise<{data: (number|*), db: Low}>} */ export default async function loadDb(runningDirectory) { - const dbInDisk = checkDirectories(runningDirectory); + const dbInDisk = populateDb(runningDirectory); const adapter = new JSONFile(dbInDisk); const db = new Low(adapter); diff --git a/server/src/package.json b/server/src/package.json index 4f29f67e7..3e6f624a7 100644 --- a/server/src/package.json +++ b/server/src/package.json @@ -22,6 +22,7 @@ }, "scripts": { "nodestart": "nodemon app.js", - "start": "node app.js" + "start": "node app.js", + "start:headless": "NODE_ENV=production node run.js" } } diff --git a/server/data/.keep b/server/src/preloaded-db/.keep similarity index 100% rename from server/data/.keep rename to server/src/preloaded-db/.keep diff --git a/server/src/run.js b/server/src/run.js new file mode 100644 index 000000000..d96068fc9 --- /dev/null +++ b/server/src/run.js @@ -0,0 +1,14 @@ +(async () => { + let loaded; + try { + const { startServer, startOSCServer } = await import('./app.js'); + // Start express server + loaded = await startServer(); + + // Start OSC Server (API) + await startOSCServer(); + } catch (error) { + console.log(error); + } + console.log(loaded); +})(); diff --git a/server/src/utils/fileManagement.js b/server/src/utils/fileManagement.js index ea6b8104f..17d702562 100644 --- a/server/src/utils/fileManagement.js +++ b/server/src/utils/fileManagement.js @@ -15,20 +15,16 @@ export function ensureDirectory(directory) { } } -/** - * @description Whether a file exists - * @param directory - * @return {boolean} - */ -export function doesFileExist(directory) { - return existsSync(directory); -} - /** * @description Returns public path depending on OS * @return {string|*} */ export function getAppDataPath() { + // handle docker + if (process.env.ONTIME_DATA) { + return path.join(process.env.ONTIME_DATA); + } + switch (process.platform) { case 'darwin': { return path.join(process.env.HOME, 'Library', 'Application Support', 'Ontime');