Key Concepts
Understanding these fundamental concepts will help you write effective Cloud Code.
File Structure
A typical Cloud Code project has a simple structure:
your-cloud-code/
├── main.js # Main entry point (required)
├── lib/ # Optional: reusable modules
│ ├── helpers.js
│ └── validators.js
└── config/ # Optional: configuration files
└── constants.jsMain Entry Point
The main.js file is where you register all your Cloud Code handlers:
// main.js
// Register callbacks
Nimbu.Cloud.before('created', 'customers', validateCustomer);
// Register functions
Nimbu.Cloud.define('calculateTotal', calculateOrderTotal);
// Register routes
Nimbu.Cloud.get('/api/products', listProducts);
// Register jobs
Nimbu.Cloud.job('daily_cleanup', cleanupOldData);
// Schedule recurring jobs
Nimbu.Cloud.schedule('daily_cleanup', {}, {
every: '0 2 * * *' // Daily at 2 AM
});
Organizing Your Code
For larger projects, split your code into multiple files:
// main.js
const validators = require('lib/validators');
const helpers = require('lib/helpers');
Nimbu.Cloud.before('created', 'orders', validators.validateOrder);
Nimbu.Cloud.define('formatPrice', helpers.formatPrice);// lib/validators.js
exports.validateOrder = (req, res) => {
// Validation logic
};// lib/helpers.js
exports.formatPrice = (req, res) => {
// Formatting logic
};Module System
Cloud Code uses a require() function to load modules. You can require:
- Native Nimbu modules - Built-in modules like
http,mail,crypto - Your own files - Custom JavaScript files in your project
Requiring Native Modules
Native modules are available through the require() function:
const HTTP = require('http');
const Mail = require('mail');
const Crypto = require('crypto');Requiring Your Own Files
Load your own JavaScript files using relative or absolute paths:
// Relative path from main.js
const helpers = require('lib/helpers');
// Files must export functions/objects
// lib/helpers.js:
exports.formatDate = (date) => {
// formatting logic
};Available Native Modules
Cloud Code provides many built-in modules for common tasks. Here's an overview organized by category:
Encoding & Data Formats
| Module | Purpose | Example |
|---|---|---|
atob | Base64 decode | atob.decode('SGVsbG8=') |
btoa | Base64 encode | btoa.encode('Hello') |
crypto | Cryptographic operations | Crypto.createHash('sha256') |
csv | Parse and generate CSV files | Csv.parse(csvString) |
xml | XML parsing and generation | Xml.parse(xmlString) |
zip | Create ZIP archives | Zip.create([{filename, contents}]) |
jwt | JSON Web Token operations | Jwt.encode(payload, secret) |
External Communication
| Module | Purpose | Example |
|---|---|---|
http | Make HTTP requests | HTTP.get(url) |
mail | Send emails | Mail.send({to, subject, text}) |
soap | SOAP web service calls | Soap.call(wsdl, operation, message) |
oauth2 | OAuth2 authentication | OAuth2.getToken(options) |
Cloud Storage
| Module | Purpose | Example |
|---|---|---|
s3 | AWS S3 operations | S3.generate_upload_url(options) |
azure | Azure Blob storage | Azure.generate_sas(options) |
Payment Integrations
| Module | Purpose | Example |
|---|---|---|
mollie | Mollie payment API | Mollie.createPayment(params) |
stripe | Stripe payment API | Stripe.createCheckoutSession(params) |
Content & Media
| Module | Purpose | Example |
|---|---|---|
pdf | Generate PDF files | Pdf.render(html, options) |
imgkit | Image manipulation | Image processing operations |
html | HTML sanitization | Html.strip_html(text) |
Nimbu-Specific
| Module | Purpose | Example |
|---|---|---|
site_variables | Access site environment variables | SiteVariables.get('API_KEY') |
order_helpers | Order processing utilities | OrderHelpers.queueAttachmentProcessing(order) |
i18n | Internationalization | I18n.t('key', variables) |
signer | HMAC signing | Signer.sign(data, secret) |
Utilities
| Module | Purpose | Example |
|---|---|---|
fs | Read bundled files | Fs.readFileSync('config/data.json') |
gc | Garbage collection | Gc.run() |
googleauth | Google service account auth | Googleauth.token(scope) |
Common Module Usage Examples
Making HTTP Requests
const HTTP = require('http');
// GET request
const response = await HTTP.get('https://api.example.com/data');
console.log(response.body);
// POST request
const result = await HTTP.post('https://api.example.com/submit', {
body: JSON.stringify({ name: 'John' }),
headers: { 'Content-Type': 'application/json' }
});Sending Emails
const Mail = require('mail');
// Simple email
await Mail.send({
to: '[email protected]',
subject: 'Welcome!',
text: 'Thanks for signing up!'
});
// Template-based email
await Mail.send({
to: '[email protected]',
template: 'welcome_email',
variables: {
name: 'John Doe',
confirmationUrl: 'https://...'
}
});Cryptographic Operations
const Crypto = require('crypto');
// Generate hash
const hash = Crypto.calculate_hash({
data: 'sensitive data',
algorithm: 'sha256',
digest: 'hex'
});
// Generate HMAC
const hmac = Crypto.calculate_hmac({
data: 'message',
key: 'secret',
algorithm: 'sha256',
digest: 'hex'
});Working with CSV
const Csv = require('csv');
// Parse CSV
const data = Csv.parse(csvString, {
headers: true,
delimiter: ','
});
// Generate CSV
const csv = Csv.to_csv([
['Name', 'Email'],
['John Doe', '[email protected]'],
['Jane Smith', '[email protected]']
]);Site Environment Variables
const SiteVariables = require('site_variables');
// Get a variable
const apiKey = SiteVariables.get('STRIPE_API_KEY');
// Check if a variable exists
if (SiteVariables.has('MAILCHIMP_KEY')) {
// Use the key
}
// Get all variable names
const keys = SiteVariables.keys();Console Logging
Use standard console methods for debugging:
console.log('Info message');
console.info('Information');
console.warn('Warning message');
console.error('Error occurred');
console.debug('Debug information');All console output is captured in the Cloud Code logs, which you can view in the Nimbu admin interface.
Logging Best Practices
// Log at the start of handlers
console.log('[Job: send_newsletter] Starting execution');
// Log important data
console.log('Processing order:', order.id);
// Log errors with context
try {
await someOperation();
} catch (error) {
console.error('Operation failed:', error.message);
throw error;
}
// Log completion
console.log('[Job: send_newsletter] Completed successfully');Runtime Environment
JavaScript Support
Cloud Code runs on a V8 JavaScript engine with full modern JavaScript support:
- ES6+ features - arrow functions, template literals, destructuring, etc.
- async/await - Full support for asynchronous operations
- Promises - Native Promise support
- Classes - ES6 class syntax
// Modern JavaScript is fully supported
const processOrder = async (order) => {
const { items, customer } = order;
const total = items.reduce((sum, item) => sum + item.price, 0);
await customer.set('total_spent', total);
await customer.save();
};Execution Limits
To ensure fair resource usage, Cloud Code has execution limits:
Timeout limits - Handlers must complete within allocated time
- Callbacks: ~5 seconds
- Functions: ~10 seconds
- Routes: ~30 seconds
- Jobs: ~5 minutes
Memory limits - Reasonable memory usage expected
Network timeouts - HTTP requests timeout after 30 seconds
What's NOT Available
Unlike Node.js, Cloud Code runs in a sandboxed environment. Some Node.js features are not available:
- ❌ File system access (except reading your own bundled files with
fsmodule) - ❌ Installing npm packages
- ❌ Direct database connections
- ❌ Child processes
- ❌ Most Node.js built-in modules
Instead, use:
- ✅ Nimbu SDK for data operations
- ✅ Built-in HTTP module for external APIs
- ✅ Built-in modules for common tasks
Best Practices
1. Keep Code Organized
// Good: Organized into modules
const validators = require('lib/validators');
Nimbu.Cloud.before('created', 'orders', validators.validateOrder);
// Avoid: Everything in main.js
Nimbu.Cloud.before('created', 'orders', (req, res) => {
// 100 lines of validation logic here...
});2. Use Environment Variables for Secrets
// Good: Use site variables
const SiteVariables = require('site_variables');
const apiKey = SiteVariables.get('STRIPE_API_KEY');
// Avoid: Hard-coded secrets
const apiKey = 'sk_live_abc123...'; // Never do this!3. Handle Errors Gracefully
// Good: Proper error handling
try {
await HTTP.post(webhookUrl, data);
res.success();
} catch (error) {
console.error('Webhook failed:', error.message);
res.error('Failed to send webhook');
}
// Avoid: Unhandled errors
await HTTP.post(webhookUrl, data); // Might crash4. Log Meaningful Information
// Good: Contextual logging
console.log('[Newsletter] Sending to', customer.get('email'));
// Avoid: Generic logging
console.log('Doing stuff'); // Not helpful for debugging5. Use Async/Await
// Good: Modern async/await
const customers = await query.collection().fetch();
for (const customer of customers) {
await sendEmail(customer);
}
// Avoid: Callback hell
query.collection().fetch().then(customers => {
customers.forEach(customer => {
sendEmail(customer).then(() => {
// nested callbacks...
});
});
});Next Steps
Now that you understand the basics, explore specific Cloud Code features:
- Callbacks - React to data changes
- Cloud Functions - Create callable server-side functions
- Routes - Build custom HTTP endpoints
- Extensions - Add custom admin actions
- Background Jobs - Schedule automated tasks
- Available Modules - Complete module reference