Clone this repository and use it as a template for your projects.
Read the AdaptiveStone Framework documentation for installation, configuration, and API guides.
This project includes working examples of the framework features commonly used when building an application.
| Feature | Where to look |
|---|---|
| Controller auto-loading, pathless route groups, and framework overrides | PathlessRouteGroups.ts is physically grouped but serves GET /pathlessroutegroups; Auth.ts stays at /auth and replaces the framework controller even from inside a group. |
| Standard Schema validation, generated request types, Zod input coercion, and resilient OpenAPI | PathlessRouteGroups.ts uses z.coerce.date() and Pagination; Person.ts validates a request body. npm run gen types both handlers and npm run openapi documents them, including Pagination's page and limit. |
| Cache with memory/Redis driver portability | PathlessRouteGroups.ts uses the default memory-backed app.cache.getSetValue() API; selecting Redis requires no controller change. |
| Typed HTTP errors | Person.ts throws NotFoundError and lets the framework render the response centrally. |
| Authentication middleware and typed authenticated users | Profile.ts uses GetUserByToken + Auth; generated types make req.appInfo.user non-null. |
| Typed config and named rate-limit policies | rateLimiter.ts declares the policy consumed as route-level middleware by Person.ts; its simple config read before the literal route return remains codegen-safe. |
| Model schemas, statics, instance methods, and virtuals | Person.ts demonstrates every model extension surface. |
| Email module, custom template engines, and localized templates | Email.ts, registerEngines.ts, and src/locales/. |
| HTTP boot hook and external observability integration | server.ts keeps the typed bootHttp hook next to its owner, registers the live GET /health route, and initializes Sentry. |
| Single-process and clustered deployment | server.ts is supervisor-friendly; index.ts uses the public runCluster() helper. |
| Framework-aware testing | src/tests/ integrates Node's test runner with the framework lifecycle; setupHooks.ts shows safe server readiness, and controller/model tests are colocated. |
| Operational CLI | src/cli.ts propagates command failures through the process exit code; npm run routes, npm run openapi, npm run gen, and npm run cli migration/create -- --name=<name> expose routing, API contracts, generated types, and migrations. |
Node.js 24 or newer is required. CI currently runs on the Node.js 24 LTS line.
Run backend commands inside Docker:
docker compose exec -T backend npm test
docker compose exec backend npm run t
docker compose exec -T backend npm run test:cinpm testruns the suite once with Node's built-in test runner.npm run treruns affected tests in watch mode.npm run test:cienforces 80% line coverage, 80% branch coverage, and 75% function coverage, and writescoverage/lcov.info.- A root-level application setup hook must call
await ensureTestServerReady()before it reads framework config, models, or the HTTP server. - When using
t.plan(n), make every assertion throught.assert.*; separately importednode:assertcalls are not counted by the plan.
npm run routes
npm run openapiroutes prints the runtime route tree. openapi writes the generated OpenAPI
3.1 document to the gitignored openapi.json file without opening a database,
network connection, or listening port.
npm startruns one server process. Use this under Docker, Kubernetes, systemd, PM2, or another external supervisor.npm run start:clusteruses the framework's publicrunCluster()helper to run one worker per available CPU, forward shutdown signals, and apply the framework's fixed crash-loop safety policy. Use it only when this Node process should supervise all workers on a single host.
Do not combine framework clustering with PM2 cluster mode or multiple workers inside each container; choose one owner for process count and restarts.