Architecture

Orveth is a backend framework ecosystem organized as acyclic npm packages. The framework core is @orveth/server; everything else is optional infrastructure around it.

Package layers

  1. Runtime@orveth/server wraps Node.js http with routing, middleware, and response helpers.
  2. HTTP primitives@orveth/http (status, headers, response bodies) and @orveth/https (TLS material and HTTPS listeners).
  3. Cross-cutting@orveth/errors, @orveth/config, @orveth/logger, @orveth/validation, @orveth/core.
  4. Integrations@orveth/jwt (symmetric tokens), @orveth/prisma (health and shutdown around Prisma Client).
  5. Convenienceorveth meta-package re-exports public APIs from every layer above.

Dependency rules

  • No published package imports application code.
  • @orveth/server depends only on @orveth/errors and @orveth/http.
  • @orveth/https, @orveth/jwt, and @orveth/prisma do not depend on @orveth/server—they accept minimal context shapes or Node listeners so you can use them outside the Orveth app class.
  • Public APIs export from package roots only; deep src/ paths are internal.

Request lifecycle

Inside @orveth/server, each inbound request follows this path:

  1. Node invokes the RequestListener from Orveth#toRequestListener() or listen().
  2. The HTTP method is parsed. Unsupported verbs receive 405 with code ORVETH_HTTP_METHOD_NOT_ALLOWED (verbs are not coerced to GET).
  3. The path is normalized (leading slash, query string stripped for matching).
  4. A RequestContext is constructed inside a try/catch so dispatch failures still return JSON error bodies.
  5. Registered middleware runs in order; each calls next() to continue.
  6. An O(1) lookup resolves method + path. No match → 404 ORVETH_HTTP_NOT_FOUND.
  7. The route handler runs. Returning ctx.ok() / ctx.json() is equivalent to awaiting those helpers.
  8. If nothing commits a response, the runtime emits 500 ORVETH_NO_RESPONSE. Thrown HttpError values map to their status codes.

Routing model

  • Exact match on HTTP method and path—no parameters, wildcards, or nested routers.
  • Duplicate registration for the same method/path throws ORVETH_ROUTE_DUPLICATE at startup.
  • app.all(path, handler) registers the same handler for every supported verb.

Meta-package vs scoped installs

orveth is a thin re-export barrel. Production services should depend on @orveth/server (and optional scoped modules) so dependency graphs stay explicit and auditable.

Implementation details for each module live on the package index and individual reference pages.