@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.
@@ -14,14 +14,7 @@ function _define_property(obj, key, value) {
14
14
  import { ErrorHandler } from '../utils/error-handler.util';
15
15
  import { Logger, NotFoundException } from '@nestjs/common';
16
16
  import { In } from 'typeorm';
17
- /**
18
- * Generic API service to handle common CRUD operations with caching support.
19
- * This class is fully abstract and should be extended by concrete services
20
- * for specific entities.
21
- */ export class ApiService {
22
- // ---------------------------------------------------------------------
23
- // INSERT SINGLE ENTITY
24
- // ---------------------------------------------------------------------
17
+ /** Generic API service with CRUD operations and caching support */ export class ApiService {
25
18
  async insert(dto, user) {
26
19
  await this.ensureRepositoryInitialized();
27
20
  const qr = this.repository.manager.connection.createQueryRunner();
@@ -48,9 +41,6 @@ import { In } from 'typeorm';
48
41
  await qr.release();
49
42
  }
50
43
  }
51
- // ---------------------------------------------------------------------
52
- // INSERT MULTIPLE ENTITIES
53
- // ---------------------------------------------------------------------
54
44
  async insertMany(dtos, user) {
55
45
  await this.ensureRepositoryInitialized();
56
46
  const qr = this.repository.manager.connection.createQueryRunner();
@@ -81,9 +71,6 @@ import { In } from 'typeorm';
81
71
  await qr.release();
82
72
  }
83
73
  }
84
- // ---------------------------------------------------------------------
85
- // UPDATE SINGLE ENTITY
86
- // ---------------------------------------------------------------------
87
74
  async update(dto, user) {
88
75
  await this.ensureRepositoryInitialized();
89
76
  const qr = this.repository.manager.connection.createQueryRunner();
@@ -110,9 +97,6 @@ import { In } from 'typeorm';
110
97
  await qr.release();
111
98
  }
112
99
  }
113
- // ---------------------------------------------------------------------
114
- // UPDATE MULTIPLE ENTITIES
115
- // ---------------------------------------------------------------------
116
100
  async updateMany(dtos, user) {
117
101
  await this.ensureRepositoryInitialized();
118
102
  const qr = this.repository.manager.connection.createQueryRunner();
@@ -143,9 +127,6 @@ import { In } from 'typeorm';
143
127
  await qr.release();
144
128
  }
145
129
  }
146
- // ---------------------------------------------------------------------
147
- // FIND BY IDS
148
- // ---------------------------------------------------------------------
149
130
  async findByIds(ids, user) {
150
131
  await this.ensureRepositoryInitialized();
151
132
  try {
@@ -170,9 +151,6 @@ import { In } from 'typeorm';
170
151
  this.handleError(error, 'findByIds');
171
152
  }
172
153
  }
173
- // ---------------------------------------------------------------------
174
- // FIND BY ID
175
- // ---------------------------------------------------------------------
176
154
  async findById(id, user, select) {
177
155
  await this.ensureRepositoryInitialized();
178
156
  try {
@@ -211,9 +189,6 @@ import { In } from 'typeorm';
211
189
  this.handleError(error, 'findById');
212
190
  }
213
191
  }
214
- // ---------------------------------------------------------------------
215
- // GET ALL (WITH FILTER, SORT, SEARCH, PAGINATION & CACHING)
216
- // ---------------------------------------------------------------------
217
192
  async getAll(search, filterAndPaginationDto, user) {
218
193
  await this.ensureRepositoryInitialized();
219
194
  try {
@@ -312,9 +287,6 @@ import { In } from 'typeorm';
312
287
  this.handleError(error, 'getAll');
313
288
  }
314
289
  }
315
- // ---------------------------------------------------------------------
316
- // DELETE / RESTORE / HARD DELETE
317
- // ---------------------------------------------------------------------
318
290
  async delete(option, user) {
319
291
  await this.ensureRepositoryInitialized();
320
292
  const queryRunner = this.repository.manager.connection.createQueryRunner();
@@ -357,9 +329,7 @@ import { In } from 'typeorm';
357
329
  await queryRunner.release();
358
330
  }
359
331
  }
360
- // ---------------------------------------------------------------------
361
- // CACHING HELPERS
362
- // ---------------------------------------------------------------------
332
+ // Caching
363
333
  async clearCacheForAll() {
364
334
  await this.utilsService.clearCache(this.entityName, this.cacheManager);
365
335
  }
@@ -374,17 +344,8 @@ import { In } from 'typeorm';
374
344
  });
375
345
  ErrorHandler.rethrowError(error);
376
346
  }
377
- // ---------------------------------------------------------------------
378
- // HOOKS / HELPERS (OVERRIDE IN CHILD CLASSES)
379
- // ---------------------------------------------------------------------
380
- /**
381
- * Hook called before ANY repository access
382
- * CRITICAL: Override this in REQUEST-scoped services that use lazy repository initialization
383
- * Example use case: DataSource Provider pattern where repository is set dynamically
384
- */ async ensureRepositoryInitialized() {
385
- // Default: no-op - repository is already initialized in constructor
386
- // Override in child classes that need lazy initialization
387
- }
347
+ // Hooks (override in child classes)
348
+ async ensureRepositoryInitialized() {}
388
349
  async beforeInsertOperation(_dto, _user, _queryRunner) {}
389
350
  async afterInsertOperation(_entity, _user, _queryRunner) {}
390
351
  async beforeUpdateOperation(_dto, _user, _queryRunner) {}
@@ -433,9 +394,7 @@ import { In } from 'typeorm';
433
394
  isRaw: false
434
395
  };
435
396
  }
436
- // ---------------------------------------------------------------------
437
- // DTO <-> ENTITY CONVERSION
438
- // ---------------------------------------------------------------------
397
+ // DTO conversion
439
398
  async convertRequestDtoToEntity(dto, user) {
440
399
  return Array.isArray(dto) ? await this.convertArrayDtoToEntities(dto, user) : [
441
400
  await this.convertSingleDtoToEntity(dto, user)
@@ -20,18 +20,7 @@ function _ts_decorate(decorators, target, key, desc) {
20
20
  import { Injectable, Scope } from '@nestjs/common';
21
21
  import { ApiService } from './api-service.class';
22
22
  export class RequestScopedApiService extends ApiService {
23
- /**
24
- * Ensures repository is initialized before any database access
25
- * CRITICAL: Automatically called by ApiService before all CRUD operations
26
- *
27
- * This method:
28
- * 1. Calls resolveEntity() to get the entity class
29
- * 2. Calls getDataSourceProvider() to get the provider
30
- * 3. Loads the repository from the provider
31
- * 4. Marks initialization as complete
32
- *
33
- * @internal - Called automatically, do not call manually
34
- */ async ensureRepositoryInitialized() {
23
+ async ensureRepositoryInitialized() {
35
24
  if (!this.repositoryInitialized) {
36
25
  const entity = this.resolveEntity();
37
26
  const provider = this.getDataSourceProvider();
@@ -39,26 +28,7 @@ export class RequestScopedApiService extends ApiService {
39
28
  this.repositoryInitialized = true;
40
29
  }
41
30
  }
42
- /**
43
- * Helper method to initialize additional repositories
44
- * Useful when service needs multiple repositories beyond the primary entity repository
45
- *
46
- * @param entities - Array of entity classes to load repositories for
47
- * @returns Array of initialized repositories in the same order as entities
48
- *
49
- * @example
50
- * ```typescript
51
- * protected override async ensureRepositoryInitialized(): Promise<void> {
52
- * await super.ensureRepositoryInitialized();
53
- *
54
- * if (this.configService.isCompanyFeatureEnabled() && !this.permissionRepository) {
55
- * [this.permissionRepository] = await this.initializeAdditionalRepositories([
56
- * UserCompanyPermission
57
- * ]);
58
- * }
59
- * }
60
- * ```
61
- */ async initializeAdditionalRepositories(entities) {
31
+ /** Initialize additional repositories beyond the primary entity */ async initializeAdditionalRepositories(entities) {
62
32
  const provider = this.getDataSourceProvider();
63
33
  const repositories = [];
64
34
  for (const entity of entities){
@@ -66,31 +36,12 @@ export class RequestScopedApiService extends ApiService {
66
36
  }
67
37
  return repositories;
68
38
  }
69
- /**
70
- * Helper method to get the DataSource
71
- * Useful when service needs direct DataSource access for transactions or custom queries
72
- *
73
- * @returns DataSource instance
74
- *
75
- * @example
76
- * ```typescript
77
- * protected override async ensureRepositoryInitialized(): Promise<void> {
78
- * await super.ensureRepositoryInitialized();
79
- *
80
- * if (!this.dataSource) {
81
- * this.dataSource = await this.getDataSourceForService();
82
- * }
83
- * }
84
- * ```
85
- */ async getDataSourceForService() {
39
+ /** Get DataSource for direct access (transactions, custom queries) */ async getDataSourceForService() {
86
40
  const provider = this.getDataSourceProvider();
87
41
  return await provider.getDataSource();
88
42
  }
89
43
  constructor(...args){
90
- super(...args), /**
91
- * Tracks whether repository has been initialized
92
- * Automatically managed by ensureRepositoryInitialized()
93
- */ _define_property(this, "repositoryInitialized", false);
44
+ super(...args), _define_property(this, "repositoryInitialized", false);
94
45
  }
95
46
  }
96
47
  RequestScopedApiService = _ts_decorate([
@@ -20,9 +20,7 @@ import * as TransportModule from 'winston-transport';
20
20
  const Transport = TransportModule.default || TransportModule;
21
21
  import * as DailyRotateFileModule from 'winston-daily-rotate-file';
22
22
  const DailyRotateFile = DailyRotateFileModule.default || DailyRotateFileModule;
23
- // =============================================================================
24
- // CONFIGURATION (from envConfig)
25
- // =============================================================================
23
+ // Configuration
26
24
  const logConfig = envConfig.getLogConfig();
27
25
  const LOG_DIR = logConfig.dir;
28
26
  const LOG_LEVEL = logConfig.level;
@@ -35,9 +33,7 @@ if (!existsSync(LOG_DIR)) {
35
33
  recursive: true
36
34
  });
37
35
  }
38
- // =============================================================================
39
- // CUSTOM FORMATS
40
- // =============================================================================
36
+ // Custom Formats
41
37
  /**
42
38
  * Custom format for structured logging
43
39
  * Includes: timestamp, level, context, requestId, userId, message, metadata
@@ -67,9 +63,7 @@ if (!existsSync(LOG_DIR)) {
67
63
  const stackTrace = stack ? `\n${stack}` : '';
68
64
  return `${timestamp} [${level.toUpperCase().padEnd(7)}] [${ctx}]${endpoint}${status}${time}${reqId}${user} ${message}${stackTrace}`;
69
65
  });
70
- // =============================================================================
71
- // TRANSPORTS
72
- // =============================================================================
66
+ // Transports
73
67
  /**
74
68
  * Daily rotating file transport for all logs
75
69
  */ const combinedRotateTransport = new DailyRotateFile({
@@ -90,9 +84,7 @@ if (!existsSync(LOG_DIR)) {
90
84
  maxFiles: LOG_MAX_FILES,
91
85
  level: 'error'
92
86
  });
93
- // =============================================================================
94
- // TENANT-AWARE TRANSPORT
95
- // =============================================================================
87
+ // Tenant-Aware Transport
96
88
  /**
97
89
  * Cache for tenant-specific transports
98
90
  * Avoids creating new transport instances for each log entry
@@ -158,9 +150,7 @@ if (!existsSync(LOG_DIR)) {
158
150
  stack: true
159
151
  }), devConsoleFormat)
160
152
  });
161
- // =============================================================================
162
- // LOGGER INSTANCES
163
- // =============================================================================
153
+ // Logger Instances
164
154
  /**
165
155
  * Development logger configuration
166
156
  * - Console output with colors
@@ -198,9 +188,7 @@ if (!existsSync(LOG_DIR)) {
198
188
  ],
199
189
  exitOnError: false
200
190
  });
201
- // =============================================================================
202
- // EXPORTS
203
- // =============================================================================
191
+ // Exports
204
192
  /**
205
193
  * Winston logger instance
206
194
  * - DEV: Console output with colors
@@ -1,29 +1,14 @@
1
- /**
2
- * Constants for the common module
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) */ export const IS_PUBLIC_KEY = 'isPublic';
12
- /** Metadata key for required permissions */ export const PERMISSIONS_KEY = 'permissions';
13
- // =============================================================================
14
- // INJECTION TOKENS (used with @Inject decorator)
15
- // =============================================================================
16
- /** Injection token for cache instance */ export const CACHE_INSTANCE = 'CACHE_INSTANCE';
17
- /** Injection token for permission guard configuration */ export const PERMISSION_GUARD_CONFIG = 'PERMISSION_GUARD_CONFIG';
18
- /** Injection token for logger instance */ export const LOGGER_INSTANCE = 'LOGGER_INSTANCE';
19
- // =============================================================================
20
- // HEADER NAMES
21
- // =============================================================================
22
- /** Header for idempotency key */ export const IDEMPOTENCY_KEY_HEADER = 'x-idempotency-key';
23
- /** Header for request ID (correlation) */ export const REQUEST_ID_HEADER = 'x-request-id';
24
- /** Header for client type (browser, mobile, api) */ export const CLIENT_TYPE_HEADER = 'x-client-type';
25
- // =============================================================================
26
- // CACHE KEY PREFIXES (Generic - usable by any package)
27
- // =============================================================================
28
- /** Cache key prefix for user permissions (generic, not auth-specific) */ export const PERMISSIONS_CACHE_PREFIX = 'permissions';
29
- /** Cache key prefix for idempotency */ export const IDEMPOTENCY_CACHE_PREFIX = 'idempotency';
1
+ // Metadata keys
2
+ export const IS_PUBLIC_KEY = 'isPublic';
3
+ export const PERMISSIONS_KEY = 'permissions';
4
+ // Injection tokens
5
+ export const CACHE_INSTANCE = 'CACHE_INSTANCE';
6
+ export const PERMISSION_GUARD_CONFIG = 'PERMISSION_GUARD_CONFIG';
7
+ export const LOGGER_INSTANCE = 'LOGGER_INSTANCE';
8
+ // Header names
9
+ export const IDEMPOTENCY_KEY_HEADER = 'x-idempotency-key';
10
+ export const REQUEST_ID_HEADER = 'x-request-id';
11
+ export const CLIENT_TYPE_HEADER = 'x-client-type';
12
+ // Cache key prefixes
13
+ export const PERMISSIONS_CACHE_PREFIX = 'permissions';
14
+ export const IDEMPOTENCY_CACHE_PREFIX = 'idempotency';