76efc459bb
- Lean file-backed accounts (server/src/accounts.ts): scrypt-hashed passwords, hashed bearer tokens, per-user backup blob; persisted under DATA_DIR. /api routes (register/login/logout, PUT/GET /save) with per-IP throttle + 48MB body limit. - Client cloud lib + Settings "Cloud sync": sign up / sign in, back up this device, restore from cloud (whole-backup push/pull, last-write-wins). Local-first default; the assistant key (localStorage) is never part of the synced Dexie backup. - Pathbuilder 2e import: the existing character import now detects a Pathbuilder build JSON and converts it to a PF2e character (abilities/HP/saves/skills). - Dockerfile creates a node-owned /data; compose mounts a named ttrpg-data volume. - (Spectator links = existing /play?room=CODE; PDF export = existing Print.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
24 lines
836 B
Docker
24 lines
836 B
Docker
# --- build stage: bundle the PWA + the realtime server ---
|
|
FROM oven/bun:1 AS build
|
|
WORKDIR /app
|
|
COPY package.json bun.lock* bun.lockb* ./
|
|
RUN bun install
|
|
COPY . .
|
|
RUN bun run build # tsc -b && vite build → /app/dist
|
|
RUN bun run build:server # esbuild → /app/server/dist/index.js
|
|
|
|
# --- runtime stage: small node image, non-root, serves dist + /ws ---
|
|
FROM node:20-slim AS runtime
|
|
ENV NODE_ENV=production STATIC_DIR=/app/dist PORT=8787
|
|
WORKDIR /app/server
|
|
COPY server/package.json ./
|
|
RUN npm install --omit=dev --no-audit --no-fund
|
|
COPY --from=build /app/server/dist ./dist
|
|
COPY --from=build /app/dist /app/dist
|
|
# Cloud-sync data dir; create it node-owned so a fresh named volume mounts writable.
|
|
ENV DATA_DIR=/data
|
|
RUN mkdir -p /data && chown -R node:node /app /data
|
|
USER node
|
|
EXPOSE 8787
|
|
CMD ["node", "dist/index.js"]
|