somewhere-tech 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- somewhere_tech-0.2.0/LICENSE +21 -0
- somewhere_tech-0.2.0/PKG-INFO +150 -0
- somewhere_tech-0.2.0/README.md +125 -0
- somewhere_tech-0.2.0/pyproject.toml +36 -0
- somewhere_tech-0.2.0/setup.cfg +4 -0
- somewhere_tech-0.2.0/somewhere/__init__.py +168 -0
- somewhere_tech-0.2.0/somewhere/auth.py +210 -0
- somewhere_tech-0.2.0/somewhere/chat.py +297 -0
- somewhere_tech-0.2.0/somewhere/client.py +542 -0
- somewhere_tech-0.2.0/somewhere/emails.py +106 -0
- somewhere_tech-0.2.0/somewhere/errors.py +45 -0
- somewhere_tech-0.2.0/somewhere/query_builder.py +312 -0
- somewhere_tech-0.2.0/somewhere/storage.py +233 -0
- somewhere_tech-0.2.0/somewhere_tech.egg-info/PKG-INFO +150 -0
- somewhere_tech-0.2.0/somewhere_tech.egg-info/SOURCES.txt +17 -0
- somewhere_tech-0.2.0/somewhere_tech.egg-info/dependency_links.txt +1 -0
- somewhere_tech-0.2.0/somewhere_tech.egg-info/requires.txt +1 -0
- somewhere_tech-0.2.0/somewhere_tech.egg-info/top_level.txt +1 -0
- somewhere_tech-0.2.0/tests/test_basic.py +83 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 somewhere.tech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: somewhere-tech
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Official Python SDK for the somewhere.tech platform API. Supabase-compatible interface.
|
|
5
|
+
Author: somewhere.tech
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://somewhere.tech
|
|
8
|
+
Project-URL: Repository, https://github.com/somewhere-tech/somewhere-sdk-python
|
|
9
|
+
Keywords: somewhere,somewhere.tech,backend,sdk,cloudflare,d1,r2,supabase
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Intended Audience :: Developers
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: httpx>=0.24
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# somewhere — Python SDK
|
|
27
|
+
|
|
28
|
+
Official Python SDK for the [somewhere.tech](https://somewhere.tech) platform API. Thin wrapper around the REST API at `https://api.somewhere.tech/v1`.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install somewhere
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick start
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from somewhere import Somewhere, SomewhereError
|
|
40
|
+
|
|
41
|
+
sw = Somewhere(key="smt_...") # or token="eyJ..." for app-user mode
|
|
42
|
+
|
|
43
|
+
# Create a project
|
|
44
|
+
project = sw.projects.create(name="Booking App")
|
|
45
|
+
|
|
46
|
+
# Run a migration
|
|
47
|
+
sw.db.migrate(
|
|
48
|
+
"""
|
|
49
|
+
CREATE TABLE bookings (
|
|
50
|
+
id INTEGER PRIMARY KEY,
|
|
51
|
+
name TEXT NOT NULL,
|
|
52
|
+
slot TEXT NOT NULL,
|
|
53
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
54
|
+
);
|
|
55
|
+
""",
|
|
56
|
+
project["id"],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Insert + query
|
|
60
|
+
sw.db.query(
|
|
61
|
+
"INSERT INTO bookings (name, slot) VALUES (?, ?)",
|
|
62
|
+
["Alice", "2026-05-01 18:00"],
|
|
63
|
+
project["id"],
|
|
64
|
+
)
|
|
65
|
+
rows = sw.db.query("SELECT * FROM bookings", [], project["id"])
|
|
66
|
+
|
|
67
|
+
# Deploy a static site
|
|
68
|
+
sw.deploy(
|
|
69
|
+
files={"index.html": "<h1>Book a table</h1>"},
|
|
70
|
+
project_id=project["id"],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
print(f"Live at https://{project['subdomain']}.somewhere.tech")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Auth modes
|
|
77
|
+
|
|
78
|
+
**Developer mode** — full access, server-side only:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
sw = Somewhere(key="smt_...")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**App-user mode** — app JWT, browser-safe operations only (db, storage, fs, auth.me):
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
sw = Somewhere(token="eyJ...", project_id="booking-app")
|
|
88
|
+
me = sw.auth.me()
|
|
89
|
+
rows = sw.db.query("SELECT * FROM bookings WHERE email = ?", [me["user"]["email"]])
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Default project**:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
sw = Somewhere(key="smt_...", project_id="booking-app")
|
|
96
|
+
sw.db.query("SELECT * FROM bookings") # uses 'booking-app'
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Error handling
|
|
100
|
+
|
|
101
|
+
Every API error raises a typed `SomewhereError`:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from somewhere import SomewhereError
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
sw.email.send(to="user@example.com", subject="Hi", text="Welcome")
|
|
108
|
+
except SomewhereError as err:
|
|
109
|
+
print(err.code) # "QUOTA_EXCEEDED"
|
|
110
|
+
print(err.message) # human-readable
|
|
111
|
+
print(err.status_code) # 429
|
|
112
|
+
print(err.retry) # True if client should retry
|
|
113
|
+
print(err.retry_after_ms) # ms to wait
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Method reference
|
|
117
|
+
|
|
118
|
+
| Namespace | Methods |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `sw.projects` | `create`, `list`, `get`, `delete`, `undeploy`, `archive`, `unarchive`, `rename`, `deploys` |
|
|
121
|
+
| `sw.deploy` | `sw.deploy(files=..., functions=..., project_id=...)`, `sw.deploy.status(project_id)` |
|
|
122
|
+
| `sw.promote` | `sw.promote(project_id)`, `sw.promote.rollback(project_id)` |
|
|
123
|
+
| `sw.db` | `query`, `migrate`, `tables`, `schema` |
|
|
124
|
+
| `sw.storage` | `put`, `get`, `delete`, `list` |
|
|
125
|
+
| `sw.fs` | `write`, `read`, `delete`, `move`, `copy`, `stat`, `versions`, `restore` |
|
|
126
|
+
| `sw.auth` | `signup`, `login`, `logout`, `me`, `forgot`, `reset`, `users`, `verify_email`, `request_verification`, `delete_account`, `update_me` |
|
|
127
|
+
| `sw.email` | `send` |
|
|
128
|
+
| `sw.ai` | `complete`, `embed`*, `image`*, `tts`*, `transcribe`* |
|
|
129
|
+
| `sw.jobs` | `create`, `status`, `list`, `cancel`, `progress` |
|
|
130
|
+
| `sw.cron` | `create`, `list`, `update`, `delete` |
|
|
131
|
+
| `sw.queue` | `push` |
|
|
132
|
+
| `sw.logs` | `write`, `read` |
|
|
133
|
+
| `sw.env` | `set`, `list`, `delete` |
|
|
134
|
+
| `sw.domains` | `add`, `verify`, `list`, `delete` |
|
|
135
|
+
| `sw.preview` | `invite`, `revoke`, `viewers` |
|
|
136
|
+
| `sw.feedback` | `submit`, `list` |
|
|
137
|
+
| `sw.billing` | `status`, `checkout`, `portal` |
|
|
138
|
+
| `sw.usage` | `get`, `summary` |
|
|
139
|
+
|
|
140
|
+
`*` = stub for not-yet-shipped endpoints; calling returns `UNSUPPORTED_FEATURE`.
|
|
141
|
+
|
|
142
|
+
## Test
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
SMT_KEY=smt_... python tests/test_basic.py
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT © somewhere.tech
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# somewhere — Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for the [somewhere.tech](https://somewhere.tech) platform API. Thin wrapper around the REST API at `https://api.somewhere.tech/v1`.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install somewhere
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from somewhere import Somewhere, SomewhereError
|
|
15
|
+
|
|
16
|
+
sw = Somewhere(key="smt_...") # or token="eyJ..." for app-user mode
|
|
17
|
+
|
|
18
|
+
# Create a project
|
|
19
|
+
project = sw.projects.create(name="Booking App")
|
|
20
|
+
|
|
21
|
+
# Run a migration
|
|
22
|
+
sw.db.migrate(
|
|
23
|
+
"""
|
|
24
|
+
CREATE TABLE bookings (
|
|
25
|
+
id INTEGER PRIMARY KEY,
|
|
26
|
+
name TEXT NOT NULL,
|
|
27
|
+
slot TEXT NOT NULL,
|
|
28
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
29
|
+
);
|
|
30
|
+
""",
|
|
31
|
+
project["id"],
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Insert + query
|
|
35
|
+
sw.db.query(
|
|
36
|
+
"INSERT INTO bookings (name, slot) VALUES (?, ?)",
|
|
37
|
+
["Alice", "2026-05-01 18:00"],
|
|
38
|
+
project["id"],
|
|
39
|
+
)
|
|
40
|
+
rows = sw.db.query("SELECT * FROM bookings", [], project["id"])
|
|
41
|
+
|
|
42
|
+
# Deploy a static site
|
|
43
|
+
sw.deploy(
|
|
44
|
+
files={"index.html": "<h1>Book a table</h1>"},
|
|
45
|
+
project_id=project["id"],
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
print(f"Live at https://{project['subdomain']}.somewhere.tech")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Auth modes
|
|
52
|
+
|
|
53
|
+
**Developer mode** — full access, server-side only:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
sw = Somewhere(key="smt_...")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**App-user mode** — app JWT, browser-safe operations only (db, storage, fs, auth.me):
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
sw = Somewhere(token="eyJ...", project_id="booking-app")
|
|
63
|
+
me = sw.auth.me()
|
|
64
|
+
rows = sw.db.query("SELECT * FROM bookings WHERE email = ?", [me["user"]["email"]])
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Default project**:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
sw = Somewhere(key="smt_...", project_id="booking-app")
|
|
71
|
+
sw.db.query("SELECT * FROM bookings") # uses 'booking-app'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Error handling
|
|
75
|
+
|
|
76
|
+
Every API error raises a typed `SomewhereError`:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from somewhere import SomewhereError
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
sw.email.send(to="user@example.com", subject="Hi", text="Welcome")
|
|
83
|
+
except SomewhereError as err:
|
|
84
|
+
print(err.code) # "QUOTA_EXCEEDED"
|
|
85
|
+
print(err.message) # human-readable
|
|
86
|
+
print(err.status_code) # 429
|
|
87
|
+
print(err.retry) # True if client should retry
|
|
88
|
+
print(err.retry_after_ms) # ms to wait
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Method reference
|
|
92
|
+
|
|
93
|
+
| Namespace | Methods |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `sw.projects` | `create`, `list`, `get`, `delete`, `undeploy`, `archive`, `unarchive`, `rename`, `deploys` |
|
|
96
|
+
| `sw.deploy` | `sw.deploy(files=..., functions=..., project_id=...)`, `sw.deploy.status(project_id)` |
|
|
97
|
+
| `sw.promote` | `sw.promote(project_id)`, `sw.promote.rollback(project_id)` |
|
|
98
|
+
| `sw.db` | `query`, `migrate`, `tables`, `schema` |
|
|
99
|
+
| `sw.storage` | `put`, `get`, `delete`, `list` |
|
|
100
|
+
| `sw.fs` | `write`, `read`, `delete`, `move`, `copy`, `stat`, `versions`, `restore` |
|
|
101
|
+
| `sw.auth` | `signup`, `login`, `logout`, `me`, `forgot`, `reset`, `users`, `verify_email`, `request_verification`, `delete_account`, `update_me` |
|
|
102
|
+
| `sw.email` | `send` |
|
|
103
|
+
| `sw.ai` | `complete`, `embed`*, `image`*, `tts`*, `transcribe`* |
|
|
104
|
+
| `sw.jobs` | `create`, `status`, `list`, `cancel`, `progress` |
|
|
105
|
+
| `sw.cron` | `create`, `list`, `update`, `delete` |
|
|
106
|
+
| `sw.queue` | `push` |
|
|
107
|
+
| `sw.logs` | `write`, `read` |
|
|
108
|
+
| `sw.env` | `set`, `list`, `delete` |
|
|
109
|
+
| `sw.domains` | `add`, `verify`, `list`, `delete` |
|
|
110
|
+
| `sw.preview` | `invite`, `revoke`, `viewers` |
|
|
111
|
+
| `sw.feedback` | `submit`, `list` |
|
|
112
|
+
| `sw.billing` | `status`, `checkout`, `portal` |
|
|
113
|
+
| `sw.usage` | `get`, `summary` |
|
|
114
|
+
|
|
115
|
+
`*` = stub for not-yet-shipped endpoints; calling returns `UNSUPPORTED_FEATURE`.
|
|
116
|
+
|
|
117
|
+
## Test
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
SMT_KEY=smt_... python tests/test_basic.py
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT © somewhere.tech
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "somewhere-tech"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Official Python SDK for the somewhere.tech platform API. Supabase-compatible interface."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "somewhere.tech" }]
|
|
12
|
+
keywords = ["somewhere", "somewhere.tech", "backend", "sdk", "cloudflare", "d1", "r2", "supabase"]
|
|
13
|
+
requires-python = ">=3.8"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Programming Language :: Python :: 3.8",
|
|
19
|
+
"Programming Language :: Python :: 3.9",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"httpx>=0.24",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://somewhere.tech"
|
|
32
|
+
Repository = "https://github.com/somewhere-tech/somewhere-sdk-python"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
include = ["somewhere*"]
|
|
36
|
+
exclude = ["tests*"]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""Official Python SDK for the somewhere.tech platform API.
|
|
2
|
+
|
|
3
|
+
Supabase-compatible interface with query builder, auth, storage, email,
|
|
4
|
+
and OpenAI-compatible chat completions.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from somewhere import Somewhere
|
|
8
|
+
|
|
9
|
+
sw = Somewhere(key='smt_...', project_id='my-project')
|
|
10
|
+
|
|
11
|
+
# Database (Supabase-style query builder)
|
|
12
|
+
result = sw.from_('users').select('*').eq('role', 'admin').execute()
|
|
13
|
+
|
|
14
|
+
# Auth
|
|
15
|
+
result = sw.auth.sign_up(email='u@test.com', password='pass123')
|
|
16
|
+
|
|
17
|
+
# Storage
|
|
18
|
+
result = sw.storage.from_('avatars').upload('photo.png', file_bytes)
|
|
19
|
+
|
|
20
|
+
# Email
|
|
21
|
+
result = sw.emails.send(to='user@test.com', subject='Hi', html='<h1>Hello</h1>')
|
|
22
|
+
|
|
23
|
+
# AI (OpenAI-compatible)
|
|
24
|
+
completion = sw.chat.completions.create(model='claude-sonnet-4-6', messages=[...])
|
|
25
|
+
"""
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
from typing import Dict, Optional
|
|
29
|
+
|
|
30
|
+
import httpx
|
|
31
|
+
|
|
32
|
+
from .auth import AuthClient
|
|
33
|
+
from .chat import ChatClient
|
|
34
|
+
from .client import (
|
|
35
|
+
BillingClient,
|
|
36
|
+
CronClient,
|
|
37
|
+
DeployClient,
|
|
38
|
+
DomainsClient,
|
|
39
|
+
EnvClient,
|
|
40
|
+
FeedbackClient,
|
|
41
|
+
HttpClient,
|
|
42
|
+
JobsClient,
|
|
43
|
+
LogsClient,
|
|
44
|
+
PreviewClient,
|
|
45
|
+
ProjectsClient,
|
|
46
|
+
QueueClient,
|
|
47
|
+
UsageClient,
|
|
48
|
+
)
|
|
49
|
+
from .emails import EmailsClient
|
|
50
|
+
from .errors import SomewhereError
|
|
51
|
+
from .query_builder import QueryBuilder, Result
|
|
52
|
+
from .storage import StorageClient
|
|
53
|
+
|
|
54
|
+
__all__ = ["Somewhere", "SomewhereError", "Result"]
|
|
55
|
+
__version__ = "0.2.0"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Somewhere:
|
|
59
|
+
"""Entry point for the somewhere.tech SDK.
|
|
60
|
+
|
|
61
|
+
Provides a Supabase-compatible interface with query builder, auth,
|
|
62
|
+
storage, email, and OpenAI-compatible chat completions.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
key: Developer API key (smt_...). Mutually exclusive with token.
|
|
66
|
+
token: App-user JWT. Mutually exclusive with key.
|
|
67
|
+
project_id: Default project ID for all operations.
|
|
68
|
+
base_url: API base URL (defaults to https://api.somewhere.tech/v1).
|
|
69
|
+
http_client: Custom httpx.Client instance (optional).
|
|
70
|
+
headers: Extra headers to send with every request (optional).
|
|
71
|
+
timeout: Request timeout in seconds (default 60).
|
|
72
|
+
|
|
73
|
+
Example:
|
|
74
|
+
sw = Somewhere(key='smt_...', project_id='booking-app')
|
|
75
|
+
result = sw.from_('users').select('*').eq('role', 'admin').execute()
|
|
76
|
+
print(result.data)
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
*,
|
|
82
|
+
key: Optional[str] = None,
|
|
83
|
+
token: Optional[str] = None,
|
|
84
|
+
project_id: Optional[str] = None,
|
|
85
|
+
base_url: str = "https://api.somewhere.tech/v1",
|
|
86
|
+
http_client: Optional[httpx.Client] = None,
|
|
87
|
+
headers: Optional[Dict[str, str]] = None,
|
|
88
|
+
timeout: float = 60.0,
|
|
89
|
+
) -> None:
|
|
90
|
+
self._http = HttpClient(
|
|
91
|
+
key=key,
|
|
92
|
+
token=token,
|
|
93
|
+
project_id=project_id,
|
|
94
|
+
base_url=base_url,
|
|
95
|
+
http_client=http_client,
|
|
96
|
+
headers=headers,
|
|
97
|
+
timeout=timeout,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Supabase-compatible clients
|
|
101
|
+
self.auth = AuthClient(
|
|
102
|
+
project_id=self._http.project_id,
|
|
103
|
+
http_client=self._http.client,
|
|
104
|
+
base_url=self._http.base_url,
|
|
105
|
+
auth_header=self._http.auth_header,
|
|
106
|
+
extra_headers=self._http.extra_headers,
|
|
107
|
+
)
|
|
108
|
+
self.storage = StorageClient(
|
|
109
|
+
project_id=self._http.project_id,
|
|
110
|
+
http_client=self._http.client,
|
|
111
|
+
base_url=self._http.base_url,
|
|
112
|
+
auth_header=self._http.auth_header,
|
|
113
|
+
extra_headers=self._http.extra_headers,
|
|
114
|
+
)
|
|
115
|
+
self.emails = EmailsClient(
|
|
116
|
+
project_id=self._http.project_id,
|
|
117
|
+
http_client=self._http.client,
|
|
118
|
+
base_url=self._http.base_url,
|
|
119
|
+
auth_header=self._http.auth_header,
|
|
120
|
+
extra_headers=self._http.extra_headers,
|
|
121
|
+
)
|
|
122
|
+
self.chat = ChatClient(
|
|
123
|
+
project_id=self._http.project_id,
|
|
124
|
+
http_client=self._http.client,
|
|
125
|
+
base_url=self._http.base_url,
|
|
126
|
+
auth_header=self._http.auth_header,
|
|
127
|
+
extra_headers=self._http.extra_headers,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Simple resource clients
|
|
131
|
+
self.env = EnvClient(self._http)
|
|
132
|
+
self.jobs = JobsClient(self._http)
|
|
133
|
+
self.cron = CronClient(self._http)
|
|
134
|
+
self.domains = DomainsClient(self._http)
|
|
135
|
+
self.projects = ProjectsClient(self._http)
|
|
136
|
+
self.deploy = DeployClient(self._http)
|
|
137
|
+
self.logs = LogsClient(self._http)
|
|
138
|
+
self.queue = QueueClient(self._http)
|
|
139
|
+
self.billing = BillingClient(self._http)
|
|
140
|
+
self.usage = UsageClient(self._http)
|
|
141
|
+
self.feedback = FeedbackClient(self._http)
|
|
142
|
+
self.preview = PreviewClient(self._http)
|
|
143
|
+
|
|
144
|
+
def from_(self, table: str) -> QueryBuilder:
|
|
145
|
+
"""Start a Supabase-style query builder for the given table.
|
|
146
|
+
|
|
147
|
+
Uses `from_` because `from` is a reserved word in Python.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
table: The database table name.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
A QueryBuilder that supports .select(), .insert(), .update(),
|
|
154
|
+
.delete(), .upsert(), plus filter chains (.eq(), .gt(), etc.)
|
|
155
|
+
ending with .execute().
|
|
156
|
+
|
|
157
|
+
Example:
|
|
158
|
+
result = sw.from_('users').select('*').eq('role', 'admin').execute()
|
|
159
|
+
result = sw.from_('users').insert({'name': 'A'}).execute()
|
|
160
|
+
"""
|
|
161
|
+
return QueryBuilder(
|
|
162
|
+
table=table,
|
|
163
|
+
project_id=self._http.project_id,
|
|
164
|
+
http_client=self._http.client,
|
|
165
|
+
base_url=self._http.base_url,
|
|
166
|
+
auth_header=self._http.auth_header,
|
|
167
|
+
extra_headers=self._http.extra_headers,
|
|
168
|
+
)
|