@@ -968,6 +968,88 @@ namespace vix::commands
968968 return line.substr (start, end - start);
969969 }
970970
971+ std::optional<std::string> detect_websocket_port_from_config ()
972+ {
973+ const fs::path vixJson = fs::current_path () / " vix.json" ;
974+
975+ if (!fs::exists (vixJson))
976+ return std::nullopt ;
977+
978+ try
979+ {
980+ const json root = read_json_or_throw (vixJson);
981+
982+ if (!root.is_object () ||
983+ !root.contains (" production" ) ||
984+ !root[" production" ].is_object ())
985+ {
986+ return std::nullopt ;
987+ }
988+
989+ const auto &production = root[" production" ];
990+
991+ if (!production.contains (" ports" ) ||
992+ !production[" ports" ].is_object ())
993+ {
994+ return std::nullopt ;
995+ }
996+
997+ const auto &ports = production[" ports" ];
998+
999+ if (!ports.contains (" websocket" ) ||
1000+ !ports[" websocket" ].is_number_integer ())
1001+ {
1002+ return std::nullopt ;
1003+ }
1004+
1005+ const int port = ports[" websocket" ].get <int >();
1006+
1007+ if (port <= 0 )
1008+ return std::nullopt ;
1009+
1010+ return std::to_string (port);
1011+ }
1012+ catch (...)
1013+ {
1014+ return std::nullopt ;
1015+ }
1016+ }
1017+
1018+ std::optional<std::string> detect_nginx_proxy_target (const std::string &projectName)
1019+ {
1020+ const std::string lower = lower_copy (projectName);
1021+
1022+ auto out = run_capture (
1023+ " grep -R \" proxy_pass\" /etc/nginx/sites-available /etc/nginx/sites-enabled "
1024+ " 2>/dev/null | grep -i " +
1025+ shell_quote (lower) +
1026+ " | head -1" );
1027+
1028+ if (!out)
1029+ {
1030+ out = run_capture (
1031+ " grep -R \" proxy_pass\" /etc/nginx/sites-available /etc/nginx/sites-enabled "
1032+ " 2>/dev/null | head -1" );
1033+ }
1034+
1035+ if (!out)
1036+ return std::nullopt ;
1037+
1038+ const std::string line = *out;
1039+ const std::string key = " proxy_pass" ;
1040+ const auto pos = line.find (key);
1041+
1042+ if (pos == std::string::npos)
1043+ return std::nullopt ;
1044+
1045+ std::string value = trim_copy (line.substr (pos + key.size ()));
1046+
1047+ if (!value.empty () && value.back () == ' ;' )
1048+ value.pop_back ();
1049+
1050+ return trim_copy (value);
1051+ }
1052+
9711053 std::optional<std::string> detect_nginx_domain (const std::string &projectName)
9721054 {
9731055 const std::string lower = lower_copy (projectName);
@@ -1192,15 +1274,23 @@ namespace vix::commands
11921274 const auto workingDir =
11931275 serviceExists ? systemctl_property (*service, " WorkingDirectory" ) : std::nullopt ;
11941276
1277+ const auto environment =
1278+ serviceExists ? systemctl_property (*service, " Environment" ) : std::nullopt ;
1279+
11951280 const bool binaryExists = binary && fs::exists (*binary);
11961281 const bool running = binaryExists && process_running_for_binary (*binary);
11971282
11981283 const auto port =
11991284 binaryExists ? detect_listening_port_for_binary (*binary) : std::nullopt ;
12001285
1286+ const auto websocketPort =
1287+ detect_websocket_port_from_config ();
1288+
12011289 const bool nginxExists = nginx_config_exists_for_project (projectName);
12021290 const auto domain = detect_nginx_domain (projectName);
12031291 const bool tls = domain && tls_config_exists_for_domain (*domain);
1292+ const auto proxyTarget =
1293+ detect_nginx_proxy_target (projectName);
12041294
12051295 const bool localHealth = port && local_health_ok (*port);
12061296 const bool publicHealth = domain && public_health_ok (*domain);
@@ -1300,8 +1390,20 @@ namespace vix::commands
13001390 vix::cli::util::kv (std::cout, " Service status" , serviceStatus.value_or (" unknown" ));
13011391 vix::cli::util::kv (std::cout, " Restart policy" , restartPolicy.value_or (" unknown" ));
13021392 vix::cli::util::kv (std::cout, " Working directory" , workingDir.value_or (" unknown" ));
1393+ vix::cli::util::kv (
1394+ std::cout,
1395+ " Environment" ,
1396+ environment && !environment->empty () ? *environment : " unknown" );
13031397 vix::cli::util::kv (std::cout, " HTTP port" , port.value_or (" unknown" ));
1398+ vix::cli::util::kv (
1399+ std::cout,
1400+ " WebSocket port" ,
1401+ websocketPort.value_or (" unknown" ));
13041402 vix::cli::util::kv (std::cout, " Proxy" , nginxExists ? " nginx" : " not found" );
1403+ vix::cli::util::kv (
1404+ std::cout,
1405+ " Proxy target" ,
1406+ proxyTarget.value_or (" unknown" ));
13051407 vix::cli::util::kv (std::cout, " Public URL" , domain ? " https://" + *domain : " unknown" );
13061408 vix::cli::util::kv (std::cout, " TLS" , tls ? " enabled" : " unknown" );
13071409 vix::cli::util::kv (std::cout, " Local health" , localHealth ? " ok" : " unknown" );
@@ -1378,6 +1480,9 @@ namespace vix::commands
13781480 out[" websocket_health_configured" ] = websocketHealthConfigured;
13791481 out[" deploy_rollback_configured" ] = deployRollbackConfigured;
13801482 out[" readiness" ] = json::array ();
1483+ out[" environment" ] = environment.value_or (" " );
1484+ out[" websocket_port" ] = websocketPort.value_or (" " );
1485+ out[" proxy_target" ] = proxyTarget.value_or (" " );
13811486
13821487 for (const auto &item : readiness)
13831488 {
0 commit comments