Metadata-Version: 2.5
Name: jigkit
Version: 0.5.1
Summary: The shared foundations of small self-hosted web apps: settings, database, migrations, logging, health checks and test fixtures
Project-URL: Homepage, https://github.com/jmerhar/jigkit
Project-URL: Changelog, https://github.com/jmerhar/jigkit/blob/main/CHANGELOG.md
Author: Jure Merhar
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.14
Requires-Dist: pydantic-settings>=2.15
Requires-Dist: pydantic>=2.13
Requires-Dist: tzdata>=2026.5
Provides-Extra: auth
Requires-Dist: argon2-cffi>=25.1; extra == 'auth'
Provides-Extra: db
Requires-Dist: aiosqlite>=0.22; extra == 'db'
Requires-Dist: alembic>=1.19; extra == 'db'
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; extra == 'db'
Provides-Extra: dev
Requires-Dist: aiosqlite>=0.22; extra == 'dev'
Requires-Dist: alembic>=1.19; extra == 'dev'
Requires-Dist: apprise>=1.9; extra == 'dev'
Requires-Dist: argon2-cffi>=25.1; extra == 'dev'
Requires-Dist: build>=1.3; extra == 'dev'
Requires-Dist: fastapi<1,>=0.141; extra == 'dev'
Requires-Dist: httpx2>=2.13; extra == 'dev'
Requires-Dist: httpx>=0.28; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.4; extra == 'dev'
Requires-Dist: pytest-cov>=7.1; extra == 'dev'
Requires-Dist: pytest>=9.1; extra == 'dev'
Requires-Dist: ruff>=0.16; extra == 'dev'
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; extra == 'dev'
Requires-Dist: twine>=6.2; extra == 'dev'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'dev'
Provides-Extra: heartbeat
Requires-Dist: httpx2>=2.13; extra == 'heartbeat'
Provides-Extra: influx
Requires-Dist: httpx2>=2.13; extra == 'influx'
Provides-Extra: notify
Requires-Dist: apprise>=1.9; extra == 'notify'
Provides-Extra: postgres
Requires-Dist: aiosqlite>=0.22; extra == 'postgres'
Requires-Dist: alembic>=1.19; extra == 'postgres'
Requires-Dist: asyncpg>=0.30; extra == 'postgres'
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; extra == 'postgres'
Provides-Extra: testing
Requires-Dist: pytest-asyncio>=1.4; extra == 'testing'
Requires-Dist: pytest>=9.1; extra == 'testing'
Provides-Extra: web
Requires-Dist: fastapi<1,>=0.141; extra == 'web'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'web'
Description-Content-Type: text/markdown

# jigkit

The shared foundations of small self-hosted web apps built on FastAPI, async SQLAlchemy and
Svelte: settings, database, migrations, logging, health checks and test fixtures, each hardened
once instead of copied between applications.

```bash
pip install "jigkit[db]"
```

| Module | Extra | What it gives an application |
|---|---|---|
| `jigkit.settings` | — | `AppSettings`: blank environment values mean unset, `X` or `X_FILE` for secrets (never both), a validated `TZ`, a data directory |
| `jigkit.db` | `db` | an async engine with SQLite's pragmas (foreign keys, WAL, busy timeout), a session factory, a commit-or-roll-back `session_scope` |
| `jigkit.models` | `db` | a declarative `Base` with deterministic constraint names, `UtcDateTime`, `TimestampMixin` |
| `jigkit.migrations` | `db` | the whole of an Alembic `env.py`, with foreign keys off during SQLite table rebuilds and checked afterwards |
| `jigkit.logging` | — | stream and rotating file handlers, a level that changes at runtime, credential-carrying HTTP client loggers kept quiet |
| `jigkit.healthcheck` | — | `python -m jigkit.healthcheck URL --expect database=connected`, a container health probe |
| `jigkit.secrets` | — | `load_or_create_secret`, a generated secret kept owner-only in the data directory |
| `jigkit.sinks` | — | `Point` (timestamp with an explicit precision), `Outcome`, the `Sink` protocol, the neutral spooled form |
| `jigkit.spool`, `jigkit.delivery` | — | a bounded on-disk queue per destination, and write-now-or-spool-and-replay |
| `jigkit.influx` | `influx` | InfluxDB 3 and 2.x sinks: line protocol in each batch's precision, and SQL reads from InfluxDB 3 |
| `jigkit.heartbeat` | `heartbeat` | a push-monitor heartbeat after delivered writes, at most once per interval |
| `jigkit.web` | `web` | FastAPI building blocks: write guard, security headers, SPA serving, health router, PWA manifest, `serve()` |
| `jigkit.scheduler` | — | `TickLoop`: in-process work on a fixed tick |
| `jigkit.notify` | `notify` | Apprise delivery off the event loop, and URL redaction for logs |
| `jigkit.ratelimit` | — | `RateLimiter`: a token bucket per client with bounded memory |
| `jigkit.auth` | `auth` | Argon2id passwords, a bounded failed-login throttle, the first-run setup token, the session cookie |
| `jigkit.auth.sessions` | `auth`, `db` | logins in the database as hashed, revocable tokens with a sliding expiry |
| `jigkit.testing` | `testing` | a pytest plugin (`data_dir`, `no_network`), migration checks run through the application's own `env.py`, and a recording stand-in HTTP server |

PostgreSQL is supported through the `postgres` extra. Python 3.14 or newer.

See the [repository](https://github.com/jmerhar/jigkit) for the changelog and documentation.
