Pārlūkot izejas kodu

Update dependencies and add nodemon configurations

Timothy Pomeroy 3 nedēļas atpakaļ
vecāks
revīzija
dded92b4c2

+ 19 - 0
apps/service/dev-restart.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# Continuous restart wrapper for development
+while true; do
+  echo "[dev-restart] Starting NestJS application..."
+  nest start
+  EXIT_CODE=$?
+  
+  if [ $EXIT_CODE -eq 0 ]; then
+    echo "[dev-restart] Clean exit detected, restarting in 1 second..."
+    sleep 1
+  elif [ $EXIT_CODE -eq 1 ]; then
+    echo "[dev-restart] Restart requested, restarting in 1 second..."
+    sleep 1
+  else
+    echo "[dev-restart] Unexpected exit code $EXIT_CODE, restarting in 3 seconds..."
+    sleep 3
+  fi
+done

+ 8 - 0
apps/service/nodemon-prod.json

@@ -0,0 +1,8 @@
+{
+  "watch": [],
+  "exec": "node dist/main",
+  "signal": "SIGHUP",
+  "env": {
+    "NODE_ENV": "production"
+  }
+}

+ 11 - 0
apps/service/nodemon.json

@@ -0,0 +1,11 @@
+{
+  "watch": ["src"],
+  "ext": "ts",
+  "ignore": ["src/**/*.spec.ts"],
+  "exec": "nest start",
+  "delay": 500,
+  "signal": "SIGHUP",
+  "env": {
+    "NODE_ENV": "development"
+  }
+}

+ 3 - 2
apps/service/package.json

@@ -7,12 +7,12 @@
   "license": "UNLICENSED",
   "scripts": {
     "build": "nest build",
-    "dev": "nest start --watch",
+    "dev": "nodemon",
     "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
     "start": "node dist/main",
     "start:dev": "nest start --watch",
     "start:debug": "nest start --debug --watch",
-    "start:prod": "node dist/main",
+    "start:prod": "pm2-runtime dist/main.js --name service",
     "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
     "test": "jest",
     "test:watch": "jest --watch",
@@ -47,6 +47,7 @@
     "eslint-plugin-prettier": "^5.2.2",
     "globals": "^16.0.0",
     "jest": "^30.0.0",
+    "pm2": "^5.4.3",
     "prettier": "^3.4.2",
     "socket.io-client": "^4.8.3",
     "source-map-support": "^0.5.21",

+ 13 - 4
apps/service/src/app.controller.ts

@@ -95,11 +95,20 @@ export class AppController {
     setImmediate(async () => {
       try {
         await this.app!.close();
-        // Exit with code 0 to let process manager restart us
-        process.exit(0);
+        if (process.env.NODE_ENV === 'production') {
+          // In prod with pm2, exit to trigger restart
+          process.exit(0);
+        } else {
+          // In dev with nodemon, send SIGHUP to parent
+          process.kill(process.ppid, 'SIGHUP');
+        }
       } catch (error) {
-        console.error('Error during graceful restart:', error);
-        process.exit(1);
+        console.error('Error during restart:', error);
+        if (process.env.NODE_ENV === 'production') {
+          process.exit(0);
+        } else {
+          process.kill(process.ppid, 'SIGHUP');
+        }
       }
     });
 

+ 1 - 1
apps/service/src/watcher.service.ts

@@ -526,7 +526,7 @@ export class WatcherService implements OnModuleDestroy {
           this.logger.warn(`Error closing watcher: ${error.message}`);
         }
       }
-      
+
       this.watcher = null;
       this.isWatching = false;
       this.eventsGateway.emitWatcherUpdate({ type: 'stopped' });

+ 1 - 0
apps/web/package.json

@@ -6,6 +6,7 @@
     "dev": "next dev",
     "build": "next build",
     "start": "next start",
+    "start:prod": "next start",
     "lint": "eslint",
     "test": "jest",
     "test:watch": "jest --watch",

+ 26 - 39
apps/web/src/app/components/ApiHealth.tsx

@@ -102,60 +102,47 @@ export default function ApiHealth() {
                 </span>
               )}
             </div>
-            <div className="text-sm font-medium text-gray-400">
-              {isRestarting ? "Restarting..." : "API Health"}
-            </div>
+            <div className="text-sm font-medium text-gray-400">API Health</div>
             {responseTime !== null && !isRestarting && (
               <div className="text-xs text-gray-500 mt-1">
                 {responseTime}ms response
               </div>
             )}
+            {isRestarting && (
+              <div className="text-xs text-blue-400 mt-1">Restarting...</div>
+            )}
           </div>
         </div>
-        <button
-          onClick={() => setShowRestartConfirm(true)}
-          disabled={restartMutation.isPending || isRestarting}
-          className="px-3 py-1 rounded text-xs font-medium transition-colors bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1"
-          title="Restart API service"
-        >
-          <ArrowPathIcon
-            className={`h-3 w-3 ${restartMutation.isPending || isRestarting ? "animate-spin" : ""}`}
-          />
-          Restart
-        </button>
-      </div>
-
-      {/* Restart Confirmation Dialog */}
-      {showRestartConfirm && (
-        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
-          <div className="bg-white dark:bg-gray-900 rounded-lg shadow-lg p-6 max-w-sm mx-4">
-            <h2 className="text-lg font-semibold mb-2">Restart API Service?</h2>
-            <p className="text-gray-600 dark:text-gray-400 text-sm mb-6">
-              This will gracefully restart the API service. The service will be
-              temporarily unavailable.
-            </p>
-            <div className="flex justify-end gap-3">
+        <div className="flex items-center gap-2">
+          {!showRestartConfirm ? (
+            <button
+              onClick={() => setShowRestartConfirm(true)}
+              disabled={isRestarting}
+              className="flex items-center gap-1.5 rounded-lg bg-blue-500/20 px-3 py-1.5 text-xs font-medium text-blue-400 ring-1 ring-blue-500/30 transition-all hover:bg-blue-500/30 hover:ring-blue-500/50 disabled:opacity-50 disabled:cursor-not-allowed"
+              title="Restart API service"
+            >
+              <ArrowPathIcon className="h-4 w-4" />
+              Restart
+            </button>
+          ) : (
+            <div className="flex items-center gap-2">
               <button
-                onClick={() => setShowRestartConfirm(false)}
-                disabled={restartMutation.isPending}
-                className="px-4 py-2 rounded border border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-800 disabled:opacity-50 transition-colors"
+                onClick={() => restartMutation.mutate()}
+                disabled={isRestarting}
+                className="rounded-lg bg-red-500/20 px-3 py-1.5 text-xs font-medium text-red-400 ring-1 ring-red-500/30 transition-all hover:bg-red-500/30 hover:ring-red-500/50 disabled:opacity-50"
               >
-                Cancel
+                Confirm
               </button>
               <button
-                onClick={() => restartMutation.mutate()}
-                disabled={restartMutation.isPending}
-                className="px-4 py-2 rounded bg-red-600 hover:bg-red-700 dark:bg-red-700 dark:hover:bg-red-800 text-white disabled:opacity-50 transition-colors flex items-center gap-2"
+                onClick={() => setShowRestartConfirm(false)}
+                className="rounded-lg bg-gray-500/20 px-3 py-1.5 text-xs font-medium text-gray-400 ring-1 ring-gray-500/30 transition-all hover:bg-gray-500/30 hover:ring-gray-500/50"
               >
-                {restartMutation.isPending && (
-                  <ArrowPathIcon className="w-4 h-4 animate-spin" />
-                )}
-                Restart
+                Cancel
               </button>
             </div>
-          </div>
+          )}
         </div>
-      )}
+      </div>
     </div>
   );
 }

+ 1 - 0
package.json

@@ -5,6 +5,7 @@
     "build": "turbo run build",
     "dev": "turbo run dev",
     "start": "turbo run start",
+    "start:prod": "turbo run start:prod",
     "lint": "turbo run lint",
     "format": "prettier --write \"**/*.{ts,tsx,md}\"",
     "check-types": "turbo run check-types",

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 459 - 2
pnpm-lock.yaml


+ 5 - 0
turbo.json

@@ -21,6 +21,11 @@
       "dependsOn": ["build"],
       "cache": false,
       "persistent": true
+    },
+    "start:prod": {
+      "dependsOn": ["build"],
+      "cache": false,
+      "persistent": true
     }
   }
 }

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels