Skip to main content

Node.js SDK Tutorial

This tutorial will guide you through using the Cloakr.ai SDK in Node.js applications, from basic setup to advanced features.

Installation

Prerequisites

  • Node.js 18+
  • npm, yarn, or pnpm

Install the SDK

npm install @cloakrai/sdk

TypeScript Support

The SDK includes full TypeScript support. If you're using TypeScript, no additional types need to be installed.

Basic Setup

Initialize the Client

import { CloakrClient } from '@cloakrai/sdk';

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
// Optional configuration
encryption: true,
piiDetection: true,
retryAttempts: 3,
timeout: 30000
});

Environment Variables

Create a .env file in your project root:

CLOAKR_API_KEY=your-api-key-here
CLOAKR_ENCRYPTION_KEY=your-encryption-key-here # Optional
CLOAKR_KEY_ID=your-key-id-here # Optional

Load environment variables:

import dotenv from 'dotenv';
dotenv.config();

Basic Usage

Simple Chat Request

import { CloakrClient } from '@cloakrai/sdk';

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY
});

async function simpleChat() {
try {
const response = await client.chat({
model: 'gpt-4o',
prompt: 'What is Cloakr.ai?',
maxTokens: 1000,
temperature: 0.7
});

console.log(response.choices[0].text);
} catch (error) {
console.error('Error:', error.message);
}
}

simpleChat();

Streaming Responses

async function streamingChat() {
try {
const stream = await client.chat({
model: 'gpt-4o',
prompt: 'Write a story about AI security',
stream: true
});

for await (const chunk of stream) {
if (chunk.choices[0].delta?.text) {
process.stdout.write(chunk.choices[0].delta.text);
}
}
} catch (error) {
console.error('Error:', error.message);
}
}

Advanced Features

Custom PII Redaction

import { CloakrClient, PIIRedactor } from '@cloakrai/sdk';

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
piiDetection: true
});

// Custom redaction rules
const customRedactor = new PIIRedactor({
rules: [
{
type: 'custom_pattern',
pattern: /CUSTOMER-\d{6}/g,
replacement: '[REDACTED_CUSTOMER_ID]'
},
{
type: 'email',
domains: ['internal.com', 'test.com']
}
]
});

client.setPIIRedactor(customRedactor);

Encryption Configuration

import { CloakrClient, EncryptionConfig } from '@cloakrai/sdk';

const encryptionConfig = new EncryptionConfig({
algorithm: 'AES-256-GCM',
keyId: process.env.CLOAKR_KEY_ID,
keyRotation: true,
compression: true
});

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
encryption: encryptionConfig
});

Retry Logic with Exponential Backoff

import { CloakrClient, RetryConfig } from '@cloakrai/sdk';

const retryConfig = new RetryConfig({
maxAttempts: 5,
baseDelay: 1000,
maxDelay: 30000,
backoffMultiplier: 2,
retryableErrors: ['rate_limit_exceeded', 'internal_error']
});

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
retry: retryConfig
});

Error Handling

Comprehensive Error Handling

import { CloakrClient, CloakrError } from '@cloakrai/sdk';

async function robustChat() {
try {
const response = await client.chat({
model: 'gpt-4o',
prompt: 'Hello world'
});

return response;
} catch (error) {
if (error instanceof CloakrError) {
switch (error.code) {
case 'rate_limit_exceeded':
console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
// Implement retry logic
break;

case 'invalid_api_key':
console.error('Invalid API key. Check your configuration.');
break;

case 'content_policy_violation':
console.error('Content violates usage policies:', error.details);
break;

default:
console.error('Unexpected error:', error.message);
}
} else {
console.error('Network or other error:', error.message);
}

throw error;
}
}

Custom Error Handler

class CustomErrorHandler {
static async handle(error, context) {
console.error('Cloakr Error:', {
code: error.code,
message: error.message,
context: context,
timestamp: new Date().toISOString()
});

// Log to external service
await this.logToExternalService(error, context);

// Notify team if critical
if (error.code === 'internal_error') {
await this.notifyTeam(error, context);
}
}

static async logToExternalService(error, context) {
// Implementation for external logging
}

static async notifyTeam(error, context) {
// Implementation for team notification
}
}

Performance Optimization

Connection Pooling

import { CloakrClient, ConnectionPool } from '@cloakrai/sdk';

const pool = new ConnectionPool({
maxConnections: 10,
maxIdleTime: 30000,
connectionTimeout: 5000
});

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
connectionPool: pool
});

Request Batching

async function batchRequests(prompts) {
const batchSize = 5;
const results = [];

for (let i = 0; i < prompts.length; i += batchSize) {
const batch = prompts.slice(i, i + batchSize);
const batchPromises = batch.map(prompt =>
client.chat({
model: 'gpt-4o',
prompt: prompt
})
);

const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
}

return results;
}

Caching

import { CloakrClient, CacheManager } from '@cloakrai/sdk';

const cache = new CacheManager({
ttl: 3600, // 1 hour
maxSize: 1000,
strategy: 'lru'
});

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
cache: cache
});

// Cache key based on request parameters
const cacheKey = `chat:${model}:${hash(prompt)}`;

Testing

Unit Tests with Jest

import { CloakrClient } from '@cloakrai/sdk';

// Mock the client for testing
jest.mock('@cloakrai/sdk');

describe('Chat Service', () => {
let client;

beforeEach(() => {
client = new CloakrClient({
apiKey: 'test-key'
});
});

test('should handle successful chat request', async () => {
const mockResponse = {
choices: [{ text: 'Mock response' }]
};

client.chat.mockResolvedValue(mockResponse);

const result = await client.chat({
model: 'gpt-4o',
prompt: 'Test prompt'
});

expect(result.choices[0].text).toBe('Mock response');
});

test('should handle rate limit errors', async () => {
const mockError = new Error('Rate limit exceeded');
mockError.code = 'rate_limit_exceeded';
mockError.retryAfter = 60;

client.chat.mockRejectedValue(mockError);

await expect(client.chat({
model: 'gpt-4o',
prompt: 'Test prompt'
})).rejects.toThrow('Rate limit exceeded');
});
});

Integration Tests

import { CloakrClient } from '@cloakrai/sdk';

describe('Cloakr Integration', () => {
let client;

beforeAll(() => {
client = new CloakrClient({
apiKey: process.env.CLOAKR_TEST_API_KEY
});
});

test('should complete a chat request', async () => {
const response = await client.chat({
model: 'gpt-4o',
prompt: 'Hello, this is a test',
maxTokens: 50
});

expect(response).toHaveProperty('choices');
expect(response.choices[0]).toHaveProperty('text');
expect(response.choices[0].text).toBeTruthy();
});
});

Production Best Practices

Environment Configuration

// config/cloakr.js
const config = {
development: {
apiKey: process.env.CLOAKR_DEV_API_KEY,
encryption: false,
retryAttempts: 1
},
production: {
apiKey: process.env.CLOAKR_PROD_API_KEY,
encryption: true,
retryAttempts: 3,
timeout: 30000
}
};

export const cloakrConfig = config[process.env.NODE_ENV] || config.development;

Monitoring and Logging

import { CloakrClient, MetricsCollector } from '@cloakrai/sdk';

const metrics = new MetricsCollector({
enabled: process.env.NODE_ENV === 'production',
endpoint: process.env.METRICS_ENDPOINT
});

const client = new CloakrClient({
apiKey: process.env.CLOAKR_API_KEY,
metrics: metrics
});

// Custom metrics
client.on('request', (data) => {
metrics.increment('cloakr.requests.total');
metrics.timing('cloakr.requests.duration', data.duration);
});

client.on('error', (error) => {
metrics.increment('cloakr.errors.total');
metrics.increment(`cloakr.errors.${error.code}`);
});

Security Considerations

// Validate API key format
function validateApiKey(apiKey) {
if (!apiKey || typeof apiKey !== 'string') {
throw new Error('API key must be a non-empty string');
}

if (!apiKey.startsWith('cloakr_')) {
throw new Error('Invalid API key format');
}

return apiKey;
}

// Secure client initialization
const client = new CloakrClient({
apiKey: validateApiKey(process.env.CLOAKR_API_KEY),
encryption: true,
piiDetection: true
});

Next Steps