""" Databases Handler - manages Appwrite databases, collections, attributes, and indexes Phase I.1: 18 tools - Databases: 5 (list, get, create, update, delete) - Collections: 5 (list, get, create, update, delete) - Attributes: 5 (list, create_string, create_integer, create_boolean, delete) - Indexes: 3 (list, create, delete) """ import json from typing import Any from plugins.appwrite.client import AppwriteClient def get_tool_specifications() -> list[dict[str, Any]]: """Return tool specifications for ToolGenerator (18 tools)""" return [ # ===================== # DATABASES (5) # ===================== { "name": "list_databases", "method_name": "list_databases", "description": "List all databases in the Appwrite project. Returns database ID, name, and creation date.", "schema": { "type": "object", "properties": { "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering (e.g., 'limit(25)', 'offset(0)')", }, "search": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Search term to filter databases by name", }, }, "required": [], }, "scope": "read", }, { "name": "get_database", "method_name": "get_database", "description": "Get database details by ID.", "schema": { "type": "object", "properties": {"database_id": {"type": "string", "description": "Database ID"}}, "required": ["database_id"], }, "scope": "read", }, { "name": "create_database", "method_name": "create_database", "description": "Create a new database. Use 'unique()' as database_id to auto-generate a unique ID.", "schema": { "type": "object", "properties": { "database_id": { "type": "string", "description": "Unique database ID. Use 'unique()' for auto-generation", }, "name": {"type": "string", "description": "Database name"}, "enabled": { "type": "boolean", "description": "Enable or disable the database", "default": True, }, }, "required": ["database_id", "name"], }, "scope": "write", }, { "name": "update_database", "method_name": "update_database", "description": "Update database name or enabled status.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "name": {"type": "string", "description": "New database name"}, "enabled": { "anyOf": [{"type": "boolean"}, {"type": "null"}], "description": "Enable or disable the database", }, }, "required": ["database_id", "name"], }, "scope": "write", }, { "name": "delete_database", "method_name": "delete_database", "description": "Delete a database and all its collections. This action is irreversible.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID to delete"} }, "required": ["database_id"], }, "scope": "admin", }, # ===================== # COLLECTIONS (5) # ===================== { "name": "list_collections", "method_name": "list_collections", "description": "List all collections in a database.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering", }, "search": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Search term to filter collections", }, }, "required": ["database_id"], }, "scope": "read", }, { "name": "get_collection", "method_name": "get_collection", "description": "Get collection details including attributes and indexes.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, }, "required": ["database_id", "collection_id"], }, "scope": "read", }, { "name": "create_collection", "method_name": "create_collection", "description": "Create a new collection in a database. Use 'unique()' for auto-generated ID.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": { "type": "string", "description": "Unique collection ID. Use 'unique()' for auto-generation", }, "name": {"type": "string", "description": "Collection name"}, "permissions": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Collection permissions (e.g., 'read(\"any\")', 'write(\"users\")')", }, "document_security": { "type": "boolean", "description": "Enable document-level security", "default": True, }, "enabled": { "type": "boolean", "description": "Enable or disable the collection", "default": True, }, }, "required": ["database_id", "collection_id", "name"], }, "scope": "write", }, { "name": "update_collection", "method_name": "update_collection", "description": "Update collection settings.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "name": {"type": "string", "description": "New collection name"}, "permissions": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "New permissions", }, "document_security": { "anyOf": [{"type": "boolean"}, {"type": "null"}], "description": "Enable/disable document-level security", }, "enabled": { "anyOf": [{"type": "boolean"}, {"type": "null"}], "description": "Enable/disable the collection", }, }, "required": ["database_id", "collection_id", "name"], }, "scope": "write", }, { "name": "delete_collection", "method_name": "delete_collection", "description": "Delete a collection and all its documents. This action is irreversible.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID to delete"}, }, "required": ["database_id", "collection_id"], }, "scope": "admin", }, # ===================== # ATTRIBUTES (5) # ===================== { "name": "list_attributes", "method_name": "list_attributes", "description": "List all attributes (fields/columns) of a collection.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering", }, }, "required": ["database_id", "collection_id"], }, "scope": "read", }, { "name": "create_string_attribute", "method_name": "create_string_attribute", "description": "Create a string attribute in a collection.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "key": {"type": "string", "description": "Attribute key (field name)"}, "size": { "type": "integer", "description": "Maximum string length", "default": 255, }, "required": { "type": "boolean", "description": "Is this field required?", "default": False, }, "default": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Default value", }, "array": { "type": "boolean", "description": "Is this an array attribute?", "default": False, }, "encrypt": { "type": "boolean", "description": "Encrypt the attribute value", "default": False, }, }, "required": ["database_id", "collection_id", "key"], }, "scope": "write", }, { "name": "create_integer_attribute", "method_name": "create_integer_attribute", "description": "Create an integer attribute in a collection.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "key": {"type": "string", "description": "Attribute key (field name)"}, "required": { "type": "boolean", "description": "Is this field required?", "default": False, }, "min": { "anyOf": [{"type": "integer"}, {"type": "null"}], "description": "Minimum value", }, "max": { "anyOf": [{"type": "integer"}, {"type": "null"}], "description": "Maximum value", }, "default": { "anyOf": [{"type": "integer"}, {"type": "null"}], "description": "Default value", }, "array": { "type": "boolean", "description": "Is this an array attribute?", "default": False, }, }, "required": ["database_id", "collection_id", "key"], }, "scope": "write", }, { "name": "create_boolean_attribute", "method_name": "create_boolean_attribute", "description": "Create a boolean attribute in a collection.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "key": {"type": "string", "description": "Attribute key (field name)"}, "required": { "type": "boolean", "description": "Is this field required?", "default": False, }, "default": { "anyOf": [{"type": "boolean"}, {"type": "null"}], "description": "Default value", }, "array": { "type": "boolean", "description": "Is this an array attribute?", "default": False, }, }, "required": ["database_id", "collection_id", "key"], }, "scope": "write", }, { "name": "delete_attribute", "method_name": "delete_attribute", "description": "Delete an attribute from a collection. This will remove the field from all documents.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "key": {"type": "string", "description": "Attribute key to delete"}, }, "required": ["database_id", "collection_id", "key"], }, "scope": "admin", }, # ===================== # INDEXES (3) # ===================== { "name": "list_indexes", "method_name": "list_indexes", "description": "List all indexes of a collection.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering", }, }, "required": ["database_id", "collection_id"], }, "scope": "read", }, { "name": "create_index", "method_name": "create_index", "description": "Create an index on collection attributes for faster queries.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "key": {"type": "string", "description": "Index key (unique name)"}, "type": { "type": "string", "enum": ["key", "unique", "fulltext"], "description": "Index type: key (regular), unique, or fulltext", }, "attributes": { "type": "array", "items": {"type": "string"}, "description": "Array of attribute keys to index", }, "orders": { "anyOf": [ {"type": "array", "items": {"type": "string", "enum": ["ASC", "DESC"]}}, {"type": "null"}, ], "description": "Sort order for each attribute (ASC or DESC)", }, }, "required": ["database_id", "collection_id", "key", "type", "attributes"], }, "scope": "write", }, { "name": "delete_index", "method_name": "delete_index", "description": "Delete an index from a collection.", "schema": { "type": "object", "properties": { "database_id": {"type": "string", "description": "Database ID"}, "collection_id": {"type": "string", "description": "Collection ID"}, "key": {"type": "string", "description": "Index key to delete"}, }, "required": ["database_id", "collection_id", "key"], }, "scope": "admin", }, ] # ===================== # HANDLER FUNCTIONS # ===================== async def list_databases( client: AppwriteClient, queries: list[str] | None = None, search: str | None = None ) -> str: """List all databases.""" try: result = await client.list_databases(queries=queries, search=search) databases = result.get("databases", []) response = { "success": True, "total": result.get("total", len(databases)), "databases": databases, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def get_database(client: AppwriteClient, database_id: str) -> str: """Get database by ID.""" try: result = await client.get_database(database_id) return json.dumps({"success": True, "database": result}, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_database( client: AppwriteClient, database_id: str, name: str, enabled: bool = True ) -> str: """Create a new database.""" try: result = await client.create_database(database_id=database_id, name=name, enabled=enabled) return json.dumps( { "success": True, "message": f"Database '{name}' created successfully", "database": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def update_database( client: AppwriteClient, database_id: str, name: str, enabled: bool | None = None ) -> str: """Update database.""" try: result = await client.update_database(database_id=database_id, name=name, enabled=enabled) return json.dumps( {"success": True, "message": "Database updated successfully", "database": result}, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_database(client: AppwriteClient, database_id: str) -> str: """Delete database.""" try: await client.delete_database(database_id) return json.dumps( {"success": True, "message": f"Database '{database_id}' deleted successfully"}, indent=2 ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def list_collections( client: AppwriteClient, database_id: str, queries: list[str] | None = None, search: str | None = None, ) -> str: """List collections in a database.""" try: result = await client.list_collections( database_id=database_id, queries=queries, search=search ) collections = result.get("collections", []) response = { "success": True, "database_id": database_id, "total": result.get("total", len(collections)), "collections": collections, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def get_collection(client: AppwriteClient, database_id: str, collection_id: str) -> str: """Get collection details.""" try: result = await client.get_collection(database_id, collection_id) return json.dumps({"success": True, "collection": result}, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_collection( client: AppwriteClient, database_id: str, collection_id: str, name: str, permissions: list[str] | None = None, document_security: bool = True, enabled: bool = True, ) -> str: """Create a new collection.""" try: result = await client.create_collection( database_id=database_id, collection_id=collection_id, name=name, permissions=permissions, document_security=document_security, enabled=enabled, ) return json.dumps( { "success": True, "message": f"Collection '{name}' created successfully", "collection": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def update_collection( client: AppwriteClient, database_id: str, collection_id: str, name: str, permissions: list[str] | None = None, document_security: bool | None = None, enabled: bool | None = None, ) -> str: """Update collection.""" try: result = await client.update_collection( database_id=database_id, collection_id=collection_id, name=name, permissions=permissions, document_security=document_security, enabled=enabled, ) return json.dumps( {"success": True, "message": "Collection updated successfully", "collection": result}, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_collection(client: AppwriteClient, database_id: str, collection_id: str) -> str: """Delete collection.""" try: await client.delete_collection(database_id, collection_id) return json.dumps( {"success": True, "message": f"Collection '{collection_id}' deleted successfully"}, indent=2, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def list_attributes( client: AppwriteClient, database_id: str, collection_id: str, queries: list[str] | None = None ) -> str: """List collection attributes.""" try: result = await client.list_attributes( database_id=database_id, collection_id=collection_id, queries=queries ) attributes = result.get("attributes", []) response = { "success": True, "database_id": database_id, "collection_id": collection_id, "total": result.get("total", len(attributes)), "attributes": attributes, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_string_attribute( client: AppwriteClient, database_id: str, collection_id: str, key: str, size: int = 255, required: bool = False, default: str | None = None, array: bool = False, encrypt: bool = False, ) -> str: """Create string attribute.""" try: result = await client.create_string_attribute( database_id=database_id, collection_id=collection_id, key=key, size=size, required=required, default=default, array=array, encrypt=encrypt, ) return json.dumps( { "success": True, "message": f"String attribute '{key}' created successfully", "attribute": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_integer_attribute( client: AppwriteClient, database_id: str, collection_id: str, key: str, required: bool = False, min: int | None = None, max: int | None = None, default: int | None = None, array: bool = False, ) -> str: """Create integer attribute.""" try: result = await client.create_integer_attribute( database_id=database_id, collection_id=collection_id, key=key, required=required, min=min, max=max, default=default, array=array, ) return json.dumps( { "success": True, "message": f"Integer attribute '{key}' created successfully", "attribute": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_boolean_attribute( client: AppwriteClient, database_id: str, collection_id: str, key: str, required: bool = False, default: bool | None = None, array: bool = False, ) -> str: """Create boolean attribute.""" try: result = await client.create_boolean_attribute( database_id=database_id, collection_id=collection_id, key=key, required=required, default=default, array=array, ) return json.dumps( { "success": True, "message": f"Boolean attribute '{key}' created successfully", "attribute": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_attribute( client: AppwriteClient, database_id: str, collection_id: str, key: str ) -> str: """Delete attribute.""" try: await client.delete_attribute(database_id, collection_id, key) return json.dumps( {"success": True, "message": f"Attribute '{key}' deleted successfully"}, indent=2 ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def list_indexes( client: AppwriteClient, database_id: str, collection_id: str, queries: list[str] | None = None ) -> str: """List collection indexes.""" try: result = await client.list_indexes( database_id=database_id, collection_id=collection_id, queries=queries ) indexes = result.get("indexes", []) response = { "success": True, "database_id": database_id, "collection_id": collection_id, "total": result.get("total", len(indexes)), "indexes": indexes, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_index( client: AppwriteClient, database_id: str, collection_id: str, key: str, type: str, attributes: list[str], orders: list[str] | None = None, ) -> str: """Create index.""" try: result = await client.create_index( database_id=database_id, collection_id=collection_id, key=key, type=type, attributes=attributes, orders=orders, ) return json.dumps( {"success": True, "message": f"Index '{key}' created successfully", "index": result}, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_index( client: AppwriteClient, database_id: str, collection_id: str, key: str ) -> str: """Delete index.""" try: await client.delete_index(database_id, collection_id, key) return json.dumps( {"success": True, "message": f"Index '{key}' deleted successfully"}, indent=2 ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2)