# syntax=docker/dockerfile:1
# check=skip=SecretsUsedInArgOrEnv

# Base image can be overridden for Turbo Layer Caching
# Default is the standard node image
ARG BASE_IMAGE=node:22-alpine3.23
FROM ${BASE_IMAGE} AS builder

# Build args for Vite (baked into client bundle at build time).
# The anon key is a public value — it ships in the JS bundle to every browser.
ARG VITE_PROJECT_NAME
ARG VITE_SUPABASE_URL
ARG VITE_SUPABASE_ANON_KEY
# Optional service feature flags (set to "true" when the service is enabled)
ARG VITE_N8N_ENABLED
ARG VITE_METABASE_ENABLED
ARG VITE_REDIS_ENABLED
ARG VITE_OBSERVABILITY_ENABLED
# Routing mode: 'subdomain' (compose) or 'path' (k8s)
ARG VITE_ROUTING_MODE
# Analytics (optional — empty by default, no tracking unless configured)
ARG VITE_PLAUSIBLE_DOMAIN
ARG VITE_PLAUSIBLE_SCRIPT_URL

# Ensure pnpm is available (runtime base image already has it, standard node image doesn't)
RUN command -v pnpm >/dev/null 2>&1 || npm install -g pnpm@9

WORKDIR /app

# Install dependencies first so the layer caches independently of source.
# .dockerignore excludes node_modules, so this always runs against a clean
# /app — no need for a defensive `if [ ! -d node_modules ]` check.
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
    pnpm install --frozen-lockfile

# Copy application code
COPY tsconfig.json tsconfig.server.json biome.json vite.config.ts components.json ./
COPY content/ ./content/
COPY scripts/ ./scripts/
COPY src/ ./src/

# Build client (Vite) and server (TypeScript). Split into TWO RUNs so an
# edit that only touches src/server/ doesn't bust the Vite client cache
# (and vice versa). The COPY src/ above still cache-busts both on any
# src change, but with split RUNs the slower of the two (Vite) can land
# from cache when only the other side moved.
# VITE_ env vars are available from ARGs during build
ENV VITE_PROJECT_NAME=$VITE_PROJECT_NAME
ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL
ENV VITE_SUPABASE_ANON_KEY=$VITE_SUPABASE_ANON_KEY
ENV VITE_N8N_ENABLED=$VITE_N8N_ENABLED
ENV VITE_METABASE_ENABLED=$VITE_METABASE_ENABLED
ENV VITE_REDIS_ENABLED=$VITE_REDIS_ENABLED
ENV VITE_OBSERVABILITY_ENABLED=$VITE_OBSERVABILITY_ENABLED
ENV VITE_ROUTING_MODE=$VITE_ROUTING_MODE
ENV VITE_PLAUSIBLE_DOMAIN=$VITE_PLAUSIBLE_DOMAIN
ENV VITE_PLAUSIBLE_SCRIPT_URL=$VITE_PLAUSIBLE_SCRIPT_URL
RUN pnpm build:client
RUN pnpm build:server

# Dependency stage — install runtime deps in a throwaway container
FROM node:22-alpine3.23 AS deps
WORKDIR /deps
RUN npm init -y > /dev/null 2>&1 && \
    npm install --no-package-lock pino@10

# Production stage — minimal Alpine with just the node binary
FROM alpine:3.23 AS runner

RUN apk add --no-cache libstdc++ && \
    addgroup -g 1001 -S hono && \
    adduser -S hono -u 1001 -G hono

COPY --from=node:22-alpine3.23 /usr/local/bin/node /usr/local/bin/node

WORKDIR /app

# Copy pre-installed runtime dependencies from deps stage
COPY --from=deps /deps/node_modules ./node_modules

# Copy built application
COPY --from=builder /app/dist ./dist

# Copy entrypoint
COPY docker-entrypoint.sh ./
RUN chmod +x docker-entrypoint.sh

# Security: switch to non-root user
USER hono

EXPOSE 3000

ENV NODE_ENV=production
ENV PORT=3000

ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["node", "dist/server/index.js"]
