nx-mongo 3.8.1 → 3.8.3
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/dist/simpleMongoHelper.d.ts +23 -1
- package/dist/simpleMongoHelper.d.ts.map +1 -1
- package/dist/simpleMongoHelper.js +314 -13
- package/dist/simpleMongoHelper.js.map +1 -1
- package/package.json +3 -2
- package/src/simpleMongoHelper.ts +365 -12
- package/test-connection.ts +0 -47
package/src/simpleMongoHelper.ts
CHANGED
|
@@ -1,5 +1,182 @@
|
|
|
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
180
|
|
|
4
181
|
export interface PaginationOptions {
|
|
5
182
|
page?: number;
|
|
@@ -351,6 +528,94 @@ export function computeSignature(
|
|
|
351
528
|
return hash.digest('hex');
|
|
352
529
|
}
|
|
353
530
|
|
|
531
|
+
/**
|
|
532
|
+
* Extracts database name from MongoDB connection string URI.
|
|
533
|
+
* Only extracts from pathname, NOT from query parameters.
|
|
534
|
+
* @param uri - MongoDB connection string
|
|
535
|
+
* @returns Database name or null if not found
|
|
536
|
+
*/
|
|
537
|
+
function extractDatabaseNameFromUri(uri: string): string | null {
|
|
538
|
+
try {
|
|
539
|
+
const url = new URL(uri);
|
|
540
|
+
// Only extract from pathname, NOT from query parameters
|
|
541
|
+
const dbName = url.pathname ? url.pathname.slice(1) : null; // Remove leading /
|
|
542
|
+
|
|
543
|
+
// Validate: database name should not contain query parameter values
|
|
544
|
+
if (dbName && (dbName.includes('?') || dbName.includes('&') || dbName.includes('='))) {
|
|
545
|
+
// This means we're incorrectly parsing query params
|
|
546
|
+
return null; // Don't use invalid database name
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return dbName || null;
|
|
550
|
+
} catch (error) {
|
|
551
|
+
// Fallback: regex approach
|
|
552
|
+
// Match: mongodb://.../databaseName?query
|
|
553
|
+
// Don't match: mongodb://...?authSource=admin (no path)
|
|
554
|
+
const pathMatch = uri.match(/mongodb:\/\/[^\/]+\/([^\/\?]+)(\?|$)/);
|
|
555
|
+
if (pathMatch && pathMatch[1]) {
|
|
556
|
+
return pathMatch[1];
|
|
557
|
+
}
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Validates a MongoDB database name according to MongoDB rules.
|
|
564
|
+
* @param dbName - Database name to validate
|
|
565
|
+
* @returns true if valid, false otherwise
|
|
566
|
+
*/
|
|
567
|
+
function isValidDatabaseName(dbName: string): boolean {
|
|
568
|
+
if (!dbName || typeof dbName !== 'string') {
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Database names cannot contain: / ? & =
|
|
573
|
+
// These are URL/query parameter characters
|
|
574
|
+
if (dbName.includes('/') || dbName.includes('?') || dbName.includes('&') || dbName.includes('=')) {
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Database names cannot be empty or just whitespace
|
|
579
|
+
if (dbName.trim().length === 0) {
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// MongoDB database name rules
|
|
584
|
+
// Cannot contain: / \ . " $ * < > : | ?
|
|
585
|
+
const invalidChars = /[\/\\\.\"\$*<>:|?]/;
|
|
586
|
+
if (invalidChars.test(dbName)) {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Cannot start or end with space or dot
|
|
591
|
+
if (dbName.trim() !== dbName || dbName.startsWith('.') || dbName.endsWith('.')) {
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Cleans a connection string by removing database name from URI path.
|
|
600
|
+
* Preserves query parameters (authSource, etc.).
|
|
601
|
+
* @param uri - MongoDB connection string
|
|
602
|
+
* @returns Cleaned connection string without database name in path
|
|
603
|
+
*/
|
|
604
|
+
function cleanConnectionString(uri: string): string {
|
|
605
|
+
// Remove database name from URI path
|
|
606
|
+
// Preserve query parameters (authSource, etc.)
|
|
607
|
+
try {
|
|
608
|
+
const url = new URL(uri);
|
|
609
|
+
url.pathname = ''; // Remove database name from path
|
|
610
|
+
return url.toString().replace(/\/\?/g, '?').replace(/\/$/, '');
|
|
611
|
+
} catch (error) {
|
|
612
|
+
// Fallback: regex approach
|
|
613
|
+
return uri.replace(/\/[^\/\?]+(\?|$)/, (match, query) => {
|
|
614
|
+
return query === '?' ? '?' : '';
|
|
615
|
+
}).replace(/\/$/, '');
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
354
619
|
/**
|
|
355
620
|
* Internal class that implements the ProgressAPI interface for stage tracking.
|
|
356
621
|
*/
|
|
@@ -642,6 +907,7 @@ class ProgressAPIImpl implements ProgressAPI {
|
|
|
642
907
|
|
|
643
908
|
export class SimpleMongoHelper {
|
|
644
909
|
private connectionString: string;
|
|
910
|
+
private originalConnectionString: string; // Store original for database name extraction
|
|
645
911
|
private client: MongoClient | null = null;
|
|
646
912
|
protected db: Db | null = null;
|
|
647
913
|
private isInitialized: boolean = false;
|
|
@@ -650,9 +916,12 @@ export class SimpleMongoHelper {
|
|
|
650
916
|
public readonly progress: ProgressAPI;
|
|
651
917
|
private cleanupRegistered: boolean = false;
|
|
652
918
|
private isDisconnecting: boolean = false;
|
|
919
|
+
private namespace: string = 'nx-mongo';
|
|
653
920
|
|
|
654
921
|
constructor(connectionString: string, retryOptions?: RetryOptions, config?: HelperConfig) {
|
|
655
|
-
//
|
|
922
|
+
// Store original connection string for database name extraction
|
|
923
|
+
this.originalConnectionString = connectionString;
|
|
924
|
+
// Strip database name from connection string if present (for backward compatibility)
|
|
656
925
|
this.connectionString = this.stripDatabaseFromConnectionString(connectionString);
|
|
657
926
|
this.retryOptions = {
|
|
658
927
|
maxRetries: retryOptions?.maxRetries ?? 3,
|
|
@@ -673,9 +942,43 @@ export class SimpleMongoHelper {
|
|
|
673
942
|
*/
|
|
674
943
|
useConfig(config: HelperConfig): this {
|
|
675
944
|
this.config = config;
|
|
945
|
+
logger.debug('Configuration updated', this.namespace);
|
|
946
|
+
return this;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Sets the logging namespace for this instance
|
|
951
|
+
* @param namespace - Namespace string for logging
|
|
952
|
+
* @returns This instance for method chaining
|
|
953
|
+
*/
|
|
954
|
+
setNamespace(namespace: string): this {
|
|
955
|
+
this.namespace = namespace;
|
|
676
956
|
return this;
|
|
677
957
|
}
|
|
678
958
|
|
|
959
|
+
/**
|
|
960
|
+
* Logging methods - delegates to console logger
|
|
961
|
+
*/
|
|
962
|
+
logVerbose(message: string): void {
|
|
963
|
+
logger.verbose(message, this.namespace);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
logDebug(message: string): void {
|
|
967
|
+
logger.debug(message, this.namespace);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
logInfo(message: string): void {
|
|
971
|
+
logger.info(message, this.namespace);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
logWarn(message: string): void {
|
|
975
|
+
logger.warn(message, this.namespace);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
logError(message: string, throwError: boolean = true): void {
|
|
979
|
+
logger.error(message, this.namespace, throwError);
|
|
980
|
+
}
|
|
981
|
+
|
|
679
982
|
/**
|
|
680
983
|
* Tests the MongoDB connection and returns detailed error information if it fails.
|
|
681
984
|
* This method does not establish a persistent connection - use initialize() for that.
|
|
@@ -930,37 +1233,77 @@ export class SimpleMongoHelper {
|
|
|
930
1233
|
/**
|
|
931
1234
|
* Establishes MongoDB connection internally with retry logic.
|
|
932
1235
|
* Must be called before using other methods.
|
|
1236
|
+
* @param options - Optional initialization options
|
|
1237
|
+
* @param options.connectionString - Connection string (overrides constructor value if provided)
|
|
1238
|
+
* @param options.databaseName - Database name (takes priority over URI extraction)
|
|
933
1239
|
* @throws Error if connection fails or if already initialized
|
|
934
1240
|
*/
|
|
935
|
-
async initialize(): Promise<void> {
|
|
1241
|
+
async initialize(options?: { connectionString?: string; databaseName?: string }): Promise<void> {
|
|
936
1242
|
if (this.isInitialized) {
|
|
937
|
-
|
|
1243
|
+
this.logError('SimpleMongoHelper is already initialized');
|
|
938
1244
|
}
|
|
939
1245
|
|
|
1246
|
+
logger.debug('Initializing MongoDB connection', this.namespace);
|
|
1247
|
+
|
|
1248
|
+
// Use provided connection string or original (not stripped) connection string
|
|
1249
|
+
const connectionString = options?.connectionString || this.originalConnectionString;
|
|
1250
|
+
|
|
1251
|
+
// ✅ Priority 1: Use provided databaseName parameter
|
|
1252
|
+
let dbName: string | undefined = options?.databaseName;
|
|
1253
|
+
const dbNameProvided = !!dbName;
|
|
1254
|
+
|
|
1255
|
+
// ✅ Priority 2: Only extract from URI if databaseName not provided
|
|
1256
|
+
if (!dbName) {
|
|
1257
|
+
const extractedDbName = extractDatabaseNameFromUri(connectionString);
|
|
1258
|
+
dbName = extractedDbName || undefined;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
// ✅ Validate database name
|
|
1262
|
+
if (dbName && !isValidDatabaseName(dbName)) {
|
|
1263
|
+
this.logError(`Invalid database name: '${dbName}'. Database names cannot contain: / ? & =`);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
if (!dbName) {
|
|
1267
|
+
this.logError('Database name is required. Provide databaseName parameter or include it in connection string path.');
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
logger.debug(`Using database: ${dbName}`, this.namespace);
|
|
1271
|
+
|
|
1272
|
+
// ✅ Clean connection string if databaseName was provided separately
|
|
1273
|
+
// (to avoid using database name from URI path when we have explicit databaseName)
|
|
1274
|
+
const cleanUri = dbNameProvided ?
|
|
1275
|
+
cleanConnectionString(connectionString) :
|
|
1276
|
+
connectionString;
|
|
1277
|
+
|
|
940
1278
|
let lastError: Error | null = null;
|
|
941
1279
|
for (let attempt = 0; attempt <= this.retryOptions.maxRetries!; attempt++) {
|
|
942
1280
|
try {
|
|
943
|
-
this.
|
|
1281
|
+
logger.verbose(`Connection attempt ${attempt + 1}/${this.retryOptions.maxRetries! + 1}`, this.namespace);
|
|
1282
|
+
this.client = new MongoClient(cleanUri);
|
|
944
1283
|
await this.client.connect();
|
|
945
|
-
//
|
|
946
|
-
this.db = this.client.db(
|
|
1284
|
+
// Use the resolved database name
|
|
1285
|
+
this.db = this.client.db(dbName);
|
|
947
1286
|
this.isInitialized = true;
|
|
1287
|
+
logger.info(`Successfully connected to MongoDB database: ${dbName}`, this.namespace);
|
|
948
1288
|
return;
|
|
949
1289
|
} catch (error) {
|
|
950
1290
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
951
1291
|
this.client = null;
|
|
952
1292
|
this.db = null;
|
|
953
1293
|
|
|
1294
|
+
logger.warn(`Connection attempt ${attempt + 1} failed: ${lastError.message}`, this.namespace);
|
|
1295
|
+
|
|
954
1296
|
if (attempt < this.retryOptions.maxRetries!) {
|
|
955
1297
|
const delay = this.retryOptions.exponentialBackoff
|
|
956
1298
|
? this.retryOptions.retryDelay! * Math.pow(2, attempt)
|
|
957
1299
|
: this.retryOptions.retryDelay!;
|
|
1300
|
+
logger.debug(`Retrying in ${delay}ms...`, this.namespace);
|
|
958
1301
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
959
1302
|
}
|
|
960
1303
|
}
|
|
961
1304
|
}
|
|
962
1305
|
|
|
963
|
-
|
|
1306
|
+
this.logError(`Failed to initialize MongoDB connection after ${this.retryOptions.maxRetries! + 1} attempts: ${lastError?.message}`);
|
|
964
1307
|
}
|
|
965
1308
|
|
|
966
1309
|
/**
|
|
@@ -1020,7 +1363,9 @@ export class SimpleMongoHelper {
|
|
|
1020
1363
|
const results = await cursor.toArray();
|
|
1021
1364
|
return results;
|
|
1022
1365
|
} catch (error) {
|
|
1023
|
-
|
|
1366
|
+
const errorMsg = `Failed to load collection '${collectionName}': ${error instanceof Error ? error.message : String(error)}`;
|
|
1367
|
+
this.logError(errorMsg);
|
|
1368
|
+
throw new Error(errorMsg); // TypeScript control flow
|
|
1024
1369
|
}
|
|
1025
1370
|
}
|
|
1026
1371
|
|
|
@@ -1057,7 +1402,9 @@ export class SimpleMongoHelper {
|
|
|
1057
1402
|
const result = await collection.findOne(query, findOptions);
|
|
1058
1403
|
return result;
|
|
1059
1404
|
} catch (error) {
|
|
1060
|
-
|
|
1405
|
+
const errorMsg = `Failed to find document in collection '${collectionName}': ${error instanceof Error ? error.message : String(error)}`;
|
|
1406
|
+
this.logError(errorMsg);
|
|
1407
|
+
throw new Error(errorMsg); // TypeScript control flow
|
|
1061
1408
|
}
|
|
1062
1409
|
}
|
|
1063
1410
|
|
|
@@ -1092,7 +1439,9 @@ export class SimpleMongoHelper {
|
|
|
1092
1439
|
return result;
|
|
1093
1440
|
}
|
|
1094
1441
|
} catch (error) {
|
|
1095
|
-
|
|
1442
|
+
const errorMsg = `Failed to insert into collection '${collectionName}': ${error instanceof Error ? error.message : String(error)}`;
|
|
1443
|
+
this.logError(errorMsg);
|
|
1444
|
+
throw new Error(errorMsg); // TypeScript control flow
|
|
1096
1445
|
}
|
|
1097
1446
|
}
|
|
1098
1447
|
|
|
@@ -1131,7 +1480,9 @@ export class SimpleMongoHelper {
|
|
|
1131
1480
|
return result;
|
|
1132
1481
|
}
|
|
1133
1482
|
} catch (error) {
|
|
1134
|
-
|
|
1483
|
+
const errorMsg = `Failed to update collection '${collectionName}': ${error instanceof Error ? error.message : String(error)}`;
|
|
1484
|
+
this.logError(errorMsg);
|
|
1485
|
+
throw new Error(errorMsg); // TypeScript control flow
|
|
1135
1486
|
}
|
|
1136
1487
|
}
|
|
1137
1488
|
|
|
@@ -1165,7 +1516,9 @@ export class SimpleMongoHelper {
|
|
|
1165
1516
|
return result;
|
|
1166
1517
|
}
|
|
1167
1518
|
} catch (error) {
|
|
1168
|
-
|
|
1519
|
+
const errorMsg = `Failed to delete from collection '${collectionName}': ${error instanceof Error ? error.message : String(error)}`;
|
|
1520
|
+
this.logError(errorMsg);
|
|
1521
|
+
throw new Error(errorMsg); // TypeScript control flow
|
|
1169
1522
|
}
|
|
1170
1523
|
}
|
|
1171
1524
|
|
package/test-connection.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { SimpleMongoHelper } from './src/simpleMongoHelper';
|
|
2
|
-
|
|
3
|
-
async function testConnection() {
|
|
4
|
-
// Test with the connection string from the blocker report
|
|
5
|
-
const connectionString = 'mongodb://localhost:27017/';
|
|
6
|
-
const helper = new SimpleMongoHelper(connectionString);
|
|
7
|
-
|
|
8
|
-
console.log('Testing MongoDB connection...');
|
|
9
|
-
console.log(`Connection String: ${connectionString}`);
|
|
10
|
-
console.log(`Database: server`);
|
|
11
|
-
console.log('');
|
|
12
|
-
|
|
13
|
-
const result = await helper.testConnection();
|
|
14
|
-
|
|
15
|
-
if (result.success) {
|
|
16
|
-
console.log('✅ Connection test passed!');
|
|
17
|
-
console.log('You can now call helper.initialize() to establish a persistent connection.');
|
|
18
|
-
} else {
|
|
19
|
-
console.error('❌ Connection test failed!');
|
|
20
|
-
console.error('');
|
|
21
|
-
console.error('Error Type:', result.error?.type);
|
|
22
|
-
console.error('Error Message:', result.error?.message);
|
|
23
|
-
console.error('Error Details:', result.error?.details);
|
|
24
|
-
console.error('');
|
|
25
|
-
|
|
26
|
-
// Show full error object for debugging
|
|
27
|
-
console.error('Full error object:');
|
|
28
|
-
console.error(JSON.stringify(result.error, null, 2));
|
|
29
|
-
|
|
30
|
-
// Provide troubleshooting tips
|
|
31
|
-
console.error('');
|
|
32
|
-
console.error('Troubleshooting tips:');
|
|
33
|
-
if (result.error?.type === 'connection_failed') {
|
|
34
|
-
console.error(' - Try using 127.0.0.1 instead of localhost');
|
|
35
|
-
console.error(' - Verify MongoDB is running: mongosh --eval "db.version()"');
|
|
36
|
-
console.error(' - Check if MongoDB is listening on port 27017');
|
|
37
|
-
console.error(' - Check Windows Firewall settings');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Run the test
|
|
43
|
-
testConnection().catch((error) => {
|
|
44
|
-
console.error('Unexpected error:', error);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
});
|
|
47
|
-
|