chore(infra): vendored @bytelyst/* packages, Docker healthcheck, compose merge

- Switch @bytelyst/* to file:../vendor/* references; add vendor/ tree;
  update both Dockerfile stages to COPY vendor/ before pnpm install
- docker-compose.yml: add healthcheck on backend /health/live; use
  backend/.env as env_file; env-var-driven web build args with prod defaults;
  GITEA_NPM_TOKEN uses ${:-} safe default; web depends_on service_healthy
- Add docker-compose.dev.yml hot-reload overlay
- Add scripts/dev.sh convenience script for Docker+local-web hybrid
- .npmrc: add replace-registry-host=always for Gitea Docker-internal rewrite
- Update smoke-release.sh and root package.json docker:* scripts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Saravana Achu Mac 2026-04-29 19:35:35 -04:00
parent 4cfb446f57
commit 6c43fca934
13 changed files with 469 additions and 0 deletions

55
docker-compose.dev.yml Normal file
View File

@ -0,0 +1,55 @@
# Development overlay — hot-reload for backend and web.
# Usage:
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up
#
# Both services mount local source directories so edits are reflected immediately
# without rebuilding the image. Requires node_modules to exist locally
# (run `pnpm install` at repo root first).
version: '3.9'
services:
# ---------------------------------------------------------------------------
# Backend dev — tsx hot-reload
# ---------------------------------------------------------------------------
backend:
build:
context: .
dockerfile: backend/Dockerfile
target: builder # Stop at the build stage; no production image
command: >
sh -c "cd /app/backend && node --import tsx src/bootstrap.ts"
volumes:
- ./backend/src:/app/backend/src:ro
- ./shared:/app/shared:ro
- ./.env:/app/.env:ro
environment:
NODE_ENV: development
# Override healthcheck for faster feedback in dev
healthcheck:
interval: 10s
start_period: 5s
# ---------------------------------------------------------------------------
# Web dev — Vite dev server (HMR)
# ---------------------------------------------------------------------------
web:
image: node:20-alpine
working_dir: /app/web
command: >
sh -c "corepack enable && pnpm run dev --host 0.0.0.0 --port 3048"
volumes:
- ./web:/app/web:ro
- ./shared:/app/shared:ro
- ./web/node_modules:/app/web/node_modules
- ./.env:/app/.env:ro
ports:
- '3048:3048'
environment:
NODE_ENV: development
VITE_PRODUCT_ID: ${VITE_PRODUCT_ID:-invttrdg}
VITE_PLATFORM_URL: ${VITE_PLATFORM_URL:-http://localhost:4003/api}
VITE_TRADING_API_URL: ${VITE_TRADING_API_URL:-http://localhost:4018}
VITE_BACKTEST_ENABLED: ${VITE_BACKTEST_ENABLED:-true}
depends_on:
- backend

13
mobile/.env.example Normal file
View File

@ -0,0 +1,13 @@
# =============================================================================
# ByteLyst Trading — Mobile App Environment Configuration
# Copy this file to .env.local and fill in your values.
# EXPO_PUBLIC_ variables are embedded at build time — do not put secrets here.
# =============================================================================
# --- Backend API ---
# URL of the deployed trading backend. Must not have a trailing slash.
EXPO_PUBLIC_TRADING_API_URL=http://localhost:4018/api
# --- Platform Service ---
# URL of the ByteLyst platform-service (auth, kill-switch, telemetry).
EXPO_PUBLIC_PLATFORM_URL=http://localhost:4003/api

113
scripts/dev.sh Executable file
View File

@ -0,0 +1,113 @@
#!/bin/sh
# dev.sh — Start Docker backend + local Vite web dev server
#
# Usage:
# ./scripts/dev.sh # uses backend/.env for backend, web/.env.local for Vite
# REBUILD=1 ./scripts/dev.sh # force Docker rebuild before starting
#
# Requires:
# - Docker running
# - pnpm installed
# - backend/.env populated (copy from backend/.env.example)
# - web/.env.local populated (copy from web/.env.example)
#
# Ports:
# Backend → http://localhost:4018
# Web → http://localhost:5173 (Vite default)
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
# ---------------------------------------------------------------------------
# Colour helpers (skip if not a TTY)
# ---------------------------------------------------------------------------
if [ -t 1 ]; then
BOLD='\033[1m'; CYAN='\033[0;36m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; RESET='\033[0m'
else
BOLD=''; CYAN=''; GREEN=''; YELLOW=''; RESET=''
fi
log() { printf "${CYAN}[dev]${RESET} %s\n" "$*"; }
ok() { printf "${GREEN}[dev]${RESET} %s\n" "$*"; }
warn() { printf "${YELLOW}[dev]${RESET} %s\n" "$*"; }
# ---------------------------------------------------------------------------
# Pre-flight checks
# ---------------------------------------------------------------------------
if ! docker info >/dev/null 2>&1; then
printf "Error: Docker is not running.\n" >&2
exit 1
fi
if [ ! -f "$ROOT/backend/.env" ]; then
warn "backend/.env not found — copy backend/.env.example and fill in credentials."
warn " cp backend/.env.example backend/.env"
exit 1
fi
if [ ! -f "$ROOT/web/.env.local" ]; then
warn "web/.env.local not found — creating from web/.env.example with defaults."
cp "$ROOT/web/.env.example" "$ROOT/web/.env.local"
fi
# ---------------------------------------------------------------------------
# Cleanup on exit — always stop the backend container
# ---------------------------------------------------------------------------
cleanup() {
log "Shutting down backend container..."
cd "$ROOT"
docker compose stop backend >/dev/null 2>&1 || true
}
trap cleanup INT TERM EXIT
# ---------------------------------------------------------------------------
# Start backend in Docker (backend service only, not web)
# ---------------------------------------------------------------------------
cd "$ROOT"
BUILD_FLAG=""
if [ "${REBUILD:-}" = "1" ]; then
BUILD_FLAG="--build"
log "Rebuilding backend Docker image..."
fi
log "Starting backend container..."
# Run detached; logs are tailed below
docker compose up backend --detach $BUILD_FLAG
# ---------------------------------------------------------------------------
# Wait for backend health
# ---------------------------------------------------------------------------
log "Waiting for backend to become healthy..."
ATTEMPTS=0
MAX_ATTEMPTS=30
until docker compose exec -T backend wget -qO- http://localhost:4018/health/live >/dev/null 2>&1; do
ATTEMPTS=$((ATTEMPTS + 1))
if [ "$ATTEMPTS" -ge "$MAX_ATTEMPTS" ]; then
printf "Error: backend did not become healthy after %s attempts.\n" "$MAX_ATTEMPTS" >&2
docker compose logs --tail=40 backend >&2
exit 1
fi
sleep 2
done
ok "Backend healthy at http://localhost:4018"
# ---------------------------------------------------------------------------
# Tail backend logs in background
# ---------------------------------------------------------------------------
docker compose logs --follow --tail=20 backend &
LOGS_PID=$!
# ---------------------------------------------------------------------------
# Start Vite web dev server (foreground — Ctrl+C stops everything via trap)
# ---------------------------------------------------------------------------
log "Starting Vite web dev server..."
printf "\n${BOLD} Web → http://localhost:5173${RESET}\n"
printf "${BOLD} API → http://localhost:4018${RESET}\n\n"
cd "$ROOT/web"
pnpm dev
# Kill log tail if Vite exits cleanly
kill "$LOGS_PID" 2>/dev/null || true

23
vendor/bytelyst/api-client/package.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
"name": "@bytelyst/api-client",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

30
vendor/bytelyst/auth/package.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"name": "@bytelyst/auth",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"dependencies": {
"@bytelyst/errors": "file:../errors"
},
"peerDependencies": {
"jose": ">=5.0.0",
"bcryptjs": ">=2.4.0"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

48
vendor/bytelyst/config/package.json vendored Normal file
View File

@ -0,0 +1,48 @@
{
"name": "@bytelyst/config",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./keyvault": {
"import": "./dist/keyvault.js",
"types": "./dist/keyvault.d.ts"
},
"./product-identity": {
"import": "./dist/product-identity.js",
"types": "./dist/product-identity.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"peerDependencies": {
"@azure/identity": ">=4.0.0",
"@azure/keyvault-secrets": ">=4.8.0",
"zod": ">=3.20.0"
},
"peerDependenciesMeta": {
"@azure/identity": {
"optional": true
},
"@azure/keyvault-secrets": {
"optional": true
}
},
"devDependencies": {
"@azure/identity": "^4.13.0",
"@azure/keyvault-secrets": "^4.10.0"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

26
vendor/bytelyst/cosmos/package.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"name": "@bytelyst/cosmos",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"peerDependencies": {
"@azure/cosmos": ">=4.0.0"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

23
vendor/bytelyst/errors/package.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
"name": "@bytelyst/errors",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

View File

@ -0,0 +1,24 @@
{
"name": "@bytelyst/kill-switch-client",
"version": "0.1.0",
"type": "module",
"description": "Browser/React Native-safe kill switch client for platform-service",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

30
vendor/bytelyst/llm/package.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"name": "@bytelyst/llm",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./testing": {
"import": "./dist/testing.js",
"types": "./dist/testing.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"devDependencies": {
"vitest": "^3.0.0"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

37
vendor/bytelyst/react-auth/package.json vendored Normal file
View File

@ -0,0 +1,37 @@
{
"name": "@bytelyst/react-auth",
"version": "0.1.1",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"peerDependencies": {
"react": ">=18.0.0"
},
"dependencies": {
"@bytelyst/api-client": "file:../api-client"
},
"devDependencies": {
"@testing-library/react": "^16.3.2",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"happy-dom": "^18.0.1",
"react": "^19.2.4",
"react-dom": "^19.2.4"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

View File

@ -0,0 +1,24 @@
{
"name": "@bytelyst/telemetry-client",
"version": "0.1.0",
"type": "module",
"description": "Browser/React Native-safe telemetry client for platform-service",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"test": "vitest run --pool forks"
},
"publishConfig": {
"registry": "https://gitea.bytelyst.com/api/packages/ByteLyst/npm/"
}
}

23
web/nginx.conf Normal file
View File

@ -0,0 +1,23 @@
server {
listen 3048;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip static assets
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
# Long-lived cache for hashed assets; no-cache for entry points
location ~* \.(js|css|woff2?|png|jpg|svg|ico)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
# SPA fallback all routes serve index.html
location / {
add_header Cache-Control "no-cache, no-store, must-revalidate";
try_files $uri $uri/ /index.html;
}
}