opticore-webapp 1.0.69 → 1.0.71
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/index.cjs +575 -1042
- package/dist/index.d.cts +136 -438
- package/dist/index.d.ts +136 -438
- package/dist/index.js +608 -1084
- package/dist/utils/translations/message.translation.en.json +8 -15
- package/dist/utils/translations/message.translation.fr.json +8 -4
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -30,116 +30,35 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
HotReloadWatcher: () => HotReloadWatcher,
|
|
33
34
|
WebServer: () => WebServerCore,
|
|
34
35
|
envPath: () => envPath
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(index_exports);
|
|
37
38
|
|
|
38
39
|
// src/core/webServer.core.ts
|
|
39
|
-
var
|
|
40
|
-
var
|
|
40
|
+
var path3 = __toESM(require("path"), 1);
|
|
41
|
+
var import_node_process4 = __toESM(require("process"), 1);
|
|
41
42
|
var import_cors = __toESM(require("cors"), 1);
|
|
42
|
-
var import_express = __toESM(require("express"), 1);
|
|
43
|
-
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
44
43
|
var import_opticore_catch_exception_error3 = require("opticore-catch-exception-error");
|
|
44
|
+
var import_opticore_express2 = require("opticore-express");
|
|
45
45
|
var import_opticore_env_access2 = require("opticore-env-access");
|
|
46
|
+
var import_opticore_http_response4 = require("opticore-http-response");
|
|
47
|
+
var import_opticore_translator3 = require("opticore-translator");
|
|
46
48
|
var import_opticore_request_call_event = require("opticore-request-call-event");
|
|
47
|
-
var import_opticore_dependency_inject2 = require("opticore-dependency-inject");
|
|
48
|
-
var import_opticore_http_response3 = require("opticore-http-response");
|
|
49
|
-
var import_opticore_translator2 = require("opticore-translator");
|
|
50
49
|
|
|
51
50
|
// src/core/handlers/eventProcess.handler.ts
|
|
52
51
|
var import_node_process = __toESM(require("process"), 1);
|
|
53
52
|
var import_node_events = __toESM(require("events"), 1);
|
|
53
|
+
var import_opticore_express = require("opticore-express");
|
|
54
54
|
var import_opticore_catch_exception_error = require("opticore-catch-exception-error");
|
|
55
|
-
|
|
56
|
-
// src/utils/isTransformError.utils.ts
|
|
57
|
-
var isTransformErrorUtils = (error) => {
|
|
58
|
-
return error?.name === "TransformError" || error?.message?.includes("Transform failed") || error?.message?.includes("esbuild");
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// src/core/handlers/eventProcess.handler.ts
|
|
62
|
-
function eventProcessHandler(localeLanguage, expressApp) {
|
|
55
|
+
function eventProcessHandler(localeLanguage) {
|
|
63
56
|
const errorEmitter = new import_node_events.default();
|
|
57
|
+
const app = (0, import_opticore_express.express)();
|
|
64
58
|
const serverListenEvent = new import_opticore_catch_exception_error.ServerListenEventError(localeLanguage);
|
|
65
|
-
console.log("[Server] Setting up error event handlers...");
|
|
66
59
|
errorEmitter.on(import_opticore_catch_exception_error.CEventNameError.error, (error) => {
|
|
67
|
-
console.error("[Server] EventEmitter error caught:", error.message);
|
|
68
|
-
if (isTransformErrorUtils(error)) {
|
|
69
|
-
handleTransformError(error);
|
|
70
|
-
}
|
|
71
60
|
serverListenEvent.listenerError(error);
|
|
72
61
|
});
|
|
73
|
-
function handleTransformError(error) {
|
|
74
|
-
console.error("[Server] ============================================");
|
|
75
|
-
console.error("[Server] TRANSFORM ERROR DETECTED");
|
|
76
|
-
console.error("[Server] ============================================");
|
|
77
|
-
console.error("[Server] Message:", error.message);
|
|
78
|
-
console.error("[Server] Stack:", error.stack);
|
|
79
|
-
if (error.errors && Array.isArray(error.errors)) {
|
|
80
|
-
error.errors.forEach((err, index) => {
|
|
81
|
-
console.error(`[Server] Error ${index + 1}:`, err.text);
|
|
82
|
-
if (err.location) {
|
|
83
|
-
console.error(`[Server] File: ${err.location.file}`);
|
|
84
|
-
console.error(`[Server] Line: ${err.location.line}, Column: ${err.location.column}`);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
const fileMatch = error.message.match(/([^:]+\.ts):(\d+):(\d+):/);
|
|
89
|
-
if (fileMatch) {
|
|
90
|
-
console.error("[Server] Problem file:", fileMatch[1]);
|
|
91
|
-
console.error("[Server] Line:", fileMatch[2], "Column:", fileMatch[3]);
|
|
92
|
-
}
|
|
93
|
-
const errorDetailMatch = error.message.match(/ERROR: (.+)$/m);
|
|
94
|
-
if (errorDetailMatch) {
|
|
95
|
-
console.error("[Server] Error detail:", errorDetailMatch[1]);
|
|
96
|
-
}
|
|
97
|
-
console.error("[Server] ============================================");
|
|
98
|
-
if (import_node_process.default.send) {
|
|
99
|
-
import_node_process.default.send({
|
|
100
|
-
type: "TRANSFORM_ERROR",
|
|
101
|
-
error: error.message,
|
|
102
|
-
stack: error.stack,
|
|
103
|
-
errorName: error.name,
|
|
104
|
-
details: error.errors,
|
|
105
|
-
timestamp: Date.now()
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.uncaughtException, (error) => {
|
|
110
|
-
console.error("[Server] UNCAUGHT EXCEPTION:", error.message);
|
|
111
|
-
console.error("[Server] Stack:", error.stack);
|
|
112
|
-
if (isTransformErrorUtils(error)) {
|
|
113
|
-
errorEmitter.emit("transformError", error);
|
|
114
|
-
}
|
|
115
|
-
serverListenEvent.uncaughtException(error);
|
|
116
|
-
if (import_node_process.default.send) {
|
|
117
|
-
const messageType = isTransformErrorUtils(error) ? "TRANSFORM_ERROR" : "HOT_RELOAD_ERROR";
|
|
118
|
-
import_node_process.default.send({
|
|
119
|
-
type: messageType,
|
|
120
|
-
error: error.message,
|
|
121
|
-
stack: error.stack,
|
|
122
|
-
errorName: error.name,
|
|
123
|
-
timestamp: Date.now()
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.unhandledRejection, (reason, promise) => {
|
|
128
|
-
console.error("[Server] UNHANDLED REJECTION:", reason);
|
|
129
|
-
if (isTransformErrorUtils(reason)) {
|
|
130
|
-
errorEmitter.emit("transformError", reason);
|
|
131
|
-
}
|
|
132
|
-
serverListenEvent.unhandledRejection(reason, promise);
|
|
133
|
-
if (import_node_process.default.send) {
|
|
134
|
-
const messageType = isTransformErrorUtils(reason) ? "TRANSFORM_ERROR" : "HOT_RELOAD_ERROR";
|
|
135
|
-
import_node_process.default.send({
|
|
136
|
-
type: messageType,
|
|
137
|
-
error: reason?.message || String(reason),
|
|
138
|
-
errorName: reason?.name,
|
|
139
|
-
timestamp: Date.now()
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
62
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.beforeExit, (code) => {
|
|
144
63
|
setTimeout(() => {
|
|
145
64
|
serverListenEvent.processBeforeExit(code);
|
|
@@ -154,20 +73,20 @@ function eventProcessHandler(localeLanguage, expressApp) {
|
|
|
154
73
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.rejectionHandled, (promise) => {
|
|
155
74
|
serverListenEvent.promiseRejectionHandled(promise);
|
|
156
75
|
});
|
|
76
|
+
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.uncaughtException, (error) => {
|
|
77
|
+
serverListenEvent.uncaughtException(error);
|
|
78
|
+
});
|
|
157
79
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.uncaughtExceptionMonitor, (error) => {
|
|
158
|
-
console.error("[Server] UNCAUGHT EXCEPTION MONITOR:", error.message);
|
|
159
|
-
if (isTransformErrorUtils(error)) {
|
|
160
|
-
errorEmitter.emit("transformError", error);
|
|
161
|
-
}
|
|
162
80
|
serverListenEvent.uncaughtExceptionMonitor(error);
|
|
163
81
|
});
|
|
82
|
+
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.unhandledRejection, (reason, promise) => {
|
|
83
|
+
serverListenEvent.unhandledRejection(reason, promise);
|
|
84
|
+
});
|
|
164
85
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.warning, (warning) => {
|
|
165
86
|
serverListenEvent.warning(warning);
|
|
166
87
|
});
|
|
167
88
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.message, (message) => {
|
|
168
|
-
|
|
169
|
-
serverListenEvent.message(message);
|
|
170
|
-
}
|
|
89
|
+
serverListenEvent.message(message);
|
|
171
90
|
});
|
|
172
91
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.multipleResolves, (type, promise, reason) => {
|
|
173
92
|
serverListenEvent.multipleResolves(type, promise, reason);
|
|
@@ -178,15 +97,9 @@ function eventProcessHandler(localeLanguage, expressApp) {
|
|
|
178
97
|
import_node_process.default.on(import_opticore_catch_exception_error.CEvent.sigterm, (signal) => {
|
|
179
98
|
serverListenEvent.sigtermSignalReceived(signal);
|
|
180
99
|
});
|
|
181
|
-
|
|
182
|
-
console.error("[Server] Express error middleware triggered:", err.message);
|
|
183
|
-
console.error("[Server] Request URL:", req.url);
|
|
184
|
-
console.error("[Server] Request method:", req.method);
|
|
185
|
-
errorEmitter.emit(import_opticore_catch_exception_error.CEventNameError.error, err);
|
|
100
|
+
app.use((err, req, res, next) => {
|
|
186
101
|
serverListenEvent.expressErrorHandlingMiddleware(errorEmitter, err, req, res, next);
|
|
187
102
|
});
|
|
188
|
-
console.log("[Server] Error event handlers configured successfully");
|
|
189
|
-
return errorEmitter;
|
|
190
103
|
}
|
|
191
104
|
|
|
192
105
|
// src/application/service/core.service.ts
|
|
@@ -238,18 +151,20 @@ var dependenciesContainerProvider = (localLang) => {
|
|
|
238
151
|
};
|
|
239
152
|
|
|
240
153
|
// src/application/service/core.service.ts
|
|
241
|
-
var
|
|
154
|
+
var import_opticore_dependency_inject2 = require("opticore-dependency-inject");
|
|
242
155
|
|
|
243
|
-
// src/
|
|
244
|
-
var
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
156
|
+
// src/utils/parsingDateTime.utils.ts
|
|
157
|
+
var parsingDateTimeUtils = (localFormatTime) => {
|
|
158
|
+
const now = /* @__PURE__ */ new Date();
|
|
159
|
+
const formatter = new Intl.DateTimeFormat(localFormatTime, {
|
|
160
|
+
day: "2-digit",
|
|
161
|
+
month: "2-digit",
|
|
162
|
+
year: "numeric",
|
|
163
|
+
hour: "2-digit",
|
|
164
|
+
minute: "2-digit",
|
|
165
|
+
hour12: false
|
|
166
|
+
});
|
|
167
|
+
return formatter.format(now);
|
|
253
168
|
};
|
|
254
169
|
|
|
255
170
|
// src/application/service/core.service.ts
|
|
@@ -258,10 +173,12 @@ var CoreService = class {
|
|
|
258
173
|
environmentPath;
|
|
259
174
|
serverLog;
|
|
260
175
|
logger;
|
|
176
|
+
container;
|
|
261
177
|
constructor(localLang, environmentPath) {
|
|
178
|
+
this.loadTranslationFiles();
|
|
262
179
|
this.environmentPath = environmentPath;
|
|
263
180
|
this.localLanguage = localLang;
|
|
264
|
-
|
|
181
|
+
this.container = new import_opticore_dependency_inject2.SContainer(localLang);
|
|
265
182
|
this.serverLog = dependenciesContainerProvider(localLang).resolve("OpticoreLogger");
|
|
266
183
|
this.logger = dependenciesContainerProvider(localLang).resolve("LoggerCore");
|
|
267
184
|
}
|
|
@@ -275,6 +192,41 @@ var CoreService = class {
|
|
|
275
192
|
formatMemoryUsage(data) {
|
|
276
193
|
return `${Math.round(data / 1024 / 1024 * 100) / 100} MB`;
|
|
277
194
|
}
|
|
195
|
+
loadTranslationFiles() {
|
|
196
|
+
loaderTranslationFile(this.localLanguage);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
*
|
|
200
|
+
* @param filePath
|
|
201
|
+
* @private
|
|
202
|
+
*
|
|
203
|
+
* Return void
|
|
204
|
+
*/
|
|
205
|
+
getEnvFileLoading(filePath) {
|
|
206
|
+
this.loadTranslationFiles();
|
|
207
|
+
try {
|
|
208
|
+
const fullPath = path.resolve(import_node_process2.default.cwd(), filePath);
|
|
209
|
+
if (fs.existsSync(fullPath)) {
|
|
210
|
+
const env = fs.readFileSync(fullPath, "utf-8");
|
|
211
|
+
const lines = env.split("\n");
|
|
212
|
+
lines.forEach((line) => {
|
|
213
|
+
const match = line.match(/^([^#=]+)=([^#]+)$/);
|
|
214
|
+
if (match) {
|
|
215
|
+
const key = match[1].trim();
|
|
216
|
+
import_node_process2.default.env[key] = match[2].trim();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
} catch (err) {
|
|
221
|
+
this.logger.error({
|
|
222
|
+
message: err.message,
|
|
223
|
+
title: import_opticore_translator.TranslationLoader.t("EnvFileLoading", this.localLanguage),
|
|
224
|
+
errorType: err.code,
|
|
225
|
+
stackTrace: err.stack,
|
|
226
|
+
httpCodeValue: import_opticore_http_response.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
278
230
|
/**
|
|
279
231
|
* Returns an Object containing a node version, openssl, and v0
|
|
280
232
|
*/
|
|
@@ -299,7 +251,7 @@ var CoreService = class {
|
|
|
299
251
|
* and Memory usage system
|
|
300
252
|
*/
|
|
301
253
|
getUsageMemory() {
|
|
302
|
-
|
|
254
|
+
this.loadTranslationFiles();
|
|
303
255
|
const memoryData = import_node_process2.default.memoryUsage();
|
|
304
256
|
const data = {
|
|
305
257
|
[import_opticore_translator.TranslationLoader.t("totalMemoryAllocated", this.localLanguage)]: this.formatMemoryUsage(memoryData.rss),
|
|
@@ -331,37 +283,6 @@ var CoreService = class {
|
|
|
331
283
|
"startingTime": `${executionTime.toFixed(5)} ms`
|
|
332
284
|
};
|
|
333
285
|
}
|
|
334
|
-
/**
|
|
335
|
-
*
|
|
336
|
-
* @param filePath
|
|
337
|
-
* @private
|
|
338
|
-
*
|
|
339
|
-
* Return void
|
|
340
|
-
*/
|
|
341
|
-
getEnvFileLoading(filePath) {
|
|
342
|
-
try {
|
|
343
|
-
const fullPath = path.resolve(import_node_process2.default.cwd(), filePath);
|
|
344
|
-
if (fs.existsSync(fullPath)) {
|
|
345
|
-
const env = fs.readFileSync(fullPath, "utf-8");
|
|
346
|
-
const lines = env.split("\n");
|
|
347
|
-
lines.forEach((line) => {
|
|
348
|
-
const match = line.match(/^([^#=]+)=([^#]+)$/);
|
|
349
|
-
if (match) {
|
|
350
|
-
const key = match[1].trim();
|
|
351
|
-
import_node_process2.default.env[key] = match[2].trim();
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
} catch (err) {
|
|
356
|
-
this.logger.error({
|
|
357
|
-
message: err.message,
|
|
358
|
-
title: import_opticore_translator.TranslationLoader.t("EnvFileLoading", this.localLanguage),
|
|
359
|
-
errorType: err.code,
|
|
360
|
-
stackTrace: err.stack,
|
|
361
|
-
httpCodeValue: import_opticore_http_response.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
286
|
/**
|
|
366
287
|
*
|
|
367
288
|
* @param development
|
|
@@ -370,14 +291,15 @@ var CoreService = class {
|
|
|
370
291
|
* Return string
|
|
371
292
|
*/
|
|
372
293
|
getServerRunningMode(development, production) {
|
|
294
|
+
this.loadTranslationFiles();
|
|
373
295
|
try {
|
|
374
|
-
loaderTranslationFile(this.localLanguage);
|
|
375
296
|
this.getEnvFileLoading(".env");
|
|
376
|
-
const env = (0, import_opticore_env_access.
|
|
377
|
-
const isDevelopment = env.devEnv === development
|
|
297
|
+
const env = (0, import_opticore_env_access.getEnvironmentValue)(path.join(envPath));
|
|
298
|
+
const isDevelopment = env.devEnv === development;
|
|
299
|
+
const isProd = env.prodEnv === production;
|
|
378
300
|
if (isDevelopment) {
|
|
379
301
|
return `${import_opticore_translator.TranslationLoader.t("serverRunning", this.localLanguage)} ${import_ansi_colors.default.bgBlue(`${import_ansi_colors.default.bold(`${development}`)}`)} mode`;
|
|
380
|
-
} else if (
|
|
302
|
+
} else if (isProd) {
|
|
381
303
|
return `${import_opticore_translator.TranslationLoader.t("serverRunning", this.localLanguage)} ${import_ansi_colors.default.bgBlue(`${import_ansi_colors.default.bold(`${production}`)}`)} mode`;
|
|
382
304
|
} else {
|
|
383
305
|
return `${import_opticore_translator.TranslationLoader.t("serverRunning", this.localLanguage)} ${import_ansi_colors.default.bgBlue(`${import_ansi_colors.default.bold(`${development}`)}`)} mode`;
|
|
@@ -393,10 +315,10 @@ var CoreService = class {
|
|
|
393
315
|
}
|
|
394
316
|
}
|
|
395
317
|
infoServer(host, port) {
|
|
318
|
+
this.loadTranslationFiles();
|
|
396
319
|
try {
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
-
const msg5 = getEnvironment.protocolTransfert === "" ? import_ansi_colors.default.underline(`http://${host}:${port}`) : import_ansi_colors.default.underline(`${getEnvironment.protocolTransfert}://${host}:${port}`);
|
|
320
|
+
const getEnvironment = (0, import_opticore_env_access.getEnvironmentValue)(this.environmentPath);
|
|
321
|
+
const msg5 = getEnvironment.protocolTransfer === "" ? import_ansi_colors.default.underline(`http://${host}:${port}`) : import_ansi_colors.default.underline(`${getEnvironment.protocolTransfer}://${host}:${port}`);
|
|
400
322
|
const messages = [
|
|
401
323
|
import_opticore_translator.TranslationLoader.t("webServerListening", this.localLanguage),
|
|
402
324
|
import_opticore_translator.TranslationLoader.t("webServerUsingNodeVersion", this.localLanguage, { nodeVersion: this.getVersions().nodeVersion }),
|
|
@@ -416,20 +338,33 @@ var CoreService = class {
|
|
|
416
338
|
});
|
|
417
339
|
console.log(border);
|
|
418
340
|
console.log("\n");
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
title: import_opticore_translator.TranslationLoader.t("serverRunningTitle", this.localLanguage),
|
|
422
|
-
message: import_opticore_translator.TranslationLoader.t("serverRunningAt", this.localLanguage, { server: msg5 })
|
|
423
|
-
});
|
|
424
|
-
SLogger(this.localLanguage).serverLog.serverLog({
|
|
425
|
-
timestamp: (/* @__PURE__ */ new Date()).toString(),
|
|
341
|
+
this.serverLog.serverLog({
|
|
342
|
+
timestamp: parsingDateTimeUtils(getEnvironment.localFormatTime),
|
|
426
343
|
level: "SERVER",
|
|
427
344
|
title: import_opticore_translator.TranslationLoader.t("serverRunningTitle", this.localLanguage),
|
|
428
345
|
typeName: import_opticore_translator.TranslationLoader.t("opticoreServerTypeName", this.localLanguage),
|
|
429
346
|
message: import_opticore_translator.TranslationLoader.t("serverRunningAt", this.localLanguage, { server: msg5 })
|
|
430
347
|
});
|
|
348
|
+
const dependenciesList = this.container.listDependencies();
|
|
349
|
+
if (dependenciesList.length > 0) {
|
|
350
|
+
this.serverLog.opticoreLog({
|
|
351
|
+
level: "OPTICORE",
|
|
352
|
+
message: import_opticore_translator.TranslationLoader.t("DEPENDENCIES_STORED", this.localLanguage, { dependenciesList: dependenciesList.join(", ") }),
|
|
353
|
+
timestamp: parsingDateTimeUtils(getEnvironment.localFormatTime),
|
|
354
|
+
title: import_opticore_translator.TranslationLoader.t("DEPENDENCIES_CONTAINER", this.localLanguage),
|
|
355
|
+
typeName: "DEPENDENCIES_CONTAINER"
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
this.serverLog.opticoreLog({
|
|
359
|
+
level: "OPTICORE",
|
|
360
|
+
message: import_opticore_translator.TranslationLoader.t("NO_DEPENDENCIES_STORED", this.localLanguage),
|
|
361
|
+
timestamp: parsingDateTimeUtils(getEnvironment.localFormatTime),
|
|
362
|
+
title: import_opticore_translator.TranslationLoader.t("DEPENDENCIES_CONTAINER", this.localLanguage),
|
|
363
|
+
typeName: "DEPENDENCIES_CONTAINER"
|
|
364
|
+
});
|
|
365
|
+
}
|
|
431
366
|
} catch (err) {
|
|
432
|
-
|
|
367
|
+
this.logger.error({
|
|
433
368
|
message: err.message,
|
|
434
369
|
title: import_opticore_translator.TranslationLoader.t("server", this.localLanguage),
|
|
435
370
|
errorType: err.code,
|
|
@@ -445,6 +380,20 @@ var dateTimeFormattedUtils = `${(/* @__PURE__ */ new Date()).getMonth()}-${(/* @
|
|
|
445
380
|
|
|
446
381
|
// src/application/service/serverStartError.service.ts
|
|
447
382
|
var import_opticore_catch_exception_error2 = require("opticore-catch-exception-error");
|
|
383
|
+
|
|
384
|
+
// src/application/service/logger.service.ts
|
|
385
|
+
var SLogger = (localLang) => {
|
|
386
|
+
return {
|
|
387
|
+
get serverLog() {
|
|
388
|
+
return dependenciesContainerProvider(localLang).resolve("OpticoreLogger");
|
|
389
|
+
},
|
|
390
|
+
get logger() {
|
|
391
|
+
return dependenciesContainerProvider(localLang).resolve("LoggerCore");
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// src/application/service/serverStartError.service.ts
|
|
448
397
|
var import_opticore_http_response2 = require("opticore-http-response");
|
|
449
398
|
var SServerStartError = (err, environmentPath) => {
|
|
450
399
|
if (err.name) {
|
|
@@ -476,391 +425,165 @@ var SServerStartError = (err, environmentPath) => {
|
|
|
476
425
|
}
|
|
477
426
|
};
|
|
478
427
|
|
|
428
|
+
// src/core/webServer.core.ts
|
|
429
|
+
var import_opticore_dependency_inject3 = require("opticore-dependency-inject");
|
|
430
|
+
|
|
431
|
+
// src/application/service/getEnvFileLoading.service.ts
|
|
432
|
+
var import_path = __toESM(require("path"), 1);
|
|
433
|
+
var import_node_process3 = __toESM(require("process"), 1);
|
|
434
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
435
|
+
var import_opticore_translator2 = require("opticore-translator");
|
|
436
|
+
var import_opticore_http_response3 = require("opticore-http-response");
|
|
437
|
+
var getEnvFileLoadingService = (filePath, localLanguage) => {
|
|
438
|
+
loaderTranslationFile(localLanguage);
|
|
439
|
+
const logger = dependenciesContainerProvider(localLanguage).resolve("LoggerCore");
|
|
440
|
+
try {
|
|
441
|
+
const fullPath = import_path.default.resolve(import_node_process3.default.cwd(), filePath);
|
|
442
|
+
if (import_fs.default.existsSync(fullPath)) {
|
|
443
|
+
const env = import_fs.default.readFileSync(fullPath, "utf-8");
|
|
444
|
+
const lines = env.split("\n");
|
|
445
|
+
lines.forEach((line) => {
|
|
446
|
+
const match = line.match(/^([^#=]+)=([^#]+)$/);
|
|
447
|
+
if (match) {
|
|
448
|
+
const key = match[1].trim();
|
|
449
|
+
import_node_process3.default.env[key] = match[2].trim();
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
} catch (err) {
|
|
454
|
+
logger.error({
|
|
455
|
+
message: err.message,
|
|
456
|
+
title: import_opticore_translator2.TranslationLoader.t("EnvFileLoading", localLanguage),
|
|
457
|
+
errorType: err.code,
|
|
458
|
+
stackTrace: err.stack,
|
|
459
|
+
httpCodeValue: import_opticore_http_response3.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
479
464
|
// src/core/webServer.core.ts
|
|
480
465
|
var WebServerCore = class {
|
|
481
466
|
serverUtility;
|
|
482
|
-
expressApp;
|
|
467
|
+
expressApp = (0, import_opticore_express2.express)();
|
|
468
|
+
container;
|
|
483
469
|
localLanguage;
|
|
484
470
|
loggerConfig;
|
|
485
|
-
|
|
471
|
+
routerExpressApp;
|
|
472
|
+
getEnvironmentValue;
|
|
486
473
|
environmentPath;
|
|
487
474
|
serverListenEvent;
|
|
488
|
-
|
|
489
|
-
currentRoutes = [];
|
|
490
|
-
currentDependencies = [];
|
|
491
|
-
server = void 0;
|
|
492
|
-
errorEmitter;
|
|
493
|
-
serverStatus = "STARTING";
|
|
494
|
-
serverStartTime = /* @__PURE__ */ new Date();
|
|
495
|
-
// HMR properties
|
|
496
|
-
fileWatcher = null;
|
|
497
|
-
hmrRestartPending = false;
|
|
498
|
-
hmrDebounceTimeout = null;
|
|
499
|
-
hmrRestartCount = 0;
|
|
500
|
-
lastHmrRestartTime = 0;
|
|
501
|
-
/**
|
|
502
|
-
* Creates a new WebServerCore instance.
|
|
503
|
-
*
|
|
504
|
-
* @constructor
|
|
505
|
-
* @param {WebServerConstructorInterface} paramsConstructor - Configuration parameters
|
|
506
|
-
*
|
|
507
|
-
* @param {express.Application} paramsConstructor.app - Express application instance
|
|
508
|
-
* @param {LoggerCore} paramsConstructor.loggerConfig - Logger configuration
|
|
509
|
-
* @param {string} paramsConstructor.environmentPath - Path to environment file
|
|
510
|
-
* @param {string} paramsConstructor.localLanguage - Default language for translations
|
|
511
|
-
* @param {CorsOptions} paramsConstructor.corsOriginOptions - CORS configuration
|
|
512
|
-
*
|
|
513
|
-
* @returns {WebServerCore} New WebServerCore instance
|
|
514
|
-
*
|
|
515
|
-
* @throws {Error} If environment file cannot be loaded
|
|
516
|
-
*
|
|
517
|
-
* @example
|
|
518
|
-
* ```typescript
|
|
519
|
-
* const server = new WebServerCore({
|
|
520
|
-
* app: express(),
|
|
521
|
-
* loggerConfig: new LoggerCore(config),
|
|
522
|
-
* environmentPath: ".env",
|
|
523
|
-
* localLanguage: "fr",
|
|
524
|
-
* corsOriginOptions: { origin: "http://localhost:3000" }
|
|
525
|
-
* });
|
|
526
|
-
* ```
|
|
527
|
-
*/
|
|
475
|
+
dependenciesRegistered = false;
|
|
528
476
|
constructor(paramsConstructor) {
|
|
529
|
-
this.
|
|
477
|
+
this.loadTranslationFiles();
|
|
478
|
+
this.stackTraceErrorHandling();
|
|
479
|
+
this.getEnvironmentValue = (0, import_opticore_env_access2.getEnvironmentValue)(paramsConstructor.environmentPath);
|
|
480
|
+
this.routerExpressApp = paramsConstructor.app;
|
|
530
481
|
this.loggerConfig = paramsConstructor.loggerConfig;
|
|
531
482
|
this.localLanguage = paramsConstructor.localLanguage;
|
|
532
483
|
this.environmentPath = paramsConstructor.environmentPath;
|
|
533
|
-
this.
|
|
534
|
-
this.
|
|
535
|
-
this.expressApp.use(
|
|
536
|
-
this.expressApp.use(
|
|
537
|
-
this.expressApp.use(
|
|
538
|
-
this.expressApp.use(import_express.default.urlencoded({ extended: true }));
|
|
484
|
+
this.container = new import_opticore_dependency_inject3.SContainer(paramsConstructor.localLanguage);
|
|
485
|
+
this.expressApp.use(import_opticore_express2.express.json());
|
|
486
|
+
this.expressApp.use(import_opticore_express2.express.raw());
|
|
487
|
+
this.expressApp.use(import_opticore_express2.express.text());
|
|
488
|
+
this.expressApp.use(import_opticore_express2.express.urlencoded({ extended: true }));
|
|
539
489
|
this.expressApp.use((0, import_cors.default)(paramsConstructor.corsOriginOptions));
|
|
490
|
+
this.serverListenEvent = new import_opticore_catch_exception_error3.ServerListenEventError(paramsConstructor.localLanguage);
|
|
540
491
|
this.serverUtility = new CoreService(paramsConstructor.localLanguage, paramsConstructor.environmentPath);
|
|
541
|
-
this.serverStatus = "STARTING";
|
|
542
|
-
this.serverStartTime = /* @__PURE__ */ new Date();
|
|
543
|
-
this.setupProcessEventListeners();
|
|
544
492
|
}
|
|
545
493
|
/**
|
|
546
|
-
* Starts the HTTP server and initializes all components including HMR if enabled.
|
|
547
|
-
*
|
|
548
|
-
* @method onStartServer
|
|
549
|
-
* @public
|
|
550
494
|
*
|
|
551
|
-
* @param
|
|
552
|
-
* @param {(env: IEnvVariables) => void} [databaseCallback] - Optional database connection callback
|
|
553
|
-
* @param {TDependency[]} [dependenciesProvider] - Optional dependency injection providers
|
|
554
|
-
*
|
|
555
|
-
* @returns {serverWebApp | undefined} HTTP server instance or undefined if startup fails
|
|
556
|
-
*
|
|
557
|
-
* @throws {ServerListenEventError} If port/host configuration is invalid
|
|
558
|
-
* @throws {Error} If server initialization fails
|
|
559
|
-
*
|
|
560
|
-
* @fires WebServerCore#startHttpServer - When server successfully starts
|
|
561
|
-
* @fires WebServerCore#startHMR - When HMR is started (if enabled)
|
|
562
|
-
* @fires WebServerCore#serverError - When server fails to start
|
|
563
|
-
*
|
|
564
|
-
* @example
|
|
565
|
-
* ```typescript
|
|
566
|
-
* const server = app.onStartServer(
|
|
567
|
-
* routes,
|
|
568
|
-
* (env) => connectToDatabase(env),
|
|
569
|
-
* dependencies
|
|
570
|
-
* );
|
|
571
|
-
*
|
|
572
|
-
* if (server) {
|
|
573
|
-
* console.log("Server started successfully");
|
|
574
|
-
* }
|
|
575
|
-
* ```
|
|
495
|
+
* @param dependencies
|
|
576
496
|
*/
|
|
577
|
-
|
|
497
|
+
registerDependencies(dependencies2) {
|
|
498
|
+
this.loadTranslationFiles();
|
|
578
499
|
try {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
if (!this.validateServerParameters()) {
|
|
585
|
-
return void 0;
|
|
586
|
-
}
|
|
587
|
-
const server = this.startHttpServer(databaseCallback);
|
|
588
|
-
if (this.getEnvironment.hmrEnabled) {
|
|
589
|
-
this.startHMR();
|
|
500
|
+
getEnvFileLoadingService(".env", this.localLanguage);
|
|
501
|
+
if (dependencies2 && dependencies2.length > 0) {
|
|
502
|
+
dependencies2.forEach((dependency) => {
|
|
503
|
+
this.container.register(dependency.key, dependency.factory, dependency.scope);
|
|
504
|
+
});
|
|
590
505
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
506
|
+
} catch (err) {
|
|
507
|
+
SLogger(this.environmentPath).logger.error({
|
|
508
|
+
message: err.message,
|
|
509
|
+
title: "Register Dependencies",
|
|
510
|
+
errorType: err.code,
|
|
511
|
+
stackTrace: err.stack,
|
|
512
|
+
httpCodeValue: import_opticore_http_response4.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
513
|
+
});
|
|
594
514
|
}
|
|
595
515
|
}
|
|
596
516
|
/**
|
|
597
|
-
* Validates server configuration parameters.
|
|
598
517
|
*
|
|
599
|
-
* @
|
|
600
|
-
* @
|
|
601
|
-
*
|
|
602
|
-
* @returns {boolean} True if all parameters are valid, false otherwise
|
|
603
|
-
*
|
|
604
|
-
* @remarks
|
|
605
|
-
* Validates:
|
|
606
|
-
* - Port number is valid and positive
|
|
607
|
-
* - Host is not empty
|
|
608
|
-
* - Local language is specified
|
|
609
|
-
* - HMR configuration (if enabled)
|
|
518
|
+
* @param routers
|
|
519
|
+
* @param databaseCallback
|
|
520
|
+
* @param dependenciesProvider
|
|
610
521
|
*/
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
if (
|
|
522
|
+
onStartServer(routers, databaseCallback, dependenciesProvider) {
|
|
523
|
+
this.loadTranslationFiles();
|
|
524
|
+
getEnvFileLoadingService(".env", this.localLanguage);
|
|
525
|
+
if (this.getEnvironmentValue.appPort === "" && Number(this.getEnvironmentValue.appPort) === 0) {
|
|
526
|
+
this.serverListenEvent.hostPortUndefined(Number(this.getEnvironmentValue.appPort));
|
|
527
|
+
} else if (this.getEnvironmentValue.appHost === "") {
|
|
528
|
+
this.serverListenEvent.hostUndefined(this.getEnvironmentValue.appHost);
|
|
529
|
+
} else if (Number(this.getEnvironmentValue.appPort) === 0) {
|
|
615
530
|
this.serverListenEvent.portUndefined();
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
}
|
|
622
|
-
if (!this.localLanguage || this.localLanguage.trim() === "") {
|
|
623
|
-
SLogger(this.localLanguage).logger.error({
|
|
624
|
-
message: import_opticore_translator2.TranslationLoader.t("noDefaultLocalLang", this.localLanguage),
|
|
625
|
-
title: import_opticore_translator2.TranslationLoader.t("noLocalLang", this.localLanguage),
|
|
626
|
-
errorType: import_opticore_translator2.TranslationLoader.t("localLangMissing", this.localLanguage),
|
|
531
|
+
} else if (this.localLanguage === "") {
|
|
532
|
+
SLogger(this.environmentPath).logger.error({
|
|
533
|
+
message: import_opticore_translator3.TranslationLoader.t("noDefaultLocalLang", this.localLanguage),
|
|
534
|
+
title: import_opticore_translator3.TranslationLoader.t("noLocalLang", this.localLanguage),
|
|
535
|
+
errorType: import_opticore_translator3.TranslationLoader.t("localLangMissing", this.localLanguage),
|
|
627
536
|
stackTrace: void 0,
|
|
628
|
-
httpCodeValue:
|
|
537
|
+
httpCodeValue: import_opticore_http_response4.HttpStatusCode.NOT_FOUND
|
|
629
538
|
});
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
* @private
|
|
647
|
-
*
|
|
648
|
-
* @param {(env: IEnvVariables) => void} [databaseCallback] - Database connection callback
|
|
649
|
-
*
|
|
650
|
-
* @returns {serverWebApp | undefined} HTTP server instance or undefined if startup fails
|
|
651
|
-
*
|
|
652
|
-
* @throws {Error} If server fails to start
|
|
653
|
-
*/
|
|
654
|
-
startHttpServer(databaseCallback) {
|
|
655
|
-
try {
|
|
656
|
-
loaderTranslationFile(this.localLanguage);
|
|
657
|
-
const port = Number(this.getEnvironment.appPort);
|
|
658
|
-
const host = this.getEnvironment.appHost;
|
|
659
|
-
this.server = this.expressApp.listen(port, host, () => {
|
|
660
|
-
try {
|
|
661
|
-
this.configureServerComponents(databaseCallback);
|
|
662
|
-
this.serverStatus = "READY";
|
|
663
|
-
SLogger(this.localLanguage).logger.info({
|
|
664
|
-
title: import_opticore_translator2.TranslationLoader.t("SERVER_RUNNING_TITLE", this.localLanguage),
|
|
665
|
-
message: import_opticore_translator2.TranslationLoader.t("SERVER_RUNNING_AT", this.localLanguage, {
|
|
666
|
-
server: `${host}:${port}`,
|
|
667
|
-
hmrEnabled: this.getEnvironment.hmrEnabled ? "with HMR" : "without HMR"
|
|
668
|
-
})
|
|
669
|
-
});
|
|
670
|
-
} catch (err) {
|
|
671
|
-
this.handleServerConfigurationError(err);
|
|
539
|
+
} else {
|
|
540
|
+
return this.expressApp.listen(
|
|
541
|
+
Number(this.getEnvironmentValue.appPort),
|
|
542
|
+
() => {
|
|
543
|
+
this.loadTranslationFiles();
|
|
544
|
+
try {
|
|
545
|
+
databaseCallback(this.getEnvironmentValue);
|
|
546
|
+
if (dependenciesProvider) {
|
|
547
|
+
this.registerDependencies(dependenciesProvider);
|
|
548
|
+
}
|
|
549
|
+
this.container.loadServices();
|
|
550
|
+
this.expressApp.use(import_opticore_express2.express.static(path3.join(import_node_process4.default.cwd(), "public/template")));
|
|
551
|
+
this.registerRoutes(routers);
|
|
552
|
+
} catch (err) {
|
|
553
|
+
SServerStartError(err, this.environmentPath);
|
|
554
|
+
}
|
|
672
555
|
}
|
|
673
|
-
});
|
|
674
|
-
this.setupServerEventListeners();
|
|
675
|
-
return this.server;
|
|
676
|
-
} catch (error) {
|
|
677
|
-
this.serverListenEvent.onEventError(
|
|
678
|
-
new Error(import_opticore_translator2.TranslationLoader.t(
|
|
679
|
-
"HTTP_SERVER_FAILED",
|
|
680
|
-
this.localLanguage,
|
|
681
|
-
{ errorMessage: error.message }
|
|
682
|
-
))
|
|
683
556
|
);
|
|
684
557
|
}
|
|
685
558
|
}
|
|
686
559
|
/**
|
|
687
|
-
* Configures server components (database, dependencies, routes, etc.).
|
|
688
|
-
*
|
|
689
|
-
* @method configureServerComponents
|
|
690
|
-
* @private
|
|
691
|
-
*
|
|
692
|
-
* @param {(env: IEnvVariables) => void} [databaseCallback] - Database connection callback
|
|
693
|
-
*
|
|
694
|
-
* @returns {void}
|
|
695
560
|
*
|
|
696
|
-
* @
|
|
561
|
+
* @param serverWeb
|
|
697
562
|
*/
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
);
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
try {
|
|
711
|
-
new import_opticore_dependency_inject2.SContainer(this.localLanguage, this.currentDependencies);
|
|
712
|
-
} catch (depError) {
|
|
713
|
-
this.serverListenEvent.listenerError(
|
|
714
|
-
new Error(import_opticore_translator2.TranslationLoader.t("DEPENDENCY_INJECTION_FAILED", this.localLanguage, { depErrorMessage: depError.message }))
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
this.expressApp.use(import_express.default.static(path2.join(import_node_process3.default.cwd(), "public/template")));
|
|
718
|
-
this.registerRoutes(this.currentRoutes);
|
|
719
|
-
this.setupErrorHandling();
|
|
563
|
+
onListeningOnServerEvent(serverWeb) {
|
|
564
|
+
this.loadTranslationFiles();
|
|
565
|
+
serverWeb.on(import_opticore_catch_exception_error3.CEventNameError.error, (err) => {
|
|
566
|
+
this.serverListenEvent.onEventError(err);
|
|
567
|
+
}).on(import_opticore_catch_exception_error3.CEventNameError.close, () => {
|
|
568
|
+
this.serverListenEvent.serverClosing();
|
|
569
|
+
}).on(import_opticore_catch_exception_error3.CEventNameError.drop, () => {
|
|
570
|
+
this.serverListenEvent.dropNewConnection();
|
|
571
|
+
}).on(import_opticore_catch_exception_error3.CEventNameError.listening, () => {
|
|
720
572
|
this.infoWebApp();
|
|
721
|
-
} catch (error) {
|
|
722
|
-
this.serverListenEvent.listenerError(
|
|
723
|
-
new Error(import_opticore_translator2.TranslationLoader.t("SERVER_COMPONENT_CONFIG_FAILED", this.localLanguage, { errorMessage: error.message }))
|
|
724
|
-
);
|
|
725
|
-
throw error;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
/**
|
|
729
|
-
* Handles server configuration errors.
|
|
730
|
-
*
|
|
731
|
-
* @method handleServerConfigurationError
|
|
732
|
-
* @private
|
|
733
|
-
*
|
|
734
|
-
* @param {any} err - The error that occurred
|
|
735
|
-
*
|
|
736
|
-
* @returns {void}
|
|
737
|
-
*/
|
|
738
|
-
handleServerConfigurationError(err) {
|
|
739
|
-
loaderTranslationFile(this.localLanguage);
|
|
740
|
-
this.serverStatus = "ERROR";
|
|
741
|
-
this.serverListenEvent.onEventError(err);
|
|
742
|
-
try {
|
|
743
|
-
SServerStartError(err, this.environmentPath);
|
|
744
|
-
} catch (startError) {
|
|
745
|
-
this.serverListenEvent.listenerError(startError);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Handles general startup errors.
|
|
750
|
-
*
|
|
751
|
-
* @method handleStartupError
|
|
752
|
-
* @private
|
|
753
|
-
*
|
|
754
|
-
* @param {any} error - The startup error
|
|
755
|
-
*
|
|
756
|
-
* @returns {void}
|
|
757
|
-
*/
|
|
758
|
-
handleStartupError(error) {
|
|
759
|
-
loaderTranslationFile(this.localLanguage);
|
|
760
|
-
this.serverStatus = "ERROR";
|
|
761
|
-
this.serverListenEvent.listenerError(error);
|
|
762
|
-
SLogger(this.localLanguage).logger.error({
|
|
763
|
-
title: import_opticore_translator2.TranslationLoader.t("GLOBAL_STARTUP_ERROR", this.localLanguage),
|
|
764
|
-
message: error.message,
|
|
765
|
-
errorType: error.name || "StartupError",
|
|
766
|
-
stackTrace: error.stack,
|
|
767
|
-
httpCodeValue: import_opticore_http_response3.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Sets up Node.js process event listeners.
|
|
772
|
-
*
|
|
773
|
-
* @method setupProcessEventListeners
|
|
774
|
-
* @private
|
|
775
|
-
*
|
|
776
|
-
* @returns {void}
|
|
777
|
-
*
|
|
778
|
-
* @remarks
|
|
779
|
-
* Listens for:
|
|
780
|
-
* - Process exit events
|
|
781
|
-
* - Uncaught exceptions
|
|
782
|
-
* - Unhandled rejections
|
|
783
|
-
* - System signals (SIGINT, SIGTERM)
|
|
784
|
-
*/
|
|
785
|
-
setupProcessEventListeners() {
|
|
786
|
-
loaderTranslationFile(this.localLanguage);
|
|
787
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.beforeExit, (code) => {
|
|
788
|
-
this.serverListenEvent.processBeforeExit(code);
|
|
789
|
-
});
|
|
790
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.disconnect, () => {
|
|
791
|
-
this.serverListenEvent.processDisconnected();
|
|
792
|
-
});
|
|
793
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.exit, (code) => {
|
|
794
|
-
this.serverListenEvent.exited(code);
|
|
795
|
-
});
|
|
796
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.message, (message) => {
|
|
797
|
-
this.serverListenEvent.message(message);
|
|
798
|
-
});
|
|
799
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.multipleResolves, (type, promise, reason) => {
|
|
800
|
-
this.serverListenEvent.multipleResolves(type, promise, reason);
|
|
801
|
-
});
|
|
802
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.rejectionHandled, (promise) => {
|
|
803
|
-
this.serverListenEvent.promiseRejectionHandled(promise);
|
|
804
|
-
});
|
|
805
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.uncaughtException, (error) => {
|
|
806
|
-
this.serverListenEvent.uncaughtException(error);
|
|
807
|
-
});
|
|
808
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.uncaughtExceptionMonitor, (error) => {
|
|
809
|
-
this.serverListenEvent.uncaughtExceptionMonitor(error);
|
|
810
|
-
});
|
|
811
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.unhandledRejection, (reason, promise) => {
|
|
812
|
-
this.serverListenEvent.unhandledRejection(reason, promise);
|
|
813
|
-
});
|
|
814
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.warning, (warning) => {
|
|
815
|
-
this.serverListenEvent.warning(warning);
|
|
816
|
-
});
|
|
817
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.sigint, () => {
|
|
818
|
-
this.serverListenEvent.processInterrupted();
|
|
819
|
-
});
|
|
820
|
-
import_node_process3.default.on(import_opticore_catch_exception_error3.CEvent.sigterm, (signal) => {
|
|
821
|
-
this.serverListenEvent.sigtermSignalReceived(signal);
|
|
822
573
|
});
|
|
823
574
|
}
|
|
824
575
|
/**
|
|
825
|
-
* Sets up HTTP server event listeners.
|
|
826
|
-
*
|
|
827
|
-
* @method setupServerEventListeners
|
|
828
|
-
* @private
|
|
829
576
|
*
|
|
830
|
-
* @
|
|
831
|
-
*
|
|
832
|
-
* @remarks
|
|
833
|
-
* Configures listeners for:
|
|
834
|
-
* - Server errors
|
|
835
|
-
* - Connection closing
|
|
836
|
-
* - Connection dropping
|
|
837
|
-
* - HTTP requests (for logging)
|
|
838
|
-
*
|
|
839
|
-
* @listens Server#error - Server error events
|
|
840
|
-
* @listens Server#close - Server closing events
|
|
841
|
-
* @listens Server#drop - Connection drop events
|
|
842
|
-
* @listens Server#request - HTTP request events
|
|
577
|
+
* @param serverWeb
|
|
843
578
|
*/
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
this.server.on(import_opticore_catch_exception_error3.CEventNameError.error, (err) => {
|
|
850
|
-
this.serverListenEvent.onEventError(err);
|
|
851
|
-
});
|
|
852
|
-
this.server.on(import_opticore_catch_exception_error3.CEventNameError.close, () => {
|
|
853
|
-
this.serverListenEvent.serverClosing();
|
|
854
|
-
});
|
|
855
|
-
this.server.on(import_opticore_catch_exception_error3.CEventNameError.drop, () => {
|
|
856
|
-
this.serverListenEvent.dropNewConnection();
|
|
857
|
-
});
|
|
858
|
-
this.server.on(import_opticore_catch_exception_error3.CEventNameError.request, (req, res) => {
|
|
579
|
+
onRequestOnServerEvent(serverWeb) {
|
|
580
|
+
this.loadTranslationFiles();
|
|
581
|
+
serverWeb.on(import_opticore_catch_exception_error3.CEventNameError.request, (req, res) => {
|
|
859
582
|
(0, import_opticore_request_call_event.requestCallsEvent)(
|
|
860
583
|
req,
|
|
861
584
|
res,
|
|
862
|
-
this.
|
|
863
|
-
Number(this.
|
|
585
|
+
this.getEnvironmentValue.appHost,
|
|
586
|
+
Number(this.getEnvironmentValue.appPort),
|
|
864
587
|
dateTimeFormattedUtils,
|
|
865
588
|
this.environmentPath,
|
|
866
589
|
this.localLanguage
|
|
@@ -868,627 +591,437 @@ var WebServerCore = class {
|
|
|
868
591
|
});
|
|
869
592
|
}
|
|
870
593
|
/**
|
|
871
|
-
* Sets up error handling middleware and event emitters.
|
|
872
594
|
*
|
|
873
|
-
* @method setupErrorHandling
|
|
874
595
|
* @private
|
|
875
|
-
*
|
|
876
|
-
* @returns {void}
|
|
877
596
|
*/
|
|
878
|
-
|
|
597
|
+
loadTranslationFiles() {
|
|
879
598
|
loaderTranslationFile(this.localLanguage);
|
|
880
|
-
SLogger(this.localLanguage).logger.info({
|
|
881
|
-
title: import_opticore_translator2.TranslationLoader.t("SETTING_UP", this.localLanguage),
|
|
882
|
-
message: import_opticore_translator2.TranslationLoader.t("SETTING_UP_ERROR", this.localLanguage)
|
|
883
|
-
});
|
|
884
|
-
this.errorEmitter = eventProcessHandler(this.localLanguage, this.expressApp);
|
|
885
|
-
if (this.errorEmitter) {
|
|
886
|
-
this.expressApp.use((err, req, res, next) => {
|
|
887
|
-
this.serverListenEvent.expressErrorHandlingMiddleware(
|
|
888
|
-
this.errorEmitter,
|
|
889
|
-
err,
|
|
890
|
-
req,
|
|
891
|
-
res,
|
|
892
|
-
next
|
|
893
|
-
);
|
|
894
|
-
});
|
|
895
|
-
this.errorEmitter.on("transformError", (error) => {
|
|
896
|
-
this.serverListenEvent.listenerError(error);
|
|
897
|
-
});
|
|
898
|
-
this.errorEmitter.on("error", (error) => {
|
|
899
|
-
this.serverListenEvent.listenerError(error);
|
|
900
|
-
});
|
|
901
|
-
this.errorEmitter.on("hotReload", (data) => {
|
|
902
|
-
SLogger(this.localLanguage).logger.info({
|
|
903
|
-
title: import_opticore_translator2.TranslationLoader.t("HOT_RELOAD_EVENT", this.localLanguage),
|
|
904
|
-
message: `Hot reload triggered for ${data.file}`
|
|
905
|
-
});
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
|
-
SLogger(this.localLanguage).logger.info({
|
|
909
|
-
title: import_opticore_translator2.TranslationLoader.t("ERROR_HANDLING", this.localLanguage),
|
|
910
|
-
message: import_opticore_translator2.TranslationLoader.t("ERROR_HANDLING_CONFIGURED", this.localLanguage)
|
|
911
|
-
});
|
|
912
599
|
}
|
|
913
600
|
/**
|
|
914
|
-
* Registers routes with the Express application.
|
|
915
601
|
*
|
|
916
|
-
* @
|
|
602
|
+
* @param allFeatureRoutes
|
|
917
603
|
* @private
|
|
918
|
-
*
|
|
919
|
-
* @param {any[]} allFeatureRoutes - Array of feature routes to register
|
|
920
|
-
*
|
|
921
|
-
* @returns {void}
|
|
922
604
|
*/
|
|
923
605
|
registerRoutes(allFeatureRoutes) {
|
|
924
|
-
allFeatureRoutes.
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
});
|
|
929
|
-
}
|
|
606
|
+
allFeatureRoutes.map((router) => {
|
|
607
|
+
router.routes.map((route) => {
|
|
608
|
+
this.expressApp.use(route.path, route.handler);
|
|
609
|
+
});
|
|
930
610
|
});
|
|
931
611
|
}
|
|
932
612
|
/**
|
|
933
|
-
* Displays server information.
|
|
934
613
|
*
|
|
935
|
-
* @method infoWebApp
|
|
936
614
|
* @private
|
|
937
|
-
*
|
|
938
|
-
* @returns {void}
|
|
939
615
|
*/
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
this.serverUtility.infoServer(
|
|
943
|
-
this.getEnvironment.appHost,
|
|
944
|
-
Number(this.getEnvironment.appPort)
|
|
945
|
-
);
|
|
616
|
+
stackTraceErrorHandling() {
|
|
617
|
+
return eventProcessHandler(this.localLanguage);
|
|
946
618
|
}
|
|
947
619
|
/**
|
|
948
|
-
* Starts the Hot Module Replacement (HMR) file watching system.
|
|
949
620
|
*
|
|
950
|
-
* @method startHMR
|
|
951
621
|
* @private
|
|
952
|
-
*
|
|
953
|
-
* @returns {void}
|
|
954
|
-
*
|
|
955
|
-
* @remarks
|
|
956
|
-
* Configures file watcher based on environment variables:
|
|
957
|
-
* - HMR_ENABLED: Enable/disable HMR
|
|
958
|
-
* - HMR_WATCH_PATTERNS: Files to watch
|
|
959
|
-
* - HMR_IGNORE_PATTERNS: Files to ignore
|
|
960
|
-
*
|
|
961
|
-
* @throws {Error} If HMR configuration is invalid
|
|
962
622
|
*/
|
|
963
|
-
|
|
623
|
+
infoWebApp() {
|
|
624
|
+
this.loadTranslationFiles();
|
|
625
|
+
this.serverUtility.infoServer(
|
|
626
|
+
this.getEnvironmentValue.appHost,
|
|
627
|
+
Number(this.getEnvironmentValue.appPort)
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// src/hotReload/hotReload.watcher.ts
|
|
633
|
+
var import_child_process = require("child_process");
|
|
634
|
+
var import_fs2 = require("fs");
|
|
635
|
+
var import_promises = require("fs/promises");
|
|
636
|
+
var import_path2 = require("path");
|
|
637
|
+
var import_dotenv = require("dotenv");
|
|
638
|
+
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
639
|
+
var import_ansi_colors2 = __toESM(require("ansi-colors"), 1);
|
|
640
|
+
var import_gradient_string = __toESM(require("gradient-string"), 1);
|
|
641
|
+
var DEFAULT_WATCH_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
642
|
+
var DEFAULT_HOT_RELOAD_EXTENSIONS = [".json"];
|
|
643
|
+
var DEFAULT_IGNORE = [
|
|
644
|
+
"node_modules",
|
|
645
|
+
"dist",
|
|
646
|
+
".git",
|
|
647
|
+
"package.json",
|
|
648
|
+
"package-lock.json",
|
|
649
|
+
".idea",
|
|
650
|
+
".vscode",
|
|
651
|
+
"coverage",
|
|
652
|
+
"logs"
|
|
653
|
+
];
|
|
654
|
+
var DEFAULT_DEBOUNCE_MS = 300;
|
|
655
|
+
var DEFAULT_MAX_CRASH_RESTARTS = 5;
|
|
656
|
+
var HotReloadWatcher = class {
|
|
657
|
+
cfg;
|
|
658
|
+
child = null;
|
|
659
|
+
watchers = [];
|
|
660
|
+
debounceTimer = null;
|
|
661
|
+
isRestarting = false;
|
|
662
|
+
crashRestartCount = 0;
|
|
663
|
+
started = false;
|
|
664
|
+
restartStart = 0;
|
|
665
|
+
constructor(config) {
|
|
666
|
+
this.cfg = {
|
|
667
|
+
entry: (0, import_path2.resolve)(config.entry),
|
|
668
|
+
runtime: config.runtime ?? "node",
|
|
669
|
+
runtimeArgs: config.runtimeArgs ?? [],
|
|
670
|
+
rootDir: (0, import_path2.resolve)(config.rootDir ?? process.cwd()),
|
|
671
|
+
watchDirs: config.watchDirs ?? [],
|
|
672
|
+
watchExtensions: config.watchExtensions ?? DEFAULT_WATCH_EXTENSIONS,
|
|
673
|
+
ignore: [...DEFAULT_IGNORE, ...config.ignore ?? []],
|
|
674
|
+
envFile: config.envFile ?? ".env",
|
|
675
|
+
hotReloadExtensions: config.hotReloadExtensions ?? DEFAULT_HOT_RELOAD_EXTENSIONS,
|
|
676
|
+
debounceMs: config.debounceMs ?? DEFAULT_DEBOUNCE_MS,
|
|
677
|
+
restartOnCrash: config.restartOnCrash ?? true,
|
|
678
|
+
maxCrashRestarts: config.maxCrashRestarts ?? DEFAULT_MAX_CRASH_RESTARTS
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
// ─── Public API ──────────────────────────────────────────────────────────
|
|
682
|
+
async start() {
|
|
683
|
+
if (this.started) return;
|
|
684
|
+
this.started = true;
|
|
685
|
+
this.printBanner();
|
|
686
|
+
this.spawnChild();
|
|
687
|
+
await this.setupWatchers();
|
|
688
|
+
this.setupProcessSignals();
|
|
689
|
+
}
|
|
690
|
+
async stop() {
|
|
691
|
+
this.watchers.forEach((w) => {
|
|
692
|
+
w.close();
|
|
693
|
+
});
|
|
694
|
+
this.watchers = [];
|
|
695
|
+
await this.killChild(true);
|
|
696
|
+
this.printStopped();
|
|
697
|
+
}
|
|
698
|
+
// ─── Child process management ────────────────────────────────────────────
|
|
699
|
+
spawnChild() {
|
|
700
|
+
const { entry, runtime, runtimeArgs } = this.cfg;
|
|
964
701
|
try {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
return;
|
|
973
|
-
}
|
|
974
|
-
if (!hmrConfig.hmrWatchPatterns || hmrConfig.hmrWatchPatterns.length === 0) {
|
|
975
|
-
SLogger(this.localLanguage).logger.error({
|
|
976
|
-
title: import_opticore_translator2.TranslationLoader.t("HMR_WATCH_PATTERNS_MISSING", this.localLanguage),
|
|
977
|
-
message: "No watch patterns defined for HMR",
|
|
978
|
-
errorType: "HMR Configuration Error",
|
|
979
|
-
httpCodeValue: import_opticore_http_response3.HttpStatusCode.BAD_REQUEST
|
|
980
|
-
});
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
const watchPatterns = hmrConfig.hmrWatchPatterns;
|
|
984
|
-
const ignorePatterns = hmrConfig.hmrIgnorePatterns || [
|
|
985
|
-
"node_modules/**",
|
|
986
|
-
"dist/**",
|
|
987
|
-
"build/**",
|
|
988
|
-
"*.log",
|
|
989
|
-
".git/**"
|
|
990
|
-
];
|
|
991
|
-
const allPatterns = [
|
|
992
|
-
...watchPatterns,
|
|
993
|
-
...ignorePatterns.map((pattern) => `!${pattern}`)
|
|
994
|
-
];
|
|
995
|
-
this.fileWatcher = import_chokidar.default.watch(allPatterns, {
|
|
996
|
-
ignored: /(^|[/\\])\../,
|
|
997
|
-
persistent: true,
|
|
998
|
-
ignoreInitial: true,
|
|
999
|
-
awaitWriteFinish: {
|
|
1000
|
-
stabilityThreshold: 300,
|
|
1001
|
-
pollInterval: 100
|
|
1002
|
-
},
|
|
1003
|
-
cwd: import_node_process3.default.cwd(),
|
|
1004
|
-
depth: 10
|
|
702
|
+
this.child = runtime === "node" ? (0, import_child_process.fork)(entry, [], {
|
|
703
|
+
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
704
|
+
env: process.env
|
|
705
|
+
}) : (0, import_child_process.spawn)(runtime, [...runtimeArgs, entry], {
|
|
706
|
+
stdio: "inherit",
|
|
707
|
+
env: process.env,
|
|
708
|
+
shell: false
|
|
1005
709
|
});
|
|
1006
|
-
this.
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
710
|
+
this.child.on("exit", (code) => {
|
|
711
|
+
if (this.isRestarting) return;
|
|
712
|
+
if (code !== 0 && code !== null) {
|
|
713
|
+
this.printCrash(code);
|
|
714
|
+
if (this.cfg.restartOnCrash && this.crashRestartCount < this.cfg.maxCrashRestarts) {
|
|
715
|
+
this.crashRestartCount++;
|
|
716
|
+
this.printCrashRetry(this.crashRestartCount, this.cfg.maxCrashRestarts);
|
|
717
|
+
setTimeout(() => {
|
|
718
|
+
this.spawnChild();
|
|
719
|
+
}, 1e3);
|
|
720
|
+
} else if (this.crashRestartCount >= this.cfg.maxCrashRestarts) {
|
|
721
|
+
this.printCrashLimit(this.cfg.maxCrashRestarts);
|
|
722
|
+
process.exit(1);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
1012
725
|
});
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
title: import_opticore_translator2.TranslationLoader.t("HMR_START_FAILED", this.localLanguage),
|
|
1016
|
-
message: error.message,
|
|
1017
|
-
errorType: "HMR Error",
|
|
1018
|
-
stackTrace: error.stack
|
|
726
|
+
this.child.on("error", (err) => {
|
|
727
|
+
this.printError(`Failed to start child process: ${err.message}`);
|
|
1019
728
|
});
|
|
729
|
+
} catch (err) {
|
|
730
|
+
this.printError(`Cannot spawn '${runtime} ${entry}': ${err.message}`);
|
|
731
|
+
process.exit(1);
|
|
1020
732
|
}
|
|
1021
733
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
*/
|
|
1037
|
-
handleFileChange(filePath, action = "modified") {
|
|
1038
|
-
const debounceMs = this.getEnvironment.hmrDebounceMs || 500;
|
|
1039
|
-
if (this.hmrDebounceTimeout) {
|
|
1040
|
-
clearTimeout(this.hmrDebounceTimeout);
|
|
1041
|
-
}
|
|
1042
|
-
this.hmrDebounceTimeout = setTimeout(async () => {
|
|
1043
|
-
await this.triggerHotReload(filePath, action);
|
|
1044
|
-
}, debounceMs);
|
|
1045
|
-
SLogger(this.localLanguage).logger.info({
|
|
1046
|
-
title: import_opticore_translator2.TranslationLoader.t("FILE_CHANGE_DETECTED", this.localLanguage),
|
|
1047
|
-
message: `File ${action}: ${filePath}`
|
|
734
|
+
async killChild(silent = false) {
|
|
735
|
+
if (!this.child) return;
|
|
736
|
+
const child = this.child;
|
|
737
|
+
this.child = null;
|
|
738
|
+
await new Promise((done) => {
|
|
739
|
+
const forceKill = setTimeout(() => {
|
|
740
|
+
child.kill("SIGKILL");
|
|
741
|
+
done();
|
|
742
|
+
}, 3e3);
|
|
743
|
+
child.once("exit", () => {
|
|
744
|
+
clearTimeout(forceKill);
|
|
745
|
+
done();
|
|
746
|
+
});
|
|
747
|
+
child.kill("SIGTERM");
|
|
1048
748
|
});
|
|
1049
749
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
*
|
|
1059
|
-
* @returns {Promise<void>}
|
|
1060
|
-
*
|
|
1061
|
-
* @remarks
|
|
1062
|
-
* - Checks if reload is already in progress
|
|
1063
|
-
* - Validates restart limits
|
|
1064
|
-
* - Performs appropriate reload actions based on file type
|
|
1065
|
-
* - Emits hotReload event
|
|
1066
|
-
*/
|
|
1067
|
-
async triggerHotReload(filePath, action) {
|
|
1068
|
-
if (this.hmrRestartPending) {
|
|
1069
|
-
return;
|
|
750
|
+
// ─── File watching ────────────────────────────────────────────────────────
|
|
751
|
+
async setupWatchers() {
|
|
752
|
+
const dirs = [
|
|
753
|
+
this.cfg.rootDir,
|
|
754
|
+
...this.cfg.watchDirs.map((d) => (0, import_path2.resolve)(d))
|
|
755
|
+
];
|
|
756
|
+
for (const dir of dirs) {
|
|
757
|
+
await this.watchDirectoryRecursive(dir);
|
|
1070
758
|
}
|
|
1071
|
-
|
|
759
|
+
}
|
|
760
|
+
async watchDirectoryRecursive(dir) {
|
|
761
|
+
if (this.shouldIgnoreDir(dir)) return;
|
|
762
|
+
try {
|
|
763
|
+
await (0, import_promises.access)(dir);
|
|
764
|
+
} catch {
|
|
1072
765
|
return;
|
|
1073
766
|
}
|
|
1074
|
-
this.hmrRestartPending = true;
|
|
1075
|
-
this.hmrRestartCount++;
|
|
1076
|
-
this.lastHmrRestartTime = Date.now();
|
|
1077
767
|
try {
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
message: import_opticore_translator2.TranslationLoader.t("RELOADING_APPLICATION", this.localLanguage, {
|
|
1082
|
-
file: filePath,
|
|
1083
|
-
action
|
|
1084
|
-
})
|
|
1085
|
-
});
|
|
1086
|
-
if (this.errorEmitter) {
|
|
1087
|
-
this.errorEmitter.emit("hotReload", {
|
|
1088
|
-
file: filePath,
|
|
1089
|
-
action,
|
|
1090
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
1091
|
-
restartCount: this.hmrRestartCount
|
|
1092
|
-
});
|
|
1093
|
-
}
|
|
1094
|
-
await this.performHotReloadActions(filePath);
|
|
1095
|
-
SLogger(this.localLanguage).logger.success({
|
|
1096
|
-
title: import_opticore_translator2.TranslationLoader.t("HOT_RELOAD_COMPLETE", this.localLanguage),
|
|
1097
|
-
message: import_opticore_translator2.TranslationLoader.t("APPLICATION_RELOADED", this.localLanguage, {
|
|
1098
|
-
file: filePath,
|
|
1099
|
-
restartCount: this.hmrRestartCount,
|
|
1100
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1101
|
-
})
|
|
768
|
+
const watcher = (0, import_fs2.watch)(dir, (event2, filename) => {
|
|
769
|
+
if (!filename) return;
|
|
770
|
+
this.onFileChange((0, import_path2.join)(dir, filename));
|
|
1102
771
|
});
|
|
1103
|
-
|
|
1104
|
-
SLogger(this.localLanguage).logger.error({
|
|
1105
|
-
title: import_opticore_translator2.TranslationLoader.t("HOT_RELOAD_FAILED", this.localLanguage),
|
|
1106
|
-
message: error.message,
|
|
1107
|
-
errorType: "HotReloadError",
|
|
1108
|
-
stackTrace: error.stack,
|
|
1109
|
-
httpCodeValue: import_opticore_http_response3.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
772
|
+
watcher.on("error", () => {
|
|
1110
773
|
});
|
|
1111
|
-
|
|
1112
|
-
|
|
774
|
+
this.watchers.push(watcher);
|
|
775
|
+
const entries = await (0, import_promises.readdir)(dir, { withFileTypes: true });
|
|
776
|
+
for (const entry of entries) {
|
|
777
|
+
if (entry.isDirectory()) {
|
|
778
|
+
await this.watchDirectoryRecursive((0, import_path2.join)(dir, entry.name));
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
} catch {
|
|
1113
782
|
}
|
|
1114
783
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
*
|
|
1125
|
-
* @remarks
|
|
1126
|
-
* Different actions for different file types:
|
|
1127
|
-
* - .json/.env: Reload translations
|
|
1128
|
-
* - routes/controller files: Reload routes
|
|
1129
|
-
* - config/.env files: Reload dependencies
|
|
1130
|
-
*/
|
|
1131
|
-
async performHotReloadActions(filePath) {
|
|
1132
|
-
if (filePath.includes(".json") || filePath.endsWith(".env")) {
|
|
1133
|
-
loaderTranslationFile(this.localLanguage);
|
|
1134
|
-
}
|
|
1135
|
-
if (filePath.includes("routes") || filePath.includes("controller")) {
|
|
1136
|
-
await this.reloadRoutes();
|
|
1137
|
-
}
|
|
1138
|
-
if (filePath.includes("config") || filePath.includes(".env")) {
|
|
1139
|
-
await this.reloadDependencies();
|
|
784
|
+
// ─── Change handling ─────────────────────────────────────────────────────
|
|
785
|
+
onFileChange(filePath) {
|
|
786
|
+
if (this.shouldIgnoreFile(filePath)) return;
|
|
787
|
+
if (!this.isWatchedFile(filePath)) return;
|
|
788
|
+
const rel = (0, import_path2.relative)(this.cfg.rootDir, filePath);
|
|
789
|
+
if (this.isHotReloadable(filePath)) {
|
|
790
|
+
this.doHotReload(filePath, rel);
|
|
791
|
+
} else {
|
|
792
|
+
this.scheduleRestart(rel);
|
|
1140
793
|
}
|
|
1141
794
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
* @throws {Error} If route reloading fails
|
|
1151
|
-
*
|
|
1152
|
-
* @remarks
|
|
1153
|
-
* This method should be implemented based on your architecture.
|
|
1154
|
-
* It should reload route modules from the filesystem.
|
|
1155
|
-
*/
|
|
1156
|
-
async reloadRoutes() {
|
|
1157
|
-
try {
|
|
1158
|
-
SLogger(this.localLanguage).logger.info({
|
|
1159
|
-
title: import_opticore_translator2.TranslationLoader.t("ROUTES_RELOADED", this.localLanguage),
|
|
1160
|
-
message: "Routes dynamically reloaded"
|
|
1161
|
-
});
|
|
1162
|
-
} catch (error) {
|
|
1163
|
-
throw new Error(`Route reload failed: ${error.message}`);
|
|
795
|
+
doHotReload(filePath, relativePath) {
|
|
796
|
+
if (this.isEnvFile(filePath)) {
|
|
797
|
+
(0, import_dotenv.config)({ path: filePath, override: true });
|
|
798
|
+
this.printHot(relativePath, "env variables reloaded");
|
|
799
|
+
this.sendIpc({ type: "hot-reload", file: relativePath, kind: "env" });
|
|
800
|
+
} else {
|
|
801
|
+
this.printHot(relativePath, "json config reloaded");
|
|
802
|
+
this.sendIpc({ type: "hot-reload", file: relativePath, kind: "json" });
|
|
1164
803
|
}
|
|
1165
804
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
805
|
+
scheduleRestart(relativePath) {
|
|
806
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
807
|
+
this.debounceTimer = setTimeout(async () => {
|
|
808
|
+
this.printReloading(relativePath);
|
|
809
|
+
this.restartStart = Date.now();
|
|
810
|
+
this.isRestarting = true;
|
|
811
|
+
this.crashRestartCount = 0;
|
|
812
|
+
await this.killChild(true);
|
|
813
|
+
this.isRestarting = false;
|
|
814
|
+
this.spawnChild();
|
|
815
|
+
this.printReady(Date.now() - this.restartStart);
|
|
816
|
+
}, this.cfg.debounceMs);
|
|
817
|
+
}
|
|
818
|
+
// ─── IPC ─────────────────────────────────────────────────────────────────
|
|
819
|
+
sendIpc(message) {
|
|
820
|
+
if (this.child && typeof this.child.send === "function") {
|
|
821
|
+
try {
|
|
822
|
+
this.child.send(message);
|
|
823
|
+
} catch {
|
|
1184
824
|
}
|
|
1185
|
-
} catch (error) {
|
|
1186
|
-
throw new Error(`Dependency reload failed: ${error.message}`);
|
|
1187
825
|
}
|
|
1188
826
|
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
* @method canProceedWithHMRRestart
|
|
1193
|
-
* @private
|
|
1194
|
-
*
|
|
1195
|
-
* @returns {boolean} True if restart can proceed, false otherwise
|
|
1196
|
-
*
|
|
1197
|
-
* @remarks
|
|
1198
|
-
* Checks:
|
|
1199
|
-
* - Auto-restart enabled/disabled
|
|
1200
|
-
* - Maximum restarts per minute limit
|
|
1201
|
-
*/
|
|
1202
|
-
canProceedWithHMRRestart() {
|
|
1203
|
-
const hmrConfig = this.getEnvironment;
|
|
1204
|
-
if (!hmrConfig.hmrAutoRestarts) {
|
|
1205
|
-
SLogger(this.localLanguage).logger.warn({
|
|
1206
|
-
title: import_opticore_translator2.TranslationLoader.t("HMR_AUTO_RESTART_DISABLED", this.localLanguage),
|
|
1207
|
-
message: "HMR auto-restart disabled"
|
|
1208
|
-
});
|
|
1209
|
-
return false;
|
|
1210
|
-
}
|
|
1211
|
-
const maxRestarts = hmrConfig.hmrMaxRestarts || 5;
|
|
1212
|
-
const now = Date.now();
|
|
1213
|
-
const oneMinuteAgo = now - 6e4;
|
|
1214
|
-
if (this.lastHmrRestartTime < oneMinuteAgo) {
|
|
1215
|
-
this.hmrRestartCount = 0;
|
|
1216
|
-
}
|
|
1217
|
-
if (this.hmrRestartCount >= maxRestarts) {
|
|
1218
|
-
const nextReset = Math.ceil((this.lastHmrRestartTime + 6e4 - now) / 1e3);
|
|
1219
|
-
SLogger(this.localLanguage).logger.error({
|
|
1220
|
-
title: import_opticore_translator2.TranslationLoader.t("HMR_RESTART_LIMIT_EXCEEDED", this.localLanguage),
|
|
1221
|
-
message: import_opticore_translator2.TranslationLoader.t("HMR_RESTART_LIMIT_MESSAGE", this.localLanguage, {
|
|
1222
|
-
max: maxRestarts,
|
|
1223
|
-
nextReset
|
|
1224
|
-
})
|
|
1225
|
-
});
|
|
1226
|
-
return false;
|
|
1227
|
-
}
|
|
1228
|
-
return true;
|
|
827
|
+
// ─── Ignore / watch filters ───────────────────────────────────────────────
|
|
828
|
+
shouldIgnoreDir(dirPath) {
|
|
829
|
+
return this.cfg.ignore.some((p) => dirPath.includes(`/${p}`) || dirPath.endsWith(p));
|
|
1229
830
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
* @private
|
|
1235
|
-
*
|
|
1236
|
-
* @param {string[]} watchPatterns - Patterns being watched
|
|
1237
|
-
* @param {string[]} ignorePatterns - Patterns being ignored
|
|
1238
|
-
*
|
|
1239
|
-
* @returns {void}
|
|
1240
|
-
*/
|
|
1241
|
-
onHMRWatcherReady(watchPatterns, ignorePatterns) {
|
|
1242
|
-
SLogger(this.localLanguage).logger.info({
|
|
1243
|
-
title: import_opticore_translator2.TranslationLoader.t("HMR_WATCHER_READY", this.localLanguage),
|
|
1244
|
-
message: import_opticore_translator2.TranslationLoader.t("HMR_WATCHING_DETAILS", this.localLanguage, {
|
|
1245
|
-
watchCount: watchPatterns,
|
|
1246
|
-
ignoreCount: ignorePatterns
|
|
1247
|
-
})
|
|
1248
|
-
});
|
|
831
|
+
shouldIgnoreFile(filePath) {
|
|
832
|
+
const name = (0, import_path2.basename)(filePath);
|
|
833
|
+
const rel = (0, import_path2.relative)(this.cfg.rootDir, filePath);
|
|
834
|
+
return this.cfg.ignore.some((p) => name === p || rel.includes(p) || filePath.includes(`/${p}/`));
|
|
1249
835
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
stackTrace: error.stack
|
|
1266
|
-
});
|
|
836
|
+
isWatchedFile(filePath) {
|
|
837
|
+
if (this.isEnvFile(filePath)) return true;
|
|
838
|
+
return this.cfg.watchExtensions.includes((0, import_path2.extname)(filePath));
|
|
839
|
+
}
|
|
840
|
+
isHotReloadable(filePath) {
|
|
841
|
+
if (this.isEnvFile(filePath)) return true;
|
|
842
|
+
return this.cfg.hotReloadExtensions.includes((0, import_path2.extname)(filePath));
|
|
843
|
+
}
|
|
844
|
+
isEnvFile(filePath) {
|
|
845
|
+
const name = (0, import_path2.basename)(filePath);
|
|
846
|
+
return name === this.cfg.envFile || name.startsWith(".env");
|
|
847
|
+
}
|
|
848
|
+
// ─── ANSI strip helper (for width calculation) ────────────────────────────
|
|
849
|
+
strip(str) {
|
|
850
|
+
return str.replace(/\[[0-9;]*m/g, "").replace(/\][^]*/g, "");
|
|
1267
851
|
}
|
|
852
|
+
// ─── Timestamp ────────────────────────────────────────────────────────────
|
|
853
|
+
ts() {
|
|
854
|
+
const n = /* @__PURE__ */ new Date();
|
|
855
|
+
const h = String(n.getHours()).padStart(2, "0");
|
|
856
|
+
const m = String(n.getMinutes()).padStart(2, "0");
|
|
857
|
+
const s = String(n.getSeconds()).padStart(2, "0");
|
|
858
|
+
return `${h}:${m}:${s}`;
|
|
859
|
+
}
|
|
860
|
+
// ─── Console output ───────────────────────────────────────────────────────
|
|
1268
861
|
/**
|
|
1269
|
-
*
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
862
|
+
* Startup banner — mirrors the infoServer() box style from CoreService.
|
|
863
|
+
*
|
|
864
|
+
* ╔══════════════════════════════════════════╗
|
|
865
|
+
* gradient title
|
|
866
|
+
* ╔══ bgGreen box ════════════════════════╗
|
|
867
|
+
* entry dist/index.js
|
|
868
|
+
* runtime node (IPC enabled)
|
|
869
|
+
* root ./src
|
|
870
|
+
* watching .ts .js .json .env
|
|
871
|
+
* debounce 300ms
|
|
872
|
+
* ╚══════════════════════════════════════════╝
|
|
1275
873
|
*/
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
874
|
+
printBanner() {
|
|
875
|
+
const entryRel = (0, import_path2.relative)(process.cwd(), this.cfg.entry) || this.cfg.entry;
|
|
876
|
+
const rootRel = (0, import_path2.relative)(process.cwd(), this.cfg.rootDir) || ".";
|
|
877
|
+
const runtimeStr = this.cfg.runtime === "node" ? `node ${import_chalk2.default.blackBright("(IPC enabled)")}` : this.cfg.runtime;
|
|
878
|
+
const extStr = [...this.cfg.watchExtensions, ".env"].join(" ");
|
|
879
|
+
const ignoreStr = this.cfg.ignore.slice(0, 4).join(" ") + (this.cfg.ignore.length > 4 ? ` ${import_chalk2.default.blackBright(`+${this.cfg.ignore.length - 4} more`)}` : "");
|
|
880
|
+
const TITLE = "OPTICORE HOT RELOAD";
|
|
881
|
+
const rows = [
|
|
882
|
+
` entry ${import_chalk2.default.white.bold(entryRel)}`,
|
|
883
|
+
` runtime ${runtimeStr}`,
|
|
884
|
+
` root ${import_chalk2.default.white(rootRel)}`,
|
|
885
|
+
` watching ${import_chalk2.default.cyan(extStr)}`,
|
|
886
|
+
` ignoring ${import_chalk2.default.blackBright(ignoreStr)}`,
|
|
887
|
+
` debounce ${import_chalk2.default.white(`${this.cfg.debounceMs}ms`)}`
|
|
888
|
+
];
|
|
889
|
+
const maxLen = Math.max(
|
|
890
|
+
TITLE.length + 4,
|
|
891
|
+
...rows.map((r) => this.strip(r).length)
|
|
892
|
+
) + 4;
|
|
893
|
+
const border = import_chalk2.default.bgGreen.white(" ".repeat(maxLen));
|
|
894
|
+
const titlePad = " ".repeat(Math.max(0, Math.floor((maxLen - TITLE.length) / 2)));
|
|
895
|
+
console.log("\n" + titlePad + (0, import_gradient_string.default)(["#43e97b", "#38f9d7", "#00c6fb"])(TITLE));
|
|
896
|
+
console.log(border);
|
|
897
|
+
rows.forEach((row) => {
|
|
898
|
+
const cleanLen = this.strip(row).length;
|
|
899
|
+
const padding = Math.max(0, maxLen - cleanLen - 2);
|
|
900
|
+
console.log(import_chalk2.default.bgGreen.white(` ${row}${" ".repeat(padding)} `));
|
|
1288
901
|
});
|
|
902
|
+
console.log(border);
|
|
903
|
+
console.log(import_chalk2.default.blackBright(` watching for changes...
|
|
904
|
+
`));
|
|
1289
905
|
}
|
|
1290
906
|
/**
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
* @method onStopServer
|
|
1294
|
-
* @public
|
|
907
|
+
* HOT event — in-process reload, no server restart.
|
|
1295
908
|
*
|
|
1296
|
-
*
|
|
909
|
+
* ✔ [ HOT ] 14:23:45 | .env → env variables reloaded
|
|
1297
910
|
*/
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
});
|
|
1307
|
-
this.serverStatus = "STOPPED";
|
|
1308
|
-
}
|
|
911
|
+
printHot(file, action) {
|
|
912
|
+
const badge = import_ansi_colors2.default.bgCyan(import_ansi_colors2.default.white.bold(" HOT "));
|
|
913
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
914
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
915
|
+
const filePart = import_chalk2.default.cyan.bold(file.padEnd(32));
|
|
916
|
+
const arrow = import_chalk2.default.green("\u2192");
|
|
917
|
+
const msg = import_chalk2.default.green(action);
|
|
918
|
+
console.log(` ${import_chalk2.default.green("\u2714")} ${badge} ${ts} ${sep} ${filePart} ${arrow} ${msg}`);
|
|
1309
919
|
}
|
|
1310
920
|
/**
|
|
1311
|
-
*
|
|
921
|
+
* RELOAD event — server restart triggered.
|
|
1312
922
|
*
|
|
1313
|
-
*
|
|
1314
|
-
* @public
|
|
1315
|
-
*
|
|
1316
|
-
* @returns {IServerStateInfo} Server state information object
|
|
1317
|
-
*
|
|
1318
|
-
* @remarks
|
|
1319
|
-
* Includes:
|
|
1320
|
-
* - Status, host, port
|
|
1321
|
-
* - Route and dependency counts
|
|
1322
|
-
* - Uptime and memory usage
|
|
1323
|
-
* - HMR configuration and statistics
|
|
923
|
+
* ⚡ [ RELOAD ] 14:24:03 | src/routes/user.ts → restarting server...
|
|
1324
924
|
*/
|
|
1325
|
-
|
|
1326
|
-
const
|
|
1327
|
-
const
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
routesCount: this.currentRoutes.length,
|
|
1335
|
-
dependenciesCount: this.currentDependencies.length,
|
|
1336
|
-
startTime: this.serverStartTime,
|
|
1337
|
-
currentTime: now,
|
|
1338
|
-
uptime,
|
|
1339
|
-
uptimeFormatted: this.formatUptime(uptime),
|
|
1340
|
-
memoryUsage: import_node_process3.default.memoryUsage(),
|
|
1341
|
-
pid: import_node_process3.default.pid,
|
|
1342
|
-
platform: import_node_process3.default.platform,
|
|
1343
|
-
nodeVersion: import_node_process3.default.version,
|
|
1344
|
-
cwd: import_node_process3.default.cwd(),
|
|
1345
|
-
hmrEnabled: this.getEnvironment.hmrEnabled,
|
|
1346
|
-
hmrWatchingFiles: this.getEnvironment.hmrWatchPatterns?.length || 0,
|
|
1347
|
-
hmrRestartCount: this.hmrRestartCount
|
|
1348
|
-
};
|
|
925
|
+
printReloading(file) {
|
|
926
|
+
const badge = import_ansi_colors2.default.bgYellow(import_ansi_colors2.default.white.bold(" RELOAD "));
|
|
927
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
928
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
929
|
+
const filePart = import_chalk2.default.yellow.bold(file.padEnd(32));
|
|
930
|
+
const arrow = import_chalk2.default.yellow("\u2192");
|
|
931
|
+
const msg = import_chalk2.default.yellow("restarting server...");
|
|
932
|
+
console.log(`
|
|
933
|
+
${import_chalk2.default.yellow("\u26A1")} ${badge} ${ts} ${sep} ${filePart} ${arrow} ${msg}`);
|
|
1349
934
|
}
|
|
1350
935
|
/**
|
|
1351
|
-
*
|
|
1352
|
-
*
|
|
1353
|
-
* @method getServerStatus
|
|
1354
|
-
* @public
|
|
936
|
+
* READY event — server successfully restarted.
|
|
937
|
+
* Uses the same full-width bgGreen border as infoServer().
|
|
1355
938
|
*
|
|
1356
|
-
*
|
|
939
|
+
* ════════════════════════════════════════════
|
|
940
|
+
* READY server restarted in 245ms
|
|
941
|
+
* ════════════════════════════════════════════
|
|
1357
942
|
*/
|
|
1358
|
-
|
|
1359
|
-
|
|
943
|
+
printReady(elapsedMs) {
|
|
944
|
+
const msg = ` server restarted in ${import_chalk2.default.white.bold(`${elapsedMs}ms`)}`;
|
|
945
|
+
const cleanLen = this.strip(msg).length;
|
|
946
|
+
const width = Math.max(52, cleanLen + 6);
|
|
947
|
+
const border = import_chalk2.default.bgGreen.white(" ".repeat(width));
|
|
948
|
+
const padding = Math.max(0, width - cleanLen - 2);
|
|
949
|
+
const line = import_chalk2.default.bgGreen.white(` ${import_chalk2.default.bgGreen.white.bold(" READY ")} ${msg}${" ".repeat(padding)} `);
|
|
950
|
+
console.log(` ${border}`);
|
|
951
|
+
console.log(` ${line}`);
|
|
952
|
+
console.log(` ${border}
|
|
953
|
+
`);
|
|
1360
954
|
}
|
|
1361
955
|
/**
|
|
1362
|
-
*
|
|
1363
|
-
*
|
|
1364
|
-
* @method getServerStats
|
|
1365
|
-
* @public
|
|
1366
|
-
*
|
|
1367
|
-
* @returns {IServerStats} Server statistics object
|
|
956
|
+
* CRASH event — unexpected child process exit.
|
|
1368
957
|
*
|
|
1369
|
-
*
|
|
1370
|
-
* Includes:
|
|
1371
|
-
* - Performance metrics (CPU, memory)
|
|
1372
|
-
* - Uptime information
|
|
1373
|
-
* - HMR statistics
|
|
958
|
+
* ✘ [ CRASH ] 14:24:10 | server exited with code 1
|
|
1374
959
|
*/
|
|
1375
|
-
|
|
1376
|
-
const
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
rss: this.formatBytes(memory.rss),
|
|
1383
|
-
heapTotal: this.formatBytes(memory.heapTotal),
|
|
1384
|
-
heapUsed: this.formatBytes(memory.heapUsed),
|
|
1385
|
-
external: this.formatBytes(memory.external)
|
|
1386
|
-
},
|
|
1387
|
-
performance: {
|
|
1388
|
-
cpuUsage: import_node_process3.default.cpuUsage(),
|
|
1389
|
-
resourceUsage: import_node_process3.default.resourceUsage?.()
|
|
1390
|
-
},
|
|
1391
|
-
hmrStats: {
|
|
1392
|
-
enabled: this.getEnvironment.hmrEnabled,
|
|
1393
|
-
restartCount: this.hmrRestartCount,
|
|
1394
|
-
lastRestartTime: this.lastHmrRestartTime,
|
|
1395
|
-
watchingFiles: this.getEnvironment.hmrWatchPatterns?.length || 0
|
|
1396
|
-
}
|
|
1397
|
-
};
|
|
960
|
+
printCrash(code) {
|
|
961
|
+
const badge = import_ansi_colors2.default.bgRed(import_ansi_colors2.default.white.bold(" CRASH "));
|
|
962
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
963
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
964
|
+
const msg = import_chalk2.default.red(`server exited with code ${import_chalk2.default.bold(String(code))}`);
|
|
965
|
+
console.log(`
|
|
966
|
+
${import_chalk2.default.red("\u2718")} ${badge} ${ts} ${sep} ${msg}`);
|
|
1398
967
|
}
|
|
1399
968
|
/**
|
|
1400
|
-
*
|
|
969
|
+
* RETRY event — auto-restart after crash.
|
|
1401
970
|
*
|
|
1402
|
-
*
|
|
1403
|
-
* @private
|
|
1404
|
-
*
|
|
1405
|
-
* @param {number} ms - Milliseconds to format
|
|
1406
|
-
*
|
|
1407
|
-
* @returns {string} Formatted uptime string
|
|
1408
|
-
*
|
|
1409
|
-
* @example
|
|
1410
|
-
* formatUptime(3661000) // returns "1h 1m 1s"
|
|
971
|
+
* ↺ [ RETRY ] 14:24:11 | attempt 1 / 5
|
|
1411
972
|
*/
|
|
1412
|
-
|
|
1413
|
-
const
|
|
1414
|
-
const
|
|
1415
|
-
const
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1418
|
-
return `${days}d ${hours % 24}h ${minutes % 60}m`;
|
|
1419
|
-
} else if (hours > 0) {
|
|
1420
|
-
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
1421
|
-
} else if (minutes > 0) {
|
|
1422
|
-
return `${minutes}m ${seconds % 60}s`;
|
|
1423
|
-
} else {
|
|
1424
|
-
return `${seconds}s`;
|
|
1425
|
-
}
|
|
973
|
+
printCrashRetry(attempt, max) {
|
|
974
|
+
const badge = import_ansi_colors2.default.bgMagenta(import_ansi_colors2.default.white.bold(" RETRY "));
|
|
975
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
976
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
977
|
+
const msg = import_chalk2.default.magenta(`auto-restart attempt ${import_chalk2.default.bold(`${attempt} / ${max}`)}`);
|
|
978
|
+
console.log(` ${import_chalk2.default.magenta("\u21BA")} ${badge} ${ts} ${sep} ${msg}`);
|
|
1426
979
|
}
|
|
1427
980
|
/**
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
* @method formatBytes
|
|
1431
|
-
* @private
|
|
1432
|
-
*
|
|
1433
|
-
* @param {number} bytes - Bytes to format
|
|
1434
|
-
*
|
|
1435
|
-
* @returns {string} Formatted size string
|
|
1436
|
-
*
|
|
1437
|
-
* @example
|
|
1438
|
-
* formatBytes(1048576) // returns "1.00 MB"
|
|
981
|
+
* LIMIT reached — give up restarting.
|
|
1439
982
|
*/
|
|
1440
|
-
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
return `${value.toFixed(2)} ${units[unitIndex]}`;
|
|
983
|
+
printCrashLimit(max) {
|
|
984
|
+
const badge = import_ansi_colors2.default.bgRed(import_ansi_colors2.default.white.bold(" ERROR "));
|
|
985
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
986
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
987
|
+
const msg = import_chalk2.default.red(`max crash restarts reached (${import_chalk2.default.bold(String(max))}), giving up`);
|
|
988
|
+
console.log(`
|
|
989
|
+
${import_chalk2.default.red("\u2718")} ${badge} ${ts} ${sep} ${msg}
|
|
990
|
+
`);
|
|
1449
991
|
}
|
|
1450
992
|
/**
|
|
1451
|
-
*
|
|
1452
|
-
*
|
|
1453
|
-
* @method isHMRActive
|
|
1454
|
-
* @public
|
|
1455
|
-
*
|
|
1456
|
-
* @returns {boolean} True if HMR is enabled and watching files, false otherwise
|
|
993
|
+
* Error — miscellaneous internal error.
|
|
1457
994
|
*/
|
|
1458
|
-
|
|
1459
|
-
|
|
995
|
+
printError(message) {
|
|
996
|
+
const badge = import_ansi_colors2.default.bgRed(import_ansi_colors2.default.white.bold(" ERROR "));
|
|
997
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
998
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
999
|
+
console.error(` ${import_chalk2.default.red("\u2718")} ${badge} ${ts} ${sep} ${import_chalk2.default.red(message)}`);
|
|
1460
1000
|
}
|
|
1461
1001
|
/**
|
|
1462
|
-
*
|
|
1463
|
-
*
|
|
1464
|
-
* @method getHMRInfo
|
|
1465
|
-
* @public
|
|
1466
|
-
*
|
|
1467
|
-
* @returns {any} HMR information object
|
|
1468
|
-
*
|
|
1469
|
-
* @remarks
|
|
1470
|
-
* Includes:
|
|
1471
|
-
* - Configuration settings from .env
|
|
1472
|
-
* - Current restart count
|
|
1473
|
-
* - Watcher status
|
|
1002
|
+
* Stopped — watcher shut down.
|
|
1474
1003
|
*/
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1004
|
+
printStopped() {
|
|
1005
|
+
const badge = import_ansi_colors2.default.bgBlackBright(import_ansi_colors2.default.white.bold(" STOPPED"));
|
|
1006
|
+
const ts = import_chalk2.default.blackBright(this.ts());
|
|
1007
|
+
const sep = import_chalk2.default.blackBright("|");
|
|
1008
|
+
console.log(` ${import_chalk2.default.gray("\u25A0")} ${badge} ${ts} ${sep} ${import_chalk2.default.gray("watcher stopped")}
|
|
1009
|
+
`);
|
|
1010
|
+
}
|
|
1011
|
+
// ─── Graceful shutdown ────────────────────────────────────────────────────
|
|
1012
|
+
setupProcessSignals() {
|
|
1013
|
+
const shutdown = async () => {
|
|
1014
|
+
console.log("");
|
|
1015
|
+
await this.stop();
|
|
1016
|
+
process.exit(0);
|
|
1487
1017
|
};
|
|
1018
|
+
process.once("SIGINT", shutdown);
|
|
1019
|
+
process.once("SIGTERM", shutdown);
|
|
1488
1020
|
}
|
|
1489
1021
|
};
|
|
1490
1022
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1491
1023
|
0 && (module.exports = {
|
|
1024
|
+
HotReloadWatcher,
|
|
1492
1025
|
WebServer,
|
|
1493
1026
|
envPath
|
|
1494
1027
|
});
|