# The Tera API, as one small image. # # TypeScript is not compiled: Node runs the .ts sources directly by stripping # types at load, which is why there is no build stage, no dist/ and no source # maps to keep in sync. It is also why `erasableSyntaxOnly` is on in # server/tsconfig.json — an enum or a parameter property would break the runtime # and not the typecheck, which is the worst possible order to find out. # # The build context is the repo root, because the server's type contract lives # in the root package at src/server/wire.ts. FROM node:24-alpine WORKDIR /app # The lockfile and both manifests, so the layer cache survives a source change. COPY package.json package-lock.json ./ COPY server/package.json ./server/ # Only the server workspace's production dependencies. Without --workspace this # would also install three.js, which the API has no use for. RUN npm ci --omit=dev --workspace @lumbridge/tera-api # The whole browser package's source, for the sake of src/server/wire.ts. Every # import of it is type-only and is erased before anything is loaded, so none of # this is read at runtime — it is here so that a typecheck inside the image tells # the truth. COPY src ./src COPY server/src ./server/src ENV NODE_ENV=production # Inside a container, loopback is a different loopback. This is the only reason # TERA_HOST exists. ENV TERA_HOST=0.0.0.0 EXPOSE 8431 USER node CMD ["node", "server/src/index.ts"]