Metadata-Version: 2.4
Name: fh-saas
Version: 0.9.14
Summary: Production-ready multi-tenant SaaS toolkit for FastHTML applications with authentication, billing, and integrations
Home-page: https://github.com/abhisheksreesaila/fh-saas
Author: abhishek sreesaila
Author-email: abhishek sreesaila <abhishek.sreesaila@gmail.com>
License: Apache-2.0
Project-URL: Repository, https://github.com/abhisheksreesaila/fh-saas
Project-URL: Documentation, https://abhisheksreesaila.github.io/fh-saas
Keywords: nbdev,jupyter,notebook,python,fasthtml,saas,multi-tenant,oauth,authentication
Classifier: Natural Language :: English
Classifier: Intended Audience :: Developers
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.25.0
Requires-Dist: tenacity>=8.2.0
Requires-Dist: polars>=0.20.0
Requires-Dist: pandas>=2.2.0
Requires-Dist: Markdown>=3.4.0
Requires-Dist: python-frontmatter>=1.1.0
Requires-Dist: pygments>=2.17.0
Requires-Dist: fastsql
Requires-Dist: python-fasthtml
Requires-Dist: starlette
Requires-Dist: python-dotenv
Requires-Dist: sqlalchemy
Requires-Dist: psycopg2-binary
Requires-Dist: fastcore
Requires-Dist: stripe
Requires-Dist: faststripe<2026.1.28
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# 🚀 fh-saas


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

## ⚡ Quick Start

### 1. Install

``` bash
pip install fh-saas
```

### 2. Configure Environment

``` bash
# .env file
DB_TYPE=POSTGRESQL
DB_USER=postgres
DB_PASS=your_password
DB_HOST=localhost
DB_NAME=app_host

# Optional integrations
STRIPE_SECRET_KEY=sk_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_MONTHLY_PRICE_ID=price_...
STRIPE_YEARLY_PRICE_ID=price_...
STRIPE_BASE_URL=https://yourapp.com
RESEND_API_KEY=re_...
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
```

### 3. Initialize Your App

``` python
from fh_saas.db_host import HostDatabase, GlobalUser, TenantCatalog, Membership, gen_id, timestamp
from fh_saas.db_tenant import get_or_create_tenant_db
from fh_saas.utils_db import register_tables, create_indexes
from fh_saas.utils_log import configure_logging

# Configure logging (once at startup)
configure_logging()

# Connect to host database
host_db = HostDatabase.from_env()

# Create a new user
user = GlobalUser(
    id=gen_id(),
    email="founder@startup.com",
    oauth_id="google_abc123",
    created_at=timestamp()
)
host_db.global_users.insert(user)

# Create a tenant for their organization
tenant = TenantCatalog(
    id=gen_id(),
    name="Acme Corp",
    db_url="postgresql://...",
    created_at=timestamp()
)
host_db.tenant_catalogs.insert(tenant)

# Link user to tenant as owner
membership = Membership(
    id=gen_id(),
    user_id=user.id,
    tenant_id=tenant.id,
    profile_id=gen_id(),
    role="owner",
    created_at=timestamp()
)
host_db.memberships.insert(membership)
host_db.commit()
```

### 4. Work with Tenant Data

``` python
# Get tenant's isolated database
tenant_db = get_or_create_tenant_db(tenant.id, tenant.name)

# Define your app's data models
class Project:
    id: str
    name: str
    status: str = "active"
    created_at: str

class Task:
    id: str
    project_id: str
    title: str
    completed: bool = False

# Register tables (creates if not exist)
tables = register_tables(tenant_db, [
    (Project, "projects", "id"),
    (Task, "tasks", "id"),
])

# Add indexes for performance
create_indexes(tenant_db, [
    ("tasks", ["project_id"], False, None),
    ("tasks", ["completed"], False, None),
])

# Use the tables
projects = tables["projects"]
projects.insert(Project(id=gen_id(), name="Launch MVP", created_at=timestamp()))
tenant_db.conn.commit()
```

------------------------------------------------------------------------

## 📚 Documentation Guide

|  |  |
|----|----|
| Section | What You'll Learn |
| **📦 Core** |  |
| [Multi-Tenant Setup](https://abhisheksreesaila.github.io/fh-saas/db_host.html) | Host database, user management, tenant registry |
| [Tenant Databases](https://abhisheksreesaila.github.io/fh-saas/db_tenant.html) | Isolated databases per tenant, connection pooling |
| [Table Management](https://abhisheksreesaila.github.io/fh-saas/utils_db.html) | Create tables & indexes from dataclasses |
| **🔌 Integrations** |  |
| [HTTP Client](https://abhisheksreesaila.github.io/fh-saas/utils_api.html) | REST APIs with retries, rate limiting, auth |
| [GraphQL Client](https://abhisheksreesaila.github.io/fh-saas/utils_graphql.html) | Streaming pagination for large datasets |
| [Webhooks](https://abhisheksreesaila.github.io/fh-saas/utils_webhook.html) | Receive & verify external webhooks |
| **💳 Payments & Migrations** |  |
| [Billing Orchestrator](https://abhisheksreesaila.github.io/fh-saas/utils_billing.html) | Provider-agnostic billing contracts, lifecycle services, one-liner route registration |
| [Stripe Payments](https://abhisheksreesaila.github.io/fh-saas/utils_stripe.html) | Subscriptions, trials, access control |
| [DB Migrations](https://abhisheksreesaila.github.io/fh-saas/utils_migrate.html) | Version tracking, rollback support |
| **⚙️ Data Pipeline** |  |
| [Background Tasks](https://abhisheksreesaila.github.io/fh-saas/utils_bgtsk.html) | Async job execution |
| [Data Transforms](https://abhisheksreesaila.github.io/fh-saas/utils_polars_mapper.html) | JSON → Polars → Database pipeline |
| **🛠️ Utilities** |  |
| [SQL Helpers](https://abhisheksreesaila.github.io/fh-saas/utils_sql.html) | Database type detection, query builders |
| [Logging](https://abhisheksreesaila.github.io/fh-saas/utils_log.html) | Configurable logging for all modules |
| [Authentication](https://abhisheksreesaila.github.io/fh-saas/utils_oauth.html) | OAuth flows (Google, GitHub) |
| [Email Sending](https://abhisheksreesaila.github.io/fh-saas/utils_email.html) | Transactional emails via Resend |
| **📣 Content** |  |
| [Blog Publishing](https://abhisheksreesaila.github.io/fh-saas/utils_blog.html) | Markdown blog with frontmatter |
| [SEO & Sitemaps](https://abhisheksreesaila.github.io/fh-saas/utils_seo.html) | Sitemap generation, meta tags |
| [Workflow Engine](https://abhisheksreesaila.github.io/fh-saas/utils_workflow.html) | Multi-step automation |

------------------------------------------------------------------------

## ⚡ Performance Notes

For FastHTML and Starlette apps with a mix of DB-backed and non-DB protected
pages, use auth hydration and tenant DB access as separate steps:

``` python
from fh_saas.utils_auth import create_auth_beforeware, require_tenant_access

beforeware = create_auth_beforeware(
    setup_tenant_db=False,
    session_cache=True,
)

@app.get('/dashboard')
def dashboard(request):
    return render_dashboard(request.state.user)

@app.get('/transactions')
def transactions(request):
    tenant_db = require_tenant_access(request)
    tables = get_app_tables(tenant_db)
    return render_transactions(tables)
```

This keeps protected non-DB pages from paying tenant DB setup costs on every
request while still preserving a lazy boundary for routes that actually need
tenant data. For rollout diagnostics, set `FH_TIMING_ENABLED=1` to emit timing
labels for auth and tenant DB setup.

------------------------------------------------------------------------

## 📝 Release Notes

### v0.9.13

| Before | After | Benefit |
|---|---|---|
| Auth beforeware eagerly opened the tenant DB on every protected request, even for pages that only needed session or user info. | Auth hydration and tenant DB access were split, so non-DB routes can stop at `request.state.user`, and DB routes cross the boundary only when they call `require_tenant_access`. | Lower latency on protected pages like dashboards, nav loads, and HTMX partials that do not query tenant tables. |
| Every tenant DB open could pay engine setup and schema reflection costs again. | Tenant routing, shared SQLAlchemy engine, and reflected metadata are cached, while each request still gets a fresh live connection. | Warm tenant routes become much cheaper after the first hit, especially for repeated requests within the same tenant. |
| Role lookup and membership validation did broader reads and more Python-side filtering than necessary. | Role resolution, global user lookup, membership lookup, and membership verification now use direct `where ... limit 1` queries. | Faster auth decisions, less DB I/O, and less Python work on login and route protection paths. |
| Session-heavy HTMX traffic could rebuild the same auth state on each request. | Optional session auth caching reuses a recent hydrated auth payload for a short TTL. | Reduced repeated auth cost on bursty UI interactions and partial refreshes. |
| Billing middleware and checkout return paths could fetch the same subscription more than once in one request flow. | Trial initialization returns the resolved subscription, and checkout and billing hooks reuse already-fetched subscription state. | Fewer duplicate host DB reads on subscription-gated routes and payment return flows. |
| Route timing required ad hoc logging to understand where latency was going. | Env-gated timing hooks emit labeled timings for auth and tenant DB phases when enabled. | Easier rollout diagnostics and faster identification of remaining bottlenecks. |

------------------------------------------------------------------------

## 🛠️ Developer Guide

This project uses [nbdev](https://nbdev.fast.ai/) for literate
programming. The source of truth is in the `nbs/` notebooks.

### Development Setup

``` bash
# Clone and install in dev mode
git clone https://github.com/abhisheksreesaila/fh-saas.git
cd fh-saas
pip install -e .

# Make changes in nbs/ directory, then compile
nbdev_prepare
```

------------------------------------------------------------------------

## 📦 Installation

``` bash
# From PyPI (recommended)
pip install fh-saas

# From GitHub (latest)
pip install git+https://github.com/abhisheksreesaila/fh-saas.git
```

[GitHub](https://github.com/abhisheksreesaila/fh-saas) ·
[PyPI](https://pypi.org/project/fh-saas/) ·
[Documentation](https://abhisheksreesaila.github.io/fh-saas/)

**🤖 For AI Assistants:** [Download
llms-ctx.txt](https://raw.githubusercontent.com/abhisheksreesaila/fh-saas/main/llms-ctx.txt)
— Complete API documentation for LLMs

------------------------------------------------------------------------

## 🤖 AI Assistant Context

**For AI coding assistants** (GitHub Copilot, Claude, ChatGPT, Cursor,
etc.), download the complete API documentation:

**[📥 Download
llms-ctx.txt](https://raw.githubusercontent.com/abhisheksreesaila/fh-saas/main/llms-ctx.txt)**
— Complete fh-saas documentation in LLM-friendly format

### How to use:

1.  Download the context file
2.  Add to your AI assistant’s instructions/knowledge base  
3.  Get accurate code suggestions for fh-saas APIs

This file contains all module documentation, examples, and API
signatures formatted for optimal LLM understanding.

------------------------------------------------------------------------

## 🤝 Contributing

Contributions are welcome! Please check the [GitHub
repository](https://github.com/abhisheksreesaila/fh-saas) for issues and
discussions.
