Metadata-Version: 2.4
Name: ildev-mongodb
Version: 0.1.0
Summary: SOLID, extensible MongoDB client for Python using Motor (AsyncCollectionProtocol + RepositoryProtocol TCreate/TUpdate/TOut)
Author: ildev
License: MIT
Project-URL: Repository, https://github.com/ildev/ildev-mongodb
Project-URL: Documentation, https://github.com/ildev/ildev-mongodb#readme
Keywords: mongodb,async,asyncio,motor,database
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: motor>=3.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"

# ildev-mongodb

SOLID, extensible MongoDB client for Python using **Motor**. Dict-based AsyncCollectionProtocol and RepositoryProtocol (TCreate/TUpdate/TOut + to_doc_create, to_doc_update, from_doc_out). Dependency Inversion and DI.

**Requires:** Python ≥3.10, Motor.

## Install

```bash
pip install ildev-mongodb
```

## Layers

1. **AsyncCollectionProtocol** – base protocol, `document: dict[str, Any]`. Full CRUD.
2. **RepositoryProtocol[TCreate, TUpdate, TOut]** – typed CRUD + explicit transforms: `to_doc_create`, `to_doc_update`, `from_doc_out`.
3. **BaseAsyncCollection** – implements AsyncCollectionProtocol (dict-based).
4. **BaseTypedRepository** – implements RepositoryProtocol; wraps AsyncCollectionProtocol and uses the three transforms.

## Quick start (dict-based)

```python
import asyncio
from ildev_mongodb import create_async_client

async def main():
    async with create_async_client("mongodb://localhost:27017/") as client:
        db = client.get_database("mydb")
        coll = db.get_collection("items")
        await coll.insert_one({"name": "test"})
        doc = await coll.find_one({"name": "test"})
        print(doc)

asyncio.run(main())
```

## Quick start (typed TCreate/TUpdate/TOut)

```python
import asyncio
from ildev_mongodb import create_async_client, BaseTypedRepository

class Item:
    def __init__(self, name: str, value: int): ...
    def to_doc(self): ...
    @classmethod
    def from_doc(cls, d: dict): ...

async def main():
    async with create_async_client("mongodb://localhost:27017/") as client:
        raw = client.get_database("mydb").get_collection("items")
        items = BaseTypedRepository(
            raw,
            to_doc_create=lambda x: x.to_doc(),
            to_doc_update=lambda u: u if isinstance(u, dict) else u.to_doc(),
            from_doc_out=Item.from_doc,
        )
        await items.insert_one(Item("x", 1))
        one = await items.find_one({"name": "x"})
        await items.update_one({"name": "x"}, {"$set": {"value": 2}})
        async for doc in items.find():
            print(doc.name, doc.value)

asyncio.run(main())
```

## Full CRUD

**AsyncCollectionProtocol** (dict-based): insert_one, insert_many, find_one, find, update_one, update_many, delete_one, delete_many, count_documents.

**RepositoryProtocol[TCreate, TUpdate, TOut]**: same CRUD with typed payloads; exposes `to_doc_create`, `to_doc_update`, `from_doc_out` and `.collection`.

**BaseTypedRepository** implements RepositoryProtocol by wrapping AsyncCollectionProtocol (e.g. BaseAsyncCollection) and the three transform callables.

## Design (SOLID, DI)

- **AsyncCollectionProtocol** – dict-based collection; BaseAsyncCollection implements it.
- **RepositoryProtocol** – typed repository with explicit doc transforms; BaseTypedRepository implements it.
- **create_async_client()** – DI entry point; yields BaseAsyncClient.

## Direct client construction

```python
from ildev_mongodb import BaseAsyncClient

async def main():
    client = BaseAsyncClient(uri="mongodb://localhost:27017/")
    try:
        db = client.get_database("mydb")
        coll = db.get_collection("items")
        # ...
    finally:
        await client.close()
```

## PyPI

```bash
pip install build twine
python -m build
twine upload dist/*
```

## License

MIT
