A flexible and extensible API framework for Node.js, designed to work with multiple database types and configurations. It features a modular architecture, dynamic database connection management, and a flexible routing system. The framework supports TypeSc
npm install @medyll/idae-api@medyll/idae-api is a modular Node.js API framework designed to work with multiple database types thanks to the @medyll/idae-db library. It offers:
$in, $gt, $set, etc.), making it intuitive for developers familiar with MongoDB.
bash
npm install @medyll/idae-api
npm install @medyll/idae-api --latest # to install the latest version
npm install @medyll/idae-api --next # for the next version (if available)
`
---
Main Features
- Multi-database management (MongoDB, MySQL, etc.)
- Flexible routing and custom route addition
- Optional authentication middleware
- Centralized error handling
- Hooks/events on all CRUD operations
- Complete TypeScript client for API consumption
- Inherits all advanced methods from @medyll/idae-db
- Comprehensive middleware system for authentication, authorization, validation, multi-tenancy, docs, and health endpoints
- Strict multi-tenancy: Tenant context required for all requests (see below)
- Robust error handling: All errors are handled by a centralized middleware
$3
- OpenAPI auto-generation & docs: /openapi.json (spec), /docs (Swagger UI), /redoc (Redoc)
- RBAC/ABAC: Per-route authorization via JWT roles/scopes (see authorization in route definitions)
- Strict multi-tenancy: Tenant context required for all requests (from JWT, e.g. tenantId claim)
- Security/validation: CORS, helmet, rate limiting, payload limits, Zod validation, DB guardrails, health endpoints
---
Middleware, Multi-Tenancy, and Error Handling
This project uses a comprehensive middleware system for authentication, authorization, validation, multi-tenancy, documentation, and health endpoints. See src/lib/server/middleware/README.md for a full list and integration order.
Multi-tenancy is enforced via tenantContextMiddleware, which extracts the tenant context from the JWT or user object and injects it into the request. All protected routes require a valid tenant context. See the developer docs and middleware README for details and options.
Error handling is centralized: any error thrown in a route or middleware is caught and returned as a JSON error response with the appropriate status code.
Testing: Extensive tests cover edge cases, error handling, and multi-tenancy scenarios. See src/lib/server/__tests__/middleware/ for examples.
CI/CD: The test suite must pass for all changes. Run npm run test locally and ensure your CI pipeline is green before merging.
---
Server Usage
$3
`typescript
import { idaeApi } from '@medyll/idae-api';
idaeApi.setOptions({
port: 3000,
enableAuth: true, // or false
jwtSecret: 'your-secret-key',
tokenExpiration: '1h',
routes: customRoutes // optional
});
idaeApi.start();
`
#### Example of custom routes
`typescript
const customRoutes = [
{
method: 'get',
path: '/custom/hello',
handler: async () => ({ message: 'Hello from custom route!' }),
requiresAuth: false
}
];
idaeApi.router.addRoutes(customRoutes);
`
$3
idae-api relies on @medyll/idae-db for connection and database operation management. You can:
- Add new database adapters (see the DatabaseAdapter interface in idae-db)
- Use all hooks/events from idae-db (see below)
$3
An error handling middleware is included. You can customize it via the configureErrorHandling method in the IdaeApi class.
---
Client Usage
$3
`typescript
import { IdaeApiClientConfig } from '@medyll/idae-api';
IdaeApiClientConfig.setOptions({
host: 'localhost',
port: 3000,
method: 'http',
defaultDb: 'idae_base',
separator: '//'
});
`
$3
`typescript
import { IdaeApiClient } from '@medyll/idae-api';
const client = new IdaeApiClient();
`
$3
#### Database and Collection Management
- getDbList() : List available databases
- getCollections(dbName) : List collections in a database
- db(dbName) : Select a database (returns an object with collection and getCollections)
- collection(collectionName, dbName?) : Select a collection (optionally in a given database)
$3
You can register hooks on all operations:
`typescript
const usersCollection = client.collection('user');
usersCollection.registerEvents({
findById: {
pre: (id) => console.log(Before searching for ID: ${id}),
post: (result, id) => console.log(Result for ${id}:, result),
error: (error) => console.error('Error on findById:', error)
},
// ... same for update, create, etc.
});
#### CRUD Operations on a Collection
All the following methods are available via the IdaeApiClientCollection object:
- findAll(params?) : List all documents (with filters, sorting, pagination)
- findById(id) : Get a document by its ID
- findOne(params) : Get a document by a filter (inherited from idae-db)
- create(body) : Create a document
- update(id, body) : Update a document
- deleteById(id) : Delete a document by its ID
- deleteManyByQuery(params) : Delete multiple documents by filter
#
`
$3
$3
All query and update operations use a syntax very close to MongoDB. For example, you can use operators like $in, $gt, $set, etc. in your queries and updates.
---
#### List databases
`typescript
const dbList = await client.getDbList();
console.log('Databases:', dbList);
`
#### List collections in a database
`typescript
const collections = await client.getCollections('idae_base');
console.log('Collections:', collections);
`
#### Find documents with advanced query (MongoDB-like)
`typescript
const userCollection = client.db('app').collection('user');
const users = await userCollection.find({
email: { $in: ["Karin@example.com", "Test@Value"] },
age: 31,
});
console.log(users);
`
#### Create a new document
`typescript
const newUser = await userCollection.create({
name: "new user",
email: "Test@Value",
});
console.log(newUser);
`
#### Find all documents in a collection
`typescript
const allDocs = await userCollection.findAll();
console.log(allDocs);
`
#### Find a specific document by ID
`typescript
const foundDoc = await userCollection.findById(newUser._id);
console.log(foundDoc);
`
#### Update a document (MongoDB-like update syntax)
`typescript
const updatedDoc = await userCollection.update(newUser._id, {
$set: { value: "Updated Value" },
});
console.log(updatedDoc);
`
#### Delete a document
`typescript
const deleteResult = await userCollection.deleteById(newUser._id);
console.log(deleteResult);
`
#### Use a specific database and collection
`typescript
const appSchemeCollection = client.db('idae_base').collection('appscheme');
const docs = await appSchemeCollection.findAll();
console.log(docs);
`
#### Delete many documents by query (be careful with this!)
`typescript
const deleteResult2 = await client
.collection('appscheme_base')
.deleteManyByQuery({ testField: 'testValue' });
console.log(deleteResult2);
`
#### Register hooks/events on collection methods
`typescript
const usersCollection = client.collection('user');
usersCollection.registerEvents({
findById: {
pre: (id) => console.log(Before searching for ID: ${id}),
post: (result, id) => console.log(Result for ${id}:, result),
error: (error) => console.error('Error on findById:', error)
},
// ... same for update, create, etc.
});
`
---
Full List of Methods (inherited from idae-db)
$3
- find(params) : Advanced search (filters, sorting, pagination)
- findOne(params) : Find a single document by filter
- findById(id) : Find by ID
- create(data) : Create
- update(id, data) : Update
- deleteById(id) : Delete by ID
- deleteManyByQuery(params) : Bulk delete
- registerEvents(events) : Register hooks (pre/post/error) on each method
$3
- closeAllConnections() : Close all active connections
$3
- RequestParams : Record
- HttpMethod : 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
- RouteNamespace : methods/${'dbs' | 'collections'}
- UrlParams : { dbName?: string; collectionName?: string; slug?: string; params?: Record
- RequestOptions : UrlParams & { baseUrl?: string; method?: HttpMethod; body?: T; headers?: RequestInit['headers'] }
---
Contributing
Contributions are welcome! Feel free to submit a Pull Request.
---
---
Erreurs courantes & troubleshooting
Voici quelques problèmes fréquemment rencontrés et leurs solutions rapides :
- req.idaeDb ou req.connectedCollection undefined : la route ne correspond pas au pattern attendu ou le middleware n’est pas appliqué. Vérifie le chemin et l’ordre des middlewares.
- Token invalide sur route protégée : header Authorization absent/mal formé, ou token expiré. Vérifie la config côté client et serveur.
- Timeout ou erreur de connexion MongoDB : URI incorrect ou service MongoDB non démarré. Vérifie la chaîne de connexion et l’état du service.
- Résultat de requête vide : mauvais nom de collection/db, ou filtre trop restrictif. Loggue les paramètres pour debug.
- 404 ou handler non appelé : route non enregistrée ou méthode HTTP incorrecte. Vérifie la déclaration dans routeDefinitions.ts.
- Mismatch de types client/serveur : le serveur doit retourner des objets sérialisables, le client doit utiliser les bons types génériques.
- Middleware d’auth non appliqué partout : chaque route protégée doit avoir requiresAuth: true et l’auth doit être activée dans la config.
Pour plus de détails et de cas avancés, consulte :
- .github/copilot-instructions.md
- src/lib/server/middleware/README.md
---
Schéma d’architecture (à compléter)
`mermaid
flowchart TD
Client <--> API[IdaeApi (Express)]
API --> MW[Middleware]
MW --> DB[IdaeDbAdapter (MongoDB/MySQL)]
API --> Auth[Auth/JWT]
API --> Docs[OpenAPI/Swagger]
MW --> MultiTenancy[TenantContext]
``