$ cat node-template.py
Drive Folder Reader
// Reads all documents from a selected Drive folder recursively.
Input
Storage
template.py
1import os2import sys3import json4import traceback5import requests67# Environment variables automatically set by workspace executor8EMBLEMA_API_BASE_URL = os.getenv("EMBLEMA_API_BASE_URL")9USER_TOKEN = os.getenv("USER_TOKEN")1011if not EMBLEMA_API_BASE_URL:12 raise ValueError("EMBLEMA_API_BASE_URL environment variable not set")131415def api_request(method, path, **kwargs):16 """Make authenticated API request.1718 Args:19 method: HTTP method (GET, POST, PUT, DELETE, etc.)20 path: API path (e.g., "/api/v2/drive/items")21 **kwargs: Additional arguments for requests.request()22 """23 if not USER_TOKEN:24 raise ValueError("USER_TOKEN environment variable not set")2526 headers = {27 "Authorization": f"Bearer {USER_TOKEN}",28 "Content-Type": "application/json",29 }30 url = f"{EMBLEMA_API_BASE_URL}{path}"31 response = requests.request(method, url, headers=headers, **kwargs)32 response.raise_for_status()33 return response.json()343536def main():37 """Main execution function"""38 try:39 # Read execution input from stdin40 input_json = sys.stdin.read()41 execution_input = json.loads(input_json)4243 # Extract folder ID from inputs44 inputs = execution_input.get("inputs", {})45 folder_id = inputs.get("driveItemId")4647 if not folder_id:48 raise ValueError("driveItemId input is required")4950 # Call REST API to get folder contents RECURSIVELY51 # API automatically applies user permissions via PAT52 # Use query syntax to filter:53 # - path descendantOf 'folder-id' - RECURSIVE (includes all nested subfolders)54 # - refId != null - only files/documents, NOT folders55 result = api_request("GET", "/api/v2/drive/items", params={56 "q": f"path descendantOf '{folder_id}' and refId!=null",57 "pageSize": 1000,58 })5960 # Extract DriveItem IDs from items61 # IMPORTANT: We return DriveItem IDs, NOT Document IDs (refId)!62 # This ensures proper permission validation via DriveItem path63 # DriveItem wraps the Document and carries permission information64 drive_item_ids = []65 for item in result.get("items", []):66 # All items returned from query should be documents (refId!=null filter)67 # We return the DriveItem ID so downstream nodes can validate permissions68 if item.get("id"):69 drive_item_ids.append(item["id"])7071 # Output result (matches OUTPUT_SCHEMA)72 output = {73 "driveItemIds": drive_item_ids,74 }75 print(json.dumps(output, indent=2))7677 except requests.HTTPError as e:78 # HTTP error (401, 403, 404, etc.)79 error_output = {80 "error": f"API request failed: {e}",81 "errorType": "HTTPError",82 "status": e.response.status_code,83 "detail": e.response.text,84 }85 print(json.dumps(error_output), file=sys.stderr)86 sys.exit(1)87 except Exception as e:88 # Other errors89 error_output = {90 "error": str(e),91 "errorType": type(e).__name__,92 "traceback": traceback.format_exc(),93 }94 print(json.dumps(error_output), file=sys.stderr)95 sys.exit(1)969798if __name__ == "__main__":99 main()