From 404d63d71222b5b49181478bf06509dd6bb76347 Mon Sep 17 00:00:00 2001 From: chemicalcommand Date: Thu, 26 Mar 2026 09:36:00 +0100 Subject: [PATCH] feat: add api module blueprint --- README.md | 6 +++ docs/api-architecture.md | 45 +++++++++++++++++++ tooling/api-module-template/README.md | 24 ++++++++++ tooling/api-module-template/index.ts | 4 ++ .../template.controller.ts | 9 ++++ .../api-module-template/template.routes.ts | 13 ++++++ .../api-module-template/template.service.ts | 7 +++ tooling/api-module-template/template.types.ts | 8 ++++ 8 files changed, 116 insertions(+) create mode 100644 docs/api-architecture.md create mode 100644 tooling/api-module-template/README.md create mode 100644 tooling/api-module-template/index.ts create mode 100644 tooling/api-module-template/template.controller.ts create mode 100644 tooling/api-module-template/template.routes.ts create mode 100644 tooling/api-module-template/template.service.ts create mode 100644 tooling/api-module-template/template.types.ts diff --git a/README.md b/README.md index c032058..fe8397b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ # Timely Capsule App 🕰️ +## Repository scaffolding + +The repository includes merge-safe implementation templates for work that will land incrementally. + +- `tooling/api-module-template` contains the baseline Express module structure for future API features. +- `docs/api-architecture.md` documents the intended module registration pattern. diff --git a/docs/api-architecture.md b/docs/api-architecture.md new file mode 100644 index 0000000..df51515 --- /dev/null +++ b/docs/api-architecture.md @@ -0,0 +1,45 @@ +# API Architecture + +This repository uses a feature-module pattern for the Express API. + +## Proposed structure + +When `apps/api` is added, use this layout: + +- `src/app` + - `create-app.ts` + - `register-routes.ts` +- `src/middleware` + - shared middleware and error handling +- `src/modules` + - one folder per feature + +Example: + +- `src/modules/health` +- `src/modules/auth` +- `src/modules/capsules` + +Each feature module should contain: + +- routes +- controller +- service +- types + +## Registration flow + +1. App bootstrap creates the Express app. +2. Shared middleware is attached. +3. Feature routers are mounted from a single module registry. +4. Error middleware is mounted last. + +## Why this is merge-safe + +- New features can add a module without editing unrelated business logic. +- Routing stays centralized while implementation remains feature-scoped. +- Services can evolve independently from controllers and middleware. + +## Template + +Use `tooling/api-module-template` as the starting point for new modules. diff --git a/tooling/api-module-template/README.md b/tooling/api-module-template/README.md new file mode 100644 index 0000000..5606131 --- /dev/null +++ b/tooling/api-module-template/README.md @@ -0,0 +1,24 @@ +# API Module Template + +This template provides a minimal Express module layout that can be copied into `apps/api/src/modules/` when the API app exists. + +## Layout + +- `index.ts`: module exports +- `.routes.ts`: route registration +- `.controller.ts`: request handlers +- `.service.ts`: business logic +- `.types.ts`: module-local types + +## Design goals + +- Route files only compose middleware and handlers +- Controllers translate HTTP requests into service calls +- Services own business rules and persistence orchestration +- Types stay close to the module until they become shared contracts + +## Integration notes + +- Register modules from a single `src/modules/index.ts` +- Keep middleware in `src/middleware` +- Keep app bootstrap and shared Express concerns in `src/app` diff --git a/tooling/api-module-template/index.ts b/tooling/api-module-template/index.ts new file mode 100644 index 0000000..fcf2f43 --- /dev/null +++ b/tooling/api-module-template/index.ts @@ -0,0 +1,4 @@ +export * from "./template.types"; +export { createTemplateController } from "./template.controller"; +export { createTemplateRouter } from "./template.routes"; +export { createTemplateService } from "./template.service"; diff --git a/tooling/api-module-template/template.controller.ts b/tooling/api-module-template/template.controller.ts new file mode 100644 index 0000000..53186fc --- /dev/null +++ b/tooling/api-module-template/template.controller.ts @@ -0,0 +1,9 @@ +import type { Request, Response } from "express"; +import type { TemplateService } from "./template.types"; + +export const createTemplateController = (service: TemplateService) => ({ + list: async (_request: Request, response: Response) => { + const records = await service.list(); + response.json({ data: records }); + } +}); diff --git a/tooling/api-module-template/template.routes.ts b/tooling/api-module-template/template.routes.ts new file mode 100644 index 0000000..d1d210b --- /dev/null +++ b/tooling/api-module-template/template.routes.ts @@ -0,0 +1,13 @@ +import { Router } from "express"; +import { createTemplateController } from "./template.controller"; +import { createTemplateService } from "./template.service"; + +export const createTemplateRouter = () => { + const router = Router(); + const service = createTemplateService(); + const controller = createTemplateController(service); + + router.get("/", controller.list); + + return router; +}; diff --git a/tooling/api-module-template/template.service.ts b/tooling/api-module-template/template.service.ts new file mode 100644 index 0000000..2816482 --- /dev/null +++ b/tooling/api-module-template/template.service.ts @@ -0,0 +1,7 @@ +import type { TemplateRecord, TemplateService } from "./template.types"; + +export const createTemplateService = (): TemplateService => ({ + async list(): Promise { + return []; + } +}); diff --git a/tooling/api-module-template/template.types.ts b/tooling/api-module-template/template.types.ts new file mode 100644 index 0000000..3ace5fe --- /dev/null +++ b/tooling/api-module-template/template.types.ts @@ -0,0 +1,8 @@ +export interface TemplateRecord { + id: string; + name: string; +} + +export interface TemplateService { + list(): Promise; +}