@heliyos/heliyos-api-core 1.0.13 → 1.0.15
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/mongoose.d.ts +2 -2
- package/dist/mongoose.js +150 -50
- package/package.json +1 -1
package/dist/mongoose.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import mongoose, {
|
|
1
|
+
import mongoose, { Model, Schema, FilterQuery, UpdateQuery } from "mongoose";
|
|
2
2
|
export * from "mongoose";
|
|
3
3
|
export interface Pagination<T> {
|
|
4
4
|
data: T[];
|
|
@@ -16,7 +16,7 @@ declare module "mongoose" {
|
|
|
16
16
|
}
|
|
17
17
|
export declare const mongooseConnection: Promise<mongoose.Connection>;
|
|
18
18
|
export declare const mongooseReplicaConnection: Promise<mongoose.Connection>;
|
|
19
|
-
export declare const createModel: <T extends mongoose.Document<unknown, any, any>>(name: string, schema: Schema
|
|
19
|
+
export declare const createModel: <T extends mongoose.Document<unknown, any, any>>(name: string, schema: Schema) => mongoose.Model<T, {}, {}, {}, mongoose.IfAny<T, any, mongoose.Document<unknown, {}, T> & mongoose.Default__v<mongoose.Require_id<T>>>, any>;
|
|
20
20
|
export declare const createBulkOperations: <T>(operations: {
|
|
21
21
|
updateOne?: {
|
|
22
22
|
filter: mongoose.FilterQuery<T>;
|
package/dist/mongoose.js
CHANGED
|
@@ -10,18 +10,6 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
10
10
|
if (k2 === undefined) k2 = k;
|
|
11
11
|
o[k2] = m[k];
|
|
12
12
|
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
13
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
26
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
15
|
};
|
|
@@ -34,9 +22,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
34
22
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
35
23
|
});
|
|
36
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
37
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
29
|
exports.closeConnections = exports.checkDatabaseHealth = exports.upsertDocument = exports.safeDelete = exports.withTransaction = exports.ensureIndexes = exports.createBulkOperations = exports.createModel = exports.mongooseReplicaConnection = exports.mongooseConnection = void 0;
|
|
39
|
-
const mongoose_1 =
|
|
30
|
+
const mongoose_1 = __importDefault(require("mongoose"));
|
|
40
31
|
const ssm_1 = require("./ssm");
|
|
41
32
|
const logger_1 = require("./logger");
|
|
42
33
|
// Export commonly used mongoose types
|
|
@@ -45,36 +36,111 @@ __exportStar(require("mongoose"), exports);
|
|
|
45
36
|
let cachedConnection;
|
|
46
37
|
let cachedReplicaConnection;
|
|
47
38
|
const connectionOptions = {
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
// Connection timeouts
|
|
40
|
+
serverSelectionTimeoutMS: 60000,
|
|
41
|
+
connectTimeoutMS: 60000,
|
|
42
|
+
socketTimeoutMS: 360000,
|
|
43
|
+
// Connection pool
|
|
44
|
+
maxPoolSize: 50,
|
|
45
|
+
minPoolSize: 5,
|
|
46
|
+
// Reliability settings
|
|
50
47
|
retryWrites: true,
|
|
48
|
+
retryReads: true,
|
|
49
|
+
// Performance settings
|
|
50
|
+
heartbeatFrequencyMS: 10000,
|
|
51
|
+
// Monitoring
|
|
52
|
+
monitorCommands: true,
|
|
51
53
|
};
|
|
54
|
+
const MAX_RETRY_ATTEMPTS = 5;
|
|
55
|
+
const INITIAL_RETRY_DELAY = 1000; // 1 second
|
|
56
|
+
const connectWithRetry = (mongoUrl, attempt = 1) => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
+
try {
|
|
58
|
+
logger_1.logger.info(`Attempting to connect to MongoDB (attempt ${attempt}/${MAX_RETRY_ATTEMPTS})`);
|
|
59
|
+
const connection = mongoose_1.default.createConnection(mongoUrl, connectionOptions);
|
|
60
|
+
// Wait for connection to be ready
|
|
61
|
+
yield new Promise((resolve, reject) => {
|
|
62
|
+
connection.once("connected", () => resolve());
|
|
63
|
+
connection.once("error", (err) => reject(err));
|
|
64
|
+
});
|
|
65
|
+
return connection;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (attempt >= MAX_RETRY_ATTEMPTS) {
|
|
69
|
+
logger_1.logger.error("Max retry attempts reached. Failed to connect to MongoDB");
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const delay = INITIAL_RETRY_DELAY * Math.pow(2, attempt - 1);
|
|
73
|
+
logger_1.logger.warn(`Connection attempt ${attempt} failed. Retrying in ${delay}ms...`);
|
|
74
|
+
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
75
|
+
return connectWithRetry(mongoUrl, attempt + 1);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
52
78
|
const mongooseConnected = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
79
|
if (cachedConnection) {
|
|
54
|
-
|
|
55
|
-
|
|
80
|
+
// Use type assertion to check connection state
|
|
81
|
+
if (cachedConnection.readyState ===
|
|
82
|
+
mongoose_1.default.ConnectionStates.connected) {
|
|
83
|
+
logger_1.logger.info("Using cached MongoDB Connection");
|
|
84
|
+
return cachedConnection;
|
|
85
|
+
}
|
|
86
|
+
// Try to reconnect using existing connection
|
|
87
|
+
try {
|
|
88
|
+
yield cachedConnection.openUri(process.env.MONGO_DATABASE_URL, connectionOptions);
|
|
89
|
+
if (cachedConnection.readyState ===
|
|
90
|
+
mongoose_1.default.ConnectionStates.connected) {
|
|
91
|
+
logger_1.logger.info("Successfully reconnected using cached connection");
|
|
92
|
+
return cachedConnection;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
logger_1.logger.warn("Failed to reconnect using cached connection, will create new one");
|
|
97
|
+
}
|
|
56
98
|
}
|
|
57
99
|
let mongoUrl;
|
|
58
100
|
const nodeEnv = process.env.NODE_ENV;
|
|
59
|
-
if (nodeEnv === "local") {
|
|
101
|
+
if (nodeEnv === "local" || nodeEnv === "development") {
|
|
60
102
|
mongoUrl = process.env.MONGO_DATABASE_URL;
|
|
103
|
+
// Add logging to debug URL
|
|
104
|
+
logger_1.logger.info(`Connecting to MongoDB URL: ${mongoUrl.replace(/\/\/[^@]*@/, "//****:****@")}`);
|
|
61
105
|
}
|
|
62
106
|
else if (["development", "production"].includes(nodeEnv)) {
|
|
63
107
|
const secrets = yield (0, ssm_1.getSecretsManagerSecret)(process.env.ENV_SECRET_NAME);
|
|
64
108
|
mongoUrl = secrets.MONGO_DATABASE_URL;
|
|
65
109
|
}
|
|
66
110
|
else {
|
|
67
|
-
logger_1.logger.
|
|
111
|
+
logger_1.logger.error(`Invalid NODE_ENV: ${nodeEnv}`);
|
|
68
112
|
return null;
|
|
69
113
|
}
|
|
70
114
|
if (!mongoUrl) {
|
|
71
|
-
logger_1.logger.
|
|
115
|
+
logger_1.logger.error("MONGO_DATABASE_URL not set");
|
|
72
116
|
return null;
|
|
73
117
|
}
|
|
74
|
-
logger_1.logger.info("
|
|
75
|
-
const connection =
|
|
118
|
+
logger_1.logger.info("Creating new MongoDB Connection");
|
|
119
|
+
const connection = yield connectWithRetry(mongoUrl);
|
|
120
|
+
if (!connection) {
|
|
121
|
+
logger_1.logger.error("Failed to establish MongoDB connection after retries");
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
// Enhanced error handling
|
|
76
125
|
connection.on("error", (err) => {
|
|
77
|
-
|
|
126
|
+
logger_1.logger.error("MongoDB connection error:", err);
|
|
127
|
+
// Attempt to reconnect after a delay
|
|
128
|
+
setTimeout(() => {
|
|
129
|
+
if (connection.readyState !== mongoose_1.default.ConnectionStates.connected) {
|
|
130
|
+
logger_1.logger.info("Attempting to reconnect...");
|
|
131
|
+
connection.openUri(mongoUrl, connectionOptions);
|
|
132
|
+
}
|
|
133
|
+
}, 5000);
|
|
134
|
+
});
|
|
135
|
+
// Add connection monitoring
|
|
136
|
+
connection.on("disconnected", () => {
|
|
137
|
+
logger_1.logger.warn("MongoDB disconnected. Attempting to reconnect...");
|
|
138
|
+
});
|
|
139
|
+
connection.on("reconnected", () => {
|
|
140
|
+
logger_1.logger.info("MongoDB reconnected successfully");
|
|
141
|
+
});
|
|
142
|
+
connection.on("connected", () => {
|
|
143
|
+
logger_1.logger.info("MongoDB connected successfully");
|
|
78
144
|
});
|
|
79
145
|
cachedConnection = connection;
|
|
80
146
|
return connection;
|
|
@@ -102,7 +168,11 @@ const replicaMongooseConnected = () => __awaiter(void 0, void 0, void 0, functio
|
|
|
102
168
|
return null;
|
|
103
169
|
}
|
|
104
170
|
logger_1.logger.info("New MongoDB Replica Connection");
|
|
105
|
-
const connection =
|
|
171
|
+
const connection = yield connectWithRetry(replicaUrl);
|
|
172
|
+
if (!connection) {
|
|
173
|
+
logger_1.logger.error("Failed to establish MongoDB replica connection after retries");
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
106
176
|
connection.on("error", (err) => {
|
|
107
177
|
console.error("MongoDB replica connection error:", err);
|
|
108
178
|
});
|
|
@@ -127,34 +197,31 @@ mongoose_1.default.Query.prototype.paginate = function (page = 1, limit = 10) {
|
|
|
127
197
|
exports.mongooseConnection = mongooseConnected();
|
|
128
198
|
exports.mongooseReplicaConnection = replicaMongooseConnected();
|
|
129
199
|
// Helper for creating typed models
|
|
130
|
-
const createModel = (name, schema
|
|
131
|
-
// Add debug logging
|
|
200
|
+
const createModel = (name, schema) => {
|
|
132
201
|
logger_1.logger.info(`Creating model ${name}`);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
logger_1.logger.info(`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
202
|
+
try {
|
|
203
|
+
// If no cached connection exists, create one
|
|
204
|
+
if (!cachedConnection) {
|
|
205
|
+
logger_1.logger.info(`No cached connection found, establishing new connection for model ${name}`);
|
|
206
|
+
let mongoUrl = process.env.MONGO_DATABASE_URL;
|
|
207
|
+
if (!mongoUrl) {
|
|
208
|
+
logger_1.logger.error("MONGO_DATABASE_URL not set");
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
cachedConnection = mongoose_1.default.createConnection(mongoUrl, connectionOptions);
|
|
212
|
+
cachedConnection.on("error", (err) => {
|
|
213
|
+
console.error("MongoDB connection error:", err);
|
|
214
|
+
});
|
|
215
|
+
logger_1.logger.info(`New connection established for model ${name}`);
|
|
142
216
|
}
|
|
217
|
+
// Use the cached connection
|
|
218
|
+
logger_1.logger.info(`Creating model ${name} with connection`);
|
|
219
|
+
return cachedConnection.model(name, schema);
|
|
143
220
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
.then((conn) => {
|
|
147
|
-
if (!conn) {
|
|
148
|
-
logger_1.logger.info(`Database connection not established for model: ${name}`);
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
logger_1.logger.info(`Creating model ${name} with async connection`);
|
|
152
|
-
return conn.model(name, schema);
|
|
153
|
-
})
|
|
154
|
-
.catch((error) => {
|
|
155
|
-
logger_1.logger.info(`Error creating model ${name}:`, error);
|
|
221
|
+
catch (error) {
|
|
222
|
+
logger_1.logger.error(`Error creating model ${name}:`, error);
|
|
156
223
|
return null;
|
|
157
|
-
}
|
|
224
|
+
}
|
|
158
225
|
};
|
|
159
226
|
exports.createModel = createModel;
|
|
160
227
|
// Helper for bulk operations with better typing
|
|
@@ -212,8 +279,8 @@ exports.upsertDocument = upsertDocument;
|
|
|
212
279
|
const checkDatabaseHealth = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
213
280
|
try {
|
|
214
281
|
const [primary, replica] = yield Promise.all([
|
|
215
|
-
exports.mongooseConnection.then((conn) => conn.readyState ===
|
|
216
|
-
exports.mongooseReplicaConnection.then((conn) => { var _a; return (_a = (conn === null || conn === void 0 ? void 0 : conn.readyState) ===
|
|
282
|
+
exports.mongooseConnection.then((conn) => conn.readyState === mongoose_1.default.ConnectionStates.connected),
|
|
283
|
+
exports.mongooseReplicaConnection.then((conn) => { var _a; return (_a = (conn === null || conn === void 0 ? void 0 : conn.readyState) === mongoose_1.default.ConnectionStates.connected) !== null && _a !== void 0 ? _a : false; }),
|
|
217
284
|
]);
|
|
218
285
|
return { primary, replica };
|
|
219
286
|
}
|
|
@@ -240,3 +307,36 @@ const closeConnections = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
240
307
|
}
|
|
241
308
|
});
|
|
242
309
|
exports.closeConnections = closeConnections;
|
|
310
|
+
// Add this new utility function
|
|
311
|
+
const startConnectionMonitoring = (checkInterval = 30000) => {
|
|
312
|
+
let isReconnecting = false;
|
|
313
|
+
setInterval(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
314
|
+
try {
|
|
315
|
+
if (isReconnecting)
|
|
316
|
+
return;
|
|
317
|
+
const conn = yield exports.mongooseConnection;
|
|
318
|
+
if (!conn ||
|
|
319
|
+
conn.readyState !== mongoose_1.default.ConnectionStates.connected) {
|
|
320
|
+
isReconnecting = true;
|
|
321
|
+
logger_1.logger.warn("Database connection is not healthy");
|
|
322
|
+
try {
|
|
323
|
+
if (cachedConnection) {
|
|
324
|
+
yield cachedConnection.openUri(process.env.MONGO_DATABASE_URL, connectionOptions);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
catch (reconnectError) {
|
|
328
|
+
logger_1.logger.error("Failed to reconnect:", reconnectError);
|
|
329
|
+
}
|
|
330
|
+
finally {
|
|
331
|
+
isReconnecting = false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
isReconnecting = false;
|
|
337
|
+
logger_1.logger.error("Connection monitoring error:", error);
|
|
338
|
+
}
|
|
339
|
+
}), checkInterval);
|
|
340
|
+
};
|
|
341
|
+
// Call this when your application starts
|
|
342
|
+
startConnectionMonitoring();
|