modular_api
Use-case–centric toolkit for building Modular APIs with Shelf.
Define UseCase classes (input → validate → execute → output), connect them to HTTP routes,
add CORS / API Key middlewares, and expose Swagger / OpenAPI documentation.
Designed for the MACSS ecosystem — modular, explicit and testable server code.
🚀 Quick start
This quick start mirrors the included example implementation (example/example.dart).
import 'package:modular_api/modular_api.dart';
Future<void> main(List<String> args) async {
final api = ModularApi(basePath: '/api');
// POST api/module1/hello-world
api.module('module1', (m) {
m.usecase('hello-world', HelloWorld.fromJson);
});
final port = 8080;
await api.serve(port: port,);
print('Docs on http://localhost:$port/docs');
}
Example request (example server registers /api/module1/hello-world as a POST):
curl -H "Content-Type: application/json" -d '{"word":"world"}' \
-H "x-api-key: SECRET" \
"http://localhost:8080/api/module1/hello-world"
Example response (HelloOutput):
{"output":"Hello, world!"}
📖 Documentation
Start here: doc/INDEX.md — Complete documentation index and vertical development guide
Quick Links
Core guides for vertical feature development:
- doc/INDEX.md — Entry point: vertical development flow from DB to UI
- AGENTS.md — Framework overview and implementation guide (optimized for AI assistants)
- doc/usecase_dto_guide.md — Creating Input/Output DTOs
- doc/usecase_implementation.md — Implementing UseCases with business logic
- doc/testing_guide.md — Testing UseCases with
useCaseTestHandler - doc/http_client_guide.md — Using httpClient in Flutter and Dart apps
- doc/authentication_guide.md — Token management and storage adapters
- doc/auth_implementation_guide.md — Complete JWT authentication system
✨ Features
-
✅
UseCase<I extends Input, O extends Output>base classes and DTOs (Input/Output). -
🧩
useCaseHttpHandler()adapter: accepts a factoryUseCase Function(Map<String, dynamic>)and returns a ShelfHandler. -
🔐 Authentication & HTTP Client:
httpClient()— intelligent HTTP client with automatic authentication, token management, and auto-refresh on 401Token— in-memory session management (access tokens, expiration checking)TokenVault— configurable persistent storage for refresh tokens (with adapters for memory, file, and custom storage)JwtHelper— JWT generation and validation utilitiesPasswordHasher— bcrypt password hashing and verificationTokenHasher— SHA-256 token hashing for secure storageAuthReLoginException— specialized exception for authentication flow control
-
🧱 Included middlewares:
cors()— simple CORS support.apiKey()— header-based authentication; the key is read from theAPI_KEYenvironment variable (viaEnv).
-
📄 OpenAPI / Swagger helpers:
OpenApi.init(title)andOpenApi.docs— generate an OpenAPI spec from registered usecases (uses DTOtoSchema()), and provide a Swagger UIHandler.
-
📡 Automatic health endpoint:
- The server registers a simple health check endpoint at
GET /healthwhich responds with 200 OK and bodyok. This is implemented inmodular_api.dartas:_root.get('/health', (Request request) => Response.ok('ok'));
- The server registers a simple health check endpoint at
-
⚙️ Utilities:
Env.getString,Env.getInt,Env.setString(.env support via dotenv). -
Envbehavior: if a.envfile is not present the library will read values fromPlatform.environment; if a requested key is missing from both sources anEnvKeyNotFoundExceptionis thrown. -
🧪 Example project and tests included in
example/andtest/. -
🗄️ ODBC database client: a minimal ODBC
DbClientimplementation (DSN-based) tested with Oracle and SQL Server — seeNOTICEfor provenance and details.Usage:
import 'package:modular_api/modular_api.dart'; Future<void> runQuery() async { // Create a DSN-based client (example factories available in example/lib/db/db.dart) final db = createSqlServerClient(); try { final rows = await db.execute('SELECT @@VERSION as version'); print(rows); } finally { // ensure disconnect await db.disconnect(); } }See
template/lib/db/db_client.dartfor convenience factories andNOTICEfor provenance details.
📦 Installation
In pubspec.yaml:
dependencies:
modular_api: ^0.0.7
Or from the command line:
dart pub add modular_api
dart pub get
🔐 Authentication with httpClient
The intelligent httpClient simplifies authentication by automatically managing tokens for single-user applications:
import 'package:modular_api/modular_api.dart';
Future<void> authenticatedFlow() async {
const baseUrl = 'http://localhost:8080';
// Login - httpClient automatically captures and stores tokens
final loginResponse = await httpClient(
method: 'POST',
baseUrl: baseUrl,
endpoint: 'api/auth/login',
body: {'username': 'user', 'password': 'pass'},
auth: true, // Auto-captures tokens from response
) as Map<String, dynamic>;
print('Access token: ${loginResponse['access_token']}');
// Protected request - httpClient automatically:
// 1. Attaches Bearer token
// 2. Retries with refresh token on 401
// 3. Throws AuthReLoginException if refresh fails
try {
final profile = await httpClient(
method: 'POST',
baseUrl: baseUrl,
endpoint: 'api/users/profile',
body: {'user_id': 123},
auth: true, // Auto-attaches Bearer token
);
print('Profile: $profile');
} on AuthReLoginException {
// Session expired, redirect to login
print('Please log in again');
}
}
See doc/http_client_guide.md for complete examples and configuration.
🧭 Architecture
- UseCase layer — pure logic, independent of HTTP.
- HTTP adapter — turns a
UseCaseinto aHandler. - Middlewares — cross-cutting concerns (CORS, auth, logging).
- Swagger UI — documentation served automatically from registered use cases.
🧩 Middlewares
final api = ModularApi(basePath: '/api');
.use(cors())
.use(apiKey());
📄 Swagger/OpenAPI
To auto-generate the spec from registered routes and serve a UI:
Open http://localhost:<port>/docs to view the UI.
🧱 Modular examples
There are two example flavours included in this repository:
example/— a minimal, simplified runnable example. Checkexample/example.dartandtemplate/lib/modules/module1/hello_world.dartfor a concreteUseCase+ DTO example.template/— a fuller modular architecture template showing how to structure modules, repositories and tests for larger projects. See thetemplate/folder for a complete starter layout (modulesmodule1,module2,module3, and convenience DB clients).
🧪 Tests
The repository includes example tests (test/usecase_test.dart) that demonstrate the
recommended pattern and the useCaseTestHandler helper for unit-testing UseCase logic.
Run tests with:
dart test
🛠️ Compile to executable
-
Windows
dart compile exe example/example.dart -o build/api_example.exe -
Linux / macOS
dart compile exe example/example.dart -o build/api_example
📄 License
MIT © ccisne.dev
Libraries
- modular_api
- Public library for modular_api package. This library provides a use case centric API toolkit for Dart applications, including Shelf UseCase base class, HTTP adapters, CORS/API-Key middlewares, and OpenAPI specifications.