Metadata-Version: 2.5
Name: xlambda-postgres
Version: 0.2.0
Summary: xlambda managed PostgreSQL SDK: provisioning, sub-users, backups, and a get_pool() convenience.
Project-URL: Homepage, https://xlambda.tech
Project-URL: Source, https://github.com/randyryan177-cloud/media-server/tree/main/packages-python/postgres
Author: xlambda
License-Expression: MIT
Keywords: database,postgres,postgresql,sdk,xlambda
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.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: Topic :: Database
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: xlambda-core==0.2.0
Provides-Extra: pool
Requires-Dist: psycopg-pool>=3.2; extra == 'pool'
Requires-Dist: psycopg[binary]>=3.1; extra == 'pool'
Description-Content-Type: text/markdown

# xlambda-postgres

Managed PostgreSQL: provisioning, sub-users, backups, and a `get_pool()`
convenience.

```
pip install xlambda-postgres          # provisioning only
pip install "xlambda-postgres[pool]"  # plus psycopg, for get_pool()
```

Python port of [`@xlambda-tech/postgres`](../../packages/postgres).

## Provisioning

```python
from xlambda.postgres import PostgresClient

client = PostgresClient(api_key=os.environ["XLAMBDA_API_KEY"])

db = client.databases.create(project_id="proj_123", name="app", tier="starter")
db["connectionString"]   # shown here and on rotate/reveal only
```

`create()`, `rotate_password()`, and `reveal_connection()` return a
`DatabaseHandle` — a plain `dict` subclass, so every response field reads
normally, with pool constructors added on top:

```python
pool = db.get_pool()                  # port 6432, PgBouncer transaction pooling
migrations = db.get_session_pool()    # port 6433, direct session

async_pool = db.get_async_pool()      # psycopg_pool.AsyncConnectionPool
```

**Which port matters.** 6432 is transaction-pooled and is what steady-state
app traffic should use; its connection string carries `?pgbouncer=true`,
which disables client-side prepared statements because transaction pooling
breaks them. Use 6433 for migrations, DDL, advisory locks, and anything else
needing a real session.

`reveal_connection()` discloses the *current* password rather than changing
it. It 404s for instances that predate the feature or were created without
`CONSOLE_CREDENTIAL_ENCRYPTION_KEY` configured — rotate to recover in that
case.

## Sub-users and backups

```python
user = client.databases.users(db["id"]).create(permission="readonly", expires_at="2027-01-01T00:00:00Z")
user["password"]     # shown once

backups = client.databases.backups(db["id"])
backups.create()
backups.restore("bkp_123")   # overwrites all current data; cannot be undone
```

## What this doesn't wrap

The dashboard's own SQL console. Running queries isn't something the REST API
mediates — there's no app-facing `/v1/databases/:id/query` route — so once a
database is provisioned you talk to it with psycopg through the handle above.
`get_pool()` is a thin ergonomic wrapper around `psycopg_pool`, not a
reimplementation of it, and psycopg stays an optional extra so provisioning-only
callers don't install a driver they never use.

## Async

```python
from xlambda.postgres import AsyncPostgresClient

async with AsyncPostgresClient(api_key=...) as client:
    db = await client.databases.create(project_id="proj_123", name="app")
```

## Conventions

Arguments are snake_case; responses are the API's own camelCase, returned as
plain dicts typed by `TypedDict`. Byte counts that are bigints server-side
(`storageQuotaBytes`, `storageBytes`, backup `sizeBytes`) arrive as strings
rather than losing precision in JSON. See
[xlambda-core](../core#conventions).
