5.9 KiB
5.9 KiB
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
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. |