@mini2/core 1.0.9 → 1.1.1
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/Readme.MD
CHANGED
|
@@ -1,33 +1,26 @@
|
|
|
1
1
|
# @mini2/core
|
|
2
2
|
|
|
3
|
-
**Mini
|
|
3
|
+
**Mini REST Framework** - A lightweight and modular web framework built on top of Express.js. Features TypeScript support, automatic Swagger documentation, dependency injection, and decorator-based routing system for modern API development experience.
|
|
4
4
|
|
|
5
|
-
## ✨
|
|
5
|
+
## ✨ Features
|
|
6
6
|
|
|
7
|
-
- 🚀 **Decorator
|
|
8
|
-
- 📝 **
|
|
9
|
-
- 🔧 **Dependency Injection**:
|
|
10
|
-
- 🛡️ **
|
|
11
|
-
- 📦 **
|
|
12
|
-
- 🎯 **Response Builder**:
|
|
13
|
-
- ⚡ **
|
|
7
|
+
- 🚀 **Decorator-Based Routing**: Easy route definition with decorators like `@get`, `@post`
|
|
8
|
+
- 📝 **Automatic Swagger Documentation**: API documentation generated automatically
|
|
9
|
+
- 🔧 **Dependency Injection**: Powerful DI container based on InversifyJS
|
|
10
|
+
- 🛡️ **Security Middlewares**: Authentication, authorization, and validation
|
|
11
|
+
- 📦 **Full TypeScript Support**: Type-safe API development
|
|
12
|
+
- 🎯 **Response Builder**: Consistent API responses
|
|
13
|
+
- ⚡ **Quick Setup**: Minimal configuration required
|
|
14
14
|
|
|
15
|
-
## 📦
|
|
15
|
+
## 📦 Installation
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm install @mini2/core
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
## 🚀 Quick Start
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
# Eğer MongoDB kullanıyorsanız
|
|
25
|
-
npm install mongoose
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## 🚀 Hızlı Başlangıç
|
|
29
|
-
|
|
30
|
-
### 1. Temel Konfigürasyon
|
|
23
|
+
### 1. Basic Configuration
|
|
31
24
|
|
|
32
25
|
```typescript
|
|
33
26
|
import { App, IConfig } from '@mini2/core';
|
|
@@ -38,9 +31,9 @@ const config: IConfig = {
|
|
|
38
31
|
applicationName: 'My API',
|
|
39
32
|
};
|
|
40
33
|
|
|
41
|
-
//
|
|
34
|
+
// Define your controllers
|
|
42
35
|
const controllers = [
|
|
43
|
-
//
|
|
36
|
+
// Your controller classes
|
|
44
37
|
];
|
|
45
38
|
|
|
46
39
|
const app = new App(controllers);
|
|
@@ -48,89 +41,494 @@ await app.init(config);
|
|
|
48
41
|
await app.afterInit();
|
|
49
42
|
```
|
|
50
43
|
|
|
51
|
-
### 2. Controller
|
|
44
|
+
### 2. Creating a Controller
|
|
52
45
|
|
|
53
46
|
```typescript
|
|
54
47
|
import {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
controller,
|
|
49
|
+
get,
|
|
50
|
+
post,
|
|
51
|
+
put,
|
|
52
|
+
del,
|
|
53
|
+
req,
|
|
54
|
+
res,
|
|
58
55
|
ResponseBuilder,
|
|
59
|
-
|
|
56
|
+
authenticated,
|
|
57
|
+
authorized,
|
|
58
|
+
validate,
|
|
60
59
|
} from '@mini2/core';
|
|
61
60
|
|
|
62
|
-
@
|
|
61
|
+
@controller('/api/users')
|
|
63
62
|
export class UserController {
|
|
64
|
-
@
|
|
65
|
-
async getUsers() {
|
|
66
|
-
const
|
|
63
|
+
@get('/')
|
|
64
|
+
async getUsers(@req() request: Request) {
|
|
65
|
+
const page = Number(request.query.page) || 1;
|
|
66
|
+
const users = await this.userService.findAll(page);
|
|
67
67
|
return new ResponseBuilder().ok(users);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
@
|
|
71
|
-
@
|
|
72
|
-
async createUser(@
|
|
70
|
+
@post('/')
|
|
71
|
+
@validate({ body: CreateUserDto })
|
|
72
|
+
async createUser(@req() req: Request) {
|
|
73
|
+
const userData = req.body;
|
|
73
74
|
const user = await this.userService.create(userData);
|
|
74
75
|
return new ResponseBuilder().created(user);
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
@
|
|
78
|
-
@
|
|
79
|
-
@
|
|
80
|
-
async getUser(@
|
|
78
|
+
@get('/:id')
|
|
79
|
+
@authenticated()
|
|
80
|
+
@authorized(['user:read'])
|
|
81
|
+
async getUser(@req() req: Request) {
|
|
82
|
+
const id = req.params.id;
|
|
81
83
|
const user = await this.userService.findById(id);
|
|
84
|
+
if (!user) throw new NotFoundException({ message: 'User not found' });
|
|
85
|
+
return new ResponseBuilder().ok(user);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@put('/:id')
|
|
89
|
+
@authenticated()
|
|
90
|
+
@authorized(['user:write'])
|
|
91
|
+
@validate({ body: UpdateUserDto, params: UserParamsDto })
|
|
92
|
+
async updateUser(@req() req: Request) {
|
|
93
|
+
const id = req.params.id;
|
|
94
|
+
const updateData = req.body;
|
|
95
|
+
const user = await this.userService.update(id, updateData);
|
|
82
96
|
return new ResponseBuilder().ok(user);
|
|
83
97
|
}
|
|
98
|
+
|
|
99
|
+
@del('/:id')
|
|
100
|
+
@authenticated()
|
|
101
|
+
@authorized(['admin', 'user:delete'])
|
|
102
|
+
async deleteUser(@req() req: Request) {
|
|
103
|
+
const id = req.params.id;
|
|
104
|
+
await this.userService.delete(id);
|
|
105
|
+
return new ResponseBuilder().ok({ message: 'User deleted successfully' });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 🎭 Decorators Deep Dive
|
|
111
|
+
|
|
112
|
+
Decorators are the core feature of @mini2/core, providing a clean and intuitive way to define routes, middleware, and validation rules.
|
|
113
|
+
|
|
114
|
+
### 🏷️ Class Decorators
|
|
115
|
+
|
|
116
|
+
#### **@controller(path?: string)**
|
|
117
|
+
|
|
118
|
+
Defines a controller class and optionally sets a base path for all routes in the controller.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
@controller('/api/v1/users')
|
|
122
|
+
export class UserController {
|
|
123
|
+
// All routes will be prefixed with '/api/v1/users'
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@controller('') // No base path
|
|
127
|
+
export class HomeController {
|
|
128
|
+
@get('/') // Route: '/'
|
|
129
|
+
home() {
|
|
130
|
+
/* ... */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Features:**
|
|
136
|
+
|
|
137
|
+
- Sets base path for all routes in the controller
|
|
138
|
+
- Enables automatic route registration
|
|
139
|
+
- Integrates with Swagger documentation generation
|
|
140
|
+
|
|
141
|
+
### 🚦 HTTP Method Decorators
|
|
142
|
+
|
|
143
|
+
#### **@get(path: string)**
|
|
144
|
+
|
|
145
|
+
Defines a GET route handler.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
@get('/profile')
|
|
149
|
+
async getProfile(@req() req: Request) {
|
|
150
|
+
// Handles GET /api/users/profile
|
|
151
|
+
return new ResponseBuilder().ok(req.user);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@get('/:id/posts')
|
|
155
|
+
async getUserPosts(@req() req: Request) {
|
|
156
|
+
const userId = req.params.id;
|
|
157
|
+
// Handles GET /api/users/:id/posts
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@get('/search')
|
|
161
|
+
async searchUsers(@req() req: Request) {
|
|
162
|
+
const query = req.query.q;
|
|
163
|
+
// Handles GET /api/users/search?q=searchterm
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### **@post(path: string)**
|
|
168
|
+
|
|
169
|
+
Defines a POST route handler.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
@post('/')
|
|
173
|
+
@validate({ body: CreateUserDto })
|
|
174
|
+
async createUser(@req() req: Request) {
|
|
175
|
+
// Handles POST /api/users
|
|
176
|
+
const userData = req.body;
|
|
177
|
+
return new ResponseBuilder().created(userData);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@post('/:id/avatar')
|
|
181
|
+
@authenticated()
|
|
182
|
+
async uploadAvatar(@req() req: Request) {
|
|
183
|
+
const id = req.params.id;
|
|
184
|
+
// Handles POST /api/users/:id/avatar
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### **@put(path: string)**
|
|
189
|
+
|
|
190
|
+
Defines a PUT route handler for full resource updates.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
@put('/:id')
|
|
194
|
+
@authenticated()
|
|
195
|
+
@validate({ body: UpdateUserDto })
|
|
196
|
+
async updateUser(@req() req: Request) {
|
|
197
|
+
const id = req.params.id;
|
|
198
|
+
const data = req.body;
|
|
199
|
+
// Handles PUT /api/users/:id
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### **@patch(path: string)**
|
|
204
|
+
|
|
205
|
+
Defines a PATCH route handler for partial resource updates.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
@patch('/:id')
|
|
209
|
+
@authenticated()
|
|
210
|
+
@validate({ body: PartialUserDto })
|
|
211
|
+
async patchUser(@req() req: Request) {
|
|
212
|
+
const id = req.params.id;
|
|
213
|
+
const data = req.body;
|
|
214
|
+
// Handles PATCH /api/users/:id
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### **@del(path: string)**
|
|
219
|
+
|
|
220
|
+
Defines a DELETE route handler. Note: uses `@del` instead of `@delete` (reserved keyword).
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
@del('/:id')
|
|
224
|
+
@authenticated()
|
|
225
|
+
@authorized(['admin'])
|
|
226
|
+
async deleteUser(@req() req: Request) {
|
|
227
|
+
const id = req.params.id;
|
|
228
|
+
// Handles DELETE /api/users/:id
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 📝 Parameter Decorators
|
|
233
|
+
|
|
234
|
+
Parameter decorators inject Express request/response objects into method parameters.
|
|
235
|
+
|
|
236
|
+
#### **@req()**
|
|
237
|
+
|
|
238
|
+
Injects the Express request object.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
@get('/:id')
|
|
242
|
+
async getUser(@req() request: Request) {
|
|
243
|
+
const id = request.params.id;
|
|
244
|
+
const userAgent = request.headers['user-agent'];
|
|
245
|
+
const query = request.query;
|
|
246
|
+
// Full access to Express Request object
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### **@res()**
|
|
251
|
+
|
|
252
|
+
Injects the Express response object. **Note: If you use @res(), you must handle the response manually.**
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
@get('/download/:file')
|
|
256
|
+
async downloadFile(@req() req: Request, @res() res: Response) {
|
|
257
|
+
const filename = req.params.file;
|
|
258
|
+
|
|
259
|
+
// Manual response handling required
|
|
260
|
+
res.setHeader('Content-Disposition', `attachment; filename=${filename}`);
|
|
261
|
+
res.sendFile(path.join(__dirname, 'files', filename));
|
|
262
|
+
|
|
263
|
+
// Don't return ResponseBuilder when using @res()
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 🛡️ Security Decorators
|
|
268
|
+
|
|
269
|
+
#### **@authenticated()**
|
|
270
|
+
|
|
271
|
+
Ensures the user is authenticated before accessing the route.
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
@get('/profile')
|
|
275
|
+
@authenticated()
|
|
276
|
+
async getProfile(@req() req: Request) {
|
|
277
|
+
// req.authenticated is guaranteed to be true
|
|
278
|
+
// User must be logged in to access this route
|
|
279
|
+
return new ResponseBuilder().ok(req.user);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Requirements:**
|
|
284
|
+
|
|
285
|
+
- Request must have `authenticated: true` property
|
|
286
|
+
- Usually set by authentication middleware
|
|
287
|
+
- Throws `UnauthorizedException` if not authenticated
|
|
288
|
+
|
|
289
|
+
#### **@authorized(permissions: string | string[])**
|
|
290
|
+
|
|
291
|
+
Checks if the authenticated user has required permissions.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
@del('/:id')
|
|
295
|
+
@authenticated()
|
|
296
|
+
@authorized(['admin'])
|
|
297
|
+
async deleteUser(@req() req: Request) {
|
|
298
|
+
// Only users with 'admin' permission can access
|
|
299
|
+
const id = req.params.id;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@get('/reports')
|
|
303
|
+
@authenticated()
|
|
304
|
+
@authorized(['reports:read', 'admin'])
|
|
305
|
+
async getReports(@req() req: Request) {
|
|
306
|
+
// Users need either 'reports:read' OR 'admin' permission
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Requirements:**
|
|
311
|
+
|
|
312
|
+
- User must be authenticated first
|
|
313
|
+
- Request must have `user.permissions: string[]` property
|
|
314
|
+
- Uses OR logic: user needs ANY of the specified permissions
|
|
315
|
+
- Throws `ForbiddenException` if insufficient permissions
|
|
316
|
+
|
|
317
|
+
### ✅ Validation Decorators
|
|
318
|
+
|
|
319
|
+
#### **@validate(options: ValidationOptions)**
|
|
320
|
+
|
|
321
|
+
Validates request data using class-validator.
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
@post('/')
|
|
325
|
+
@validate({
|
|
326
|
+
body: CreateUserDto,
|
|
327
|
+
params: UserParamsDto,
|
|
328
|
+
query: SearchQueryDto
|
|
329
|
+
})
|
|
330
|
+
async createUser(@req() req: Request) {
|
|
331
|
+
// req.body, req.params, req.query are validated and transformed
|
|
332
|
+
const userData = req.body as CreateUserDto; // Typed as CreateUserDto
|
|
333
|
+
const params = req.params as UserParamsDto; // Typed as UserParamsDto
|
|
334
|
+
const query = req.query as SearchQueryDto; // Typed as SearchQueryDto
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Options:**
|
|
339
|
+
|
|
340
|
+
- `body`: DTO class for request body validation
|
|
341
|
+
- `params`: DTO class for URL parameters validation
|
|
342
|
+
- `query`: DTO class for query parameters validation
|
|
343
|
+
|
|
344
|
+
**Example DTO Classes:**
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
import {
|
|
348
|
+
IsEmail,
|
|
349
|
+
IsString,
|
|
350
|
+
MinLength,
|
|
351
|
+
IsOptional,
|
|
352
|
+
IsNumber,
|
|
353
|
+
} from 'class-validator';
|
|
354
|
+
|
|
355
|
+
export class CreateUserDto {
|
|
356
|
+
@IsEmail()
|
|
357
|
+
email: string;
|
|
358
|
+
|
|
359
|
+
@IsString()
|
|
360
|
+
@MinLength(3)
|
|
361
|
+
name: string;
|
|
362
|
+
|
|
363
|
+
@IsOptional()
|
|
364
|
+
@IsNumber()
|
|
365
|
+
age?: number;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export class UserParamsDto {
|
|
369
|
+
@IsString()
|
|
370
|
+
id: string;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export class SearchQueryDto {
|
|
374
|
+
@IsOptional()
|
|
375
|
+
@IsString()
|
|
376
|
+
q?: string;
|
|
377
|
+
|
|
378
|
+
@IsOptional()
|
|
379
|
+
@IsNumber()
|
|
380
|
+
page?: number = 1;
|
|
84
381
|
}
|
|
85
382
|
```
|
|
86
383
|
|
|
87
|
-
|
|
384
|
+
### 🔧 Custom Middleware Decorators
|
|
88
385
|
|
|
89
|
-
|
|
386
|
+
#### **@middleware(middleware: RequestHandler)**
|
|
387
|
+
|
|
388
|
+
Adds custom Express middleware to a specific route.
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import rateLimit from 'express-rate-limit';
|
|
392
|
+
import multer from 'multer';
|
|
393
|
+
|
|
394
|
+
const uploadMiddleware = multer({ dest: 'uploads/' });
|
|
395
|
+
const limiter = rateLimit({
|
|
396
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
397
|
+
max: 100
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
@post('/upload')
|
|
401
|
+
@middleware(uploadMiddleware.single('file'))
|
|
402
|
+
@middleware(limiter)
|
|
403
|
+
async uploadFile(@req() req: Request) {
|
|
404
|
+
// Custom middleware applied before route handler
|
|
405
|
+
const file = req.file;
|
|
406
|
+
return new ResponseBuilder().created({ filename: file?.filename });
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### 🔄 Decorator Combination and Order
|
|
411
|
+
|
|
412
|
+
Decorators can be combined and are executed in a specific order:
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
@post('/:id/activate')
|
|
416
|
+
@middleware(loggingMiddleware) // 1. Custom middleware first
|
|
417
|
+
@authenticated() // 2. Authentication check
|
|
418
|
+
@authorized(['admin']) // 3. Authorization check
|
|
419
|
+
@validate({
|
|
420
|
+
params: UserParamsDto, // 4. Validation (params, query, body)
|
|
421
|
+
body: ActivationDto
|
|
422
|
+
})
|
|
423
|
+
async activateUser(@req() req: Request) {
|
|
424
|
+
// 5. Route handler executes last
|
|
425
|
+
const id = req.params.id;
|
|
426
|
+
const data = req.body;
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Execution Order:**
|
|
431
|
+
|
|
432
|
+
1. Custom middlewares (from `@middleware`)
|
|
433
|
+
2. Authentication middleware (from `@authenticated`)
|
|
434
|
+
3. Authorization middleware (from `@authorized`)
|
|
435
|
+
4. Validation middleware (from `@validate`)
|
|
436
|
+
5. Route handler method
|
|
437
|
+
|
|
438
|
+
### 🎯 Advanced Decorator Patterns
|
|
439
|
+
|
|
440
|
+
#### **Multiple HTTP Methods on Same Path**
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
@controller('/api/users/:id')
|
|
444
|
+
export class UserDetailController {
|
|
445
|
+
@get('/')
|
|
446
|
+
async getUser(@req() req: Request) {
|
|
447
|
+
// GET /api/users/:id
|
|
448
|
+
const id = req.params.id;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
@put('/')
|
|
452
|
+
@validate({ body: UpdateUserDto })
|
|
453
|
+
async updateUser(@req() req: Request) {
|
|
454
|
+
// PUT /api/users/:id
|
|
455
|
+
const id = req.params.id;
|
|
456
|
+
const data = req.body;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
@del('/')
|
|
460
|
+
@authorized(['admin'])
|
|
461
|
+
async deleteUser(@req() req: Request) {
|
|
462
|
+
// DELETE /api/users/:id
|
|
463
|
+
const id = req.params.id;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
#### **Conditional Decorators**
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
export class UserController {
|
|
472
|
+
@get('/public')
|
|
473
|
+
async getPublicUsers(@req() req: Request) {
|
|
474
|
+
// No authentication required
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
@get('/private')
|
|
478
|
+
@authenticated()
|
|
479
|
+
async getPrivateUsers(@req() req: Request) {
|
|
480
|
+
// Authentication required
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## 📚 API Reference
|
|
486
|
+
|
|
487
|
+
### 🏗️ Core Classes
|
|
90
488
|
|
|
91
489
|
#### **App**
|
|
92
490
|
|
|
93
|
-
|
|
491
|
+
Main application class that manages the Express server.
|
|
94
492
|
|
|
95
493
|
```typescript
|
|
96
494
|
import { App, IConfig } from '@mini2/core';
|
|
97
495
|
|
|
98
496
|
const app = new App(controllers);
|
|
99
|
-
await app.init(config); //
|
|
100
|
-
await app.afterInit(); //
|
|
497
|
+
await app.init(config); // Start the server
|
|
498
|
+
await app.afterInit(); // Post-initialization tasks
|
|
101
499
|
```
|
|
102
500
|
|
|
103
|
-
|
|
501
|
+
**Properties:**
|
|
104
502
|
|
|
105
|
-
- Express server
|
|
106
|
-
- Middleware
|
|
107
|
-
- Swagger
|
|
108
|
-
- Controller routing
|
|
503
|
+
- Express server management
|
|
504
|
+
- Middleware configuration
|
|
505
|
+
- Swagger documentation integration
|
|
506
|
+
- Controller routing system
|
|
109
507
|
|
|
110
508
|
#### **Container & container**
|
|
111
509
|
|
|
112
|
-
|
|
510
|
+
InversifyJS containers for dependency injection.
|
|
113
511
|
|
|
114
512
|
```typescript
|
|
115
513
|
import { Container, container } from '@mini2/core';
|
|
116
514
|
|
|
117
|
-
//
|
|
515
|
+
// Create new container
|
|
118
516
|
const myContainer = new Container();
|
|
119
517
|
myContainer.bind('UserService').to(UserService);
|
|
120
518
|
|
|
121
|
-
//
|
|
519
|
+
// Use pre-configured container
|
|
122
520
|
container.bind('UserService').to(UserService);
|
|
123
521
|
```
|
|
124
522
|
|
|
125
|
-
### 📋
|
|
523
|
+
### 📋 Interfaces
|
|
126
524
|
|
|
127
525
|
#### **IConfig**
|
|
128
526
|
|
|
129
527
|
```typescript
|
|
130
528
|
interface IConfig {
|
|
131
|
-
host: string; // Server host
|
|
132
|
-
port: number; // Server
|
|
133
|
-
applicationName: string; //
|
|
529
|
+
host: string; // Server host address
|
|
530
|
+
port: number; // Server port
|
|
531
|
+
applicationName: string; // Application name
|
|
134
532
|
}
|
|
135
533
|
```
|
|
136
534
|
|
|
@@ -145,7 +543,7 @@ interface IApp {
|
|
|
145
543
|
|
|
146
544
|
#### **IRepository<IdentifierType, ModelType>**
|
|
147
545
|
|
|
148
|
-
Generic repository pattern interface
|
|
546
|
+
Generic repository pattern interface.
|
|
149
547
|
|
|
150
548
|
```typescript
|
|
151
549
|
interface IRepository<IdentifierType, ModelType> {
|
|
@@ -184,82 +582,82 @@ interface IResponseBuilder<T = any> {
|
|
|
184
582
|
}
|
|
185
583
|
```
|
|
186
584
|
|
|
187
|
-
### 🛡️
|
|
585
|
+
### 🛡️ Middlewares
|
|
188
586
|
|
|
189
587
|
#### **validationMiddleware**
|
|
190
588
|
|
|
191
|
-
Class-validator
|
|
589
|
+
Class-validator based data validation.
|
|
192
590
|
|
|
193
591
|
```typescript
|
|
194
592
|
import { validationMiddleware } from '@mini2/core';
|
|
195
593
|
|
|
196
|
-
//
|
|
197
|
-
@
|
|
198
|
-
@
|
|
199
|
-
async createUser(@
|
|
200
|
-
//
|
|
594
|
+
// Usage in controller
|
|
595
|
+
@post('/users')
|
|
596
|
+
@validate({ body: CreateUserDto })
|
|
597
|
+
async createUser(@req() req: Request) {
|
|
598
|
+
// Validated data available in req.body
|
|
201
599
|
}
|
|
202
600
|
```
|
|
203
601
|
|
|
204
|
-
**
|
|
602
|
+
**Supported Validation Types:**
|
|
205
603
|
|
|
206
|
-
- `body` - Request body
|
|
207
|
-
- `params` - URL
|
|
208
|
-
- `query` - Query
|
|
604
|
+
- `body` - Request body validation
|
|
605
|
+
- `params` - URL parameters validation
|
|
606
|
+
- `query` - Query parameters validation
|
|
209
607
|
|
|
210
608
|
#### **authenticatedMiddleware**
|
|
211
609
|
|
|
212
|
-
|
|
610
|
+
Authentication control middleware.
|
|
213
611
|
|
|
214
612
|
```typescript
|
|
215
613
|
import { authenticatedMiddleware, IAuthenticatedRequest } from '@mini2/core';
|
|
216
614
|
|
|
217
|
-
//
|
|
218
|
-
@
|
|
219
|
-
@
|
|
220
|
-
async getProfile(@
|
|
221
|
-
// req.authenticated === true
|
|
615
|
+
// Usage
|
|
616
|
+
@get('/profile')
|
|
617
|
+
@authenticated()
|
|
618
|
+
async getProfile(@req() req: IAuthenticatedRequest) {
|
|
619
|
+
// req.authenticated === true is guaranteed
|
|
222
620
|
}
|
|
223
621
|
```
|
|
224
622
|
|
|
225
623
|
#### **authorizedMiddleware**
|
|
226
624
|
|
|
227
|
-
|
|
625
|
+
Authorization control middleware.
|
|
228
626
|
|
|
229
627
|
```typescript
|
|
230
628
|
import { authorizedMiddleware } from '@mini2/core';
|
|
231
629
|
|
|
232
|
-
//
|
|
233
|
-
@
|
|
234
|
-
@
|
|
235
|
-
@
|
|
236
|
-
async deleteUser(@
|
|
237
|
-
// req.user.permissions
|
|
630
|
+
// Usage
|
|
631
|
+
@del('/admin/users/:id')
|
|
632
|
+
@authenticated()
|
|
633
|
+
@authorized(['admin', 'user:delete'])
|
|
634
|
+
async deleteUser(@req() req: Request) {
|
|
635
|
+
// req.user.permissions is checked
|
|
238
636
|
}
|
|
239
637
|
```
|
|
240
638
|
|
|
241
639
|
### 🎯 Response Builder
|
|
242
640
|
|
|
243
|
-
HTTP
|
|
641
|
+
Standardizes HTTP responses with a fluent API.
|
|
244
642
|
|
|
245
643
|
```typescript
|
|
246
644
|
import { ResponseBuilder } from '@mini2/core';
|
|
247
645
|
|
|
248
|
-
//
|
|
646
|
+
// Basic usage
|
|
249
647
|
return new ResponseBuilder().ok({ message: 'Success', data: users });
|
|
250
648
|
|
|
251
|
-
//
|
|
649
|
+
// Created response
|
|
252
650
|
return new ResponseBuilder()
|
|
253
651
|
.created({ id: newUser.id })
|
|
254
652
|
.setHeader('Location', `/users/${newUser.id}`);
|
|
255
653
|
|
|
256
|
-
//
|
|
654
|
+
// File response
|
|
257
655
|
return new ResponseBuilder()
|
|
258
656
|
.ok(fileBuffer)
|
|
259
657
|
.setHeader('Content-Type', 'application/pdf')
|
|
260
658
|
.asFile();
|
|
261
659
|
|
|
262
|
-
// Custom status
|
|
660
|
+
// Custom status and headers
|
|
263
661
|
return new ResponseBuilder()
|
|
264
662
|
.status(202)
|
|
265
663
|
.setHeaders({
|
|
@@ -269,41 +667,19 @@ return new ResponseBuilder()
|
|
|
269
667
|
.ok({ status: 'processing' });
|
|
270
668
|
```
|
|
271
669
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
#### **HTTP Method Decorator'ları**
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
@Get('/path') // GET request
|
|
278
|
-
@Post('/path') // POST request
|
|
279
|
-
@Put('/path') // PUT request
|
|
280
|
-
@Delete('/path') // DELETE request
|
|
281
|
-
@Patch('/path') // PATCH request
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
#### **Parameter Decorator'ları**
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
@Param('id') id: string // URL parametresi
|
|
288
|
-
@Body() data: CreateUserDto // Request body
|
|
289
|
-
@Query('page') page: number // Query parametresi
|
|
290
|
-
@Req() request: Request // Request objesi
|
|
291
|
-
@Res() response: Response // Response objesi
|
|
292
|
-
@Next() next: NextFunction // Next function
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
#### **Middleware Decorator'ları**
|
|
670
|
+
**Methods:**
|
|
296
671
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
672
|
+
- `ok(data)` - 200 OK response
|
|
673
|
+
- `created(data)` - 201 Created response
|
|
674
|
+
- `status(code)` - Set custom status code
|
|
675
|
+
- `setHeader(key, value)` - Set single header
|
|
676
|
+
- `setHeaders(headers)` - Set multiple headers
|
|
677
|
+
- `asFile()` - Mark response as file download
|
|
678
|
+
- `build(res)` - Build and send response
|
|
303
679
|
|
|
304
680
|
### ⚠️ Exception Handling
|
|
305
681
|
|
|
306
|
-
|
|
682
|
+
Pre-defined HTTP exceptions for common error scenarios.
|
|
307
683
|
|
|
308
684
|
```typescript
|
|
309
685
|
import {
|
|
@@ -312,10 +688,12 @@ import {
|
|
|
312
688
|
UnauthorizedException,
|
|
313
689
|
ForbiddenException,
|
|
314
690
|
NotFoundException,
|
|
315
|
-
|
|
691
|
+
ConflictException,
|
|
692
|
+
UnprocessableEntityException,
|
|
693
|
+
InternalServerErrorException,
|
|
316
694
|
} from '@mini2/core';
|
|
317
695
|
|
|
318
|
-
//
|
|
696
|
+
// Basic usage
|
|
319
697
|
throw new BadRequestException({
|
|
320
698
|
message: 'Invalid input data',
|
|
321
699
|
validationErrors: [{ field: 'email', errors: ['Invalid email format'] }],
|
|
@@ -329,9 +707,15 @@ throw new HttpException(
|
|
|
329
707
|
},
|
|
330
708
|
422
|
|
331
709
|
);
|
|
710
|
+
|
|
711
|
+
// Not found
|
|
712
|
+
throw new NotFoundException({
|
|
713
|
+
message: 'User not found',
|
|
714
|
+
errorId: 404001,
|
|
715
|
+
});
|
|
332
716
|
```
|
|
333
717
|
|
|
334
|
-
**
|
|
718
|
+
**Available Exceptions:**
|
|
335
719
|
|
|
336
720
|
- `BadRequestException` (400)
|
|
337
721
|
- `UnauthorizedException` (401)
|
|
@@ -339,22 +723,27 @@ throw new HttpException(
|
|
|
339
723
|
- `ForbiddenException` (403)
|
|
340
724
|
- `NotFoundException` (404)
|
|
341
725
|
- `MethodNotAllowedException` (405)
|
|
726
|
+
- `NotAcceptableException` (406)
|
|
342
727
|
- `ConflictException` (409)
|
|
343
728
|
- `UnprocessableEntityException` (422)
|
|
344
729
|
- `TooManyRequestsException` (429)
|
|
345
730
|
- `InternalServerErrorException` (500)
|
|
346
|
-
-
|
|
731
|
+
- `NotImplementedException` (501)
|
|
732
|
+
- `BadGatewayException` (502)
|
|
733
|
+
- `ServiceUnavailableException` (503)
|
|
734
|
+
- `GatewayTimeoutException` (504)
|
|
347
735
|
|
|
348
|
-
### 🛠️
|
|
736
|
+
### 🛠️ Utility Functions
|
|
349
737
|
|
|
350
738
|
#### **arrayUnify**
|
|
351
739
|
|
|
352
|
-
|
|
740
|
+
Merges array elements and removes duplicates.
|
|
353
741
|
|
|
354
742
|
```typescript
|
|
355
743
|
import { arrayUnify } from '@mini2/core';
|
|
356
744
|
|
|
357
745
|
const result = arrayUnify([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
746
|
+
const strings = arrayUnify(['a', 'b', 'a', 'c']); // ['a', 'b', 'c']
|
|
358
747
|
```
|
|
359
748
|
|
|
360
749
|
#### **Math Utilities**
|
|
@@ -365,17 +754,86 @@ import { sum } from '@mini2/core';
|
|
|
365
754
|
const result = sum(5, 3); // 8
|
|
366
755
|
```
|
|
367
756
|
|
|
368
|
-
### 📖 Swagger
|
|
757
|
+
### 📖 Swagger Integration
|
|
758
|
+
|
|
759
|
+
@mini2/core automatically generates comprehensive API documentation using Swagger/OpenAPI 3.0 specification based on your decorators and DTOs.
|
|
760
|
+
|
|
761
|
+
#### **📍 API Documentation Endpoints**
|
|
762
|
+
|
|
763
|
+
When your application starts, Swagger documentation is automatically available at:
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
// Interactive Swagger UI - Test your API directly in browser
|
|
767
|
+
http://localhost:3000/api-docs
|
|
768
|
+
|
|
769
|
+
// Raw OpenAPI JSON specification - For tools, imports, etc.
|
|
770
|
+
http://localhost:3000/api-docs.json
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
#### **🔧 Automatic Documentation Features**
|
|
774
|
+
|
|
775
|
+
- **Route Discovery**: All `@controller` and HTTP method decorators are automatically documented
|
|
776
|
+
- **Request/Response Schemas**: DTO classes with `class-validator` decorators generate JSON schemas
|
|
777
|
+
- **Security Requirements**: `@authenticated` and `@authorized` decorators add security info
|
|
778
|
+
- **Parameter Documentation**: Path parameters, query parameters, and request bodies are documented
|
|
779
|
+
- **HTTP Status Codes**: Response codes from `ResponseBuilder` and exceptions are included
|
|
780
|
+
|
|
781
|
+
#### **📋 Example Generated Documentation**
|
|
782
|
+
|
|
783
|
+
For this controller:
|
|
784
|
+
|
|
785
|
+
```typescript
|
|
786
|
+
@controller('/api/users')
|
|
787
|
+
export class UserController {
|
|
788
|
+
@get('/:id')
|
|
789
|
+
@authenticated()
|
|
790
|
+
@authorized(['user:read'])
|
|
791
|
+
@validate({ params: UserParamsDto })
|
|
792
|
+
async getUser(@req() req: Request) {
|
|
793
|
+
const id = req.params.id;
|
|
794
|
+
const user = await this.userService.findById(id);
|
|
795
|
+
return new ResponseBuilder().ok(user);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
@post('/')
|
|
799
|
+
@validate({ body: CreateUserDto })
|
|
800
|
+
async createUser(@req() req: Request) {
|
|
801
|
+
const userData = req.body;
|
|
802
|
+
const user = await this.userService.create(userData);
|
|
803
|
+
return new ResponseBuilder().created(user);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
Swagger will automatically generate:
|
|
369
809
|
|
|
370
|
-
|
|
810
|
+
- **GET /api/users/{id}** - Requires authentication and authorization
|
|
811
|
+
- **POST /api/users** - With CreateUserDto schema for request body
|
|
812
|
+
- Parameter definitions, security requirements, and response schemas
|
|
813
|
+
|
|
814
|
+
#### **🎯 DTO-Based Schema Generation**
|
|
815
|
+
|
|
816
|
+
Class-validator decorators automatically create OpenAPI schemas:
|
|
371
817
|
|
|
372
818
|
```typescript
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
819
|
+
export class CreateUserDto {
|
|
820
|
+
@IsEmail()
|
|
821
|
+
email: string;
|
|
822
|
+
|
|
823
|
+
@IsString()
|
|
824
|
+
@MinLength(2)
|
|
825
|
+
name: string;
|
|
826
|
+
|
|
827
|
+
@IsOptional()
|
|
828
|
+
@IsNumber()
|
|
829
|
+
@Min(0)
|
|
830
|
+
age?: number;
|
|
831
|
+
}
|
|
376
832
|
```
|
|
377
833
|
|
|
378
|
-
|
|
834
|
+
#### **⚙️ Swagger Configuration**
|
|
835
|
+
|
|
836
|
+
Default configuration is applied automatically, but you can customize it:
|
|
379
837
|
|
|
380
838
|
```typescript
|
|
381
839
|
const swaggerOptions = {
|
|
@@ -383,17 +841,69 @@ const swaggerOptions = {
|
|
|
383
841
|
description: `API documentation for ${config.applicationName}`,
|
|
384
842
|
version: '1.0.0',
|
|
385
843
|
servers: [{ url: `http://${config.host}:${config.port}` }],
|
|
386
|
-
docsPath: '/api-docs',
|
|
387
|
-
jsonPath: '/api-docs.json',
|
|
844
|
+
docsPath: '/api-docs', // Swagger UI endpoint
|
|
845
|
+
jsonPath: '/api-docs.json', // OpenAPI JSON endpoint
|
|
846
|
+
components: {
|
|
847
|
+
securitySchemes: {
|
|
848
|
+
bearerAuth: {
|
|
849
|
+
type: 'http',
|
|
850
|
+
scheme: 'bearer',
|
|
851
|
+
bearerFormat: 'JWT',
|
|
852
|
+
},
|
|
853
|
+
},
|
|
854
|
+
},
|
|
388
855
|
};
|
|
389
856
|
```
|
|
390
857
|
|
|
391
|
-
|
|
858
|
+
#### **🔐 Security Documentation**
|
|
859
|
+
|
|
860
|
+
Security decorators automatically add authentication requirements:
|
|
861
|
+
|
|
862
|
+
```typescript
|
|
863
|
+
@get('/profile')
|
|
864
|
+
@authenticated()
|
|
865
|
+
@authorized(['user:profile'])
|
|
866
|
+
async getProfile(@req() req: Request) {
|
|
867
|
+
// Swagger will show:
|
|
868
|
+
// - 🔒 Authentication required
|
|
869
|
+
// - 🛡️ Requires 'user:profile' permission
|
|
870
|
+
// - 401 Unauthorized response possible
|
|
871
|
+
// - 403 Forbidden response possible
|
|
872
|
+
}
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
#### **📊 Response Documentation**
|
|
876
|
+
|
|
877
|
+
ResponseBuilder methods automatically document response types:
|
|
878
|
+
|
|
879
|
+
```typescript
|
|
880
|
+
@post('/users')
|
|
881
|
+
async createUser(@req() req: Request) {
|
|
882
|
+
const user = await this.userService.create(req.body);
|
|
883
|
+
|
|
884
|
+
// Swagger documents:
|
|
885
|
+
// - 201 Created status
|
|
886
|
+
// - User object schema in response body
|
|
887
|
+
// - Location header if set
|
|
888
|
+
return new ResponseBuilder()
|
|
889
|
+
.created(user)
|
|
890
|
+
.setHeader('Location', `/users/${user.id}`);
|
|
891
|
+
}
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
#### **🚀 Production Usage**
|
|
895
|
+
|
|
896
|
+
- Swagger UI is automatically available in all environments
|
|
897
|
+
- For production, consider disabling Swagger UI and keeping only JSON endpoint
|
|
898
|
+
- OpenAPI JSON can be used with external documentation tools
|
|
899
|
+
- All validation errors are automatically documented with examples
|
|
392
900
|
|
|
393
|
-
|
|
901
|
+
### 📝 TypeScript Support
|
|
902
|
+
|
|
903
|
+
Full TypeScript support with type-safe API development:
|
|
394
904
|
|
|
395
905
|
```typescript
|
|
396
|
-
//
|
|
906
|
+
// Strong typing for DTOs
|
|
397
907
|
export class CreateUserDto {
|
|
398
908
|
@IsEmail()
|
|
399
909
|
email: string;
|
|
@@ -407,60 +917,122 @@ export class CreateUserDto {
|
|
|
407
917
|
age?: number;
|
|
408
918
|
}
|
|
409
919
|
|
|
410
|
-
//
|
|
411
|
-
@
|
|
412
|
-
@
|
|
413
|
-
async createUser(@
|
|
920
|
+
// Type-safe controller methods
|
|
921
|
+
@post('/users')
|
|
922
|
+
@validate({ body: CreateUserDto })
|
|
923
|
+
async createUser(@req() req: Request): Promise<ResponseBuilder<User>> {
|
|
924
|
+
const userData = req.body as CreateUserDto; // Type-safe after validation
|
|
414
925
|
const user = await this.userService.create(userData);
|
|
415
926
|
return new ResponseBuilder<User>().created(user);
|
|
416
927
|
}
|
|
417
928
|
```
|
|
418
929
|
|
|
419
|
-
## 🔧
|
|
930
|
+
## 🔧 Advanced Usage
|
|
420
931
|
|
|
421
|
-
### Custom Middleware
|
|
932
|
+
### Custom Middleware Creation
|
|
422
933
|
|
|
423
934
|
```typescript
|
|
935
|
+
import { RequestHandler } from 'express';
|
|
424
936
|
import { middleware } from '@mini2/core';
|
|
425
937
|
|
|
426
|
-
|
|
427
|
-
|
|
938
|
+
// Logging middleware
|
|
939
|
+
const loggingMiddleware: RequestHandler = (req, res, next) => {
|
|
940
|
+
console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`);
|
|
428
941
|
next();
|
|
429
942
|
};
|
|
430
943
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
944
|
+
// Rate limiting middleware
|
|
945
|
+
const createRateLimiter = (requests: number, windowMs: number): RequestHandler => {
|
|
946
|
+
const requests_map = new Map();
|
|
947
|
+
return (req, res, next) => {
|
|
948
|
+
const clientId = req.ip;
|
|
949
|
+
const now = Date.now();
|
|
950
|
+
const windowStart = now - windowMs;
|
|
951
|
+
|
|
952
|
+
const clientRequests = requests_map.get(clientId) || [];
|
|
953
|
+
const recentRequests = clientRequests.filter((time: number) => time > windowStart);
|
|
954
|
+
|
|
955
|
+
if (recentRequests.length >= requests) {
|
|
956
|
+
return res.status(429).json({ error: 'Too many requests' });
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
recentRequests.push(now);
|
|
960
|
+
requests_map.set(clientId, recentRequests);
|
|
961
|
+
next();
|
|
962
|
+
};
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
// Usage in controller
|
|
966
|
+
@get('/users')
|
|
967
|
+
@middleware(loggingMiddleware)
|
|
968
|
+
@middleware(createRateLimiter(10, 60000))
|
|
969
|
+
async getUsers(@req() req: Request) {
|
|
970
|
+
// Middleware chain: logging -> rate limiting -> route handler
|
|
435
971
|
}
|
|
436
972
|
```
|
|
437
973
|
|
|
438
|
-
### Dependency Injection
|
|
974
|
+
### Dependency Injection Patterns
|
|
439
975
|
|
|
440
976
|
```typescript
|
|
441
977
|
import { Container, injectable, inject } from '@mini2/core';
|
|
442
978
|
|
|
979
|
+
// Service interfaces
|
|
980
|
+
interface IUserService {
|
|
981
|
+
create(userData: CreateUserDto): Promise<User>;
|
|
982
|
+
findById(id: string): Promise<User | null>;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// Service implementations
|
|
443
986
|
@injectable()
|
|
444
|
-
|
|
987
|
+
class UserService implements IUserService {
|
|
445
988
|
constructor(@inject('UserRepository') private userRepo: IUserRepository) {}
|
|
989
|
+
|
|
990
|
+
async create(userData: CreateUserDto): Promise<User> {
|
|
991
|
+
return this.userRepo.create(userData);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
async findById(id: string): Promise<User | null> {
|
|
995
|
+
return this.userRepo.findById(id);
|
|
996
|
+
}
|
|
446
997
|
}
|
|
447
998
|
|
|
448
|
-
// Container
|
|
449
|
-
container.bind('UserRepository').to(UserRepository);
|
|
450
|
-
container.bind('UserService').to(UserService);
|
|
999
|
+
// Container configuration
|
|
1000
|
+
container.bind<IUserRepository>('UserRepository').to(UserRepository);
|
|
1001
|
+
container.bind<IUserService>('UserService').to(UserService);
|
|
1002
|
+
|
|
1003
|
+
// Controller with dependency injection
|
|
1004
|
+
@controller('/api/users')
|
|
1005
|
+
@injectable()
|
|
1006
|
+
export class UserController {
|
|
1007
|
+
constructor(@inject('UserService') private userService: IUserService) {}
|
|
1008
|
+
|
|
1009
|
+
@post('/')
|
|
1010
|
+
@validate({ body: CreateUserDto })
|
|
1011
|
+
async createUser(@req() req: Request) {
|
|
1012
|
+
const userData = req.body;
|
|
1013
|
+
const user = await this.userService.create(userData);
|
|
1014
|
+
return new ResponseBuilder().created(user);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
451
1017
|
```
|
|
452
1018
|
|
|
453
|
-
## 📋
|
|
1019
|
+
## 📋 Complete Export List
|
|
454
1020
|
|
|
455
1021
|
```typescript
|
|
456
|
-
//
|
|
1022
|
+
// Core classes
|
|
457
1023
|
export { App } from '@mini2/core';
|
|
458
1024
|
export { Container, container } from '@mini2/core';
|
|
459
1025
|
|
|
460
1026
|
// Interfaces
|
|
461
|
-
export {
|
|
1027
|
+
export {
|
|
1028
|
+
IApp,
|
|
1029
|
+
IConfig,
|
|
1030
|
+
IRepository,
|
|
1031
|
+
IResponseBuilder,
|
|
1032
|
+
IAuthenticatedRequest,
|
|
1033
|
+
} from '@mini2/core';
|
|
462
1034
|
|
|
463
|
-
//
|
|
1035
|
+
// Middlewares
|
|
464
1036
|
export {
|
|
465
1037
|
validationMiddleware,
|
|
466
1038
|
authenticatedMiddleware,
|
|
@@ -470,44 +1042,52 @@ export {
|
|
|
470
1042
|
// Utilities
|
|
471
1043
|
export { arrayUnify, sum, ResponseBuilder } from '@mini2/core';
|
|
472
1044
|
|
|
473
|
-
//
|
|
1045
|
+
// Exceptions
|
|
474
1046
|
export {
|
|
475
1047
|
HttpException,
|
|
476
1048
|
BadRequestException,
|
|
477
1049
|
UnauthorizedException,
|
|
478
|
-
|
|
1050
|
+
ForbiddenException,
|
|
1051
|
+
NotFoundException,
|
|
1052
|
+
MethodNotAllowedException,
|
|
1053
|
+
ConflictException,
|
|
1054
|
+
UnprocessableEntityException,
|
|
1055
|
+
TooManyRequestsException,
|
|
1056
|
+
InternalServerErrorException,
|
|
1057
|
+
// ... all other exceptions
|
|
479
1058
|
} from '@mini2/core';
|
|
480
1059
|
|
|
481
|
-
// Types
|
|
1060
|
+
// Types and constants
|
|
482
1061
|
export { MINI_TYPES } from '@mini2/core';
|
|
1062
|
+
|
|
1063
|
+
// Decorators
|
|
483
1064
|
export {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
Authenticated,
|
|
497
|
-
Authorized,
|
|
498
|
-
Validation,
|
|
499
|
-
Middleware,
|
|
1065
|
+
controller,
|
|
1066
|
+
get,
|
|
1067
|
+
post,
|
|
1068
|
+
put,
|
|
1069
|
+
del,
|
|
1070
|
+
patch,
|
|
1071
|
+
req,
|
|
1072
|
+
res,
|
|
1073
|
+
authenticated,
|
|
1074
|
+
authorized,
|
|
1075
|
+
validate,
|
|
1076
|
+
middleware,
|
|
500
1077
|
} from '@mini2/core';
|
|
501
1078
|
|
|
502
1079
|
// Swagger
|
|
503
1080
|
export { SwaggerIntegration, SwaggerOptions } from '@mini2/core';
|
|
1081
|
+
|
|
1082
|
+
// REST utilities
|
|
1083
|
+
export { buildApp, Method, RouteOptions } from '@mini2/core';
|
|
504
1084
|
```
|
|
505
1085
|
|
|
506
|
-
## 📄
|
|
1086
|
+
## 📄 License
|
|
507
1087
|
|
|
508
1088
|
ISC
|
|
509
1089
|
|
|
510
|
-
## 👨💻
|
|
1090
|
+
## 👨💻 Author
|
|
511
1091
|
|
|
512
1092
|
**Mustafa Çolakoğlu**
|
|
513
1093
|
Email: mustafacolakoglu94@gmail.com
|
|
@@ -515,4 +1095,4 @@ GitHub: https://github.com/mustafa-colakoglu
|
|
|
515
1095
|
|
|
516
1096
|
---
|
|
517
1097
|
|
|
518
|
-
**
|
|
1098
|
+
**Note:** This framework is actively maintained. Visit the GitHub repository for contributions and suggestions.
|
|
@@ -1,34 +1,9 @@
|
|
|
1
1
|
export interface IRepository<IdentifierType, ModelType> {
|
|
2
|
-
findAll(): Promise<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
})[]>;
|
|
7
|
-
findById(id: IdentifierType): Promise<(ModelType & {
|
|
8
|
-
id: string;
|
|
9
|
-
createdAt: Date;
|
|
10
|
-
updatedAt: Date;
|
|
11
|
-
}) | null>;
|
|
12
|
-
create(item: ModelType): Promise<ModelType & {
|
|
13
|
-
id: string;
|
|
14
|
-
createdAt: Date;
|
|
15
|
-
updatedAt: Date;
|
|
16
|
-
}>;
|
|
17
|
-
update(id: IdentifierType, item: Partial<ModelType>): Promise<ModelType & {
|
|
18
|
-
id: string;
|
|
19
|
-
createdAt: Date;
|
|
20
|
-
updatedAt: Date;
|
|
21
|
-
}>;
|
|
2
|
+
findAll(): Promise<ModelType[]>;
|
|
3
|
+
findById(id: IdentifierType): Promise<ModelType | null>;
|
|
4
|
+
create(item: ModelType): Promise<ModelType>;
|
|
5
|
+
update(id: IdentifierType, item: Partial<ModelType>): Promise<ModelType>;
|
|
22
6
|
delete(id: IdentifierType): Promise<void>;
|
|
23
|
-
findPaginated(query: Partial<ModelType>, page: number, limit: number): Promise<
|
|
24
|
-
id: string;
|
|
25
|
-
createdAt: Date;
|
|
26
|
-
updatedAt: Date;
|
|
27
|
-
})[]>;
|
|
28
|
-
mapper(model: any): ModelType & {
|
|
29
|
-
id: string;
|
|
30
|
-
createdAt: Date;
|
|
31
|
-
updatedAt: Date;
|
|
32
|
-
};
|
|
7
|
+
findPaginated(query: Partial<ModelType>, page: number, limit: number): Promise<ModelType[]>;
|
|
33
8
|
}
|
|
34
9
|
//# sourceMappingURL=repository.interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.interface.d.ts","sourceRoot":"","sources":["../../interfaces/repository.interface.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repository.interface.d.ts","sourceRoot":"","sources":["../../interfaces/repository.interface.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,WAAW,CAAC,cAAc,EAAE,SAAS;IACrD,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACzE,MAAM,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,aAAa,CACZ,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,EACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"rebuild": "npm run clean && npm run build",
|
|
7
7
|
"prepublishOnly": "npm run rebuild",
|
|
8
8
|
"dev": "tsc --watch",
|
|
9
|
-
"
|
|
9
|
+
"publish:npm": "npm run build && npm publish",
|
|
10
10
|
"publish:patch": "tsc && npm version patch && npm publish",
|
|
11
11
|
"publish:minor": "tsc && npm version minor && npm publish",
|
|
12
12
|
"publish:major": "tsc && npm version major && npm publish"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"license": "ISC",
|
|
26
26
|
"description": "Mini Express Framework - Lightweight and modular Express.js framework with TypeScript support",
|
|
27
27
|
"name": "@mini2/core",
|
|
28
|
-
"version": "1.
|
|
28
|
+
"version": "1.1.1",
|
|
29
29
|
"author": "Mustafa Çolakoglu <mustafacolakoglu94@gmail.com> (https://github.com/mustafa-colakoglu)",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"class-transformer": "^0.5.1",
|
|
@@ -45,13 +45,5 @@
|
|
|
45
45
|
"@types/node": "^20.14.9",
|
|
46
46
|
"@types/swagger-ui-express": "^4.1.6",
|
|
47
47
|
"typescript": "^5.5.3"
|
|
48
|
-
},
|
|
49
|
-
"peerDependencies": {
|
|
50
|
-
"mongoose": "^8.0.0"
|
|
51
|
-
},
|
|
52
|
-
"peerDependenciesMeta": {
|
|
53
|
-
"mongoose": {
|
|
54
|
-
"optional": true
|
|
55
|
-
}
|
|
56
48
|
}
|
|
57
49
|
}
|