opticore-webapp 1.0.67 → 1.0.68

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.js CHANGED
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/core/webServer.core.ts
9
2
  import * as path2 from "path";
10
3
  import process4 from "process";
@@ -12,6 +5,10 @@ import corsOrigin from "cors";
12
5
  import { CEventNameError as eventName2, ServerListenEventError as ServerListenEventError2 } from "opticore-catch-exception-error";
13
6
  import { express } from "opticore-express";
14
7
  import { getEnvironnementValue as getEnvironnementValue2 } from "opticore-env-access";
8
+ import { requestCallsEvent } from "opticore-request-call-event";
9
+ import { SContainer as SContainer2 } from "opticore-dependency-inject";
10
+ import { HttpStatusCode as HttpStatusCode3 } from "opticore-http-response";
11
+ import { TranslationLoader as TranslationLoader2 } from "opticore-translator";
15
12
 
16
13
  // src/core/handlers/eventProcess.handler.ts
17
14
  import process from "process";
@@ -449,13 +446,11 @@ var SServerStartError = (err, environmentPath) => {
449
446
  };
450
447
 
451
448
  // src/core/webServer.core.ts
452
- import { requestCallsEvent } from "opticore-request-call-event";
453
- import { SContainer as SContainer2 } from "opticore-dependency-inject";
454
- import { HttpStatusCode as HttpStatusCode3 } from "opticore-http-response";
455
- import { TranslationLoader as TranslationLoader2 } from "opticore-translator";
449
+ import { WebServerWatcherService } from "opticore-watcher";
456
450
  var WebServerCore = class {
457
451
  serverUtility;
458
452
  expressApp = express();
453
+ fileWatcher;
459
454
  localLanguage;
460
455
  loggerConfig;
461
456
  routerExpressApp;
@@ -466,13 +461,9 @@ var WebServerCore = class {
466
461
  currentDependencies = [];
467
462
  server = void 0;
468
463
  errorEmitter;
469
- // ✅✅✅ ÉTAT DU SERVEUR
470
- serverState = "READY";
471
- lastError = null;
472
- // Statistiques
473
- hotReloadAttempts = 0;
474
- hotReloadSuccesses = 0;
475
- hotReloadFailures = 0;
464
+ isWatcherEnabled = true;
465
+ serverStatus = "STARTING";
466
+ serverStartTime = /* @__PURE__ */ new Date();
476
467
  constructor(paramsConstructor) {
477
468
  this.getEnvironment = getEnvironnementValue2(paramsConstructor.environmentPath);
478
469
  this.routerExpressApp = paramsConstructor.app;
@@ -486,8 +477,6 @@ var WebServerCore = class {
486
477
  this.expressApp.use(corsOrigin(paramsConstructor.corsOriginOptions));
487
478
  this.serverListenEvent = new ServerListenEventError2(paramsConstructor.localLanguage);
488
479
  this.serverUtility = new CoreService(paramsConstructor.localLanguage, paramsConstructor.environmentPath);
489
- this.setupSignalHandlers();
490
- this.setupIPCHandlers();
491
480
  }
492
481
  onStartServer(routers, databaseCallback, dependenciesProvider) {
493
482
  loaderTranslationFile(this.localLanguage);
@@ -520,11 +509,7 @@ var WebServerCore = class {
520
509
  this.getEnvironment.appHost,
521
510
  () => {
522
511
  try {
523
- SLogger(this.localLanguage).logger.info({
524
- message: TranslationLoader2.t("HOT_RELOAD_READY", this.localLanguage),
525
- title: TranslationLoader2.t("HOT_RELOAD", this.localLanguage)
526
- });
527
- if (databaseCallback) {
512
+ if (databaseCallback && typeof databaseCallback === "function") {
528
513
  databaseCallback(this.getEnvironment);
529
514
  }
530
515
  new SContainer2(this.localLanguage, this.currentDependencies);
@@ -532,9 +517,10 @@ var WebServerCore = class {
532
517
  this.registerRoutes(this.currentRoutes);
533
518
  this.setupErrorHandling();
534
519
  this.setupServerEvents();
535
- this.serverState = "READY";
520
+ if (this.isWatcherEnabled) {
521
+ this.initializeFileWatcher();
522
+ }
536
523
  this.infoWebApp();
537
- this.notifyServerReady();
538
524
  } catch (err) {
539
525
  SLogger(this.localLanguage).logger.error({
540
526
  title: TranslationLoader2.t("STARTUP_ERROR", this.localLanguage),
@@ -550,7 +536,7 @@ var WebServerCore = class {
550
536
  return this.server;
551
537
  }
552
538
  /**
553
- * ✅✅✅ Configuration de la gestion d'erreurs
539
+ * Error handling configuration
554
540
  */
555
541
  setupErrorHandling() {
556
542
  SLogger(this.localLanguage).logger.info({
@@ -560,18 +546,24 @@ var WebServerCore = class {
560
546
  this.errorEmitter = eventProcessHandler(this.localLanguage, this.expressApp);
561
547
  if (this.errorEmitter) {
562
548
  this.errorEmitter.on("transformError", (error) => {
563
- SLogger(this.localLanguage).logger.info({
564
- title: TranslationLoader2.t("", this.localLanguage),
565
- message: TranslationLoader2.t("", this.localLanguage)
549
+ SLogger(this.localLanguage).logger.error({
550
+ title: TranslationLoader2.t("TRANSFORM_ERROR", this.localLanguage),
551
+ message: error.message,
552
+ errorType: error.name,
553
+ stackTrace: error.stackTrace,
554
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
566
555
  });
567
- this.lastError = error;
568
- this.serverState = "BLOCKED";
569
- this.notifyWatcherBlockedByError(error);
570
556
  });
571
557
  this.errorEmitter.on("error", (error) => {
572
558
  SLogger(this.localLanguage).logger.info({
573
559
  title: TranslationLoader2.t("ERROR_EMITTED", this.localLanguage),
574
- message: `Error emitted: ${error.message}`
560
+ message: error.message
561
+ });
562
+ });
563
+ this.errorEmitter.on("hotReload", (data) => {
564
+ SLogger(this.localLanguage).logger.info({
565
+ title: TranslationLoader2.t("HOT_RELOAD_EVENT", this.localLanguage),
566
+ message: `Hot reload triggered for ${data.file}`
575
567
  });
576
568
  });
577
569
  }
@@ -580,6 +572,9 @@ var WebServerCore = class {
580
572
  message: TranslationLoader2.t("ERROR_HANDLING_CONFIGURED", this.localLanguage)
581
573
  });
582
574
  }
575
+ /**
576
+ * Setup server events
577
+ */
583
578
  setupServerEvents() {
584
579
  if (!this.server) return;
585
580
  this.server.on(eventName2.error, (err) => {
@@ -603,145 +598,353 @@ var WebServerCore = class {
603
598
  );
604
599
  });
605
600
  }
606
- notifyServerReady() {
607
- setTimeout(() => {
608
- if (process4.send) {
609
- process4.send({
610
- type: "SERVER_READY",
611
- timestamp: Date.now(),
612
- port: Number(this.getEnvironment.appPort),
613
- host: this.getEnvironment.appHost,
614
- message: "Server ready for hot reload"
615
- });
616
- }
617
- }, 100);
601
+ /**
602
+ * Initialize file watcher
603
+ */
604
+ initializeFileWatcher() {
605
+ try {
606
+ this.fileWatcher = new WebServerWatcherService(this.localLanguage);
607
+ this.setupWatcherEvents();
608
+ this.fileWatcher.startWatching();
609
+ this.fileWatcher.setHotReload(true);
610
+ SLogger(this.localLanguage).logger.info({
611
+ title: TranslationLoader2.t("WATCHER_INITIALIZED", this.localLanguage),
612
+ message: "File watcher has been initialized successfully"
613
+ });
614
+ } catch (error) {
615
+ SLogger(this.localLanguage).logger.error({
616
+ title: TranslationLoader2.t("WATCHER_INIT_ERROR", this.localLanguage),
617
+ message: `Failed to initialize file watcher: ${error.message}`,
618
+ errorType: "WatcherInitializationError",
619
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
620
+ });
621
+ }
618
622
  }
619
- setupSignalHandlers() {
620
- process4.on("SIGHUP", async () => {
621
- if (this.serverState === "READY") {
623
+ /**
624
+ * Setup watcher events
625
+ */
626
+ setupWatcherEvents() {
627
+ if (!this.fileWatcher) return;
628
+ try {
629
+ this.fileWatcher.on("fileChangeDetected", (data) => {
630
+ this.handleFileChange(data);
631
+ });
632
+ this.fileWatcher.on("hotReloadRequired", (data) => {
633
+ this.handleHotReload(data);
634
+ });
635
+ this.fileWatcher.on("watcherError", (error) => {
636
+ this.handleWatcherError(error);
637
+ });
638
+ this.fileWatcher.on("started", () => {
622
639
  SLogger(this.localLanguage).logger.info({
623
- title: TranslationLoader2.t("SIGHUP", this.localLanguage),
624
- message: TranslationLoader2.t("RECEIVED_SIGHUP", this.localLanguage)
640
+ title: TranslationLoader2.t("WATCHER_STARTED", this.localLanguage),
641
+ message: TranslationLoader2.t("FILE_WATCHER_ACTIVE", this.localLanguage)
625
642
  });
626
- await this.performTrueHotReload();
627
- }
628
- });
629
- process4.on("SIGTERM", () => {
630
- SLogger(this.localLanguage).logger.info({
631
- title: TranslationLoader2.t("SIGHUP", this.localLanguage),
632
- message: TranslationLoader2.t("RECEIVED_SIGHUP", this.localLanguage)
633
643
  });
634
- this.shutdown();
635
- });
636
- process4.on("SIGINT", () => {
637
- SLogger(this.localLanguage).logger.info({
638
- title: TranslationLoader2.t("SIGINT", this.localLanguage),
639
- message: TranslationLoader2.t("RECEIVED_SIGINT", this.localLanguage)
644
+ this.fileWatcher.on("stopped", () => {
645
+ SLogger(this.localLanguage).logger.info({
646
+ title: TranslationLoader2.t("WATCHER_STOPPED", this.localLanguage),
647
+ message: TranslationLoader2.t("FILE_WATCHER_INACTIVE", this.localLanguage)
648
+ });
640
649
  });
641
- this.shutdown();
642
- });
650
+ } catch (error) {
651
+ SLogger(this.localLanguage).logger.error({
652
+ title: TranslationLoader2.t("WATCHER_EVENTS_ERROR", this.localLanguage),
653
+ message: `Failed to setup watcher events: ${error.message}`,
654
+ errorType: "WatcherEventsError",
655
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
656
+ });
657
+ }
643
658
  }
644
- setupIPCHandlers() {
645
- if (!process4.send) {
646
- SLogger(this.localLanguage).logger.info({
647
- title: TranslationLoader2.t("IPC", this.localLanguage),
648
- message: TranslationLoader2.t("IPC_NOT_AVAILABLE", this.localLanguage)
659
+ /**
660
+ * Handle file changes detected by watcher
661
+ */
662
+ handleFileChange(data) {
663
+ const { event: event2, action, requiresReload } = data;
664
+ SLogger(this.localLanguage).logger.info({
665
+ title: TranslationLoader2.t("FILE_CHANGE_HANDLED", this.localLanguage),
666
+ message: TranslationLoader2.t(
667
+ "PROCESSING_FILE_CHANGE",
668
+ this.localLanguage
669
+ ).replace(
670
+ "{file}",
671
+ path2.basename(event2.filePath)
672
+ ).replace(
673
+ "{action}",
674
+ action
675
+ )
676
+ });
677
+ if (this.errorEmitter) {
678
+ this.errorEmitter.emit("fileChanged", {
679
+ file: event2.filePath,
680
+ type: event2.extension,
681
+ action,
682
+ timestamp: /* @__PURE__ */ new Date()
649
683
  });
650
- return;
651
684
  }
685
+ switch (action) {
686
+ case "reloadEnvironment":
687
+ this.reloadEnvironmentConfig();
688
+ break;
689
+ case "reloadConfig":
690
+ this.reloadConfigurationFiles();
691
+ break;
692
+ case "reloadRoutes":
693
+ this.reloadApplicationRoutes(event2.filePath);
694
+ break;
695
+ case "reloadDependencies":
696
+ this.reloadDependencies();
697
+ break;
698
+ case "notifyOnly":
699
+ this.notifyFileChange(event2);
700
+ break;
701
+ }
702
+ }
703
+ /**
704
+ * Handle hot reload requested by watcher
705
+ */
706
+ handleHotReload(data) {
707
+ const { file, type, action } = data;
652
708
  SLogger(this.localLanguage).logger.info({
653
- title: TranslationLoader2.t("IPC_READY", this.localLanguage),
654
- message: TranslationLoader2.t("IPC_READY_HOT_RELOAD", this.localLanguage)
709
+ title: TranslationLoader2.t("HOT_RELOAD_STARTING", this.localLanguage),
710
+ message: TranslationLoader2.t("HOT_RELOAD_FOR_FILE", this.localLanguage).replace("{file}", path2.basename(file)).replace("{type}", type)
655
711
  });
656
- process4.on("message", async (message) => {
657
- if (message.type === "HOT_RELOAD_REQUEST") {
658
- if (this.serverState === "BLOCKED") {
659
- SLogger(this.localLanguage).logger.info({
660
- title: TranslationLoader2.t("BLOCKED", this.localLanguage),
661
- message: TranslationLoader2.t("BLOCKED_STATE", this.localLanguage)
662
- });
663
- return;
664
- }
665
- if (this.serverState === "READY") {
666
- await this.performTrueHotReload();
667
- }
668
- }
712
+ if (this.errorEmitter) {
713
+ this.errorEmitter.emit("hotReload", {
714
+ file,
715
+ type,
716
+ action,
717
+ timestamp: /* @__PURE__ */ new Date()
718
+ });
719
+ }
720
+ switch (action) {
721
+ case "reloadEnvironment":
722
+ this.executeHotReloadEnvironment(file);
723
+ break;
724
+ case "reloadConfig":
725
+ this.executeHotReloadConfig(file);
726
+ break;
727
+ case "reloadRoutes":
728
+ this.executeHotReloadRoutes(file);
729
+ break;
730
+ case "reloadDependencies":
731
+ this.executeHotReloadDependencies(file);
732
+ break;
733
+ }
734
+ }
735
+ /**
736
+ * Handle watcher errors
737
+ */
738
+ handleWatcherError(error) {
739
+ SLogger(this.localLanguage).logger.error({
740
+ title: TranslationLoader2.t("WATCHER_SYSTEM_ERROR", this.localLanguage),
741
+ message: error.message || "Unknown watcher system error",
742
+ errorType: "WatcherSystemError",
743
+ stackTrace: error.stack,
744
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
669
745
  });
670
746
  }
671
747
  /**
672
- * ✅✅✅ HOT RELOAD avec gestion d'état stricte
748
+ * Notify file change without action
673
749
  */
674
- async performTrueHotReload() {
675
- this.serverState = "RELOADING";
676
- this.hotReloadAttempts++;
677
- const startTime = Date.now();
750
+ notifyFileChange(event2) {
678
751
  SLogger(this.localLanguage).logger.info({
679
- title: TranslationLoader2.t("RELOAD_STARTING", this.localLanguage),
680
- message: TranslationLoader2.t("HOT_RELOAD_ATTEMPTED", this.localLanguage, { hotReloadAttempts: this.hotReloadAttempts })
752
+ title: TranslationLoader2.t("FILE_CHANGE_NOTIFIED", this.localLanguage),
753
+ message: TranslationLoader2.t("FILE_CHANGE_NO_ACTION", this.localLanguage).replace("{file}", path2.basename(event2.filePath))
681
754
  });
755
+ }
756
+ /**
757
+ * Reload environment configuration
758
+ */
759
+ reloadEnvironmentConfig() {
682
760
  try {
683
- const clearedModules = this.clearApplicationModulesCache();
684
- SLogger(this.localLanguage).logger.info({
685
- title: TranslationLoader2.t("APP_MODULES_CLEARED", this.localLanguage),
686
- message: TranslationLoader2.t("CLEARED_MODULES", this.localLanguage, { clearedModules })
687
- });
688
761
  this.reloadConfigurations();
689
762
  SLogger(this.localLanguage).logger.info({
690
- title: TranslationLoader2.t("APP_MODULES_CLEARED", this.localLanguage),
691
- message: TranslationLoader2.t("CLEARED_MODULES", this.localLanguage, { hotReloadAttempts: this.hotReloadAttempts })
763
+ title: TranslationLoader2.t("ENV_RELOADED", this.localLanguage),
764
+ message: TranslationLoader2.t("ENVIRONMENT_RELOADED_SUCCESS", this.localLanguage)
692
765
  });
693
- this.reloadDependencies();
694
- SLogger(this.localLanguage).logger.info({
695
- title: TranslationLoader2.t("DEPENDENCIES", this.localLanguage),
696
- message: TranslationLoader2.t("RELOAD_DEPENDENCIES", this.localLanguage)
766
+ this.notifyEnvironmentReload();
767
+ } catch (error) {
768
+ SLogger(this.localLanguage).logger.error({
769
+ title: TranslationLoader2.t("ENV_RELOAD_FAILED", this.localLanguage),
770
+ message: error.message,
771
+ errorType: "EnvironmentReloadError",
772
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
697
773
  });
698
- const duration = Date.now() - startTime;
699
- this.hotReloadSuccesses++;
700
- this.serverState = "READY";
701
- this.lastError = null;
774
+ }
775
+ }
776
+ /**
777
+ * Execute hot reload for environment files
778
+ */
779
+ executeHotReloadEnvironment(filePath) {
780
+ try {
781
+ const newEnv = getEnvironnementValue2(this.environmentPath);
782
+ Object.keys(newEnv).forEach((key) => {
783
+ this.getEnvironment[key] = newEnv[key];
784
+ });
785
+ loaderTranslationFile(this.localLanguage);
702
786
  SLogger(this.localLanguage).logger.info({
703
- title: TranslationLoader2.t("RELOAD_SUCCESS", this.localLanguage),
704
- message: TranslationLoader2.t("HOT_RELOAD_SUCCESS", this.localLanguage, { duration })
787
+ title: TranslationLoader2.t("HOT_RELOAD_ENV_SUCCESS", this.localLanguage),
788
+ message: TranslationLoader2.t("ENV_HOT_RELOAD_COMPLETE", this.localLanguage).replace("{file}", path2.basename(filePath))
705
789
  });
706
- this.notifyWatcherReloadSuccess(duration);
707
790
  } catch (error) {
708
- this.hotReloadFailures++;
709
- const duration = Date.now() - startTime;
791
+ SLogger(this.localLanguage).logger.error({
792
+ title: TranslationLoader2.t("HOT_RELOAD_ENV_FAILED", this.localLanguage),
793
+ message: error.message,
794
+ errorType: "HotReloadEnvironmentError",
795
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
796
+ });
797
+ }
798
+ }
799
+ /**
800
+ * Reload configuration files
801
+ */
802
+ reloadConfigurationFiles() {
803
+ try {
804
+ loaderTranslationFile(this.localLanguage);
710
805
  SLogger(this.localLanguage).logger.info({
711
- title: TranslationLoader2.t("RELOAD_FAILED", this.localLanguage),
712
- message: TranslationLoader2.t("HOT_RELOAD_FAILED", this.localLanguage, { duration, errorMessage: error.message })
713
- });
714
- const isTransformError = error?.name === "TransformError" || error?.message?.includes("Transform failed") || error?.message?.includes("esbuild");
715
- if (isTransformError) {
716
- this.lastError = error;
717
- this.serverState = "BLOCKED";
718
- this.notifyWatcherBlockedByError(error);
719
- } else {
720
- this.serverState = "BLOCKED";
721
- this.notifyWatcherReloadError(error);
806
+ title: TranslationLoader2.t("CONFIG_RELOADED", this.localLanguage),
807
+ message: TranslationLoader2.t("CONFIGURATION_RELOADED_SUCCESS", this.localLanguage)
808
+ });
809
+ } catch (error) {
810
+ SLogger(this.localLanguage).logger.error({
811
+ title: TranslationLoader2.t("CONFIG_RELOAD_FAILED", this.localLanguage),
812
+ message: error.message,
813
+ errorType: "ConfigurationReloadError",
814
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
815
+ });
816
+ }
817
+ }
818
+ /**
819
+ * Execute hot reload for config files
820
+ */
821
+ executeHotReloadConfig(filePath) {
822
+ try {
823
+ if (filePath.includes("locales") || filePath.includes("translations")) {
824
+ loaderTranslationFile(this.localLanguage);
825
+ SLogger(this.localLanguage).logger.info({
826
+ title: TranslationLoader2.t("TRANSLATIONS_RELOADED", this.localLanguage),
827
+ message: TranslationLoader2.t("TRANSLATIONS_HOT_RELOAD_COMPLETE", this.localLanguage).replace("{file}", path2.basename(filePath))
828
+ });
722
829
  }
830
+ } catch (error) {
831
+ SLogger(this.localLanguage).logger.error({
832
+ title: TranslationLoader2.t("HOT_RELOAD_CONFIG_FAILED", this.localLanguage),
833
+ message: error.message,
834
+ errorType: "HotReloadConfigError",
835
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
836
+ });
723
837
  }
724
838
  }
725
839
  /**
726
- * Nettoie le cache des modules applicatifs
840
+ * Reload application routes
727
841
  */
728
- clearApplicationModulesCache() {
729
- const baseDirs = [
730
- path2.join(process4.cwd(), "src"),
731
- path2.join(process4.cwd(), "dist")
732
- ];
733
- let clearedCount = 0;
734
- for (const key in __require.cache) {
735
- const isApplicationModule = baseDirs.some((dir) => key.startsWith(dir));
736
- const isNodeModule = key.includes("node_modules");
737
- const isJsonFile = key.endsWith(".json");
738
- if (isApplicationModule && !isNodeModule && !isJsonFile) {
739
- delete __require.cache[key];
740
- clearedCount++;
842
+ reloadApplicationRoutes(filePath) {
843
+ try {
844
+ SLogger(this.localLanguage).logger.info({
845
+ title: TranslationLoader2.t("ROUTES_RELOADING", this.localLanguage),
846
+ message: TranslationLoader2.t("APPLICATION_ROUTES_RELOADING", this.localLanguage).replace("{file}", path2.basename(filePath))
847
+ });
848
+ if (filePath.includes("routes") || filePath.includes("controller")) {
849
+ this.reloadSpecificRoute(filePath);
850
+ }
851
+ if (this.errorEmitter) {
852
+ this.errorEmitter.emit("routesReloaded", {
853
+ timestamp: /* @__PURE__ */ new Date(),
854
+ file: filePath,
855
+ routesCount: this.currentRoutes.length
856
+ });
741
857
  }
858
+ } catch (error) {
859
+ SLogger(this.localLanguage).logger.error({
860
+ title: TranslationLoader2.t("ROUTES_RELOAD_FAILED", this.localLanguage),
861
+ message: error.message,
862
+ errorType: "RoutesReloadError",
863
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
864
+ });
865
+ }
866
+ }
867
+ /**
868
+ * Execute hot reload for routes
869
+ */
870
+ executeHotReloadRoutes(filePath) {
871
+ try {
872
+ SLogger(this.localLanguage).logger.info({
873
+ title: TranslationLoader2.t("HOT_RELOAD_ROUTES_START", this.localLanguage),
874
+ message: TranslationLoader2.t("ROUTES_HOT_RELOADING", this.localLanguage).replace("{file}", path2.basename(filePath))
875
+ });
876
+ this.reloadRouterForFile(filePath);
877
+ SLogger(this.localLanguage).logger.info({
878
+ title: TranslationLoader2.t("HOT_RELOAD_ROUTES_SUCCESS", this.localLanguage),
879
+ message: TranslationLoader2.t("ROUTES_HOT_RELOAD_COMPLETE", this.localLanguage)
880
+ });
881
+ } catch (error) {
882
+ SLogger(this.localLanguage).logger.error({
883
+ title: TranslationLoader2.t("HOT_RELOAD_ROUTES_FAILED", this.localLanguage),
884
+ message: error.message,
885
+ errorType: "HotReloadRoutesError",
886
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
887
+ });
888
+ }
889
+ }
890
+ /**
891
+ * Execute hot reload for dependencies
892
+ */
893
+ executeHotReloadDependencies(filePath) {
894
+ try {
895
+ SLogger(this.localLanguage).logger.info({
896
+ title: TranslationLoader2.t("HOT_RELOAD_DEPS_START", this.localLanguage),
897
+ message: TranslationLoader2.t(
898
+ "DEPENDENCIES_HOT_RELOADING",
899
+ this.localLanguage
900
+ ).replace("{file}", path2.basename(filePath))
901
+ });
902
+ this.reloadDependencies();
903
+ SLogger(this.localLanguage).logger.info({
904
+ title: TranslationLoader2.t("HOT_RELOAD_DEPS_SUCCESS", this.localLanguage),
905
+ message: TranslationLoader2.t("DEPENDENCIES_HOT_RELOAD_COMPLETE", this.localLanguage)
906
+ });
907
+ } catch (error) {
908
+ SLogger(this.localLanguage).logger.error({
909
+ title: TranslationLoader2.t("HOT_RELOAD_DEPS_FAILED", this.localLanguage),
910
+ message: error.message,
911
+ errorType: "HotReloadDependenciesError",
912
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
913
+ });
914
+ }
915
+ }
916
+ /**
917
+ * Notify environment reload
918
+ */
919
+ notifyEnvironmentReload() {
920
+ if (this.errorEmitter) {
921
+ this.errorEmitter.emit("environmentReloaded", {
922
+ timestamp: /* @__PURE__ */ new Date(),
923
+ environment: this.getEnvironment
924
+ });
742
925
  }
743
- return clearedCount;
744
926
  }
927
+ /**
928
+ * Reload specific route
929
+ */
930
+ reloadSpecificRoute(filePath) {
931
+ SLogger(this.localLanguage).logger.info({
932
+ title: "Route Reload",
933
+ message: `Reloading route from: ${filePath}`
934
+ });
935
+ }
936
+ /**
937
+ * Reload router for specific file
938
+ */
939
+ reloadRouterForFile(filePath) {
940
+ SLogger(this.localLanguage).logger.info({
941
+ title: "Router Reload",
942
+ message: `Reloading router for file: ${filePath}`
943
+ });
944
+ }
945
+ /**
946
+ * Reload configurations
947
+ */
745
948
  reloadConfigurations() {
746
949
  try {
747
950
  const newEnv = getEnvironnementValue2(this.environmentPath);
@@ -753,6 +956,9 @@ var WebServerCore = class {
753
956
  throw new Error(`Configuration reload failed: ${error.message}`);
754
957
  }
755
958
  }
959
+ /**
960
+ * Reload dependencies
961
+ */
756
962
  reloadDependencies() {
757
963
  try {
758
964
  new SContainer2(this.localLanguage, this.currentDependencies);
@@ -765,57 +971,19 @@ var WebServerCore = class {
765
971
  }
766
972
  }
767
973
  /**
768
- * ✅✅✅ Notifier le watcher : SUCCÈS
974
+ * Register routes
769
975
  */
770
- notifyWatcherReloadSuccess(duration) {
771
- if (process4.send && process4.env.WATCHER_MODE === "true") {
772
- process4.send({
773
- type: "HOT_RELOAD_SUCCESS",
774
- timestamp: Date.now(),
775
- duration,
776
- serverState: this.serverState,
777
- message: "Code reloaded successfully"
778
- });
779
- }
780
- }
781
- /**
782
- * ✅✅✅ Notifier le watcher : BLOQUÉ PAR ERREUR TRANSFORM
783
- */
784
- notifyWatcherBlockedByError(error) {
785
- if (process4.send && process4.env.WATCHER_MODE === "true") {
786
- const errorDetails = this.parseTransformError(error);
787
- process4.send({
788
- type: "HOT_RELOAD_BLOCKED_BY_ERROR",
789
- timestamp: Date.now(),
790
- serverState: this.serverState,
791
- error: {
792
- message: error.message,
793
- errorType: error.name || "TransformError",
794
- file: errorDetails.file,
795
- line: errorDetails.line,
796
- column: errorDetails.column,
797
- detail: errorDetails.errorDetail,
798
- tool: errorDetails.tool
799
- }
800
- });
801
- }
802
- }
803
- /**
804
- * ✅✅✅ Notifier le watcher : ERREUR GÉNÉRIQUE
805
- */
806
- notifyWatcherReloadError(error) {
807
- if (process4.send && process4.env.WATCHER_MODE === "true") {
808
- process4.send({
809
- type: "HOT_RELOAD_ERROR",
810
- timestamp: Date.now(),
811
- serverState: this.serverState,
812
- error: error.message,
813
- errorType: error.name || "UNKNOWN_ERROR"
814
- });
815
- }
976
+ registerRoutes(allFeatureRoutes) {
977
+ allFeatureRoutes.forEach((router) => {
978
+ if (router.routes) {
979
+ router.routes.forEach((route) => {
980
+ this.expressApp.use(route.path, route.handler);
981
+ });
982
+ }
983
+ });
816
984
  }
817
985
  /**
818
- * ✅✅✅ Parser les détails d'une TransformError
986
+ * Parse transform error
819
987
  */
820
988
  parseTransformError(error) {
821
989
  const errorMessage = error.message || String(error);
@@ -837,22 +1005,43 @@ var WebServerCore = class {
837
1005
  tool
838
1006
  };
839
1007
  }
840
- registerRoutes(allFeatureRoutes) {
841
- allFeatureRoutes.forEach((router) => {
842
- if (router.routes) {
843
- router.routes.forEach((route) => {
844
- this.expressApp.use(route.path, route.handler);
845
- });
846
- }
847
- });
848
- }
1008
+ /**
1009
+ * Display server info
1010
+ */
849
1011
  infoWebApp() {
850
1012
  this.serverUtility.infoServer(
851
1013
  this.getEnvironment.appHost,
852
1014
  Number(this.getEnvironment.appPort)
853
1015
  );
854
1016
  }
1017
+ /**
1018
+ * Stop file watcher
1019
+ */
1020
+ stopFileWatcher() {
1021
+ if (this.fileWatcher) {
1022
+ try {
1023
+ this.fileWatcher.stopWatching();
1024
+ SLogger(this.localLanguage).logger.info({
1025
+ title: TranslationLoader2.t("WATCHER_STOPPED", this.localLanguage),
1026
+ message: TranslationLoader2.t("FILE_WATCHER_STOPPED_GRACEFULLY", this.localLanguage)
1027
+ });
1028
+ } catch (error) {
1029
+ SLogger(this.localLanguage).logger.error({
1030
+ title: TranslationLoader2.t("WATCHER_STOP_ERROR", this.localLanguage),
1031
+ message: `Error stopping watcher: ${error.message}`,
1032
+ errorType: "WatcherStopError",
1033
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
1034
+ });
1035
+ } finally {
1036
+ this.fileWatcher = void 0;
1037
+ }
1038
+ }
1039
+ }
1040
+ /**
1041
+ * Shutdown server
1042
+ */
855
1043
  shutdown() {
1044
+ this.stopFileWatcher();
856
1045
  if (this.server) {
857
1046
  this.server.close(() => {
858
1047
  SLogger(this.localLanguage).logger.info({
@@ -862,12 +1051,193 @@ var WebServerCore = class {
862
1051
  process4.exit(0);
863
1052
  });
864
1053
  setTimeout(() => {
1054
+ SLogger(this.localLanguage).logger.error({
1055
+ title: TranslationLoader2.t("FORCE_SHUTDOWN", this.localLanguage),
1056
+ message: TranslationLoader2.t("SERVER_FORCE_SHUTDOWN", this.localLanguage)
1057
+ });
865
1058
  process4.exit(1);
866
1059
  }, 5e3);
867
1060
  } else {
868
1061
  process4.exit(0);
869
1062
  }
870
1063
  }
1064
+ /**
1065
+ * Enable/disable watcher
1066
+ */
1067
+ setWatcherEnabled(enabled) {
1068
+ this.isWatcherEnabled = enabled;
1069
+ if (enabled && !this.fileWatcher) {
1070
+ this.initializeFileWatcher();
1071
+ } else if (!enabled && this.fileWatcher) {
1072
+ this.stopFileWatcher();
1073
+ }
1074
+ SLogger(this.localLanguage).logger.info({
1075
+ title: "Watcher Status",
1076
+ message: `File watcher ${enabled ? "enabled" : "disabled"}`
1077
+ });
1078
+ }
1079
+ /**
1080
+ * Get watcher status
1081
+ */
1082
+ getWatcherStatus() {
1083
+ return {
1084
+ enabled: this.isWatcherEnabled,
1085
+ active: this.fileWatcher !== void 0
1086
+ };
1087
+ }
1088
+ /**
1089
+ * Get server state information
1090
+ */
1091
+ getServerState() {
1092
+ const now = /* @__PURE__ */ new Date();
1093
+ const uptime = this.serverStartTime ? now.getTime() - this.serverStartTime.getTime() : 0;
1094
+ const formatUptime = (ms) => {
1095
+ const seconds = Math.floor(ms / 1e3);
1096
+ const minutes = Math.floor(seconds / 60);
1097
+ const hours = Math.floor(minutes / 60);
1098
+ const days = Math.floor(hours / 24);
1099
+ if (days > 0) return `${days}j ${hours % 24}h ${minutes % 60}m`;
1100
+ if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
1101
+ if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
1102
+ return `${seconds}s`;
1103
+ };
1104
+ const memory = process4.memoryUsage();
1105
+ return {
1106
+ status: this.serverStatus,
1107
+ isRunning: this.server !== void 0,
1108
+ host: this.getEnvironment.appHost,
1109
+ port: Number(this.getEnvironment.appPort),
1110
+ language: this.localLanguage,
1111
+ watcherEnabled: this.isWatcherEnabled,
1112
+ watcherActive: this.fileWatcher !== void 0,
1113
+ routesCount: this.currentRoutes.length,
1114
+ dependenciesCount: this.currentDependencies.length,
1115
+ startTime: this.serverStartTime,
1116
+ currentTime: now,
1117
+ uptime,
1118
+ uptimeFormatted: formatUptime(uptime),
1119
+ memoryUsage: {
1120
+ rss: memory.rss,
1121
+ heapTotal: memory.heapTotal,
1122
+ heapUsed: memory.heapUsed,
1123
+ external: memory.external,
1124
+ arrayBuffers: memory.arrayBuffers
1125
+ },
1126
+ pid: process4.pid,
1127
+ platform: process4.platform,
1128
+ nodeVersion: process4.version,
1129
+ cwd: process4.cwd()
1130
+ };
1131
+ }
1132
+ /**
1133
+ * Simple method to get just the status
1134
+ */
1135
+ getServerStatus() {
1136
+ return this.serverStatus;
1137
+ }
1138
+ /**
1139
+ * Get server statistics for monitoring
1140
+ */
1141
+ getServerStats() {
1142
+ const uptime = this.serverStartTime ? Date.now() - this.serverStartTime.getTime() : 0;
1143
+ const memory = process4.memoryUsage();
1144
+ return {
1145
+ status: this.serverStatus,
1146
+ uptime: this.formatUptime(uptime),
1147
+ memory: {
1148
+ rss: this.formatBytes(memory.rss),
1149
+ heapTotal: this.formatBytes(memory.heapTotal),
1150
+ heapUsed: this.formatBytes(memory.heapUsed),
1151
+ external: this.formatBytes(memory.external)
1152
+ },
1153
+ performance: {
1154
+ cpuUsage: process4.cpuUsage(),
1155
+ resourceUsage: process4.resourceUsage?.()
1156
+ }
1157
+ };
1158
+ }
1159
+ /**
1160
+ * Format bytes to human readable string
1161
+ */
1162
+ formatBytes(bytes) {
1163
+ const units = ["B", "KB", "MB", "GB", "TB"];
1164
+ let value = bytes;
1165
+ let unitIndex = 0;
1166
+ while (value >= 1024 && unitIndex < units.length - 1) {
1167
+ value /= 1024;
1168
+ unitIndex++;
1169
+ }
1170
+ return `${value.toFixed(2)} ${units[unitIndex]}`;
1171
+ }
1172
+ /**
1173
+ * Format uptime to human readable string
1174
+ */
1175
+ formatUptime(ms) {
1176
+ const seconds = Math.floor(ms / 1e3);
1177
+ const minutes = Math.floor(seconds / 60);
1178
+ const hours = Math.floor(minutes / 60);
1179
+ const days = Math.floor(hours / 24);
1180
+ if (days > 0) {
1181
+ return `${days}j ${hours % 24}h ${minutes % 60}m`;
1182
+ } else if (hours > 0) {
1183
+ return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
1184
+ } else if (minutes > 0) {
1185
+ return `${minutes}m ${seconds % 60}s`;
1186
+ } else {
1187
+ return `${seconds}s`;
1188
+ }
1189
+ }
1190
+ /**
1191
+ * Add watch directories
1192
+ */
1193
+ addWatchDirectories(directories) {
1194
+ if (this.fileWatcher) {
1195
+ this.fileWatcher.addWatchDirectories(directories);
1196
+ }
1197
+ }
1198
+ /**
1199
+ * Clear file cache
1200
+ */
1201
+ clearFileCache() {
1202
+ if (this.fileWatcher) {
1203
+ this.fileWatcher.clearFileCache();
1204
+ }
1205
+ }
1206
+ /**
1207
+ * Force reload configurations
1208
+ */
1209
+ forceReloadConfig() {
1210
+ try {
1211
+ this.reloadConfigurations();
1212
+ this.reloadDependencies();
1213
+ SLogger(this.localLanguage).logger.info({
1214
+ title: "Force Reload",
1215
+ message: "All configurations and dependencies have been reloaded"
1216
+ });
1217
+ } catch (error) {
1218
+ SLogger(this.localLanguage).logger.error({
1219
+ title: "Force Reload Failed",
1220
+ message: error.message,
1221
+ errorType: "ForceReloadError",
1222
+ httpCodeValue: HttpStatusCode3.INTERNAL_SERVER_ERROR
1223
+ });
1224
+ }
1225
+ }
1226
+ /**
1227
+ * Restart watcher
1228
+ */
1229
+ restartWatcher() {
1230
+ this.stopFileWatcher();
1231
+ if (this.isWatcherEnabled) {
1232
+ setTimeout(() => {
1233
+ this.initializeFileWatcher();
1234
+ SLogger(this.localLanguage).logger.info({
1235
+ title: "Watcher Restarted",
1236
+ message: "File watcher has been restarted successfully"
1237
+ });
1238
+ }, 1e3);
1239
+ }
1240
+ }
871
1241
  };
872
1242
  export {
873
1243
  WebServerCore as WebServer,