Metadata-Version: 2.4
Name: sqlite-callback-store
Version: 0.0.4
Summary: Typed callback transactions and exception-free SQLite storage
Author-email: Veya Fürst <ghgstefan@gmail.com>
License-Expression: MIT
Project-URL: PyPI, https://pypi.org/project/sqlite-callback-store/
Project-URL: Repository, https://github.com/0xveya/sqlite-callback-store
Project-URL: Issues, https://github.com/0xveya/sqlite-callback-store/issues
Keywords: sqlite,database,transactions,result
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Database
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typed-errs<1,>=0
Dynamic: license-file

# sqlite-callback-store

[![PyPI](https://img.shields.io/pypi/v/sqlite-callback-store)](https://pypi.org/project/sqlite-callback-store/)
[![CI](https://github.com/0xveya/sqlite-callback-store/actions/workflows/ci.yml/badge.svg)](https://github.com/0xveya/sqlite-callback-store/actions/workflows/ci.yml)

**[View sqlite-callback-store on PyPI](https://pypi.org/project/sqlite-callback-store/)**

Short-lived SQLite connections wrapped in typed read and transaction callbacks.
An `Ok` commits, an `Err` rolls back, and database exceptions become
`StorageError` results.

```bash
uv add sqlite-callback-store
```

## Example

```python
from sqlite_callback_store import SQLiteStore, Transaction
from typed_errs import Ok

store = SQLiteStore("data/app.db")
store.initialize("CREATE TABLE IF NOT EXISTS notes (body TEXT NOT NULL)")


def insert(tx: Transaction):
    tx.conn.execute("INSERT INTO notes(body) VALUES (?)", ("hello",))
    return Ok(None)


store.transaction(insert)
rows = store.read(lambda conn: Ok(conn.execute("SELECT * FROM notes").fetchall()))
```

Applications keep their domain-specific typed query classes; this library owns
connection setup, pragmas, commit/rollback, directory creation, and error
conversion.

## Adding your own store methods

Subclass `SQLiteStore` and add methods named for your domain. Write methods call
`self.transaction(callback)`: returning `Ok` commits and returning `Err` rolls
back. Read methods call `self.read(callback)` and receive a short-lived
`sqlite3.Connection` configured to produce `sqlite3.Row` values. You may also
override `initialize()` to supply your schema by default while delegating to
`super().initialize(schema)`.

See the complete [typed notes store](examples/typed_notes_store.py). It defines
a `Note` model and a `NotesStore` with `initialize`, `add`, and `all` methods,
while the base library continues to own connections, pragmas, commits,
rollbacks, and error conversion.

## Where I use it

This is my internal SQLite foundation for 42 projects. It was extracted from
[RAG Against the Machine](https://github.com/0xveya/42-rag-against-the-machine),
where it manages the source/chunk index, FTS queries, short-lived read
connections, WAL configuration, and atomic indexing transactions. The
RAG-specific schema and query models stay in RAG; this package contains only
the reusable callback transaction layer.

## Dependencies

- Python 3.10+ and its standard-library `sqlite3`
- `typed-errs`

## Use and contributions

This is a personal library, but it is not private or locked to my projects.
You may use it in general Python work and in 42 projects under the MIT license;
just follow the rules that apply to your campus and assignment.

Contributions are welcome: open an issue or send a pull request. I do not care
whether a contribution is written by hand, AI-assisted, or generated another
way; I care about whether it is correct, tested, understandable, and a good fit.
Because this is opinionated personal infrastructure, pull requests are reviewed
selectively and are likely to be rejected unless they clearly improve the
library without making it harder to maintain.

## Development and release

Run `mise run check`. Every push to `master` publishes a unique `0.0.<CI run>` ZeroVer
version through PyPI Trusted Publishing. `mise run publish` remains available.
