Other SDK Classes
Beyond Nimbu.Object and Nimbu.Query, the Nimbu SDK provides specialized classes for working with specific data types and features. These classes extend the base Nimbu.Object functionality with domain-specific methods.
Nimbu.Customer
The Customer class represents customer accounts in your Nimbu site. Customers can log in, make purchases, and have associated data like orders and favorites.
Creating Customers
// Create a new customer
const customer = new Nimbu.Customer();
customer.set('email', '[email protected]');
customer.set('name', 'John Doe');
customer.set('password', 'securePassword123');
await customer.save();
console.log('Customer created:', customer.id);Finding Customers
// Find customer by email
const query = new Nimbu.Query('customers');
query.equalTo('email', '[email protected]');
const customer = await query.first();
if (customer) {
console.log('Found customer:', customer.get('name'));
}Customer Properties
// Access customer data
const email = customer.get('email');
const name = customer.get('name');
const createdAt = customer.createdAt;
// Check customer status
const isActive = customer.get('active');
const newsletterSubscribed = customer.get('newsletter_subscribed');Updating Customer Data
// Update customer information
const customer = await new Nimbu.Query('customers').get(customerId);
customer.set('phone', '+32 123 456 789');
customer.set('loyalty_points', 100);
customer.set('newsletter_subscribed', true);
await customer.save();Customer Roles
// Add customer to a role
const customer = await new Nimbu.Query('customers').get(customerId);
const role = await new Nimbu.Query('roles').get(roleId);
role.getCustomers().add(customer);
await role.save();
// Check if customer has a role
const customerRoles = customer.relation('roles');
const roles = await customerRoles.query().collection().fetch();
console.log(`Customer has ${roles.length} roles`);Customer Orders
// Get customer's orders
const customer = await new Nimbu.Query('customers').get(customerId);
const orders = customer.relation('orders');
const customerOrders = await orders.query()
.descending('created_at')
.limit(10)
.collection()
.fetch();
console.log(`Found ${customerOrders.length} orders`);Nimbu.Collection
The Collection class is a utility for working with custom content types (channels) in Nimbu.
Querying Collections
// Query a custom collection
const Collection = Nimbu.Object.extend('blog_posts');
const query = new Nimbu.Query(Collection);
query.equalTo('published', true);
query.descending('published_at');
query.limit(10);
const posts = await query.collection().fetch();Creating Collection Entries
// Create a new blog post
const BlogPost = Nimbu.Object.extend('blog_posts');
const post = new BlogPost();
post.set('title', 'My First Blog Post');
post.set('content', 'This is the content of my post');
post.set('published', true);
post.set('published_at', new Date());
await post.save();Collection with Custom Fields
// Work with custom fields
const entry = new Nimbu.Object('projects');
entry.set('project_name', 'New Website');
entry.set('project_status', 'in_progress');
entry.set('project_deadline', new Date('2024-12-31'));
entry.set('project_tags', ['web', 'design', 'development']);
await entry.save();Nimbu.Product
The Product class provides specialized methods for e-commerce products.
Product Queries
// Find active products
const query = new Nimbu.Query('products');
query.equalTo('active', true);
query.greaterThan('stock', 0);
query.ascending('name');
const products = await query.collection().fetch();Product Properties
const product = await new Nimbu.Query('products').get(productId);
// Basic properties
const name = product.get('name');
const price = product.get('price');
const stock = product.get('stock');
const sku = product.get('sku');
// Product attributes
const description = product.get('description');
const category = product.get('category');
const tags = product.get('tags');
const active = product.get('active');Product Variants
// Access product variants
const product = await new Nimbu.Query('products').get(productId);
const variants = product.get('variants');
if (variants && variants.length > 0) {
variants.forEach(variant => {
console.log(`${variant.name}: €${variant.price}`);
});
}Product Stock Management
// Update product stock
const product = await new Nimbu.Query('products').get(productId);
// Decrement stock (atomic operation)
await product.increment('stock', -1);
await product.save();
// Check stock level
if (product.get('stock') === 0) {
product.set('active', false);
await product.save();
}Product Categories
// Find products by category
const query = new Nimbu.Query('products');
query.equalTo('category', 'electronics');
query.equalTo('active', true);
const electronics = await query.collection().fetch();Nimbu.Order
The Order class represents customer orders and purchases.
Order Queries
// Find recent orders
const query = new Nimbu.Query('orders');
query.descending('created_at');
query.limit(20);
query.include('customer');
const recentOrders = await query.collection().fetch();
recentOrders.forEach(order => {
const customer = order.get('customer');
console.log(`Order ${order.id} - ${customer.get('name')}`);
});Order Properties
const order = await new Nimbu.Query('orders').get(orderId);
// Order details
const orderNumber = order.get('order_number');
const status = order.get('status');
const total = order.get('total');
const currency = order.get('currency');
// Order items
const items = order.get('items');
items.forEach(item => {
console.log(`${item.quantity}x ${item.product_name} - €${item.price}`);
});
// Customer information
const customer = order.get('customer');
const shippingAddress = order.get('shipping_address');
const billingAddress = order.get('billing_address');Order Status Management
// Update order status
const order = await new Nimbu.Query('orders').get(orderId);
order.set('status', 'processing');
order.set('processed_at', new Date());
await order.save();Order Filtering
// Find pending orders
const query = new Nimbu.Query('orders');
query.containedIn('status', ['pending', 'processing']);
query.include('customer');
const pendingOrders = await query.collection().fetch();
console.log(`${pendingOrders.length} orders need attention`);Nimbu.File
The File class handles file uploads and management.
Uploading Files
// Upload a file
const fileData = {
name: 'document.pdf',
data: fileBuffer, // or base64 string
contentType: 'application/pdf'
};
const file = new Nimbu.File(fileData);
await file.save();
console.log('File uploaded:', file.url());Attaching Files to Objects
// Attach file to an object
const document = new Nimbu.Object('documents');
document.set('title', 'Annual Report');
document.set('file', file);
await document.save();
// Access file later
const savedDocument = await new Nimbu.Query('documents').get(documentId);
const attachedFile = savedDocument.get('file');
console.log('Download URL:', attachedFile.url());File Metadata
// Access file properties
const fileName = file.name();
const fileUrl = file.url();
const fileSize = file.get('size');
const contentType = file.get('content_type');
console.log(`File: ${fileName} (${fileSize} bytes)`);Nimbu.Gallery
The Gallery class manages image galleries and media collections.
Creating Galleries
// Create a new gallery
const gallery = new Nimbu.Object('galleries');
gallery.set('name', 'Product Photos');
gallery.set('description', 'Photos of our products');
await gallery.save();Adding Images to Gallery
// Add images to gallery
const image1 = new Nimbu.File({ name: 'product1.jpg', data: imageData1 });
const image2 = new Nimbu.File({ name: 'product2.jpg', data: imageData2 });
await image1.save();
await image2.save();
const gallery = await new Nimbu.Query('galleries').get(galleryId);
const images = gallery.get('images') || [];
images.push(image1, image2);
gallery.set('images', images);
await gallery.save();Gallery Queries
// Find galleries
const query = new Nimbu.Query('galleries');
query.equalTo('active', true);
query.descending('created_at');
const galleries = await query.collection().fetch();
galleries.forEach(gallery => {
const images = gallery.get('images') || [];
console.log(`${gallery.get('name')}: ${images.length} images`);
});Nimbu.Role
The Role class manages customer roles and permissions.
Creating Roles
// Create a new role
const role = new Nimbu.Object('roles');
role.set('name', 'Premium Members');
role.set('description', 'Customers with premium access');
await role.save();Adding Customers to Roles
// Add customers to a role
const role = await new Nimbu.Query('roles').get(roleId);
const customer = await new Nimbu.Query('customers').get(customerId);
role.getCustomers().add(customer);
await role.save();
console.log('Customer added to role');Querying Role Members
// Get all customers in a role
const role = await new Nimbu.Query('roles').get(roleId);
const customers = await role.getCustomers().list();
console.log(`Role has ${customers.length} members`);
customers.forEach(customer => {
console.log(`- ${customer.get('name')} (${customer.get('email')})`);
});Removing Customers from Roles
// Remove customer from role
const role = await new Nimbu.Query('roles').get(roleId);
const customer = await new Nimbu.Query('customers').get(customerId);
role.getCustomers().remove(customer);
await role.save();Finding Roles by Customer
// Find all roles for a customer
const customer = await new Nimbu.Query('customers').get(customerId);
const roles = customer.relation('roles');
const customerRoles = await roles.query().collection().fetch();
customerRoles.forEach(role => {
console.log(`Customer has role: ${role.get('name')}`);
});Role-Based Access Control
// Check if customer has specific role
async function hasRole(customer, roleName) {
const roles = customer.relation('roles');
const query = roles.query();
query.equalTo('name', roleName);
const matchingRoles = await query.collection().fetch();
return matchingRoles.length > 0;
}
// Usage
const customer = await new Nimbu.Query('customers').get(customerId);
const isPremium = await hasRole(customer, 'Premium Members');
if (isPremium) {
console.log('Customer has premium access');
}Nimbu.API
The API class provides direct access to the Nimbu REST API for advanced use cases.
Making API Requests
// GET request
const response = await Nimbu.API.get('/api/products', {
params: {
active: true,
limit: 10
}
});
console.log('Products:', response.data);POST Requests
// Create resource via API
const response = await Nimbu.API.post('/api/customers', {
data: {
email: '[email protected]',
name: 'John Doe'
}
});
console.log('Created customer:', response.data);PUT/PATCH Requests
// Update resource
const response = await Nimbu.API.patch(`/api/products/${productId}`, {
data: {
price: 29.99,
stock: 100
}
});DELETE Requests
// Delete resource
await Nimbu.API.delete(`/api/products/${productId}`);
console.log('Product deleted');Custom Headers
// Add custom headers
const response = await Nimbu.API.get('/api/custom-endpoint', {
headers: {
'X-Custom-Header': 'value'
}
});Common Patterns
Customer Registration Flow
async function registerCustomer(email, password, name) {
// Check if email already exists
const query = new Nimbu.Query('customers');
query.equalTo('email', email.toLowerCase());
const existing = await query.first();
if (existing) {
throw new Error('Email already registered');
}
// Create new customer
const customer = new Nimbu.Customer();
customer.set('email', email.toLowerCase());
customer.set('password', password);
customer.set('name', name);
customer.set('active', true);
await customer.save();
// Add to default role
const defaultRole = await new Nimbu.Query('roles')
.equalTo('name', 'Customers')
.first();
if (defaultRole) {
defaultRole.getCustomers().add(customer);
await defaultRole.save();
}
return customer;
}Order Processing
async function processOrder(orderId) {
const order = await new Nimbu.Query('orders').get(orderId);
// Validate stock availability
const items = order.get('items');
for (const item of items) {
const product = await new Nimbu.Query('products').get(item.product_id);
if (product.get('stock') < item.quantity) {
throw new Error(`Insufficient stock for ${product.get('name')}`);
}
}
// Update stock levels
for (const item of items) {
const product = await new Nimbu.Query('products').get(item.product_id);
await product.increment('stock', -item.quantity);
await product.save();
}
// Update order status
order.set('status', 'processing');
order.set('processed_at', new Date());
await order.save();
return order;
}File Upload with Validation
async function uploadDocument(fileData, metadata) {
// Validate file type
const allowedTypes = ['application/pdf', 'image/jpeg', 'image/png'];
if (!allowedTypes.includes(fileData.contentType)) {
throw new Error('Invalid file type');
}
// Validate file size (5MB max)
const maxSize = 5 * 1024 * 1024;
if (fileData.size > maxSize) {
throw new Error('File too large');
}
// Upload file
const file = new Nimbu.File(fileData);
await file.save();
// Create document record
const document = new Nimbu.Object('documents');
document.set('title', metadata.title);
document.set('description', metadata.description);
document.set('file', file);
document.set('uploaded_by', metadata.uploadedBy);
await document.save();
return {
id: document.id,
url: file.url()
};
}Best Practices
1. Use Specialized Classes When Available
// Good: Use specialized class
const customer = new Nimbu.Customer();
// Avoid: Generic object for specialized types
const customer = new Nimbu.Object('customers');2. Include Relations to Avoid N+1 Queries
// Good: Include related data
const query = new Nimbu.Query('orders');
query.include('customer');
query.include('products');
const orders = await query.collection().fetch();
// Avoid: Fetching relations separately
const orders = await query.collection().fetch();
for (const order of orders) {
const customer = await order.get('customer').fetch(); // N+1 query!
}3. Validate Data Before Saving
// Good: Validate before save
if (!email || !email.includes('@')) {
throw new Error('Invalid email');
}
await customer.save();
// Avoid: Saving without validation
await customer.save(); // May fail with unclear error4. Handle Errors Gracefully
// Good: Error handling
try {
await order.save();
} catch (error) {
console.error('Failed to save order:', error.message);
// Handle error appropriately
}
// Avoid: No error handling
await order.save(); // Unhandled errorsNext Steps
- Review Nimbu.Object - Base class fundamentals
- Review Nimbu.Query - Query patterns
- Explore Callbacks - React to data changes
- Check Cloud Functions - Use SDK in functions