edgebase-admin 0.1.3__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.
- edgebase_admin-0.1.3/.gitignore +11 -0
- edgebase_admin-0.1.3/LICENSE +21 -0
- edgebase_admin-0.1.3/PKG-INFO +128 -0
- edgebase_admin-0.1.3/README.md +117 -0
- edgebase_admin-0.1.3/llms.txt +170 -0
- edgebase_admin-0.1.3/pyproject.toml +24 -0
- edgebase_admin-0.1.3/src/edgebase_admin/__init__.py +23 -0
- edgebase_admin-0.1.3/src/edgebase_admin/admin_auth.py +137 -0
- edgebase_admin-0.1.3/src/edgebase_admin/admin_client.py +165 -0
- edgebase_admin-0.1.3/src/edgebase_admin/analytics.py +142 -0
- edgebase_admin-0.1.3/src/edgebase_admin/d1.py +47 -0
- edgebase_admin-0.1.3/src/edgebase_admin/functions.py +50 -0
- edgebase_admin-0.1.3/src/edgebase_admin/generated/admin_api_core.py +409 -0
- edgebase_admin-0.1.3/src/edgebase_admin/kv.py +59 -0
- edgebase_admin-0.1.3/src/edgebase_admin/push.py +63 -0
- edgebase_admin-0.1.3/src/edgebase_admin/vectorize.py +161 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 melodysdreamj
|
|
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,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: edgebase-admin
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Python admin SDK for EdgeBase service-key workloads
|
|
5
|
+
Author: EdgeBase Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: edgebase-core<0.2.0,>=0.1.3
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# edgebase-admin
|
|
13
|
+
|
|
14
|
+
Server-only Python admin SDK for EdgeBase.
|
|
15
|
+
|
|
16
|
+
Use `edgebase-admin` from trusted environments that hold a Service Key, such as backend APIs, cron jobs, workers, and operational tooling. It exposes admin auth, service-key database access, storage management, raw SQL, functions, analytics, push, and native Cloudflare resources.
|
|
17
|
+
|
|
18
|
+
If you want the unified package that also includes the higher-level `EdgeBaseServer` entry point and room helpers, install [`edgebase`](https://pypi.org/project/edgebase/) instead.
|
|
19
|
+
|
|
20
|
+
## Documentation Map
|
|
21
|
+
|
|
22
|
+
Use this README for the fast overview, then jump into the docs when you need depth:
|
|
23
|
+
|
|
24
|
+
- [SDK Overview](https://edgebase.fun/docs/sdks)
|
|
25
|
+
Install commands and language matrix for all public SDKs
|
|
26
|
+
- [Admin SDK](https://edgebase.fun/docs/sdks/client-vs-server)
|
|
27
|
+
Service-key concepts, trust boundaries, and admin-only capabilities
|
|
28
|
+
- [Admin SDK Reference](https://edgebase.fun/docs/admin-sdk/reference)
|
|
29
|
+
Cross-language auth, database, storage, functions, and push examples
|
|
30
|
+
- [Admin User Management](https://edgebase.fun/docs/authentication/admin-users)
|
|
31
|
+
Create, update, delete, and manage users with the Service Key
|
|
32
|
+
- [Database Admin SDK](https://edgebase.fun/docs/database/admin-sdk)
|
|
33
|
+
Table queries, filters, pagination, batch writes, and raw SQL
|
|
34
|
+
- [Storage](https://edgebase.fun/docs/storage/upload-download)
|
|
35
|
+
Uploads, downloads, metadata, and signed URLs
|
|
36
|
+
- [Analytics Admin SDK](https://edgebase.fun/docs/analytics/admin-sdk)
|
|
37
|
+
Request metrics, event tracking, and event queries
|
|
38
|
+
- [Push Admin SDK](https://edgebase.fun/docs/push/admin-sdk)
|
|
39
|
+
Push send, topic broadcast, token inspection, and logs
|
|
40
|
+
- [Native Resources](https://edgebase.fun/docs/server/native-resources)
|
|
41
|
+
KV, D1, Vectorize, and other edge-native resources
|
|
42
|
+
|
|
43
|
+
## For AI Coding Assistants
|
|
44
|
+
|
|
45
|
+
This package includes an `llms.txt` file for AI-assisted development.
|
|
46
|
+
|
|
47
|
+
Use it when you want an agent or code assistant to:
|
|
48
|
+
|
|
49
|
+
- use the right Python admin method signatures
|
|
50
|
+
- remember which surfaces are properties vs methods
|
|
51
|
+
- avoid copying JavaScript or Go API shapes into Python
|
|
52
|
+
- choose `edgebase-admin` instead of the broader `edgebase` package when only admin features are needed
|
|
53
|
+
|
|
54
|
+
You can find it:
|
|
55
|
+
|
|
56
|
+
- in this repository: [llms.txt](https://github.com/edge-base/edgebase/blob/main/packages/sdk/python/packages/admin/llms.txt)
|
|
57
|
+
- in your environment after install, inside the `edgebase_admin` package directory as `llms.txt`
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install edgebase-admin
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import os
|
|
69
|
+
|
|
70
|
+
from edgebase_admin import create_admin_client
|
|
71
|
+
|
|
72
|
+
admin = create_admin_client(
|
|
73
|
+
"https://your-project.edgebase.fun",
|
|
74
|
+
service_key=os.environ["EDGEBASE_SERVICE_KEY"],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
users = admin.admin_auth.list_users(limit=20)
|
|
78
|
+
|
|
79
|
+
posts = (
|
|
80
|
+
admin.db("shared")
|
|
81
|
+
.table("posts")
|
|
82
|
+
.where("published", "==", True)
|
|
83
|
+
.order_by("createdAt", "desc")
|
|
84
|
+
.limit(10)
|
|
85
|
+
.get_list()
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
rows = admin.sql(
|
|
89
|
+
"shared",
|
|
90
|
+
None,
|
|
91
|
+
"SELECT COUNT(*) AS total FROM posts WHERE published = ?",
|
|
92
|
+
[1],
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
bucket = admin.storage().bucket("avatars")
|
|
96
|
+
signed = bucket.create_signed_url("user-1.jpg", expires_in="1h")
|
|
97
|
+
|
|
98
|
+
print(len(users.get("users", [])), len(posts.items), rows, signed.url)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Core API
|
|
102
|
+
|
|
103
|
+
- `AdminClient(base_url, service_key=...)`
|
|
104
|
+
Main admin entry point
|
|
105
|
+
- `create_admin_client(base_url, service_key=...)`
|
|
106
|
+
Convenience helper matching the public docs
|
|
107
|
+
- `admin.admin_auth`
|
|
108
|
+
Admin user management
|
|
109
|
+
- `admin.db(namespace="shared", instance_id=None).table(name)`
|
|
110
|
+
Service-key database access
|
|
111
|
+
- `admin.storage()`
|
|
112
|
+
Storage bucket access
|
|
113
|
+
- `admin.sql(namespace="shared", instance_id=None, query="", params=None)`
|
|
114
|
+
Raw SQL
|
|
115
|
+
- `admin.functions()`
|
|
116
|
+
Call app functions from trusted code
|
|
117
|
+
- `admin.analytics()`
|
|
118
|
+
Query request metrics and track custom events
|
|
119
|
+
- `admin.push()`
|
|
120
|
+
Send push notifications and inspect logs
|
|
121
|
+
- `admin.kv(namespace)`, `admin.d1(database)`, `admin.vector(index)` / `admin.vectorize(index)`
|
|
122
|
+
Native Cloudflare resources
|
|
123
|
+
|
|
124
|
+
## Requirements
|
|
125
|
+
|
|
126
|
+
- Python `3.10+`
|
|
127
|
+
- `edgebase-core>=0.1.3,<0.2.0`
|
|
128
|
+
- A valid EdgeBase Service Key
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# edgebase-admin
|
|
2
|
+
|
|
3
|
+
Server-only Python admin SDK for EdgeBase.
|
|
4
|
+
|
|
5
|
+
Use `edgebase-admin` from trusted environments that hold a Service Key, such as backend APIs, cron jobs, workers, and operational tooling. It exposes admin auth, service-key database access, storage management, raw SQL, functions, analytics, push, and native Cloudflare resources.
|
|
6
|
+
|
|
7
|
+
If you want the unified package that also includes the higher-level `EdgeBaseServer` entry point and room helpers, install [`edgebase`](https://pypi.org/project/edgebase/) instead.
|
|
8
|
+
|
|
9
|
+
## Documentation Map
|
|
10
|
+
|
|
11
|
+
Use this README for the fast overview, then jump into the docs when you need depth:
|
|
12
|
+
|
|
13
|
+
- [SDK Overview](https://edgebase.fun/docs/sdks)
|
|
14
|
+
Install commands and language matrix for all public SDKs
|
|
15
|
+
- [Admin SDK](https://edgebase.fun/docs/sdks/client-vs-server)
|
|
16
|
+
Service-key concepts, trust boundaries, and admin-only capabilities
|
|
17
|
+
- [Admin SDK Reference](https://edgebase.fun/docs/admin-sdk/reference)
|
|
18
|
+
Cross-language auth, database, storage, functions, and push examples
|
|
19
|
+
- [Admin User Management](https://edgebase.fun/docs/authentication/admin-users)
|
|
20
|
+
Create, update, delete, and manage users with the Service Key
|
|
21
|
+
- [Database Admin SDK](https://edgebase.fun/docs/database/admin-sdk)
|
|
22
|
+
Table queries, filters, pagination, batch writes, and raw SQL
|
|
23
|
+
- [Storage](https://edgebase.fun/docs/storage/upload-download)
|
|
24
|
+
Uploads, downloads, metadata, and signed URLs
|
|
25
|
+
- [Analytics Admin SDK](https://edgebase.fun/docs/analytics/admin-sdk)
|
|
26
|
+
Request metrics, event tracking, and event queries
|
|
27
|
+
- [Push Admin SDK](https://edgebase.fun/docs/push/admin-sdk)
|
|
28
|
+
Push send, topic broadcast, token inspection, and logs
|
|
29
|
+
- [Native Resources](https://edgebase.fun/docs/server/native-resources)
|
|
30
|
+
KV, D1, Vectorize, and other edge-native resources
|
|
31
|
+
|
|
32
|
+
## For AI Coding Assistants
|
|
33
|
+
|
|
34
|
+
This package includes an `llms.txt` file for AI-assisted development.
|
|
35
|
+
|
|
36
|
+
Use it when you want an agent or code assistant to:
|
|
37
|
+
|
|
38
|
+
- use the right Python admin method signatures
|
|
39
|
+
- remember which surfaces are properties vs methods
|
|
40
|
+
- avoid copying JavaScript or Go API shapes into Python
|
|
41
|
+
- choose `edgebase-admin` instead of the broader `edgebase` package when only admin features are needed
|
|
42
|
+
|
|
43
|
+
You can find it:
|
|
44
|
+
|
|
45
|
+
- in this repository: [llms.txt](https://github.com/edge-base/edgebase/blob/main/packages/sdk/python/packages/admin/llms.txt)
|
|
46
|
+
- in your environment after install, inside the `edgebase_admin` package directory as `llms.txt`
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install edgebase-admin
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import os
|
|
58
|
+
|
|
59
|
+
from edgebase_admin import create_admin_client
|
|
60
|
+
|
|
61
|
+
admin = create_admin_client(
|
|
62
|
+
"https://your-project.edgebase.fun",
|
|
63
|
+
service_key=os.environ["EDGEBASE_SERVICE_KEY"],
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
users = admin.admin_auth.list_users(limit=20)
|
|
67
|
+
|
|
68
|
+
posts = (
|
|
69
|
+
admin.db("shared")
|
|
70
|
+
.table("posts")
|
|
71
|
+
.where("published", "==", True)
|
|
72
|
+
.order_by("createdAt", "desc")
|
|
73
|
+
.limit(10)
|
|
74
|
+
.get_list()
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
rows = admin.sql(
|
|
78
|
+
"shared",
|
|
79
|
+
None,
|
|
80
|
+
"SELECT COUNT(*) AS total FROM posts WHERE published = ?",
|
|
81
|
+
[1],
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
bucket = admin.storage().bucket("avatars")
|
|
85
|
+
signed = bucket.create_signed_url("user-1.jpg", expires_in="1h")
|
|
86
|
+
|
|
87
|
+
print(len(users.get("users", [])), len(posts.items), rows, signed.url)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Core API
|
|
91
|
+
|
|
92
|
+
- `AdminClient(base_url, service_key=...)`
|
|
93
|
+
Main admin entry point
|
|
94
|
+
- `create_admin_client(base_url, service_key=...)`
|
|
95
|
+
Convenience helper matching the public docs
|
|
96
|
+
- `admin.admin_auth`
|
|
97
|
+
Admin user management
|
|
98
|
+
- `admin.db(namespace="shared", instance_id=None).table(name)`
|
|
99
|
+
Service-key database access
|
|
100
|
+
- `admin.storage()`
|
|
101
|
+
Storage bucket access
|
|
102
|
+
- `admin.sql(namespace="shared", instance_id=None, query="", params=None)`
|
|
103
|
+
Raw SQL
|
|
104
|
+
- `admin.functions()`
|
|
105
|
+
Call app functions from trusted code
|
|
106
|
+
- `admin.analytics()`
|
|
107
|
+
Query request metrics and track custom events
|
|
108
|
+
- `admin.push()`
|
|
109
|
+
Send push notifications and inspect logs
|
|
110
|
+
- `admin.kv(namespace)`, `admin.d1(database)`, `admin.vector(index)` / `admin.vectorize(index)`
|
|
111
|
+
Native Cloudflare resources
|
|
112
|
+
|
|
113
|
+
## Requirements
|
|
114
|
+
|
|
115
|
+
- Python `3.10+`
|
|
116
|
+
- `edgebase-core>=0.1.3,<0.2.0`
|
|
117
|
+
- A valid EdgeBase Service Key
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# edgebase-admin
|
|
2
|
+
|
|
3
|
+
Use this file as a quick-reference contract for AI coding assistants working with the `edgebase-admin` Python package.
|
|
4
|
+
|
|
5
|
+
## Package Boundary
|
|
6
|
+
|
|
7
|
+
Use `edgebase-admin` for trusted, service-key-backed server workloads.
|
|
8
|
+
|
|
9
|
+
This package is the slim Python admin SDK. It is the right choice when you need admin auth, service-key database access, storage management, raw SQL, functions, analytics, push, or native Cloudflare resources without the broader `edgebase` package.
|
|
10
|
+
|
|
11
|
+
## Source Of Truth
|
|
12
|
+
|
|
13
|
+
- Package README: https://github.com/edge-base/edgebase/blob/main/packages/sdk/python/packages/admin/README.md
|
|
14
|
+
- SDK overview: https://edgebase.fun/docs/sdks
|
|
15
|
+
- Admin SDK guide: https://edgebase.fun/docs/sdks/client-vs-server
|
|
16
|
+
- Admin SDK reference: https://edgebase.fun/docs/admin-sdk/reference
|
|
17
|
+
- Admin users: https://edgebase.fun/docs/authentication/admin-users
|
|
18
|
+
- Database admin SDK: https://edgebase.fun/docs/database/admin-sdk
|
|
19
|
+
- Storage: https://edgebase.fun/docs/storage/upload-download
|
|
20
|
+
- Analytics admin SDK: https://edgebase.fun/docs/analytics/admin-sdk
|
|
21
|
+
- Push admin SDK: https://edgebase.fun/docs/push/admin-sdk
|
|
22
|
+
- Native resources: https://edgebase.fun/docs/server/native-resources
|
|
23
|
+
|
|
24
|
+
If docs, snippets, and assumptions disagree, prefer the current package API over guessed patterns from another runtime.
|
|
25
|
+
|
|
26
|
+
## Canonical Examples
|
|
27
|
+
|
|
28
|
+
### Create an admin client
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import os
|
|
32
|
+
|
|
33
|
+
from edgebase_admin import create_admin_client
|
|
34
|
+
|
|
35
|
+
admin = create_admin_client(
|
|
36
|
+
"https://your-project.edgebase.fun",
|
|
37
|
+
service_key=os.environ["EDGEBASE_SERVICE_KEY"],
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Query data
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
posts = (
|
|
45
|
+
admin.db("shared")
|
|
46
|
+
.table("posts")
|
|
47
|
+
.where("published", "==", True)
|
|
48
|
+
.order_by("createdAt", "desc")
|
|
49
|
+
.limit(20)
|
|
50
|
+
.get_list()
|
|
51
|
+
)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Manage users
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
page = admin.admin_auth.list_users(limit=20)
|
|
58
|
+
|
|
59
|
+
user = admin.admin_auth.create_user(
|
|
60
|
+
"june@example.com",
|
|
61
|
+
"securePassword",
|
|
62
|
+
data={"displayName": "June", "role": "editor"},
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
admin.admin_auth.set_custom_claims(user["id"], {"plan": "pro"})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Storage
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
bucket = admin.storage().bucket("avatars")
|
|
72
|
+
|
|
73
|
+
bucket.upload("user-1.jpg", file_bytes, content_type="image/jpeg")
|
|
74
|
+
signed = bucket.create_signed_url("user-1.jpg", expires_in="1h")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Functions and analytics
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
result = admin.functions().post("jobs/send-welcome-email", {"userId": "user-123"})
|
|
81
|
+
|
|
82
|
+
admin.analytics().track(
|
|
83
|
+
"user_upgraded",
|
|
84
|
+
{"plan": "pro", "amount": 29.99},
|
|
85
|
+
user_id="user_123",
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Native resources
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
admin.kv("cache").set("homepage", "ready", ttl=300)
|
|
93
|
+
rows = admin.d1("analytics").query("SELECT 1", [])
|
|
94
|
+
matches = admin.vector("embeddings").search([0.1, 0.2, 0.3], top_k=5)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Common Mistakes
|
|
98
|
+
|
|
99
|
+
- use `create_admin_client(...)` or `AdminClient(...)`, not a browser/client SDK factory
|
|
100
|
+
- `admin.admin_auth` is a property, not a method
|
|
101
|
+
- `admin.storage()`, `admin.functions()`, `admin.analytics()`, and `admin.push()` are methods
|
|
102
|
+
- `admin.db(namespace="shared", instance_id=None)` uses an optional positional instance id
|
|
103
|
+
- `table.get()` returns `ListResult`, not a single record
|
|
104
|
+
- use `table.get_one(id)` or `table.doc(id).get()` for a single record
|
|
105
|
+
- `AdminClient.sql(...)` requires a non-empty query string
|
|
106
|
+
- `admin.admin_auth.create_user(...)` accepts optional profile fields via `data=...`
|
|
107
|
+
- `create_signed_upload_url(path, expires_in=...)` expects seconds as an `int`
|
|
108
|
+
- `admin.vector(...)` and `admin.vectorize(...)` are both valid; `vectorize()` is just an alias
|
|
109
|
+
|
|
110
|
+
## Quick Reference
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Initialize
|
|
114
|
+
admin = create_admin_client(base_url, service_key=service_key)
|
|
115
|
+
|
|
116
|
+
# Admin auth (property)
|
|
117
|
+
admin.admin_auth.get_user(user_id) # dict
|
|
118
|
+
admin.admin_auth.create_user(email, password, data=None) # dict
|
|
119
|
+
admin.admin_auth.update_user(user_id, data) # dict
|
|
120
|
+
admin.admin_auth.delete_user(user_id) # dict
|
|
121
|
+
admin.admin_auth.list_users(limit=20, cursor=None) # dict
|
|
122
|
+
admin.admin_auth.set_custom_claims(user_id, claims) # None
|
|
123
|
+
admin.admin_auth.revoke_all_sessions(user_id) # None
|
|
124
|
+
admin.admin_auth.disable_mfa(user_id) # None
|
|
125
|
+
|
|
126
|
+
# Database
|
|
127
|
+
admin.db("shared").table("posts").get_list() # ListResult
|
|
128
|
+
admin.db("shared").table("posts").get_one("id-1") # dict
|
|
129
|
+
admin.db("shared").table("posts").insert(record) # dict
|
|
130
|
+
admin.db("shared").table("posts").update("id-1", data) # dict
|
|
131
|
+
admin.db("shared").table("posts").delete("id-1") # dict
|
|
132
|
+
admin.sql("shared", None, query, params) # list
|
|
133
|
+
|
|
134
|
+
# Storage
|
|
135
|
+
bucket = admin.storage().bucket("avatars")
|
|
136
|
+
bucket.get_url("user-1.jpg") # str
|
|
137
|
+
bucket.upload("user-1.jpg", file_bytes, content_type="image/jpeg") # dict
|
|
138
|
+
bucket.download("user-1.jpg") # bytes
|
|
139
|
+
bucket.get_metadata("user-1.jpg") # FileInfo
|
|
140
|
+
bucket.update_metadata("user-1.jpg", metadata) # dict
|
|
141
|
+
bucket.list(prefix="", limit=100, offset=0) # list[FileInfo]
|
|
142
|
+
bucket.list_page(prefix="", limit=100, cursor=None) # FileListResult
|
|
143
|
+
bucket.create_signed_url("user-1.jpg", expires_in="1h") # SignedUrlResult
|
|
144
|
+
bucket.create_signed_upload_url("large.zip", expires_in=600) # SignedUrlResult
|
|
145
|
+
|
|
146
|
+
# Functions / analytics / push
|
|
147
|
+
admin.functions().get("health", query=None) # Any
|
|
148
|
+
admin.functions().post("jobs/run", body={}) # Any
|
|
149
|
+
admin.analytics().overview(range="7d") # dict
|
|
150
|
+
admin.analytics().track(name, properties=None, user_id=None) # None
|
|
151
|
+
admin.analytics().track_batch(events) # None
|
|
152
|
+
admin.analytics().query_events(metric="list", range="7d") # Any
|
|
153
|
+
admin.push().send(user_id, payload) # dict
|
|
154
|
+
admin.push().send_many(user_ids, payload) # dict
|
|
155
|
+
admin.push().send_to_token(token, payload, platform=None) # dict
|
|
156
|
+
admin.push().send_to_topic(topic, payload) # dict
|
|
157
|
+
admin.push().broadcast(payload) # dict
|
|
158
|
+
admin.push().get_tokens(user_id) # list[dict]
|
|
159
|
+
admin.push().get_logs(user_id, limit=None) # list[dict]
|
|
160
|
+
|
|
161
|
+
# Native resources
|
|
162
|
+
admin.kv("cache").get("key") # str | None
|
|
163
|
+
admin.kv("cache").set("key", "value", ttl=300) # None
|
|
164
|
+
admin.kv("cache").list(prefix=None, limit=None, cursor=None) # dict
|
|
165
|
+
admin.kv("cache").delete("key") # None
|
|
166
|
+
admin.d1("analytics").exec("SELECT 1", []) # list
|
|
167
|
+
admin.d1("analytics").query("SELECT 1", []) # list
|
|
168
|
+
admin.vector("embeddings").search([0.1, 0.2], top_k=5) # list[dict]
|
|
169
|
+
admin.vectorize("embeddings").search([0.1, 0.2], top_k=5) # list[dict]
|
|
170
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "edgebase-admin"
|
|
7
|
+
version = "0.1.3"
|
|
8
|
+
description = "Python admin SDK for EdgeBase service-key workloads"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "EdgeBase Team" }
|
|
14
|
+
]
|
|
15
|
+
dependencies = ["edgebase-core>=0.1.3,<0.2.0"]
|
|
16
|
+
|
|
17
|
+
[tool.hatch.build.targets.sdist]
|
|
18
|
+
include = ["src/edgebase_admin", "README.md", "llms.txt"]
|
|
19
|
+
|
|
20
|
+
[tool.hatch.build.targets.wheel]
|
|
21
|
+
packages = ["src/edgebase_admin"]
|
|
22
|
+
|
|
23
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
24
|
+
"llms.txt" = "edgebase_admin/llms.txt"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""EdgeBase Admin SDK — admin auth, KV, D1, Vectorize."""
|
|
2
|
+
|
|
3
|
+
from edgebase_admin.admin_auth import AdminAuthClient
|
|
4
|
+
from edgebase_admin.analytics import AnalyticsClient
|
|
5
|
+
from edgebase_admin.admin_client import AdminClient, DbRef, create_admin_client
|
|
6
|
+
from edgebase_admin.kv import KvClient
|
|
7
|
+
from edgebase_admin.d1 import D1Client
|
|
8
|
+
from edgebase_admin.functions import FunctionsClient
|
|
9
|
+
from edgebase_admin.vectorize import VectorizeClient
|
|
10
|
+
from edgebase_admin.push import PushClient
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"AdminAuthClient",
|
|
14
|
+
"AnalyticsClient",
|
|
15
|
+
"AdminClient",
|
|
16
|
+
"DbRef",
|
|
17
|
+
"create_admin_client",
|
|
18
|
+
"KvClient",
|
|
19
|
+
"D1Client",
|
|
20
|
+
"FunctionsClient",
|
|
21
|
+
"VectorizeClient",
|
|
22
|
+
"PushClient",
|
|
23
|
+
]
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Admin authentication client — Service Key-based user management.
|
|
2
|
+
|
|
3
|
+
Python SDK is server-only: AdminAuthClient validates the service key is present
|
|
4
|
+
before making any request. Without a service key the server always returns 403,
|
|
5
|
+
so we short-circuit locally to save a round-trip and give a clear error.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from edgebase_core.errors import EdgeBaseError
|
|
13
|
+
from edgebase_core.http_client import HttpClient
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AdminAuthClient:
|
|
17
|
+
"""Admin auth — server-side user management via Service Key.
|
|
18
|
+
|
|
19
|
+
Usage::
|
|
20
|
+
|
|
21
|
+
user = admin.admin_auth.get_user("user-id")
|
|
22
|
+
new_user = admin.admin_auth.create_user(
|
|
23
|
+
email="admin@example.com", password="secure"
|
|
24
|
+
)
|
|
25
|
+
admin.admin_auth.set_custom_claims("user-id", {"role": "pro"})
|
|
26
|
+
admin.admin_auth.revoke_all_sessions("user-id")
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, client: HttpClient) -> None:
|
|
30
|
+
self._client = client
|
|
31
|
+
|
|
32
|
+
# ── Guard ─────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
def _require_service_key(self) -> None:
|
|
35
|
+
"""Raise EdgeBaseError(403) locally if no service key is configured.
|
|
36
|
+
|
|
37
|
+
All admin operations require a service key.
|
|
38
|
+
Failing fast here avoids an unnecessary network round-trip and surfaces
|
|
39
|
+
the misconfiguration immediately with a clear error message.
|
|
40
|
+
"""
|
|
41
|
+
if not getattr(self._client, "_service_key", None):
|
|
42
|
+
raise EdgeBaseError(
|
|
43
|
+
status_code=403,
|
|
44
|
+
message="Service Key required for admin operations. "
|
|
45
|
+
"Pass service_key= when constructing EdgeBaseServer.",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def _unwrap_user_payload(payload: dict[str, Any]) -> dict[str, Any]:
|
|
50
|
+
user = payload.get("user")
|
|
51
|
+
if isinstance(user, dict):
|
|
52
|
+
merged = dict(user)
|
|
53
|
+
for key, value in payload.items():
|
|
54
|
+
if key != "user" and key not in merged:
|
|
55
|
+
merged[key] = value
|
|
56
|
+
return merged
|
|
57
|
+
return payload
|
|
58
|
+
|
|
59
|
+
# ── Public API ────────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
def get_user(self, user_id: str) -> dict[str, Any]:
|
|
62
|
+
"""Get a user by ID."""
|
|
63
|
+
self._require_service_key()
|
|
64
|
+
result = self._client.get(f"/auth/admin/users/{user_id}")
|
|
65
|
+
return self._unwrap_user_payload(result if isinstance(result, dict) else {})
|
|
66
|
+
|
|
67
|
+
def create_user(
|
|
68
|
+
self,
|
|
69
|
+
email: str,
|
|
70
|
+
password: str,
|
|
71
|
+
data: dict[str, Any] | None = None,
|
|
72
|
+
) -> dict[str, Any]:
|
|
73
|
+
"""Create a new user."""
|
|
74
|
+
self._require_service_key()
|
|
75
|
+
body: dict[str, Any] = {"email": email, "password": password}
|
|
76
|
+
if data:
|
|
77
|
+
body["data"] = data
|
|
78
|
+
result = self._client.post("/auth/admin/users", body)
|
|
79
|
+
return self._unwrap_user_payload(result if isinstance(result, dict) else {})
|
|
80
|
+
|
|
81
|
+
def update_user(self, user_id: str, data: dict[str, Any]) -> dict[str, Any]:
|
|
82
|
+
"""Update a user."""
|
|
83
|
+
self._require_service_key()
|
|
84
|
+
result = self._client.patch(f"/auth/admin/users/{user_id}", data)
|
|
85
|
+
return self._unwrap_user_payload(result if isinstance(result, dict) else {})
|
|
86
|
+
|
|
87
|
+
def delete_user(self, user_id: str) -> dict[str, Any]:
|
|
88
|
+
"""Delete a user."""
|
|
89
|
+
self._require_service_key()
|
|
90
|
+
return self._client.delete(f"/auth/admin/users/{user_id}")
|
|
91
|
+
|
|
92
|
+
def list_users(
|
|
93
|
+
self,
|
|
94
|
+
limit: int = 20,
|
|
95
|
+
cursor: str | None = None,
|
|
96
|
+
) -> dict[str, Any]:
|
|
97
|
+
"""List users with cursor-based pagination.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
limit: Maximum number of users to return (default 20).
|
|
101
|
+
cursor: Pagination cursor from previous response.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Dict with 'users' list and optional 'cursor' for next page.
|
|
105
|
+
"""
|
|
106
|
+
self._require_service_key()
|
|
107
|
+
params: dict[str, str] = {"limit": str(limit)}
|
|
108
|
+
if cursor:
|
|
109
|
+
params["cursor"] = cursor
|
|
110
|
+
result = self._client.get("/auth/admin/users", params)
|
|
111
|
+
return result if isinstance(result, dict) else {"users": [], "cursor": None}
|
|
112
|
+
|
|
113
|
+
def set_custom_claims(
|
|
114
|
+
self,
|
|
115
|
+
user_id: str,
|
|
116
|
+
claims: dict[str, Any],
|
|
117
|
+
) -> None:
|
|
118
|
+
"""Set custom claims for a user (reflected in JWT on next token refresh)."""
|
|
119
|
+
self._require_service_key()
|
|
120
|
+
self._client.put(f"/auth/admin/users/{user_id}/claims", claims)
|
|
121
|
+
|
|
122
|
+
def revoke_all_sessions(self, user_id: str) -> None:
|
|
123
|
+
"""Revoke all sessions for a user (force re-authentication)."""
|
|
124
|
+
self._require_service_key()
|
|
125
|
+
self._client.post(f"/auth/admin/users/{user_id}/revoke")
|
|
126
|
+
|
|
127
|
+
def disable_mfa(self, user_id: str) -> None:
|
|
128
|
+
"""Disable MFA for a user (admin operation via Service Key).
|
|
129
|
+
|
|
130
|
+
Removes all MFA factors for the specified user, allowing them
|
|
131
|
+
to sign in without MFA verification.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
user_id: The user's ID whose MFA should be disabled.
|
|
135
|
+
"""
|
|
136
|
+
self._require_service_key()
|
|
137
|
+
self._client.delete(f"/auth/admin/users/{user_id}/mfa")
|