Metadata-Version: 2.4
Name: urich
Version: 0.1.2
Summary: Async DDD framework for microservices on Starlette
Project-URL: Homepage, https://kashn9sh.github.io/urich
Project-URL: Documentation, https://kashn9sh.github.io/urich
Project-URL: Repository, https://github.com/KashN9sh/urich
Keywords: asgi,ddd,microservices,starlette,cqrs
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: starlette>=0.41.0
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: httpx; extra == "dev"
Requires-Dist: uvicorn; extra == "dev"
Provides-Extra: cli
Requires-Dist: typer>=0.9.0; extra == "cli"
Provides-Extra: docs
Requires-Dist: mkdocs<2,>=1.5; extra == "docs"
Requires-Dist: mkdocs-material>=9.0; extra == "docs"
Requires-Dist: pymdown-extensions; extra == "docs"
Dynamic: license-file

# Urich

Async DDD framework for microservices on Starlette.

**Documentation:** [kashn9sh.github.io/urich](https://kashn9sh.github.io/urich) · **Contributing:** [CONTRIBUTING.md](CONTRIBUTING.md) · **Community & promotion:** [docs/community.md](https://kashn9sh.github.io/urich/community/)

The application is composed from module objects via `app.register(module)` — similar to FastAPI with routers, but one consistent style for domain, events, RPC and discovery.

## Idea

- **One object = one building block:** DomainModule, EventBusModule, OutboxModule, DiscoveryModule, RpcModule. All configured via fluent API and attached with `app.register(module)`.
- **DDD:** Bounded context as DomainModule with `.aggregate()`, `.repository()`, `.command()`, `.query()`, `.on_event()`. Commands and queries get HTTP routes automatically.
- **No lock-in:** Protocols (EventBus, ServiceDiscovery, RpcTransport) in core; implementations (Redis, Consul, HTTP+JSON) supplied by the user or optional out-of-the-box adapters.

## Install

```bash
pip install urich
# CLI for generating skeletons:
pip install "urich[cli]"
```

## Quick start

```python
from urich import Application
from urich.ddd import DomainModule

# One object = full bounded context
from orders.module import orders_module

app = Application()
app.register(orders_module)

# Run: python -m uvicorn main:app --reload  (or: pip install uvicorn && uvicorn main:app --reload)
```

Routes by convention: `POST /orders/commands/create_order`, `GET /orders/queries/get_order`.

## OpenAPI / Swagger

After registering all modules, call `app.openapi(title="My API", version="0.1.0")`. Then:

- **GET /openapi.json** — OpenAPI 3.0 spec
- **GET /docs** — Swagger UI

```python
app = Application()
# ... app.register(module) ...
app.openapi(title="My API", version="0.1.0")
```

## CLI

```bash
urich create-app myapp
cd myapp
urich add-context orders --dir .
urich add-aggregate orders Order --dir .
# In main.py: from orders.module import orders_module; app.register(orders_module)
```

## Module structure (DomainModule)

- **domain** — aggregate (AggregateRoot), domain events (DomainEvent).
- **application** — commands/queries (Command/Query), handlers (one per command/query).
- **infrastructure** — repository interface and implementation (e.g. in-memory for prototypes).
- **module.py** — one object `DomainModule("orders").aggregate(...).repository(...).command(...).query(...).on_event(...)`; register in the app with `app.register(orders_module)`.

## Other modules

- **EventBusModule** — `.adapter(impl)` or `.in_memory()`; in container as EventBus.
- **OutboxModule** — `.storage(...)` and `.publisher(...)`; contracts in core.
- **DiscoveryModule** — `.static({"svc": "http://..."})` or `.adapter(impl)`; ServiceDiscovery protocol.
- **RpcModule** — `.server(path="/rpc")` and `.client(discovery=..., transport=...)`; optional JsonHttpRpcTransport (requires httpx).

Full composition example: `examples/ecommerce/main.py`.
