Metadata-Version: 2.4
Name: cjm-fasthtml-settings
Version: 0.0.14
Summary: A drop-in schema-based configuration system for FastHTML applications with automatic UI generation, sidebar navigation, and persistent storage.
Home-page: https://github.com/cj-mills/cjm-fasthtml-settings
Author: Christian J. Mills
Author-email: 9126128+cj-mills@users.noreply.github.com
License: Apache Software License 2.0
Keywords: nbdev jupyter notebook python
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: Apache Software License
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastcore
Requires-Dist: pandas
Requires-Dist: cjm_fasthtml_daisyui
Requires-Dist: cjm_fasthtml_jsonschema
Requires-Dist: cjm_fasthtml_app_core
Requires-Dist: cjm_fasthtml_plugins
Requires-Dist: cjm_error_handling
Requires-Dist: cjm_fasthtml_interactions
Provides-Extra: dev
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# cjm-fasthtml-settings


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## Install

``` bash
pip install cjm_fasthtml_settings
```

## Project Structure

    nbs/
    ├── components/ (4)
    │   ├── dashboard.ipynb              # Settings dashboard layout components
    │   ├── forms.ipynb                  # Form generation components for settings interfaces
    │   ├── master_detail_adapter.ipynb  # Adapter for integrating cjm-fasthtml-interactions MasterDetail pattern into settings
    │   └── sidebar.ipynb                # Navigation menu components for settings sidebar
    ├── core/ (5)
    │   ├── config.ipynb        # Configuration constants, directory management, and base application schema
    │   ├── html_ids.ipynb      # Centralized HTML ID constants for settings components
    │   ├── schema_group.ipynb  # Grouping related configuration schemas for better organization
    │   ├── schemas.ipynb       # Schema registry and management for settings
    │   └── utils.ipynb         # Configuration loading, saving, and conversion utilities
    ├── plugins.ipynb  # Optional plugin integration for extensible settings systems
    └── routes.ipynb   # FastHTML route handlers for settings interface

Total: 11 notebooks across 2 directories

## Module Dependencies

``` mermaid
graph LR
    components_dashboard[components.dashboard<br/>Dashboard]
    components_forms[components.forms<br/>Forms]
    components_master_detail_adapter[components.master_detail_adapter<br/>Master-Detail Adapter]
    components_sidebar[components.sidebar<br/>Sidebar]
    core_config[core.config<br/>Config]
    core_html_ids[core.html_ids<br/>HTML IDs]
    core_schema_group[core.schema_group<br/>Schema Group]
    core_schemas[core.schemas<br/>Schemas]
    core_utils[core.utils<br/>Utils]
    plugins[plugins<br/>Plugins]
    routes[routes<br/>Routes]

    components_dashboard --> core_utils
    components_dashboard --> core_html_ids
    components_dashboard --> components_forms
    components_dashboard --> components_sidebar
    components_dashboard --> core_config
    components_forms --> core_html_ids
    components_forms --> core_utils
    components_forms --> core_config
    components_master_detail_adapter --> core_utils
    components_master_detail_adapter --> components_forms
    components_master_detail_adapter --> core_schemas
    components_master_detail_adapter --> core_config
    components_sidebar --> core_html_ids
    components_sidebar --> core_schemas
    components_sidebar --> core_config
    core_schemas --> core_config
    core_schemas --> core_schema_group
    core_schemas --> core_schemas
    core_utils --> core_config
    routes --> core_html_ids
    routes --> components_forms
    routes --> core_utils
    routes --> core_schemas
    routes --> core_config
    routes --> routes
```

*25 cross-module dependencies detected*

## CLI Reference

No CLI commands found in this project.

## Module Overview

Detailed documentation for each module in the project:

### Config (`config.ipynb`)

> Configuration constants, directory management, and base application
> schema

#### Import

``` python
from cjm_fasthtml_settings.core.config import (
    DEFAULT_CONFIG_DIR,
    get_app_config_schema
)
```

#### Functions

``` python
def get_app_config_schema(
    app_title: str = "FastHTML Application",  # Default application title
    config_dir: str = "configs",  # Default configuration directory
    server_port: int = 5000,  # Default server port
    themes_enum: Optional[List[str]] = None,  # Optional list of theme values
    themes_enum_names: Optional[List[str]] = None,  # Optional list of theme display names
    default_theme: Optional[str] = None,  # Default theme value
    include_theme: bool = True,  # Whether to include theme selection
    **extra_properties  # Additional custom properties to add to the schema
) -> Dict[str, Any]:  # JSON Schema for application configuration
    "Generate a customizable application configuration schema."
```

#### Variables

``` python
DEFAULT_CONFIG_DIR
```

### Dashboard (`dashboard.ipynb`)

> Settings dashboard layout components

#### Import

``` python
from cjm_fasthtml_settings.components.dashboard import (
    create_form_skeleton,
    render_schema_settings_content,
    settings_content
)
```

#### Functions

``` python
def create_form_skeleton(
    schema_id: str,  # The schema ID for the settings
    hx_get_url: str  # URL to fetch the actual form content
) -> FT:  # Div element with loading trigger
    "Create a loading skeleton for the settings form that loads asynchronously."
```

``` python
def render_schema_settings_content(
    schema: Dict,  # JSON schema for the settings
    config_dir: Optional[Path] = None  # Config directory path
) -> FT:  # Settings form container
    "Render settings content for a schema-based configuration."
```

``` python
def settings_content(
    request,  # FastHTML request object
    schema: Dict,  # Schema to display
    schemas: Dict,  # All registered schemas for sidebar
    config_dir: Optional[Path] = None,  # Config directory
    menu_section_title: str = "Settings",  # Sidebar section title
    plugin_registry: Optional[Any] = None  # Optional plugin registry
) -> FT:  # Settings content layout
    "Return settings content with sidebar and form."
```

### Forms (`forms.ipynb`)

> Form generation components for settings interfaces

#### Import

``` python
from cjm_fasthtml_settings.components.forms import (
    create_settings_form,
    create_settings_form_container
)
```

#### Functions

``` python
def create_settings_form(
    schema: Dict[str, Any],  # JSON schema for the form
    values: Dict[str, Any],  # Current values for the form fields
    post_url: str,  # URL for form submission
    reset_url: str,  # URL for resetting form to defaults
    target_id: str = None  # HTML ID of target container (defaults to SETTINGS_CONTENT)
) -> FT:  # Form element with settings and action buttons
    "Create a settings form with action buttons."
```

``` python
def create_settings_form_container(
    schema: Dict[str, Any],  # JSON schema for the form
    values: Dict[str, Any],  # Current values for the form fields
    post_url: str,  # URL for form submission
    reset_url: str,  # URL for resetting form to defaults
    alert_message: Optional[Any] = None,  # Optional alert element to display
    use_alert_container: bool = False,  # If True, add empty alert-container div
    target_id: str = None  # HTML ID of target container (defaults to SETTINGS_CONTENT)
) -> FT:  # Div containing the alert (if any) and the settings form
    "Create a container with optional alert and settings form."
```

### HTML IDs (`html_ids.ipynb`)

> Centralized HTML ID constants for settings components

#### Import

``` python
from cjm_fasthtml_settings.core.html_ids import (
    SettingsHtmlIds
)
```

#### Classes

``` python
class SettingsHtmlIds(AppHtmlIds):
    "HTML ID constants for settings components."
    
    def menu_item(
            name: str  # Settings name
        ) -> str:  # Menu item ID
        "Generate a menu item ID for a given settings name."
```

### Master-Detail Adapter (`master_detail_adapter.ipynb`)

> Adapter for integrating cjm-fasthtml-interactions MasterDetail pattern
> into settings

#### Import

``` python
from cjm_fasthtml_settings.components.master_detail_adapter import (
    create_settings_detail_renderer,
    create_settings_data_loader,
    is_schema_configured,
    create_settings_master_detail
)
```

#### Functions

``` python
def create_settings_detail_renderer(
    config_dir: Path,  # Configuration directory
    save_route_fn: callable,  # Function that returns save route URL for schema_id
    reset_route_fn: callable  # Function that returns reset route URL for schema_id
) -> callable:  # Render function for detail view
    """
    Create a render function for settings detail view.
    
    This creates a closure that captures the config_dir and route functions,
    returning a render function compatible with DetailItem.
    """
```

``` python
def create_settings_data_loader(
    schema: Dict,  # JSON schema
    schema_id: str  # Schema identifier
) -> callable:  # Data loader function
    "Create a data loader that provides schema information."
```

``` python
def is_schema_configured(
    schema_id: str,  # Schema identifier
    config_dir: Path  # Configuration directory
) -> bool:  # True if config file exists
    "Check if a schema has been configured."
```

``` python
def create_settings_master_detail(
    schemas: Dict,  # All registered schemas (from registry.get_all())
    config_dir: Path,  # Configuration directory
    save_route_fn: callable,  # Function that returns save route URL for schema_id
    reset_route_fn: callable,  # Function that returns reset route URL for schema_id
    default_schema: str = "general",  # Default schema to show
    menu_section_title: str = "Settings",  # Title for master list
    plugin_registry: Optional[Any] = None,  # Optional plugin registry
    plugin_save_route_fn: Optional[callable] = None,  # Function that returns save route URL for plugin_id
    plugin_reset_route_fn: Optional[callable] = None  # Function that returns reset route URL for plugin_id
) -> MasterDetail:  # Configured MasterDetail instance
    """
    Create a MasterDetail instance configured for settings.
    
    This adapter function transforms the settings schema structure into
    DetailItem and DetailItemGroup objects compatible with MasterDetail.
    """
```

### Plugins (`plugins.ipynb`)

> Optional plugin integration for extensible settings systems

#### Import

``` python
from cjm_fasthtml_settings.plugins import (
    PluginRegistryProtocol
)
```

#### Classes

``` python
@runtime_checkable
class PluginRegistryProtocol(Protocol):
    "Protocol that plugin registries should implement."
    
    def get_plugin(
            self, 
            unique_id: str  # Plugin unique ID
        ) -> Optional[PluginMetadata]:  # Plugin metadata or None
        "Get plugin metadata by unique ID."
    
    def get_plugins_by_category(
            self, 
            category: str  # Category name
        ) -> list[PluginMetadata]:  # List of plugins in category
        "Get all plugins in a category."
    
    def get_categories_with_plugins(
            self
        ) -> list[str]:  # List of category names
        "Get all categories that have registered plugins."
    
    def load_plugin_config(
            self, 
            unique_id: str  # Plugin unique ID
        ) -> Dict[str, Any]:  # Loaded configuration
        "Load saved configuration for a plugin."
    
    def save_plugin_config(
            self, 
            unique_id: str,  # Plugin unique ID
            config: Dict[str, Any]  # Configuration to save
        ) -> bool:  # True if save succeeded
        "Save configuration for a plugin."
```

### Routes (`routes.ipynb`)

> FastHTML route handlers for settings interface

#### Import

``` python
from cjm_fasthtml_settings.routes import (
    config,
    settings_ar,
    RoutesConfig,
    configure_settings,
    index,
    save,
    reset,
    plugin_reset,
    plugin_save
)
```

#### Functions

``` python
def configure_settings(
    config_dir: Path = None,  # Directory for storing configuration files
    wrap_with_layout: Callable = None,  # Function to wrap full page content with app layout
    plugin_registry = None,  # Optional plugin registry (must implement PluginRegistryProtocol)
    default_schema: str = "general",  # Default schema to display
    menu_section_title: str = "Settings"  # Title for the settings menu section
) -> RoutesConfig:  # Configured RoutesConfig instance
    "Configure the settings system with a single function call."
```

``` python
def _resolve_schema(
    id: str  # Schema ID
) -> tuple:  # (schema, error_message)
    "Resolve schema from ID using the registry."
```

``` python
@settings_ar
def index(
    request,  # FastHTML request object
    id: str = None  # Schema ID to display (defaults to config.default_schema)
) -> FT:  # Settings page content
    "Main settings page."
```

``` python
@settings_ar
async def save(
    request,  # FastHTML request object
    id: str  # Schema ID to save
) -> FT:  # Response with form or error
    "Save configuration handler."
```

``` python
@settings_ar
def reset(
    id: str  # Schema ID to reset
) -> FT:  # Response with form or error
    "Reset configuration to defaults handler."
```

``` python
@settings_ar
def plugin_reset(
    id: str  # Plugin unique ID
) -> FT:  # Response with form or error
    "Reset plugin configuration to defaults handler."
```

``` python
@settings_ar
async def plugin_save(
    request,  # FastHTML request object
    id: str  # Plugin unique ID
) -> FT:  # Response with form or error
    "Save plugin configuration handler."
```

#### Classes

``` python
class RoutesConfig:
    "Configuration for settings routes behavior."
```

### Schema Group (`schema_group.ipynb`)

> Grouping related configuration schemas for better organization

#### Import

``` python
from cjm_fasthtml_settings.core.schema_group import (
    SchemaGroup
)
```

#### Classes

``` python
@dataclass
class SchemaGroup:
    "A group of related configuration schemas."
    
    name: str
    title: str
    schemas: Dict[str, Dict[str, Any]]
    icon: Optional[Any]
    default_open: bool = True
    description: Optional[str]
    
    def get_schema(
            self, 
            schema_name: str  # Schema name
        ) -> Optional[Dict[str, Any]]:  # Schema dictionary or None
        "Get a specific schema from the group by name."
    
    def get_unique_id(
            self, 
            schema_name: str  # Schema name
        ) -> str:  # Unique ID in format: {group_name}_{schema_name}
        "Generate a unique ID for a schema within this group."
    
    def has_configured_schemas(
            self,
            config_dir: Path  # Directory where config files are stored
        ) -> bool:  # True if any schema in group has saved config
        "Check if any schemas in this group have saved configurations."
    
    def get_configured_schemas(
            self,
            config_dir: Path  # Directory where config files are stored
        ) -> list:  # List of schema names that have saved configs
        "Get list of configured schema names in this group."
```

### Schemas (`schemas.ipynb`)

> Schema registry and management for settings

#### Import

``` python
from cjm_fasthtml_settings.core.schemas import (
    registry,
    SettingsRegistry
)
```

#### Classes

``` python
class SettingsRegistry:
    def __init__(self):
        self._schemas: Dict[str, Union[Dict[str, Any], 'SchemaGroup']] = {}
    "Registry for managing settings schemas and schema groups."
    
    def __init__(self):
            self._schemas: Dict[str, Union[Dict[str, Any], 'SchemaGroup']] = {}
    
    def register(
            self,
            schema: Union[Dict[str, Any], 'SchemaGroup'],  # Schema or SchemaGroup to register
            name: Optional[str] = None  # Optional name override
        )
        "Register a settings schema or schema group."
    
    def get(
            self,
            name: str  # Name of the schema/group to retrieve
        ) -> Optional[Union[Dict[str, Any], 'SchemaGroup']]:  # The schema/group, or None if not found
        "Get a registered schema or group by name."
    
    def list_schemas(
            self
        ) -> list:  # List of registered schema/group names
        "List all registered schema and group names."
    
    def get_all(
            self
        ) -> Dict[str, Union[Dict[str, Any], 'SchemaGroup']]:  # All schemas and groups
        "Get all registered schemas and groups."
    
    def resolve_schema(
            self,
            id: str  # Schema ID (can be 'name' or 'group_schema' format)
        ) -> tuple:  # (schema_dict, error_message)
        "Resolve a schema ID to a schema dictionary."
```

### Sidebar (`sidebar.ipynb`)

> Navigation menu components for settings sidebar

#### Import

``` python
from cjm_fasthtml_settings.components.sidebar import (
    create_sidebar_menu,
    create_oob_sidebar_menu
)
```

#### Functions

``` python
def create_sidebar_menu(
    schemas: Dict[str, Any],  # Dictionary of schemas/groups to display in sidebar
    active_schema: Optional[str] = None,  # The currently active schema name
    config_dir: Optional[Path] = None,  # Directory where config files are stored
    include_wrapper: bool = True,  # Whether to include the outer wrapper div
    menu_section_title: str = "Settings",  # Title for the settings section
    plugin_registry: Optional[Any] = None  # Optional plugin registry
) -> FT:  # Div or Ul element containing the sidebar menu
    "Create the sidebar navigation menu with support for schema groups and plugins."
```

``` python
def create_oob_sidebar_menu(
    schemas: Dict[str, Dict[str, Any]],  # Dictionary of schemas
    active_schema: str,  # Active schema name
    config_dir: Optional[Path] = None,  # Config directory
    menu_section_title: str = "Settings",  # Menu section title
    plugin_registry: Optional[Any] = None  # Optional plugin registry
) -> FT:  # Sidebar menu with OOB swap attribute
    "Create sidebar menu with OOB swap attribute for HTMX."
```

### Utils (`utils.ipynb`)

> Configuration loading, saving, and conversion utilities

#### Import

``` python
from cjm_fasthtml_settings.core.utils import (
    load_config,
    save_config,
    get_default_values_from_schema,
    get_config_with_defaults,
    convert_form_data_to_config
)
```

#### Functions

``` python
def load_config(
    schema_name: str,  # Name of the schema/configuration to load
    config_dir: Optional[Path] = None  # Directory where config files are stored
) -> Dict[str, Any]:  # Loaded configuration dictionary (empty dict if file doesn't exist)
    "Load saved configuration for a schema."
```

``` python
def save_config(
    schema_name: str,  # Name of the schema/configuration to save
    config: Dict[str, Any],  # Configuration dictionary to save
    config_dir: Optional[Path] = None  # Directory where config files are stored
) -> bool:  # True if save succeeded, False otherwise
    "Save configuration for a schema."
```

``` python
def get_default_values_from_schema(
    schema: Dict[str, Any]  # JSON Schema dictionary
) -> Dict[str, Any]:  # Dictionary of default values extracted from schema
    "Extract default values from a JSON schema."
```

``` python
def get_config_with_defaults(
    schema_name: str,  # Name of the schema (or unique_id for grouped schemas)
    schema: Dict[str, Any],  # JSON Schema dictionary
    config_dir: Optional[Path] = None  # Directory where config files are stored
) -> Dict[str, Any]:  # Merged configuration with defaults and saved values
    "Get configuration with defaults merged with saved values."
```

``` python
def convert_form_data_to_config(
    form_data: dict,  # Raw form data from request
    schema: Dict[str, Any]  # JSON Schema for type conversion
) -> dict:  # Converted configuration dictionary
    "Convert form data to configuration dict based on schema."
```
