diff --git a/.github/workflows/build-lawndon.yaml b/.github/workflows/build-lawndon.yaml new file mode 100644 index 0000000..4aa849b --- /dev/null +++ b/.github/workflows/build-lawndon.yaml @@ -0,0 +1,108 @@ +name: Build Lawndon + +on: + workflow_dispatch: + release: + types: [released] + +jobs: + build-lawndon: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Arduino cli + uses: arduino/setup-arduino-cli@v2 + + - name: Install libraries + run: | + arduino-cli lib install IBusBM Servo + + - name: Compile Lawndon + uses: arduino/compile-sketches@v1 + with: + fqbn: "arduino:avr:mega" + libraries: | + - name: IBusBM + - name: Servo + sketch-paths: | + - ./lawndon + enable-warnings-report: true + verbose: false + cli-compile-flags: | + - --export-binaries + + - name: Package build + if: startsWith(github.ref, 'refs/tags/') + run: | + for dir in ./lawndon/build/*; do + if [ -d "${dir}" ]; then + tar -czvf "${dir}.tar.gz" -C "${dir}" . + fi + done + + - name: Release build + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + files: | + lawndon/build/*.tar.gz + + build-lawndon-pi: + runs-on: ubuntu-latest + needs: build-lawndon + env: + WORKING_DIR: ./pi + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU for multi-platform builds + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + buildkitd-flags: --allow-insecure-entitlement security.insecure + install: true + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push server image + uses: docker/build-push-action@v4 + working-directory: ${{ env.WORKING_DIR }} + with: + context: . + file: ./Dockerfile.server + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ghcr.io/${{ github.repository_owner }}/lawndon-pi-server:${{ github.ref_name }} + ghcr.io/${{ github.repository_owner }}/lawndon-pi-server:${{ github.sha }} + + - name: Build and push UI image + uses: docker/build-push-action@v4 + working-directory: ${{ env.WORKING_DIR }} + with: + context: . + file: ./Dockerfile.ui + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ghcr.io/${{ github.repository_owner }}/lawndon-pi-ui:${{ github.ref_name }} + ghcr.io/${{ github.repository_owner }}/lawndon-pi-ui:${{ github.sha }} diff --git a/.github/workflows/build-lawndon.yml b/.github/workflows/build-lawndon.yml deleted file mode 100644 index e1844b9..0000000 --- a/.github/workflows/build-lawndon.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: Build Lawndon - -on: - workflow_dispatch: - release: - types: [released] - -jobs: - build-lawndon: - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install Arduino cli - uses: arduino/setup-arduino-cli@v2 - - - name: Install libraries - run: | - arduino-cli lib install IBusBM Servo - - - name: Compile Lawndon - uses: arduino/compile-sketches@v1 - with: - fqbn: "arduino:avr:mega" - libraries: | - - name: IBusBM - - name: Servo - sketch-paths: | - - ./lawndon - enable-warnings-report: true - verbose: false - cli-compile-flags: | - - --export-binaries - - - name: Package build - if: startsWith(github.ref, 'refs/tags/') - run: | - for dir in ./lawndon/build/*; do - if [ -d "${dir}" ]; then - tar -czvf "${dir}.tar.gz" -C "${dir}" . - fi - done - - - name: Release build - uses: softprops/action-gh-release@v2 - if: startsWith(github.ref, 'refs/tags/') - with: - files: | - lawndon/build/*.tar.gz - - build-lawndon-pi: - runs-on: ubuntu-latest - needs: build-lawndon - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Package application - working-directory: ./pi - run: | - bash package.sh - - - name: Upload release assets - uses: softprops/action-gh-release@v2 - if: startsWith(github.ref, 'refs/tags/') - with: - files: | - ./pi/lawndon-pi.tar.gz \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yaml similarity index 86% rename from .github/workflows/tests.yml rename to .github/workflows/tests.yaml index 087b8f0..5a08d4b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yaml @@ -8,7 +8,7 @@ on: - cron: "0 4 * * 4" jobs: - build-lawndon: + build-lawndon-test: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -41,7 +41,7 @@ jobs: cli-compile-flags: | - --export-binaries - package-lawndon-pi: + build-lawndon-pi-test: runs-on: ubuntu-latest env: WORKING_DIR: ./pi @@ -79,12 +79,12 @@ jobs: run: | pnpm build:server - - name: Run package script + - name: Test Docker build for Server working-directory: ${{ env.WORKING_DIR }} run: | - ./package.sh + docker build --no-cache --file ./Dockerfile.server --tag lawndon-pi-server-test . - - name: Verify package contents + - name: Test Docker build for UI working-directory: ${{ env.WORKING_DIR }} run: | - tar -df lawndon-pi.tar.gz lawndon-pi + docker build --no-cache --file ./Dockerfile.ui --tag lawndon-pi-ui-test . diff --git a/pi/Dockerfile.server b/pi/Dockerfile.server new file mode 100644 index 0000000..02becf6 --- /dev/null +++ b/pi/Dockerfile.server @@ -0,0 +1,27 @@ +# Build stage +FROM node:22-alpine AS build +WORKDIR /usr/src/app + +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +ENV NODE_ENV=production +ENV CONFIG_PATH=/usr/src/app/config + +RUN corepack enable +COPY server/package*.json ./ +RUN pnpm install + +COPY server ./server +WORKDIR /usr/src/app/server +RUN pnpm build + +# Runtime stage +FROM node:22-alpine +WORKDIR /usr/src/app + +COPY --from=build /usr/src/app/server/dist ./dist +COPY --from=build /usr/src/app/server/node_modules ./node_modules +COPY config ./config + +EXPOSE 5000 8080 +CMD ["node", "dist/server.js"] diff --git a/pi/Dockerfile.ui b/pi/Dockerfile.ui new file mode 100644 index 0000000..c05bd32 --- /dev/null +++ b/pi/Dockerfile.ui @@ -0,0 +1,22 @@ +# Build stage +FROM node:22-alpine AS build +WORKDIR /usr/src/app + +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +ENV VITE_NODE_ENV=production + +RUN corepack enable +COPY ui/package*.json ./ +RUN pnpm install + +COPY ui ./ui +WORKDIR /usr/src/app/ui +RUN pnpm build + +# Runtime stage +FROM nginx:alpine +COPY --from=build /usr/src/app/ui/dist /usr/share/nginx/html + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/pi/docker-compose.yaml b/pi/docker-compose.yaml new file mode 100644 index 0000000..e92adc4 --- /dev/null +++ b/pi/docker-compose.yaml @@ -0,0 +1,28 @@ +services: + server: + image: ghcr.io/jordojordo/lawndon-pi-server:latest + environment: + NODE_ENV: production + CONFIG_PATH: /usr/src/app/config + ports: + - "5000:5000" # WebSocket and API + - "8080:8080" # ESP32 module communication + volumes: + - ./config:/usr/src/app/config:ro # Mount config for anchor positions + networks: + - app_network + + ui: + image: ghcr.io/jordojordo/uwb-ui:latest + environment: + VITE_NODE_ENV: production + ports: + - "80:80" # Expose UI + depends_on: + - server + networks: + - app_network + +networks: + app_network: + driver: bridge diff --git a/pi/package.json b/pi/package.json index cd43688..6fd29c9 100644 --- a/pi/package.json +++ b/pi/package.json @@ -2,6 +2,7 @@ "name": "lawndon-pi", "version": "0.1.0", "private": true, + "type": "module", "scripts": { "install:ui": "pnpm install --prefix ui", "install:server": "pnpm install --prefix server", @@ -10,7 +11,7 @@ "start": "node server/dist/server.js", "dev": "concurrently -k -n SERVER,UI \"pnpm dev:server\" \"pnpm dev:ui\"", "dev:ui": "pnpm --prefix ui dev", - "dev:server": "NODE_ENV=development pnpm --prefix server dev" + "dev:server": "pnpm --prefix server dev" }, "packageManager": "pnpm@9.14.2", "devDependencies": { diff --git a/pi/server/.env.dev b/pi/server/.env.dev index 9518a4a..999e070 100644 --- a/pi/server/.env.dev +++ b/pi/server/.env.dev @@ -1,3 +1,2 @@ NODE_ENV="development" CONFIG_PATH="../../config" -UI_PATH="../../ui" \ No newline at end of file diff --git a/pi/server/.env.prod b/pi/server/.env.prod index 4a1d8ce..3ede221 100644 --- a/pi/server/.env.prod +++ b/pi/server/.env.prod @@ -1,3 +1,2 @@ NODE_ENV="production" CONFIG_PATH="../config" -UI_PATH="../ui" \ No newline at end of file diff --git a/pi/server/esbuild.config.js b/pi/server/esbuild.config.js deleted file mode 100644 index 7ae6f93..0000000 --- a/pi/server/esbuild.config.js +++ /dev/null @@ -1,21 +0,0 @@ -import { build } from 'esbuild'; - -const isProduction = process.env.NODE_ENV === 'production'; - -build({ - entryPoints: ['./src/server.ts'], - bundle: true, - platform: 'node', - target: 'node22', - outfile: './dist/server.cjs', // Use .cjs extension - sourcemap: !isProduction, - format: 'cjs', // Ensure format is 'cjs' - define: { 'process.env.NODE_ENV': `"${ process.env.NODE_ENV || 'development' }"` }, -}) - .then(() => { - console.log('Build complete'); - }) - .catch((error) => { - console.error('Build failed:', error); - process.exit(1); - }); diff --git a/pi/server/package.json b/pi/server/package.json index e01ff0f..baef2a1 100644 --- a/pi/server/package.json +++ b/pi/server/package.json @@ -2,11 +2,12 @@ "name": "uwb-server", "version": "0.1.0", "description": "", - "main": "dist/server.cjs", + "main": "dist/server.js", + "type": "module", "scripts": { - "start": "node dist/server.cjs", - "build": "NODE_ENV=production node esbuild.config.js", - "dev": "nodemon --watch src --ext ts --exec 'ts-node ./src/server.ts'", + "start": "node dist/server.js", + "build": "tsc --outDir dist", + "dev": "NODE_ENV=development nodemon --watch src --ext ts --exec 'node --loader ts-node/esm ./src/server.ts'", "lint": "npx eslint .", "format": "npx eslint . --fix" }, @@ -23,9 +24,9 @@ }, "devDependencies": { "@types/cors": "^2.8.17", + "@types/dotenv": "^8.2.3", "@types/express": "^5.0.0", - "@types/node": "^22.9.1", - "esbuild": "^0.24.0", + "@types/node": "^22.9.3", "eslint": "^9.15.0", "globals": "^15.12.0", "http-proxy-middleware": "^3.0.3", diff --git a/pi/server/pnpm-lock.yaml b/pi/server/pnpm-lock.yaml index 4130309..c33915a 100644 --- a/pi/server/pnpm-lock.yaml +++ b/pi/server/pnpm-lock.yaml @@ -27,15 +27,15 @@ importers: '@types/cors': specifier: ^2.8.17 version: 2.8.17 + '@types/dotenv': + specifier: ^8.2.3 + version: 8.2.3 '@types/express': specifier: ^5.0.0 version: 5.0.0 '@types/node': - specifier: ^22.9.1 - version: 22.9.1 - esbuild: - specifier: ^0.24.0 - version: 0.24.0 + specifier: ^22.9.3 + version: 22.9.3 eslint: specifier: ^9.15.0 version: 9.15.0 @@ -50,10 +50,10 @@ importers: version: 3.1.7 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.9.1)(typescript@5.7.2) + version: 10.9.2(@types/node@22.9.3)(typescript@5.7.2) ts-node-dev: specifier: ^2.0.0 - version: 2.0.0(@types/node@22.9.1)(typescript@5.7.2) + version: 2.0.0(@types/node@22.9.3)(typescript@5.7.2) typescript: specifier: ^5.7.2 version: 5.7.2 @@ -68,150 +68,6 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@esbuild/aix-ppc64@0.24.0': - resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.24.0': - resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.24.0': - resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.24.0': - resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.24.0': - resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.24.0': - resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.24.0': - resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.24.0': - resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.24.0': - resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.24.0': - resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.24.0': - resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.24.0': - resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.24.0': - resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.24.0': - resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.24.0': - resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.24.0': - resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.24.0': - resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.24.0': - resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.24.0': - resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.24.0': - resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.24.0': - resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.24.0': - resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.24.0': - resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.24.0': - resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -303,6 +159,10 @@ packages: '@types/cors@2.8.17': resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + '@types/dotenv@8.2.3': + resolution: {integrity: sha512-g2FXjlDX/cYuc5CiQvyU/6kkbP1JtmGzh0obW50zD7OKeILVL0NSpPWLXVfqoAGQjom2/SLLx9zHq0KXvD6mbw==} + deprecated: This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed. + '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -324,8 +184,8 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/node@22.9.1': - resolution: {integrity: sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==} + '@types/node@22.9.3': + resolution: {integrity: sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==} '@types/qs@6.9.17': resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} @@ -544,11 +404,6 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - esbuild@0.24.0: - resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} - engines: {node: '>=18'} - hasBin: true - escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -1226,78 +1081,6 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@esbuild/aix-ppc64@0.24.0': - optional: true - - '@esbuild/android-arm64@0.24.0': - optional: true - - '@esbuild/android-arm@0.24.0': - optional: true - - '@esbuild/android-x64@0.24.0': - optional: true - - '@esbuild/darwin-arm64@0.24.0': - optional: true - - '@esbuild/darwin-x64@0.24.0': - optional: true - - '@esbuild/freebsd-arm64@0.24.0': - optional: true - - '@esbuild/freebsd-x64@0.24.0': - optional: true - - '@esbuild/linux-arm64@0.24.0': - optional: true - - '@esbuild/linux-arm@0.24.0': - optional: true - - '@esbuild/linux-ia32@0.24.0': - optional: true - - '@esbuild/linux-loong64@0.24.0': - optional: true - - '@esbuild/linux-mips64el@0.24.0': - optional: true - - '@esbuild/linux-ppc64@0.24.0': - optional: true - - '@esbuild/linux-riscv64@0.24.0': - optional: true - - '@esbuild/linux-s390x@0.24.0': - optional: true - - '@esbuild/linux-x64@0.24.0': - optional: true - - '@esbuild/netbsd-x64@0.24.0': - optional: true - - '@esbuild/openbsd-arm64@0.24.0': - optional: true - - '@esbuild/openbsd-x64@0.24.0': - optional: true - - '@esbuild/sunos-x64@0.24.0': - optional: true - - '@esbuild/win32-arm64@0.24.0': - optional: true - - '@esbuild/win32-ia32@0.24.0': - optional: true - - '@esbuild/win32-x64@0.24.0': - optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0)': dependencies: eslint: 9.15.0 @@ -1372,23 +1155,27 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.9.1 + '@types/node': 22.9.3 '@types/connect@3.4.38': dependencies: - '@types/node': 22.9.1 + '@types/node': 22.9.3 '@types/cookie@0.4.1': {} '@types/cors@2.8.17': dependencies: - '@types/node': 22.9.1 + '@types/node': 22.9.3 + + '@types/dotenv@8.2.3': + dependencies: + dotenv: 16.4.5 '@types/estree@1.0.6': {} '@types/express-serve-static-core@5.0.1': dependencies: - '@types/node': 22.9.1 + '@types/node': 22.9.3 '@types/qs': 6.9.17 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -1404,13 +1191,13 @@ snapshots: '@types/http-proxy@1.17.15': dependencies: - '@types/node': 22.9.1 + '@types/node': 22.9.3 '@types/json-schema@7.0.15': {} '@types/mime@1.3.5': {} - '@types/node@22.9.1': + '@types/node@22.9.3': dependencies: undici-types: 6.19.8 @@ -1421,12 +1208,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.9.1 + '@types/node': 22.9.3 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 22.9.1 + '@types/node': 22.9.3 '@types/send': 0.17.4 '@types/strip-bom@3.0.0': {} @@ -1612,7 +1399,7 @@ snapshots: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.17 - '@types/node': 22.9.1 + '@types/node': 22.9.3 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -1631,33 +1418,6 @@ snapshots: es-errors@1.3.0: {} - esbuild@0.24.0: - optionalDependencies: - '@esbuild/aix-ppc64': 0.24.0 - '@esbuild/android-arm': 0.24.0 - '@esbuild/android-arm64': 0.24.0 - '@esbuild/android-x64': 0.24.0 - '@esbuild/darwin-arm64': 0.24.0 - '@esbuild/darwin-x64': 0.24.0 - '@esbuild/freebsd-arm64': 0.24.0 - '@esbuild/freebsd-x64': 0.24.0 - '@esbuild/linux-arm': 0.24.0 - '@esbuild/linux-arm64': 0.24.0 - '@esbuild/linux-ia32': 0.24.0 - '@esbuild/linux-loong64': 0.24.0 - '@esbuild/linux-mips64el': 0.24.0 - '@esbuild/linux-ppc64': 0.24.0 - '@esbuild/linux-riscv64': 0.24.0 - '@esbuild/linux-s390x': 0.24.0 - '@esbuild/linux-x64': 0.24.0 - '@esbuild/netbsd-x64': 0.24.0 - '@esbuild/openbsd-arm64': 0.24.0 - '@esbuild/openbsd-x64': 0.24.0 - '@esbuild/sunos-x64': 0.24.0 - '@esbuild/win32-arm64': 0.24.0 - '@esbuild/win32-ia32': 0.24.0 - '@esbuild/win32-x64': 0.24.0 - escape-html@1.0.3: {} escape-latex@1.2.0: {} @@ -2257,7 +2017,7 @@ snapshots: tree-kill@1.2.2: {} - ts-node-dev@2.0.0(@types/node@22.9.1)(typescript@5.7.2): + ts-node-dev@2.0.0(@types/node@22.9.3)(typescript@5.7.2): dependencies: chokidar: 3.6.0 dynamic-dedupe: 0.3.0 @@ -2267,7 +2027,7 @@ snapshots: rimraf: 2.7.1 source-map-support: 0.5.21 tree-kill: 1.2.2 - ts-node: 10.9.2(@types/node@22.9.1)(typescript@5.7.2) + ts-node: 10.9.2(@types/node@22.9.3)(typescript@5.7.2) tsconfig: 7.0.0 typescript: 5.7.2 transitivePeerDependencies: @@ -2275,14 +2035,14 @@ snapshots: - '@swc/wasm' - '@types/node' - ts-node@10.9.2(@types/node@22.9.1)(typescript@5.7.2): + ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.9.1 + '@types/node': 22.9.3 acorn: 8.14.0 acorn-walk: 8.3.4 arg: 4.1.3 diff --git a/pi/server/src/server.ts b/pi/server/src/server.ts index 4bb427a..377773f 100644 --- a/pi/server/src/server.ts +++ b/pi/server/src/server.ts @@ -1,18 +1,13 @@ -import dotenv from 'dotenv'; import express from 'express'; import { createServer } from 'http'; import { Server } from 'socket.io'; import net from 'net'; -import { resolve, join } from 'path'; +import { fileURLToPath } from 'url'; +import { resolve, join, dirname } from 'path'; import cors from 'cors'; -import { createProxyMiddleware } from 'http-proxy-middleware'; -// Load environment variables -if (process.env.NODE_ENV === 'development') { - dotenv.config({ path: resolve(__dirname, '../.env.dev') }); -} else { - dotenv.config({ path: resolve(__dirname, '../.env.prod') }); -} +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); const app = express(); const httpServer = createServer(app); @@ -23,33 +18,20 @@ const io = new Server(httpServer, { const PORT = process.env.PORT || 5000; const TCP_PORT = process.env.TCP_PORT || 8080; -// Paths for configuration and UI const CONFIG_PATH = process.env.CONFIG_PATH || resolve(__dirname, '../../config'); -const UI_PATH = process.env.UI_PATH || resolve(__dirname, '../../ui'); app.use(cors()); // Allow all origins app.get('/api/config', (req, res) => { - res.sendFile(join(__dirname, CONFIG_PATH, 'anchorPositions.json')); -}); + const configPath = join(CONFIG_PATH, 'anchorPositions.json'); -// Proxy to Vite dev server in development -if (process.env.NODE_ENV === 'development') { - app.use( - '/', - createProxyMiddleware({ - target: 'http://localhost:5173', - changeOrigin: true, - ws: true, - }) - ); -} else { - // Serve static files in production - app.use(express.static(UI_PATH)); - app.get('/', (req, res) => { - res.sendFile(resolve(UI_PATH, 'index.html')); + res.sendFile(configPath, (err) => { + if (err) { + console.error('Error sending file:', err); + res.status(500).send('Error loading configuration file.'); + } }); -} +}); io.on('connection', (socket) => { console.log('A client connected'); diff --git a/pi/server/tsconfig.json b/pi/server/tsconfig.json index b2d59f0..a8c0293 100644 --- a/pi/server/tsconfig.json +++ b/pi/server/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { - "module": "CommonJS", + "module": "NodeNext", + "moduleResolution": "nodenext", "target": "ESNext", "outDir": "./dist", "rootDir": "./src", @@ -10,8 +11,10 @@ "strict": true, "noImplicitAny": true, "skipLibCheck": true, - "noEmit": true + "paths": { + "@src/*": ["./src/*"], + } }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] -} +} \ No newline at end of file diff --git a/pi/ui/env.d.ts b/pi/ui/env.d.ts index 81486fe..27abeaf 100644 --- a/pi/ui/env.d.ts +++ b/pi/ui/env.d.ts @@ -1,6 +1,8 @@ // / interface ImportMetaEnv { + readonly VITE_NODE_ENV: string; + readonly VITE_BACKEND_URL: string; readonly BASE_URL: string; readonly PROD: boolean } diff --git a/pi/ui/nginx.conf b/pi/ui/nginx.conf new file mode 100644 index 0000000..dbd9288 --- /dev/null +++ b/pi/ui/nginx.conf @@ -0,0 +1,63 @@ +user nginx; +worker_processes 1; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + server { + listen 80; + server_name localhost; + + location / { + root /app; + index index.html; + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_pass http://server:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + access_log /var/log/nginx/api_access.log main; + } + + location /ws/ { + proxy_pass http://server:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + access_log /var/log/nginx/websocket_access.log main; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} \ No newline at end of file diff --git a/pi/ui/package.json b/pi/ui/package.json index 1e48912..1d55e56 100644 --- a/pi/ui/package.json +++ b/pi/ui/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "dev": "vite", + "dev": "NODE_ENV=development vite", "build": "run-p type-check \"build-only {@}\" --", "preview": "vite preview", "build-only": "vite build", @@ -16,24 +16,24 @@ "d3": "^7.9.0", "pinia": "^2.2.6", "socket.io-client": "^4.8.1", - "vue": "^3.5.12", + "vue": "^3.5.13", "vue-router": "^4.4.5" }, "devDependencies": { "@tsconfig/node22": "^22.0.0", "@types/d3": "^7.4.3", - "@types/node": "^22.9.1", - "@vitejs/plugin-vue": "^5.1.4", + "@types/node": "^22.9.3", + "@vitejs/plugin-vue": "^5.2.0", "@vue/eslint-config-prettier": "^10.1.0", "@vue/eslint-config-typescript": "^14.1.3", "@vue/tsconfig": "^0.6.0", - "eslint": "^9.14.0", - "eslint-plugin-vue": "^9.30.0", + "eslint": "^9.15.0", + "eslint-plugin-vue": "^9.31.0", "npm-run-all2": "^7.0.1", "prettier": "^3.3.3", "typescript": "~5.6.3", - "vite": "^5.4.10", - "vite-plugin-vue-devtools": "^7.5.4", + "vite": "^5.4.11", + "vite-plugin-vue-devtools": "^7.6.4", "vue-tsc": "^2.1.10" }, "packageManager": "pnpm@9.14.2" diff --git a/pi/ui/pnpm-lock.yaml b/pi/ui/pnpm-lock.yaml index 9845b25..2634cac 100644 --- a/pi/ui/pnpm-lock.yaml +++ b/pi/ui/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: specifier: ^4.8.1 version: 4.8.1 vue: - specifier: ^3.5.12 + specifier: ^3.5.13 version: 3.5.13(typescript@5.6.3) vue-router: specifier: ^4.4.5 @@ -31,11 +31,11 @@ importers: specifier: ^7.4.3 version: 7.4.3 '@types/node': - specifier: ^22.9.1 - version: 22.9.1 + specifier: ^22.9.3 + version: 22.9.3 '@vitejs/plugin-vue': - specifier: ^5.1.4 - version: 5.2.0(vite@5.4.11(@types/node@22.9.1))(vue@3.5.13(typescript@5.6.3)) + specifier: ^5.2.0 + version: 5.2.0(vite@5.4.11(@types/node@22.9.3))(vue@3.5.13(typescript@5.6.3)) '@vue/eslint-config-prettier': specifier: ^10.1.0 version: 10.1.0(eslint@9.15.0)(prettier@3.3.3) @@ -46,10 +46,10 @@ importers: specifier: ^0.6.0 version: 0.6.0(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3)) eslint: - specifier: ^9.14.0 + specifier: ^9.15.0 version: 9.15.0 eslint-plugin-vue: - specifier: ^9.30.0 + specifier: ^9.31.0 version: 9.31.0(eslint@9.15.0) npm-run-all2: specifier: ^7.0.1 @@ -61,11 +61,11 @@ importers: specifier: ~5.6.3 version: 5.6.3 vite: - specifier: ^5.4.10 - version: 5.4.11(@types/node@22.9.1) + specifier: ^5.4.11 + version: 5.4.11(@types/node@22.9.3) vite-plugin-vue-devtools: - specifier: ^7.5.4 - version: 7.6.4(rollup@4.27.3)(vite@5.4.11(@types/node@22.9.1))(vue@3.5.13(typescript@5.6.3)) + specifier: ^7.6.4 + version: 7.6.4(rollup@4.27.4)(vite@5.4.11(@types/node@22.9.3))(vue@3.5.13(typescript@5.6.3)) vue-tsc: specifier: ^2.1.10 version: 2.1.10(typescript@5.6.3) @@ -453,93 +453,93 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.27.3': - resolution: {integrity: sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==} + '@rollup/rollup-android-arm-eabi@4.27.4': + resolution: {integrity: sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.27.3': - resolution: {integrity: sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==} + '@rollup/rollup-android-arm64@4.27.4': + resolution: {integrity: sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.27.3': - resolution: {integrity: sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==} + '@rollup/rollup-darwin-arm64@4.27.4': + resolution: {integrity: sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.27.3': - resolution: {integrity: sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==} + '@rollup/rollup-darwin-x64@4.27.4': + resolution: {integrity: sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.27.3': - resolution: {integrity: sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==} + '@rollup/rollup-freebsd-arm64@4.27.4': + resolution: {integrity: sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.27.3': - resolution: {integrity: sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==} + '@rollup/rollup-freebsd-x64@4.27.4': + resolution: {integrity: sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.27.3': - resolution: {integrity: sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==} + '@rollup/rollup-linux-arm-gnueabihf@4.27.4': + resolution: {integrity: sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.27.3': - resolution: {integrity: sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==} + '@rollup/rollup-linux-arm-musleabihf@4.27.4': + resolution: {integrity: sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.27.3': - resolution: {integrity: sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==} + '@rollup/rollup-linux-arm64-gnu@4.27.4': + resolution: {integrity: sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.27.3': - resolution: {integrity: sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==} + '@rollup/rollup-linux-arm64-musl@4.27.4': + resolution: {integrity: sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.27.3': - resolution: {integrity: sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==} + '@rollup/rollup-linux-powerpc64le-gnu@4.27.4': + resolution: {integrity: sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.27.3': - resolution: {integrity: sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==} + '@rollup/rollup-linux-riscv64-gnu@4.27.4': + resolution: {integrity: sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.27.3': - resolution: {integrity: sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==} + '@rollup/rollup-linux-s390x-gnu@4.27.4': + resolution: {integrity: sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.27.3': - resolution: {integrity: sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==} + '@rollup/rollup-linux-x64-gnu@4.27.4': + resolution: {integrity: sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.27.3': - resolution: {integrity: sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==} + '@rollup/rollup-linux-x64-musl@4.27.4': + resolution: {integrity: sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.27.3': - resolution: {integrity: sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==} + '@rollup/rollup-win32-arm64-msvc@4.27.4': + resolution: {integrity: sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.27.3': - resolution: {integrity: sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==} + '@rollup/rollup-win32-ia32-msvc@4.27.4': + resolution: {integrity: sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.27.3': - resolution: {integrity: sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==} + '@rollup/rollup-win32-x64-msvc@4.27.4': + resolution: {integrity: sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==} cpu: [x64] os: [win32] @@ -651,8 +651,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.9.1': - resolution: {integrity: sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==} + '@types/node@22.9.3': + resolution: {integrity: sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==} '@typescript-eslint/eslint-plugin@8.15.0': resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} @@ -1086,8 +1086,8 @@ packages: delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} - electron-to-chromium@1.5.63: - resolution: {integrity: sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==} + electron-to-chromium@1.5.64: + resolution: {integrity: sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==} engine.io-client@6.6.2: resolution: {integrity: sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==} @@ -1604,8 +1604,8 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup@4.27.3: - resolution: {integrity: sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==} + rollup@4.27.4: + resolution: {integrity: sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2237,66 +2237,66 @@ snapshots: '@polka/url@1.0.0-next.28': {} - '@rollup/pluginutils@5.1.3(rollup@4.27.3)': + '@rollup/pluginutils@5.1.3(rollup@4.27.4)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: - rollup: 4.27.3 + rollup: 4.27.4 - '@rollup/rollup-android-arm-eabi@4.27.3': + '@rollup/rollup-android-arm-eabi@4.27.4': optional: true - '@rollup/rollup-android-arm64@4.27.3': + '@rollup/rollup-android-arm64@4.27.4': optional: true - '@rollup/rollup-darwin-arm64@4.27.3': + '@rollup/rollup-darwin-arm64@4.27.4': optional: true - '@rollup/rollup-darwin-x64@4.27.3': + '@rollup/rollup-darwin-x64@4.27.4': optional: true - '@rollup/rollup-freebsd-arm64@4.27.3': + '@rollup/rollup-freebsd-arm64@4.27.4': optional: true - '@rollup/rollup-freebsd-x64@4.27.3': + '@rollup/rollup-freebsd-x64@4.27.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.27.3': + '@rollup/rollup-linux-arm-gnueabihf@4.27.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.27.3': + '@rollup/rollup-linux-arm-musleabihf@4.27.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.27.3': + '@rollup/rollup-linux-arm64-gnu@4.27.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.27.3': + '@rollup/rollup-linux-arm64-musl@4.27.4': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.27.3': + '@rollup/rollup-linux-powerpc64le-gnu@4.27.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.27.3': + '@rollup/rollup-linux-riscv64-gnu@4.27.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.27.3': + '@rollup/rollup-linux-s390x-gnu@4.27.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.27.3': + '@rollup/rollup-linux-x64-gnu@4.27.4': optional: true - '@rollup/rollup-linux-x64-musl@4.27.3': + '@rollup/rollup-linux-x64-musl@4.27.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.27.3': + '@rollup/rollup-win32-arm64-msvc@4.27.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.27.3': + '@rollup/rollup-win32-ia32-msvc@4.27.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.27.3': + '@rollup/rollup-win32-x64-msvc@4.27.4': optional: true '@socket.io/component-emitter@3.1.2': {} @@ -2426,7 +2426,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@22.9.1': + '@types/node@22.9.3': dependencies: undici-types: 6.19.8 @@ -2512,9 +2512,9 @@ snapshots: '@typescript-eslint/types': 8.15.0 eslint-visitor-keys: 4.2.0 - '@vitejs/plugin-vue@5.2.0(vite@5.4.11(@types/node@22.9.1))(vue@3.5.13(typescript@5.6.3))': + '@vitejs/plugin-vue@5.2.0(vite@5.4.11(@types/node@22.9.3))(vue@3.5.13(typescript@5.6.3))': dependencies: - vite: 5.4.11(@types/node@22.9.1) + vite: 5.4.11(@types/node@22.9.3) vue: 3.5.13(typescript@5.6.3) '@volar/language-core@2.4.10': @@ -2596,14 +2596,14 @@ snapshots: '@vue/devtools-api@6.6.4': {} - '@vue/devtools-core@7.6.4(vite@5.4.11(@types/node@22.9.1))(vue@3.5.13(typescript@5.6.3))': + '@vue/devtools-core@7.6.4(vite@5.4.11(@types/node@22.9.3))(vue@3.5.13(typescript@5.6.3))': dependencies: '@vue/devtools-kit': 7.6.4 '@vue/devtools-shared': 7.6.4 mitt: 3.0.1 nanoid: 3.3.7 pathe: 1.1.2 - vite-hot-client: 0.2.3(vite@5.4.11(@types/node@22.9.1)) + vite-hot-client: 0.2.3(vite@5.4.11(@types/node@22.9.3)) vue: 3.5.13(typescript@5.6.3) transitivePeerDependencies: - vite @@ -2732,7 +2732,7 @@ snapshots: browserslist@4.24.2: dependencies: caniuse-lite: 1.0.30001683 - electron-to-chromium: 1.5.63 + electron-to-chromium: 1.5.64 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) @@ -2948,7 +2948,7 @@ snapshots: dependencies: robust-predicates: 3.0.2 - electron-to-chromium@1.5.63: {} + electron-to-chromium@1.5.64: {} engine.io-client@6.6.2: dependencies: @@ -3443,28 +3443,28 @@ snapshots: robust-predicates@3.0.2: {} - rollup@4.27.3: + rollup@4.27.4: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.27.3 - '@rollup/rollup-android-arm64': 4.27.3 - '@rollup/rollup-darwin-arm64': 4.27.3 - '@rollup/rollup-darwin-x64': 4.27.3 - '@rollup/rollup-freebsd-arm64': 4.27.3 - '@rollup/rollup-freebsd-x64': 4.27.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.27.3 - '@rollup/rollup-linux-arm-musleabihf': 4.27.3 - '@rollup/rollup-linux-arm64-gnu': 4.27.3 - '@rollup/rollup-linux-arm64-musl': 4.27.3 - '@rollup/rollup-linux-powerpc64le-gnu': 4.27.3 - '@rollup/rollup-linux-riscv64-gnu': 4.27.3 - '@rollup/rollup-linux-s390x-gnu': 4.27.3 - '@rollup/rollup-linux-x64-gnu': 4.27.3 - '@rollup/rollup-linux-x64-musl': 4.27.3 - '@rollup/rollup-win32-arm64-msvc': 4.27.3 - '@rollup/rollup-win32-ia32-msvc': 4.27.3 - '@rollup/rollup-win32-x64-msvc': 4.27.3 + '@rollup/rollup-android-arm-eabi': 4.27.4 + '@rollup/rollup-android-arm64': 4.27.4 + '@rollup/rollup-darwin-arm64': 4.27.4 + '@rollup/rollup-darwin-x64': 4.27.4 + '@rollup/rollup-freebsd-arm64': 4.27.4 + '@rollup/rollup-freebsd-x64': 4.27.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.4 + '@rollup/rollup-linux-arm-musleabihf': 4.27.4 + '@rollup/rollup-linux-arm64-gnu': 4.27.4 + '@rollup/rollup-linux-arm64-musl': 4.27.4 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.4 + '@rollup/rollup-linux-riscv64-gnu': 4.27.4 + '@rollup/rollup-linux-s390x-gnu': 4.27.4 + '@rollup/rollup-linux-x64-gnu': 4.27.4 + '@rollup/rollup-linux-x64-musl': 4.27.4 + '@rollup/rollup-win32-arm64-msvc': 4.27.4 + '@rollup/rollup-win32-ia32-msvc': 4.27.4 + '@rollup/rollup-win32-x64-msvc': 4.27.4 fsevents: 2.3.3 run-applescript@7.0.0: {} @@ -3585,14 +3585,14 @@ snapshots: util-deprecate@1.0.2: {} - vite-hot-client@0.2.3(vite@5.4.11(@types/node@22.9.1)): + vite-hot-client@0.2.3(vite@5.4.11(@types/node@22.9.3)): dependencies: - vite: 5.4.11(@types/node@22.9.1) + vite: 5.4.11(@types/node@22.9.3) - vite-plugin-inspect@0.8.8(rollup@4.27.3)(vite@5.4.11(@types/node@22.9.1)): + vite-plugin-inspect@0.8.8(rollup@4.27.4)(vite@5.4.11(@types/node@22.9.3)): dependencies: '@antfu/utils': 0.7.10 - '@rollup/pluginutils': 5.1.3(rollup@4.27.3) + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) debug: 4.3.7 error-stack-parser-es: 0.1.5 fs-extra: 11.2.0 @@ -3600,28 +3600,28 @@ snapshots: perfect-debounce: 1.0.0 picocolors: 1.1.1 sirv: 3.0.0 - vite: 5.4.11(@types/node@22.9.1) + vite: 5.4.11(@types/node@22.9.3) transitivePeerDependencies: - rollup - supports-color - vite-plugin-vue-devtools@7.6.4(rollup@4.27.3)(vite@5.4.11(@types/node@22.9.1))(vue@3.5.13(typescript@5.6.3)): + vite-plugin-vue-devtools@7.6.4(rollup@4.27.4)(vite@5.4.11(@types/node@22.9.3))(vue@3.5.13(typescript@5.6.3)): dependencies: - '@vue/devtools-core': 7.6.4(vite@5.4.11(@types/node@22.9.1))(vue@3.5.13(typescript@5.6.3)) + '@vue/devtools-core': 7.6.4(vite@5.4.11(@types/node@22.9.3))(vue@3.5.13(typescript@5.6.3)) '@vue/devtools-kit': 7.6.4 '@vue/devtools-shared': 7.6.4 execa: 8.0.1 sirv: 3.0.0 - vite: 5.4.11(@types/node@22.9.1) - vite-plugin-inspect: 0.8.8(rollup@4.27.3)(vite@5.4.11(@types/node@22.9.1)) - vite-plugin-vue-inspector: 5.2.0(vite@5.4.11(@types/node@22.9.1)) + vite: 5.4.11(@types/node@22.9.3) + vite-plugin-inspect: 0.8.8(rollup@4.27.4)(vite@5.4.11(@types/node@22.9.3)) + vite-plugin-vue-inspector: 5.2.0(vite@5.4.11(@types/node@22.9.3)) transitivePeerDependencies: - '@nuxt/kit' - rollup - supports-color - vue - vite-plugin-vue-inspector@5.2.0(vite@5.4.11(@types/node@22.9.1)): + vite-plugin-vue-inspector@5.2.0(vite@5.4.11(@types/node@22.9.3)): dependencies: '@babel/core': 7.26.0 '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0) @@ -3632,17 +3632,17 @@ snapshots: '@vue/compiler-dom': 3.5.13 kolorist: 1.8.0 magic-string: 0.30.13 - vite: 5.4.11(@types/node@22.9.1) + vite: 5.4.11(@types/node@22.9.3) transitivePeerDependencies: - supports-color - vite@5.4.11(@types/node@22.9.1): + vite@5.4.11(@types/node@22.9.3): dependencies: esbuild: 0.21.5 postcss: 8.4.49 - rollup: 4.27.3 + rollup: 4.27.4 optionalDependencies: - '@types/node': 22.9.1 + '@types/node': 22.9.3 fsevents: 2.3.3 vscode-uri@3.0.8: {} diff --git a/pi/ui/src/components/UWBVisualization.vue b/pi/ui/src/components/UWBVisualization.vue index c6ffc0b..217ec07 100644 --- a/pi/ui/src/components/UWBVisualization.vue +++ b/pi/ui/src/components/UWBVisualization.vue @@ -4,18 +4,19 @@ import * as d3 from 'd3'; import { Socket } from 'socket.io-client'; interface AnchorData { - A: string; // Anchor ID - R: string; // Range + A: string // Anchor ID + R: string // Range } interface AnchorConfig { - anchors: string[]; - distances: { [key: string]: number }; + anchors: string[] + distances: { [key: string]: number } } export default defineComponent({ name: 'UWBVisualization', setup() { + const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5000'; const socket = inject('socket') as Socket; const uwbData = ref([]); @@ -24,7 +25,7 @@ export default defineComponent({ const anchorIDs = ref([]); // D3 variables - let svg: d3.Selection; // eslint-disable-line + let svg: d3.Selection // eslint-disable-line const width = 600; const height = 400; const padding = 20; // Padding around the visualization @@ -36,7 +37,7 @@ export default defineComponent({ const scalingFactor = 50; // Adjust to control visualization size onMounted(() => { - fetch('/api/config') + fetch(`${ backendUrl }/api/config`) .then((response) => response.json()) .then((configData: AnchorConfig) => { console.log('## configData:', configData); @@ -72,7 +73,6 @@ export default defineComponent({ return; } - positions[ids[0]] = [0, 0]; // First anchor at (0, 0) const d1 = getDistance(ids[0], ids[1]) * scalingFactor; @@ -92,11 +92,7 @@ export default defineComponent({ } function getDistance(id1: string, id2: string): number { - return ( - anchorDistances.value[`${ id1 }-${ id2 }`] || - anchorDistances.value[`${ id2 }-${ id1 }`] || - 0 - ); + return anchorDistances.value[`${ id1 }-${ id2 }`] || anchorDistances.value[`${ id2 }-${ id1 }`] || 0; } function updateScales(tagPosition?: [number, number]) { @@ -129,11 +125,13 @@ export default defineComponent({ const anchors = Object.entries(anchorPositions.value) as [string, [number, number]][]; // Bind data to anchor circles - const anchorCircles = svg.selectAll('.anchor') + const anchorCircles = svg + .selectAll('.anchor') .data(anchors, (d) => d[0]); // Enter selection - anchorCircles.enter() + anchorCircles + .enter() .append('circle') .attr('class', 'anchor') .attr('r', 5) @@ -146,11 +144,13 @@ export default defineComponent({ anchorCircles.exit().remove(); // Bind data to anchor labels - const anchorLabels = svg.selectAll('.anchor-label') + const anchorLabels = svg + .selectAll('.anchor-label') .data(anchors, (d) => d[0]); // Enter selection - anchorLabels.enter() + anchorLabels + .enter() .append('text') .attr('class', 'anchor-label') .attr('font-size', '12px') @@ -214,10 +214,9 @@ export default defineComponent({ drawTag(tagX, tagY); } - function calculateTagPosition( positions: [number, number][], - distances: number[] + distances: number[], ): [number, number] { if (positions.length < 3) { console.error('At least three anchors are required.'); @@ -279,7 +278,6 @@ export default defineComponent({ } } - return {}; }, }); diff --git a/pi/ui/src/main.ts b/pi/ui/src/main.ts index ef2b5f2..57cfd44 100644 --- a/pi/ui/src/main.ts +++ b/pi/ui/src/main.ts @@ -9,7 +9,8 @@ import router from './router'; const app = createApp(App); -const socket: Socket = io('http://0.0.0.0:5000', { transports: ['websocket'] }); +const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5000'; +const socket: Socket = io(backendUrl, { transports: ['websocket'] }); app.provide('socket', socket);