# Build the browser bundle separately so the final image contains only runtime
# dependencies and the generated static files.
FROM node:22-bookworm-slim AS build
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci
COPY frontend/package.json frontend/package-lock.json ./frontend/
RUN npm --prefix frontend ci

COPY app ./app
COPY public ./public
COPY frontend ./frontend
RUN npm run build:frontend

FROM node:22-bookworm-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production

COPY package.json package-lock.json ./
RUN npm ci --omit=dev && npm cache clean --force

COPY app ./app
COPY public ./public
COPY scripts ./scripts
# The tests and the front-end source travel with the image so the bundle can
# check ITSELF on whatever machine it is copied to: `npm test` and
# `npm run audit` both read fixtures from tests/, and the test that proves a
# view-only screen really disables its controls inspects
# frontend/src/lib/mayEdit.ts rather than trusting it was wired up.
COPY tests ./tests
COPY frontend/src ./frontend/src
COPY frontend/package.json frontend/tsconfig.json ./frontend/
COPY --from=build /app/frontend/dist ./frontend/dist

USER node
EXPOSE 3000

# A process probe rather than a database probe prevents a brief database outage
# from causing the platform to repeatedly replace healthy application instances.
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  CMD node -e "fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + '/health/live').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"

CMD ["node", "app/server.js"]
