@olakai/sdk
Version:
This document demonstrates how to use the Olakai SDK with all its features.
298 lines • 13.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getQueueManager = exports.flushQueue = exports.clearQueue = exports.getQueueSize = void 0;
exports.initClient = initClient;
exports.getConfig = getConfig;
exports.sendToAPI = sendToAPI;
const index_1 = require("./queue/storage/index");
const queue_1 = require("./queue");
const package_json_1 = __importDefault(require("../package.json"));
const utils_1 = require("./utils");
const types_1 = require("./types");
const exceptions_1 = require("./exceptions");
let config;
let isOnline = true; // Default to online for server environments
// Setup online/offline detection for browser environments
function initOnlineDetection() {
if (typeof window !== "undefined" && typeof navigator !== "undefined") {
// Browser environment - use navigator.onLine and window events
isOnline = navigator.onLine;
window.addEventListener("online", () => {
isOnline = true;
// Queue manager will handle processing when online
});
window.addEventListener("offline", () => {
isOnline = false;
});
}
else {
// Server environment - assume always online
// Could be enhanced with network connectivity checks if needed
isOnline = true;
}
(0, utils_1.olakaiLogger)(`Online detection initialized. Status: ${isOnline}`, "info");
}
/**
* Initialize the SDK
* @param apiKey - The API key
* @param domainUrl - The domain URL
* @param options - The extra options for the SDKConfig
* @default options - {
* enableBatching: false,
* batchSize: 10,
* batchTime: 300,
* retries: 4,
* timeout: 30000,
* enableStorage: false,
* storageType: StorageType.AUTO,
* debug: false,
* verbose: false,
* storageKey: "olakai-sdk-queue",
* maxStorageSize: 1000000,
* sanitizePatterns: [],
* version: packageJson.version,
* }
* @throws {URLConfigurationError} if the API URL is not set
* @throws {APIKeyMissingError} if the API key is not set
*/
async function initClient(apiKey, domainUrl, options = {}) {
// Extract known parameters
const configBuilder = new utils_1.ConfigBuilder();
configBuilder.apiKey(apiKey);
configBuilder.monitorEndpoint(`${domainUrl}/api/monitoring/prompt`);
configBuilder.controlEndpoint(`${domainUrl}/api/control/prompt`);
configBuilder.enableBatching(options.enableBatching || false);
configBuilder.batchSize(options.batchSize || 10);
configBuilder.batchTime(options.batchTime || 300);
configBuilder.retries(options.retries || 4);
configBuilder.timeout(options.timeout || 30000);
configBuilder.enableStorage(options.enableStorage || false);
configBuilder.storageKey(options.storageKey || "olakai-sdk-queue");
configBuilder.maxStorageSize(options.maxStorageSize || 1000000);
configBuilder.sanitizePatterns(options.sanitizePatterns || []);
configBuilder.version(options.version || package_json_1.default.version);
configBuilder.debug(options.debug || false);
configBuilder.verbose(options.verbose || false);
configBuilder.storageType(options.storageType || types_1.StorageType.AUTO);
config = configBuilder.build();
// Validate required configuration
if (!config.monitorEndpoint || config.monitorEndpoint === "/api/monitoring/prompt") {
throw new exceptions_1.URLConfigurationError("[Olakai SDK] API URL is not set. Please provide a valid monitorEndpoint in the configuration.");
}
if (!config.controlEndpoint || config.controlEndpoint === "/api/control/prompt") {
throw new exceptions_1.URLConfigurationError("[Olakai SDK] API URL is not set. Please provide a valid controlEndpoint in the configuration.");
}
if (!config.apiKey || config.apiKey.trim() === "") {
throw new exceptions_1.APIKeyMissingError("[Olakai SDK] API key is not set. Please provide a valid apiKey in the configuration.");
}
(0, utils_1.olakaiLogger)(`Config: ${JSON.stringify(config)}`, "info");
// Initialize online detection
initOnlineDetection();
// Initialize storage
const storageType = (0, index_1.isStorageEnabled)(config) ? config.storageType : types_1.StorageType.DISABLED;
(0, index_1.initStorage)(storageType, config.cacheDirectory);
// Initialize queue manager with dependencies
const queueDependencies = {
config,
isOnline: () => isOnline,
sendWithRetry: sendWithRetry
};
const queueManager = await (0, queue_1.initQueueManager)(queueDependencies);
(0, utils_1.olakaiLogger)(`Queue manager initialized successfully`, "info");
}
/**
* Get the current configuration
* @returns The current configuration
* @throws {ConfigNotInitializedError} if the config is not initialized
*/
function getConfig() {
if (!config) {
throw new exceptions_1.ConfigNotInitializedError("[Olakai SDK] Config is not initialized");
}
return config;
}
/**
* Make an API call to the configured endpoint
* @param payload - The payload to send to the endpoint
* @param role - The role of the API call
* @returns A promise that resolves to the API response
* @throws {APIKeyMissingError} if the API key is not set
* @throws {HTTPError} if the API call fails
* @throws {Error} if the internal logic fails
*/
async function makeAPICall(payload, role = "monitoring") {
if (!config.apiKey) {
throw new exceptions_1.APIKeyMissingError("[Olakai SDK] API key is not set");
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
let url = "";
if (role === "monitoring") {
url = config.monitorEndpoint;
}
else if (role === "control") {
url = config.controlEndpoint;
}
(0, utils_1.olakaiLogger)(`Making API call to ${role} endpoint: ${url}`, "info");
try {
const response = await fetch(url, {
method: "POST",
headers: {
"x-api-key": config.apiKey,
},
body: JSON.stringify(payload),
signal: controller.signal,
});
(0, utils_1.olakaiLogger)(`API call response: ${response.status}`, "info");
let responseData = {};
if (role === "monitoring") {
responseData = await response.json();
}
else if (role === "control") {
responseData = await response.json();
}
(0, utils_1.olakaiLogger)(`API response: ${JSON.stringify(responseData)}`, "info");
clearTimeout(timeoutId);
// Handle different status codes for batch operations
if (role === "monitoring") {
responseData = responseData;
if (response.status === types_1.ErrorCode.SUCCESS) {
// All requests succeeded
(0, utils_1.olakaiLogger)(`All batch requests succeeded: ${JSON.stringify(responseData)}`, "info");
return responseData;
}
else if (response.status === types_1.ErrorCode.PARTIAL_SUCCESS) {
// Mixed success/failure (Multi-Status)
(0, utils_1.olakaiLogger)(`Batch requests had mixed results: ${responseData.successCount}/${responseData.totalRequests} succeeded`, "warn");
return responseData; // Note: overall success=true even for partial failures
}
else if (response.status === types_1.ErrorCode.FAILED) {
// All failed or system error
(0, utils_1.olakaiLogger)(`All batch requests failed: ${JSON.stringify(responseData)}`, "error");
throw new Error(`Batch processing failed: ${responseData.message || response.statusText}`);
}
else if (!response.ok) {
// Other error status codes
(0, utils_1.olakaiLogger)(`API call failed: ${JSON.stringify(payload)}`, "info");
(0, utils_1.olakaiLogger)(`Unexpected API response status: ${response.status}`, "warn");
throw new exceptions_1.HTTPError(`HTTP ${response.status}: ${response.statusText}`);
}
else {
// Legacy support for other 2xx status codes
return responseData;
}
}
else if (role === "control") {
responseData = responseData;
if (response.status === types_1.ErrorCode.SUCCESS) {
return responseData;
}
else if (!response.ok) {
// Other error status codes
(0, utils_1.olakaiLogger)(`Unexpected API response status: ${response.status}`, "warn");
throw new exceptions_1.HTTPError(`HTTP ${response.status}: ${response.statusText}`);
}
else {
return responseData;
}
}
}
catch (err) {
clearTimeout(timeoutId);
throw err;
}
throw new Error("[Olakai SDK] Invalid role");
}
/**
* Send a payload to the API with retry logic
* @param payload - The payload to send to the endpoint
* @param maxRetries - The maximum number of retries
* @returns A promise that resolves to an object with success status and details about batch results
*/
async function sendWithRetry(payload, maxRetries = config.retries, role = "monitoring") {
let lastError = null;
let response = {};
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
if (role === "monitoring") {
response = await makeAPICall(payload, "monitoring");
if (response.success) {
return response;
}
else if (response.failureCount && response.failureCount > 0) {
(0, utils_1.olakaiLogger)(`Batch partial success: ${response.successCount}/${response.totalRequests} requests succeeded`, "info");
return response;
}
}
else if (role === "control") {
response = await makeAPICall(payload, "control");
return response;
}
}
catch (err) {
lastError = err;
(0, utils_1.olakaiLogger)(`Attempt ${attempt + 1}/${maxRetries + 1} failed: ${lastError?.message}`, "warn");
if (attempt < maxRetries) {
// Exponential backoff: 1s, 2s, 4s, 8s...
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
await (0, utils_1.sleep)(delay);
}
}
}
(0, utils_1.olakaiLogger)(`All retry attempts failed: ${JSON.stringify(lastError)}`, "error");
throw lastError;
}
/**
* Send a payload to the API
* Adds the payload to the queue and processes it
* Persists queue to localStorage (for offline support)
* Schedules batch processing for normal requests
* Processes immediately for high priority requests
* @param payload - The payload to send to the endpoint
* @param options - The options for the API call
* @returns A promise that resolves when the payload is sent
*/
async function sendToAPI(payload, role = "monitoring", options = {}) {
if (!config.apiKey) {
throw new exceptions_1.APIKeyMissingError("[Olakai SDK] API key is not set");
}
if (role === "monitoring") {
if (config.enableBatching) {
await (0, queue_1.addToQueue)(payload, options);
}
else {
// For non-batching mode, use makeAPICall directly and handle the response
//legacy support for non-batching mode
const response = await makeAPICall([payload], "monitoring");
// Log any batch-style response information if present
if (response.totalRequests !== undefined && response.successCount !== undefined) {
(0, utils_1.olakaiLogger)(`Direct API call result: ${response.successCount}/${response.totalRequests} requests succeeded`, response.failureCount && response.failureCount > 0 ? "warn" : "info");
}
}
}
else if (role === "control") {
try {
const response = await sendWithRetry(payload, config.retries, "control");
return response;
}
catch (error) {
if (error instanceof exceptions_1.OlakaiBlockedError) {
throw error;
}
throw error;
}
}
else {
throw new Error("[Olakai SDK] Invalid role");
}
}
// Re-export queue utility functions
var queue_2 = require("./queue");
Object.defineProperty(exports, "getQueueSize", { enumerable: true, get: function () { return queue_2.getQueueSize; } });
Object.defineProperty(exports, "clearQueue", { enumerable: true, get: function () { return queue_2.clearQueue; } });
Object.defineProperty(exports, "flushQueue", { enumerable: true, get: function () { return queue_2.flushQueue; } });
Object.defineProperty(exports, "getQueueManager", { enumerable: true, get: function () { return queue_2.getQueueManager; } });
//# sourceMappingURL=client.js.map