ErrorHandlerService has zero dependency on Express — it's a plain
"map an error to {status, body}" service that works identically
behind any HTTP framework. It had no business living in a package
named express-tools.
Extracted HttpError, ErrorHandlerService, and ErrorHandlingResult
into a new packages/error-tools package (same tsc-build-to-dist
pattern as shared/express-tools). express-tools now only keeps the
actual Express-specific layer: ExpressServer, wrapAsyncHandler, and
createErrorMiddleware (which adapts ErrorHandlerService, imported
from error-tools, onto Express).
- packages/error-tools: new package, depends on shared + zod
- packages/express-tools: drops zod dependency, adds error-tools
dependency for error-middleware.ts's type import
- apps/api: adds error-tools dependency; app.ts, auth.service.ts,
require-auth.ts now import HttpError/errorHandlerService from
error-tools instead of express-tools
- apps/api/Dockerfile: adds COPY for packages/error-tools in the
runtime stage
- specs/error-handling.md, specs/backend-architecture.md, README.md
updated to reflect the new package split
Verified: pnpm lint, pnpm build (all packages, correct dependency
order), pnpm test (9/9 Mocha), pnpm test:bdd (5/5 Cucumber), full
Docker rebuild + compose up (no crash-loop), curl + browser checks
of /health, unknown-route 404, signup (201), duplicate-email 409
(code 4001 EMAIL_ALREADY_IN_USE) — all going through the moved
ErrorHandlerService/HttpError correctly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
38 lines
1.8 KiB
Docker
38 lines
1.8 KiB
Docker
# Debian-based (not alpine) on purpose: avoids musl-vs-glibc native binding
|
|
# surprises for argon2/Prisma's engine binaries. Same base image family for
|
|
# build and runtime stages, so "native" binaries built in `build` are
|
|
# guaranteed compatible with `runtime`.
|
|
FROM node:22-slim AS base
|
|
# Prisma's query engine needs OpenSSL to be present to detect the right
|
|
# binary target; without it, it silently defaults to a guess (openssl-1.1.x)
|
|
# that may not match what's actually on the image and fail at runtime.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends openssl && rm -rf /var/lib/apt/lists/*
|
|
RUN corepack enable
|
|
WORKDIR /repo
|
|
|
|
FROM base AS build
|
|
COPY . .
|
|
RUN pnpm install --frozen-lockfile
|
|
RUN pnpm --filter api build
|
|
|
|
# Copies the monorepo structure as-is (not a flattened single package) so
|
|
# pnpm's symlinked node_modules (root node_modules/.pnpm <- apps/api/node_modules)
|
|
# stay valid — paths must match exactly between build and runtime stages.
|
|
FROM base AS runtime
|
|
ENV NODE_ENV=production
|
|
COPY --from=build /repo/node_modules ./node_modules
|
|
COPY --from=build /repo/package.json ./package.json
|
|
COPY --from=build /repo/pnpm-workspace.yaml ./pnpm-workspace.yaml
|
|
COPY --from=build /repo/packages/shared ./packages/shared
|
|
COPY --from=build /repo/packages/error-tools ./packages/error-tools
|
|
COPY --from=build /repo/packages/express-tools ./packages/express-tools
|
|
COPY --from=build /repo/apps/api/node_modules ./apps/api/node_modules
|
|
COPY --from=build /repo/apps/api/dist ./apps/api/dist
|
|
COPY --from=build /repo/apps/api/prisma ./apps/api/prisma
|
|
COPY --from=build /repo/apps/api/package.json ./apps/api/package.json
|
|
|
|
WORKDIR /repo/apps/api
|
|
EXPOSE 3000
|
|
# Applies pending migrations before starting — keeps the review environment's
|
|
# schema in sync automatically, no manual step needed.
|
|
CMD ["sh", "-c", "node_modules/.bin/prisma migrate deploy && node dist/server.js"]
|