ExetJS Architecture
ExetJS is a small modular backend engine on top of Express and TypeScript.
Core rule
Every module is explicit:
export type ExetModule = {
name: string;
basePath?: string;
dependsOn?: readonly string[];
register: (ctx: ExetContext) => Promise<ExetModuleRegisterResult> | ExetModuleRegisterResult;
};
An HTTP module returns { router }; an infrastructure module can return { dispose } without a router. dispose is also allowed alongside a router.
Registration orders explicitly declared dependencies and validates missing dependencies, duplicate names and cycles before side effects. Startup failure closes successful resource registrations in reverse order. HTTP server startup waits for listening; server shutdown drains HTTP before disposing resources. Signal handling is configurable and defaults to enabled only when resource disposers exist.
No magic
ExetJS intentionally avoids:
- decorators;
- reflection metadata;
- hidden dependency injection;
- mandatory ORM;
- automatic file discovery;
- hidden resource discovery.
Core packages
@exetjs/core Runtime engine helpers and shared types
@exetjs/cli Developer CLI and code templates
Generated app shape
Generated applications depend on @exetjs/core for the engine helpers and keep business code inside src/modules.
src/
├─ main.ts
├─ app.ts
├─ config/
├─ middlewares/
├─ modules/
└─ shared/
Internal DB development layer
tools/db-core is the single development source for shared DB behavior. It is outside the workspace packages and does not ship to consumers. Provider descriptors and native adapters produce standalone CLI templates at build time. The engine and CLI installer contain no closed list of database providers.
A new database is added as a new adapter directory following the same contract. See Database modules and the internal authoring guide in tools/db-core/README.md.