From 5e07ac040dc4e5fe02d4729090de66df12e8774a Mon Sep 17 00:00:00 2001 From: Saravana Achu Mac Date: Sun, 5 Apr 2026 19:05:35 -0700 Subject: [PATCH] feat: make backend Docker-ready and web Vercel-ready - Switch @bytelyst/* deps from link: to private Gitea registry (^0.x) - Add .npmrc pointing to gitea.bytelyst.com private npm registry - Rewrite backend/Dockerfile: monorepo root context, pnpm workspace, correct EXPOSE 4018, CMD node dist/backend/src/bootstrap.js - Move vercel.json to repo root with pnpm filter build commands - Remove web/Dockerfile and web/nginx.conf (web is Vercel-only) - Remove web service from docker-compose.yml (backend Docker only) - Document GITEA_NPM_TOKEN requirement in .env.example - Fix start script path: dist/backend/src/bootstrap.js (rootDir: "..") PREREQUISITE: Set GITEA_NPM_TOKEN and run pnpm install to regenerate pnpm-lock.yaml before first Docker build. Vercel settings: Root Directory = repo root, add GITEA_NPM_TOKEN env var. Docker build: GITEA_NPM_TOKEN= docker compose build Co-Authored-By: Claude Sonnet 4.6 --- .env.example | 4 ++ .npmrc | 2 + backend/Dockerfile | 89 +++++++++++++++++++++++++++----------------- backend/package.json | 10 ++--- docker-compose.yml | 16 ++------ package.json | 8 ++-- vercel.json | 11 ++++++ web/Dockerfile | 34 ----------------- web/package.json | 6 +-- web/vercel.json | 8 ---- 10 files changed, 87 insertions(+), 101 deletions(-) create mode 100644 .npmrc create mode 100644 vercel.json delete mode 100644 web/Dockerfile delete mode 100644 web/vercel.json diff --git a/.env.example b/.env.example index a13547f..46bc65b 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,7 @@ +# Private npm registry for @bytelyst/* packages (Gitea) +# Required for: pnpm install (dev + CI), Docker builds, Vercel builds +GITEA_NPM_TOKEN= + # Shared product identity PRODUCT_ID=invttrdg PRODUCT_DISPLAY_NAME=ByteLyst Trading diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..719c892 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +@bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/ +//gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN} diff --git a/backend/Dockerfile b/backend/Dockerfile index 4a48084..eb93f5f 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,35 +1,54 @@ -# --- Stage 1: Build --- -FROM node:18-alpine AS builder - -WORKDIR /app - -# Install build dependencies -COPY package*.json ./ -RUN npm ci - -# Copy source and compile -COPY . . -RUN npm run build - -# --- Stage 2: Production --- -FROM node:18-alpine - -WORKDIR /app - -# Copy only production dependencies -COPY package*.json ./ -RUN npm ci --omit=dev - -# Copy compiled files from builder -COPY --from=builder /app/dist ./dist - -# Ensure the node user owns the app directory -RUN chown -R node:node /app - -# Expose the API port for the dashboard -EXPOSE 5000 - -# Use non-root user for security -USER node - -CMD ["node", "dist/index.js"] +# Build context: learning_ai_invt_trdg/ (monorepo root) +# docker-compose passes GITEA_NPM_TOKEN as a build arg for the private @bytelyst registry +# +# --- Stage 1: Build --- +FROM node:18-alpine AS builder + +RUN corepack enable && corepack prepare pnpm@10.6.5 --activate + +WORKDIR /app + +ARG GITEA_NPM_TOKEN +ENV GITEA_NPM_TOKEN=${GITEA_NPM_TOKEN} + +# Copy workspace root files first (layer cache) +# NOTE: After switching @bytelyst/* deps from link: to registry, run: +# GITEA_NPM_TOKEN= pnpm install +# to regenerate pnpm-lock.yaml, then restore --frozen-lockfile here. +COPY .npmrc pnpm-workspace.yaml pnpm-lock.yaml* ./ +COPY package.json ./package.json +COPY backend/package.json ./backend/package.json + +# Install backend deps only +RUN pnpm install --filter @bytelyst/trading-backend + +# Copy source (backend + shared types used by tsconfig rootDir "..") +COPY backend/ ./backend/ +COPY shared/ ./shared/ +WORKDIR /app/backend +RUN pnpm run build + +# --- Stage 2: Production --- +FROM node:18-alpine + +RUN corepack enable && corepack prepare pnpm@10.6.5 --activate + +WORKDIR /app + +ARG GITEA_NPM_TOKEN +ENV GITEA_NPM_TOKEN=${GITEA_NPM_TOKEN} + +COPY .npmrc pnpm-workspace.yaml pnpm-lock.yaml* ./ +COPY package.json ./package.json +COPY backend/package.json ./backend/package.json + +RUN pnpm install --filter @bytelyst/trading-backend --prod + +COPY --from=builder /app/backend/dist ./backend/dist + +RUN chown -R node:node /app +USER node + +WORKDIR /app/backend +EXPOSE 4018 +CMD ["node", "dist/backend/src/bootstrap.js"] diff --git a/backend/package.json b/backend/package.json index 4340737..ef75e77 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,7 +9,7 @@ "dev": "node --import tsx src/bootstrap.ts", "build": "tsc", "typecheck": "tsc --noEmit", - "start": "node dist/bootstrap.js", + "start": "node dist/backend/src/bootstrap.js", "check:schema-contract": "node --import tsx verifySchemaContract.ts", "check:rls-policies": "node --import tsx verifyRlsPolicies.ts", "check:secret-hygiene": "node --import tsx verifySecretHygiene.ts", @@ -53,10 +53,10 @@ "@azure/cosmos": "^4.3.0", "@azure/identity": "^4.10.0", "@azure/keyvault-secrets": "^4.9.0", - "@bytelyst/auth": "link:../../../learning_ai/learning_ai_common_plat/packages/auth", - "@bytelyst/config": "link:../../../learning_ai/learning_ai_common_plat/packages/config", - "@bytelyst/cosmos": "link:../../../learning_ai/learning_ai_common_plat/packages/cosmos", - "@bytelyst/llm": "link:../../../learning_ai/learning_ai_common_plat/packages/llm", + "@bytelyst/auth": "^0.1.0", + "@bytelyst/config": "^0.1.0", + "@bytelyst/cosmos": "^0.1.0", + "@bytelyst/llm": "^0.1.0", "@alpacahq/alpaca-trade-api": "^3.1.3", "@supabase/supabase-js": "^2.90.1", "@types/cors": "^2.8.19", diff --git a/docker-compose.yml b/docker-compose.yml index 0c9545e..0820d54 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,19 +3,11 @@ version: '3.9' services: backend: build: - context: ./backend + context: . + dockerfile: backend/Dockerfile + args: + GITEA_NPM_TOKEN: ${GITEA_NPM_TOKEN} env_file: - .env ports: - '4018:4018' - - web: - build: - context: ./web - env_file: - - .env - ports: - - '3048:3048' - depends_on: - - backend - diff --git a/package.json b/package.json index 9c5fa62..647f417 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,10 @@ "verify": "./scripts/verify.sh" }, "dependencies": { - "@bytelyst/kill-switch-client": "link:../../learning_ai/learning_ai_common_plat/packages/kill-switch-client", - "@bytelyst/react-auth": "link:../../learning_ai/learning_ai_common_plat/packages/react-auth", - "@bytelyst/react-native-platform-sdk": "link:../../learning_ai/learning_ai_common_plat/packages/react-native-platform-sdk", - "@bytelyst/telemetry-client": "link:../../learning_ai/learning_ai_common_plat/packages/telemetry-client" + "@bytelyst/kill-switch-client": "^0.1.0", + "@bytelyst/react-auth": "^0.1.1", + "@bytelyst/react-native-platform-sdk": "^1.0.0", + "@bytelyst/telemetry-client": "^0.1.0" }, "devDependencies": { "typescript": "^5.9.3" diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..efe821e --- /dev/null +++ b/vercel.json @@ -0,0 +1,11 @@ +{ + "installCommand": "pnpm install --filter @bytelyst/trading-web", + "buildCommand": "pnpm --filter @bytelyst/trading-web run build", + "outputDirectory": "web/dist", + "rewrites": [ + { + "source": "/(.*)", + "destination": "/index.html" + } + ] +} diff --git a/web/Dockerfile b/web/Dockerfile deleted file mode 100644 index d8e1178..0000000 --- a/web/Dockerfile +++ /dev/null @@ -1,34 +0,0 @@ -# --- Stage 1: Build --- -FROM node:18-alpine AS builder - -WORKDIR /app - -# Install build dependencies -COPY package*.json ./ -RUN npm install - -# Copy source and build -# Copy source and build -COPY . . - -# Build-time environment variables -ARG VITE_SUPABASE_URL -ARG VITE_SUPABASE_ANON_KEY -ARG VITE_API_URL - -ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL -ENV VITE_SUPABASE_ANON_KEY=$VITE_SUPABASE_ANON_KEY -ENV VITE_API_URL=$VITE_API_URL - -RUN npm run build - -# --- Stage 2: Serve --- -FROM nginx:stable-alpine - -# Copy static assets from builder -COPY --from=builder /app/dist /usr/share/nginx/html - -# Expose port 80 -EXPOSE 80 - -CMD ["nginx", "-g", "daemon off;"] diff --git a/web/package.json b/web/package.json index 61b3bf8..caf8a34 100644 --- a/web/package.json +++ b/web/package.json @@ -18,9 +18,9 @@ "preview": "vite preview" }, "dependencies": { - "@bytelyst/kill-switch-client": "link:../../../learning_ai/learning_ai_common_plat/packages/kill-switch-client", - "@bytelyst/react-auth": "link:../../../learning_ai/learning_ai_common_plat/packages/react-auth", - "@bytelyst/telemetry-client": "link:../../../learning_ai/learning_ai_common_plat/packages/telemetry-client", + "@bytelyst/kill-switch-client": "^0.1.0", + "@bytelyst/react-auth": "^0.1.1", + "@bytelyst/telemetry-client": "^0.1.0", "lucide-react": "^0.562.0", "react": "^19.2.0", "react-dom": "^19.2.0", diff --git a/web/vercel.json b/web/vercel.json deleted file mode 100644 index 99225d0..0000000 --- a/web/vercel.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rewrites": [ - { - "source": "/(.*)", - "destination": "/index.html" - } - ] -} \ No newline at end of file