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 handlerfunction 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 documentsapp.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 documentapp.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 documentapp.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 documentapp.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 ZIPapp.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');