Metadata-Version: 2.4
Name: db2md
Version: 0.1.0
Summary: Connect to any SQLAlchemy URL, introspect schemas, and generate Markdown docs with Mermaid ER diagrams
Project-URL: Homepage, https://github.com/edwinalkins/db2md
Project-URL: Documentation, https://edwinalkins.github.io/db2md/
Project-URL: Repository, https://github.com/edwinalkins/db2md
Project-URL: Issues, https://github.com/edwinalkins/db2md/issues
Project-URL: Changelog, https://github.com/edwinalkins/db2md/blob/main/CHANGELOG.md
Author: edwinalkins
License-Expression: MIT
License-File: LICENSE
Keywords: database,documentation,markdown,mermaid,schema,sqlalchemy
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Documentation
Classifier: Typing :: Typed
Requires-Python: >=3.14
Requires-Dist: click>=8.1
Requires-Dist: sqlalchemy[asyncio]>=2.0
Provides-Extra: all
Requires-Dist: aiomysql>=0.2; extra == 'all'
Requires-Dist: aiosqlite>=0.20; extra == 'all'
Requires-Dist: asyncpg>=0.29; extra == 'all'
Provides-Extra: mysql
Requires-Dist: aiomysql>=0.2; extra == 'mysql'
Provides-Extra: postgres
Requires-Dist: asyncpg>=0.29; extra == 'postgres'
Provides-Extra: sqlite
Requires-Dist: aiosqlite>=0.20; extra == 'sqlite'
Description-Content-Type: text/markdown

<p align="center">
  <img src="logo.png" alt="db2md" width="280" />
</p>

<p align="center">
  <a href="https://github.com/edwinalkins/db2md/actions/workflows/ci.yml"><img src="https://github.com/edwinalkins/db2md/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
  <img src="https://img.shields.io/badge/python-3.14%2B-blue" alt="Python 3.14+" />
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
</p>

<p align="center"><strong>One URL in. Schema docs out.</strong></p>

<p align="center">
  <img src="docs/db2md-flow.png" alt="Database → db2md → Markdown → Mermaid ER" width="820" />
</p>

```text
Database  →  db2md  →  Markdown  →  Mermaid ER
```

Connect with any SQLAlchemy URL. Discover databases. Introspect tables, FKs, indexes, and comments. Write **one Markdown file per database** with a Mermaid ER diagram — no hardcoded names, no config file.

```bash
pip install 'db2md[postgres]'
db2md --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres'
# → ./schemas/<database>.md
```

Full documentation: [edwinalkins.github.io/db2md](https://edwinalkins.github.io/db2md/)

## Why db2md?

| | |
|---|---|
| **Async-native** | SQLAlchemy 2.x + async drivers (`asyncpg`, `aiomysql`, `aiosqlite`) |
| **Zero hardcoding** | Everything comes from introspection |
| **Docs you can commit** | Markdown + Mermaid — preview on GitHub, MkDocs, Notion… |
| **Library + CLI** | Script it, or run `db2md` in CI |

## Install

```bash
pip install 'db2md[postgres]'   # or [mysql] / [sqlite] / [all]

# From this repo
uv sync --extra postgres
```

| Dialect | Extra | Driver |
|---------|-------|--------|
| PostgreSQL | `postgres` | `asyncpg` |
| MySQL / MariaDB | `mysql` | `aiomysql` |
| SQLite | `sqlite` | `aiosqlite` |

## CLI

```bash
# List databases (skips system catalogs by default)
db2md --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres' --list

# Document every non-system database → ./schemas/<db>.md
db2md --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres'

# Specific databases / output path
db2md \
  --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres' \
  -d myapp -d analytics \
  -o ./docs/db

uv run db2md --url 'sqlite+aiosqlite:///./app.db' -o ./schemas
```

### Options

| Flag | Description |
|------|-------------|
| `-u`, `--url` | SQLAlchemy URL (or set `DATABASE_URL`) |
| `-o`, `--output` | Output directory (default: `schemas/`), or a file when documenting a single `-d` |
| `-d`, `--database` | Database to document (repeatable). Default: all non-system DBs |
| `--schema` | Schema/namespace (default: dialect-specific — `public` for PostgreSQL) |
| `--list` | List databases and exit |
| `--include-system` | Include system databases |
| `-v`, `--verbose` | Debug logging |
| `--version` | Show version |

Bare dialects are upgraded to async drivers automatically (`postgresql://…` → `postgresql+asyncpg://…`, etc.).

## Library API

```python
import asyncio
from db2md import list_databases, generate_schema_markdown, export_schemas

URL = "postgresql+asyncpg://user:pass@localhost:5432/postgres"

async def main() -> None:
    dbs = await list_databases(URL)
    name, table_count, md = await generate_schema_markdown(URL, "myapp")
    paths = await export_schemas(URL, "schemas")
    print(dbs, name, table_count, paths)

asyncio.run(main())
```

### Public symbols

| Symbol | Role |
|--------|------|
| `list_databases(url, *, include_system=False)` | List database names (dialect-aware) |
| `generate_schema_markdown(url, database, *, schema=None)` | Returns `(name, table_count, markdown)` |
| `export_schemas(url, output="schemas", …)` | Write one `.md` file per database |
| `ColumnInfo` / `ForeignKeyInfo` / `IndexInfo` / `CheckConstraintInfo` / `TableInfo` | Introspection dataclasses |

## Output

Each generated file contains:

1. **ER diagram** — Mermaid `erDiagram` with PK/FK markers and inferred cardinalities (1–1, 1–N, N–N)
2. **Tables** — columns, nullability, defaults, primary keys, comments
3. **Foreign keys**, unique constraints, check constraints (name + SQL), indexes (columns + UNIQUE)

Example sketch:

````markdown
# Database schema — `myapp`

> Auto-generated on 2026-08-02 12:00:00 UTC (schema `public`, 2 table(s)).

## ER diagram

```mermaid
erDiagram
    "users" {
        INTEGER id "PK"
        VARCHAR_255 email
    }
    "users" ||--|{ "notes" : "notes_user_id_fkey"
```

## Tables

### `users`

Application users

| Column | Type | Nullable | Default | PK | Comment |
|---|---|---|---|---|---|
| `id` | `INTEGER` | no | — | yes | Primary key |
…
````

## Dialect behaviour

| Backend | Database discovery | Default schema |
|---------|-------------------|----------------|
| PostgreSQL | `pg_database` (non-template) | `public` |
| MySQL / MariaDB | `SHOW DATABASES` | current catalog |
| SQLite | single file DB | n/a |
| Other | current database only | dialect-dependent |

System databases skipped by default:

- PostgreSQL: `postgres`, `template0`, `template1`
- MySQL / MariaDB: `mysql`, `information_schema`, `performance_schema`, `sys`

## Limitations

- Views, materialized views, and sequences are not documented yet (base tables only).
- Mermaid cardinalities are inferred from UNIQUE/PK constraints and FK nullability (junction tables → N–N). Details: [docs/mermaid-cardinalities.md](docs/mermaid-cardinalities.md).
- Under SQLite, `-d` / `--database` does not switch files (one DB per path); a warning is logged.

## Development

```bash
uv sync --all-extras --group dev
uv run ruff check src tests
uv run mypy src
uv run pytest

# Docs
uv sync --group docs
uv run mkdocs serve
```

See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

[MIT](LICENSE) © edwinalkins
