#!/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}")