@flusys/nestjs-shared 0.1.0-beta.2 → 1.0.0-beta
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 +51 -29
- package/cjs/classes/api-controller.class.js +0 -21
- package/cjs/classes/api-service.class.js +4 -41
- package/cjs/classes/request-scoped-api.service.js +4 -53
- package/cjs/classes/winston.logger.class.js +5 -15
- package/cjs/constants/index.js +2 -11
- package/cjs/dtos/response-payload.dto.js +40 -85
- package/cjs/interfaces/logged-user-info.interface.js +1 -2
- package/cjs/interfaces/permission.interface.js +1 -10
- package/cjs/middlewares/logger.middleware.js +2 -6
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +9 -9
- package/fesm/classes/api-controller.class.js +1 -69
- package/fesm/classes/api-service.class.js +5 -46
- package/fesm/classes/request-scoped-api.service.js +4 -53
- package/fesm/classes/winston.logger.class.js +6 -18
- package/fesm/constants/index.js +14 -29
- package/fesm/dtos/response-payload.dto.js +44 -109
- package/fesm/interfaces/logged-user-info.interface.js +1 -2
- package/fesm/interfaces/permission.interface.js +0 -12
- package/fesm/middlewares/logger.middleware.js +2 -6
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +9 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -32,8 +32,8 @@ This comprehensive guide covers the shared package - the shared NestJS infrastru
|
|
|
32
32
|
- **Generic CRUD** - Standardized API controller and service patterns
|
|
33
33
|
- **Permission System** - Role and permission-based access control
|
|
34
34
|
- **Caching** - In-memory + Redis hybrid caching
|
|
35
|
-
- **Request Correlation** - AsyncLocalStorage-based request tracking
|
|
36
|
-
- **Middleware** - Logging, correlation, and performance monitoring
|
|
35
|
+
- **Request Correlation** - AsyncLocalStorage-based request tracking
|
|
36
|
+
- **Middleware** - Logging, correlation, and performance monitoring
|
|
37
37
|
- **Interceptors** - Response metadata, idempotency, auto field setting
|
|
38
38
|
- **Multi-Tenancy** - Dynamic database connection management
|
|
39
39
|
- **Error Handling** - Centralized error handling utilities
|
|
@@ -462,23 +462,52 @@ export class ReportsController {
|
|
|
462
462
|
}
|
|
463
463
|
```
|
|
464
464
|
|
|
465
|
-
### @
|
|
465
|
+
### @RequirePermissionCondition
|
|
466
466
|
|
|
467
|
-
|
|
467
|
+
Build complex permission conditions with nested AND/OR logic:
|
|
468
468
|
|
|
469
469
|
```typescript
|
|
470
|
-
import {
|
|
470
|
+
import { RequirePermissionCondition } from '@flusys/nestjs-shared/decorators';
|
|
471
471
|
|
|
472
472
|
@Controller('sensitive')
|
|
473
473
|
export class SensitiveController {
|
|
474
|
-
|
|
475
|
-
@
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
}
|
|
474
|
+
// Simple: User needs 'admin' OR 'manager'
|
|
475
|
+
@RequirePermissionCondition({
|
|
476
|
+
operator: 'or',
|
|
477
|
+
permissions: ['admin', 'manager'],
|
|
478
|
+
})
|
|
479
|
+
@Get('simple')
|
|
480
|
+
getSimpleData() {}
|
|
481
|
+
|
|
482
|
+
// Complex: User needs 'users.read' AND ('admin' OR 'manager')
|
|
483
|
+
@RequirePermissionCondition({
|
|
484
|
+
operator: 'and',
|
|
485
|
+
permissions: ['users.read'],
|
|
486
|
+
children: [
|
|
487
|
+
{ operator: 'or', permissions: ['admin', 'manager'] }
|
|
488
|
+
]
|
|
489
|
+
})
|
|
490
|
+
@Get('complex')
|
|
491
|
+
getComplexData() {}
|
|
492
|
+
|
|
493
|
+
// Very complex: (A AND B) OR (C AND D)
|
|
494
|
+
@RequirePermissionCondition({
|
|
495
|
+
operator: 'or',
|
|
496
|
+
children: [
|
|
497
|
+
{ operator: 'and', permissions: ['finance.read', 'finance.write'] },
|
|
498
|
+
{ operator: 'and', permissions: ['admin.full', 'reports.access'] }
|
|
499
|
+
]
|
|
500
|
+
})
|
|
501
|
+
@Get('very-complex')
|
|
502
|
+
getVeryComplexData() {}
|
|
479
503
|
}
|
|
480
504
|
```
|
|
481
505
|
|
|
506
|
+
**Note:** For simple "require ALL permissions" use case, use `@RequirePermission` which defaults to AND logic:
|
|
507
|
+
```typescript
|
|
508
|
+
@RequirePermission('admin.access', 'security.clearance') // User needs BOTH
|
|
509
|
+
```
|
|
510
|
+
|
|
482
511
|
---
|
|
483
512
|
|
|
484
513
|
## Guards
|
|
@@ -586,7 +615,7 @@ PermissionModule.forRoot({
|
|
|
586
615
|
|
|
587
616
|
## Middleware
|
|
588
617
|
|
|
589
|
-
### LoggerMiddleware
|
|
618
|
+
### LoggerMiddleware
|
|
590
619
|
|
|
591
620
|
**Location:** `@flusys/nestjs-shared/middlewares/logger.middleware.ts`
|
|
592
621
|
|
|
@@ -1235,11 +1264,12 @@ import {
|
|
|
1235
1264
|
Public,
|
|
1236
1265
|
RequirePermission,
|
|
1237
1266
|
RequireAnyPermission,
|
|
1238
|
-
|
|
1267
|
+
RequirePermissionCondition,
|
|
1239
1268
|
} from '@flusys/nestjs-shared/decorators';
|
|
1240
1269
|
|
|
1241
1270
|
// Guards
|
|
1242
1271
|
import {
|
|
1272
|
+
JwtAuthGuard,
|
|
1243
1273
|
PermissionGuard,
|
|
1244
1274
|
} from '@flusys/nestjs-shared/guards';
|
|
1245
1275
|
|
|
@@ -1375,25 +1405,17 @@ async getPermissions(userId: string) {
|
|
|
1375
1405
|
|
|
1376
1406
|
The `@flusys/nestjs-shared` package provides:
|
|
1377
1407
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1408
|
+
- **Generic CRUD** - Consistent API patterns
|
|
1409
|
+
- **Permission System** - Flexible access control
|
|
1410
|
+
- **Caching** - High-performance data access
|
|
1411
|
+
- **Multi-Tenancy** - Database isolation
|
|
1412
|
+
- **Request Correlation** - AsyncLocalStorage-based tracking
|
|
1413
|
+
- **Middleware** - Logging and performance monitoring
|
|
1414
|
+
- **Interceptors** - Request/response processing
|
|
1415
|
+
- **Error Handling** - Centralized error management
|
|
1386
1416
|
|
|
1387
1417
|
This is the shared infrastructure layer used by all other Flusys packages.
|
|
1388
1418
|
|
|
1389
1419
|
---
|
|
1390
1420
|
|
|
1391
|
-
**Last Updated:** 2026-02-
|
|
1392
|
-
**Recent Improvements:**
|
|
1393
|
-
- 2026-02-07: Documentation cleanup - removed outdated JWT configuration section, updated package architecture to match actual structure
|
|
1394
|
-
- 2026-01-14: Enhanced `LoggerMiddleware` with complete request/response details (URL, path, query, headers, user context)
|
|
1395
|
-
- 2026-01-14: Added multiple response hooks (send, json, end) for reliable response capture
|
|
1396
|
-
- 2026-01-14: Improved error logging with stack traces
|
|
1397
|
-
- 2026-01-12: Added `LoggerMiddleware` for request correlation and structured logging
|
|
1398
|
-
- 2026-01-12: Added AsyncLocalStorage-based request context (requestId, tenantId, userId, companyId)
|
|
1399
|
-
- 2026-01-13: Removed JWT config/constants (moved to auth-specific packages)
|
|
1421
|
+
**Last Updated:** 2026-02-16
|
|
@@ -117,9 +117,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
117
117
|
delete: isGlobalSecurity ? defaultSecurity : normalizeSecurity(securityConfig?.delete)
|
|
118
118
|
};
|
|
119
119
|
let ApiController = class ApiController {
|
|
120
|
-
// =========================================================================
|
|
121
|
-
// INSERT (Single Item) - With Idempotency Support
|
|
122
|
-
// =========================================================================
|
|
123
120
|
async insert(addDto, user) {
|
|
124
121
|
const entity = await this.service.insert(addDto, user);
|
|
125
122
|
const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
|
|
@@ -129,9 +126,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
129
126
|
data
|
|
130
127
|
};
|
|
131
128
|
}
|
|
132
|
-
// =========================================================================
|
|
133
|
-
// INSERT MANY (Bulk) - With Idempotency Support
|
|
134
|
-
// =========================================================================
|
|
135
129
|
async insertMany(addDto, user) {
|
|
136
130
|
const entities = await this.service.insertMany(addDto, user);
|
|
137
131
|
const data = entities.map((item)=>(0, _classtransformer.plainToInstance)(responseDtoClass, item));
|
|
@@ -146,9 +140,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
146
140
|
}
|
|
147
141
|
};
|
|
148
142
|
}
|
|
149
|
-
// =========================================================================
|
|
150
|
-
// GET BY ID (Single Item)
|
|
151
|
-
// =========================================================================
|
|
152
143
|
async getById(id, body, user) {
|
|
153
144
|
const entity = await this.service.findById(id, user, body?.select);
|
|
154
145
|
const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
|
|
@@ -158,9 +149,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
158
149
|
data
|
|
159
150
|
};
|
|
160
151
|
}
|
|
161
|
-
// =========================================================================
|
|
162
|
-
// UPDATE (Single Item)
|
|
163
|
-
// =========================================================================
|
|
164
152
|
async update(updateDto, user) {
|
|
165
153
|
const entity = await this.service.update(updateDto, user);
|
|
166
154
|
const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
|
|
@@ -170,9 +158,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
170
158
|
data
|
|
171
159
|
};
|
|
172
160
|
}
|
|
173
|
-
// =========================================================================
|
|
174
|
-
// UPDATE MANY (Bulk)
|
|
175
|
-
// =========================================================================
|
|
176
161
|
async updateMany(updateDtos, user) {
|
|
177
162
|
const entities = await this.service.updateMany(updateDtos, user);
|
|
178
163
|
const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entities);
|
|
@@ -187,9 +172,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
187
172
|
}
|
|
188
173
|
};
|
|
189
174
|
}
|
|
190
|
-
// =========================================================================
|
|
191
|
-
// GET ALL (Paginated List)
|
|
192
|
-
// =========================================================================
|
|
193
175
|
async getAll(filterAndPaginationDto, user, search) {
|
|
194
176
|
const result = await this.service.getAll(search ?? '', filterAndPaginationDto, user);
|
|
195
177
|
const data = (0, _classtransformer.plainToInstance)(responseDtoClass, result.data);
|
|
@@ -210,9 +192,6 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
210
192
|
}
|
|
211
193
|
};
|
|
212
194
|
}
|
|
213
|
-
// =========================================================================
|
|
214
|
-
// DELETE (Soft/Restore/Permanent)
|
|
215
|
-
// =========================================================================
|
|
216
195
|
async delete(deleteDto, user) {
|
|
217
196
|
await this.service.delete(deleteDto, user);
|
|
218
197
|
const count = Array.isArray(deleteDto.id) ? deleteDto.id.length : 1;
|
|
@@ -25,9 +25,6 @@ function _define_property(obj, key, value) {
|
|
|
25
25
|
return obj;
|
|
26
26
|
}
|
|
27
27
|
let ApiService = class ApiService {
|
|
28
|
-
// ---------------------------------------------------------------------
|
|
29
|
-
// INSERT SINGLE ENTITY
|
|
30
|
-
// ---------------------------------------------------------------------
|
|
31
28
|
async insert(dto, user) {
|
|
32
29
|
await this.ensureRepositoryInitialized();
|
|
33
30
|
const qr = this.repository.manager.connection.createQueryRunner();
|
|
@@ -54,9 +51,6 @@ let ApiService = class ApiService {
|
|
|
54
51
|
await qr.release();
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
|
-
// ---------------------------------------------------------------------
|
|
58
|
-
// INSERT MULTIPLE ENTITIES
|
|
59
|
-
// ---------------------------------------------------------------------
|
|
60
54
|
async insertMany(dtos, user) {
|
|
61
55
|
await this.ensureRepositoryInitialized();
|
|
62
56
|
const qr = this.repository.manager.connection.createQueryRunner();
|
|
@@ -87,9 +81,6 @@ let ApiService = class ApiService {
|
|
|
87
81
|
await qr.release();
|
|
88
82
|
}
|
|
89
83
|
}
|
|
90
|
-
// ---------------------------------------------------------------------
|
|
91
|
-
// UPDATE SINGLE ENTITY
|
|
92
|
-
// ---------------------------------------------------------------------
|
|
93
84
|
async update(dto, user) {
|
|
94
85
|
await this.ensureRepositoryInitialized();
|
|
95
86
|
const qr = this.repository.manager.connection.createQueryRunner();
|
|
@@ -116,9 +107,6 @@ let ApiService = class ApiService {
|
|
|
116
107
|
await qr.release();
|
|
117
108
|
}
|
|
118
109
|
}
|
|
119
|
-
// ---------------------------------------------------------------------
|
|
120
|
-
// UPDATE MULTIPLE ENTITIES
|
|
121
|
-
// ---------------------------------------------------------------------
|
|
122
110
|
async updateMany(dtos, user) {
|
|
123
111
|
await this.ensureRepositoryInitialized();
|
|
124
112
|
const qr = this.repository.manager.connection.createQueryRunner();
|
|
@@ -149,9 +137,6 @@ let ApiService = class ApiService {
|
|
|
149
137
|
await qr.release();
|
|
150
138
|
}
|
|
151
139
|
}
|
|
152
|
-
// ---------------------------------------------------------------------
|
|
153
|
-
// FIND BY IDS
|
|
154
|
-
// ---------------------------------------------------------------------
|
|
155
140
|
async findByIds(ids, user) {
|
|
156
141
|
await this.ensureRepositoryInitialized();
|
|
157
142
|
try {
|
|
@@ -176,9 +161,6 @@ let ApiService = class ApiService {
|
|
|
176
161
|
this.handleError(error, 'findByIds');
|
|
177
162
|
}
|
|
178
163
|
}
|
|
179
|
-
// ---------------------------------------------------------------------
|
|
180
|
-
// FIND BY ID
|
|
181
|
-
// ---------------------------------------------------------------------
|
|
182
164
|
async findById(id, user, select) {
|
|
183
165
|
await this.ensureRepositoryInitialized();
|
|
184
166
|
try {
|
|
@@ -217,9 +199,6 @@ let ApiService = class ApiService {
|
|
|
217
199
|
this.handleError(error, 'findById');
|
|
218
200
|
}
|
|
219
201
|
}
|
|
220
|
-
// ---------------------------------------------------------------------
|
|
221
|
-
// GET ALL (WITH FILTER, SORT, SEARCH, PAGINATION & CACHING)
|
|
222
|
-
// ---------------------------------------------------------------------
|
|
223
202
|
async getAll(search, filterAndPaginationDto, user) {
|
|
224
203
|
await this.ensureRepositoryInitialized();
|
|
225
204
|
try {
|
|
@@ -318,9 +297,6 @@ let ApiService = class ApiService {
|
|
|
318
297
|
this.handleError(error, 'getAll');
|
|
319
298
|
}
|
|
320
299
|
}
|
|
321
|
-
// ---------------------------------------------------------------------
|
|
322
|
-
// DELETE / RESTORE / HARD DELETE
|
|
323
|
-
// ---------------------------------------------------------------------
|
|
324
300
|
async delete(option, user) {
|
|
325
301
|
await this.ensureRepositoryInitialized();
|
|
326
302
|
const queryRunner = this.repository.manager.connection.createQueryRunner();
|
|
@@ -363,9 +339,7 @@ let ApiService = class ApiService {
|
|
|
363
339
|
await queryRunner.release();
|
|
364
340
|
}
|
|
365
341
|
}
|
|
366
|
-
//
|
|
367
|
-
// CACHING HELPERS
|
|
368
|
-
// ---------------------------------------------------------------------
|
|
342
|
+
// Caching
|
|
369
343
|
async clearCacheForAll() {
|
|
370
344
|
await this.utilsService.clearCache(this.entityName, this.cacheManager);
|
|
371
345
|
}
|
|
@@ -380,17 +354,8 @@ let ApiService = class ApiService {
|
|
|
380
354
|
});
|
|
381
355
|
_errorhandlerutil.ErrorHandler.rethrowError(error);
|
|
382
356
|
}
|
|
383
|
-
//
|
|
384
|
-
|
|
385
|
-
// ---------------------------------------------------------------------
|
|
386
|
-
/**
|
|
387
|
-
* Hook called before ANY repository access
|
|
388
|
-
* CRITICAL: Override this in REQUEST-scoped services that use lazy repository initialization
|
|
389
|
-
* Example use case: DataSource Provider pattern where repository is set dynamically
|
|
390
|
-
*/ async ensureRepositoryInitialized() {
|
|
391
|
-
// Default: no-op - repository is already initialized in constructor
|
|
392
|
-
// Override in child classes that need lazy initialization
|
|
393
|
-
}
|
|
357
|
+
// Hooks (override in child classes)
|
|
358
|
+
async ensureRepositoryInitialized() {}
|
|
394
359
|
async beforeInsertOperation(_dto, _user, _queryRunner) {}
|
|
395
360
|
async afterInsertOperation(_entity, _user, _queryRunner) {}
|
|
396
361
|
async beforeUpdateOperation(_dto, _user, _queryRunner) {}
|
|
@@ -439,9 +404,7 @@ let ApiService = class ApiService {
|
|
|
439
404
|
isRaw: false
|
|
440
405
|
};
|
|
441
406
|
}
|
|
442
|
-
//
|
|
443
|
-
// DTO <-> ENTITY CONVERSION
|
|
444
|
-
// ---------------------------------------------------------------------
|
|
407
|
+
// DTO conversion
|
|
445
408
|
async convertRequestDtoToEntity(dto, user) {
|
|
446
409
|
return Array.isArray(dto) ? await this.convertArrayDtoToEntities(dto, user) : [
|
|
447
410
|
await this.convertSingleDtoToEntity(dto, user)
|
|
@@ -30,18 +30,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
30
30
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
31
31
|
}
|
|
32
32
|
let RequestScopedApiService = class RequestScopedApiService extends _apiserviceclass.ApiService {
|
|
33
|
-
|
|
34
|
-
* Ensures repository is initialized before any database access
|
|
35
|
-
* CRITICAL: Automatically called by ApiService before all CRUD operations
|
|
36
|
-
*
|
|
37
|
-
* This method:
|
|
38
|
-
* 1. Calls resolveEntity() to get the entity class
|
|
39
|
-
* 2. Calls getDataSourceProvider() to get the provider
|
|
40
|
-
* 3. Loads the repository from the provider
|
|
41
|
-
* 4. Marks initialization as complete
|
|
42
|
-
*
|
|
43
|
-
* @internal - Called automatically, do not call manually
|
|
44
|
-
*/ async ensureRepositoryInitialized() {
|
|
33
|
+
async ensureRepositoryInitialized() {
|
|
45
34
|
if (!this.repositoryInitialized) {
|
|
46
35
|
const entity = this.resolveEntity();
|
|
47
36
|
const provider = this.getDataSourceProvider();
|
|
@@ -49,26 +38,7 @@ let RequestScopedApiService = class RequestScopedApiService extends _apiservicec
|
|
|
49
38
|
this.repositoryInitialized = true;
|
|
50
39
|
}
|
|
51
40
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Helper method to initialize additional repositories
|
|
54
|
-
* Useful when service needs multiple repositories beyond the primary entity repository
|
|
55
|
-
*
|
|
56
|
-
* @param entities - Array of entity classes to load repositories for
|
|
57
|
-
* @returns Array of initialized repositories in the same order as entities
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* ```typescript
|
|
61
|
-
* protected override async ensureRepositoryInitialized(): Promise<void> {
|
|
62
|
-
* await super.ensureRepositoryInitialized();
|
|
63
|
-
*
|
|
64
|
-
* if (this.configService.isCompanyFeatureEnabled() && !this.permissionRepository) {
|
|
65
|
-
* [this.permissionRepository] = await this.initializeAdditionalRepositories([
|
|
66
|
-
* UserCompanyPermission
|
|
67
|
-
* ]);
|
|
68
|
-
* }
|
|
69
|
-
* }
|
|
70
|
-
* ```
|
|
71
|
-
*/ async initializeAdditionalRepositories(entities) {
|
|
41
|
+
/** Initialize additional repositories beyond the primary entity */ async initializeAdditionalRepositories(entities) {
|
|
72
42
|
const provider = this.getDataSourceProvider();
|
|
73
43
|
const repositories = [];
|
|
74
44
|
for (const entity of entities){
|
|
@@ -76,31 +46,12 @@ let RequestScopedApiService = class RequestScopedApiService extends _apiservicec
|
|
|
76
46
|
}
|
|
77
47
|
return repositories;
|
|
78
48
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Helper method to get the DataSource
|
|
81
|
-
* Useful when service needs direct DataSource access for transactions or custom queries
|
|
82
|
-
*
|
|
83
|
-
* @returns DataSource instance
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```typescript
|
|
87
|
-
* protected override async ensureRepositoryInitialized(): Promise<void> {
|
|
88
|
-
* await super.ensureRepositoryInitialized();
|
|
89
|
-
*
|
|
90
|
-
* if (!this.dataSource) {
|
|
91
|
-
* this.dataSource = await this.getDataSourceForService();
|
|
92
|
-
* }
|
|
93
|
-
* }
|
|
94
|
-
* ```
|
|
95
|
-
*/ async getDataSourceForService() {
|
|
49
|
+
/** Get DataSource for direct access (transactions, custom queries) */ async getDataSourceForService() {
|
|
96
50
|
const provider = this.getDataSourceProvider();
|
|
97
51
|
return await provider.getDataSource();
|
|
98
52
|
}
|
|
99
53
|
constructor(...args){
|
|
100
|
-
super(...args),
|
|
101
|
-
* Tracks whether repository has been initialized
|
|
102
|
-
* Automatically managed by ensureRepositoryInitialized()
|
|
103
|
-
*/ _define_property(this, "repositoryInitialized", false);
|
|
54
|
+
super(...args), _define_property(this, "repositoryInitialized", false);
|
|
104
55
|
}
|
|
105
56
|
};
|
|
106
57
|
RequestScopedApiService = _ts_decorate([
|
|
@@ -70,9 +70,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
70
70
|
}
|
|
71
71
|
const Transport = _winstontransport.default || _winstontransport;
|
|
72
72
|
const DailyRotateFile = _winstondailyrotatefile.default || _winstondailyrotatefile;
|
|
73
|
-
//
|
|
74
|
-
// CONFIGURATION (from envConfig)
|
|
75
|
-
// =============================================================================
|
|
73
|
+
// Configuration
|
|
76
74
|
const logConfig = _config.envConfig.getLogConfig();
|
|
77
75
|
const LOG_DIR = logConfig.dir;
|
|
78
76
|
const LOG_LEVEL = logConfig.level;
|
|
@@ -85,9 +83,7 @@ if (!(0, _fs.existsSync)(LOG_DIR)) {
|
|
|
85
83
|
recursive: true
|
|
86
84
|
});
|
|
87
85
|
}
|
|
88
|
-
//
|
|
89
|
-
// CUSTOM FORMATS
|
|
90
|
-
// =============================================================================
|
|
86
|
+
// Custom Formats
|
|
91
87
|
/**
|
|
92
88
|
* Custom format for structured logging
|
|
93
89
|
* Includes: timestamp, level, context, requestId, userId, message, metadata
|
|
@@ -117,9 +113,7 @@ if (!(0, _fs.existsSync)(LOG_DIR)) {
|
|
|
117
113
|
const stackTrace = stack ? `\n${stack}` : '';
|
|
118
114
|
return `${timestamp} [${level.toUpperCase().padEnd(7)}] [${ctx}]${endpoint}${status}${time}${reqId}${user} ${message}${stackTrace}`;
|
|
119
115
|
});
|
|
120
|
-
//
|
|
121
|
-
// TRANSPORTS
|
|
122
|
-
// =============================================================================
|
|
116
|
+
// Transports
|
|
123
117
|
/**
|
|
124
118
|
* Daily rotating file transport for all logs
|
|
125
119
|
*/ const combinedRotateTransport = new DailyRotateFile({
|
|
@@ -140,9 +134,7 @@ if (!(0, _fs.existsSync)(LOG_DIR)) {
|
|
|
140
134
|
maxFiles: LOG_MAX_FILES,
|
|
141
135
|
level: 'error'
|
|
142
136
|
});
|
|
143
|
-
//
|
|
144
|
-
// TENANT-AWARE TRANSPORT
|
|
145
|
-
// =============================================================================
|
|
137
|
+
// Tenant-Aware Transport
|
|
146
138
|
/**
|
|
147
139
|
* Cache for tenant-specific transports
|
|
148
140
|
* Avoids creating new transport instances for each log entry
|
|
@@ -208,9 +200,7 @@ if (!(0, _fs.existsSync)(LOG_DIR)) {
|
|
|
208
200
|
stack: true
|
|
209
201
|
}), devConsoleFormat)
|
|
210
202
|
});
|
|
211
|
-
//
|
|
212
|
-
// LOGGER INSTANCES
|
|
213
|
-
// =============================================================================
|
|
203
|
+
// Logger Instances
|
|
214
204
|
/**
|
|
215
205
|
* Development logger configuration
|
|
216
206
|
* - Console output with colors
|
package/cjs/constants/index.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* This file centralizes all constants used across the module:
|
|
5
|
-
* - Metadata keys for decorators
|
|
6
|
-
* - Injection tokens for DI
|
|
7
|
-
* - Header names
|
|
8
|
-
*/ // =============================================================================
|
|
9
|
-
// METADATA KEYS (used with @SetMetadata decorator)
|
|
10
|
-
// =============================================================================
|
|
11
|
-
/** Metadata key for public routes (skip authentication) */ "use strict";
|
|
1
|
+
// Metadata keys
|
|
2
|
+
"use strict";
|
|
12
3
|
Object.defineProperty(exports, "__esModule", {
|
|
13
4
|
value: true
|
|
14
5
|
});
|