cybernate-ai
Version:
JavaScript SDK for Cybernate AI Security Platform
3 lines (2 loc) • 13.7 kB
JavaScript
"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t={exports:{}};!function(e){let t;if("undefined"!=typeof window)t=window.fetch;else try{t=require("cross-fetch")}catch(e){throw new Error("cross-fetch is required for Node.js environments")}class n{constructor(e,t={}){if(!e)throw new Error("API key is required");this.apiKey=e,this.baseUrl=t.baseUrl||"https://api.cybernate.ai/v1",this.timeout=t.timeout||3e4,this.autoReconnect=!1!==t.autoReconnect,this.enableWebSocket=!1!==t.enableWebSocket,this.reconnectAttempts=t.reconnectAttempts||5,this.reconnectDelay=t.reconnectDelay||1e3,this.eventListeners={},this.activeWatchers=new Map,this.socket=null,this.isConnected=!1,this.isConnecting=!1,this.reconnectCount=0,this.rateLimit={limit:0,remaining:0,reset:0}}async connect(){if(this.isConnecting)throw new Error("Connection already in progress");this.isConnecting=!0;try{var e;const t=await this._request("GET","/auth/validate");if(this.user=t.user,this.organization=t.organization,this.enableWebSocket&&this._socketIsEnabled())try{await this._setupWebSocket()}catch(e){console.warn("WebSocket connection failed, falling back to HTTP-only mode:",e.message)}return this.isConnected=!0,this.isConnecting=!1,{connected:!0,user:this.user,organization:this.organization,websocketEnabled:!(null===(e=this.socket)||void 0===e||!e.connected)}}catch(e){throw this.isConnected=!1,this.isConnecting=!1,new Error(`Failed to connect to Cybernate: ${e.message}`)}}async watch(e){var t;if(this._ensureConnected(),!e.streamUrl&&!e.deviceId&&!e.businessId)throw new Error("You must specify either streamUrl, deviceId, or businessId");let n,s;if(e.streamUrl?(n="/events/watch",s={url:e.streamUrl,type:"stream",id:e.businessId,name:e.name||`Stream ${(new Date).toISOString()}`,detectionSettings:e.detectionSettings||{}}):e.deviceId?(n="/devices/watch",s={type:"device",id:e.deviceId,detectionSettings:e.detectionSettings||{}}):(n="/businesses/watch",s={type:"business",id:e.businessId,detectionSettings:e.detectionSettings||{}}),s.notificationSettings=e.notificationSettings||{method:null!==(t=this.socket)&&void 0!==t&&t.connected?"socket":"webhook"},"webhook"===s.notificationSettings.method&&!s.notificationSettings.webhookUrl)throw new Error("webhookUrl is required for webhook notifications");console.log("Watch request:",{endpoint:n,payload:s,apiKey:this.apiKey?"Present":"Missing"});const i=await this._request("POST",n,s);return this.activeWatchers.set(i.watcherId,{id:i.watcherId,type:i.type,entityId:i.entityId,createdAt:new Date}),i}async unwatch(e){if(this._ensureConnected(),!e)throw new Error("watcherId is required");const t=await this._request("DELETE",`/events/watch/${e}`);return this.activeWatchers.delete(e),t}async getActiveWatchers(){this._ensureConnected();const e=await this._request("GET","/events/watchers");this.activeWatchers.clear();for(const t of e.watchers)this.activeWatchers.set(t.id,t);return e.watchers}async queryEvents(e={}){this._ensureConnected();const t=new URLSearchParams;return Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,n)})),this._request("GET",`/events?${t.toString()}`)}async getEventStatistics(e={}){this._ensureConnected();const t=new URLSearchParams;return Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,n)})),this._request("GET",`/events/statistics?${t.toString()}`)}async acknowledgeEvent(e,t){if(this._ensureConnected(),!e)throw new Error("eventId is required");return this._request("POST",`/events/${e}/acknowledge`,{notes:t||""})}async setWebhook(e){if(this._ensureConnected(),!e.url)throw new Error("url is required");return this._request("POST","/webhooks/configure",{url:e.url,events:e.events||["detection","connection_lost","alert"]})}async getWebhooks(){return this._ensureConnected(),this._request("GET","/webhooks")}async deleteWebhook(e){return this._ensureConnected(),this._request("DELETE",`/webhooks/${e}`)}async testWebhook(e,t){return this._ensureConnected(),this._request("POST","/webhooks/test",{url:e,payload:t})}async uploadFile(e){if(this._ensureConnected(),!e.file)throw new Error("file is required");if(!e.fileName)throw new Error("fileName is required");const n=new FormData;n.append("file",e.file),n.append("fileName",e.fileName),e.eventId&&n.append("eventId",e.eventId),e.streamId&&n.append("streamId",e.streamId),e.deviceId&&n.append("deviceId",e.deviceId),e.businessId&&n.append("businessId",e.businessId),e.metadata&&n.append("metadata",JSON.stringify(e.metadata)),void 0!==e.isPublic&&n.append("isPublic",e.isPublic);const s=`${this.baseUrl}/storage/upload`,i=await t(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:n,timeout:this.timeout});if(!i.ok){const e=await i.json().catch((()=>({})));throw new Error(e.message||`HTTP error ${i.status}`)}return await i.json()}async getFileInfo(e){return this._ensureConnected(),this._request("GET",`/storage/files/${e}`)}async queryFiles(e={}){this._ensureConnected();const t=new URLSearchParams;return Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,n)})),this._request("GET",`/storage/files?${t.toString()}`)}async deleteFile(e){return this._ensureConnected(),this._request("DELETE",`/storage/files/${e}`)}async getFileUrl(e,t=3600){return this._ensureConnected(),this._request("GET",`/storage/files/${e}/url?expiresIn=${t}`)}async captureStreamFrame(e,t={}){return this._ensureConnected(),this._request("POST",`/storage/capture/${e}`,t)}async getAnalytics(e,t={}){this._ensureConnected();const n=new URLSearchParams;return n.append("businessId",e),Object.entries(t).forEach((([e,t])=>{null!=t&&n.append(e,t)})),this._request("GET",`/analytics?${n.toString()}`)}async getInsights(e,t={}){this._ensureConnected();const n=new URLSearchParams;return n.append("businessId",e),Object.entries(t).forEach((([e,t])=>{null!=t&&n.append(e,t)})),this._request("GET",`/analytics/insights?${n.toString()}`)}async acknowledgeInsight(e,t){return this._ensureConnected(),this._request("POST",`/analytics/insights/${e}/acknowledge`,{actionTaken:t||"Reviewed"})}async getDashboardAnalytics(e){return this._ensureConnected(),this._request("GET",`/analytics/dashboard/${e}`)}async getIntegrations(e={}){this._ensureConnected();const t=new URLSearchParams;return Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,n)})),this._request("GET",`/integrations?${t.toString()}`)}async createIntegration(e){return this._ensureConnected(),this._request("POST","/integrations",e)}async getIntegration(e){return this._ensureConnected(),this._request("GET",`/integrations/${e}`)}async updateIntegration(e,t){return this._ensureConnected(),this._request("PUT",`/integrations/${e}`,t)}async deleteIntegration(e){return this._ensureConnected(),this._request("DELETE",`/integrations/${e}`)}async testIntegration(e){return this._ensureConnected(),this._request("POST",`/integrations/${e}/test`)}async triggerIntegration(e,t,n={}){return this._ensureConnected(),this._request("POST",`/integrations/${e}/trigger`,{action:t,data:n})}async getNotifications(e={}){this._ensureConnected();const t=new URLSearchParams;return Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,n)})),this._request("GET",`/notifications?${t.toString()}`)}async markNotificationAsRead(e){return this._ensureConnected(),this._request("POST",`/notifications/${e}/read`)}async markAllNotificationsAsRead(){return this._ensureConnected(),this._request("POST","/notifications/read-all")}async getNotificationPreferences(){return this._ensureConnected(),this._request("GET","/notifications/preferences")}async updateNotificationPreferences(e){return this._ensureConnected(),this._request("PUT","/notifications/preferences",e)}async addDeviceToken(e){return this._ensureConnected(),this._request("POST","/notifications/device-token",{token:e})}async removeDeviceToken(e){return this._ensureConnected(),this._request("DELETE",`/notifications/device-token?token=${encodeURIComponent(e)}`)}on(e,t){var n;if("function"!=typeof t)throw new Error("Callback must be a function");this.eventListeners[e]||(this.eventListeners[e]=[]),this.eventListeners[e].push(t),!this.enableWebSocket||!this._socketIsEnabled()||null!==(n=this.socket)&&void 0!==n&&n.connected||this._setupWebSocket().catch((e=>console.warn("Failed to setup WebSocket for event listener:",e.message)))}off(e,t){this.eventListeners[e]&&(t?this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t)):delete this.eventListeners[e])}getConnectionStatus(){var e;return{isConnected:this.isConnected,websocketConnected:!(null===(e=this.socket)||void 0===e||!e.connected),websocketEnabled:this.enableWebSocket,reconnectCount:this.reconnectCount,activeWatchers:this.activeWatchers.size}}async retryWebSocketConnection(){var e;if(!this.enableWebSocket||!this._socketIsEnabled())throw new Error("WebSocket not enabled or available");if(null!==(e=this.socket)&&void 0!==e&&e.connected)return!0;try{return await this._setupWebSocket(),!0}catch(e){return console.error("Manual WebSocket retry failed:",e.message),!1}}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null),this.isConnected=!1,this.isConnecting=!1,this.reconnectCount=0,this.activeWatchers.clear()}async _request(e,n,s=null){const i=`${this.baseUrl}${n}`,r={Authorization:`Bearer ${this.apiKey}`,"X-API-Key":this.apiKey,"Content-Type":"application/json","User-Agent":"Cybernate-SDK/1.0",Accept:"application/json"},o={method:e,headers:r,timeout:this.timeout};!s||"POST"!==e&&"PUT"!==e&&"PATCH"!==e||(o.body=JSON.stringify(s)),console.log("API Request:",{method:e,url:i,headers:{...r,Authorization:r.Authorization?"Bearer [REDACTED]":"Missing","X-API-Key":r["X-API-Key"]?"[REDACTED]":"Missing"},hasBody:!!o.body});try{const e=await t(i,o);if(e.headers.has("X-RateLimit-Limit")&&(this.rateLimit.limit=parseInt(e.headers.get("X-RateLimit-Limit"),10)),e.headers.has("X-RateLimit-Remaining")&&(this.rateLimit.remaining=parseInt(e.headers.get("X-RateLimit-Remaining"),10)),e.headers.has("X-RateLimit-Reset")&&(this.rateLimit.reset=parseInt(e.headers.get("X-RateLimit-Reset"),10)),!e.ok){let t;try{t=await e.json()}catch(n){t={message:`HTTP ${e.status}: ${e.statusText}`}}throw console.error("API Error Response:",{status:e.status,statusText:e.statusText,url:i,errorData:t}),401===e.status?new Error(`Authentication failed: ${t.message||"Invalid API key"}`):403===e.status?new Error(`Access forbidden: ${t.message||"Insufficient permissions"}`):404===e.status?new Error(`Endpoint not found: ${t.message||"The requested resource was not found"}`):e.status>=500?new Error(`Server error: ${t.message||"Internal server error"}`):new Error(t.message||`HTTP error ${e.status}`)}const n=await e.json();return console.log("API Response:",{status:e.status,data:n}),n}catch(e){if(e.message.includes("fetch"))throw new Error(`Network error: Unable to connect to ${i}. Please check your internet connection.`);throw new Error(`API request failed: ${e.message}`)}}async _setupWebSocket(){return new Promise(((e,t)=>{if(!this._socketIsEnabled())return t(new Error("WebSocket not enabled or supported"));try{let n;if("undefined"!=typeof window&&void 0!==window.io)n=window.io;else{try{n=require("socket.io-client")}catch(e){return t(new Error("socket.io-client package not found. Install with: npm install socket.io-client"))}}this.socket&&(this.socket.disconnect(),this.socket=null),this.socket=n(`${this.baseUrl}/events`,{auth:{token:this.apiKey},transports:["websocket","polling"],reconnection:this.autoReconnect,reconnectionAttempts:this.reconnectAttempts,reconnectionDelay:this.reconnectDelay,timeout:this.timeout,forceNew:!0}),this.socket.on("connect",(()=>{console.log("Connected to Cybernate events socket"),this.reconnectCount=0,e()})),this.socket.on("disconnect",(e=>{console.log("Disconnected from Cybernate events socket:",e),"io server disconnect"===e&&this.autoReconnect&&setTimeout((()=>{this.reconnectCount<this.reconnectAttempts&&(this.reconnectCount++,console.log(`Attempting to reconnect (${this.reconnectCount}/${this.reconnectAttempts})...`),this._setupWebSocket().catch((()=>{})))}),this.reconnectDelay)})),this.socket.on("connect_error",(e=>{console.error("Socket connection error:",e.message),0===this.reconnectCount&&t(new Error(`WebSocket connection failed: ${e.message}`))})),this.socket.on("error",(e=>{console.error("Socket error:",e)})),this.socket.on("event",(e=>{this._dispatchEvent(e)})),this.socket.on("notification",(e=>{this._dispatchEvent({...e,eventType:"notification"})})),this.socket.on("system",(e=>{this._dispatchEvent({...e,eventType:"system"})}));const s=setTimeout((()=>{var e,n;null!==(e=this.socket)&&void 0!==e&&e.connected||(null===(n=this.socket)||void 0===n||n.disconnect(),t(new Error("WebSocket connection timeout")))}),this.timeout);this.socket.on("connect",(()=>{clearTimeout(s)}))}catch(e){t(new Error(`Failed to initialize WebSocket: ${e.message}`))}}))}_dispatchEvent(e){const t=e.eventType||"detection";this.eventListeners[t]&&this.eventListeners[t].forEach((n=>{try{n(e)}catch(e){console.error(`Error in event listener for ${t}:`,e)}})),this.eventListeners.all&&this.eventListeners.all.forEach((t=>{try{t(e)}catch(e){console.error('Error in "all" event listener:',e)}}))}_socketIsEnabled(){return"undefined"!=typeof window&&void 0!==window.io||this._isSocketIOAvailable()}_isSocketIOAvailable(){try{return require.resolve("socket.io-client"),!0}catch(e){return!1}}_ensureConnected(){if(!this.isConnected)throw new Error("Not connected to Cybernate API. Call connect() first.")}}e.exports?e.exports={CybernateAI:n}:"undefined"!=typeof window&&(window.CybernateAI=n)}(t);var n=e(t.exports);exports.default=n;
//# sourceMappingURL=index.js.map