Metadata-Version: 2.4
Name: fastx-database
Version: 1.9.0
Summary: Shared SQLAlchemy ORM models plus IRepository and concrete repos for FastMVC apps.
Author-email: Shivansh Sengar <sengarsinghshivansh@gmail.com>, Shreyansh Sengar <sengarsinghshreyansh@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/shregar1/fastMVC
Project-URL: Repository, https://github.com/shregar1/fastMVC
Keywords: fastapi,database,sqlalchemy,orm,models,fastmvc
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: sqlalchemy<3.0,>=2.0
Requires-Dist: loguru<1.0.0,>=0.7.0
Requires-Dist: cachetools<6.0.0,>=5.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: factory-boy>=3.3.0; extra == "dev"
Dynamic: license-file

# fast-database

**Shared SQLAlchemy ORM models** for FastMVC applications: one declarative `Base`, table name constants, and models for users/auth, organizations, subscriptions, payments, commerce (cart/orders/shipments), webhooks, notifications, LLM **conversation** threads, **per-user encrypted LLM provider API keys** (BYOK), **user messaging** (chats, messages, read receipts, notification delivery), personal ledger / Pure.cam–aligned tables, and audit logs.

**Operational / production patterns** baked into the schema include: **idempotency** (`IdempotencyRecord`), **transactional outbox** (`OutboxEvent`), **one-time tokens** (`UserOneTimeToken`), **login attempt history** (`UserLoginEvent`), **consent** (`ConsentRecord`), plus **`SystemSetting`** (runtime toggles), **`UserMfaFactor`** (MFA enrollment), **`DataExportRequest`** (GDPR-style exports), **`SecurityEvent`** (SIEM-friendly signals), and **`UsageCounter`** (quota / metering buckets).

The same wheel also ships **`fast_database.repositories`**: `IRepository`, `FilterOperator`, and concrete repository classes for the tables above (same import paths as before).

**Python:** 3.10+ · **Dependencies:** `sqlalchemy>=2,<3`, `loguru`, `cachetools`

**Import packages:** `fast_database`, `fast_database.repositories`  
**PyPI distribution name:** `fast-database` (hyphenated)

## Layout

- **`fast_database.models` — `Base`** and all table classes.
- **`fast_database.constants.db.table` — `Table`** — centralized string names for `__tablename__`.
- **`fast_database.mixins`** — `TimestampMixin`, `UUIDPrimaryKeyMixin`, `SoftDeleteMixin`, `OrganizationScopedMixin`, `TenantIdMixin`, `OptimisticLockMixin`, `AuditActorMixin`.
- **`fast_database.optimistic_lock`** — `assert_version_matches`, `expected_version`, `StaleVersionError` for service-layer checks.
- **`fast_database.soft_delete`** — `select_active`, `where_not_deleted`, `mark_soft_deleted`, `restore_soft_deleted`, `filter_active`.
- **`fast_database.factories`** (optional **`[dev]`** extra, includes `factory-boy`) — example `PlanFactory` for tests.
- **`fast_database.repositories`** — `FilterOperator`, `IRepository`, and per-entity repositories (e.g. `from fast_database.repositories.user import UserRepository`).

### Mixins (new tables)

```python
from sqlalchemy import Column, String
from fast_database import Base, TimestampMixin, UUIDPrimaryKeyMixin, SoftDeleteMixin

class Widget(Base, UUIDPrimaryKeyMixin, TimestampMixin, SoftDeleteMixin):
    __tablename__ = "widgets"
    label = Column(String(255), nullable=False)
```

### Tenant-scoped rows (composite indexes)

Use **`OrganizationScopedMixin`** (`organization_id` → `organizations.id`) or **`TenantIdMixin`** (generic `tenant_id` without FK). Add a composite index for common filters:

```python
from sqlalchemy import Column, Index, Integer, String
from fast_database import Base, OrganizationScopedMixin

class InvoiceLine(Base, OrganizationScopedMixin):
    __tablename__ = "invoice_lines"
    __table_args__ = (Index("ix_invline_org_external", "organization_id", "external_ref"),)
    id = Column(Integer, primary_key=True)
    external_ref = Column(String(64), nullable=False)
```

### Optimistic locking

Add **`OptimisticLockMixin`** and map ``version`` with :func:`sqlalchemy.orm.declared_attr` (see docstring on the mixin). Use **`assert_version_matches(instance, client_version)`** before applying updates from the API.

### Audit actor columns

**`AuditActorMixin`** adds nullable **`created_by_id`** / **`updated_by_id`** FKs to `user.id` (set from the current user in services).

### factory_boy (tests)

```bash
pip install 'fast-database[dev]'
```

```python
from fast_database.factories import PlanFactory
# Bind PlanFactory._meta.sqlalchemy_session to your test session, then:
plan = PlanFactory()
```

### Alembic autogenerate

1. Point Alembic at the same metadata as your app: `target_metadata = Base.metadata` (import `Base` from `fast_database`).
2. Ensure `env.py` loads all model modules so every table is registered on `Base.metadata` before autogenerate runs (otherwise Alembic will propose dropping “unknown” tables).

Example fragment for **`migrations/env.py`** (adjust imports to your project layout):

```python
# Load ORM models so Base.metadata is complete before autogenerate.
import fast_database.models  # noqa: F401 — registers all tables on Base

from fast_database.models import Base

target_metadata = Base.metadata

# In run_migrations_online(), pass target_metadata to context.configure(
#     ...
#     target_metadata=target_metadata,
#     compare_type=True,
#     compare_server_default=True,
# )
```

Then:

```bash
alembic revision --autogenerate -m "describe change"
alembic upgrade head
```

Review autogenerated diffs carefully (renames are not always detected; constraints may need hand edits).

## Install

```bash
pip install -e ./fast_database
```

Or from PyPI (when published):

```bash
pip install fast-database
```

Pair with **`fast_db`** so your app’s engine uses the same metadata for Alembic migrations.

For tests with **factory_boy** examples: `pip install 'fast-database[dev]'`.

## Related packages

- **`fast_db`** — engine and sessions.
- Monorepo: [../README.md](../README.md).

## Tooling

See [CONTRIBUTING.md](CONTRIBUTING.md), [Makefile](Makefile), and [PUBLISHING.md](PUBLISHING.md).

---

## Documentation

| Document | Purpose |
|----------|---------|
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup, tests, monorepo sync |
| [PUBLISHING.md](PUBLISHING.md) | PyPI and releases |
| [SECURITY.md](SECURITY.md) | Reporting vulnerabilities |
| [CHANGELOG.md](CHANGELOG.md) | Version history |

**Monorepo:** [../README.md](../README.md) · **Coverage:** [../docs/COVERAGE.md](../docs/COVERAGE.md)
