"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SalesforceRestClient = void 0;
const logger_1 = __importDefault(require("../utils/logger"));
const errorHandler_1 = require("../utils/errorHandler");
const rateLimiter_1 = require("../utils/rateLimiter");
class SalesforceRestClient {
constructor(connection, rateLimitConfig) {
this.conn = null;
this.describeCache = new Map();
this.CACHE_TTL = 1000 * 60 * 60; // 1 hour
this.connection = connection;
const defaultConfig = {
maxRequestsPerSecond: 10,
maxRequestsPerHour: 5000,
retryAttempts: 3,
baseDelay: 1000
};
this.rateLimiter = new rateLimiter_1.RateLimiter(rateLimitConfig || defaultConfig);
}
async authenticate() {
try {
const username = process.env.SF_USERNAME;
const password = process.env.SF_PASSWORD;
const securityToken = process.env.SF_SECURITY_TOKEN;
if (!username || !password || !securityToken) {
throw new errorHandler_1.AppError('Missing Salesforce credentials', 400);
}
this.conn = await this.connection.connectWithOAuth(username, password, securityToken);
logger_1.default.info('Successfully authenticated with Salesforce for REST API');
}
catch (error) {
logger_1.default.error('Failed to authenticate with Salesforce', { error });
throw new errorHandler_1.AppError('Salesforce authentication failed', 401);
}
}
async describeSObject(objectName) {
if (!this.conn) {
throw new errorHandler_1.AppError('Not authenticated', 401);
}
// Check cache first
const cacheKey = `describe:${objectName}`;
const cached = this.describeCache.get(cacheKey);
if (cached && cached.expiry > Date.now()) {
logger_1.default.debug('Returning cached describe result', { objectName });
return cached.data;
}
try {
logger_1.default.debug('Describing SObject', { objectName });
const result = await this.rateLimiter.executeWithRateLimit(async () => {
return await this.conn.describe(objectName);
});
// Cache the result
this.describeCache.set(cacheKey, {
data: result,
expiry: Date.now() + this.CACHE_TTL
});
logger_1.default.debug('SObject describe completed', { objectName, fieldCount: result.fields?.length });
return result;
}
catch (error) {
logger_1.default.error('Failed to describe SObject', { error, objectName });
throw new errorHandler_1.AppError(`Failed to describe ${objectName}`, 500);
}
}
async describeGlobal() {
if (!this.conn) {
throw new errorHandler_1.AppError('Not authenticated', 401);
}
// Check cache first
const cacheKey = 'describe:global';
const cached = this.describeCache.get(cacheKey);
if (cached && cached.expiry > Date.now()) {
logger_1.default.debug('Returning cached global describe result');
return cached.data;
}
try {
logger_1.default.debug('Executing global describe');
const result = await this.rateLimiter.executeWithRateLimit(async () => {
return await this.conn.describeGlobal();
});
// Cache the result
this.describeCache.set(cacheKey, {
data: result,
expiry: Date.now() + this.CACHE_TTL
});
logger_1.default.debug('Global describe completed', { objectCount: result.sobjects?.length });
return result;
}
catch (error) {
logger_1.default.error('Failed to execute global describe', { error });
throw new errorHandler_1.AppError('Global describe failed', 500);
}
}
async executeSoql(soql) {
if (!this.conn) {
throw new errorHandler_1.AppError('Not authenticated', 401);
}
try {
logger_1.default.debug('Executing SOQL query', { soql });
const result = await this.rateLimiter.executeWithRateLimit(async () => {
return await this.conn.query(soql);
});
logger_1.default.debug('SOQL query completed', { recordCount: result.records?.length || 0 });
return result;
}
catch (error) {
logger_1.default.error('Failed to execute SOQL query', { error, soql });
throw new errorHandler_1.AppError('SOQL query failed', 500);
}
}
clearCache() {
this.describeCache.clear();
logger_1.default.info('Describe cache cleared');
}
getCacheStats() {
return {
cacheSize: this.describeCache.size,
rateLimitStats: this.rateLimiter.getStats()
};
}
}
exports.SalesforceRestClient = SalesforceRestClient;