@medyll/idae-api 0.181.0 → 0.187.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +376 -376
- package/cli.js +46 -0
- package/dist/__tests__/README.md +583 -583
- package/dist/adapters/.delete_marker +1 -0
- package/dist/idae-api.d.ts +18 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/openApi/redoc.html +12 -12
- package/dist/openApi/swagger-ui.html +23 -23
- package/dist/server/middleware/README.md +46 -46
- package/package.json +53 -39
- package/dist/__tests__/helpers/testUtils.d.ts +0 -153
package/README.md
CHANGED
|
@@ -1,376 +1,376 @@
|
|
|
1
|
-
# @medyll/idae-api
|
|
2
|
-
|
|
3
|
-
A flexible and extensible Node.js API, based on the [@medyll/idae-db](https://www.npmjs.com/package/@medyll/idae-db) library, allowing you to manage multiple types of databases (MongoDB, MySQL, etc.) and providing a complete TypeScript client to interact with your endpoints.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Table of Contents
|
|
8
|
-
|
|
9
|
-
- [Overview](#overview)
|
|
10
|
-
- [Installation](#installation)
|
|
11
|
-
- [Main Features](#main-features)
|
|
12
|
-
- [Server Usage](#server-usage)
|
|
13
|
-
- [Configuration](#configuration)
|
|
14
|
-
- [Adding Custom Routes](#adding-custom-routes)
|
|
15
|
-
- [Database Management](#database-management)
|
|
16
|
-
- [Error Handling](#error-handling)
|
|
17
|
-
- [Client Usage](#client-usage)
|
|
18
|
-
- [Client Configuration](#client-configuration)
|
|
19
|
-
- [Available Methods](#available-methods)
|
|
20
|
-
- [Usage Examples](#usage-examples)
|
|
21
|
-
- [Full List of Methods (inherited from idae-db)](#full-list-of-methods-inherited-from-idae-db)
|
|
22
|
-
- [Contributing](#contributing)
|
|
23
|
-
- [License](#license)
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Overview
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
`@medyll/idae-api` is a modular Node.js API framework designed to work with multiple database types thanks to the [@medyll/idae-db](https://www.npmjs.com/package/@medyll/idae-db) library. It offers:
|
|
31
|
-
|
|
32
|
-
- Modular architecture (routes, middlewares, dynamic connection management)
|
|
33
|
-
- TypeScript/JavaScript client for easy API consumption
|
|
34
|
-
- Extension system to support other databases
|
|
35
|
-
- Native support for MongoDB and MySQL (via idae-db)
|
|
36
|
-
- Hooks/events on CRUD operations
|
|
37
|
-
- **MongoDB-like API syntax:** All query and update operations use a syntax very close to MongoDB (operators like `$in`, `$gt`, `$set`, etc.), making it intuitive for developers familiar with MongoDB.
|
|
38
|
-
|
|
39
|
-
## Installation
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npm install @medyll/idae-api
|
|
43
|
-
|
|
44
|
-
npm install @medyll/idae-api --latest # to install the latest version
|
|
45
|
-
npm install @medyll/idae-api --next # for the next version (if available)
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
## Main Features
|
|
54
|
-
|
|
55
|
-
- Multi-database management (MongoDB, MySQL, etc.)
|
|
56
|
-
- Flexible routing and custom route addition
|
|
57
|
-
- Optional authentication middleware
|
|
58
|
-
- Centralized error handling
|
|
59
|
-
- Hooks/events on all CRUD operations
|
|
60
|
-
- Complete TypeScript client for API consumption
|
|
61
|
-
- Inherits all advanced methods from [@medyll/idae-db](https://www.npmjs.com/package/@medyll/idae-db)
|
|
62
|
-
- **Comprehensive middleware system** for authentication, authorization, validation, multi-tenancy, docs, and health endpoints
|
|
63
|
-
- **Strict multi-tenancy**: Tenant context required for all requests (see below)
|
|
64
|
-
- **Robust error handling**: All errors are handled by a centralized middleware
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
### Advanced (2026):
|
|
68
|
-
- **OpenAPI auto-generation & docs**: `/openapi.json` (spec), `/docs` (Swagger UI), `/redoc` (Redoc)
|
|
69
|
-
- **RBAC/ABAC**: Per-route authorization via JWT roles/scopes (see `authorization` in route definitions)
|
|
70
|
-
- **Strict multi-tenancy**: Tenant context required for all requests (from JWT, e.g. `tenantId` claim)
|
|
71
|
-
- **Security/validation**: CORS, helmet, rate limiting, payload limits, Zod validation, DB guardrails, health endpoints
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## Middleware, Multi-Tenancy, and Error Handling
|
|
76
|
-
|
|
77
|
-
This project uses a comprehensive middleware system for authentication, authorization, validation, multi-tenancy, documentation, and health endpoints. See [`src/lib/server/middleware/README.md`](src/lib/server/middleware/README.md) for a full list and integration order.
|
|
78
|
-
|
|
79
|
-
**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.
|
|
80
|
-
|
|
81
|
-
**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.
|
|
82
|
-
|
|
83
|
-
**Testing**: Extensive tests cover edge cases, error handling, and multi-tenancy scenarios. See `src/lib/server/__tests__/middleware/` for examples.
|
|
84
|
-
|
|
85
|
-
**CI/CD**: The test suite must pass for all changes. Run `npm run test` locally and ensure your CI pipeline is green before merging.
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Server Usage
|
|
90
|
-
|
|
91
|
-
### Configuration
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
import { idaeApi } from '@medyll/idae-api';
|
|
95
|
-
|
|
96
|
-
idaeApi.setOptions({
|
|
97
|
-
port: 3000,
|
|
98
|
-
enableAuth: true, // or false
|
|
99
|
-
jwtSecret: 'your-secret-key',
|
|
100
|
-
tokenExpiration: '1h',
|
|
101
|
-
routes: customRoutes // optional
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
idaeApi.start();
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
#### Example of custom routes
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
const customRoutes = [
|
|
111
|
-
{
|
|
112
|
-
method: 'get',
|
|
113
|
-
path: '/custom/hello',
|
|
114
|
-
handler: async () => ({ message: 'Hello from custom route!' }),
|
|
115
|
-
requiresAuth: false
|
|
116
|
-
}
|
|
117
|
-
];
|
|
118
|
-
|
|
119
|
-
idaeApi.router.addRoutes(customRoutes);
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Database Management
|
|
123
|
-
|
|
124
|
-
`idae-api` relies on `@medyll/idae-db` for connection and database operation management. You can:
|
|
125
|
-
|
|
126
|
-
- Add new database adapters (see the `DatabaseAdapter` interface in idae-db)
|
|
127
|
-
- Use all hooks/events from idae-db (see below)
|
|
128
|
-
|
|
129
|
-
### Error Handling
|
|
130
|
-
|
|
131
|
-
An error handling middleware is included. You can customize it via the `configureErrorHandling` method in the `IdaeApi` class.
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## Client Usage
|
|
136
|
-
|
|
137
|
-
### Client Configuration
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
import { IdaeApiClientConfig } from '@medyll/idae-api';
|
|
141
|
-
|
|
142
|
-
IdaeApiClientConfig.setOptions({
|
|
143
|
-
host: 'localhost',
|
|
144
|
-
port: 3000,
|
|
145
|
-
method: 'http',
|
|
146
|
-
defaultDb: 'idae_base',
|
|
147
|
-
separator: '//'
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Creating a client instance
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
import { IdaeApiClient } from '@medyll/idae-api';
|
|
155
|
-
|
|
156
|
-
const client = new IdaeApiClient();
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### Available Methods
|
|
160
|
-
|
|
161
|
-
#### Database and Collection Management
|
|
162
|
-
|
|
163
|
-
- `getDbList()` : List available databases
|
|
164
|
-
- `getCollections(dbName)` : List collections in a database
|
|
165
|
-
- `db(dbName)` : Select a database (returns an object with `collection` and `getCollections`)
|
|
166
|
-
- `collection(collectionName, dbName?)` : Select a collection (optionally in a given database)
|
|
167
|
-
|
|
168
|
-
### Event/Hook Management (inherited from idae-db)
|
|
169
|
-
|
|
170
|
-
You can register hooks on all operations:
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
const usersCollection = client.collection('user');
|
|
174
|
-
|
|
175
|
-
usersCollection.registerEvents({
|
|
176
|
-
findById: {
|
|
177
|
-
pre: (id) => console.log(`Before searching for ID: ${id}`),
|
|
178
|
-
post: (result, id) => console.log(`Result for ${id}:`, result),
|
|
179
|
-
error: (error) => console.error('Error on findById:', error)
|
|
180
|
-
},
|
|
181
|
-
// ... same for update, create, etc.
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
#### CRUD Operations on a Collection
|
|
185
|
-
|
|
186
|
-
All the following methods are available via the `IdaeApiClientCollection` object:
|
|
187
|
-
|
|
188
|
-
- `findAll(params?)` : List all documents (with filters, sorting, pagination)
|
|
189
|
-
- `findById(id)` : Get a document by its ID
|
|
190
|
-
- `findOne(params)` : Get a document by a filter (inherited from idae-db)
|
|
191
|
-
- `create(body)` : Create a document
|
|
192
|
-
- `update(id, body)` : Update a document
|
|
193
|
-
- `deleteById(id)` : Delete a document by its ID
|
|
194
|
-
- `deleteManyByQuery(params)` : Delete multiple documents by filter
|
|
195
|
-
|
|
196
|
-
#
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Usage Examples
|
|
200
|
-
|
|
201
|
-
### MongoDB-like Query Syntax
|
|
202
|
-
|
|
203
|
-
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.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
#### List databases
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
const dbList = await client.getDbList();
|
|
211
|
-
console.log('Databases:', dbList);
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
#### List collections in a database
|
|
215
|
-
|
|
216
|
-
```typescript
|
|
217
|
-
const collections = await client.getCollections('idae_base');
|
|
218
|
-
console.log('Collections:', collections);
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
#### Find documents with advanced query (MongoDB-like)
|
|
222
|
-
|
|
223
|
-
```typescript
|
|
224
|
-
const userCollection = client.db('app').collection('user');
|
|
225
|
-
const users = await userCollection.find({
|
|
226
|
-
email: { $in: ["Karin@example.com", "Test@Value"] },
|
|
227
|
-
age: 31,
|
|
228
|
-
});
|
|
229
|
-
console.log(users);
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
#### Create a new document
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
const newUser = await userCollection.create({
|
|
236
|
-
name: "new user",
|
|
237
|
-
email: "Test@Value",
|
|
238
|
-
});
|
|
239
|
-
console.log(newUser);
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
#### Find all documents in a collection
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
const allDocs = await userCollection.findAll();
|
|
246
|
-
console.log(allDocs);
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
#### Find a specific document by ID
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
const foundDoc = await userCollection.findById(newUser._id);
|
|
253
|
-
console.log(foundDoc);
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
#### Update a document (MongoDB-like update syntax)
|
|
257
|
-
|
|
258
|
-
```typescript
|
|
259
|
-
const updatedDoc = await userCollection.update(newUser._id, {
|
|
260
|
-
$set: { value: "Updated Value" },
|
|
261
|
-
});
|
|
262
|
-
console.log(updatedDoc);
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
#### Delete a document
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
const deleteResult = await userCollection.deleteById(newUser._id);
|
|
269
|
-
console.log(deleteResult);
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
#### Use a specific database and collection
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
const appSchemeCollection = client.db('idae_base').collection('appscheme');
|
|
276
|
-
const docs = await appSchemeCollection.findAll();
|
|
277
|
-
console.log(docs);
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
#### Delete many documents by query (be careful with this!)
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
const deleteResult2 = await client
|
|
284
|
-
.collection('appscheme_base')
|
|
285
|
-
.deleteManyByQuery({ testField: 'testValue' });
|
|
286
|
-
console.log(deleteResult2);
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
#### Register hooks/events on collection methods
|
|
290
|
-
|
|
291
|
-
```typescript
|
|
292
|
-
const usersCollection = client.collection('user');
|
|
293
|
-
|
|
294
|
-
usersCollection.registerEvents({
|
|
295
|
-
findById: {
|
|
296
|
-
pre: (id) => console.log(`Before searching for ID: ${id}`),
|
|
297
|
-
post: (result, id) => console.log(`Result for ${id}:`, result),
|
|
298
|
-
error: (error) => console.error('Error on findById:', error)
|
|
299
|
-
},
|
|
300
|
-
// ... same for update, create, etc.
|
|
301
|
-
});
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
---
|
|
305
|
-
|
|
306
|
-
## Full List of Methods (inherited from idae-db)
|
|
307
|
-
|
|
308
|
-
### Collection Methods
|
|
309
|
-
|
|
310
|
-
- `find(params)` : Advanced search (filters, sorting, pagination)
|
|
311
|
-
- `findOne(params)` : Find a single document by filter
|
|
312
|
-
- `findById(id)` : Find by ID
|
|
313
|
-
- `create(data)` : Create
|
|
314
|
-
- `update(id, data)` : Update
|
|
315
|
-
- `deleteById(id)` : Delete by ID
|
|
316
|
-
- `deleteManyByQuery(params)` : Bulk delete
|
|
317
|
-
- `registerEvents(events)` : Register hooks (pre/post/error) on each method
|
|
318
|
-
|
|
319
|
-
### Connection Management
|
|
320
|
-
|
|
321
|
-
- `closeAllConnections()` : Close all active connections
|
|
322
|
-
|
|
323
|
-
### Useful Types
|
|
324
|
-
|
|
325
|
-
- `RequestParams` : `Record<string, unknown>`
|
|
326
|
-
- `HttpMethod` : `'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'`
|
|
327
|
-
- `RouteNamespace` : ``methods/${'dbs' | 'collections'}``
|
|
328
|
-
- `UrlParams` : `{ dbName?: string; collectionName?: string; slug?: string; params?: Record<string, string>; routeNamespace?: RouteNamespace }`
|
|
329
|
-
- `RequestOptions<T>` : `UrlParams & { baseUrl?: string; method?: HttpMethod; body?: T; headers?: RequestInit['headers'] }`
|
|
330
|
-
|
|
331
|
-
---
|
|
332
|
-
|
|
333
|
-
## Contributing
|
|
334
|
-
|
|
335
|
-
Contributions are welcome! Feel free to submit a Pull Request.
|
|
336
|
-
|
|
337
|
-
---
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
---
|
|
341
|
-
|
|
342
|
-
## Erreurs courantes & troubleshooting
|
|
343
|
-
|
|
344
|
-
Voici quelques problèmes fréquemment rencontrés et leurs solutions rapides :
|
|
345
|
-
|
|
346
|
-
- **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.
|
|
347
|
-
- **Token invalide sur route protégée** : header Authorization absent/mal formé, ou token expiré. Vérifie la config côté client et serveur.
|
|
348
|
-
- **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.
|
|
349
|
-
- **Résultat de requête vide** : mauvais nom de collection/db, ou filtre trop restrictif. Loggue les paramètres pour debug.
|
|
350
|
-
- **404 ou handler non appelé** : route non enregistrée ou méthode HTTP incorrecte. Vérifie la déclaration dans routeDefinitions.ts.
|
|
351
|
-
- **Mismatch de types client/serveur** : le serveur doit retourner des objets sérialisables, le client doit utiliser les bons types génériques.
|
|
352
|
-
- **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.
|
|
353
|
-
|
|
354
|
-
Pour plus de détails et de cas avancés, consulte :
|
|
355
|
-
- [.github/copilot-instructions.md](.github/copilot-instructions.md)
|
|
356
|
-
- [src/lib/server/middleware/README.md](src/lib/server/middleware/README.md)
|
|
357
|
-
|
|
358
|
-
---
|
|
359
|
-
|
|
360
|
-
## Schéma d’architecture (à compléter)
|
|
361
|
-
|
|
362
|
-
```mermaid
|
|
363
|
-
flowchart TD
|
|
364
|
-
Client <--> API[IdaeApi (Express)]
|
|
365
|
-
API --> MW[Middleware]
|
|
366
|
-
MW --> DB[IdaeDbAdapter (MongoDB/MySQL)]
|
|
367
|
-
API --> Auth[Auth/JWT]
|
|
368
|
-
API --> Docs[OpenAPI/Swagger]
|
|
369
|
-
MW --> MultiTenancy[TenantContext]
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
---
|
|
373
|
-
|
|
374
|
-
## License
|
|
375
|
-
|
|
376
|
-
This project is licensed under the MIT License.
|
|
1
|
+
# @medyll/idae-api
|
|
2
|
+
|
|
3
|
+
A flexible and extensible Node.js API, based on the [@medyll/idae-db](https://www.npmjs.com/package/@medyll/idae-db) library, allowing you to manage multiple types of databases (MongoDB, MySQL, etc.) and providing a complete TypeScript client to interact with your endpoints.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Overview](#overview)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Main Features](#main-features)
|
|
12
|
+
- [Server Usage](#server-usage)
|
|
13
|
+
- [Configuration](#configuration)
|
|
14
|
+
- [Adding Custom Routes](#adding-custom-routes)
|
|
15
|
+
- [Database Management](#database-management)
|
|
16
|
+
- [Error Handling](#error-handling)
|
|
17
|
+
- [Client Usage](#client-usage)
|
|
18
|
+
- [Client Configuration](#client-configuration)
|
|
19
|
+
- [Available Methods](#available-methods)
|
|
20
|
+
- [Usage Examples](#usage-examples)
|
|
21
|
+
- [Full List of Methods (inherited from idae-db)](#full-list-of-methods-inherited-from-idae-db)
|
|
22
|
+
- [Contributing](#contributing)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
`@medyll/idae-api` is a modular Node.js API framework designed to work with multiple database types thanks to the [@medyll/idae-db](https://www.npmjs.com/package/@medyll/idae-db) library. It offers:
|
|
31
|
+
|
|
32
|
+
- Modular architecture (routes, middlewares, dynamic connection management)
|
|
33
|
+
- TypeScript/JavaScript client for easy API consumption
|
|
34
|
+
- Extension system to support other databases
|
|
35
|
+
- Native support for MongoDB and MySQL (via idae-db)
|
|
36
|
+
- Hooks/events on CRUD operations
|
|
37
|
+
- **MongoDB-like API syntax:** All query and update operations use a syntax very close to MongoDB (operators like `$in`, `$gt`, `$set`, etc.), making it intuitive for developers familiar with MongoDB.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @medyll/idae-api
|
|
43
|
+
|
|
44
|
+
npm install @medyll/idae-api --latest # to install the latest version
|
|
45
|
+
npm install @medyll/idae-api --next # for the next version (if available)
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
## Main Features
|
|
54
|
+
|
|
55
|
+
- Multi-database management (MongoDB, MySQL, etc.)
|
|
56
|
+
- Flexible routing and custom route addition
|
|
57
|
+
- Optional authentication middleware
|
|
58
|
+
- Centralized error handling
|
|
59
|
+
- Hooks/events on all CRUD operations
|
|
60
|
+
- Complete TypeScript client for API consumption
|
|
61
|
+
- Inherits all advanced methods from [@medyll/idae-db](https://www.npmjs.com/package/@medyll/idae-db)
|
|
62
|
+
- **Comprehensive middleware system** for authentication, authorization, validation, multi-tenancy, docs, and health endpoints
|
|
63
|
+
- **Strict multi-tenancy**: Tenant context required for all requests (see below)
|
|
64
|
+
- **Robust error handling**: All errors are handled by a centralized middleware
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Advanced (2026):
|
|
68
|
+
- **OpenAPI auto-generation & docs**: `/openapi.json` (spec), `/docs` (Swagger UI), `/redoc` (Redoc)
|
|
69
|
+
- **RBAC/ABAC**: Per-route authorization via JWT roles/scopes (see `authorization` in route definitions)
|
|
70
|
+
- **Strict multi-tenancy**: Tenant context required for all requests (from JWT, e.g. `tenantId` claim)
|
|
71
|
+
- **Security/validation**: CORS, helmet, rate limiting, payload limits, Zod validation, DB guardrails, health endpoints
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Middleware, Multi-Tenancy, and Error Handling
|
|
76
|
+
|
|
77
|
+
This project uses a comprehensive middleware system for authentication, authorization, validation, multi-tenancy, documentation, and health endpoints. See [`src/lib/server/middleware/README.md`](src/lib/server/middleware/README.md) for a full list and integration order.
|
|
78
|
+
|
|
79
|
+
**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.
|
|
80
|
+
|
|
81
|
+
**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.
|
|
82
|
+
|
|
83
|
+
**Testing**: Extensive tests cover edge cases, error handling, and multi-tenancy scenarios. See `src/lib/server/__tests__/middleware/` for examples.
|
|
84
|
+
|
|
85
|
+
**CI/CD**: The test suite must pass for all changes. Run `npm run test` locally and ensure your CI pipeline is green before merging.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Server Usage
|
|
90
|
+
|
|
91
|
+
### Configuration
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { idaeApi } from '@medyll/idae-api';
|
|
95
|
+
|
|
96
|
+
idaeApi.setOptions({
|
|
97
|
+
port: 3000,
|
|
98
|
+
enableAuth: true, // or false
|
|
99
|
+
jwtSecret: 'your-secret-key',
|
|
100
|
+
tokenExpiration: '1h',
|
|
101
|
+
routes: customRoutes // optional
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
idaeApi.start();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Example of custom routes
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const customRoutes = [
|
|
111
|
+
{
|
|
112
|
+
method: 'get',
|
|
113
|
+
path: '/custom/hello',
|
|
114
|
+
handler: async () => ({ message: 'Hello from custom route!' }),
|
|
115
|
+
requiresAuth: false
|
|
116
|
+
}
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
idaeApi.router.addRoutes(customRoutes);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Database Management
|
|
123
|
+
|
|
124
|
+
`idae-api` relies on `@medyll/idae-db` for connection and database operation management. You can:
|
|
125
|
+
|
|
126
|
+
- Add new database adapters (see the `DatabaseAdapter` interface in idae-db)
|
|
127
|
+
- Use all hooks/events from idae-db (see below)
|
|
128
|
+
|
|
129
|
+
### Error Handling
|
|
130
|
+
|
|
131
|
+
An error handling middleware is included. You can customize it via the `configureErrorHandling` method in the `IdaeApi` class.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Client Usage
|
|
136
|
+
|
|
137
|
+
### Client Configuration
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { IdaeApiClientConfig } from '@medyll/idae-api';
|
|
141
|
+
|
|
142
|
+
IdaeApiClientConfig.setOptions({
|
|
143
|
+
host: 'localhost',
|
|
144
|
+
port: 3000,
|
|
145
|
+
method: 'http',
|
|
146
|
+
defaultDb: 'idae_base',
|
|
147
|
+
separator: '//'
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Creating a client instance
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { IdaeApiClient } from '@medyll/idae-api';
|
|
155
|
+
|
|
156
|
+
const client = new IdaeApiClient();
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Available Methods
|
|
160
|
+
|
|
161
|
+
#### Database and Collection Management
|
|
162
|
+
|
|
163
|
+
- `getDbList()` : List available databases
|
|
164
|
+
- `getCollections(dbName)` : List collections in a database
|
|
165
|
+
- `db(dbName)` : Select a database (returns an object with `collection` and `getCollections`)
|
|
166
|
+
- `collection(collectionName, dbName?)` : Select a collection (optionally in a given database)
|
|
167
|
+
|
|
168
|
+
### Event/Hook Management (inherited from idae-db)
|
|
169
|
+
|
|
170
|
+
You can register hooks on all operations:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const usersCollection = client.collection('user');
|
|
174
|
+
|
|
175
|
+
usersCollection.registerEvents({
|
|
176
|
+
findById: {
|
|
177
|
+
pre: (id) => console.log(`Before searching for ID: ${id}`),
|
|
178
|
+
post: (result, id) => console.log(`Result for ${id}:`, result),
|
|
179
|
+
error: (error) => console.error('Error on findById:', error)
|
|
180
|
+
},
|
|
181
|
+
// ... same for update, create, etc.
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
#### CRUD Operations on a Collection
|
|
185
|
+
|
|
186
|
+
All the following methods are available via the `IdaeApiClientCollection` object:
|
|
187
|
+
|
|
188
|
+
- `findAll(params?)` : List all documents (with filters, sorting, pagination)
|
|
189
|
+
- `findById(id)` : Get a document by its ID
|
|
190
|
+
- `findOne(params)` : Get a document by a filter (inherited from idae-db)
|
|
191
|
+
- `create(body)` : Create a document
|
|
192
|
+
- `update(id, body)` : Update a document
|
|
193
|
+
- `deleteById(id)` : Delete a document by its ID
|
|
194
|
+
- `deleteManyByQuery(params)` : Delete multiple documents by filter
|
|
195
|
+
|
|
196
|
+
#
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Usage Examples
|
|
200
|
+
|
|
201
|
+
### MongoDB-like Query Syntax
|
|
202
|
+
|
|
203
|
+
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.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
#### List databases
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const dbList = await client.getDbList();
|
|
211
|
+
console.log('Databases:', dbList);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### List collections in a database
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
const collections = await client.getCollections('idae_base');
|
|
218
|
+
console.log('Collections:', collections);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Find documents with advanced query (MongoDB-like)
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
const userCollection = client.db('app').collection('user');
|
|
225
|
+
const users = await userCollection.find({
|
|
226
|
+
email: { $in: ["Karin@example.com", "Test@Value"] },
|
|
227
|
+
age: 31,
|
|
228
|
+
});
|
|
229
|
+
console.log(users);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Create a new document
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const newUser = await userCollection.create({
|
|
236
|
+
name: "new user",
|
|
237
|
+
email: "Test@Value",
|
|
238
|
+
});
|
|
239
|
+
console.log(newUser);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Find all documents in a collection
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const allDocs = await userCollection.findAll();
|
|
246
|
+
console.log(allDocs);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Find a specific document by ID
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
const foundDoc = await userCollection.findById(newUser._id);
|
|
253
|
+
console.log(foundDoc);
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
#### Update a document (MongoDB-like update syntax)
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
const updatedDoc = await userCollection.update(newUser._id, {
|
|
260
|
+
$set: { value: "Updated Value" },
|
|
261
|
+
});
|
|
262
|
+
console.log(updatedDoc);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Delete a document
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const deleteResult = await userCollection.deleteById(newUser._id);
|
|
269
|
+
console.log(deleteResult);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### Use a specific database and collection
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
const appSchemeCollection = client.db('idae_base').collection('appscheme');
|
|
276
|
+
const docs = await appSchemeCollection.findAll();
|
|
277
|
+
console.log(docs);
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Delete many documents by query (be careful with this!)
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
const deleteResult2 = await client
|
|
284
|
+
.collection('appscheme_base')
|
|
285
|
+
.deleteManyByQuery({ testField: 'testValue' });
|
|
286
|
+
console.log(deleteResult2);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### Register hooks/events on collection methods
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
const usersCollection = client.collection('user');
|
|
293
|
+
|
|
294
|
+
usersCollection.registerEvents({
|
|
295
|
+
findById: {
|
|
296
|
+
pre: (id) => console.log(`Before searching for ID: ${id}`),
|
|
297
|
+
post: (result, id) => console.log(`Result for ${id}:`, result),
|
|
298
|
+
error: (error) => console.error('Error on findById:', error)
|
|
299
|
+
},
|
|
300
|
+
// ... same for update, create, etc.
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Full List of Methods (inherited from idae-db)
|
|
307
|
+
|
|
308
|
+
### Collection Methods
|
|
309
|
+
|
|
310
|
+
- `find(params)` : Advanced search (filters, sorting, pagination)
|
|
311
|
+
- `findOne(params)` : Find a single document by filter
|
|
312
|
+
- `findById(id)` : Find by ID
|
|
313
|
+
- `create(data)` : Create
|
|
314
|
+
- `update(id, data)` : Update
|
|
315
|
+
- `deleteById(id)` : Delete by ID
|
|
316
|
+
- `deleteManyByQuery(params)` : Bulk delete
|
|
317
|
+
- `registerEvents(events)` : Register hooks (pre/post/error) on each method
|
|
318
|
+
|
|
319
|
+
### Connection Management
|
|
320
|
+
|
|
321
|
+
- `closeAllConnections()` : Close all active connections
|
|
322
|
+
|
|
323
|
+
### Useful Types
|
|
324
|
+
|
|
325
|
+
- `RequestParams` : `Record<string, unknown>`
|
|
326
|
+
- `HttpMethod` : `'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'`
|
|
327
|
+
- `RouteNamespace` : ``methods/${'dbs' | 'collections'}``
|
|
328
|
+
- `UrlParams` : `{ dbName?: string; collectionName?: string; slug?: string; params?: Record<string, string>; routeNamespace?: RouteNamespace }`
|
|
329
|
+
- `RequestOptions<T>` : `UrlParams & { baseUrl?: string; method?: HttpMethod; body?: T; headers?: RequestInit['headers'] }`
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Contributing
|
|
334
|
+
|
|
335
|
+
Contributions are welcome! Feel free to submit a Pull Request.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Erreurs courantes & troubleshooting
|
|
343
|
+
|
|
344
|
+
Voici quelques problèmes fréquemment rencontrés et leurs solutions rapides :
|
|
345
|
+
|
|
346
|
+
- **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.
|
|
347
|
+
- **Token invalide sur route protégée** : header Authorization absent/mal formé, ou token expiré. Vérifie la config côté client et serveur.
|
|
348
|
+
- **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.
|
|
349
|
+
- **Résultat de requête vide** : mauvais nom de collection/db, ou filtre trop restrictif. Loggue les paramètres pour debug.
|
|
350
|
+
- **404 ou handler non appelé** : route non enregistrée ou méthode HTTP incorrecte. Vérifie la déclaration dans routeDefinitions.ts.
|
|
351
|
+
- **Mismatch de types client/serveur** : le serveur doit retourner des objets sérialisables, le client doit utiliser les bons types génériques.
|
|
352
|
+
- **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.
|
|
353
|
+
|
|
354
|
+
Pour plus de détails et de cas avancés, consulte :
|
|
355
|
+
- [.github/copilot-instructions.md](.github/copilot-instructions.md)
|
|
356
|
+
- [src/lib/server/middleware/README.md](src/lib/server/middleware/README.md)
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Schéma d’architecture (à compléter)
|
|
361
|
+
|
|
362
|
+
```mermaid
|
|
363
|
+
flowchart TD
|
|
364
|
+
Client <--> API[IdaeApi (Express)]
|
|
365
|
+
API --> MW[Middleware]
|
|
366
|
+
MW --> DB[IdaeDbAdapter (MongoDB/MySQL)]
|
|
367
|
+
API --> Auth[Auth/JWT]
|
|
368
|
+
API --> Docs[OpenAPI/Swagger]
|
|
369
|
+
MW --> MultiTenancy[TenantContext]
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## License
|
|
375
|
+
|
|
376
|
+
This project is licensed under the MIT License.
|