FROM node:22-alpine AS base RUN corepack enable && corepack prepare pnpm@latest --activate FROM base AS deps WORKDIR /app COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./ COPY tooling/ ./tooling/ COPY packages/ ./packages/ COPY apps/ ./apps/ RUN pnpm install --frozen-lockfile FROM deps AS builder WORKDIR /app # Generate Prisma client first (needed by @yetanother/db tsc build) RUN pnpm --filter @yetanother/db exec prisma generate # Compile all workspace dependency packages so their dist/ exists RUN pnpm --filter @yetanother/db build RUN pnpm --filter @yetanother/types build RUN pnpm --filter @yetanother/utils build RUN pnpm build --filter @yetanother/api FROM builder AS deployer WORKDIR /app # Create a self-contained deployment with flat node_modules (no .pnpm symlinks) # This ensures ALL transitive deps are resolvable by Node at runtime RUN pnpm --filter @yetanother/api deploy --prod --legacy /deploy # Copy compiled dist/ output (gitignored, so pnpm deploy excludes it) RUN rm -rf /deploy/dist && cp -r /app/apps/api/dist /deploy/dist RUN rm -rf /deploy/node_modules/@yetanother/db/dist && cp -r /app/packages/db/dist /deploy/node_modules/@yetanother/db/ RUN rm -rf /deploy/node_modules/@yetanother/types/dist && cp -r /app/packages/types/dist /deploy/node_modules/@yetanother/types/ RUN rm -rf /deploy/node_modules/@yetanother/utils/dist && cp -r /app/packages/utils/dist /deploy/node_modules/@yetanother/utils/ # Copy the real Prisma generated client from the builder's pnpm store # (pnpm deploy's postinstall generates a stub since it has no schema; we replace it) RUN PRISMA_CLIENT_DIR=$(ls -d /app/node_modules/.pnpm/@prisma+client* | head -1) && \ TARGET_DIR="/deploy/${PRISMA_CLIENT_DIR#/app/}/node_modules" && \ rm -rf "$TARGET_DIR/.prisma" && cp -r "$PRISMA_CLIENT_DIR/node_modules/.prisma" "$TARGET_DIR/.prisma" # Copy Prisma schema RUN rm -rf /deploy/prisma && cp -r /app/packages/db/prisma /deploy/prisma # Fix workspace package main fields to point to compiled JS instead of TS RUN for pkg in /deploy/node_modules/@yetanother/*/; do \ sed -i 's|"main": "./src/|"main": "./dist/src/|; /"main":/s/\.ts"/\.js"/' "$pkg/package.json"; \ done # Add .js extensions to relative imports in compiled ESM output (TS doesn't add them) RUN find -L /deploy/node_modules/@yetanother -name "*.js" -exec sed -i \ -e "s/\(from '\.\/[^'.]*\)'/\1.js'/g" \ -e "s/\(from '\.\.\/[^'.]*\)'/\1.js'/g" \ {} + FROM node:22-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY --from=deployer /deploy . EXPOSE 4000 CMD ["node", "dist/src/main.js"]