# PocketBase Module Usage Examples

This file contains practical examples of how to use the PocketBase CRUD module in Wappler Server Connect.

## Example 1: Basic Blog System

### Step 1: Setup Connection
Create a Server Action called `pb_connect.json`:

```json
{
  "meta": {
    "options": {
      "linkedFile": "/api/pb_connect",
      "linkedForm": "pb_connect"
    },
    "$_GET": [
      {
        "type": "text",
        "name": "test"
      }
    ]
  },
  "exec": {
    "steps": [
      {
        "name": "connect",
        "module": "pocketbase",
        "action": "connect",
        "options": {
          "url": "http://127.0.0.1:8090"
        },
        "output": true
      }
    ]
  }
}
```

### Step 2: User Authentication
Create `pb_auth.json`:

```json
{
  "meta": {
    "options": {
      "linkedFile": "/api/pb_auth",
      "linkedForm": "pb_auth"
    },
    "$_POST": [
      {
        "type": "text",
        "name": "email"
      },
      {
        "type": "text",
        "name": "password"
      }
    ]
  },
  "exec": {
    "steps": [
      {
        "name": "authenticate",
        "module": "pocketbase",
        "action": "authenticate",
        "options": {
          "email": "{{$_POST.email}}",
          "password": "{{$_POST.password}}",
          "collection": "users"
        },
        "output": true
      }
    ]
  }
}
```

### Step 3: Create Blog Post
Create `pb_create_post.json`:

```json
{
  "meta": {
    "options": {
      "linkedFile": "/api/pb_create_post",
      "linkedForm": "pb_create_post"
    },
    "$_POST": [
      {
        "type": "text",
        "name": "title"
      },
      {
        "type": "text",
        "name": "content"
      },
      {
        "type": "text",
        "name": "category"
      }
    ],
    "$_FILES": [
      {
        "type": "file",
        "name": "featured_image"
      }
    ]
  },
  "exec": {
    "steps": [
      {
        "name": "create_post",
        "module": "pocketbase",
        "action": "create",
        "options": {
          "collection": "posts",
          "data": {
            "title": "{{$_POST.title}}",
            "content": "{{$_POST.content}}",
            "category": "{{$_POST.category}}",
            "featured_image": "{{$_FILES.featured_image.path}}",
            "author": "{{$_SESSION.pb_user.id}}",
            "status": "draft",
            "created": "{{NOW()}}"
          }
        },
        "output": true
      }
    ]
  }
}
```

### Step 4: Get Blog Posts
Create `pb_get_posts.json`:

```json
{
  "meta": {
    "options": {
      "linkedFile": "/api/pb_get_posts"
    },
    "$_GET": [
      {
        "type": "text",
        "name": "page"
      },
      {
        "type": "text",
        "name": "category"
      },
      {
        "type": "text",
        "name": "search"
      }
    ]
  },
  "exec": {
    "steps": [
      {
        "name": "get_posts",
        "module": "pocketbase",
        "action": "getList",
        "options": {
          "collection": "posts",
          "page": "{{$_GET.page || 1}}",
          "perPage": "10",
          "filter": "{{($_GET.category ? 'category = \"' + $_GET.category + '\"' : '') + ($_GET.search ? ($_GET.category ? ' && ' : '') + 'title ~ \"' + $_GET.search + '\"' : '') + (($_GET.category || $_GET.search) ? ' && ' : '') + 'status = \"published\"'}}",
          "sort": "-created",
          "expand": "author,category"
        },
        "output": true
      }
    ]
  }
}
```

### Step 5: Update Blog Post
Create `pb_update_post.json`:

```json
{
  "meta": {
    "options": {
      "linkedFile": "/api/pb_update_post",
      "linkedForm": "pb_update_post"
    },
    "$_POST": [
      {
        "type": "text",
        "name": "id"
      },
      {
        "type": "text",
        "name": "title"
      },
      {
        "type": "text",
        "name": "content"
      },
      {
        "type": "text",
        "name": "status"
      }
    ]
  },
  "exec": {
    "steps": [
      {
        "name": "update_post",
        "module": "pocketbase",
        "action": "update",
        "options": {
          "collection": "posts",
          "id": "{{$_POST.id}}",
          "data": {
            "title": "{{$_POST.title}}",
            "content": "{{$_POST.content}}",
            "status": "{{$_POST.status}}",
            "updated": "{{NOW()}}"
          }
        },
        "output": true
      }
    ]
  }
}
```

## Example 2: E-commerce Product Management

### Get Products with Advanced Filtering
```json
{
  "name": "get_products",
  "module": "pocketbase",
  "action": "getList",
  "options": {
    "collection": "products",
    "page": "{{$_GET.page || 1}}",
    "perPage": "20",
    "filter": "{{(function() { var filters = []; if ($_GET.category) filters.push('category = \"' + $_GET.category + '\"'); if ($_GET.min_price) filters.push('price >= ' + $_GET.min_price); if ($_GET.max_price) filters.push('price <= ' + $_GET.max_price); if ($_GET.in_stock) filters.push('stock > 0'); if ($_GET.search) filters.push('(name ~ \"' + $_GET.search + '\" || description ~ \"' + $_GET.search + '\")'); return filters.join(' && '); })()}}",
    "sort": "{{$_GET.sort || '-created'}}",
    "expand": "category,images"
  },
  "output": true
}
```

### Batch Update Product Inventory
```json
{
  "name": "batch_update_inventory",
  "module": "pocketbase",
  "action": "batch",
  "options": {
    "operations": "{{$_POST.inventory_updates.map(function(item) { return { type: 'update', collection: 'products', id: item.product_id, data: { stock: item.new_stock, updated: NOW() } }; })}}"
  },
  "output": true
}
```

## Example 3: User Profile Management

### Get User Profile with Relations
```json
{
  "name": "get_user_profile",
  "module": "pocketbase",
  "action": "getOne",
  "options": {
    "collection": "users",
    "id": "{{$_SESSION.pb_user.id}}",
    "expand": "profile,orders,favorites"
  },
  "output": true
}
```

### Update User Profile with Avatar
```json
{
  "name": "update_profile",
  "module": "pocketbase",
  "action": "update",
  "options": {
    "collection": "users",
    "id": "{{$_SESSION.pb_user.id}}",
    "data": {
      "name": "{{$_POST.name}}",
      "bio": "{{$_POST.bio}}",
      "avatar": "{{$_FILES.avatar ? $_FILES.avatar.path : undefined}}",
      "updated": "{{NOW()}}"
    }
  },
  "output": true
}
```

## Example 4: File Management

### Upload Multiple Files
```json
{
  "name": "upload_gallery",
  "module": "pocketbase",
  "action": "create",
  "options": {
    "collection": "gallery",
    "data": {
      "title": "{{$_POST.title}}",
      "description": "{{$_POST.description}}",
      "images": "{{Object.keys($_FILES).filter(key => key.startsWith('image_')).map(key => $_FILES[key].path)}}",
      "user": "{{$_SESSION.pb_user.id}}"
    }
  },
  "output": true
}
```

### Get File URLs for Gallery
```json
{
  "name": "get_gallery_urls",
  "module": "pocketbase",
  "action": "getFileUrl",
  "options": {
    "collection": "gallery",
    "recordId": "{{$_GET.gallery_id}}",
    "filename": "{{$_GET.filename}}",
    "thumb": "{{$_GET.size || '300x200'}}"
  },
  "output": true
}
```

## Example 5: Real-time Data with Health Checks

### Health Check Endpoint
```json
{
  "meta": {
    "options": {
      "linkedFile": "/api/health"
    }
  },
  "exec": {
    "steps": [
      {
        "name": "health_check",
        "module": "pocketbase",
        "action": "healthCheck",
        "options": {},
        "output": true
      },
      {
        "name": "get_collections",
        "module": "pocketbase",
        "action": "getCollections",
        "options": {},
        "output": true
      }
    ]
  }
}
```

## Example 6: Advanced Search

### Full-text Search Across Multiple Collections
```json
{
  "name": "global_search",
  "module": "pocketbase",
  "action": "batch",
  "options": {
    "operations": [
      {
        "type": "getList",
        "collection": "posts",
        "options": {
          "filter": "title ~ '{{$_GET.query}}' || content ~ '{{$_GET.query}}'",
          "fields": "id,title,content,created",
          "perPage": 5
        }
      },
      {
        "type": "getList", 
        "collection": "products",
        "options": {
          "filter": "name ~ '{{$_GET.query}}' || description ~ '{{$_GET.query}}'",
          "fields": "id,name,description,price",
          "perPage": 5
        }
      },
      {
        "type": "getList",
        "collection": "users", 
        "options": {
          "filter": "name ~ '{{$_GET.query}}' || bio ~ '{{$_GET.query}}'",
          "fields": "id,name,bio,avatar",
          "perPage": 5
        }
      }
    ]
  },
  "output": true
}
```

## Frontend Integration Examples

### JavaScript Fetch Examples

```javascript
// Authenticate user
async function loginUser(email, password) {
  const response = await fetch('/api/pb_auth', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email, password })
  });
  
  const result = await response.json();
  if (result.authenticate.success) {
    console.log('User logged in:', result.authenticate.user);
    return result.authenticate;
  } else {
    throw new Error('Login failed');
  }
}

// Get posts with pagination
async function getPosts(page = 1, category = null, search = null) {
  const params = new URLSearchParams({ page });
  if (category) params.append('category', category);
  if (search) params.append('search', search);
  
  const response = await fetch(`/api/pb_get_posts?${params}`);
  const result = await response.json();
  
  return result.get_posts;
}

// Create new post
async function createPost(postData, featuredImage) {
  const formData = new FormData();
  Object.keys(postData).forEach(key => {
    formData.append(key, postData[key]);
  });
  
  if (featuredImage) {
    formData.append('featured_image', featuredImage);
  }
  
  const response = await fetch('/api/pb_create_post', {
    method: 'POST',
    body: formData
  });
  
  const result = await response.json();
  return result.create_post;
}
```

### App Connect Data Bindings

```html
<!-- Display posts list -->
<div dmx-repeat:posts="serverconnect1.data.get_posts.items">
  <div class="card mb-3">
    <div class="card-body">
      <h5 class="card-title">{{title}}</h5>
      <p class="card-text">{{content.substr(0, 150)}}...</p>
      <small class="text-muted">
        By {{expand.author.name}} on {{created.formatDate('MMM dd, yyyy')}}
      </small>
    </div>
  </div>
</div>

<!-- Pagination -->
<nav>
  <ul class="pagination">
    <li class="page-item" dmx-class:disabled="serverconnect1.data.get_posts.page == 1">
      <a class="page-link" href="#" dmx-on:click="serverconnect1.load({page: serverconnect1.data.get_posts.page - 1})">Previous</a>
    </li>
    <li class="page-item" dmx-class:disabled="serverconnect1.data.get_posts.page == serverconnect1.data.get_posts.totalPages">
      <a class="page-link" href="#" dmx-on:click="serverconnect1.load({page: serverconnect1.data.get_posts.page + 1})">Next</a>
    </li>
  </ul>
</nav>
```

## Error Handling Examples

### Server Action with Error Handling
```json
{
  "exec": {
    "steps": [
      {
        "name": "try_create_post",
        "module": "core",
        "action": "trycatch",
        "options": {
          "try": [
            {
              "name": "create_post",
              "module": "pocketbase", 
              "action": "create",
              "options": {
                "collection": "posts",
                "data": "{{$_POST}}"
              }
            }
          ],
          "catch": [
            {
              "name": "error_response",
              "module": "core",
              "action": "response",
              "options": {
                "status": 400,
                "data": {
                  "error": true,
                  "message": "Failed to create post: {{$_ERROR.message}}"
                }
              }
            }
          ]
        },
        "output": true
      }
    ]
  }
}
```
