Internal architecture
Every @withpotter/* package follows the same layered (clean-architecture)
shape. Once you know the layers, you can read any package — the
module reference lists the concrete classes per package.
The layers
| Layer | File suffix | Responsibility |
|---|---|---|
| Controller | *.controller.ts | Declares HTTP routes, validates input via DTOs, delegates to a use-case. No business logic. |
| Use-case | *.usecase.ts | One application operation with a single execute() method. Orchestrates repositories, ports, and domain rules. |
| Repository | *.repo.ts | Data access for one aggregate. Wraps a Sequelize entity; the only layer that builds queries. |
| Entity | *.entity.ts | A sequelize-typescript model — the table shape, columns, and relations. |
| DTO | *.dto.ts | Request/response shapes with class-validator decorators; what the global ValidationPipe enforces. |
| Port | *.port.ts | A DI token + contract for a capability the package does not own (mail, payments, etc.). |
| Provider / Adapter | *.provider.ts, *.adapter.ts | Concrete implementations. The engine binds adapters to ports. |
| Service | *.service.ts | Shared helpers used by use-cases (pricing, formatting, integrations). |
| Module | *.module.ts | The forRoot() factory that wires the above into a DynamicModule. |
How a request flows
The controller is intentionally thin: it maps an HTTP route to exactly one use-case. All logic lives in the use-case, which is why the module reference lists use-cases as the real description of what a package does.
Why this shape
- Testable. Use-cases are plain classes with one method; they can be unit tested without HTTP or a database.
- Swappable infrastructure. Cross-package needs go through ports, so a mailer or payment gateway is replaced without touching a use-case.
- Self-owned data. Each package owns its entities and the only repository that touches them — no package reaches into another’s tables.
- Composable. The
forRoot()module is the single seam the engine wires, per the package contract.
Want the concrete classes? The module reference is generated
from source and lists every use-case (with its execute() signature), entity
(with fields), and repository (with methods) for each package.