opticore-webapp 1.0.70 → 1.0.72
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 +418 -25
- package/dist/index.d.cts +175 -1
- package/dist/index.d.ts +175 -1
- package/dist/index.js +441 -49
- package/dist/utils/translations/message.translation.en.json +4 -13
- package/dist/utils/translations/message.translation.fr.json +6 -2
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -30,20 +30,21 @@ 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
43
|
var import_opticore_catch_exception_error3 = require("opticore-catch-exception-error");
|
|
43
44
|
var import_opticore_express2 = require("opticore-express");
|
|
44
45
|
var import_opticore_env_access2 = require("opticore-env-access");
|
|
45
|
-
var
|
|
46
|
-
var
|
|
46
|
+
var import_opticore_http_response4 = require("opticore-http-response");
|
|
47
|
+
var import_opticore_translator3 = require("opticore-translator");
|
|
47
48
|
var import_opticore_request_call_event = require("opticore-request-call-event");
|
|
48
49
|
|
|
49
50
|
// src/core/handlers/eventProcess.handler.ts
|
|
@@ -149,16 +150,35 @@ var dependenciesContainerProvider = (localLang) => {
|
|
|
149
150
|
return new import_opticore_dependency_inject.SContainer(localLang, dependencies);
|
|
150
151
|
};
|
|
151
152
|
|
|
153
|
+
// src/application/service/core.service.ts
|
|
154
|
+
var import_opticore_dependency_inject2 = require("opticore-dependency-inject");
|
|
155
|
+
|
|
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);
|
|
168
|
+
};
|
|
169
|
+
|
|
152
170
|
// src/application/service/core.service.ts
|
|
153
171
|
var CoreService = class {
|
|
154
172
|
localLanguage;
|
|
155
173
|
environmentPath;
|
|
156
174
|
serverLog;
|
|
157
175
|
logger;
|
|
176
|
+
container;
|
|
158
177
|
constructor(localLang, environmentPath) {
|
|
159
178
|
this.loadTranslationFiles();
|
|
160
179
|
this.environmentPath = environmentPath;
|
|
161
180
|
this.localLanguage = localLang;
|
|
181
|
+
this.container = new import_opticore_dependency_inject2.SContainer(localLang);
|
|
162
182
|
this.serverLog = dependenciesContainerProvider(localLang).resolve("OpticoreLogger");
|
|
163
183
|
this.logger = dependenciesContainerProvider(localLang).resolve("LoggerCore");
|
|
164
184
|
}
|
|
@@ -298,7 +318,7 @@ var CoreService = class {
|
|
|
298
318
|
this.loadTranslationFiles();
|
|
299
319
|
try {
|
|
300
320
|
const getEnvironment = (0, import_opticore_env_access.getEnvironmentValue)(this.environmentPath);
|
|
301
|
-
const msg5 = getEnvironment.
|
|
321
|
+
const msg5 = getEnvironment.protocolTransfer === "" ? import_ansi_colors.default.underline(`http://${host}:${port}`) : import_ansi_colors.default.underline(`${getEnvironment.protocolTransfer}://${host}:${port}`);
|
|
302
322
|
const messages = [
|
|
303
323
|
import_opticore_translator.TranslationLoader.t("webServerListening", this.localLanguage),
|
|
304
324
|
import_opticore_translator.TranslationLoader.t("webServerUsingNodeVersion", this.localLanguage, { nodeVersion: this.getVersions().nodeVersion }),
|
|
@@ -318,17 +338,31 @@ var CoreService = class {
|
|
|
318
338
|
});
|
|
319
339
|
console.log(border);
|
|
320
340
|
console.log("\n");
|
|
321
|
-
this.logger.success({
|
|
322
|
-
title: import_opticore_translator.TranslationLoader.t("serverRunningTitle", this.localLanguage),
|
|
323
|
-
message: import_opticore_translator.TranslationLoader.t("serverRunningAt", this.localLanguage, { server: msg5 })
|
|
324
|
-
});
|
|
325
341
|
this.serverLog.serverLog({
|
|
326
|
-
timestamp: (
|
|
342
|
+
timestamp: parsingDateTimeUtils(getEnvironment.localFormatTime),
|
|
327
343
|
level: "SERVER",
|
|
328
344
|
title: import_opticore_translator.TranslationLoader.t("serverRunningTitle", this.localLanguage),
|
|
329
345
|
typeName: import_opticore_translator.TranslationLoader.t("opticoreServerTypeName", this.localLanguage),
|
|
330
346
|
message: import_opticore_translator.TranslationLoader.t("serverRunningAt", this.localLanguage, { server: msg5 })
|
|
331
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
|
+
}
|
|
332
366
|
} catch (err) {
|
|
333
367
|
this.logger.error({
|
|
334
368
|
message: err.message,
|
|
@@ -392,10 +426,284 @@ var SServerStartError = (err, environmentPath) => {
|
|
|
392
426
|
};
|
|
393
427
|
|
|
394
428
|
// src/core/webServer.core.ts
|
|
395
|
-
var
|
|
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
|
+
|
|
464
|
+
// src/hotReload/hotReload.watcher.ts
|
|
465
|
+
var import_fs2 = require("fs");
|
|
466
|
+
var import_promises = require("fs/promises");
|
|
467
|
+
var import_path2 = require("path");
|
|
468
|
+
var import_dotenv = require("dotenv");
|
|
469
|
+
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
470
|
+
var import_ansi_colors2 = __toESM(require("ansi-colors"), 1);
|
|
471
|
+
var import_gradient_string = __toESM(require("gradient-string"), 1);
|
|
472
|
+
var DEFAULT_WATCH_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
473
|
+
var DEFAULT_HOT_RELOAD_EXTENSIONS = [".json"];
|
|
474
|
+
var DEFAULT_IGNORE = [
|
|
475
|
+
"node_modules",
|
|
476
|
+
"dist",
|
|
477
|
+
".git",
|
|
478
|
+
"package.json",
|
|
479
|
+
"package-lock.json",
|
|
480
|
+
".idea",
|
|
481
|
+
".vscode",
|
|
482
|
+
"coverage",
|
|
483
|
+
"logs"
|
|
484
|
+
];
|
|
485
|
+
var DEFAULT_DEBOUNCE_MS = 300;
|
|
486
|
+
var HotReloadWatcher = class {
|
|
487
|
+
cfg;
|
|
488
|
+
server = null;
|
|
489
|
+
watchers = [];
|
|
490
|
+
debounceTimer = null;
|
|
491
|
+
restarting = false;
|
|
492
|
+
constructor(config) {
|
|
493
|
+
const c = config ?? {};
|
|
494
|
+
this.cfg = {
|
|
495
|
+
rootDir: (0, import_path2.resolve)(c.rootDir ?? process.cwd()),
|
|
496
|
+
watchDirs: c.watchDirs ?? [],
|
|
497
|
+
watchExtensions: c.watchExtensions ?? DEFAULT_WATCH_EXTENSIONS,
|
|
498
|
+
ignore: [...DEFAULT_IGNORE, ...c.ignore ?? []],
|
|
499
|
+
envFile: c.envFile ?? ".env",
|
|
500
|
+
hotReloadExtensions: c.hotReloadExtensions ?? DEFAULT_HOT_RELOAD_EXTENSIONS,
|
|
501
|
+
debounceMs: c.debounceMs ?? DEFAULT_DEBOUNCE_MS
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
// ─── Called by WebServerCore once the HTTP server is listening ────────────
|
|
505
|
+
async attach(server) {
|
|
506
|
+
this.server = server;
|
|
507
|
+
this.printBanner();
|
|
508
|
+
await this.setupWatchers();
|
|
509
|
+
this.setupProcessSignals();
|
|
510
|
+
}
|
|
511
|
+
// ─── File watching ────────────────────────────────────────────────────────
|
|
512
|
+
async setupWatchers() {
|
|
513
|
+
const dirs = [
|
|
514
|
+
this.cfg.rootDir,
|
|
515
|
+
...this.cfg.watchDirs.map((d) => (0, import_path2.resolve)(d))
|
|
516
|
+
];
|
|
517
|
+
for (const dir of dirs) {
|
|
518
|
+
await this.watchRecursive(dir);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
async watchRecursive(dir) {
|
|
522
|
+
if (this.shouldIgnoreDir(dir)) return;
|
|
523
|
+
try {
|
|
524
|
+
await (0, import_promises.access)(dir);
|
|
525
|
+
} catch {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
try {
|
|
529
|
+
const w = (0, import_fs2.watch)(dir, (_, filename) => {
|
|
530
|
+
if (filename) this.onFileChange((0, import_path2.join)(dir, filename));
|
|
531
|
+
});
|
|
532
|
+
w.on("error", () => {
|
|
533
|
+
});
|
|
534
|
+
this.watchers.push(w);
|
|
535
|
+
const entries = await (0, import_promises.readdir)(dir, { withFileTypes: true });
|
|
536
|
+
for (const entry of entries) {
|
|
537
|
+
if (entry.isDirectory()) await this.watchRecursive((0, import_path2.join)(dir, entry.name));
|
|
538
|
+
}
|
|
539
|
+
} catch {
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
// ─── Change handling ──────────────────────────────────────────────────────
|
|
543
|
+
onFileChange(filePath) {
|
|
544
|
+
if (this.shouldIgnoreFile(filePath)) return;
|
|
545
|
+
if (!this.isWatched(filePath)) return;
|
|
546
|
+
if (this.restarting) return;
|
|
547
|
+
const rel = (0, import_path2.relative)(this.cfg.rootDir, filePath);
|
|
548
|
+
if (this.isHotReloadable(filePath)) {
|
|
549
|
+
this.doHotReload(filePath, rel);
|
|
550
|
+
} else {
|
|
551
|
+
this.scheduleRestart(rel);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
doHotReload(filePath, rel) {
|
|
555
|
+
if (this.isEnvFile(filePath)) {
|
|
556
|
+
(0, import_dotenv.config)({ path: filePath, override: true });
|
|
557
|
+
this.printHot(rel, "env variables reloaded");
|
|
558
|
+
} else {
|
|
559
|
+
this.printHot(rel, "json config reloaded");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
scheduleRestart(rel) {
|
|
563
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
564
|
+
this.debounceTimer = setTimeout(() => {
|
|
565
|
+
this.restarting = true;
|
|
566
|
+
this.printReloading(rel);
|
|
567
|
+
this.closeAndExit();
|
|
568
|
+
}, this.cfg.debounceMs);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Gracefully close the HTTP server so in-flight requests can finish,
|
|
572
|
+
* then exit with code 0 — the external runner restarts the process.
|
|
573
|
+
*/
|
|
574
|
+
closeAndExit() {
|
|
575
|
+
if (!this.server) {
|
|
576
|
+
process.exit(0);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
this.server.close(() => {
|
|
580
|
+
process.exit(0);
|
|
581
|
+
});
|
|
582
|
+
setTimeout(() => {
|
|
583
|
+
process.exit(0);
|
|
584
|
+
}, 3e3).unref();
|
|
585
|
+
}
|
|
586
|
+
// ─── Filters ──────────────────────────────────────────────────────────────
|
|
587
|
+
shouldIgnoreDir(dir) {
|
|
588
|
+
return this.cfg.ignore.some(
|
|
589
|
+
(p) => dir.includes(`/${p}`) || dir.endsWith(`/${p}`) || dir.endsWith(p)
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
shouldIgnoreFile(filePath) {
|
|
593
|
+
const name = (0, import_path2.basename)(filePath);
|
|
594
|
+
const rel = (0, import_path2.relative)(this.cfg.rootDir, filePath);
|
|
595
|
+
return this.cfg.ignore.some(
|
|
596
|
+
(p) => name === p || rel.includes(p) || filePath.includes(`/${p}/`)
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
isWatched(filePath) {
|
|
600
|
+
if (this.isEnvFile(filePath)) return true;
|
|
601
|
+
return this.cfg.watchExtensions.includes((0, import_path2.extname)(filePath));
|
|
602
|
+
}
|
|
603
|
+
isHotReloadable(filePath) {
|
|
604
|
+
if (this.isEnvFile(filePath)) return true;
|
|
605
|
+
return this.cfg.hotReloadExtensions.includes((0, import_path2.extname)(filePath));
|
|
606
|
+
}
|
|
607
|
+
isEnvFile(filePath) {
|
|
608
|
+
const name = (0, import_path2.basename)(filePath);
|
|
609
|
+
return name === this.cfg.envFile || name.startsWith(".env");
|
|
610
|
+
}
|
|
611
|
+
// ─── ANSI strip (box width calculation) ───────────────────────────────────
|
|
612
|
+
strip(str) {
|
|
613
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
614
|
+
}
|
|
615
|
+
// ─── Timestamp ────────────────────────────────────────────────────────────
|
|
616
|
+
ts() {
|
|
617
|
+
const n = /* @__PURE__ */ new Date();
|
|
618
|
+
return [n.getHours(), n.getMinutes(), n.getSeconds()].map((v) => String(v).padStart(2, "0")).join(":");
|
|
619
|
+
}
|
|
620
|
+
// ─── Console output ───────────────────────────────────────────────────────
|
|
621
|
+
/**
|
|
622
|
+
* Startup banner — same bgGreen box style as CoreService.infoServer().
|
|
623
|
+
*
|
|
624
|
+
* OPTICORE HOT RELOAD ← gradient
|
|
625
|
+
* ████████████████████████████████ ← bgGreen border
|
|
626
|
+
* root ./src
|
|
627
|
+
* watching .ts .js .json .env
|
|
628
|
+
* debounce 300ms
|
|
629
|
+
* ████████████████████████████████ ← bgGreen border
|
|
630
|
+
* watching for changes...
|
|
631
|
+
*/
|
|
632
|
+
printBanner() {
|
|
633
|
+
const rootRel = (0, import_path2.relative)(process.cwd(), this.cfg.rootDir) || ".";
|
|
634
|
+
const extStr = [...this.cfg.watchExtensions, ".env"].join(" ");
|
|
635
|
+
const ignoreParts = this.cfg.ignore.slice(0, 4);
|
|
636
|
+
const ignoreMore = this.cfg.ignore.length > 4 ? ` ${import_chalk2.default.blackBright(`+${this.cfg.ignore.length - 4} more`)}` : "";
|
|
637
|
+
const ignoreStr = import_chalk2.default.blackBright(ignoreParts.join(" ")) + ignoreMore;
|
|
638
|
+
const TITLE = "OPTICORE HOT RELOAD";
|
|
639
|
+
const rows = [
|
|
640
|
+
` root ${import_chalk2.default.white(rootRel)}`,
|
|
641
|
+
` watching ${import_chalk2.default.cyan(extStr)}`,
|
|
642
|
+
` ignoring ${ignoreStr}`,
|
|
643
|
+
` debounce ${import_chalk2.default.white(`${this.cfg.debounceMs}ms`)}`
|
|
644
|
+
];
|
|
645
|
+
const maxLen = Math.max(
|
|
646
|
+
TITLE.length + 4,
|
|
647
|
+
...rows.map((r) => this.strip(r).length)
|
|
648
|
+
) + 4;
|
|
649
|
+
const border = import_chalk2.default.bgGreen.white(" ".repeat(maxLen));
|
|
650
|
+
const titlePad = " ".repeat(Math.max(0, Math.floor((maxLen - TITLE.length) / 2)));
|
|
651
|
+
console.log("\n" + titlePad + (0, import_gradient_string.default)(["#43e97b", "#38f9d7", "#00c6fb"])(TITLE));
|
|
652
|
+
console.log(border);
|
|
653
|
+
for (const row of rows) {
|
|
654
|
+
const pad = Math.max(0, maxLen - this.strip(row).length - 2);
|
|
655
|
+
console.log(import_chalk2.default.bgGreen.white(` ${row}${" ".repeat(pad)} `));
|
|
656
|
+
}
|
|
657
|
+
console.log(border);
|
|
658
|
+
console.log(import_chalk2.default.blackBright(` watching for changes...
|
|
659
|
+
`));
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* ✔ [ HOT ] 14:23:45 | .env → env variables reloaded
|
|
663
|
+
*/
|
|
664
|
+
printHot(file, action) {
|
|
665
|
+
const badge = import_ansi_colors2.default.bgCyan(import_ansi_colors2.default.white.bold(" HOT "));
|
|
666
|
+
const filePart = import_chalk2.default.cyan.bold(file.padEnd(32));
|
|
667
|
+
console.log(
|
|
668
|
+
` ${import_chalk2.default.green("\u2714")} ${badge} ${import_chalk2.default.blackBright(this.ts())} ${import_chalk2.default.blackBright("|")} ${filePart} ${import_chalk2.default.green("\u2192")} ${import_chalk2.default.green(action)}`
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* ⚡ [ RELOAD ] 14:24:03 | src/routes/user.ts → restarting server...
|
|
673
|
+
*/
|
|
674
|
+
printReloading(file) {
|
|
675
|
+
const badge = import_ansi_colors2.default.bgYellow(import_ansi_colors2.default.white.bold(" RELOAD "));
|
|
676
|
+
const filePart = import_chalk2.default.yellow.bold(file.padEnd(32));
|
|
677
|
+
console.log(
|
|
678
|
+
`
|
|
679
|
+
${import_chalk2.default.yellow("\u26A1")} ${badge} ${import_chalk2.default.blackBright(this.ts())} ${import_chalk2.default.blackBright("|")} ${filePart} ${import_chalk2.default.yellow("\u2192")} ${import_chalk2.default.yellow("restarting server...")}
|
|
680
|
+
`
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
// ─── Graceful shutdown on CTRL+C ──────────────────────────────────────────
|
|
684
|
+
setupProcessSignals() {
|
|
685
|
+
const shutdown = () => {
|
|
686
|
+
const badge = import_ansi_colors2.default.bgBlackBright(import_ansi_colors2.default.white.bold(" STOPPED"));
|
|
687
|
+
console.log(
|
|
688
|
+
`
|
|
689
|
+
${import_chalk2.default.gray("\u25A0")} ${badge} ${import_chalk2.default.blackBright(this.ts())} ${import_chalk2.default.blackBright("|")} ${import_chalk2.default.gray("watcher stopped")}
|
|
690
|
+
`
|
|
691
|
+
);
|
|
692
|
+
this.watchers.forEach((w) => {
|
|
693
|
+
w.close();
|
|
694
|
+
});
|
|
695
|
+
process.exit(0);
|
|
696
|
+
};
|
|
697
|
+
process.once("SIGINT", shutdown);
|
|
698
|
+
process.once("SIGTERM", shutdown);
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// src/core/webServer.core.ts
|
|
396
703
|
var WebServerCore = class {
|
|
397
704
|
serverUtility;
|
|
398
705
|
expressApp = (0, import_opticore_express2.express)();
|
|
706
|
+
container;
|
|
399
707
|
localLanguage;
|
|
400
708
|
loggerConfig;
|
|
401
709
|
routerExpressApp;
|
|
@@ -403,6 +711,7 @@ var WebServerCore = class {
|
|
|
403
711
|
environmentPath;
|
|
404
712
|
serverListenEvent;
|
|
405
713
|
dependenciesRegistered = false;
|
|
714
|
+
hotReloadCfg;
|
|
406
715
|
constructor(paramsConstructor) {
|
|
407
716
|
this.loadTranslationFiles();
|
|
408
717
|
this.stackTraceErrorHandling();
|
|
@@ -411,6 +720,7 @@ var WebServerCore = class {
|
|
|
411
720
|
this.loggerConfig = paramsConstructor.loggerConfig;
|
|
412
721
|
this.localLanguage = paramsConstructor.localLanguage;
|
|
413
722
|
this.environmentPath = paramsConstructor.environmentPath;
|
|
723
|
+
this.container = new import_opticore_dependency_inject3.SContainer(paramsConstructor.localLanguage);
|
|
414
724
|
this.expressApp.use(import_opticore_express2.express.json());
|
|
415
725
|
this.expressApp.use(import_opticore_express2.express.raw());
|
|
416
726
|
this.expressApp.use(import_opticore_express2.express.text());
|
|
@@ -418,17 +728,20 @@ var WebServerCore = class {
|
|
|
418
728
|
this.expressApp.use((0, import_cors.default)(paramsConstructor.corsOriginOptions));
|
|
419
729
|
this.serverListenEvent = new import_opticore_catch_exception_error3.ServerListenEventError(paramsConstructor.localLanguage);
|
|
420
730
|
this.serverUtility = new CoreService(paramsConstructor.localLanguage, paramsConstructor.environmentPath);
|
|
731
|
+
const hr = paramsConstructor.hotReload;
|
|
732
|
+
this.hotReloadCfg = !hr ? null : hr === true ? {} : hr;
|
|
421
733
|
}
|
|
734
|
+
/**
|
|
735
|
+
*
|
|
736
|
+
* @param dependencies
|
|
737
|
+
*/
|
|
422
738
|
registerDependencies(dependencies2) {
|
|
739
|
+
this.loadTranslationFiles();
|
|
423
740
|
try {
|
|
741
|
+
getEnvFileLoadingService(".env", this.localLanguage);
|
|
424
742
|
if (dependencies2 && dependencies2.length > 0) {
|
|
425
743
|
dependencies2.forEach((dependency) => {
|
|
426
|
-
|
|
427
|
-
});
|
|
428
|
-
} else {
|
|
429
|
-
SLogger(this.environmentPath).logger.info({
|
|
430
|
-
message: import_opticore_translator2.TranslationLoader.t("NO_REGISTER_DEPENDENCIES", this.localLanguage),
|
|
431
|
-
title: import_opticore_translator2.TranslationLoader.t("REGISTER_DEPENDENCIES", this.localLanguage)
|
|
744
|
+
this.container.register(dependency.key, dependency.factory, dependency.scope);
|
|
432
745
|
});
|
|
433
746
|
}
|
|
434
747
|
} catch (err) {
|
|
@@ -437,12 +750,19 @@ var WebServerCore = class {
|
|
|
437
750
|
title: "Register Dependencies",
|
|
438
751
|
errorType: err.code,
|
|
439
752
|
stackTrace: err.stack,
|
|
440
|
-
httpCodeValue:
|
|
753
|
+
httpCodeValue: import_opticore_http_response4.HttpStatusCode.INTERNAL_SERVER_ERROR
|
|
441
754
|
});
|
|
442
755
|
}
|
|
443
756
|
}
|
|
757
|
+
/**
|
|
758
|
+
*
|
|
759
|
+
* @param routers
|
|
760
|
+
* @param databaseCallback
|
|
761
|
+
* @param dependenciesProvider
|
|
762
|
+
*/
|
|
444
763
|
onStartServer(routers, databaseCallback, dependenciesProvider) {
|
|
445
764
|
this.loadTranslationFiles();
|
|
765
|
+
getEnvFileLoadingService(".env", this.localLanguage);
|
|
446
766
|
if (this.getEnvironmentValue.appPort === "" && Number(this.getEnvironmentValue.appPort) === 0) {
|
|
447
767
|
this.serverListenEvent.hostPortUndefined(Number(this.getEnvironmentValue.appPort));
|
|
448
768
|
} else if (this.getEnvironmentValue.appHost === "") {
|
|
@@ -451,29 +771,41 @@ var WebServerCore = class {
|
|
|
451
771
|
this.serverListenEvent.portUndefined();
|
|
452
772
|
} else if (this.localLanguage === "") {
|
|
453
773
|
SLogger(this.environmentPath).logger.error({
|
|
454
|
-
message:
|
|
455
|
-
title:
|
|
456
|
-
errorType:
|
|
774
|
+
message: import_opticore_translator3.TranslationLoader.t("noDefaultLocalLang", this.localLanguage),
|
|
775
|
+
title: import_opticore_translator3.TranslationLoader.t("noLocalLang", this.localLanguage),
|
|
776
|
+
errorType: import_opticore_translator3.TranslationLoader.t("localLangMissing", this.localLanguage),
|
|
457
777
|
stackTrace: void 0,
|
|
458
|
-
httpCodeValue:
|
|
778
|
+
httpCodeValue: import_opticore_http_response4.HttpStatusCode.NOT_FOUND
|
|
459
779
|
});
|
|
460
780
|
} else {
|
|
461
|
-
|
|
781
|
+
const server = this.expressApp.listen(
|
|
462
782
|
Number(this.getEnvironmentValue.appPort),
|
|
463
783
|
() => {
|
|
464
784
|
this.loadTranslationFiles();
|
|
465
785
|
try {
|
|
466
786
|
databaseCallback(this.getEnvironmentValue);
|
|
467
|
-
|
|
468
|
-
|
|
787
|
+
if (dependenciesProvider) {
|
|
788
|
+
this.registerDependencies(dependenciesProvider);
|
|
789
|
+
}
|
|
790
|
+
this.container.loadServices();
|
|
791
|
+
this.expressApp.use(import_opticore_express2.express.static(path3.join(import_node_process4.default.cwd(), "public/template")));
|
|
469
792
|
this.registerRoutes(routers);
|
|
793
|
+
const resolvedHmr = this.resolveHotReloadConfig();
|
|
794
|
+
if (resolvedHmr !== null) {
|
|
795
|
+
new HotReloadWatcher(resolvedHmr).attach(server);
|
|
796
|
+
}
|
|
470
797
|
} catch (err) {
|
|
471
798
|
SServerStartError(err, this.environmentPath);
|
|
472
799
|
}
|
|
473
800
|
}
|
|
474
801
|
);
|
|
802
|
+
return server;
|
|
475
803
|
}
|
|
476
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
*
|
|
807
|
+
* @param serverWeb
|
|
808
|
+
*/
|
|
477
809
|
onListeningOnServerEvent(serverWeb) {
|
|
478
810
|
this.loadTranslationFiles();
|
|
479
811
|
serverWeb.on(import_opticore_catch_exception_error3.CEventNameError.error, (err) => {
|
|
@@ -486,6 +818,10 @@ var WebServerCore = class {
|
|
|
486
818
|
this.infoWebApp();
|
|
487
819
|
});
|
|
488
820
|
}
|
|
821
|
+
/**
|
|
822
|
+
*
|
|
823
|
+
* @param serverWeb
|
|
824
|
+
*/
|
|
489
825
|
onRequestOnServerEvent(serverWeb) {
|
|
490
826
|
this.loadTranslationFiles();
|
|
491
827
|
serverWeb.on(import_opticore_catch_exception_error3.CEventNameError.request, (req, res) => {
|
|
@@ -507,6 +843,62 @@ var WebServerCore = class {
|
|
|
507
843
|
loadTranslationFiles() {
|
|
508
844
|
loaderTranslationFile(this.localLanguage);
|
|
509
845
|
}
|
|
846
|
+
/**
|
|
847
|
+
* Resolve the final HotReloadConfig by merging constructor config with
|
|
848
|
+
* HMR environment variables.
|
|
849
|
+
*
|
|
850
|
+
* Priority (highest → lowest):
|
|
851
|
+
* 1. Constructor hotReload properties (explicit code-level config)
|
|
852
|
+
* 2. HMR_* env variables (runtime / per-environment config)
|
|
853
|
+
* 3. HotReloadWatcher internal defaults (built-in fallbacks)
|
|
854
|
+
*
|
|
855
|
+
* The watcher starts when:
|
|
856
|
+
* - constructor passed hotReload: true | HotReloadConfig
|
|
857
|
+
* - OR HMR_ENABLED=true in the .env file
|
|
858
|
+
*/
|
|
859
|
+
resolveHotReloadConfig() {
|
|
860
|
+
const env = this.getEnvironmentValue;
|
|
861
|
+
if (this.hotReloadCfg === null && !env.hmrEnabled) {
|
|
862
|
+
return null;
|
|
863
|
+
}
|
|
864
|
+
const base = this.hotReloadCfg ?? {};
|
|
865
|
+
const envExtensions = this.hmrExtractExtensions(env.hmrWatchPatterns);
|
|
866
|
+
const envIgnore = this.hmrExtractIgnore(env.hmrIgnorePatterns);
|
|
867
|
+
return {
|
|
868
|
+
rootDir: base.rootDir,
|
|
869
|
+
watchDirs: base.watchDirs,
|
|
870
|
+
watchExtensions: base.watchExtensions ?? (envExtensions.length ? envExtensions : void 0),
|
|
871
|
+
ignore: base.ignore ?? (envIgnore.length ? envIgnore : void 0),
|
|
872
|
+
hotReloadExtensions: base.hotReloadExtensions,
|
|
873
|
+
debounceMs: base.debounceMs ?? (env.hmrDebounceMs > 0 ? env.hmrDebounceMs : void 0),
|
|
874
|
+
envFile: base.envFile
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Extract file extensions from glob patterns such as "src/** /*.ts".
|
|
879
|
+
* "src/** /*.ts"
|
|
880
|
+
* ".env" skipped, handled natively by the watcher
|
|
881
|
+
*/
|
|
882
|
+
hmrExtractExtensions(patterns) {
|
|
883
|
+
const exts = /* @__PURE__ */ new Set();
|
|
884
|
+
for (const p of patterns) {
|
|
885
|
+
const m = p.match(/\*(\.[a-zA-Z0-9]+)$/);
|
|
886
|
+
if (m) {
|
|
887
|
+
exts.add(m[1]);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return [...exts];
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Extract ignore names from glob patterns such as "node_modules/**".
|
|
894
|
+
* "node_modules/**" → "node_modules"
|
|
895
|
+
* "dist/**" → "dist"
|
|
896
|
+
*/
|
|
897
|
+
hmrExtractIgnore(patterns) {
|
|
898
|
+
return [...new Set(
|
|
899
|
+
patterns.map((p) => p.split("/")[0]).filter(Boolean)
|
|
900
|
+
)];
|
|
901
|
+
}
|
|
510
902
|
/**
|
|
511
903
|
*
|
|
512
904
|
* @param allFeatureRoutes
|
|
@@ -540,6 +932,7 @@ var WebServerCore = class {
|
|
|
540
932
|
};
|
|
541
933
|
// Annotate the CommonJS export names for ESM import in node:
|
|
542
934
|
0 && (module.exports = {
|
|
935
|
+
HotReloadWatcher,
|
|
543
936
|
WebServer,
|
|
544
937
|
envPath
|
|
545
938
|
});
|