@zudello/sdk
v0.1.1
Published
TypeScript SDK for Zudello API
Readme
@zudello/sdk
TypeScript SDK for the Zudello API.
Installation
npm install @zudello/sdkQuick Start
import { ZudelloClient, MODELS, MODULES, SUBMODULES } from '@zudello/sdk';
// Zero-config: reads from environment variables
const client = new ZudelloClient();
// Search for pending invoices
const invoices = await client.search.query({
model: MODELS.Transaction,
module: MODULES.PURCHASING,
submodule: SUBMODULES.INVOICE,
filter: { status: 'REVIEW', total__gt: 1000 },
select: ['uuid', 'document_number', 'total', 'status']
});
console.log(`Found ${invoices.metadata?.count} invoices`);
for (const invoice of invoices.data ?? []) {
console.log(`${invoice.document_number}: $${invoice.total}`);
}Environment Variables
The SDK reads configuration from environment variables by default:
| Variable | Required | Description |
|----------|----------|-------------|
| ZUDELLO_TOKEN | Yes | Authentication token |
| ZUDELLO_ORG_ID | Yes | Organization UUID |
| ZUDELLO_TEAM_ID | Yes | Team UUID |
| ZUDELLO_CLUSTER_URL | Yes | API cluster URL (e.g., api.1.global.zudello.io) |
| ZUDELLO_AUTH_API_BASE | Yes | Auth API base URL |
| ZUDELLO_USER_ID | No | User UUID |
| ZUDELLO_USER_EMAIL | No | User email |
Core Operations
Search
Search for resources with filtering and pagination:
const invoices = await client.search.query({
model: 'Transaction',
module: 'PURCHASING',
submodule: 'INVOICE',
filter: {
status__in: ['REVIEW', 'APPROVAL'],
total__gt: 1000,
supplier__trading_name__icontains: 'acme'
},
select: ['uuid', 'document_number', 'total', 'date_due'],
order_by: ['-total', 'date_due'],
limit: 50
});Auto-Pagination with Async Iterators
Iterate over all matching records automatically:
let totalValue = 0;
for await (const invoice of client.search.list({
model: 'Transaction',
module: 'PURCHASING',
submodule: 'INVOICE',
filter: { status: 'APPROVAL' },
select: ['uuid', 'document_number', 'total', 'status']
})) {
totalValue += invoice.total;
console.log(`${invoice.document_number}: $${invoice.total}`);
}
console.log(`Total pending approval: $${totalValue}`);Fetch Single Resource
const supplier = await client.search.fetch('Supplier', { uuid: 'supplier-uuid-123' });
console.log(supplier.data?.trading_name);
// With related data
const invoice = await client.search.fetch('Transaction', { uuid: 'invoice-uuid' }, {
includeModels: 'supplier,lines,attachments'
});Create Resource
const newPO = await client.resources.create({
model: 'Transaction',
module: 'PURCHASING',
submodule: 'ORDER',
data: {
supplier: 'supplier-uuid',
lines: [
{ description: 'Item 1', quantity: 10, unit_price: 99.99 }
]
}
});Update Resource
const updated = await client.resources.update({
model: 'Transaction',
uuid: 'invoice-uuid',
data: { status: 'READY' }
});Filter Operators
Append these suffixes to field names:
__in- Value in list:status__in: ['REVIEW', 'APPROVAL']__gt,__gte- Greater than (or equal):total__gt: 1000__lt,__lte- Less than (or equal):total__lt: 5000__range- Value in range:total__range: [1000, 5000]__icontains- Case-insensitive contains:trading_name__icontains: 'acme'__startswith- Starts with:document_number__startswith: 'INV'__isnull- Is null check:supplier__isnull: false
Error Handling
import {
ZudelloClient,
ZudelloAuthenticationError,
ZudelloValidationError,
ZudelloAPIError
} from '@zudello/sdk';
try {
const result = await client.search.query({ model: 'Transaction' });
} catch (error) {
if (error instanceof ZudelloAuthenticationError) {
console.log('Token expired or invalid');
} else if (error instanceof ZudelloValidationError) {
console.log('Invalid request:', error.message);
} else if (error instanceof ZudelloAPIError) {
console.log(`API error ${error.statusCode}:`, error.message);
}
}Model Introspection
// List all available models
const models = await client.models.list();
// Get schema for a model
const schema = await client.models.getSchema('Transaction');
console.log('Fields:', Object.keys(schema.fields ?? {}));
// Get field metadata
const fields = await client.models.getFieldMetadata({
module: 'PURCHASING',
submodule: 'INVOICE',
section: 'filters'
});Type-Safe Constants
Use exported constants for type safety:
import { MODELS, MODULES, SUBMODULES, STATUS_KEYS } from '@zudello/sdk';
const invoices = await client.search.query({
model: MODELS.Transaction,
module: MODULES.PURCHASING,
submodule: SUBMODULES.INVOICE,
filter: { status: STATUS_KEYS.REVIEW }
});License
MIT © Zudello Pty Ltd
