@ddl-tech/wappler-pocketbase
Version:
PocketBase CRUD module for Wappler Server Connect with complete database operations, authentication, and file management
543 lines (501 loc) • 12.6 kB
Markdown
# 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
}
]
}
}
```