Add what you need.
The modules available in the current published ExetJS toolkit.
The CLI 0.1.0 package includes a health module in every generated application and one installable template: auth. Both use the same ExetModule contract.
Health
A basic application health endpoint, ready after project creation.
GET /api/v1/healthRead module reference Auth
Registration, login, current-user lookup, and a logout response.
exet install authRead module reference exet listThe list command reports auth. Health is already part of the generated app and is not a separate installable template. Core helpers such as validation and API responses belong to @exetjs/core.
Catalog verified against the templates and manifest in @exetjs/cli 0.1.0.
Health module #
exet init adds the module under src/modules/health/ and registers it in src/modules/index.ts. It has the name health and base path /health.
/api/v1/health200 OKcurl http://localhost:5000/api/v1/health{
"success": true,
"data": {
"status": "ok",
"engine": "ExetJS",
"timestamp": "2026-09-19T12:00:00.000Z"
}
}The timestamp is created for each request. The actual endpoint follows your configured API prefix and port.
import type { ExetModule } from '@exetjs/core';
import { createHealthRouter } from './health.routes.js';
export const healthModule: ExetModule = {
name: 'health',
basePath: '/health',
register: () => ({ router: createHealthRouter() }),
};The route calls getHealth from health.controller.ts. This checks that the HTTP application is responding. It does not probe your database or external services; extend the module if you need dependency readiness checks.
Auth module #
The auth template installs editable source files into your application. It uses bcryptjs for password hashing, jsonwebtoken for JWTs, and Zod for request validation.
- Register a user with a name, email and password.
- Verify login credentials and return a signed token.
- Resolve the current user from a bearer token.
- Return a logout acknowledgement.
The template uses an in-memory repository. Stored users disappear when the process restarts. Configure durable persistence and a strong JWT_SECRET before using it for a production application.
Installation & configuration #
Run the installer inside your generated ExetJS project. A dry run lets you inspect the intended changes first.
exet install auth --dry-run
exet install authThe CLI adds the template files, updates the module registry, adds the environment keys, updates dependencies, and installs those dependencies by default.
# Replace this placeholder with a strong random secret.
JWT_SECRET=replace-with-your-generated-random-secret
JWT_EXPIRES_IN=1dSet a non-empty secret. JWT_EXPIRES_IN defaults to 1d. The template has a development fallback and rejects a missing secret in production; do not rely on the fallback outside development.
Restart the development process after installing the module or changing its configuration.
Auth endpoints #
These paths use the default /api/v1 prefix. The module base path is /auth.
| Method & path | Input | Result |
|---|---|---|
POST/api/v1/auth/register | Name, email and password | 201 · public user |
POST/api/v1/auth/login | Email and password | 200 · user and JWT token |
GET/api/v1/auth/me | Authorization: Bearer <token> | 200 · public user |
POST/api/v1/auth/logout | No request body required | 200 · loggedOut: true |
Registration
name requires at least two characters, email must be valid, and password needs at least eight characters. An already registered email produces a 400 BAD_REQUEST error.
Login and current user
Invalid credentials produce 401 UNAUTHORIZED. The /me endpoint requires an Authorization: Bearer <token> header and rejects missing, invalid or expired tokens. Public user responses contain id, name, email, and createdAt; the password hash is excluded.
Request examples #
The following requests use an example local server on port 5000. Adjust the URL to your configured address.
curl -X POST http://localhost:5000/api/v1/auth/register \
-H 'Content-Type: application/json' \
-d '{"name":"Alex Developer","email":"alex@example.com","password":"example-password-123"}'curl -X POST http://localhost:5000/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"alex@example.com","password":"example-password-123"}'Read the token from data.token in the login response and use it for the authenticated request:
curl http://localhost:5000/api/v1/auth/me \
-H 'Authorization: Bearer YOUR_TOKEN'curl -X POST http://localhost:5000/api/v1/auth/logout{
"success": true,
"data": { "loggedOut": true }
}Files & dependencies #
The installer adds eight files under src/modules/auth/ and two shared security helpers under src/shared/security/.
| File | Responsibility |
|---|---|
auth.module.ts | Composes the repository, service, and router. |
auth.routes.ts | Registers the four HTTP routes and request validation. |
auth.controller.ts | Handles HTTP input, responses, and bearer token extraction. |
auth.service.ts | Registration, password checks, token creation, and current-user lookup. |
auth.repository.ts | In-memory user storage and lookup methods. |
auth.schema.ts | Zod registration and login schemas. |
auth.types.ts | Stored user, public user, and token payload types. |
index.ts | Exports authModule. |
shared/security/password.ts | bcryptjs hashing and password comparison. |
shared/security/jwt.ts | JWT signing and verification helpers. |
Added runtime dependencies are bcryptjs and jsonwebtoken, with @types/jsonwebtoken as a development dependency. The template uses the generated project's existing Express, Zod, and Core dependencies.
The module composes the repository, service and router inside register(ctx). Its service receives ctx.logger; there is no dependency injection container.
Persistence & token behavior #
These are the behaviors of the published 0.1.0 template:
- Users are held in a process-local Map. Multiple server processes do not share that state.
- The repository exposes create, findByEmail and findById. Replace the implementation to connect your database.
- Password hashing uses bcrypt with 12 salt rounds.
- Tokens are signed with a user ID in sub and the user's email. Their lifetime follows JWT_EXPIRES_IN.
- Logout returns an acknowledgement. It does not invalidate an already issued JWT. Remove the token from the client; add server-side revocation if your application needs it.
- The template does not include refresh tokens, password reset, email verification, or roles and permissions.
Validation currently checks the auth request body, while its controller reads req.body. If you add transformations or defaults to the schemas, update your controller to use res.locals.validated, as shown in the Core validation guide.
Your own modules #
You can add application-specific modules without an installable template. Implement ExetModule, return an Express router, and register the module explicitly.
import type { ExetModule } from '@exetjs/core';
import { healthModule } from './health/health.module.js';
import { helloModule } from './hello/hello.module.js';
// exet:imports:start
import { authModule } from './auth/auth.module.js';
// exet:imports:end
export const modules: ExetModule[] = [
healthModule,
helloModule,
// exet:modules:start
authModule,
// exet:modules:end
];The example assumes you created the hello module from the getting started guide and installed auth. Keep the marker comments intact so future CLI installs can update the registry.