cloud-ide-model-schema 1.1.132 → 1.1.136
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/lib/config/database.d.ts +4 -0
- package/lib/config/database.js +161 -13
- package/lib/schema/fees/fee_receipt_template.js +1 -1
- package/lib/schema/fees/fee_structure.js +1 -1
- package/lib/schema/notifications/notification.js +7 -9
- package/lib/schema/notifications/notification_preference.js +1 -3
- package/lib/schema/notifications/notification_template.js +1 -4
- package/lib/schema/system/api_keys.js +1 -1
- package/lib/schema/system/backup_jobs.js +1 -1
- package/lib/schema/system/backup_policies.js +1 -1
- package/lib/schema/system/subscription_features.js +1 -1
- package/lib/schema/system/subscription_plans.js +1 -1
- package/package.json +1 -1
package/lib/config/database.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
|
+
/**
|
|
3
|
+
* Connect to MongoDB with robust error handling and retry logic
|
|
4
|
+
* This function is idempotent - safe to call multiple times
|
|
5
|
+
*/
|
|
2
6
|
declare function connectDB(): Promise<void>;
|
|
3
7
|
declare const customUUID: () => string;
|
|
4
8
|
export { connectDB, customUUID };
|
package/lib/config/database.js
CHANGED
|
@@ -40,31 +40,179 @@ exports.customUUID = void 0;
|
|
|
40
40
|
exports.connectDB = connectDB;
|
|
41
41
|
var mongoose = require("mongoose");
|
|
42
42
|
require("dotenv/config");
|
|
43
|
+
// Connection state tracking
|
|
44
|
+
var isConnecting = false;
|
|
45
|
+
var connectionRetryCount = 0;
|
|
46
|
+
var MAX_RETRY_ATTEMPTS = 10;
|
|
47
|
+
var INITIAL_RETRY_DELAY = 1000; // 1 second
|
|
48
|
+
var MAX_RETRY_DELAY = 30000; // 30 seconds
|
|
49
|
+
var retryTimeout = null;
|
|
50
|
+
/**
|
|
51
|
+
* Check if MongoDB is already connected
|
|
52
|
+
*/
|
|
53
|
+
function isConnected() {
|
|
54
|
+
return mongoose.connection.readyState === 1; // 1 = connected
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if MongoDB is connecting
|
|
58
|
+
*/
|
|
59
|
+
function isConnectingState() {
|
|
60
|
+
return mongoose.connection.readyState === 2; // 2 = connecting
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Setup MongoDB connection event listeners (idempotent)
|
|
64
|
+
*/
|
|
65
|
+
function setupConnectionListeners() {
|
|
66
|
+
// Only setup once
|
|
67
|
+
if (mongoose.connection.listeners('connected').length > 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Connection successful
|
|
71
|
+
mongoose.connection.on('connected', function () {
|
|
72
|
+
console.log('✅ MongoDB connected successfully');
|
|
73
|
+
connectionRetryCount = 0; // Reset retry count on success
|
|
74
|
+
isConnecting = false;
|
|
75
|
+
});
|
|
76
|
+
// Connection error
|
|
77
|
+
mongoose.connection.on('error', function (error) {
|
|
78
|
+
console.error('❌ MongoDB connection error:', error.message);
|
|
79
|
+
isConnecting = false;
|
|
80
|
+
// Don't throw - let retry logic handle it
|
|
81
|
+
});
|
|
82
|
+
// Connection disconnected
|
|
83
|
+
mongoose.connection.on('disconnected', function () {
|
|
84
|
+
console.warn('⚠️ MongoDB disconnected. Will attempt to reconnect...');
|
|
85
|
+
isConnecting = false;
|
|
86
|
+
// Attempt reconnection
|
|
87
|
+
attemptReconnection();
|
|
88
|
+
});
|
|
89
|
+
// Connection timeout
|
|
90
|
+
mongoose.connection.on('timeout', function () {
|
|
91
|
+
console.warn('⚠️ MongoDB connection timeout. Will attempt to reconnect...');
|
|
92
|
+
isConnecting = false;
|
|
93
|
+
// Attempt reconnection
|
|
94
|
+
attemptReconnection();
|
|
95
|
+
});
|
|
96
|
+
// Connection closed
|
|
97
|
+
mongoose.connection.on('close', function () {
|
|
98
|
+
console.warn('⚠️ MongoDB connection closed. Will attempt to reconnect...');
|
|
99
|
+
isConnecting = false;
|
|
100
|
+
// Attempt reconnection
|
|
101
|
+
attemptReconnection();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Attempt to reconnect to MongoDB with exponential backoff
|
|
106
|
+
*/
|
|
107
|
+
function attemptReconnection() {
|
|
108
|
+
var _this = this;
|
|
109
|
+
// Don't attempt if already connecting or connected
|
|
110
|
+
if (isConnecting || isConnected()) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Clear any existing retry timeout
|
|
114
|
+
if (retryTimeout) {
|
|
115
|
+
clearTimeout(retryTimeout);
|
|
116
|
+
retryTimeout = null;
|
|
117
|
+
}
|
|
118
|
+
// Check retry limit
|
|
119
|
+
if (connectionRetryCount >= MAX_RETRY_ATTEMPTS) {
|
|
120
|
+
console.error("\u274C MongoDB reconnection failed after ".concat(MAX_RETRY_ATTEMPTS, " attempts. Server will continue running but database operations may fail."));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Calculate exponential backoff delay
|
|
124
|
+
var delay = Math.min(INITIAL_RETRY_DELAY * Math.pow(2, connectionRetryCount), MAX_RETRY_DELAY);
|
|
125
|
+
connectionRetryCount++;
|
|
126
|
+
console.log("\uD83D\uDD04 Attempting MongoDB reconnection (".concat(connectionRetryCount, "/").concat(MAX_RETRY_ATTEMPTS, ") in ").concat(delay, "ms..."));
|
|
127
|
+
retryTimeout = setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
128
|
+
return __generator(this, function (_a) {
|
|
129
|
+
switch (_a.label) {
|
|
130
|
+
case 0:
|
|
131
|
+
retryTimeout = null;
|
|
132
|
+
return [4 /*yield*/, connectDB()];
|
|
133
|
+
case 1:
|
|
134
|
+
_a.sent(); // Recursive call
|
|
135
|
+
return [2 /*return*/];
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}); }, delay);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Connect to MongoDB with robust error handling and retry logic
|
|
142
|
+
* This function is idempotent - safe to call multiple times
|
|
143
|
+
*/
|
|
43
144
|
function connectDB() {
|
|
44
145
|
return __awaiter(this, void 0, void 0, function () {
|
|
45
|
-
var options;
|
|
146
|
+
var mongoUri, options, connectPromise, timeoutPromise, error_1, errorMessage;
|
|
46
147
|
return __generator(this, function (_a) {
|
|
47
148
|
switch (_a.label) {
|
|
48
149
|
case 0:
|
|
150
|
+
// If already connected, do nothing
|
|
151
|
+
if (isConnected()) {
|
|
152
|
+
return [2 /*return*/];
|
|
153
|
+
}
|
|
154
|
+
// If already connecting, wait for it
|
|
155
|
+
if (isConnecting || isConnectingState()) {
|
|
156
|
+
return [2 /*return*/];
|
|
157
|
+
}
|
|
158
|
+
// Setup event listeners (idempotent)
|
|
159
|
+
setupConnectionListeners();
|
|
160
|
+
mongoUri = process.env.MONGODB_URI;
|
|
161
|
+
if (!mongoUri || mongoUri.trim() === '') {
|
|
162
|
+
console.error('❌ MONGODB_URI is not set in environment variables');
|
|
163
|
+
// Don't throw - server should continue running
|
|
164
|
+
return [2 /*return*/];
|
|
165
|
+
}
|
|
166
|
+
isConnecting = true;
|
|
167
|
+
_a.label = 1;
|
|
168
|
+
case 1:
|
|
169
|
+
_a.trys.push([1, 3, , 4]);
|
|
49
170
|
options = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
171
|
+
connectTimeoutMS: 15000, // Increased timeout
|
|
172
|
+
socketTimeoutMS: 45000, // Increased socket timeout
|
|
173
|
+
serverSelectionTimeoutMS: 15000, // Timeout for server selection
|
|
174
|
+
heartbeatFrequencyMS: 10000, // Heartbeat frequency
|
|
175
|
+
retryWrites: true,
|
|
176
|
+
retryReads: true,
|
|
177
|
+
// Buffer commands if connection is not ready
|
|
178
|
+
bufferCommands: true,
|
|
179
|
+
maxPoolSize: 10, // Maximum number of connections in the pool
|
|
180
|
+
minPoolSize: 2, // Minimum number of connections in the pool
|
|
54
181
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
})
|
|
60
|
-
|
|
182
|
+
connectPromise = mongoose.connect(mongoUri, options);
|
|
183
|
+
timeoutPromise = new Promise(function (_, reject) {
|
|
184
|
+
setTimeout(function () {
|
|
185
|
+
reject(new Error('Connection timeout'));
|
|
186
|
+
}, 20000); // 20 second timeout
|
|
187
|
+
});
|
|
188
|
+
return [4 /*yield*/, Promise.race([connectPromise, timeoutPromise])];
|
|
189
|
+
case 2:
|
|
61
190
|
_a.sent();
|
|
62
|
-
|
|
191
|
+
// If we get here, connection was successful
|
|
192
|
+
console.log('✅ Connected to MongoDB');
|
|
193
|
+
connectionRetryCount = 0; // Reset retry count
|
|
194
|
+
isConnecting = false;
|
|
195
|
+
return [3 /*break*/, 4];
|
|
196
|
+
case 3:
|
|
197
|
+
error_1 = _a.sent();
|
|
198
|
+
isConnecting = false;
|
|
199
|
+
errorMessage = (error_1 === null || error_1 === void 0 ? void 0 : error_1.message) || 'Unknown error';
|
|
200
|
+
console.error("\u274C MongoDB connection failed: ".concat(errorMessage));
|
|
201
|
+
// Only attempt retry if we haven't exceeded max attempts
|
|
202
|
+
if (connectionRetryCount < MAX_RETRY_ATTEMPTS) {
|
|
203
|
+
attemptReconnection();
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
console.error("\u274C MongoDB connection failed after ".concat(MAX_RETRY_ATTEMPTS, " attempts. Server will continue running but database operations may fail."));
|
|
207
|
+
console.error('⚠️ To retry connection, restart the server or wait for automatic reconnection.');
|
|
208
|
+
}
|
|
209
|
+
return [3 /*break*/, 4];
|
|
210
|
+
case 4: return [2 /*return*/];
|
|
63
211
|
}
|
|
64
212
|
});
|
|
65
213
|
});
|
|
66
214
|
}
|
|
67
|
-
// Event
|
|
215
|
+
// Event listener for success and error
|
|
68
216
|
var customUUID = function () {
|
|
69
217
|
var _a, _b, _c;
|
|
70
218
|
var key = (_c = "".concat(process.env.UUID_PREFIX).concat((_b = (_a = (new mongoose.Types.ObjectId())) === null || _a === void 0 ? void 0 : _a.toHexString()) === null || _b === void 0 ? void 0 : _b.slice(3, 24))) === null || _c === void 0 ? void 0 : _c.toLowerCase();
|
|
@@ -84,7 +84,7 @@ var fee_receipt_template = new mongoose_1.Schema({
|
|
|
84
84
|
collection: "fee_receipt_template"
|
|
85
85
|
});
|
|
86
86
|
// Indexes
|
|
87
|
-
|
|
87
|
+
// Note: feert_template_code index is automatically created by unique: true
|
|
88
88
|
fee_receipt_template.index({ feert_entity_id_syen: 1 });
|
|
89
89
|
fee_receipt_template.index({ feert_template_type: 1 });
|
|
90
90
|
fee_receipt_template.index({ feert_status: 1 });
|
|
@@ -89,7 +89,7 @@ var fee_structure = new mongoose_1.Schema({
|
|
|
89
89
|
timestamps: false
|
|
90
90
|
});
|
|
91
91
|
// Indexes for performance
|
|
92
|
-
|
|
92
|
+
// Note: fees_structure_code index is automatically created by unique: true
|
|
93
93
|
fee_structure.index({ fees_entity_id_syen: 1, fees_academic_year_id_acayr: 1 });
|
|
94
94
|
fee_structure.index({ fees_class_program_id_acacpm: 1 });
|
|
95
95
|
fee_structure.index({ fees_entity_id_syen: 1, fees_is_active: 1 });
|
|
@@ -8,7 +8,6 @@ var notification = new mongoose_1.Schema({
|
|
|
8
8
|
type: mongoose_1.default.Schema.Types.ObjectId,
|
|
9
9
|
ref: "auth_user_mst",
|
|
10
10
|
required: true,
|
|
11
|
-
index: true,
|
|
12
11
|
comment: "Target user for notification"
|
|
13
12
|
},
|
|
14
13
|
not_type: {
|
|
@@ -16,14 +15,12 @@ var notification = new mongoose_1.Schema({
|
|
|
16
15
|
enum: ['info', 'success', 'warning', 'error', 'system'],
|
|
17
16
|
required: true,
|
|
18
17
|
default: 'info',
|
|
19
|
-
index: true,
|
|
20
18
|
comment: "Notification type"
|
|
21
19
|
},
|
|
22
20
|
not_category: {
|
|
23
21
|
type: String,
|
|
24
22
|
required: true,
|
|
25
23
|
maxlength: 50,
|
|
26
|
-
index: true,
|
|
27
24
|
comment: "Notification category"
|
|
28
25
|
},
|
|
29
26
|
not_title: {
|
|
@@ -57,7 +54,6 @@ var notification = new mongoose_1.Schema({
|
|
|
57
54
|
enum: ['pending', 'sent', 'delivered', 'read', 'archived'],
|
|
58
55
|
required: true,
|
|
59
56
|
default: 'pending',
|
|
60
|
-
index: true,
|
|
61
57
|
comment: "Notification status"
|
|
62
58
|
},
|
|
63
59
|
not_read_at: {
|
|
@@ -94,7 +90,6 @@ var notification = new mongoose_1.Schema({
|
|
|
94
90
|
enum: ['low', 'normal', 'high', 'urgent'],
|
|
95
91
|
required: true,
|
|
96
92
|
default: 'normal',
|
|
97
|
-
index: true,
|
|
98
93
|
comment: "Notification priority"
|
|
99
94
|
},
|
|
100
95
|
not_expires_at: {
|
|
@@ -109,7 +104,6 @@ var notification = new mongoose_1.Schema({
|
|
|
109
104
|
not_created_at: {
|
|
110
105
|
type: Date,
|
|
111
106
|
default: Date.now,
|
|
112
|
-
index: true,
|
|
113
107
|
comment: "Creation timestamp"
|
|
114
108
|
},
|
|
115
109
|
not_updated_at: {
|
|
@@ -122,13 +116,17 @@ var notification = new mongoose_1.Schema({
|
|
|
122
116
|
collection: 'notifications'
|
|
123
117
|
});
|
|
124
118
|
// Indexes for performance
|
|
125
|
-
|
|
126
|
-
notification.index({ not_id_user: 1
|
|
119
|
+
// Single field indexes
|
|
120
|
+
notification.index({ not_id_user: 1 });
|
|
127
121
|
notification.index({ not_type: 1 });
|
|
128
122
|
notification.index({ not_category: 1 });
|
|
129
123
|
notification.index({ not_priority: 1 });
|
|
124
|
+
notification.index({ not_status: 1 });
|
|
125
|
+
notification.index({ not_created_at: -1 }); // Descending for recent-first queries
|
|
126
|
+
// Compound indexes for common query patterns
|
|
127
|
+
notification.index({ not_id_user: 1, not_status: 1 });
|
|
128
|
+
notification.index({ not_id_user: 1, not_created_at: -1 });
|
|
130
129
|
notification.index({ not_status: 1, not_created_at: -1 });
|
|
131
|
-
// Compound index for common queries
|
|
132
130
|
notification.index({
|
|
133
131
|
not_id_user: 1,
|
|
134
132
|
not_status: 1,
|
|
@@ -9,7 +9,6 @@ var notification_preference = new mongoose_1.Schema({
|
|
|
9
9
|
ref: "auth_user_mst",
|
|
10
10
|
required: true,
|
|
11
11
|
unique: true,
|
|
12
|
-
index: true,
|
|
13
12
|
comment: "User reference"
|
|
14
13
|
},
|
|
15
14
|
npref_channels: {
|
|
@@ -116,7 +115,6 @@ var notification_preference = new mongoose_1.Schema({
|
|
|
116
115
|
timestamps: { createdAt: 'npref_created_at', updatedAt: 'npref_updated_at' },
|
|
117
116
|
collection: 'notification_preferences'
|
|
118
117
|
});
|
|
119
|
-
//
|
|
120
|
-
notification_preference.index({ npref_id_user: 1 }, { unique: true });
|
|
118
|
+
// Note: npref_id_user index is automatically created by unique: true
|
|
121
119
|
var CNotificationPreference = mongoose_1.default.model("notification_preference", notification_preference);
|
|
122
120
|
exports.CNotificationPreference = CNotificationPreference;
|
|
@@ -9,7 +9,6 @@ var notification_template = new mongoose_1.Schema({
|
|
|
9
9
|
required: true,
|
|
10
10
|
unique: true,
|
|
11
11
|
maxlength: 100,
|
|
12
|
-
index: true,
|
|
13
12
|
comment: "Unique template identifier"
|
|
14
13
|
},
|
|
15
14
|
ntemp_template_type: {
|
|
@@ -23,7 +22,6 @@ var notification_template = new mongoose_1.Schema({
|
|
|
23
22
|
type: String,
|
|
24
23
|
required: true,
|
|
25
24
|
maxlength: 50,
|
|
26
|
-
index: true,
|
|
27
25
|
comment: "Notification category"
|
|
28
26
|
},
|
|
29
27
|
ntemp_subject: {
|
|
@@ -62,7 +60,6 @@ var notification_template = new mongoose_1.Schema({
|
|
|
62
60
|
ntemp_is_active: {
|
|
63
61
|
type: Boolean,
|
|
64
62
|
default: true,
|
|
65
|
-
index: true,
|
|
66
63
|
comment: "Template active status"
|
|
67
64
|
},
|
|
68
65
|
ntemp_created_at: {
|
|
@@ -80,7 +77,7 @@ var notification_template = new mongoose_1.Schema({
|
|
|
80
77
|
collection: 'notification_templates'
|
|
81
78
|
});
|
|
82
79
|
// Indexes
|
|
83
|
-
|
|
80
|
+
// Note: ntemp_template_name index is automatically created by unique: true
|
|
84
81
|
notification_template.index({ ntemp_category: 1 });
|
|
85
82
|
notification_template.index({ ntemp_is_active: 1 });
|
|
86
83
|
var CNotificationTemplate = mongoose_1.default.model("notification_template", notification_template);
|
|
@@ -69,6 +69,6 @@ var api_keys = new mongoose_1.Schema({
|
|
|
69
69
|
// Indexes
|
|
70
70
|
api_keys.index({ akey_name: 1 });
|
|
71
71
|
api_keys.index({ akey_status: 1 });
|
|
72
|
-
|
|
72
|
+
// Note: akey_api_key index is automatically created by unique: true
|
|
73
73
|
var CApiKey = mongoose_1.default.model("api_keys", api_keys);
|
|
74
74
|
exports.CApiKey = CApiKey;
|
|
@@ -83,7 +83,7 @@ var backup_jobs = new mongoose_1.Schema({
|
|
|
83
83
|
}
|
|
84
84
|
}, { collection: 'backup_jobs', timestamps: { createdAt: 'bjob_created_at', updatedAt: 'bjob_updated_at' } });
|
|
85
85
|
// Indexes
|
|
86
|
-
|
|
86
|
+
// Note: bjob_name index is automatically created by unique: true
|
|
87
87
|
backup_jobs.index({ bjob_status: 1 });
|
|
88
88
|
backup_jobs.index({ bjob_backup_type: 1 });
|
|
89
89
|
backup_jobs.index({ bjob_backup_policy_id: 1 });
|
|
@@ -62,7 +62,7 @@ var backup_policies = new mongoose_1.Schema({
|
|
|
62
62
|
}
|
|
63
63
|
}, { collection: 'backup_policies', timestamps: { createdAt: 'bpol_created_at', updatedAt: 'bpol_updated_at' } });
|
|
64
64
|
// Indexes
|
|
65
|
-
|
|
65
|
+
// Note: bpol_name index is automatically created by unique: true
|
|
66
66
|
backup_policies.index({ bpol_isactive: 1 });
|
|
67
67
|
var CBackupPolicy = mongoose_1.default.model("backup_policies", backup_policies);
|
|
68
68
|
exports.CBackupPolicy = CBackupPolicy;
|
|
@@ -47,7 +47,7 @@ var subscription_features = new mongoose_1.Schema({
|
|
|
47
47
|
}
|
|
48
48
|
}, { collection: 'subscription_features', timestamps: { createdAt: 'sfea_created_at', updatedAt: 'sfea_updated_at' } });
|
|
49
49
|
// Indexes
|
|
50
|
-
|
|
50
|
+
// Note: sfea_code index is automatically created by unique: true
|
|
51
51
|
subscription_features.index({ sfea_category: 1 });
|
|
52
52
|
var CSubscriptionFeature = mongoose_1.default.model("subscription_features", subscription_features);
|
|
53
53
|
exports.CSubscriptionFeature = CSubscriptionFeature;
|
|
@@ -86,7 +86,7 @@ var subscription_plans = new mongoose_1.Schema({
|
|
|
86
86
|
}
|
|
87
87
|
}, { collection: 'subscription_plans', timestamps: { createdAt: 'spln_created_at', updatedAt: 'spln_updated_at' } });
|
|
88
88
|
// Indexes
|
|
89
|
-
|
|
89
|
+
// Note: spln_code index is automatically created by unique: true
|
|
90
90
|
subscription_plans.index({ spln_is_active: 1 });
|
|
91
91
|
subscription_plans.index({ spln_billing_cycle: 1 });
|
|
92
92
|
var CSubscriptionPlan = mongoose_1.default.model("subscription_plans", subscription_plans);
|
package/package.json
CHANGED