2121from rich .table import Table
2222
2323from myfy .core import Application
24+ from myfy .core .config import load_settings
25+ from myfy .web .config import WebSettings
2426from myfy_cli .commands import frontend_app
2527from myfy_cli .version import __version__
2628
@@ -122,10 +124,63 @@ def _setup_reload_module(filename: str, var_name: str) -> tuple[str, dict[str, s
122124 return "myfy_cli.asgi_factory:create_app" , env_vars
123125
124126
127+ def _resolve_host_and_port (
128+ host : str | None ,
129+ port : int | None ,
130+ application : Application | None = None ,
131+ ) -> tuple [str , int ]:
132+ """
133+ Resolve host and port from CLI args, WebSettings, or defaults.
134+
135+ Precedence: CLI flags > Environment variables > WebSettings defaults > Hardcoded defaults
136+
137+ Args:
138+ host: Host from CLI (None if not provided)
139+ port: Port from CLI (None if not provided)
140+ application: Application instance (used to get WebSettings from container)
141+
142+ Returns:
143+ Tuple of (host, port)
144+ """
145+ # If both provided via CLI, use them
146+ if host is not None and port is not None :
147+ return host , port
148+
149+ # Try to get from WebSettings (respects environment variables)
150+ if application is not None :
151+ try :
152+ web_settings = application .container .get (WebSettings )
153+ if host is None :
154+ host = web_settings .host
155+ if port is None :
156+ port = web_settings .port
157+ except Exception :
158+ pass # Fall through to defaults
159+
160+ # If using app_path (no application), try loading WebSettings directly
161+ if application is None :
162+ try :
163+ web_settings = load_settings (WebSettings )
164+ if host is None :
165+ host = web_settings .host
166+ if port is None :
167+ port = web_settings .port
168+ except Exception :
169+ pass # Fall through to defaults
170+
171+ # Fall back to hardcoded defaults
172+ if host is None :
173+ host = "127.0.0.1"
174+ if port is None :
175+ port = 8000
176+
177+ return host , port
178+
179+
125180@app .command ()
126181def run (
127- host : str = typer .Option ("127.0.0.1" , help = "Server host" ),
128- port : int = typer .Option (8000 , help = "Server port" ),
182+ host : str | None = typer .Option (None , help = "Server host" ),
183+ port : int | None = typer .Option (None , help = "Server port" ),
129184 reload : bool = typer .Option (True , help = "Enable auto-reload" ),
130185 app_path : str | None = typer .Option (None , help = "Path to app (e.g., main:app)" ),
131186):
@@ -138,6 +193,8 @@ def run(
138193
139194 if app_path :
140195 # Use provided app path
196+ host , port = _resolve_host_and_port (host , port , application = None )
197+
141198 uvicorn .run (
142199 app_path ,
143200 host = host ,
@@ -165,6 +222,9 @@ def run(
165222 console .print ("Add WebModule() to your application" )
166223 sys .exit (1 )
167224
225+ # Resolve host and port (respects CLI flags > env vars > WebSettings defaults)
226+ host , port = _resolve_host_and_port (host , port , application )
227+
168228 console .print (f"📡 Listening on http://{ host } :{ port } " )
169229 console .print (f"📦 Loaded { len (application ._modules )} module(s)" )
170230
0 commit comments