Skip to content

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.js

Main Entry Point

The main.js file is where you register all your Cloud Code handlers:

js
// 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:

js
// 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);
js
// lib/validators.js
exports.validateOrder = (req, res) => {
  // Validation logic
};
js
// lib/helpers.js
exports.formatPrice = (req, res) => {
  // Formatting logic
};

Module System

Cloud Code uses a require() function to load modules. You can require:

  1. Native Nimbu modules - Built-in modules like http, mail, crypto
  2. Your own files - Custom JavaScript files in your project

Requiring Native Modules

Native modules are available through the require() function:

js
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:

js
// 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

ModulePurposeExample
atobBase64 decodeatob.decode('SGVsbG8=')
btoaBase64 encodebtoa.encode('Hello')
cryptoCryptographic operationsCrypto.createHash('sha256')
csvParse and generate CSV filesCsv.parse(csvString)
xmlXML parsing and generationXml.parse(xmlString)
zipCreate ZIP archivesZip.create([{filename, contents}])
jwtJSON Web Token operationsJwt.encode(payload, secret)

External Communication

ModulePurposeExample
httpMake HTTP requestsHTTP.get(url)
mailSend emailsMail.send({to, subject, text})
soapSOAP web service callsSoap.call(wsdl, operation, message)
oauth2OAuth2 authenticationOAuth2.getToken(options)

Cloud Storage

ModulePurposeExample
s3AWS S3 operationsS3.generate_upload_url(options)
azureAzure Blob storageAzure.generate_sas(options)

Payment Integrations

ModulePurposeExample
mollieMollie payment APIMollie.createPayment(params)
stripeStripe payment APIStripe.createCheckoutSession(params)

Content & Media

ModulePurposeExample
pdfGenerate PDF filesPdf.render(html, options)
imgkitImage manipulationImage processing operations
htmlHTML sanitizationHtml.strip_html(text)

Nimbu-Specific

ModulePurposeExample
site_variablesAccess site environment variablesSiteVariables.get('API_KEY')
order_helpersOrder processing utilitiesOrderHelpers.queueAttachmentProcessing(order)
i18nInternationalizationI18n.t('key', variables)
signerHMAC signingSigner.sign(data, secret)

Utilities

ModulePurposeExample
fsRead bundled filesFs.readFileSync('config/data.json')
gcGarbage collectionGc.run()
googleauthGoogle service account authGoogleauth.token(scope)

Common Module Usage Examples

Making HTTP Requests

js
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

js
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

js
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

js
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

js
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:

js
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

js
// 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
js
// 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 fs module)
  • ❌ 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

js
// 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

js
// 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

js
// 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 crash

4. Log Meaningful Information

js
// Good: Contextual logging
console.log('[Newsletter] Sending to', customer.get('email'));

// Avoid: Generic logging
console.log('Doing stuff'); // Not helpful for debugging

5. Use Async/Await

js
// 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: