# --- builder --- FROM node:22-alpine AS builder WORKDIR /repo RUN corepack enable && corepack prepare pnpm@10.28.0 --activate COPY pnpm-workspace.yaml package.json pnpm-lock.yaml tsconfig.base.json ./ COPY apps/api/package.json ./apps/api/ COPY packages/db/package.json ./packages/db/ COPY packages/shared/package.json ./packages/shared/ RUN pnpm install --frozen-lockfile COPY apps/api ./apps/api COPY packages/db ./packages/db COPY packages/shared ./packages/shared # Die Workspace-Libs werden zur Laufzeit (Node) als JS geladen. Ihre tsconfig hat # jedoch noEmit:true und main zeigt auf die TS-Quelle — Node kann das nicht laden. # Daher hier mit Emit kompilieren und main/exports im Image auf die dist-Artefakte # umbiegen (nur im Image; Repo-Quelle, Dev-Modus und Web-/Vite-Build bleiben unberührt). RUN pnpm exec tsc -p packages/shared/tsconfig.json --noEmit false \ && pnpm exec tsc -p packages/db/tsconfig.json --noEmit false \ && pnpm --filter api build \ && node -e "const fs=require('fs');for(const p of ['packages/db','packages/shared']){const f=p+'/package.json';const j=JSON.parse(fs.readFileSync(f,'utf8'));const fix=s=>s.replace('./src/','./dist/').replace(/[.]ts$/,'.js');if(j.main){j.main=fix(j.main);j.types=j.main.replace(/[.]js$/,'.d.ts');}if(j.exports)for(const k in j.exports){if(typeof j.exports[k]==='string')j.exports[k]=fix(j.exports[k]);}fs.writeFileSync(f,JSON.stringify(j,null,2));}" # --- runtime --- FROM node:22-alpine AS runtime WORKDIR /app ENV NODE_ENV=production RUN corepack enable && corepack prepare pnpm@10.28.0 --activate COPY --from=builder /repo/pnpm-workspace.yaml /repo/package.json /repo/pnpm-lock.yaml ./ COPY --from=builder /repo/apps/api/package.json ./apps/api/ COPY --from=builder /repo/packages/db ./packages/db COPY --from=builder /repo/packages/shared ./packages/shared COPY --from=builder /repo/apps/api/dist ./apps/api/dist RUN pnpm install --frozen-lockfile --prod EXPOSE 3000 WORKDIR /app/apps/api CMD ["node", "dist/server.js"]