Metadata-Version: 2.4
Name: somewhere-tech
Version: 0.2.0
Summary: Official Python SDK for the somewhere.tech platform API. Supabase-compatible interface.
Author: somewhere.tech
License: MIT
Project-URL: Homepage, https://somewhere.tech
Project-URL: Repository, https://github.com/somewhere-tech/somewhere-sdk-python
Keywords: somewhere,somewhere.tech,backend,sdk,cloudflare,d1,r2,supabase
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
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: Intended Audience :: Developers
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24
Dynamic: license-file

# somewhere — Python SDK

Official Python SDK for the [somewhere.tech](https://somewhere.tech) platform API. Thin wrapper around the REST API at `https://api.somewhere.tech/v1`.

## Install

```bash
pip install somewhere
```

## Quick start

```python
from somewhere import Somewhere, SomewhereError

sw = Somewhere(key="smt_...")  # or token="eyJ..." for app-user mode

# Create a project
project = sw.projects.create(name="Booking App")

# Run a migration
sw.db.migrate(
    """
    CREATE TABLE bookings (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        slot TEXT NOT NULL,
        created_at TEXT DEFAULT (datetime('now'))
    );
    """,
    project["id"],
)

# Insert + query
sw.db.query(
    "INSERT INTO bookings (name, slot) VALUES (?, ?)",
    ["Alice", "2026-05-01 18:00"],
    project["id"],
)
rows = sw.db.query("SELECT * FROM bookings", [], project["id"])

# Deploy a static site
sw.deploy(
    files={"index.html": "<h1>Book a table</h1>"},
    project_id=project["id"],
)

print(f"Live at https://{project['subdomain']}.somewhere.tech")
```

## Auth modes

**Developer mode** — full access, server-side only:

```python
sw = Somewhere(key="smt_...")
```

**App-user mode** — app JWT, browser-safe operations only (db, storage, fs, auth.me):

```python
sw = Somewhere(token="eyJ...", project_id="booking-app")
me = sw.auth.me()
rows = sw.db.query("SELECT * FROM bookings WHERE email = ?", [me["user"]["email"]])
```

**Default project**:

```python
sw = Somewhere(key="smt_...", project_id="booking-app")
sw.db.query("SELECT * FROM bookings")  # uses 'booking-app'
```

## Error handling

Every API error raises a typed `SomewhereError`:

```python
from somewhere import SomewhereError

try:
    sw.email.send(to="user@example.com", subject="Hi", text="Welcome")
except SomewhereError as err:
    print(err.code)           # "QUOTA_EXCEEDED"
    print(err.message)        # human-readable
    print(err.status_code)    # 429
    print(err.retry)          # True if client should retry
    print(err.retry_after_ms) # ms to wait
```

## Method reference

| Namespace | Methods |
|---|---|
| `sw.projects` | `create`, `list`, `get`, `delete`, `undeploy`, `archive`, `unarchive`, `rename`, `deploys` |
| `sw.deploy` | `sw.deploy(files=..., functions=..., project_id=...)`, `sw.deploy.status(project_id)` |
| `sw.promote` | `sw.promote(project_id)`, `sw.promote.rollback(project_id)` |
| `sw.db` | `query`, `migrate`, `tables`, `schema` |
| `sw.storage` | `put`, `get`, `delete`, `list` |
| `sw.fs` | `write`, `read`, `delete`, `move`, `copy`, `stat`, `versions`, `restore` |
| `sw.auth` | `signup`, `login`, `logout`, `me`, `forgot`, `reset`, `users`, `verify_email`, `request_verification`, `delete_account`, `update_me` |
| `sw.email` | `send` |
| `sw.ai` | `complete`, `embed`*, `image`*, `tts`*, `transcribe`* |
| `sw.jobs` | `create`, `status`, `list`, `cancel`, `progress` |
| `sw.cron` | `create`, `list`, `update`, `delete` |
| `sw.queue` | `push` |
| `sw.logs` | `write`, `read` |
| `sw.env` | `set`, `list`, `delete` |
| `sw.domains` | `add`, `verify`, `list`, `delete` |
| `sw.preview` | `invite`, `revoke`, `viewers` |
| `sw.feedback` | `submit`, `list` |
| `sw.billing` | `status`, `checkout`, `portal` |
| `sw.usage` | `get`, `summary` |

`*` = stub for not-yet-shipped endpoints; calling returns `UNSUPPORTED_FEATURE`.

## Test

```bash
SMT_KEY=smt_... python tests/test_basic.py
```

## License

MIT © somewhere.tech
