Skip to content

Examples

End-to-end examples showing how to use the SDK in real-world scenarios.

Node.js / Express Backend

A complete Express.js server that proxies SDK operations:

import express from 'express';
import multer from 'multer';
import { SonarSDK, SonarSDKError } from '@sonar/sdk';
const app = express();
const upload = multer();
const sdk = new SonarSDK({
apiKey: process.env.SONAR_API_KEY!,
instanceName: process.env.SONAR_INSTANCE!,
});
// Error handler
function handleError(res: express.Response, err: unknown) {
if (err instanceof SonarSDKError) {
res.status(err.status || 500).json({
error: err.message,
code: err.code,
requestId: err.requestId,
});
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
// List documents
app.get('/api/documents', async (req, res) => {
try {
const { page, limit, classification } = req.query;
const docs = await sdk.documents.list({
page: page ? Number(page) : undefined,
limit: limit ? Number(limit) : undefined,
classification: classification as any,
});
res.json(docs);
} catch (err) {
handleError(res, err);
}
});
// Download document
app.get('/api/documents/:id/download', async (req, res) => {
try {
const { data, filename, contentType } = await sdk.documents.download(req.params.id);
res.setHeader('Content-Type', contentType);
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
res.send(Buffer.from(data));
} catch (err) {
handleError(res, err);
}
});
// Upload document
app.post('/api/documents/upload', upload.single('document'), async (req, res) => {
try {
const doc = await sdk.documents.upload({
file: req.file!.buffer,
filename: req.file!.originalname,
contentType: req.file!.mimetype,
name: req.body.name,
uploadFrom: req.body.uploadFrom || 'user-documents',
classification: req.body.classification || 'uploaded',
});
res.json(doc);
} catch (err) {
handleError(res, err);
}
});
// Delete a document
app.delete('/api/documents/:id', async (req, res) => {
try {
const result = await sdk.documents.delete(req.params.id);
res.json(result);
} catch (err) {
handleError(res, err);
}
});
// Export documents as ZIP
app.post('/api/documents/export', express.json(), async (req, res) => {
try {
const { data, filename, contentType } = await sdk.documents.export({
documentIds: req.body.documentIds,
});
res.setHeader('Content-Type', contentType);
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
res.send(Buffer.from(data));
} catch (err) {
handleError(res, err);
}
});
app.listen(3001, () => console.log('Server running on port 3001'));

Scope-Based UI Rendering (React)

import { useEffect, useState, createContext, useContext } from 'react';
const ScopesContext = createContext({ scopes: [], hasScope: () => false, loading: true });
function ScopesProvider({ children }) {
const [scopes, setScopes] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/scopes')
.then(res => res.json())
.then(data => {
setScopes(data.scopes || []);
setLoading(false);
});
}, []);
const hasScope = (scope) => scopes.includes(scope);
return (
<ScopesContext.Provider value={{ scopes, hasScope, loading }}>
{children}
</ScopesContext.Provider>
);
}
function DocumentActions({ documentId }) {
const { hasScope } = useContext(ScopesContext);
return (
<div>
{hasScope('documents:uploaded:read') && (
<button onClick={() => viewDocument(documentId)}>View</button>
)}
{hasScope('documents:uploaded:export') && (
<button onClick={() => downloadDocument(documentId)}>Download</button>
)}
{hasScope('documents:uploaded:delete') && (
<button onClick={() => deleteDocument(documentId)}>Delete</button>
)}
</div>
);
}

Document Migration Script

import { SonarSDK } from '@sonar/sdk';
import { readFileSync, readdirSync } from 'fs';
import { join, extname, basename } from 'path';
import { lookup } from 'mime-types';
const sdk = new SonarSDK({
apiKey: process.env.SONAR_API_KEY!,
instanceName: 'production',
});
async function migrateDocuments(directory: string) {
const files = readdirSync(directory);
const results = { success: 0, failed: 0, errors: [] };
for (const file of files) {
const filePath = join(directory, file);
const contentType = lookup(extname(file)) || 'application/octet-stream';
try {
const buffer = readFileSync(filePath);
const doc = await sdk.documents.upload({
file: buffer,
filename: file,
contentType,
name: basename(file, extname(file)),
uploadFrom: 'user-documents',
classification: 'uploaded',
});
console.log(`Uploaded: ${file}${doc.id}`);
results.success++;
} catch (err) {
console.error(`Failed: ${file}${err.message}`);
results.failed++;
results.errors.push({ file, error: err.message });
}
}
console.log(`\nMigration complete: ${results.success} uploaded, ${results.failed} failed`);
return results;
}
migrateDocuments('./documents-to-migrate');