@centrali-io/centrali-sdk
v2.1.7
Published
Centrali Node SDK
Readme
Centrali JavaScript/TypeScript SDK
Official Node.js SDK for Centrali - Build modern web applications without managing infrastructure.
Installation
npm install @centrali-io/centrali-sdkQuick Start
import { CentraliSDK } from '@centrali-io/centrali-sdk';
// Initialize the SDK
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'your-workspace',
token: 'your-api-key'
});
// Create a record
const product = await centrali.createRecord('Product', {
name: 'Awesome Product',
price: 99.99,
inStock: true
});
console.log('Created product:', product.data);
// Invoke a compute function
const result = await centrali.invokeFunction('calculate-discount', {
productId: product.id,
couponCode: 'SAVE20'
});
console.log('Discount result:', result.data);Authentication
The SDK supports two authentication methods:
Bearer Token (User Authentication)
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'your-workspace',
token: 'your-jwt-token'
});Service Account (Server-to-Server)
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'your-workspace',
clientId: process.env.CENTRALI_CLIENT_ID,
clientSecret: process.env.CENTRALI_CLIENT_SECRET
});
// The SDK automatically fetches and manages tokensFeatures
- ✅ Type-safe API with full TypeScript support
- ✅ Automatic authentication and token management
- ✅ Records management - Create, read, update, delete records
- ✅ Query operations - Powerful data querying with filters and sorting
- ✅ Realtime events - Subscribe to record changes via SSE
- ✅ Compute functions - Execute serverless functions
- ✅ File uploads - Upload files to Centrali storage
- ✅ Service accounts - Automatic token refresh for server-to-server auth
Core Operations
Records
// Create a record
const record = await centrali.createRecord('StructureName', {
field1: 'value1',
field2: 123
});
// Get a record
const record = await centrali.getRecord('StructureName', 'record-id');
// Update a record
await centrali.updateRecord('StructureName', 'record-id', {
field1: 'new value'
});
// Delete a record
await centrali.deleteRecord('StructureName', 'record-id');
// Query records
const products = await centrali.queryRecords('Product', {
filter: 'inStock = true AND price < 100',
sort: '-createdAt',
limit: 10
});Realtime Events
Subscribe to record changes in real-time using Server-Sent Events (SSE):
// Subscribe to realtime events
const subscription = centrali.realtime.subscribe({
structures: ['Order'], // Filter by structure (optional)
events: ['record_created', 'record_updated'], // Filter by event type (optional)
filter: 'status = "pending"', // CFL filter expression (optional)
onEvent: (event) => {
console.log('Event received:', event.event);
console.log('Record:', event.recordSlug, event.recordId);
console.log('Data:', event.data);
},
onConnected: () => {
console.log('Connected to realtime service');
},
onDisconnected: (reason) => {
console.log('Disconnected:', reason);
},
onError: (error) => {
console.error('Realtime error:', error.code, error.message);
}
});
// Later: cleanup subscription
subscription.unsubscribe();Initial Sync Pattern
Realtime delivers only new events after connection. For dashboards and lists, always:
- Fetch current records first
- Subscribe to realtime
- Apply diffs while UI shows the snapshot
// 1. Fetch initial data
const orders = await centrali.queryRecords('Order', {
filter: 'status = "pending"'
});
renderOrders(orders.data);
// 2. Subscribe to realtime updates
const subscription = centrali.realtime.subscribe({
structures: ['Order'],
events: ['record_created', 'record_updated', 'record_deleted'],
filter: 'status = "pending"',
onEvent: (event) => {
// 3. Apply updates to UI
switch (event.event) {
case 'record_created':
addOrderToUI(event.data);
break;
case 'record_updated':
updateOrderInUI(event.recordId, event.data);
break;
case 'record_deleted':
removeOrderFromUI(event.recordId);
break;
}
}
});Event Types
| Event | Description |
|-------|-------------|
| record_created | A new record was created |
| record_updated | An existing record was updated |
| record_deleted | A record was deleted |
Reconnection
The SDK automatically reconnects with exponential backoff when connections drop. Configure reconnection behavior:
import { RealtimeManager } from '@centrali-io/centrali-sdk';
const realtime = new RealtimeManager(
'https://centrali.io',
'your-workspace',
() => centrali.getToken(),
{
maxReconnectAttempts: 10, // Default: 10
initialReconnectDelayMs: 1000, // Default: 1000ms
maxReconnectDelayMs: 30000 // Default: 30000ms
}
);Compute Functions
// Execute a function
const result = await centrali.invokeFunction('myFunction', {
data: 'your-input-data'
});File Uploads
// Upload a file
const uploadResult = await centrali.uploadFile(
file,
'folder-name',
true // make publicly accessible
);
console.log('File URL:', uploadResult.data);TypeScript Support
The SDK includes full TypeScript definitions for type-safe development:
interface Product {
name: string;
price: number;
inStock: boolean;
}
const product = await centrali.createRecord<Product>('Product', {
name: 'Laptop',
price: 999.99,
inStock: true
});
// TypeScript knows product.data is of type Product
console.log(product.data.price);Error Handling
try {
const record = await centrali.createRecord('Product', productData);
console.log('Success:', record);
} catch (error) {
if (error.response?.status === 400) {
console.error('Validation error:', error.response.data);
} else if (error.response?.status === 401) {
console.error('Authentication failed');
} else {
console.error('Error:', error.message);
}
}Documentation
📚 Full documentation available at: docs.centrali.io
Examples
Check out complete example applications:
Support
License
ISC © Blueinit
Built with ❤️ by the Centrali team
