diff --git a/reflex/app.py b/reflex/app.py index 2f4e57a63..a3d0d8e10 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -164,9 +164,26 @@ def default_overlay_component() -> Component: """ config = get_config() + extra_config = config.extra_overlay_function + config_overlay = None + if extra_config: + module, _, function_name = extra_config.rpartition(".") + try: + module = __import__(module) + config_overlay = getattr(module, function_name)() + except Exception as e: + from reflex.compiler.utils import save_error + + log_path = save_error(e) + + console.error( + f"Error loading extra_overlay_function {extra_config}. Error saved to {log_path}" + ) + return Fragment.create( connection_pulser(), connection_toaster(), + *([config_overlay] if config_overlay else []), *([backend_disabled()] if config.is_reflex_cloud else []), *codespaces.codespaces_auto_redirect(), ) diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index 57241fea9..c797a095f 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -158,6 +158,22 @@ def get_import_dict(lib: str, default: str = "", rest: list[str] | None = None) } +def save_error(error: Exception) -> str: + """Save the error to a file. + + Args: + error: The error to save. + + Returns: + The path of the saved error. + """ + timestamp = datetime.now().strftime("%Y-%m-%d__%H-%M-%S") + constants.Reflex.LOGS_DIR.mkdir(parents=True, exist_ok=True) + log_path = constants.Reflex.LOGS_DIR / f"error_{timestamp}.log" + traceback.TracebackException.from_exception(error).print(file=log_path.open("w+")) + return str(log_path) + + def compile_state(state: Type[BaseState]) -> dict: """Compile the state of the app. @@ -170,10 +186,7 @@ def compile_state(state: Type[BaseState]) -> dict: try: initial_state = state(_reflex_internal_init=True).dict(initial=True) except Exception as e: - timestamp = datetime.now().strftime("%Y-%m-%d__%H-%M-%S") - constants.Reflex.LOGS_DIR.mkdir(parents=True, exist_ok=True) - log_path = constants.Reflex.LOGS_DIR / f"state_compile_error_{timestamp}.log" - traceback.TracebackException.from_exception(e).print(file=log_path.open("w+")) + log_path = save_error(e) console.warn( f"Failed to compile initial state with computed vars. Error log saved to {log_path}" ) diff --git a/reflex/config.py b/reflex/config.py index 050676227..f3d40dc37 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -709,6 +709,9 @@ class Config(Base): # Whether the app is running in the reflex cloud environment. is_reflex_cloud: bool = False + # Extra overlay function to run after the app is built. Formatted such that `from path_0.path_1... import path[-1]`, and calling it with no arguments would work. For example, "reflex.components.moment.momnet". + extra_overlay_function: Optional[str] = None + def __init__(self, *args, **kwargs): """Initialize the config values.