Metadata-Version: 2.4
Name: modulith
Version: 0.1.6
Author-email: Panuthep Tasawong <panutheptasawong@gmail.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/modulith-labs/modulith
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi
Requires-Dist: uvicorn
Requires-Dist: requests
Requires-Dist: pydantic
Requires-Dist: keyring
Requires-Dist: typer
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: tqdm; extra == "dev"
Dynamic: license-file

# Modulith  
> Build once. Run everywhere. Scale effortlessly.

**Modulith** lets you focus on your application logic, not deployment infrastructure. Structure your code as modules once, then run them locally and remotely, and scale across instances without touching your code.

## 🚀 What You Get

- 🧱 **Scalable by design** — move from local → distributed seamlessly
- 🔗 **Composable** — build systems by combining modules, local or remote
- 🌐 **Shareable** — publish and reuse modules across projects
- 🔐 **Built-in access control** — rate limits, burst limits, auth tokens

## 📦 Install
```bash
pip install modulith
```

## 🚀 Quick Start
Define a module and call it locally:

```python
# calculator/module.py
from modulith import Modulith

module = Modulith("calculator")

@module.capability("add")
def add(a: float, b: float) -> float:
    return a + b

result = module("add", kwargs={"a": 1, "b": 2}) # → 3
```

Or run it from the CLI:

```bash
modulith run calculator.module add --kwargs '{"a": 1, "b": 2}' # → 3
```

## 🐳 Build and Publish
Package your module as a Docker image and push it to Docker Hub:

```bash
modulith build calculator.module
modulith push <docker-image>
# or
modulith build calculator.module --push
```

Once published, you can serve or deploy your module on any machine, no local source code needed.    


## 🌐 Serve Your Module
Expose your module over the network with access controls:

```bash
# From source
modulith serve \
--source calculator.module \ 
--public \                  # Accessible by anyone
--rate-limit 100 \          # 100 requests/minute
--burst-limit 20            # Allow short bursts

# From Docker Hub
modulith serve \
--image <docker-image> \ 
--public \                  
--rate-limit 100 \          
--burst-limit 20            
```

You'll see:

```
🔑 Your authentication token: ...

🌐 Module 'calculator' is live:
- Repository: user3bef3/calculator
- Public URL: https://6ebm5g.instatunnel.my
- Local URL: http://localhost:8000

⚙️ Capabilities:
- add(a: float, b: float) → float

⚡ Public access limits:
- Rate limit: 100 requests/minute
- Burst limit: 20 requests

🛑 Press Ctrl+C to stop
```

Run your module from any machine:

```python
calculator = Modulith.remote(
    "user3bef3/calculator",
    access_token="..."
)
result = calculator("add", kwargs={"a": 1, "b": 2}) # → 3 (executed remotely)
```
> **Same interface. Local or remote, no difference.**

## ⚖️ Deploy at Scale
Scale horizontally across multiple instances (e.g. AWS Fargate):

```bash
# From source
modulith deploy \
--source calculator.module \
--instances 5 \           
--cpus 2 \                
--memory 1GB \            
--public \                     
--rate-limit 100 \             
--burst-limit 20 \             
--auth-token <your-auth-token> 

# From Docker Hub
modulith deploy \
--image <docker-image> \
--instances 5 \           
--cpus 2 \                
--memory 1GB \            
--public \                     
--rate-limit 100 \             
--burst-limit 20 \             
--auth-token <your-auth-token> 
```
> **Tip:** Use the same `--auth-token` across all instances to group them into the same pool. Different tokens = separate pools.

## 🔗 Compose Modules
Build new modules by calling existing modules, local or remote:

```python
new_module = Modulith()
calculator = Modulith.remote("user3bef3/calculator", access_token="...")

@new_module.capability("double_sum")
def double_sum(a: float, b: float) -> float:
    sum1 = calculator("add", kwargs={"a": a, "b": b})
    sum2 = calculator("add", kwargs={"a": a, "b": b})  # cache hit
    return sum1 + sum2

result = new_module("double_sum", kwargs={"a": 1, "b": 2}) #  → 6
```

Execution flow:

```
double_sum(1, 2)
  → add(1, 2)   [remote]  → 3
  → add(1, 2)   [cache]   → 3
  → 3 + 3                 → 6
```

## 👤 Account (Optional)
Skip manual token management by linking modules to your account:

```bash
modulith signup # Create an account
modulith login
```

Once logged in, your module is automatically registered under your username:

```
🌐 Module 'calculator' is live:
- Repository: <your_username>/calculator
...
```

## CLI Reference

| Command | Description |
|---|---|
| `modulith signup` | Create a new account and get an authentication token |
| `modulith login` | Log in to your account and store the authentication token securely |
| `modulith run` | Run a capability locally |
| `modulith build` | Package module as a Docker image |
| `modulith push` | Push image to Docker Hub |
| `modulith serve` | Serve module on current machine |
| `modulith deploy` | Deploy module on remote machine |
