Files
zeekayandHanzo Dev 43c431fdd1 build on tsc, not the tsgo binary
The 8.x convergence pass rewrote every build script to `tsgo` and added
@typescript/native-preview to both manifests. native-preview is typescript@7,
the Go-native compiler, and its package exports carry no JS compiler API:
require('typescript') yields only {version, versionMajorMinor} — no
createProgram, no transpileModule. Anything that drives the compiler in
process rather than shelling out to a binary breaks against it, which is
most of the toolchain.

So the scripts go back to `tsc` on typescript 5.9.3, the version both
packages already pinned, and native-preview leaves the manifests and the
lockfile. web's pin loosens from an exact 5.9.3 to ^5.9.3 to match
finance-ui.

The Dockerfile comment and web/css.d.ts both still described the tsgo setup
and its TS2882 behaviour; they now describe what the code actually does.
The css module declaration itself stays — Next declares only *.module.css,
so the bare stylesheet path still needs one.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 16:42:36 -07:00

49 lines
2.8 KiB
Docker

# finance.hanzo.ai — Hanzo Finance product web (landing + IAM login + app shell).
# Multi-stage build of the pnpm workspace: build the shared @hanzo/finance-ui, then the
# Next 15 standalone server. Build context is the REPO ROOT (declared in hanzo.yml), so
# the workspace + the linked package are both present. Built by CI/CD (arcd) for every
# arch — never locally. Base image uses the ECR Public Docker-library mirror to avoid
# Docker Hub's unauthenticated pull-rate limit on cold runners.
FROM public.ecr.aws/docker/library/node:22-alpine AS base
RUN corepack enable && corepack prepare [email protected] --activate
WORKDIR /app
# ── build (install + gate + next build in one stage) ─────────────────────────
FROM base AS build
# Install deps first so the layer caches on the lockfile. `.npmrc` (node-linker=hoisted)
# MUST be present before install: the canonical stack dedupes the @hanzo/gui graph into a
# single hoisted tree, which is what lets the GuiCustomConfig type augmentation (see
# gui.d.ts → @hanzo/ui/gui-config) reach @hanzo/ui and the raw-TS @hanzo/data source.
# Under the isolated linker (no .npmrc) that augmentation is lost and the type gate fails
# on every vendor shorthand prop (bg/items/justify/rounded/…). Installing in this stage
# (not a separate deps stage) keeps the hoisted node_modules linker-agnostic — no
# per-package node_modules to cherry-pick across stages.
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml .npmrc ./
COPY packages/finance-ui/package.json packages/finance-ui/
COPY web/package.json web/
RUN pnpm install --frozen-lockfile
# Overlay source; `**/node_modules` is .dockerignored so the install above survives.
COPY . .
# The image build is the single CI gate (the bare runner has no Node). Type-check the
# shared package (its `build` IS `tsc --noEmit` — one command, not
# a second spelling of the same check), run its unit tests, then build the Next app. A
# failing test or type error fails the image build, so nothing broken can deploy.
RUN pnpm --filter @hanzo/finance-ui build \
&& pnpm --filter @hanzo/finance-ui test \
&& pnpm --filter @hanzo/finance-web build
# ── runtime (Next standalone) ────────────────────────────────────────────────
FROM base AS runner
ENV NODE_ENV=production
ENV PORT=4200
ENV HOSTNAME=0.0.0.0
WORKDIR /app
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
# Standalone traces from the workspace root, so the server + its node_modules land
# under /app and the app under /app/web.
COPY --from=build --chown=nextjs:nodejs /app/web/.next/standalone ./
COPY --from=build --chown=nextjs:nodejs /app/web/.next/static ./web/.next/static
USER nextjs
EXPOSE 4200
CMD ["node", "web/server.js"]