quote-of-the-day-api-docs/architecture/tad.md

111 lines
5.9 KiB
Markdown

# Tech Architecture Document
## Stack
| Layer | Technology | Version / Notes |
|---|---|---|
| **Runtime** | Node.js | LTS ≥ 20 |
| **Language** | TypeScript | Strict mode; compiled to ES2020+; output to `dist/` |
| **Framework** | Express.js | v4 or v5 |
| **Validation** | Inline guard functions (or lightweight library such as `zod`) | Applied in route handlers before touching the store |
| **Testing** | Jest + `ts-jest` _or_ Vitest | Runnable via `npm test` |
| **Linting** | ESLint (TypeScript-aware ruleset) | Runnable via `npm run lint` |
| **Build tooling** | `tsc` (TypeScript compiler) | `tsconfig.json` with `strict: true` |
| **Package manager** | npm | Standard `package.json` / `package-lock.json` |
---
## Components
```mermaid
graph TD
Client["HTTP Client\n(browser / CLI / app)"]
subgraph "Express Application"
Router["Express Router\n(routes/quotes.ts)"]
HealthRoute["Health Route\nGET /health"]
Validator["Input Validator\n(validation.ts)"]
Store["Quote Store\n(store.ts)"]
ErrorHandler["Global Error Handler\n(middleware/error.ts)"]
end
Client -- "HTTP request" --> Router
Router --> HealthRoute
Router --> Validator
Validator -- "valid" --> Store
Validator -- "invalid → 400" --> Client
Store -- "quote data" --> Router
Router -- "JSON response" --> Client
ErrorHandler -- "500 response" --> Client
```
### Component descriptions
| Component | Responsibility |
|---|---|
| **`server.ts`** | Entry point. Creates the Express app, registers middleware (JSON body parser, routes, error handler), and starts the HTTP listener on `process.env.PORT \|\| 3000`. |
| **`routes/quotes.ts`** | Defines all four REST routes (`GET /health`, `GET /quote`, `GET /quotes`, `POST /quotes`). Delegates to the validator and store; formats JSON responses. |
| **`store.ts`** | In-memory quote repository. Exports `getAll()`, `getRandom()`, and `add(quote)`. Initialised at module load with five seed quotes. This is the unit-tested module. |
| **`validation.ts`** | Pure functions that inspect request bodies and return either a typed `Quote` object or a descriptive error string. No side effects. |
| **`middleware/error.ts`** | Express error-handling middleware (four-argument signature). Catches any unhandled error, logs it server-side, and returns `{ error: "Internal server error" }` with HTTP 500 — never leaking stack traces. |
---
## Data Model
The single domain object used throughout the service:
```
Quote {
text : string // non-empty; the body of the quote
author : string // non-empty; attribution
}
```
The in-memory store holds an array of `Quote` objects (`Quote[]`). There is no stable ID field in v1; if `DELETE`/`PUT` endpoints are added in a later phase an auto-incremented numeric index or UUID should be introduced.
**Seed data** — five `Quote` objects are hard-coded in `store.ts` and loaded at process startup. No migration, seeding script, or external database is required.
---
## Integrations
There are **no external integrations** in this version of the service. All data is held in process memory.
| Integration point | Status |
|---|---|
| Database / cache | Out of scope (NFR-9) |
| External quote APIs | Out of scope |
| Authentication / identity provider | Out of scope (Assumption 3) |
| Message broker / event bus | Out of scope |
The `GET /health` endpoint is designed to integrate with load-balancer liveness probes and monitoring systems (e.g. AWS ALB health checks, Kubernetes liveness probes, UptimeRobot) without any additional configuration.
---
## Non-Functional Requirements (Architectural Implications)
| Ref | Requirement | Architectural decision |
|---|---|---|
| NFR-1 | TypeScript strict mode, Node.js ≥ 20 | `tsconfig.json` with `"strict": true`, `"target": "ES2020"`; CI/CD should pin the Node version via `.nvmrc` or `engines` in `package.json`. |
| NFR-2 | Express.js v4 or v5 | Single dependency; middleware chain provides natural extension points for future auth or rate-limit layers. |
| NFR-3 | Input validation; 400 with `error` field | Validation extracted to `validation.ts` (pure, testable); route handlers call it before mutating the store. |
| NFR-4 | `application/json` responses | `express.json()` middleware for request parsing; all route handlers call `res.json(...)`. |
| NFR-5 | HTTP 500 without stack leaks | Centralised error-handling middleware catches everything; `console.error` on the server, sanitised body to the client. |
| NFR-6 | Unit tests via `npm test` | `store.ts` and `validation.ts` are pure modules with no Express dependency — easy to unit-test in isolation. |
| NFR-7 | `npm run lint` exits cleanly | ESLint configured with `@typescript-eslint` rules; no warnings allowed on the committed codebase. |
| NFR-8 | Cold-start ≤ 3 s | In-memory store eliminates DB connection overhead; Express startup is sub-second on any modern hardware. |
| NFR-9 | No persistence required | Intentional; simplifies the architecture and removes infrastructure dependencies for this phase. |
---
## Risks
| # | Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|---|
| R-1 | **Data loss on restart** | Certain (by design) | Low for this phase | Accepted per Assumption 1; documented clearly so consumers are not surprised. |
| R-2 | **Memory growth under heavy `POST /quotes` load** | Low (dev/demo context) | Low | Array growth is unbounded; if the service is ever exposed publicly, add a maximum-store-size guard or migrate to a persistent store. |
| R-3 | **No authentication — open write access** | Medium if publicly deployed | Medium | Acceptable for a development/demo service per Assumption 3; must be addressed before any production exposure. |
| R-4 | **Single process — no fault isolation** | Low | Low | In-scope by design (Assumption 2); the global error handler prevents a single bad request from crashing the process. |
| R-5 | **TypeScript / Express version drift** | Low | Low | Pin exact versions in `package.json`; run `npm audit` in CI. |