Files
hermes-config/skills/self-hosting/pocketbase-setup/scripts/pb_add_fields.py
T
2026-07-12 10:17:17 -04:00

92 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Add fields to PocketBase collection schema. PocketBase silently drops fields
not in schema — you MUST add them via API when extending the data model.
Usage: Edit FIELDS_TO_ADD and COLLECTION_NAME below, then run.
"""
import json, urllib.request, ssl
# === CONFIG ===
PB_URL = "http://localhost:8091"
SUPERUSER_EMAIL = "admin@example.com"
SUPERUSER_PASSWORD = "password"
COLLECTION_NAME = "services" # Change this
FIELDS_TO_ADD = [
# Example: add a text field
{"name": "recommendation", "type": "text"},
{"name": "explanation", "type": "text"},
# For other field types, see PocketBase API docs
# {"name": "duration", "type": "number", "onlyInt": False},
]
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
def api(method, path, data=None, token=None):
headers = {"Content-Type": "application/json"}
if token:
headers["Authorization"] = f"Bearer {token}"
body = json.dumps(data).encode() if data else None
req = urllib.request.Request(f"{PB_URL}{path}", data=body, headers=headers, method=method)
resp = urllib.request.urlopen(req, context=ctx)
return json.loads(resp.read())
# Step 1: Auth
auth_resp = api("POST", "/api/collections/_superusers/auth-with-password", {
"identity": SUPERUSER_EMAIL,
"password": SUPERUSER_PASSWORD
})
token = auth_resp["token"]
# Step 2: Get collection to see current fields
collections = api("GET", "/api/collections", token=token)
try:
col = next(c for c in collections["items"] if c["name"] == COLLECTION_NAME)
except StopIteration:
print(f"Collection '{COLLECTION_NAME}' not found. Available:",
[c["name"] for c in collections["items"]])
exit(1)
print(f"Collection: {col['name']} (id: {col['id']})")
print(f"Current fields: {[f['name'] for f in col['fields']]}")
# Step 3: Build new fields with unique IDs
existing_fields = col["fields"]
existing_names = {f["name"] for f in existing_fields}
new_field_defs = []
for f in FIELDS_TO_ADD:
if f["name"] in existing_names:
print(f"Field '{f['name']}' already exists, skipping")
continue
field_type = f.get("type", "text")
field_def = {
"autogeneratePattern": "",
"hidden": False,
"id": f"field_{f['name']}_{len(existing_fields) + len(new_field_defs)}",
"max": f.get("max", 0),
"min": f.get("min", 0),
"name": f["name"],
"pattern": f.get("pattern", ""),
"presentable": False,
"primaryKey": False,
"required": f.get("required", False),
"system": False,
"type": field_type,
}
if field_type == "number":
field_def["onlyInt"] = f.get("onlyInt", False)
new_field_defs.append(field_def)
if not new_field_defs:
print("No new fields to add.")
exit(0)
# Step 4: PATCH with complete fields array
all_fields = existing_fields + new_field_defs
result = api("PATCH", f"/api/collections/{col['id']}", {"fields": all_fields}, token=token)
print(f"Updated fields: {[f['name'] for f in result['fields']]}")
print(f"✅ Added {len(new_field_defs)} field(s) to {COLLECTION_NAME}")