nx-mongo 3.8.5 → 3.8.7

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.
@@ -1,182 +1,6 @@
1
1
  import { MongoClient, Db, Collection, Filter, UpdateFilter, OptionalUnlessRequiredId, Document, WithId, ClientSession, Sort, IndexSpecification, CreateIndexesOptions } from 'mongodb';
2
2
  import { createHash } from 'crypto';
3
- import { getEnvVariables, autoLoadConfig } from 'nx-config2';
4
-
5
- /**
6
- * Log levels ordered from lowest to highest severity
7
- */
8
- type LogLevel = 'verbose' | 'debug' | 'info' | 'warn' | 'error';
9
-
10
- /**
11
- * Log level numeric values for comparison (lower = more verbose)
12
- */
13
- const LOG_LEVEL_VALUES: Record<LogLevel, number> = {
14
- verbose: 0,
15
- debug: 1,
16
- info: 2,
17
- warn: 3,
18
- error: 4,
19
- };
20
-
21
- /**
22
- * Console logger with environment-based level control
23
- */
24
- class ConsoleLogger {
25
- private globalMinLevel: LogLevel;
26
- private debugNamespaces: Set<string> = new Set();
27
- private debugPatterns: string[] = [];
28
-
29
- constructor() {
30
- // Auto-load config from .env files
31
- autoLoadConfig();
32
-
33
- // Get ENV_PREFIX from environment or use default
34
- const envPrefix = process.env.ENV_PREFIX || '';
35
-
36
- // Read LOGS_LEVEL from environment
37
- // Priority: {ENV_PREFIX}_LOG_LEVEL > LOGS_LEVEL > default 'info'
38
- const logLevelEnv = (envPrefix ? process.env[`${envPrefix}_LOG_LEVEL`] : null) ||
39
- process.env.LOGS_LEVEL ||
40
- 'info';
41
-
42
- // Validate and set global minimum level
43
- if (this.isValidLogLevel(logLevelEnv)) {
44
- this.globalMinLevel = logLevelEnv as LogLevel;
45
- } else {
46
- this.globalMinLevel = 'info';
47
- }
48
-
49
- // Parse DEBUG environment variable for namespace matching
50
- const debugEnv = process.env.DEBUG || '';
51
- if (debugEnv) {
52
- const patterns = debugEnv.split(',').map(p => p.trim());
53
- for (const pattern of patterns) {
54
- if (pattern === '*') {
55
- // Wildcard matches everything
56
- this.debugPatterns.push('*');
57
- } else {
58
- // Store pattern for matching
59
- this.debugPatterns.push(pattern);
60
- }
61
- }
62
- }
63
- }
64
-
65
- /**
66
- * Checks if a string is a valid log level
67
- */
68
- private isValidLogLevel(level: string): level is LogLevel {
69
- return ['verbose', 'debug', 'info', 'warn', 'error'].includes(level);
70
- }
71
-
72
- /**
73
- * Checks if a namespace matches any DEBUG pattern
74
- */
75
- private matchesDebugPattern(namespace: string): boolean {
76
- if (this.debugPatterns.length === 0) {
77
- return false;
78
- }
79
-
80
- for (const pattern of this.debugPatterns) {
81
- if (pattern === '*') {
82
- return true;
83
- }
84
-
85
- // Simple wildcard matching: "my-pkg*" matches "my-pkg", "my-pkg:sub", etc.
86
- if (pattern.endsWith('*')) {
87
- const prefix = pattern.slice(0, -1);
88
- if (namespace.startsWith(prefix)) {
89
- return true;
90
- }
91
- } else if (pattern === namespace) {
92
- return true;
93
- }
94
- }
95
-
96
- return false;
97
- }
98
-
99
- /**
100
- * Determines if a log entry should be printed to console
101
- */
102
- private shouldPrint(level: LogLevel, namespace?: string): boolean {
103
- const levelValue = LOG_LEVEL_VALUES[level];
104
- const minLevelValue = LOG_LEVEL_VALUES[this.globalMinLevel];
105
-
106
- // Rule 1: Print if level >= global minimum level
107
- if (levelValue >= minLevelValue) {
108
- return true;
109
- }
110
-
111
- // Rule 2: Print verbose/debug if namespace matches DEBUG pattern
112
- if ((level === 'verbose' || level === 'debug') && namespace) {
113
- if (this.matchesDebugPattern(namespace)) {
114
- return true;
115
- }
116
- }
117
-
118
- return false;
119
- }
120
-
121
- /**
122
- * Logs a message to console
123
- */
124
- log(level: LogLevel, message: string, namespace?: string, throwError: boolean = false): void {
125
- if (!this.shouldPrint(level, namespace)) {
126
- return;
127
- }
128
-
129
- // Format message with namespace if provided
130
- const formattedMessage = namespace ? `[${namespace}] ${message}` : message;
131
-
132
- // Use appropriate console method
133
- switch (level) {
134
- case 'verbose':
135
- case 'debug':
136
- console.debug(formattedMessage);
137
- break;
138
- case 'info':
139
- console.info(formattedMessage);
140
- break;
141
- case 'warn':
142
- console.warn(formattedMessage);
143
- break;
144
- case 'error':
145
- console.error(formattedMessage);
146
- // Errors throw by default unless explicitly disabled
147
- if (throwError !== false) {
148
- throw new Error(formattedMessage);
149
- }
150
- break;
151
- }
152
- }
153
-
154
- /**
155
- * Convenience methods for each log level
156
- */
157
- verbose(message: string, namespace?: string): void {
158
- this.log('verbose', message, namespace, false);
159
- }
160
-
161
- debug(message: string, namespace?: string): void {
162
- this.log('debug', message, namespace, false);
163
- }
164
-
165
- info(message: string, namespace?: string): void {
166
- this.log('info', message, namespace, false);
167
- }
168
-
169
- warn(message: string, namespace?: string): void {
170
- this.log('warn', message, namespace, false);
171
- }
172
-
173
- error(message: string, namespace?: string, throwError: boolean = true): void {
174
- this.log('error', message, namespace, throwError);
175
- }
176
- }
177
-
178
- // Singleton logger instance
179
- const logger = new ConsoleLogger();
3
+ import { Logger } from 'micro-logs';
180
4
 
181
5
  export interface PaginationOptions {
182
6
  page?: number;
@@ -916,7 +740,7 @@ export class SimpleMongoHelper {
916
740
  public readonly progress: ProgressAPI;
917
741
  private cleanupRegistered: boolean = false;
918
742
  private isDisconnecting: boolean = false;
919
- private namespace: string = 'nx-mongo';
743
+ private logger: Logger;
920
744
 
921
745
  constructor(connectionString: string, retryOptions?: RetryOptions, config?: HelperConfig) {
922
746
  // Store original connection string for database name extraction
@@ -931,6 +755,12 @@ export class SimpleMongoHelper {
931
755
  this.config = config || null;
932
756
  this.progress = new ProgressAPIImpl(this, config?.progress);
933
757
 
758
+ // Initialize logger with micro-logs
759
+ this.logger = new Logger({
760
+ packageName: 'nx-mongo',
761
+ debugNamespace: 'nx-mongo'
762
+ });
763
+
934
764
  // Register automatic cleanup on process exit
935
765
  this.registerCleanup();
936
766
  }
@@ -942,7 +772,7 @@ export class SimpleMongoHelper {
942
772
  */
943
773
  useConfig(config: HelperConfig): this {
944
774
  this.config = config;
945
- logger.debug('Configuration updated', this.namespace);
775
+ this.logger.debug('Configuration updated');
946
776
  return this;
947
777
  }
948
778
 
@@ -952,31 +782,35 @@ export class SimpleMongoHelper {
952
782
  * @returns This instance for method chaining
953
783
  */
954
784
  setNamespace(namespace: string): this {
955
- this.namespace = namespace;
785
+ // Update logger with new namespace
786
+ this.logger = new Logger({
787
+ packageName: 'nx-mongo',
788
+ debugNamespace: namespace
789
+ });
956
790
  return this;
957
791
  }
958
792
 
959
793
  /**
960
- * Logging methods - delegates to console logger
794
+ * Logging methods - delegates to micro-logs Logger
961
795
  */
962
- logVerbose(message: string): void {
963
- logger.verbose(message, this.namespace);
796
+ logVerbose(message: string, data?: any): void {
797
+ this.logger.verbose(message, data);
964
798
  }
965
799
 
966
- logDebug(message: string): void {
967
- logger.debug(message, this.namespace);
800
+ logDebug(message: string, data?: any): void {
801
+ this.logger.debug(message, data);
968
802
  }
969
803
 
970
- logInfo(message: string): void {
971
- logger.info(message, this.namespace);
804
+ logInfo(message: string, data?: any): void {
805
+ this.logger.info(message, data);
972
806
  }
973
807
 
974
- logWarn(message: string): void {
975
- logger.warn(message, this.namespace);
808
+ logWarn(message: string, data?: any): void {
809
+ this.logger.warn(message, data);
976
810
  }
977
811
 
978
- logError(message: string, throwError: boolean = true): void {
979
- logger.error(message, this.namespace, throwError);
812
+ logError(message: string, data?: any): void {
813
+ this.logger.error(message, data);
980
814
  }
981
815
 
982
816
  /**
@@ -1240,10 +1074,12 @@ export class SimpleMongoHelper {
1240
1074
  */
1241
1075
  async initialize(options?: { connectionString?: string; databaseName?: string }): Promise<void> {
1242
1076
  if (this.isInitialized) {
1243
- this.logError('SimpleMongoHelper is already initialized');
1077
+ const errorMsg = 'SimpleMongoHelper is already initialized';
1078
+ this.logError(errorMsg);
1079
+ throw new Error(errorMsg);
1244
1080
  }
1245
1081
 
1246
- logger.debug('Initializing MongoDB connection', this.namespace);
1082
+ this.logger.debug('Initializing MongoDB connection');
1247
1083
 
1248
1084
  // Use provided connection string or original (not stripped) connection string
1249
1085
  const connectionString = options?.connectionString || this.originalConnectionString;
@@ -1260,14 +1096,18 @@ export class SimpleMongoHelper {
1260
1096
 
1261
1097
  // ✅ Validate database name
1262
1098
  if (dbName && !isValidDatabaseName(dbName)) {
1263
- this.logError(`Invalid database name: '${dbName}'. Database names cannot contain: / ? & =`);
1099
+ const errorMsg = `Invalid database name: '${dbName}'. Database names cannot contain: / ? & =`;
1100
+ this.logError(errorMsg);
1101
+ throw new Error(errorMsg);
1264
1102
  }
1265
1103
 
1266
1104
  if (!dbName) {
1267
- this.logError('Database name is required. Provide databaseName parameter or include it in connection string path.');
1105
+ const errorMsg = 'Database name is required. Provide databaseName parameter or include it in connection string path.';
1106
+ this.logError(errorMsg);
1107
+ throw new Error(errorMsg);
1268
1108
  }
1269
1109
 
1270
- logger.debug(`Using database: ${dbName}`, this.namespace);
1110
+ this.logger.debug(`Using database: ${dbName}`);
1271
1111
 
1272
1112
  // ✅ Clean connection string if databaseName was provided separately
1273
1113
  // (to avoid using database name from URI path when we have explicit databaseName)
@@ -1278,32 +1118,34 @@ export class SimpleMongoHelper {
1278
1118
  let lastError: Error | null = null;
1279
1119
  for (let attempt = 0; attempt <= this.retryOptions.maxRetries!; attempt++) {
1280
1120
  try {
1281
- logger.verbose(`Connection attempt ${attempt + 1}/${this.retryOptions.maxRetries! + 1}`, this.namespace);
1121
+ this.logger.verbose(`Connection attempt ${attempt + 1}/${this.retryOptions.maxRetries! + 1}`);
1282
1122
  this.client = new MongoClient(cleanUri);
1283
1123
  await this.client.connect();
1284
1124
  // Use the resolved database name
1285
1125
  this.db = this.client.db(dbName);
1286
1126
  this.isInitialized = true;
1287
- logger.info(`Successfully connected to MongoDB database: ${dbName}`, this.namespace);
1127
+ this.logger.info(`Successfully connected to MongoDB database: ${dbName}`);
1288
1128
  return;
1289
1129
  } catch (error) {
1290
1130
  lastError = error instanceof Error ? error : new Error(String(error));
1291
1131
  this.client = null;
1292
1132
  this.db = null;
1293
1133
 
1294
- logger.warn(`Connection attempt ${attempt + 1} failed: ${lastError.message}`, this.namespace);
1134
+ this.logger.warn(`Connection attempt ${attempt + 1} failed: ${lastError.message}`);
1295
1135
 
1296
1136
  if (attempt < this.retryOptions.maxRetries!) {
1297
1137
  const delay = this.retryOptions.exponentialBackoff
1298
1138
  ? this.retryOptions.retryDelay! * Math.pow(2, attempt)
1299
1139
  : this.retryOptions.retryDelay!;
1300
- logger.debug(`Retrying in ${delay}ms...`, this.namespace);
1140
+ this.logger.debug(`Retrying in ${delay}ms...`);
1301
1141
  await new Promise(resolve => setTimeout(resolve, delay));
1302
1142
  }
1303
1143
  }
1304
1144
  }
1305
1145
 
1306
- this.logError(`Failed to initialize MongoDB connection after ${this.retryOptions.maxRetries! + 1} attempts: ${lastError?.message}`);
1146
+ const errorMsg = `Failed to initialize MongoDB connection after ${this.retryOptions.maxRetries! + 1} attempts: ${lastError?.message}`;
1147
+ this.logError(errorMsg);
1148
+ throw new Error(errorMsg);
1307
1149
  }
1308
1150
 
1309
1151
  /**