een-api-toolkit 0.3.47 → 0.3.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/een-jobs-agent.md +676 -0
- package/CHANGELOG.md +7 -8
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1172 -28
- package/dist/index.js +796 -333
- package/dist/index.js.map +1 -1
- package/docs/AI-CONTEXT.md +22 -1
- package/docs/ai-reference/AI-AUTH.md +1 -1
- package/docs/ai-reference/AI-AUTOMATIONS.md +1 -1
- package/docs/ai-reference/AI-DEVICES.md +1 -1
- package/docs/ai-reference/AI-EVENTS.md +1 -1
- package/docs/ai-reference/AI-GROUPING.md +1 -1
- package/docs/ai-reference/AI-JOBS.md +1084 -0
- package/docs/ai-reference/AI-MEDIA.md +1 -1
- package/docs/ai-reference/AI-SETUP.md +1 -1
- package/docs/ai-reference/AI-USERS.md +1 -1
- package/examples/vue-jobs/.env.example +11 -0
- package/examples/vue-jobs/README.md +245 -0
- package/examples/vue-jobs/e2e/app.spec.ts +79 -0
- package/examples/vue-jobs/e2e/auth.spec.ts +382 -0
- package/examples/vue-jobs/e2e/delete-features.spec.ts +564 -0
- package/examples/vue-jobs/e2e/timelapse.spec.ts +361 -0
- package/examples/vue-jobs/index.html +13 -0
- package/examples/vue-jobs/package-lock.json +1722 -0
- package/examples/vue-jobs/package.json +28 -0
- package/examples/vue-jobs/playwright.config.ts +47 -0
- package/examples/vue-jobs/src/App.vue +154 -0
- package/examples/vue-jobs/src/main.ts +25 -0
- package/examples/vue-jobs/src/router/index.ts +82 -0
- package/examples/vue-jobs/src/views/Callback.vue +76 -0
- package/examples/vue-jobs/src/views/CreateExport.vue +284 -0
- package/examples/vue-jobs/src/views/Files.vue +424 -0
- package/examples/vue-jobs/src/views/Home.vue +195 -0
- package/examples/vue-jobs/src/views/JobDetail.vue +392 -0
- package/examples/vue-jobs/src/views/Jobs.vue +297 -0
- package/examples/vue-jobs/src/views/Login.vue +33 -0
- package/examples/vue-jobs/src/views/Logout.vue +59 -0
- package/examples/vue-jobs/src/vite-env.d.ts +1 -0
- package/examples/vue-jobs/tsconfig.json +25 -0
- package/examples/vue-jobs/vite.config.ts +12 -0
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/utils/debug.ts","../src/utils/storage.ts","../src/config.ts","../src/types/common.ts","../src/utils/timestamp.ts","../src/auth/store.ts","../src/auth/service.ts","../src/users/service.ts","../src/cameras/service.ts","../src/bridges/service.ts","../src/layouts/service.ts","../src/media/service.ts","../src/feeds/service.ts","../src/events/service.ts","../src/eventMetrics/service.ts","../src/alerts/service.ts","../src/notifications/service.ts","../src/eventSubscriptions/service.ts","../src/automations/service.ts"],"sourcesContent":["/**\n * Debug logging utility\n * Enabled when VITE_DEBUG=true in environment\n */\n\nconst isDebugEnabled = (): boolean => {\n try {\n return import.meta.env?.VITE_DEBUG === 'true'\n } catch {\n return false\n }\n}\n\nexport function debug(...args: unknown[]): void {\n if (isDebugEnabled()) {\n // eslint-disable-next-line no-console -- intentional debug logging\n console.log('[een-api-toolkit]', ...args)\n }\n}\n\nexport function debugWarn(...args: unknown[]): void {\n if (isDebugEnabled()) {\n console.warn('[een-api-toolkit]', ...args)\n }\n}\n\nexport function debugError(...args: unknown[]): void {\n if (isDebugEnabled()) {\n console.error('[een-api-toolkit]', ...args)\n }\n}\n","// Import StorageStrategy from types to maintain single source of truth\nimport type { StorageStrategy } from '../types'\nimport { debug } from './debug'\n\n// Re-export for convenience\nexport type { StorageStrategy }\n\n/**\n * Human-readable descriptions for each storage strategy.\n * Useful for displaying storage information in UI components.\n *\n * @example\n * ```typescript\n * import { getStorageStrategy, STORAGE_STRATEGY_DESCRIPTIONS } from 'een-api-toolkit'\n *\n * const strategy = getStorageStrategy()\n * const description = STORAGE_STRATEGY_DESCRIPTIONS[strategy]\n * console.log(`Using ${strategy}: ${description}`)\n * ```\n *\n * @category Configuration\n */\nexport const STORAGE_STRATEGY_DESCRIPTIONS: Record<StorageStrategy, string> = {\n localStorage: 'persists across sessions',\n sessionStorage: 'per-tab, cleared on tab close',\n memory: 'tokens lost on page refresh'\n}\n\n/**\n * Storage adapter interface for token persistence.\n * @internal\n */\nexport interface StorageAdapter {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/**\n * In-memory storage implementation.\n * Tokens are lost on page refresh but are immune to storage-based XSS attacks.\n * @internal\n */\nclass MemoryStorage implements StorageAdapter {\n private store = new Map<string, string>()\n\n getItem(key: string): string | null {\n return this.store.get(key) ?? null\n }\n\n setItem(key: string, value: string): void {\n this.store.set(key, value)\n }\n\n removeItem(key: string): void {\n this.store.delete(key)\n }\n}\n\n/**\n * Browser storage wrapper that delegates to localStorage/sessionStorage.\n * Errors are propagated to the caller (auth/store.ts) for proper logging.\n * @internal\n */\nclass BrowserStorageAdapter implements StorageAdapter {\n constructor(private storage: Storage) {}\n\n getItem(key: string): string | null {\n return this.storage.getItem(key)\n }\n\n setItem(key: string, value: string): void {\n this.storage.setItem(key, value)\n }\n\n removeItem(key: string): void {\n this.storage.removeItem(key)\n }\n}\n\n// Singleton instances\nlet currentStrategy: StorageStrategy = 'localStorage'\nlet memoryStorageInstance: MemoryStorage | null = null\n\n/**\n * Get the memory storage singleton instance.\n * @internal\n */\nfunction getMemoryStorage(): MemoryStorage {\n if (!memoryStorageInstance) {\n memoryStorageInstance = new MemoryStorage()\n }\n return memoryStorageInstance\n}\n\n/**\n * Set the storage strategy for the toolkit.\n *\n * @param strategy - The storage strategy to use\n *\n * @remarks\n * This should be called during toolkit initialization via {@link initEenToolkit}.\n * Changing the strategy after authentication may cause the current session to be lost.\n *\n * @internal\n */\nexport function setStorageStrategy(strategy: StorageStrategy): void {\n currentStrategy = strategy\n}\n\n/**\n * Get the current storage strategy.\n *\n * @returns The currently configured storage strategy\n *\n * @category Configuration\n */\nexport function getStorageStrategy(): StorageStrategy {\n return currentStrategy\n}\n\n/**\n * Get the storage adapter for the current strategy.\n *\n * @returns A storage adapter implementation based on the configured strategy\n *\n * @internal\n */\nexport function getStorageAdapter(): StorageAdapter {\n switch (currentStrategy) {\n case 'memory':\n return getMemoryStorage()\n case 'sessionStorage':\n if (typeof sessionStorage !== 'undefined') {\n return new BrowserStorageAdapter(sessionStorage)\n }\n // Fallback to memory if sessionStorage not available\n debug('sessionStorage unavailable, falling back to memory storage')\n return getMemoryStorage()\n case 'localStorage':\n default:\n if (typeof localStorage !== 'undefined') {\n return new BrowserStorageAdapter(localStorage)\n }\n // Fallback to memory if localStorage not available\n debug('localStorage unavailable, falling back to memory storage')\n return getMemoryStorage()\n }\n}\n\n/**\n * Clear the memory storage instance.\n * Useful for testing or when switching strategies.\n *\n * @internal\n */\nexport function clearMemoryStorage(): void {\n memoryStorageInstance = null\n}\n","import type { EenToolkitConfig, StorageStrategy } from './types'\nimport { setStorageStrategy, getStorageStrategy, STORAGE_STRATEGY_DESCRIPTIONS } from './utils/storage'\n\n/**\n * Global toolkit configuration\n */\nlet config: EenToolkitConfig = {}\n\n/**\n * Initialize the EEN API Toolkit\n *\n * @remarks\n * Call this function once at application startup before using any toolkit features.\n * The storage strategy determines how authentication tokens are persisted.\n *\n * @param options - Configuration options for the toolkit\n *\n * @example\n * ```typescript\n * import { initEenToolkit } from 'een-api-toolkit'\n *\n * // Basic initialization with localStorage (default, backwards compatible)\n * initEenToolkit({\n * proxyUrl: 'https://your-proxy.workers.dev',\n * clientId: 'your-client-id'\n * })\n *\n * // High-security initialization with memory-only storage\n * initEenToolkit({\n * proxyUrl: 'https://your-proxy.workers.dev',\n * clientId: 'your-client-id',\n * storageStrategy: 'memory'\n * })\n * ```\n */\nexport function initEenToolkit(options: EenToolkitConfig = {}): void {\n // Set storage strategy first (default to localStorage for backwards compatibility)\n const storageStrategy: StorageStrategy = options.storageStrategy ?? 'localStorage'\n setStorageStrategy(storageStrategy)\n\n config = {\n proxyUrl: options.proxyUrl ?? import.meta.env?.VITE_PROXY_URL,\n clientId: options.clientId ?? import.meta.env?.VITE_EEN_CLIENT_ID,\n redirectUri: options.redirectUri ?? import.meta.env?.VITE_REDIRECT_URI,\n storageStrategy,\n debug: options.debug ?? import.meta.env?.VITE_DEBUG === 'true'\n }\n}\n\nexport { getStorageStrategy, STORAGE_STRATEGY_DESCRIPTIONS }\n\n/**\n * Get the current configuration\n */\nexport function getConfig(): EenToolkitConfig {\n return config\n}\n\n/**\n * Get the proxy URL\n */\nexport function getProxyUrl(): string | undefined {\n return config.proxyUrl ?? import.meta.env?.VITE_PROXY_URL\n}\n\n/**\n * Get the client ID\n */\nexport function getClientId(): string | undefined {\n return config.clientId ?? import.meta.env?.VITE_EEN_CLIENT_ID\n}\n\n/**\n * Get the redirect URI\n */\nexport function getRedirectUri(): string {\n return config.redirectUri ?? import.meta.env?.VITE_REDIRECT_URI ?? 'http://127.0.0.1:3333'\n}\n","/**\n * Error codes returned by the toolkit.\n *\n * @remarks\n * All API functions return a {@link Result} type that contains either data or an error.\n * The error code helps you determine how to handle the failure.\n *\n * @category Types\n */\nexport type ErrorCode =\n | 'AUTH_REQUIRED'\n | 'AUTH_FAILED'\n | 'TOKEN_EXPIRED'\n | 'API_ERROR'\n | 'NETWORK_ERROR'\n | 'VALIDATION_ERROR'\n | 'NOT_FOUND'\n | 'FORBIDDEN'\n | 'RATE_LIMITED'\n | 'SERVICE_UNAVAILABLE'\n | 'UNKNOWN_ERROR'\n\n/**\n * Error object returned when an operation fails.\n *\n * @remarks\n * Contains structured error information including a machine-readable code,\n * human-readable message, and optional HTTP status code.\n *\n * @example\n * ```typescript\n * const { error } = await getUsers()\n * if (error) {\n * console.error(`${error.code}: ${error.message}`)\n * if (error.status === 401) {\n * redirectToLogin()\n * }\n * }\n * ```\n *\n * @category Types\n */\nexport interface EenError {\n /** Machine-readable error code for programmatic handling */\n code: ErrorCode\n /** Human-readable error message */\n message: string\n /** HTTP status code if the error came from an API response */\n status?: number\n /** Additional error details (varies by error type) */\n details?: unknown\n}\n\n/**\n * Result type for all API operations - functions never throw exceptions.\n *\n * @remarks\n * This is a discriminated union type. When `error` is `null`, `data` contains\n * the successful result. When `error` is not `null`, `data` is `null`.\n * TypeScript will narrow the type correctly after checking for errors.\n *\n * @example\n * ```typescript\n * const { data, error } = await getUsers()\n *\n * if (error) {\n * // TypeScript knows: data is null, error is EenError\n * console.error(error.message)\n * return\n * }\n *\n * // TypeScript knows: data is not null, error is null\n * console.log(data.results)\n * ```\n *\n * @typeParam T - The type of the data on success\n * @category Types\n */\nexport type Result<T> =\n | { data: T; error: null }\n | { data: null; error: EenError }\n\n/**\n * Pagination parameters for list operations.\n *\n * @remarks\n * Most list APIs in the EEN platform support pagination. Use `pageSize` to\n * control how many results are returned, and `pageToken` to fetch subsequent pages.\n *\n * @example\n * ```typescript\n * // First page\n * const { data } = await getUsers({ pageSize: 50 })\n *\n * // Next page (if available)\n * if (data.nextPageToken) {\n * const { data: page2 } = await getUsers({\n * pageSize: 50,\n * pageToken: data.nextPageToken\n * })\n * }\n * ```\n *\n * @category Types\n */\nexport interface PaginationParams {\n /** Number of results per page (default varies by endpoint, typically 100) */\n pageSize?: number\n /** Token for fetching a specific page (from previous response's nextPageToken) */\n pageToken?: string\n}\n\n/**\n * Paginated response from list operations.\n *\n * @remarks\n * Contains the results array and optional pagination tokens for navigating\n * through large result sets.\n *\n * @typeParam T - The type of items in the results array\n * @category Types\n */\nexport interface PaginatedResult<T> {\n /** Array of items for this page */\n results: T[]\n /** Token to fetch the next page (undefined if no more pages) */\n nextPageToken?: string\n /** Token to fetch the previous page (undefined if on first page) */\n prevPageToken?: string\n /** Total number of items across all pages (may not be provided by all endpoints) */\n totalSize?: number\n}\n\n/**\n * Storage strategy options for token persistence.\n *\n * @remarks\n * Different storage strategies offer different security/convenience tradeoffs:\n *\n * - **localStorage**: Tokens persist across browser sessions. Most convenient but\n * vulnerable to XSS attacks since JavaScript can access localStorage.\n *\n * - **sessionStorage**: Tokens persist within a single tab session. Cleared when\n * the tab is closed. Each tab has isolated storage, so opening a new tab\n * requires re-authentication.\n *\n * - **memory**: Tokens are only kept in memory (Pinia store). Most secure as\n * tokens are never written to disk, but any page refresh requires re-authentication.\n *\n * @category Configuration\n */\nexport type StorageStrategy = 'localStorage' | 'sessionStorage' | 'memory'\n\n/**\n * Configuration for initializing the toolkit.\n *\n * @remarks\n * Pass this to {@link initEenToolkit} to configure the library. All options\n * can also be set via environment variables (VITE_PROXY_URL, VITE_EEN_CLIENT_ID,\n * VITE_REDIRECT_URI, VITE_DEBUG).\n *\n * @example\n * ```typescript\n * import { initEenToolkit } from 'een-api-toolkit'\n *\n * initEenToolkit({\n * proxyUrl: 'https://your-proxy.workers.dev',\n * clientId: 'your-een-client-id',\n * redirectUri: 'http://localhost:5173/callback',\n * storageStrategy: 'sessionStorage', // More secure than default\n * debug: true\n * })\n * ```\n *\n * @category Configuration\n */\nexport interface EenToolkitConfig {\n /** URL of the OAuth proxy server (required for API calls) */\n proxyUrl?: string\n /** EEN OAuth client ID (required for authentication) */\n clientId?: string\n /** OAuth redirect URI (default: http://127.0.0.1:3333) */\n redirectUri?: string\n /**\n * Storage strategy for token persistence (default: 'localStorage').\n *\n * Security vs convenience tradeoffs:\n * - 'localStorage': Persists across sessions, vulnerable to XSS\n * - 'sessionStorage': Per-tab isolation, cleared on tab close\n * - 'memory': Most secure, lost on page refresh\n */\n storageStrategy?: StorageStrategy\n /** Enable debug logging to console */\n debug?: boolean\n}\n\n/**\n * Helper to create a success result.\n *\n * @param data - The successful result data\n * @returns A Result object with data and null error\n *\n * @internal\n */\nexport function success<T>(data: T): Result<T> {\n return { data, error: null }\n}\n\n/**\n * Helper to create an error result.\n *\n * @param code - The error code\n * @param message - Human-readable error message\n * @param status - Optional HTTP status code\n * @param details - Optional additional error details\n * @returns A Result object with null data and error\n *\n * @internal\n */\nexport function failure<T>(code: ErrorCode, message: string, status?: number, details?: unknown): Result<T> {\n return { data: null, error: { code, message, status, details } }\n}\n","/**\n * Convert ISO 8601 timestamp from Z format to +00:00 format.\n *\n * @remarks\n * The EEN API requires timestamps in +00:00 format, not Z format.\n * This function converts timestamps like `2024-01-01T00:00:00.000Z`\n * to `2024-01-01T00:00:00.000+00:00`.\n *\n * @param timestamp - ISO 8601 timestamp string\n * @returns Timestamp in +00:00 format\n *\n * @example\n * ```typescript\n * formatTimestamp('2024-01-01T00:00:00.000Z')\n * // Returns: '2024-01-01T00:00:00.000+00:00'\n *\n * formatTimestamp(new Date().toISOString())\n * // Returns: timestamp with +00:00 suffix\n * ```\n *\n * @category Utilities\n */\nexport function formatTimestamp(timestamp: string): string {\n // If already in +00:00 format, return as-is\n if (timestamp.endsWith('+00:00')) {\n return timestamp\n }\n // Convert Z to +00:00\n if (timestamp.endsWith('Z')) {\n return timestamp.replace('Z', '+00:00')\n }\n // Return original if format is not recognized\n return timestamp\n}\n","import { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport type { UserProfile } from '../types'\nimport type { Result } from '../types'\nimport { debug } from '../utils/debug'\nimport { getStorageAdapter } from '../utils/storage'\n\n// Lazy-loaded reference to refreshToken to avoid circular dependency at import time\n// Caches the promise (not the resolved value) to prevent race conditions with concurrent calls\nlet refreshTokenFnPromise: Promise<() => Promise<Result<{ accessToken: string; expiresIn: number }>>> | null = null\n\nfunction getRefreshTokenFn() {\n if (!refreshTokenFnPromise) {\n refreshTokenFnPromise = import('./service').then((service) => service.refreshToken)\n }\n return refreshTokenFnPromise\n}\n\n/**\n * Pinia store for authentication state management\n */\nexport const useAuthStore = defineStore('een-auth', () => {\n // State\n const token = ref<string | null>(null)\n const tokenExpiration = ref<number | null>(null)\n const refreshTokenMarker = ref<string | null>(null)\n const sessionId = ref<string | null>(null)\n const hostname = ref<string | null>(null)\n const port = ref<number>(443)\n const userProfile = ref<UserProfile | null>(null)\n const refreshTimerId = ref<ReturnType<typeof setTimeout> | null>(null)\n const isRefreshing = ref(false)\n let refreshPromise: Promise<void> | null = null\n const refreshFailed = ref(false)\n const refreshFailedMessage = ref<string | null>(null)\n\n // Computed\n const isAuthenticated = computed(() => !!token.value)\n\n const baseUrl = computed(() => {\n if (!hostname.value) return null\n return port.value === 443\n ? `https://${hostname.value}`\n : `https://${hostname.value}:${port.value}`\n })\n\n const isTokenExpired = computed(() => {\n if (!tokenExpiration.value) return true\n return Date.now() >= tokenExpiration.value\n })\n\n const tokenExpiresIn = computed(() => {\n if (!tokenExpiration.value) return 0\n return Math.max(0, tokenExpiration.value - Date.now())\n })\n\n // Actions\n function setToken(newToken: string, expiresIn: number) {\n token.value = newToken\n tokenExpiration.value = Date.now() + expiresIn * 1000\n saveToStorage()\n setupAutoRefresh()\n debug('Token set, expires in', expiresIn, 'seconds')\n }\n\n function setRefreshTokenMarker(marker: string) {\n refreshTokenMarker.value = marker\n saveToStorage()\n }\n\n function setSessionId(newSessionId: string) {\n sessionId.value = newSessionId\n saveToStorage()\n }\n\n function setBaseUrl(data: string | { hostname: string; port?: number }) {\n if (typeof data === 'string') {\n // Parse URL string\n try {\n const url = new URL(data.startsWith('http') ? data : `https://${data}`)\n hostname.value = url.hostname\n port.value = url.port ? parseInt(url.port, 10) : 443\n } catch (err: unknown) {\n // Invalid URL format, use as hostname directly\n debug('Failed to parse URL, using as hostname:', err instanceof Error ? err.message : String(err))\n hostname.value = data\n port.value = 443\n }\n } else {\n hostname.value = data.hostname\n port.value = data.port ?? 443\n }\n saveToStorage()\n debug('Base URL set:', baseUrl.value)\n }\n\n function setUserProfile(profile: UserProfile) {\n userProfile.value = profile\n saveToStorage()\n }\n\n function setupAutoRefresh() {\n // Clear existing timer\n if (refreshTimerId.value) {\n clearTimeout(refreshTimerId.value)\n refreshTimerId.value = null\n }\n\n if (!tokenExpiration.value || !token.value) {\n return\n }\n\n const now = Date.now()\n const expiresAt = tokenExpiration.value\n const timeUntilExpiry = expiresAt - now\n\n // Calculate refresh time: 5 minutes before expiration or 50% of TTL, whichever is earlier\n // Minimum: 1 minute before expiration, minimum timeout: 5 seconds\n const fiveMinutes = 5 * 60 * 1000\n const halfTtl = timeUntilExpiry / 2\n const refreshBuffer = Math.min(fiveMinutes, halfTtl)\n const refreshTime = Math.max(timeUntilExpiry - refreshBuffer, 60 * 1000)\n const timeout = Math.max(refreshTime, 5000)\n\n debug('Auto-refresh scheduled in', Math.round(timeout / 1000), 'seconds')\n\n refreshTimerId.value = setTimeout(async () => {\n await performAutoRefresh()\n }, timeout)\n }\n\n async function performAutoRefresh(): Promise<void> {\n // If refresh is already in progress, wait for the existing promise\n if (refreshPromise) {\n debug('Refresh already in progress, waiting for existing refresh')\n return refreshPromise\n }\n\n isRefreshing.value = true\n debug('Performing auto-refresh')\n\n refreshPromise = (async () => {\n try {\n const refreshToken = await getRefreshTokenFn()\n const result = await refreshToken()\n\n if (result.error) {\n refreshFailed.value = true\n refreshFailedMessage.value = result.error.message\n debug('Auto-refresh failed:', result.error.message)\n } else {\n refreshFailed.value = false\n refreshFailedMessage.value = null\n debug('Auto-refresh successful')\n }\n } catch (err: unknown) {\n refreshFailed.value = true\n refreshFailedMessage.value = err instanceof Error ? err.message : String(err)\n debug('Auto-refresh error:', err)\n } finally {\n isRefreshing.value = false\n refreshPromise = null\n }\n })()\n\n return refreshPromise\n }\n\n function clearRefreshFailed() {\n refreshFailed.value = false\n refreshFailedMessage.value = null\n }\n\n function logout() {\n // Clear timer\n if (refreshTimerId.value) {\n clearTimeout(refreshTimerId.value)\n refreshTimerId.value = null\n }\n\n // Clear state\n token.value = null\n tokenExpiration.value = null\n refreshTokenMarker.value = null\n sessionId.value = null\n hostname.value = null\n port.value = 443\n userProfile.value = null\n refreshFailed.value = false\n refreshFailedMessage.value = null\n\n // Clear storage\n clearStorage()\n debug('Logged out')\n }\n\n function initialize() {\n loadFromStorage()\n if (token.value && !isTokenExpired.value) {\n setupAutoRefresh()\n debug('Initialized from storage')\n } else if (token.value && isTokenExpired.value) {\n debug('Stored token expired, clearing')\n logout()\n }\n }\n\n // Storage helpers - use configured storage strategy\n function saveToStorage() {\n try {\n const storage = getStorageAdapter()\n if (token.value) storage.setItem('een_token', token.value)\n if (tokenExpiration.value) storage.setItem('een_tokenExpiration', String(tokenExpiration.value))\n if (refreshTokenMarker.value) storage.setItem('een_refreshTokenMarker', refreshTokenMarker.value)\n if (sessionId.value) storage.setItem('een_sessionId', sessionId.value)\n if (hostname.value) storage.setItem('een_hostname', hostname.value)\n if (port.value !== 443) storage.setItem('een_port', String(port.value))\n if (userProfile.value) storage.setItem('een_userProfile', JSON.stringify(userProfile.value))\n } catch (err: unknown) {\n // Storage might not be available (SSR, private browsing, etc.)\n debug('Failed to save to storage:', err instanceof Error ? err.message : String(err))\n }\n }\n\n function loadFromStorage() {\n try {\n const storage = getStorageAdapter()\n token.value = storage.getItem('een_token')\n const expStr = storage.getItem('een_tokenExpiration')\n tokenExpiration.value = expStr ? parseInt(expStr, 10) : null\n refreshTokenMarker.value = storage.getItem('een_refreshTokenMarker')\n sessionId.value = storage.getItem('een_sessionId')\n hostname.value = storage.getItem('een_hostname')\n const portStr = storage.getItem('een_port')\n port.value = portStr ? parseInt(portStr, 10) : 443\n const profileStr = storage.getItem('een_userProfile')\n userProfile.value = profileStr ? JSON.parse(profileStr) : null\n } catch (err: unknown) {\n // Storage might not be available (SSR, private browsing, etc.)\n debug('Failed to load from storage:', err instanceof Error ? err.message : String(err))\n }\n }\n\n function clearStorage() {\n try {\n const storage = getStorageAdapter()\n storage.removeItem('een_token')\n storage.removeItem('een_tokenExpiration')\n storage.removeItem('een_refreshTokenMarker')\n storage.removeItem('een_sessionId')\n storage.removeItem('een_hostname')\n storage.removeItem('een_port')\n storage.removeItem('een_userProfile')\n } catch (err: unknown) {\n // Storage might not be available (SSR, private browsing, etc.)\n debug('Failed to clear storage:', err instanceof Error ? err.message : String(err))\n }\n }\n\n return {\n // State\n token,\n tokenExpiration,\n refreshTokenMarker,\n sessionId,\n hostname,\n port,\n userProfile,\n isRefreshing,\n refreshFailed,\n refreshFailedMessage,\n\n // Computed\n isAuthenticated,\n baseUrl,\n isTokenExpired,\n tokenExpiresIn,\n\n // Actions\n setToken,\n setRefreshTokenMarker,\n setSessionId,\n setBaseUrl,\n setUserProfile,\n setupAutoRefresh,\n clearRefreshFailed,\n logout,\n initialize\n }\n})\n","import { useAuthStore } from './store'\nimport { getProxyUrl, getClientId, getRedirectUri } from '../config'\nimport { success, failure } from '../types'\nimport type { Result } from '../types'\nimport { debug } from '../utils/debug'\n\nconst EEN_AUTH_URL = 'https://auth.eagleeyenetworks.com/oauth2/authorize'\n\n/**\n * Token response from the OAuth proxy.\n *\n * @remarks\n * This is the response returned by the proxy's `/proxy/getAccessToken` endpoint\n * after successfully exchanging an authorization code for an access token.\n *\n * @category Authentication\n */\nexport interface TokenResponse {\n accessToken: string\n expiresIn: number\n httpsBaseUrl: string | { hostname: string; port?: number }\n userEmail: string\n sessionId: string\n}\n\n/**\n * Generate the OAuth authorization URL\n */\nexport function getAuthUrl(): string {\n const clientId = getClientId()\n if (!clientId) {\n throw new Error('Client ID not configured. Call initEenToolkit() or set VITE_EEN_CLIENT_ID')\n }\n\n // Generate and store state for CSRF protection\n const state = crypto.randomUUID()\n try {\n sessionStorage.setItem('een_oauth_state', state)\n } catch {\n // sessionStorage might not be available\n }\n\n const params = new URLSearchParams({\n client_id: clientId,\n response_type: 'code',\n scope: 'vms.all',\n redirect_uri: getRedirectUri(),\n state\n })\n\n debug('Generated auth URL with state:', state)\n return `${EEN_AUTH_URL}?${params.toString()}`\n}\n\n/**\n * Exchange authorization code for access token\n */\nexport async function getAccessToken(code: string): Promise<Result<TokenResponse>> {\n const proxyUrl = getProxyUrl()\n if (!proxyUrl) {\n return failure('AUTH_FAILED', 'Proxy URL not configured. Call initEenToolkit() or set VITE_PROXY_URL')\n }\n\n const params = new URLSearchParams({\n code,\n redirect_uri: getRedirectUri()\n })\n\n try {\n const response = await fetch(`${proxyUrl}/proxy/getAccessToken?${params.toString()}`, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n })\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error')\n return failure('AUTH_FAILED', `Token exchange failed: ${errorText}`, response.status)\n }\n\n const data = await response.json() as TokenResponse\n debug('Token received, expires in:', data.expiresIn)\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to exchange code: ${String(err)}`)\n }\n}\n\n/**\n * Refresh the access token using stored refresh token\n */\nexport async function refreshToken(): Promise<Result<{ accessToken: string; expiresIn: number }>> {\n const proxyUrl = getProxyUrl()\n if (!proxyUrl) {\n return failure('AUTH_FAILED', 'Proxy URL not configured')\n }\n\n const authStore = useAuthStore()\n\n try {\n const headers: HeadersInit = {\n 'Accept': 'application/json'\n }\n\n // Add session ID header as fallback for environments where cookies don't work\n if (authStore.sessionId) {\n headers['Authorization'] = `Bearer ${authStore.sessionId}`\n }\n\n const response = await fetch(`${proxyUrl}/proxy/refreshAccessToken`, {\n method: 'POST',\n credentials: 'include',\n headers\n })\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error')\n return failure('AUTH_FAILED', `Token refresh failed: ${errorText}`, response.status)\n }\n\n const data = await response.json() as { accessToken: string; expiresIn: number }\n\n // Update store with new token\n authStore.setToken(data.accessToken, data.expiresIn)\n\n debug('Token refreshed, expires in:', data.expiresIn)\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to refresh token: ${String(err)}`)\n }\n}\n\n/**\n * Revoke the current token and logout\n */\nexport async function revokeToken(): Promise<Result<void>> {\n const proxyUrl = getProxyUrl()\n if (!proxyUrl) {\n return failure('AUTH_FAILED', 'Proxy URL not configured')\n }\n\n const authStore = useAuthStore()\n\n try {\n const headers: HeadersInit = {\n 'Accept': 'application/json'\n }\n\n if (authStore.sessionId) {\n headers['Authorization'] = `Bearer ${authStore.sessionId}`\n }\n\n const response = await fetch(`${proxyUrl}/proxy/revoke`, {\n method: 'POST',\n credentials: 'include',\n headers\n })\n\n // Logout regardless of response\n authStore.logout()\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error')\n return failure('AUTH_FAILED', `Token revocation failed: ${errorText}`, response.status)\n }\n\n debug('Token revoked')\n return success(undefined)\n } catch (err) {\n // Still logout on error\n authStore.logout()\n return failure('NETWORK_ERROR', `Failed to revoke token: ${String(err)}`)\n }\n}\n\n/**\n * Handle OAuth callback - validates state and exchanges code for token\n */\nexport async function handleAuthCallback(code: string, state: string): Promise<Result<TokenResponse>> {\n // Validate state for CSRF protection\n let storedState: string | null = null\n try {\n storedState = sessionStorage.getItem('een_oauth_state')\n sessionStorage.removeItem('een_oauth_state')\n } catch {\n // sessionStorage might not be available\n }\n\n if (!storedState) {\n return failure('AUTH_FAILED', 'No OAuth state found. Please restart the login process.')\n }\n\n // Constant-time comparison to prevent timing attacks\n if (!constantTimeEquals(state, storedState)) {\n return failure('AUTH_FAILED', 'Invalid OAuth state. Possible CSRF attack.')\n }\n\n debug('State validated, exchanging code for token')\n\n // Exchange code for token\n const result = await getAccessToken(code)\n\n if (result.error) {\n return result\n }\n\n // Update auth store with received data\n const authStore = useAuthStore()\n const data = result.data\n\n authStore.setToken(data.accessToken, data.expiresIn)\n authStore.setRefreshTokenMarker('present')\n authStore.setSessionId(data.sessionId)\n authStore.setBaseUrl(data.httpsBaseUrl)\n\n debug('Auth callback complete, user:', data.userEmail)\n\n return success(data)\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks\n */\nfunction constantTimeEquals(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false\n }\n\n let result = 0\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\n }\n\n return result === 0\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, User, UserProfile, ListUsersParams, GetUserParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * Get the current authenticated user's profile.\n *\n * @remarks\n * Fetches the profile of the currently authenticated user from `/api/v3.0/users/self`.\n * The result is also stored in the auth store for easy access via `useAuthStore().userProfile`.\n *\n * @returns A Result containing the user profile or an error\n *\n * @example\n * ```typescript\n * import { getCurrentUser } from 'een-api-toolkit'\n *\n * const { data, error } = await getCurrentUser()\n *\n * if (error) {\n * if (error.code === 'AUTH_REQUIRED') {\n * router.push('/login')\n * }\n * return\n * }\n *\n * console.log(`Welcome, ${data.firstName} ${data.lastName}`)\n * ```\n *\n * @category Users\n */\nexport async function getCurrentUser(): Promise<Result<UserProfile>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/users/self`\n debug('Fetching current user:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as UserProfile\n debug('Current user fetched:', data.email)\n\n // Update profile in store\n authStore.setUserProfile(data)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch current user: ${String(err)}`)\n }\n}\n\n/**\n * List users with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of users from `/api/v3.0/users`. Use the `pageSize`\n * parameter to control how many results are returned per page, and `pageToken`\n * to navigate to subsequent pages.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getusers).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of users or an error\n *\n * @example\n * ```typescript\n * import { getUsers } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getUsers()\n * if (data) {\n * console.log(`Found ${data.results.length} users`)\n * }\n *\n * // With pagination\n * const { data } = await getUsers({ pageSize: 50 })\n * if (data?.nextPageToken) {\n * const { data: page2 } = await getUsers({\n * pageSize: 50,\n * pageToken: data.nextPageToken\n * })\n * }\n *\n * // Fetch all users\n * let allUsers: User[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getUsers({ pageSize: 100, pageToken })\n * if (error) break\n * allUsers.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Users\n */\nexport async function getUsers(params?: ListUsersParams): Promise<Result<PaginatedResult<User>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/users${queryString ? `?${queryString}` : ''}`\n debug('Fetching users:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<User>\n debug('Users fetched:', data.results?.length ?? 0, 'users')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch users: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific user by ID.\n *\n * @remarks\n * Fetches a single user from `/api/v3.0/users/{userId}`. Use the `include`\n * parameter to request additional fields like permissions.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getuser).\n *\n * @param userId - The unique identifier of the user to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the user or an error\n *\n * @example\n * ```typescript\n * import { getUser } from 'een-api-toolkit'\n *\n * const { data, error } = await getUser('user-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('User not found')\n * }\n * return\n * }\n *\n * console.log(`User: ${data.firstName} ${data.lastName}`)\n *\n * // With permissions\n * const { data: userWithPerms } = await getUser('user-123', {\n * include: ['permissions']\n * })\n * console.log('Permissions:', userWithPerms?.permissions)\n * ```\n *\n * @category Users\n */\nexport async function getUser(userId: string, params?: GetUserParams): Promise<Result<User>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!userId) {\n return failure('VALIDATION_ERROR', 'User ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/users/${encodeURIComponent(userId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching user:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as User\n debug('User fetched:', data.email)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch user: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, Camera, ListCamerasParams, GetCameraParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List cameras with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of cameras from `/api/v3.0/cameras`. Supports\n * extensive filtering options for location, status, tags, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listcameras).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of cameras or an error\n *\n * @example\n * ```typescript\n * import { getCameras } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getCameras()\n * if (data) {\n * console.log(`Found ${data.results.length} cameras`)\n * }\n *\n * // With filters\n * const { data } = await getCameras({\n * pageSize: 50,\n * status__in: ['online'],\n * include: ['deviceInfo', 'streamUrls']\n * })\n *\n * // Fetch all cameras\n * let allCameras: Camera[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getCameras({ pageSize: 100, pageToken })\n * if (error) break\n * allCameras.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Cameras\n */\nexport async function getCameras(params?: ListCamerasParams): Promise<Result<PaginatedResult<Camera>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include/Sort\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n // Location/Bridge filters\n if (params?.locationId__in && params.locationId__in.length > 0) {\n queryParams.append('locationId__in', params.locationId__in.join(','))\n }\n if (params?.bridgeId__in && params.bridgeId__in.length > 0) {\n queryParams.append('bridgeId__in', params.bridgeId__in.join(','))\n }\n\n // Multi-camera filters\n if (params?.multiCameraId) {\n queryParams.append('multiCameraId', params.multiCameraId)\n }\n if (params?.multiCameraId__ne) {\n queryParams.append('multiCameraId__ne', params.multiCameraId__ne)\n }\n if (params?.multiCameraId__in && params.multiCameraId__in.length > 0) {\n queryParams.append('multiCameraId__in', params.multiCameraId__in.join(','))\n }\n\n // Tag/Package filters\n if (params?.tags__contains && params.tags__contains.length > 0) {\n queryParams.append('tags__contains', params.tags__contains.join(','))\n }\n if (params?.tags__any && params.tags__any.length > 0) {\n queryParams.append('tags__any', params.tags__any.join(','))\n }\n if (params?.packages__contains && params.packages__contains.length > 0) {\n queryParams.append('packages__contains', params.packages__contains.join(','))\n }\n\n // Name filters\n if (params?.name) {\n queryParams.append('name', params.name)\n }\n if (params?.name__contains) {\n queryParams.append('name__contains', params.name__contains)\n }\n if (params?.name__in && params.name__in.length > 0) {\n queryParams.append('name__in', params.name__in.join(','))\n }\n\n // ID filters\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.id__notIn && params.id__notIn.length > 0) {\n queryParams.append('id__notIn', params.id__notIn.join(','))\n }\n if (params?.id__contains) {\n queryParams.append('id__contains', params.id__contains)\n }\n\n // Layout filter\n if (params?.layoutId) {\n queryParams.append('layoutId', params.layoutId)\n }\n\n // Share filters (use API nested field syntax)\n if (typeof params?.shared === 'boolean') {\n queryParams.append('shareDetails.shared', String(params.shared))\n }\n if (params?.sharedCameraAccount) {\n queryParams.append('shareDetails.accountId', params.sharedCameraAccount)\n }\n if (typeof params?.firstResponder === 'boolean') {\n queryParams.append('shareDetails.firstResponder', String(params.firstResponder))\n }\n\n // Device filters\n if (typeof params?.directToCloud === 'boolean') {\n queryParams.append('deviceInfo.directToCloud', String(params.directToCloud))\n }\n\n // Speaker filter\n if (params?.speakerId__in && params.speakerId__in.length > 0) {\n queryParams.append('speakerId__in', params.speakerId__in.join(','))\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n if (typeof params?.qRelevance__gte === 'number') {\n queryParams.append('qRelevance__gte', String(params.qRelevance__gte))\n }\n\n // Analytics filter\n if (params?.enabledAnalytics__contains && params.enabledAnalytics__contains.length > 0) {\n queryParams.append('enabledAnalytics__contains', params.enabledAnalytics__contains.join(','))\n }\n\n // Status filters\n if (params?.status__in && params.status__in.length > 0) {\n queryParams.append('status__in', params.status__in.join(','))\n }\n if (params?.status__ne) {\n queryParams.append('status__ne', params.status__ne)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/cameras${queryString ? `?${queryString}` : ''}`\n debug('Fetching cameras:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Camera>\n debug('Cameras fetched:', data.results?.length ?? 0, 'cameras')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch cameras: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific camera by ID.\n *\n * @remarks\n * Fetches a single camera from `/api/v3.0/cameras/{cameraId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getcamera).\n *\n * @param cameraId - The unique identifier of the camera to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the camera or an error\n *\n * @example\n * ```typescript\n * import { getCamera } from 'een-api-toolkit'\n *\n * const { data, error } = await getCamera('camera-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Camera not found')\n * }\n * return\n * }\n *\n * console.log(`Camera: ${data.name} (${data.status})`)\n *\n * // With additional fields\n * const { data: cameraWithDetails } = await getCamera('camera-123', {\n * include: ['deviceInfo', 'streamUrls', 'shareDetails']\n * })\n * ```\n *\n * @category Cameras\n */\nexport async function getCamera(cameraId: string, params?: GetCameraParams): Promise<Result<Camera>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!cameraId) {\n return failure('VALIDATION_ERROR', 'Camera ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/cameras/${encodeURIComponent(cameraId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching camera:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Camera\n debug('Camera fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch camera: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, Bridge, ListBridgesParams, GetBridgeParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List bridges with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of bridges from `/api/v3.0/bridges`. Supports\n * filtering options for location, status, tags, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listbridges).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of bridges or an error\n *\n * @example\n * ```typescript\n * import { getBridges } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getBridges()\n * if (data) {\n * console.log(`Found ${data.results.length} bridges`)\n * }\n *\n * // With filters\n * const { data } = await getBridges({\n * pageSize: 50,\n * status__in: ['online'],\n * include: ['deviceInfo', 'networkInfo']\n * })\n *\n * // Fetch all bridges\n * let allBridges: Bridge[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getBridges({ pageSize: 100, pageToken })\n * if (error) break\n * allBridges.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Bridges\n */\nexport async function getBridges(params?: ListBridgesParams): Promise<Result<PaginatedResult<Bridge>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include/Sort\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n // Location filters\n if (params?.locationId__in && params.locationId__in.length > 0) {\n queryParams.append('locationId__in', params.locationId__in.join(','))\n }\n\n // Tag filters\n if (params?.tags__contains && params.tags__contains.length > 0) {\n queryParams.append('tags__contains', params.tags__contains.join(','))\n }\n if (params?.tags__any && params.tags__any.length > 0) {\n queryParams.append('tags__any', params.tags__any.join(','))\n }\n\n // Name filters\n if (params?.name) {\n queryParams.append('name', params.name)\n }\n if (params?.name__contains) {\n queryParams.append('name__contains', params.name__contains)\n }\n if (params?.name__in && params.name__in.length > 0) {\n queryParams.append('name__in', params.name__in.join(','))\n }\n\n // ID filters\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.id__notIn && params.id__notIn.length > 0) {\n queryParams.append('id__notIn', params.id__notIn.join(','))\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n if (typeof params?.qRelevance__gte === 'number') {\n queryParams.append('qRelevance__gte', String(params.qRelevance__gte))\n }\n\n // Status filters\n if (params?.status__in && params.status__in.length > 0) {\n queryParams.append('status__in', params.status__in.join(','))\n }\n if (params?.status__ne) {\n queryParams.append('status__ne', params.status__ne)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/bridges${queryString ? `?${queryString}` : ''}`\n debug('Fetching bridges:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Bridge>\n debug('Bridges fetched:', data.results?.length ?? 0, 'bridges')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch bridges: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific bridge by ID.\n *\n * @remarks\n * Fetches a single bridge from `/api/v3.0/bridges/{bridgeId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getbridge).\n *\n * @param bridgeId - The unique identifier of the bridge to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the bridge or an error\n *\n * @example\n * ```typescript\n * import { getBridge } from 'een-api-toolkit'\n *\n * const { data, error } = await getBridge('bridge-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Bridge not found')\n * }\n * return\n * }\n *\n * console.log(`Bridge: ${data.name} (${data.status})`)\n *\n * // With additional fields\n * const { data: bridgeWithDetails } = await getBridge('bridge-123', {\n * include: ['deviceInfo', 'networkInfo', 'status']\n * })\n * ```\n *\n * @category Bridges\n */\nexport async function getBridge(bridgeId: string, params?: GetBridgeParams): Promise<Result<Bridge>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!bridgeId) {\n return failure('VALIDATION_ERROR', 'Bridge ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/bridges/${encodeURIComponent(bridgeId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching bridge:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Bridge\n debug('Bridge fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch bridge: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Layout,\n ListLayoutsParams,\n GetLayoutParams,\n CreateLayoutParams,\n UpdateLayoutParams\n} from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List layouts with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of layouts from `/api/v3.0/layouts`. Supports\n * filtering options for name, search, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listlayouts).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of layouts or an error\n *\n * @example\n * ```typescript\n * import { getLayouts } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getLayouts()\n * if (data) {\n * console.log(`Found ${data.results.length} layouts`)\n * }\n *\n * // With filters\n * const { data } = await getLayouts({\n * pageSize: 50,\n * include: ['resourceCounts', 'effectivePermissions']\n * })\n *\n * // Fetch all layouts\n * let allLayouts: Layout[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getLayouts({ pageSize: 100, pageToken })\n * if (error) break\n * allLayouts.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Layouts\n */\nexport async function getLayouts(params?: ListLayoutsParams): Promise<Result<PaginatedResult<Layout>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include/Sort\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n // Name filters\n if (params?.name) {\n queryParams.append('name', params.name)\n }\n if (params?.name__in && params.name__in.length > 0) {\n queryParams.append('name__in', params.name__in.join(','))\n }\n if (params?.name__contains) {\n queryParams.append('name__contains', params.name__contains)\n }\n\n // ID filters\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n\n // Bridge filter\n if (params?.['layoutPanes.cameras.bridgeId']) {\n queryParams.append('layoutPanes.cameras.bridgeId', params['layoutPanes.cameras.bridgeId'])\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n if (typeof params?.qRelevance__gte === 'number') {\n queryParams.append('qRelevance__gte', String(params.qRelevance__gte))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/layouts${queryString ? `?${queryString}` : ''}`\n debug('Fetching layouts:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Layout>\n debug('Layouts fetched:', data.results?.length ?? 0, 'layouts')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch layouts: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific layout by ID.\n *\n * @remarks\n * Fetches a single layout from `/api/v3.0/layouts/{layoutId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getlayout).\n *\n * @param layoutId - The unique identifier of the layout to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the layout or an error\n *\n * @example\n * ```typescript\n * import { getLayout } from 'een-api-toolkit'\n *\n * const { data, error } = await getLayout('layout-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Layout not found')\n * }\n * return\n * }\n *\n * console.log(`Layout: ${data.name} (${data.panes.length} panes)`)\n *\n * // With additional fields\n * const { data: layoutWithDetails } = await getLayout('layout-123', {\n * include: ['effectivePermissions', 'resourceStatusCounts']\n * })\n * ```\n *\n * @category Layouts\n */\nexport async function getLayout(layoutId: string, params?: GetLayoutParams): Promise<Result<Layout>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!layoutId) {\n return failure('VALIDATION_ERROR', 'Layout ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/layouts/${encodeURIComponent(layoutId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching layout:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Layout\n debug('Layout fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch layout: ${String(err)}`)\n }\n}\n\n/**\n * Create a new layout.\n *\n * @remarks\n * Creates a layout via `POST /api/v3.0/layouts`. Name and settings are required.\n * Panes can be added during creation or later via `updateLayout()`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/createlayout).\n *\n * @param params - The layout configuration\n * @returns A Result containing the created layout or an error\n *\n * @example\n * ```typescript\n * import { createLayout } from 'een-api-toolkit'\n *\n * const { data, error } = await createLayout({\n * name: 'Main Lobby View',\n * settings: {\n * showCameraBorder: true,\n * showCameraName: true,\n * cameraAspectRatio: '16x9',\n * paneColumns: 3\n * },\n * panes: [\n * { id: 1, name: 'Entrance', type: 'preview', size: 1, cameraId: 'cam-123' },\n * { id: 2, name: 'Lobby', type: 'preview', size: 2, cameraId: 'cam-456' }\n * ]\n * })\n *\n * if (data) {\n * console.log(`Created layout: ${data.id}`)\n * }\n * ```\n *\n * @category Layouts\n */\nexport async function createLayout(params: CreateLayoutParams): Promise<Result<Layout>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.name) {\n return failure('VALIDATION_ERROR', 'Layout name is required')\n }\n\n if (!params.settings) {\n return failure('VALIDATION_ERROR', 'Layout settings are required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/layouts`\n debug('Creating layout:', params.name)\n\n const body: Record<string, unknown> = {\n name: params.name,\n settings: params.settings\n }\n\n if (params.panes) {\n body.panes = params.panes\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(body)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Layout\n debug('Layout created:', data.id, data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to create layout: ${String(err)}`)\n }\n}\n\n/**\n * Update an existing layout.\n *\n * @remarks\n * Updates a layout via `PATCH /api/v3.0/layouts/{layoutId}`. Only provided\n * fields will be updated. Returns void on success (204 No Content).\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/updatelayout).\n *\n * @param layoutId - The unique identifier of the layout to update\n * @param params - The fields to update\n * @returns A Result containing void on success or an error\n *\n * @example\n * ```typescript\n * import { updateLayout } from 'een-api-toolkit'\n *\n * // Update name only\n * const { error } = await updateLayout('layout-123', {\n * name: 'Updated Layout Name'\n * })\n *\n * // Update settings\n * const { error } = await updateLayout('layout-123', {\n * settings: {\n * paneColumns: 4,\n * showCameraName: false\n * }\n * })\n *\n * // Replace panes\n * const { error } = await updateLayout('layout-123', {\n * panes: [\n * { id: 1, name: 'New Pane', type: 'preview', size: 1, cameraId: 'cam-789' }\n * ]\n * })\n *\n * if (error) {\n * console.error('Update failed:', error.message)\n * }\n * ```\n *\n * @category Layouts\n */\nexport async function updateLayout(layoutId: string, params: UpdateLayoutParams): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!layoutId) {\n return failure('VALIDATION_ERROR', 'Layout ID is required')\n }\n\n if (params.name === undefined && params.settings === undefined && params.panes === undefined) {\n return failure('VALIDATION_ERROR', 'At least one field (name, settings, or panes) must be provided for update')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/layouts/${encodeURIComponent(layoutId)}`\n debug('Updating layout:', layoutId)\n\n const body: Record<string, unknown> = {}\n\n if (params.name !== undefined) {\n body.name = params.name\n }\n if (params.settings !== undefined) {\n body.settings = params.settings\n }\n if (params.panes !== undefined) {\n body.panes = params.panes\n }\n\n try {\n const response = await fetch(url, {\n method: 'PATCH',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(body)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('Layout updated:', layoutId)\n\n return success(undefined)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to update layout: ${String(err)}`)\n }\n}\n\n/**\n * Delete a layout.\n *\n * @remarks\n * Deletes a layout via `DELETE /api/v3.0/layouts/{layoutId}`.\n * Returns void on success (204 No Content).\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/deletelayout).\n *\n * @param layoutId - The unique identifier of the layout to delete\n * @returns A Result containing void on success or an error\n *\n * @example\n * ```typescript\n * import { deleteLayout } from 'een-api-toolkit'\n *\n * const { error } = await deleteLayout('layout-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Layout already deleted')\n * } else {\n * console.error('Delete failed:', error.message)\n * }\n * } else {\n * console.log('Layout deleted successfully')\n * }\n * ```\n *\n * @category Layouts\n */\nexport async function deleteLayout(layoutId: string): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!layoutId) {\n return failure('VALIDATION_ERROR', 'Layout ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/layouts/${encodeURIComponent(layoutId)}`\n debug('Deleting layout:', layoutId)\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('Layout deleted:', layoutId)\n\n return success(undefined)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to delete layout: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 400:\n return failure('VALIDATION_ERROR', `Bad request: ${message}`, status)\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n MediaInterval,\n ListMediaParams,\n GetLiveImageParams,\n GetRecordedImageParams,\n LiveImageResult,\n RecordedImageResult,\n MediaSessionResponse,\n MediaSessionResult\n} from '../types'\nimport { debug } from '../utils/debug'\n\n/** Default timeout for media requests in milliseconds */\nconst DEFAULT_TIMEOUT_MS = 30000\n\n/**\n * Create an AbortController with a timeout.\n * @internal\n */\nfunction createTimeoutController(timeoutMs: number = DEFAULT_TIMEOUT_MS): { controller: AbortController; timeoutId: ReturnType<typeof setTimeout> } {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs)\n return { controller, timeoutId }\n}\n\n/**\n * Convert ArrayBuffer to base64 string.\n *\n * @remarks\n * **Memory Considerations**: This function loads the entire image into memory\n * as a string. For typical camera preview images (<500KB), this is efficient.\n * For larger images (>2MB), consider streaming or chunked processing in the\n * consuming application. Base64 encoding adds ~33% size overhead.\n *\n * @internal\n */\nfunction arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n // Use chunked approach with array join for O(n) complexity instead of O(n²) string concatenation\n // Iterate byte-by-byte within chunks to avoid call stack issues with String.fromCharCode.apply()\n const chunkSize = 8192\n const chunks: string[] = []\n for (let i = 0; i < bytes.byteLength; i += chunkSize) {\n const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.byteLength))\n let str = ''\n for (let j = 0; j < chunk.length; j++) {\n str += String.fromCharCode(chunk[j]!)\n }\n chunks.push(str)\n }\n const binary = chunks.join('')\n // Use btoa in browser, Buffer in Node.js\n if (typeof btoa === 'function') {\n return btoa(binary)\n }\n return Buffer.from(binary, 'binary').toString('base64')\n}\n\n/**\n * List media intervals (recording periods) for a device.\n *\n * @remarks\n * Fetches a paginated list of time intervals for which recordings exist.\n * Use this to find available recordings for a camera.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listmedia).\n *\n * @param params - Required parameters including deviceId, type, mediaType, and startTimestamp\n * @returns A Result containing a paginated list of media intervals or an error\n *\n * @example\n * ```typescript\n * import { listMedia } from 'een-api-toolkit'\n *\n * // Get video recordings from the last hour\n * const { data, error } = await listMedia({\n * deviceId: 'camera-123',\n * type: 'preview',\n * mediaType: 'video',\n * startTimestamp: new Date(Date.now() - 3600000).toISOString()\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} recording intervals`)\n * data.results.forEach(interval => {\n * console.log(`${interval.startTimestamp} - ${interval.endTimestamp}`)\n * })\n * }\n * ```\n *\n * @category Media\n */\nexport async function listMedia(params: ListMediaParams): Promise<Result<PaginatedResult<MediaInterval>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.deviceId) {\n return failure('VALIDATION_ERROR', 'Device ID is required')\n }\n if (!params.type) {\n return failure('VALIDATION_ERROR', 'Stream type is required (preview or main)')\n }\n if (!params.mediaType) {\n return failure('VALIDATION_ERROR', 'Media type is required (video or image)')\n }\n if (!params.startTimestamp) {\n return failure('VALIDATION_ERROR', 'Start timestamp is required')\n }\n\n const queryParams = new URLSearchParams()\n\n // Required parameters\n queryParams.append('deviceId', params.deviceId)\n queryParams.append('type', params.type)\n queryParams.append('mediaType', params.mediaType)\n queryParams.append('startTimestamp__gte', params.startTimestamp)\n\n // Optional parameters\n if (params.endTimestamp) {\n queryParams.append('endTimestamp__lte', params.endTimestamp)\n }\n if (typeof params.coalesce === 'boolean') {\n queryParams.append('coalesce', String(params.coalesce))\n }\n if (params.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n if (typeof params.pageSize === 'number') {\n queryParams.append('pageSize', String(params.pageSize))\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/media?${queryParams.toString()}`\n debug('Fetching media intervals:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<MediaInterval>\n debug('Media intervals fetched:', data.results?.length ?? 0, 'intervals')\n\n return success(data)\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch media intervals: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Get a live image from a camera.\n *\n * @remarks\n * Fetches a new live image from the specified camera. This call waits until\n * a new image is available from the device. The image is returned as a\n * base64 data URL that can be used directly in an HTML img element.\n *\n * Note: Live images only support the 'preview' stream type.\n *\n * **Memory Considerations**: Images are loaded into memory and base64 encoded,\n * adding ~33% size overhead. Typical preview images are <500KB. For high-frequency\n * polling, consider implementing error backoff and limiting concurrent requests.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getliveimage).\n *\n * @param params - Parameters including the required deviceId\n * @returns A Result containing the live image data or an error\n *\n * @example\n * ```typescript\n * import { getLiveImage } from 'een-api-toolkit'\n *\n * const { data, error } = await getLiveImage({ deviceId: 'camera-123' })\n *\n * if (data) {\n * // Display in an img element\n * document.getElementById('cameraImage').src = data.imageData\n * console.log('Image timestamp:', data.timestamp)\n * }\n *\n * // Continuously update the image with proper error handling\n * let isRunning = true\n * async function refreshLoop() {\n * const imgElement = document.getElementById('cameraImage') as HTMLImageElement\n * while (isRunning) {\n * const { data, error } = await getLiveImage({ deviceId: 'camera-123' })\n * if (error) {\n * console.error('Refresh failed:', error.message)\n * break // Stop on error\n * }\n * if (data) {\n * imgElement.src = data.imageData\n * }\n * await new Promise(r => setTimeout(r, 1000))\n * }\n * }\n * // Call refreshLoop() to start, set isRunning = false to stop\n * ```\n *\n * @category Media\n */\nexport async function getLiveImage(params: GetLiveImageParams): Promise<Result<LiveImageResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.deviceId) {\n return failure('VALIDATION_ERROR', 'Device ID is required')\n }\n\n // Live images only support 'preview' type (enforced by TypeScript)\n const type = params.type ?? 'preview'\n\n const queryParams = new URLSearchParams()\n queryParams.append('deviceId', params.deviceId)\n queryParams.append('type', type)\n\n const url = `${authStore.baseUrl}/api/v3.0/media/liveImage.jpeg?${queryParams.toString()}`\n debug('Fetching live image:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'image/jpeg',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n // Get headers before checking response.ok\n const timestamp = response.headers.get('X-Een-Timestamp')\n const prevToken = response.headers.get('X-Een-PrevToken')\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // Get image as base64\n const arrayBuffer = await response.arrayBuffer()\n const base64 = arrayBufferToBase64(arrayBuffer)\n const imageData = `data:image/jpeg;base64,${base64}`\n\n debug('Live image fetched, timestamp:', timestamp)\n\n return success({\n imageData,\n timestamp,\n prevToken\n })\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch live image: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Get a recorded image from a camera.\n *\n * @remarks\n * Fetches a recorded image from the specified camera at a specific timestamp.\n * You can specify the desired timestamp using various operators (exact, gte, lte, etc.)\n * or use a pageToken from a previous request to navigate through images.\n *\n * The image is returned as a base64 data URL that can be used directly in an HTML img element.\n *\n * Note: The 'main' type is rate-limited and requires an actual recording at the timestamp.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getrecordedimage).\n *\n * @param params - Parameters including deviceId/pageToken and timestamp options\n * @returns A Result containing the recorded image data or an error\n *\n * @example\n * ```typescript\n * import { getRecordedImage } from 'een-api-toolkit'\n *\n * // Get image at or after a specific time\n * const { data, error } = await getRecordedImage({\n * deviceId: 'camera-123',\n * type: 'preview',\n * timestamp__gte: '2024-01-15T10:00:00.000Z'\n * })\n *\n * if (data) {\n * imgElement.src = data.imageData\n * console.log('Actual timestamp:', data.timestamp)\n *\n * // Get the next image using the token\n * if (data.nextToken) {\n * const { data: nextImage } = await getRecordedImage({\n * pageToken: data.nextToken\n * })\n * }\n * }\n * ```\n *\n * @category Media\n */\nexport async function getRecordedImage(params: GetRecordedImageParams): Promise<Result<RecordedImageResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate: either deviceId or pageToken is required\n if (!params.deviceId && !params.pageToken) {\n return failure('VALIDATION_ERROR', 'Either deviceId or pageToken is required')\n }\n\n // If not using pageToken, validate at least one timestamp parameter\n if (!params.pageToken) {\n const hasTimestamp = params.timestamp__lt || params.timestamp__lte ||\n params.timestamp || params.timestamp__gte || params.timestamp__gt\n if (!hasTimestamp) {\n return failure('VALIDATION_ERROR', 'At least one timestamp parameter is required')\n }\n }\n\n // Validate overlay requirements\n if (params.include?.includes('overlaySvgHeader') &&\n (!params.overlayId__in || params.overlayId__in.length === 0)) {\n return failure('VALIDATION_ERROR', 'At least one overlayId must be provided when requesting overlay headers')\n }\n\n const queryParams = new URLSearchParams()\n\n // Add parameters\n if (params.deviceId) {\n queryParams.append('deviceId', params.deviceId)\n }\n if (params.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n if (params.type) {\n queryParams.append('type', params.type)\n }\n\n // Timestamp parameters\n if (params.timestamp__lt) {\n queryParams.append('timestamp__lt', params.timestamp__lt)\n }\n if (params.timestamp__lte) {\n queryParams.append('timestamp__lte', params.timestamp__lte)\n }\n if (params.timestamp) {\n queryParams.append('timestamp', params.timestamp)\n }\n if (params.timestamp__gte) {\n queryParams.append('timestamp__gte', params.timestamp__gte)\n }\n if (params.timestamp__gt) {\n queryParams.append('timestamp__gt', params.timestamp__gt)\n }\n\n // Overlay parameters\n if (params.overlayId__in && params.overlayId__in.length > 0) {\n queryParams.append('overlayId__in', params.overlayId__in.join(','))\n }\n if (params.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n // Size parameters\n if (typeof params.targetWidth === 'number') {\n queryParams.append('targetWidth', String(params.targetWidth))\n }\n if (typeof params.targetHeight === 'number') {\n queryParams.append('targetHeight', String(params.targetHeight))\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/media/recordedImage.jpeg?${queryParams.toString()}`\n debug('Fetching recorded image:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'image/jpeg',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n // Get headers before checking response.ok\n const timestamp = response.headers.get('X-Een-Timestamp')\n const nextToken = response.headers.get('X-Een-NextToken')\n const prevToken = response.headers.get('X-Een-PrevToken')\n const overlaySvg = response.headers.get('X-Een-OverlaySvg')\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // Get image as base64\n const arrayBuffer = await response.arrayBuffer()\n const base64 = arrayBufferToBase64(arrayBuffer)\n const imageData = `data:image/jpeg;base64,${base64}`\n\n debug('Recorded image fetched, timestamp:', timestamp)\n\n return success({\n imageData,\n timestamp,\n nextToken,\n prevToken,\n overlaySvg\n })\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch recorded image: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n case 503:\n return failure('SERVICE_UNAVAILABLE', `Service unavailable: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n\n/**\n * Get the media session URL for setting cookies.\n *\n * @remarks\n * Fetches the URL needed to set the media session cookie. The returned URL\n * must be called separately (with credentials included) to actually set the\n * cookie. This is the first step in the two-step media session initialization\n * process.\n *\n * For most use cases, prefer using {@link initMediaSession} which handles\n * both steps automatically.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/docs/watch-live-video).\n *\n * @returns A Result containing the media session URL or an error\n *\n * @example\n * ```typescript\n * import { getMediaSession } from 'een-api-toolkit'\n *\n * // Get the session URL (step 1)\n * const { data, error } = await getMediaSession()\n *\n * if (data) {\n * console.log('Session URL:', data.url)\n * // Now call data.url with credentials: 'include' to set the cookie\n * }\n * ```\n *\n * @category Media\n */\nexport async function getMediaSession(): Promise<Result<MediaSessionResponse>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/media/session`\n debug('Fetching media session:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as MediaSessionResponse\n debug('Media session URL received:', data.url)\n\n return success(data)\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch media session: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Initialize the media session by setting the session cookie.\n *\n * @remarks\n * This function handles the two-step process of setting up a media session:\n * 1. Fetches the session URL from `/api/v3.0/media/session`\n * 2. Calls that URL with credentials to set the session cookie\n *\n * Once the session cookie is set, the browser can access media streams\n * (like multipart preview URLs) without explicit Authorization headers.\n * This is required for using media URLs directly in HTML elements like\n * `<img>` or `<video>`.\n *\n * **Important**: This function must be called in a browser environment\n * where cookies can be set. It uses `credentials: 'include'` to ensure\n * the cookie is stored.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/docs/watch-live-video).\n *\n * @returns A Result containing the session result or an error\n *\n * @example\n * ```typescript\n * import { initMediaSession, listFeeds } from 'een-api-toolkit'\n *\n * // Initialize the media session (do this once after login)\n * const { data, error } = await initMediaSession()\n *\n * if (error) {\n * console.error('Failed to init media session:', error.message)\n * return\n * }\n *\n * // Now you can use multipart URLs directly in <img> elements\n * const { data: feeds } = await listFeeds({\n * deviceId: 'camera-123',\n * include: ['multipartUrl']\n * })\n *\n * if (feeds?.results[0]?.multipartUrl) {\n * // This works because the session cookie is set\n * imgElement.src = feeds.results[0].multipartUrl\n * }\n * ```\n *\n * @category Media\n */\nexport async function initMediaSession(): Promise<Result<MediaSessionResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n // Step 1: Get the media session URL\n const sessionResult = await getMediaSession()\n\n if (sessionResult.error) {\n return failure(\n sessionResult.error.code,\n `Failed to get media session: ${sessionResult.error.message}`,\n sessionResult.error.status\n )\n }\n\n if (!sessionResult.data?.url) {\n return failure('API_ERROR', 'No session URL returned from media session endpoint')\n }\n\n const sessionUrl = sessionResult.data.url\n debug('Calling session URL to set cookie:', sessionUrl)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n // Step 2: Call the session URL to set the cookie\n const response = await fetch(sessionUrl, {\n method: 'GET',\n credentials: 'include', // Critical: include cookies in the request/response\n headers: {\n 'Accept': '*/*',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n // The session endpoint typically returns 204 No Content on success\n // but may also return 200 OK\n if (!response.ok && response.status !== 204) {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n return failure('API_ERROR', `Failed to set media session cookie: ${message}`, status)\n }\n\n debug('Media session cookie set successfully')\n\n return success({\n success: true,\n sessionUrl\n })\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out while setting session cookie')\n }\n return failure('NETWORK_ERROR', `Failed to set media session cookie: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, ListFeedsParams, ListFeedsResult } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List feeds with optional filtering and pagination.\n *\n * @remarks\n * Fetches a list of feeds from `/api/v3.0/feeds`. Feeds represent live or\n * recorded streams from devices (cameras, speakers). Use the `include` parameter\n * to request specific streaming URLs.\n *\n * A single device can have multiple feeds (main, preview, talkdown) with\n * different quality levels and purposes.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listfeeds).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a list of feeds or an error\n *\n * @example\n * ```typescript\n * import { listFeeds } from 'een-api-toolkit'\n * import type { Feed } from 'een-api-toolkit'\n *\n * // Get all feeds\n * const { data, error } = await listFeeds()\n * if (data) {\n * console.log(`Found ${data.results.length} feeds`)\n * }\n *\n * // Get feeds for a specific camera with streaming URLs\n * const { data: cameraFeeds } = await listFeeds({\n * deviceId: 'camera-123',\n * include: ['hlsUrl', 'multipartUrl']\n * })\n *\n * // Get preview feeds for multiple cameras\n * const { data: previewFeeds } = await listFeeds({\n * deviceId__in: ['camera-1', 'camera-2'],\n * type: 'preview',\n * include: ['hlsUrl']\n * })\n *\n * // Paginate through all feeds\n * let allFeeds: Feed[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listFeeds({ pageSize: 100, pageToken })\n * if (error) break\n * allFeeds.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Feeds\n */\nexport async function listFeeds(params?: ListFeedsParams): Promise<Result<ListFeedsResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (typeof params?.pageSize === 'number') {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Device filters\n if (params?.deviceId) {\n queryParams.append('deviceId', params.deviceId)\n }\n if (params?.deviceId__in && params.deviceId__in.length > 0) {\n queryParams.append('deviceId__in', params.deviceId__in.join(','))\n }\n\n // Type filter\n if (params?.type) {\n queryParams.append('type', params.type)\n }\n\n // Include URL fields\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/feeds${queryString ? `?${queryString}` : ''}`\n debug('Fetching feeds:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: params?.signal\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as ListFeedsResult\n debug('Feeds fetched:', data.results?.length ?? 0, 'feeds')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch feeds: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let apiMessage: string | undefined\n try {\n const errorData = await response.json()\n apiMessage = errorData.message ?? errorData.error\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', apiMessage || 'Authentication failed', status)\n case 403:\n return failure('FORBIDDEN', apiMessage || 'Access denied', status)\n case 404:\n return failure('NOT_FOUND', apiMessage || 'Not found', status)\n case 429:\n return failure('RATE_LIMITED', apiMessage || 'Rate limited', status)\n case 503:\n return failure('SERVICE_UNAVAILABLE', apiMessage || 'Service unavailable', status)\n default:\n return failure('API_ERROR', apiMessage || response.statusText || 'API error', status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Event,\n EventType,\n EventFieldValues,\n ListEventsParams,\n GetEventParams,\n ListEventTypesParams,\n ListEventFieldValuesParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * List events with required filters and optional pagination.\n *\n * @remarks\n * Fetches a paginated list of events from `/api/v3.0/events`. The `actor`,\n * `type__in`, and `startTimestamp__gte` parameters are required.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listevents).\n *\n * @param params - Required and optional filtering parameters\n * @returns A Result containing a paginated list of events or an error\n *\n * @example\n * ```typescript\n * import { listEvents } from 'een-api-toolkit'\n *\n * // Get motion events from a camera in the last hour\n * const { data, error } = await listEvents({\n * actor: 'camera:100d4c41',\n * type__in: ['een.motionDetectionEvent.v1'],\n * startTimestamp__gte: new Date(Date.now() - 3600000).toISOString()\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} events`)\n * data.results.forEach(event => {\n * console.log(`${event.type} at ${event.startTimestamp}`)\n * })\n * }\n *\n * // Fetch all events with pagination\n * let allEvents: Event[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listEvents({\n * actor: 'camera:100d4c41',\n * type__in: ['een.motionDetectionEvent.v1'],\n * startTimestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * pageSize: 100,\n * pageToken\n * })\n * if (error) break\n * allEvents.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Events\n */\nexport async function listEvents(params: ListEventsParams): Promise<Result<PaginatedResult<Event>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.actor) {\n return failure('VALIDATION_ERROR', 'actor parameter is required')\n }\n\n if (!params.type__in || params.type__in.length === 0) {\n return failure('VALIDATION_ERROR', 'type__in parameter is required and must not be empty')\n }\n\n if (!params.startTimestamp__gte) {\n return failure('VALIDATION_ERROR', 'startTimestamp__gte parameter is required')\n }\n\n const queryParams = new URLSearchParams()\n\n // Required filters\n queryParams.append('actor', params.actor)\n queryParams.append('type__in', params.type__in.join(','))\n queryParams.append('startTimestamp__gte', formatTimestamp(params.startTimestamp__gte))\n\n // Pagination\n if (params.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Optional time filters\n if (params.startTimestamp__lte) {\n queryParams.append('startTimestamp__lte', formatTimestamp(params.startTimestamp__lte))\n }\n if (params.endTimestamp__gte) {\n queryParams.append('endTimestamp__gte', formatTimestamp(params.endTimestamp__gte))\n }\n if (params.endTimestamp__lte) {\n queryParams.append('endTimestamp__lte', formatTimestamp(params.endTimestamp__lte))\n }\n\n // Sort\n if (params.sort) {\n queryParams.append('sort', params.sort)\n }\n\n // Include\n if (params.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/events${queryString ? `?${queryString}` : ''}`\n debug('Fetching events:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Event>\n debug('Events fetched:', data.results?.length ?? 0, 'events')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch events: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific event by ID.\n *\n * @remarks\n * Fetches a single event from `/api/v3.0/events/{eventId}`. Use the `include`\n * parameter to request additional data schemas.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getevent).\n *\n * @param eventId - The unique identifier of the event to fetch\n * @param params - Optional parameters (e.g., include additional data schemas)\n * @returns A Result containing the event or an error\n *\n * @example\n * ```typescript\n * import { getEvent } from 'een-api-toolkit'\n *\n * const { data, error } = await getEvent('event-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Event not found')\n * }\n * return\n * }\n *\n * console.log(`Event: ${data.type} at ${data.startTimestamp}`)\n *\n * // With additional data schemas\n * const { data: eventWithData } = await getEvent('event-123', {\n * include: ['data.een.objectDetection.v1', 'data.een.fullFrameImageUrl.v1']\n * })\n * ```\n *\n * @category Events\n */\nexport async function getEvent(eventId: string, params?: GetEventParams): Promise<Result<Event>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!eventId) {\n return failure('VALIDATION_ERROR', 'Event ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/events/${encodeURIComponent(eventId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching event:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Event\n debug('Event fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event: ${String(err)}`)\n }\n}\n\n/**\n * List all available event types.\n *\n * @remarks\n * Fetches a paginated list of event types from `/api/v3.0/eventTypes`. Event types\n * describe the different kinds of events that can be generated in the system.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listeventtypes).\n *\n * @param params - Optional pagination and language parameters\n * @returns A Result containing a paginated list of event types or an error\n *\n * @example\n * ```typescript\n * import { listEventTypes } from 'een-api-toolkit'\n *\n * const { data, error } = await listEventTypes()\n * if (data) {\n * data.results.forEach(eventType => {\n * console.log(`${eventType.name}: ${eventType.description}`)\n * })\n * }\n *\n * // With language parameter\n * const { data: localizedTypes } = await listEventTypes({ language: 'de' })\n * ```\n *\n * @category Events\n */\nexport async function listEventTypes(params?: ListEventTypesParams): Promise<Result<PaginatedResult<EventType>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Language\n if (params?.language) {\n queryParams.append('language', params.language)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventTypes${queryString ? `?${queryString}` : ''}`\n debug('Fetching event types:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EventType>\n debug('Event types fetched:', data.results?.length ?? 0, 'types')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event types: ${String(err)}`)\n }\n}\n\n/**\n * List available event field values for a specific actor.\n *\n * @remarks\n * Fetches available event types for a specific actor from\n * `/api/v3.0/events:listFieldValues`. This is useful for building filter UIs\n * to know which event types are available for a camera or other device.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listeventfieldvalues).\n *\n * @param params - Parameters including the actor to query\n * @returns A Result containing available field values or an error\n *\n * @example\n * ```typescript\n * import { listEventFieldValues } from 'een-api-toolkit'\n *\n * const { data, error } = await listEventFieldValues({\n * actor: 'camera:100d4c41'\n * })\n *\n * if (data) {\n * console.log('Available event types:', data.type)\n * // Use these types to filter the listEvents call\n * }\n * ```\n *\n * @category Events\n */\nexport async function listEventFieldValues(params: ListEventFieldValuesParams): Promise<Result<EventFieldValues>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameter\n if (!params.actor) {\n return failure('VALIDATION_ERROR', 'actor parameter is required')\n }\n\n const queryParams = new URLSearchParams()\n queryParams.append('actor', params.actor)\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/events:listFieldValues${queryString ? `?${queryString}` : ''}`\n debug('Fetching event field values:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventFieldValues\n debug('Event field values fetched:', data.type?.length ?? 0, 'types')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event field values: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n EventMetric,\n GetEventMetricsParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * Get event metrics (time-series data) for a specific actor and event type.\n *\n * @remarks\n * Fetches time-series metric data from `/api/v3.0/eventMetrics`. The `actor` and\n * `eventType` parameters are required. Returns an array of EventMetric objects\n * containing data points over time.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listmetrics).\n *\n * @param params - Required and optional filtering parameters\n * @returns A Result containing an array of event metrics or an error\n *\n * @example\n * ```typescript\n * import { getEventMetrics } from 'een-api-toolkit'\n *\n * // Get motion event metrics for a camera (last 7 days by default)\n * const { data, error } = await getEventMetrics({\n * actor: 'camera:100d4c41',\n * eventType: 'een.motionDetectionEvent.v1'\n * })\n *\n * if (data) {\n * data.forEach(metric => {\n * console.log(`${metric.eventType}: ${metric.dataPoints.length} data points`)\n * metric.dataPoints.forEach(([timestamp, count]) => {\n * console.log(` ${new Date(timestamp).toISOString()}: ${count}`)\n * })\n * })\n * }\n *\n * // With custom time range and aggregation\n * const { data: hourlyData } = await getEventMetrics({\n * actor: 'camera:100d4c41',\n * eventType: 'een.motionDetectionEvent.v1',\n * timestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * timestamp__lte: new Date().toISOString(),\n * aggregateByMinutes: 60\n * })\n * ```\n *\n * @category Event Metrics\n */\nexport async function getEventMetrics(params: GetEventMetricsParams): Promise<Result<EventMetric[]>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.actor) {\n return failure('VALIDATION_ERROR', 'actor parameter is required')\n }\n\n if (!params.eventType) {\n return failure('VALIDATION_ERROR', 'eventType parameter is required')\n }\n\n const queryParams = new URLSearchParams()\n\n // Required parameters\n queryParams.append('actor', params.actor)\n queryParams.append('eventType', params.eventType)\n\n // Optional time filters\n if (params.timestamp__gte) {\n queryParams.append('timestamp__gte', formatTimestamp(params.timestamp__gte))\n }\n if (params.timestamp__lte) {\n queryParams.append('timestamp__lte', formatTimestamp(params.timestamp__lte))\n }\n\n // Optional aggregation\n if (params.aggregateByMinutes !== undefined) {\n queryParams.append('aggregateByMinutes', String(params.aggregateByMinutes))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventMetrics${queryString ? `?${queryString}` : ''}`\n debug('Fetching event metrics:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventMetric[]\n debug('Event metrics fetched:', data.length, 'metrics')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event metrics: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Alert,\n AlertType,\n ListAlertsParams,\n GetAlertParams,\n ListAlertTypesParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * List alerts with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alerts from `/api/v3.0/alerts`. Supports various\n * filters including time range, actor, alert type, priority, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listalerts).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of alerts or an error\n *\n * @example\n * ```typescript\n * import { listAlerts } from 'een-api-toolkit'\n *\n * // Get recent alerts from a specific camera\n * const { data, error } = await listAlerts({\n * actorId__in: ['100d4c41'],\n * timestamp__gte: new Date(Date.now() - 3600000).toISOString(),\n * pageSize: 50,\n * include: ['data', 'actions']\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} alerts`)\n * data.results.forEach(alert => {\n * console.log(`${alert.alertType} at ${alert.timestamp}`)\n * })\n * }\n *\n * // Fetch all alerts with pagination\n * let allAlerts: Alert[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listAlerts({\n * timestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * pageSize: 100,\n * pageToken\n * })\n * if (error) break\n * allAlerts.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Alerts\n */\nexport async function listAlerts(params?: ListAlertsParams): Promise<Result<PaginatedResult<Alert>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Time filters\n if (params?.timestamp__lte) {\n queryParams.append('timestamp__lte', formatTimestamp(params.timestamp__lte))\n }\n if (params?.timestamp__gte) {\n queryParams.append('timestamp__gte', formatTimestamp(params.timestamp__gte))\n }\n\n // Entity filters\n if (params?.creatorId) {\n queryParams.append('creatorId', params.creatorId)\n }\n if (params?.alertType__in && params.alertType__in.length > 0) {\n queryParams.append('alertType__in', params.alertType__in.join(','))\n }\n if (params?.actorId__in && params.actorId__in.length > 0) {\n queryParams.append('actorId__in', params.actorId__in.join(','))\n }\n if (params?.actorType__in && params.actorType__in.length > 0) {\n queryParams.append('actorType__in', params.actorType__in.join(','))\n }\n if (params?.actorAccountId) {\n queryParams.append('actorAccountId', params.actorAccountId)\n }\n\n // Rule filters\n if (params?.ruleId) {\n queryParams.append('ruleId', params.ruleId)\n }\n if (params?.ruleId__in && params.ruleId__in.length > 0) {\n queryParams.append('ruleId__in', params.ruleId__in.join(','))\n }\n\n // Event and location filters\n if (params?.eventId) {\n queryParams.append('eventId', params.eventId)\n }\n if (params?.locationId__in && params.locationId__in.length > 0) {\n queryParams.append('locationId__in', params.locationId__in.join(','))\n }\n\n // Priority filters\n if (params?.priority__gte !== undefined) {\n queryParams.append('priority__gte', String(params.priority__gte))\n }\n if (params?.priority__lte !== undefined) {\n queryParams.append('priority__lte', String(params.priority__lte))\n }\n\n // Other filters\n if (params?.showInvalidAlerts !== undefined) {\n queryParams.append('showInvalidAlerts', String(params.showInvalidAlerts))\n }\n if (params?.alertActionId__in && params.alertActionId__in.length > 0) {\n queryParams.append('alertActionId__in', params.alertActionId__in.join(','))\n }\n if (params?.alertActionStatus__in && params.alertActionStatus__in.length > 0) {\n queryParams.append('alertActionStatus__in', params.alertActionStatus__in.join(','))\n }\n\n // Response options\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n if (params?.language) {\n queryParams.append('language', params.language)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alerts${queryString ? `?${queryString}` : ''}`\n debug('Fetching alerts:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Alert>\n debug('Alerts fetched:', data.results?.length ?? 0, 'alerts')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alerts: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert by ID.\n *\n * @remarks\n * Fetches a single alert from `/api/v3.0/alerts/{alertId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getalert).\n *\n * @param alertId - The unique identifier of the alert to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the alert or an error\n *\n * @example\n * ```typescript\n * import { getAlert } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlert('alert-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Alert not found')\n * }\n * return\n * }\n *\n * console.log(`Alert: ${data.alertType} at ${data.timestamp}`)\n *\n * // With additional fields\n * const { data: alertWithData } = await getAlert('alert-123', {\n * include: ['data', 'actions', 'description']\n * })\n * ```\n *\n * @category Alerts\n */\nexport async function getAlert(alertId: string, params?: GetAlertParams): Promise<Result<Alert>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!alertId) {\n return failure('VALIDATION_ERROR', 'Alert ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alerts/${encodeURIComponent(alertId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Alert\n debug('Alert fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert: ${String(err)}`)\n }\n}\n\n/**\n * List all available alert types.\n *\n * @remarks\n * Fetches a paginated list of alert types from `/api/v3.0/alertTypes`. Alert types\n * describe the different kinds of alerts that can be generated in the system.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listalerttypes).\n *\n * @param params - Optional pagination parameters\n * @returns A Result containing a paginated list of alert types or an error\n *\n * @example\n * ```typescript\n * import { listAlertTypes } from 'een-api-toolkit'\n *\n * const { data, error } = await listAlertTypes()\n * if (data) {\n * data.results.forEach(alertType => {\n * console.log(`${alertType.type}: ${alertType.description}`)\n * })\n * }\n *\n * // With pagination\n * const { data: pagedTypes } = await listAlertTypes({ pageSize: 20 })\n * ```\n *\n * @category Alerts\n */\nexport async function listAlertTypes(params?: ListAlertTypesParams): Promise<Result<PaginatedResult<AlertType>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertTypes${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert types:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AlertType>\n debug('Alert types fetched:', data.results?.length ?? 0, 'types')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert types: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Notification,\n ListNotificationsParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * List notifications with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of notifications from `/api/v3.0/notifications`. Supports\n * various filters including time range, actor, alert type, category, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listnotifications).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of notifications or an error\n *\n * @example\n * ```typescript\n * import { listNotifications } from 'een-api-toolkit'\n *\n * // Get recent notifications for a specific camera\n * const { data, error } = await listNotifications({\n * actorId: '100d4c41',\n * timestamp__gte: new Date(Date.now() - 3600000).toISOString(),\n * pageSize: 50\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} notifications`)\n * data.results.forEach(notification => {\n * console.log(`${notification.category}: ${notification.description}`)\n * })\n * }\n *\n * // Get unread notifications\n * const { data: unread } = await listNotifications({\n * read: false,\n * category: 'video'\n * })\n *\n * // Fetch all notifications with pagination\n * let allNotifications: Notification[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listNotifications({\n * timestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * pageSize: 100,\n * pageToken\n * })\n * if (error) break\n * allNotifications.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Notifications\n */\nexport async function listNotifications(params?: ListNotificationsParams): Promise<Result<PaginatedResult<Notification>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Time filters\n if (params?.timestamp__lte) {\n queryParams.append('timestamp__lte', formatTimestamp(params.timestamp__lte))\n }\n if (params?.timestamp__gte) {\n queryParams.append('timestamp__gte', formatTimestamp(params.timestamp__gte))\n }\n\n // Entity filters\n if (params?.alertId) {\n queryParams.append('alertId', params.alertId)\n }\n if (params?.alertType) {\n queryParams.append('alertType', params.alertType)\n }\n if (params?.actorId) {\n queryParams.append('actorId', params.actorId)\n }\n if (params?.actorType) {\n queryParams.append('actorType', params.actorType)\n }\n if (params?.actorAccountId) {\n queryParams.append('actorAccountId', params.actorAccountId)\n }\n\n // Category and status filters\n if (params?.category) {\n queryParams.append('category', params.category)\n }\n if (params?.userId) {\n queryParams.append('userId', params.userId)\n }\n if (params?.read !== undefined) {\n queryParams.append('read', String(params.read))\n }\n if (params?.status) {\n queryParams.append('status', params.status)\n }\n\n // Other options\n if (params?.includeV1Notifications !== undefined) {\n queryParams.append('includeV1Notifications', String(params.includeV1Notifications))\n }\n\n // Response options\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n if (params?.language) {\n queryParams.append('language', params.language)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/notifications${queryString ? `?${queryString}` : ''}`\n debug('Fetching notifications:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Notification>\n debug('Notifications fetched:', data.results?.length ?? 0, 'notifications')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch notifications: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific notification by ID.\n *\n * @remarks\n * Fetches a single notification from `/api/v3.0/notifications/{notificationId}`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getnotification).\n *\n * @param notificationId - The unique identifier of the notification to fetch\n * @returns A Result containing the notification or an error\n *\n * @example\n * ```typescript\n * import { getNotification } from 'een-api-toolkit'\n *\n * const { data, error } = await getNotification('notification-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Notification not found')\n * }\n * return\n * }\n *\n * console.log(`Notification: ${data.category} - ${data.description}`)\n * console.log(`Read: ${data.read}`)\n * ```\n *\n * @category Notifications\n */\nexport async function getNotification(notificationId: string): Promise<Result<Notification>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!notificationId) {\n return failure('VALIDATION_ERROR', 'Notification ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/notifications/${encodeURIComponent(notificationId)}`\n debug('Fetching notification:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Notification\n debug('Notification fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch notification: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n EventSubscription,\n CreateEventSubscriptionParams,\n ListEventSubscriptionsParams,\n SSEConnection,\n SSEConnectionOptions,\n SSEConnectionStatus,\n SSEEvent\n} from '../types'\nimport { debug } from '../utils'\n\n/**\n * List all event subscriptions for the current account.\n *\n * @remarks\n * Fetches a paginated list of event subscriptions from `/api/v3.0/eventSubscriptions`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listeventsubscriptions).\n *\n * @param params - Optional pagination parameters\n * @returns A Result containing a paginated list of event subscriptions or an error\n *\n * @example\n * ```typescript\n * import { listEventSubscriptions } from 'een-api-toolkit'\n *\n * const { data, error } = await listEventSubscriptions()\n * if (data) {\n * console.log(`Found ${data.results.length} subscriptions`)\n * data.results.forEach(sub => {\n * console.log(`${sub.id}: ${sub.deliveryConfig.type}`)\n * })\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function listEventSubscriptions(\n params?: ListEventSubscriptionsParams\n): Promise<Result<PaginatedResult<EventSubscription>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions${queryString ? `?${queryString}` : ''}`\n debug('Fetching event subscriptions:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EventSubscription>\n debug('Event subscriptions fetched:', data.results?.length ?? 0, 'subscriptions')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event subscriptions: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific event subscription by ID.\n *\n * @remarks\n * Fetches a single event subscription from `/api/v3.0/eventSubscriptions/{id}`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/geteventsubscription).\n *\n * @param subscriptionId - The unique identifier of the subscription to fetch\n * @returns A Result containing the event subscription or an error\n *\n * @example\n * ```typescript\n * import { getEventSubscription } from 'een-api-toolkit'\n *\n * const { data, error } = await getEventSubscription('f3d6f55d5ba546168758a309508f4419')\n * if (data) {\n * console.log(`Subscription: ${data.id}`)\n * if (data.deliveryConfig.type === 'serverSentEvents.v1') {\n * console.log(`SSE URL: ${data.deliveryConfig.sseUrl}`)\n * }\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function getEventSubscription(\n subscriptionId: string\n): Promise<Result<EventSubscription>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!subscriptionId) {\n return failure('VALIDATION_ERROR', 'Subscription ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions/${encodeURIComponent(subscriptionId)}`\n debug('Fetching event subscription:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventSubscription\n debug('Event subscription fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event subscription: ${String(err)}`)\n }\n}\n\n/**\n * Create a new event subscription.\n *\n * @remarks\n * Creates a new event subscription at `/api/v3.0/eventSubscriptions`.\n * For SSE subscriptions, use `connectToEventSubscription()` with the returned\n * `sseUrl` to start receiving events.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/createeventsubscription).\n *\n * @param params - Parameters for creating the subscription\n * @returns A Result containing the created event subscription or an error\n *\n * @example\n * ```typescript\n * import { createEventSubscription, connectToEventSubscription } from 'een-api-toolkit'\n *\n * // Create an SSE subscription for motion events\n * const { data, error } = await createEventSubscription({\n * deliveryConfig: { type: 'serverSentEvents.v1' },\n * filters: [{\n * actors: ['camera:100d4c41'],\n * types: [{ id: 'een.motionDetectionEvent.v1' }]\n * }]\n * })\n *\n * if (data && data.deliveryConfig.type === 'serverSentEvents.v1') {\n * // Connect to the SSE stream\n * const { data: connection } = connectToEventSubscription(\n * data.deliveryConfig.sseUrl!,\n * { onEvent: (event) => console.log('Event:', event) }\n * )\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function createEventSubscription(\n params: CreateEventSubscriptionParams\n): Promise<Result<EventSubscription>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.deliveryConfig) {\n return failure('VALIDATION_ERROR', 'deliveryConfig is required')\n }\n\n if (!params.filters || params.filters.length === 0) {\n return failure('VALIDATION_ERROR', 'At least one filter is required')\n }\n\n // Validate each filter\n for (const filter of params.filters) {\n if (!filter.actors || filter.actors.length === 0) {\n return failure('VALIDATION_ERROR', 'Each filter must have at least one actor')\n }\n if (!filter.types || filter.types.length === 0) {\n return failure('VALIDATION_ERROR', 'Each filter must have at least one event type')\n }\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions`\n debug('Creating event subscription:', url)\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(params)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventSubscription\n debug('Event subscription created:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to create event subscription: ${String(err)}`)\n }\n}\n\n/**\n * Delete an event subscription.\n *\n * @remarks\n * Deletes an event subscription at `/api/v3.0/eventSubscriptions/{id}`.\n * Any active SSE connections to this subscription will be closed.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/deleteeventsubscription).\n *\n * @param subscriptionId - The unique identifier of the subscription to delete\n * @returns A Result with void data on success or an error\n *\n * @example\n * ```typescript\n * import { deleteEventSubscription } from 'een-api-toolkit'\n *\n * const { error } = await deleteEventSubscription('f3d6f55d5ba546168758a309508f4419')\n * if (error) {\n * console.error('Failed to delete:', error.message)\n * } else {\n * console.log('Subscription deleted successfully')\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function deleteEventSubscription(\n subscriptionId: string\n): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!subscriptionId) {\n return failure('VALIDATION_ERROR', 'Subscription ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions/${encodeURIComponent(subscriptionId)}`\n debug('Deleting event subscription:', url)\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('Event subscription deleted:', subscriptionId)\n return success(undefined)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to delete event subscription: ${String(err)}`)\n }\n}\n\n/**\n * Connect to an SSE event subscription to receive real-time events.\n *\n * @remarks\n * Opens an SSE connection to the provided URL and calls the `onEvent` callback\n * for each event received. The connection automatically handles reconnection\n * on errors.\n *\n * Note: SSE connections require authentication. The token is passed via the\n * `Authorization` header. Since EventSource doesn't support custom headers,\n * we use fetch with ReadableStream to implement SSE.\n *\n * @param sseUrl - The SSE URL from the event subscription's deliveryConfig\n * @param options - Connection options including event and error callbacks\n * @returns A Result containing the SSE connection handle or an error\n *\n * @example\n * ```typescript\n * import { createEventSubscription, connectToEventSubscription } from 'een-api-toolkit'\n *\n * // First create a subscription\n * const { data: subscription } = await createEventSubscription({\n * deliveryConfig: { type: 'serverSentEvents.v1' },\n * filters: [{\n * actors: ['camera:100d4c41'],\n * types: [{ id: 'een.motionDetectionEvent.v1' }]\n * }]\n * })\n *\n * if (subscription?.deliveryConfig.type === 'serverSentEvents.v1') {\n * // Connect to SSE stream\n * const { data: connection, error } = connectToEventSubscription(\n * subscription.deliveryConfig.sseUrl!,\n * {\n * onEvent: (event) => {\n * console.log(`Event: ${event.type} from ${event.actorId}`)\n * },\n * onError: (err) => {\n * console.error('SSE error:', err.message)\n * },\n * onStatusChange: (status) => {\n * console.log('Connection status:', status)\n * }\n * }\n * )\n *\n * // Later, disconnect\n * if (connection) {\n * connection.close()\n * }\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport function connectToEventSubscription(\n sseUrl: string,\n options: SSEConnectionOptions\n): Result<SSEConnection> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.token) {\n return failure('AUTH_REQUIRED', 'Access token not available')\n }\n\n if (!sseUrl) {\n return failure('VALIDATION_ERROR', 'SSE URL is required')\n }\n\n // Validate SSE URL domain to prevent SSRF attacks\n // SSE URLs should only come from trusted EEN domains\n try {\n const sseUrlObj = new URL(sseUrl)\n const allowedDomains = ['.eagleeyenetworks.com', '.een.cloud']\n // Allow both exact domain match (e.g., eagleeyenetworks.com) and subdomain match (e.g., api.eagleeyenetworks.com)\n const isAllowedDomain = allowedDomains.some(domain =>\n sseUrlObj.hostname === domain.substring(1) || sseUrlObj.hostname.endsWith(domain)\n )\n if (!isAllowedDomain) {\n return failure('VALIDATION_ERROR', `SSE URL domain not allowed: ${sseUrlObj.hostname}`)\n }\n } catch {\n return failure('VALIDATION_ERROR', 'Invalid SSE URL format')\n }\n\n // Maximum buffer size to prevent memory exhaustion (1MB)\n const MAX_BUFFER_SIZE = 1024 * 1024\n\n let status: SSEConnectionStatus = 'connecting'\n let abortController: AbortController | null = new AbortController()\n let isClosing = false\n\n const setStatus = (newStatus: SSEConnectionStatus) => {\n status = newStatus\n options.onStatusChange?.(status)\n }\n\n const close = () => {\n if (isClosing) return\n isClosing = true\n debug('Closing SSE connection')\n abortController?.abort()\n abortController = null\n setStatus('disconnected')\n }\n\n const connect = async () => {\n if (isClosing || !abortController) return\n\n setStatus('connecting')\n debug('Connecting to SSE:', sseUrl)\n\n try {\n // Note: We intentionally omit Cache-Control header here.\n // While 'Cache-Control: no-cache' is common for SSE, it triggers CORS preflight\n // requests that fail because the EEN API doesn't include it in Access-Control-Allow-Headers.\n // The SSE endpoint handles caching appropriately server-side.\n const response = await fetch(sseUrl, {\n method: 'GET',\n headers: {\n 'Accept': 'text/event-stream',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: abortController.signal\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n if (!response.body) {\n throw new Error('Response body is not available')\n }\n\n setStatus('connected')\n debug('SSE connected')\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (!isClosing) {\n const { done, value } = await reader.read()\n\n if (done) {\n debug('SSE stream ended')\n break\n }\n\n buffer += decoder.decode(value, { stream: true })\n\n // Prevent buffer from growing unbounded (protects against memory exhaustion)\n if (buffer.length > MAX_BUFFER_SIZE) {\n debug('SSE buffer exceeded maximum size, resetting')\n buffer = ''\n continue\n }\n\n const lines = buffer.split('\\n')\n buffer = lines.pop() || ''\n\n let eventData = ''\n for (const line of lines) {\n if (line.startsWith('data:')) {\n // Per SSE spec, multi-line data fields are concatenated with newlines\n const dataValue = line.substring(5).trimStart()\n eventData = eventData ? `${eventData}\\n${dataValue}` : dataValue\n } else if (line === '' && eventData) {\n // End of event\n try {\n const event = JSON.parse(eventData) as SSEEvent\n debug('SSE event received:', event.type, event.actorId)\n options.onEvent(event)\n } catch (parseError) {\n debug('Failed to parse SSE event:', parseError)\n }\n eventData = ''\n }\n }\n }\n } catch (err) {\n if (isClosing || (err instanceof Error && err.name === 'AbortError')) {\n // Expected when closing\n return\n }\n\n debug('SSE error:', err)\n setStatus('error')\n options.onError?.(err instanceof Error ? err : new Error(String(err)))\n }\n }\n\n // Start connection\n connect()\n\n const connection: SSEConnection = {\n close,\n get status() {\n return status\n }\n }\n\n return success(connection)\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', message, status)\n case 403:\n return failure('FORBIDDEN', message, status)\n case 404:\n return failure('NOT_FOUND', message, status)\n case 429:\n return failure('RATE_LIMITED', message, status)\n default:\n return failure('API_ERROR', message, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n EventAlertConditionRule,\n EventAlertConditionRuleFieldValues,\n AlertConditionRule,\n AlertActionRule,\n AutomationAlertAction,\n ListEventAlertConditionRulesParams,\n GetEventAlertConditionRuleFieldValuesParams,\n ListAlertConditionRulesParams,\n GetAlertConditionRuleParams,\n ListAlertActionRulesParams,\n ListAlertActionsParams\n} from '../types'\nimport { debug } from '../utils'\n\n// =============================================================================\n// Event Alert Condition Rules\n// =============================================================================\n\n/**\n * List event alert condition rules with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of event alert condition rules from\n * `/api/v3.0/eventAlertConditionRules`. These rules define conditions\n * under which events trigger alerts.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listalertconditionrules).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of rules or an error\n *\n * @example\n * ```typescript\n * import { listEventAlertConditionRules } from 'een-api-toolkit'\n *\n * // Get enabled rules\n * const { data, error } = await listEventAlertConditionRules({\n * enabled: true,\n * pageSize: 50\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} rules`)\n * data.results.forEach(rule => {\n * console.log(`${rule.name}: priority ${rule.priority}`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listEventAlertConditionRules(\n params?: ListEventAlertConditionRulesParams\n): Promise<Result<PaginatedResult<EventAlertConditionRule>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.outputAlertType__in && params.outputAlertType__in.length > 0) {\n queryParams.append('outputAlertType__in', params.outputAlertType__in.join(','))\n }\n if (params?.priority__gte !== undefined) {\n queryParams.append('priority__gte', String(params.priority__gte))\n }\n if (params?.priority__lte !== undefined) {\n queryParams.append('priority__lte', String(params.priority__lte))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventAlertConditionRules${queryString ? `?${queryString}` : ''}`\n debug('Fetching event alert condition rules:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EventAlertConditionRule>\n debug('Event alert condition rules fetched:', data.results?.length ?? 0, 'rules')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event alert condition rules: ${String(err)}`)\n }\n}\n\n/**\n * Get available field values for event alert condition rules.\n *\n * @remarks\n * Fetches available values that can be used for filtering event alert condition rules.\n * Useful for building filter UI components.\n *\n * @param params - Optional filter parameters\n * @returns A Result containing field values or an error\n *\n * @example\n * ```typescript\n * import { getEventAlertConditionRuleFieldValues } from 'een-api-toolkit'\n *\n * const { data, error } = await getEventAlertConditionRuleFieldValues()\n * if (data) {\n * console.log('Available event types:', data.eventTypes)\n * console.log('Available alert types:', data.outputAlertTypes)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getEventAlertConditionRuleFieldValues(\n params?: GetEventAlertConditionRuleFieldValuesParams\n): Promise<Result<EventAlertConditionRuleFieldValues>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventAlertConditionRules:listFieldValues${queryString ? `?${queryString}` : ''}`\n debug('Fetching event alert condition rule field values:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventAlertConditionRuleFieldValues\n debug('Event alert condition rule field values fetched')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch field values: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific event alert condition rule by ID.\n *\n * @remarks\n * Fetches a single event alert condition rule from\n * `/api/v3.0/eventAlertConditionRules/{id}`.\n *\n * @param ruleId - The unique identifier of the rule to fetch\n * @returns A Result containing the rule or an error\n *\n * @example\n * ```typescript\n * import { getEventAlertConditionRule } from 'een-api-toolkit'\n *\n * const { data, error } = await getEventAlertConditionRule('rule-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Rule not found')\n * }\n * return\n * }\n *\n * console.log(`Rule: ${data.name}, Priority: ${data.priority}`)\n * ```\n *\n * @category Automations\n */\nexport async function getEventAlertConditionRule(\n ruleId: string\n): Promise<Result<EventAlertConditionRule>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!ruleId) {\n return failure('VALIDATION_ERROR', 'Rule ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventAlertConditionRules/${encodeURIComponent(ruleId)}`\n debug('Fetching event alert condition rule:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventAlertConditionRule\n debug('Event alert condition rule fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event alert condition rule: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Alert Condition Rules\n// =============================================================================\n\n/**\n * List alert condition rules with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alert condition rules from\n * `/api/v3.0/alertConditionRules`. These rules process events and create alerts.\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of rules or an error\n *\n * @example\n * ```typescript\n * import { listAlertConditionRules } from 'een-api-toolkit'\n *\n * // Get enabled rules with actions\n * const { data, error } = await listAlertConditionRules({\n * enabled: true,\n * include: ['actions', 'insights']\n * })\n *\n * if (data) {\n * data.results.forEach(rule => {\n * console.log(`${rule.name}: ${rule.inputEventTypes.length} event types`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listAlertConditionRules(\n params?: ListAlertConditionRulesParams\n): Promise<Result<PaginatedResult<AlertConditionRule>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.actorId__in && params.actorId__in.length > 0) {\n queryParams.append('actorId__in', params.actorId__in.join(','))\n }\n if (params?.inputEventType__in && params.inputEventType__in.length > 0) {\n queryParams.append('inputEventType__in', params.inputEventType__in.join(','))\n }\n if (params?.outputAlertType) {\n queryParams.append('outputAlertType', params.outputAlertType)\n }\n if (params?.type) {\n queryParams.append('type', params.type)\n }\n\n // Response options\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertConditionRules${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert condition rules:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AlertConditionRule>\n debug('Alert condition rules fetched:', data.results?.length ?? 0, 'rules')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert condition rules: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert condition rule by ID.\n *\n * @remarks\n * Fetches a single alert condition rule from `/api/v3.0/alertConditionRules/{id}`.\n * Use the `include` parameter to request additional fields like actions or insights.\n *\n * @param ruleId - The unique identifier of the rule to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the rule or an error\n *\n * @example\n * ```typescript\n * import { getAlertConditionRule } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlertConditionRule('rule-123', {\n * include: ['actions', 'insights']\n * })\n *\n * if (data) {\n * console.log(`Rule: ${data.name}`)\n * console.log(`Actions: ${data.actions?.length ?? 0}`)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getAlertConditionRule(\n ruleId: string,\n params?: GetAlertConditionRuleParams\n): Promise<Result<AlertConditionRule>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!ruleId) {\n return failure('VALIDATION_ERROR', 'Rule ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertConditionRules/${encodeURIComponent(ruleId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert condition rule:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as AlertConditionRule\n debug('Alert condition rule fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert condition rule: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Alert Action Rules\n// =============================================================================\n\n/**\n * List alert action rules with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alert action rules from `/api/v3.0/alertActionRules`.\n * These rules connect alerts to actions - when an alert matches the rule's criteria,\n * the associated actions are executed.\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of rules or an error\n *\n * @example\n * ```typescript\n * import { listAlertActionRules } from 'een-api-toolkit'\n *\n * // Get enabled rules for specific alert types\n * const { data, error } = await listAlertActionRules({\n * enabled: true,\n * alertType__in: ['een.motionDetectionAlert.v1']\n * })\n *\n * if (data) {\n * data.results.forEach(rule => {\n * console.log(`${rule.name}: ${rule.alertActionIds.length} actions`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listAlertActionRules(\n params?: ListAlertActionRulesParams\n): Promise<Result<PaginatedResult<AlertActionRule>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.alertType__in && params.alertType__in.length > 0) {\n queryParams.append('alertType__in', params.alertType__in.join(','))\n }\n if (params?.actorId__in && params.actorId__in.length > 0) {\n queryParams.append('actorId__in', params.actorId__in.join(','))\n }\n if (params?.alertActionId__in && params.alertActionId__in.length > 0) {\n queryParams.append('alertActionId__in', params.alertActionId__in.join(','))\n }\n if (params?.ruleId__in && params.ruleId__in.length > 0) {\n queryParams.append('ruleId__in', params.ruleId__in.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertActionRules${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert action rules:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AlertActionRule>\n debug('Alert action rules fetched:', data.results?.length ?? 0, 'rules')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert action rules: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert action rule by ID.\n *\n * @remarks\n * Fetches a single alert action rule from `/api/v3.0/alertActionRules/{id}`.\n *\n * @param ruleId - The unique identifier of the rule to fetch\n * @returns A Result containing the rule or an error\n *\n * @example\n * ```typescript\n * import { getAlertActionRule } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlertActionRule('rule-123')\n *\n * if (data) {\n * console.log(`Rule: ${data.name}`)\n * console.log(`Alert types: ${data.alertTypes.join(', ')}`)\n * console.log(`Actions: ${data.alertActionIds.length}`)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getAlertActionRule(\n ruleId: string\n): Promise<Result<AlertActionRule>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!ruleId) {\n return failure('VALIDATION_ERROR', 'Rule ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/alertActionRules/${encodeURIComponent(ruleId)}`\n debug('Fetching alert action rule:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as AlertActionRule\n debug('Alert action rule fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert action rule: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Alert Actions\n// =============================================================================\n\n/**\n * List alert actions with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alert actions from `/api/v3.0/alertActions`.\n * Alert actions define what happens when an alert is triggered (notifications,\n * webhooks, integrations, etc.).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of actions or an error\n *\n * @example\n * ```typescript\n * import { listAlertActions } from 'een-api-toolkit'\n *\n * // Get enabled webhook and notification actions\n * const { data, error } = await listAlertActions({\n * enabled: true,\n * type__in: ['notification', 'webhook']\n * })\n *\n * if (data) {\n * data.results.forEach(action => {\n * console.log(`${action.name} (${action.type})`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listAlertActions(\n params?: ListAlertActionsParams\n): Promise<Result<PaginatedResult<AutomationAlertAction>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.type__in && params.type__in.length > 0) {\n queryParams.append('type__in', params.type__in.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertActions${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert actions:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AutomationAlertAction>\n debug('Alert actions fetched:', data.results?.length ?? 0, 'actions')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert actions: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert action by ID.\n *\n * @remarks\n * Fetches a single alert action from `/api/v3.0/alertActions/{id}`.\n *\n * @param actionId - The unique identifier of the action to fetch\n * @returns A Result containing the action or an error\n *\n * @example\n * ```typescript\n * import { getAlertAction } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlertAction('action-123')\n *\n * if (data) {\n * console.log(`Action: ${data.name} (${data.type})`)\n * console.log('Settings:', data.settings)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getAlertAction(\n actionId: string\n): Promise<Result<AutomationAlertAction>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!actionId) {\n return failure('VALIDATION_ERROR', 'Action ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/alertActions/${encodeURIComponent(actionId)}`\n debug('Fetching alert action:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as AutomationAlertAction\n debug('Alert action fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert action: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n"],"names":["isDebugEnabled","__vite_import_meta_env__","debug","args","STORAGE_STRATEGY_DESCRIPTIONS","MemoryStorage","key","value","BrowserStorageAdapter","storage","currentStrategy","memoryStorageInstance","getMemoryStorage","setStorageStrategy","strategy","getStorageStrategy","getStorageAdapter","config","initEenToolkit","options","storageStrategy","getConfig","getProxyUrl","getClientId","getRedirectUri","success","data","failure","code","message","status","details","formatTimestamp","timestamp","refreshTokenFnPromise","getRefreshTokenFn","service","useAuthStore","defineStore","token","ref","tokenExpiration","refreshTokenMarker","sessionId","hostname","port","userProfile","refreshTimerId","isRefreshing","refreshPromise","refreshFailed","refreshFailedMessage","isAuthenticated","computed","baseUrl","isTokenExpired","tokenExpiresIn","setToken","newToken","expiresIn","saveToStorage","setupAutoRefresh","setRefreshTokenMarker","marker","setSessionId","newSessionId","setBaseUrl","url","err","setUserProfile","profile","now","timeUntilExpiry","fiveMinutes","halfTtl","refreshBuffer","refreshTime","timeout","performAutoRefresh","result","clearRefreshFailed","logout","clearStorage","initialize","loadFromStorage","expStr","portStr","profileStr","EEN_AUTH_URL","getAuthUrl","clientId","state","params","getAccessToken","proxyUrl","response","errorText","refreshToken","authStore","headers","revokeToken","handleAuthCallback","storedState","constantTimeEquals","a","b","i","getCurrentUser","handleErrorResponse","getUsers","queryParams","queryString","getUser","userId","errorData","getCameras","getCamera","cameraId","parseError","getBridges","getBridge","bridgeId","getLayouts","getLayout","layoutId","createLayout","body","updateLayout","deleteLayout","DEFAULT_TIMEOUT_MS","createTimeoutController","timeoutMs","controller","timeoutId","arrayBufferToBase64","buffer","bytes","chunkSize","chunks","chunk","str","j","binary","listMedia","getLiveImage","type","prevToken","arrayBuffer","imageData","getRecordedImage","nextToken","overlaySvg","getMediaSession","initMediaSession","sessionResult","sessionUrl","listFeeds","apiMessage","listEvents","getEvent","eventId","listEventTypes","listEventFieldValues","getEventMetrics","listAlerts","getAlert","alertId","listAlertTypes","listNotifications","getNotification","notificationId","listEventSubscriptions","getEventSubscription","subscriptionId","createEventSubscription","filter","deleteEventSubscription","connectToEventSubscription","sseUrl","sseUrlObj","domain","MAX_BUFFER_SIZE","abortController","isClosing","setStatus","newStatus","close","reader","decoder","done","lines","eventData","line","dataValue","event","listEventAlertConditionRules","getEventAlertConditionRuleFieldValues","getEventAlertConditionRule","ruleId","listAlertConditionRules","getAlertConditionRule","listAlertActionRules","getAlertActionRule","listAlertActions","getAlertAction","actionId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/utils/debug.ts","../src/utils/storage.ts","../src/config.ts","../src/types/common.ts","../src/utils/timestamp.ts","../src/auth/store.ts","../src/auth/service.ts","../src/users/service.ts","../src/cameras/service.ts","../src/bridges/service.ts","../src/layouts/service.ts","../src/media/service.ts","../src/feeds/service.ts","../src/events/service.ts","../src/eventMetrics/service.ts","../src/alerts/service.ts","../src/notifications/service.ts","../src/eventSubscriptions/service.ts","../src/automations/service.ts","../src/exports/service.ts","../src/jobs/service.ts","../src/files/service.ts","../src/downloads/service.ts"],"sourcesContent":["/**\n * Debug logging utility\n * Enabled when VITE_DEBUG=true in environment\n */\n\nconst isDebugEnabled = (): boolean => {\n try {\n return import.meta.env?.VITE_DEBUG === 'true'\n } catch {\n return false\n }\n}\n\nexport function debug(...args: unknown[]): void {\n if (isDebugEnabled()) {\n // eslint-disable-next-line no-console -- intentional debug logging\n console.log('[een-api-toolkit]', ...args)\n }\n}\n\nexport function debugWarn(...args: unknown[]): void {\n if (isDebugEnabled()) {\n console.warn('[een-api-toolkit]', ...args)\n }\n}\n\nexport function debugError(...args: unknown[]): void {\n if (isDebugEnabled()) {\n console.error('[een-api-toolkit]', ...args)\n }\n}\n","// Import StorageStrategy from types to maintain single source of truth\nimport type { StorageStrategy } from '../types'\nimport { debug } from './debug'\n\n// Re-export for convenience\nexport type { StorageStrategy }\n\n/**\n * Human-readable descriptions for each storage strategy.\n * Useful for displaying storage information in UI components.\n *\n * @example\n * ```typescript\n * import { getStorageStrategy, STORAGE_STRATEGY_DESCRIPTIONS } from 'een-api-toolkit'\n *\n * const strategy = getStorageStrategy()\n * const description = STORAGE_STRATEGY_DESCRIPTIONS[strategy]\n * console.log(`Using ${strategy}: ${description}`)\n * ```\n *\n * @category Configuration\n */\nexport const STORAGE_STRATEGY_DESCRIPTIONS: Record<StorageStrategy, string> = {\n localStorage: 'persists across sessions',\n sessionStorage: 'per-tab, cleared on tab close',\n memory: 'tokens lost on page refresh'\n}\n\n/**\n * Storage adapter interface for token persistence.\n * @internal\n */\nexport interface StorageAdapter {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/**\n * In-memory storage implementation.\n * Tokens are lost on page refresh but are immune to storage-based XSS attacks.\n * @internal\n */\nclass MemoryStorage implements StorageAdapter {\n private store = new Map<string, string>()\n\n getItem(key: string): string | null {\n return this.store.get(key) ?? null\n }\n\n setItem(key: string, value: string): void {\n this.store.set(key, value)\n }\n\n removeItem(key: string): void {\n this.store.delete(key)\n }\n}\n\n/**\n * Browser storage wrapper that delegates to localStorage/sessionStorage.\n * Errors are propagated to the caller (auth/store.ts) for proper logging.\n * @internal\n */\nclass BrowserStorageAdapter implements StorageAdapter {\n constructor(private storage: Storage) {}\n\n getItem(key: string): string | null {\n return this.storage.getItem(key)\n }\n\n setItem(key: string, value: string): void {\n this.storage.setItem(key, value)\n }\n\n removeItem(key: string): void {\n this.storage.removeItem(key)\n }\n}\n\n// Singleton instances\nlet currentStrategy: StorageStrategy = 'localStorage'\nlet memoryStorageInstance: MemoryStorage | null = null\n\n/**\n * Get the memory storage singleton instance.\n * @internal\n */\nfunction getMemoryStorage(): MemoryStorage {\n if (!memoryStorageInstance) {\n memoryStorageInstance = new MemoryStorage()\n }\n return memoryStorageInstance\n}\n\n/**\n * Set the storage strategy for the toolkit.\n *\n * @param strategy - The storage strategy to use\n *\n * @remarks\n * This should be called during toolkit initialization via {@link initEenToolkit}.\n * Changing the strategy after authentication may cause the current session to be lost.\n *\n * @internal\n */\nexport function setStorageStrategy(strategy: StorageStrategy): void {\n currentStrategy = strategy\n}\n\n/**\n * Get the current storage strategy.\n *\n * @returns The currently configured storage strategy\n *\n * @category Configuration\n */\nexport function getStorageStrategy(): StorageStrategy {\n return currentStrategy\n}\n\n/**\n * Get the storage adapter for the current strategy.\n *\n * @returns A storage adapter implementation based on the configured strategy\n *\n * @internal\n */\nexport function getStorageAdapter(): StorageAdapter {\n switch (currentStrategy) {\n case 'memory':\n return getMemoryStorage()\n case 'sessionStorage':\n if (typeof sessionStorage !== 'undefined') {\n return new BrowserStorageAdapter(sessionStorage)\n }\n // Fallback to memory if sessionStorage not available\n debug('sessionStorage unavailable, falling back to memory storage')\n return getMemoryStorage()\n case 'localStorage':\n default:\n if (typeof localStorage !== 'undefined') {\n return new BrowserStorageAdapter(localStorage)\n }\n // Fallback to memory if localStorage not available\n debug('localStorage unavailable, falling back to memory storage')\n return getMemoryStorage()\n }\n}\n\n/**\n * Clear the memory storage instance.\n * Useful for testing or when switching strategies.\n *\n * @internal\n */\nexport function clearMemoryStorage(): void {\n memoryStorageInstance = null\n}\n","import type { EenToolkitConfig, StorageStrategy } from './types'\nimport { setStorageStrategy, getStorageStrategy, STORAGE_STRATEGY_DESCRIPTIONS } from './utils/storage'\n\n/**\n * Global toolkit configuration\n */\nlet config: EenToolkitConfig = {}\n\n/**\n * Initialize the EEN API Toolkit\n *\n * @remarks\n * Call this function once at application startup before using any toolkit features.\n * The storage strategy determines how authentication tokens are persisted.\n *\n * @param options - Configuration options for the toolkit\n *\n * @example\n * ```typescript\n * import { initEenToolkit } from 'een-api-toolkit'\n *\n * // Basic initialization with localStorage (default, backwards compatible)\n * initEenToolkit({\n * proxyUrl: 'https://your-proxy.workers.dev',\n * clientId: 'your-client-id'\n * })\n *\n * // High-security initialization with memory-only storage\n * initEenToolkit({\n * proxyUrl: 'https://your-proxy.workers.dev',\n * clientId: 'your-client-id',\n * storageStrategy: 'memory'\n * })\n * ```\n */\nexport function initEenToolkit(options: EenToolkitConfig = {}): void {\n // Set storage strategy first (default to localStorage for backwards compatibility)\n const storageStrategy: StorageStrategy = options.storageStrategy ?? 'localStorage'\n setStorageStrategy(storageStrategy)\n\n config = {\n proxyUrl: options.proxyUrl ?? import.meta.env?.VITE_PROXY_URL,\n clientId: options.clientId ?? import.meta.env?.VITE_EEN_CLIENT_ID,\n redirectUri: options.redirectUri ?? import.meta.env?.VITE_REDIRECT_URI,\n storageStrategy,\n debug: options.debug ?? import.meta.env?.VITE_DEBUG === 'true'\n }\n}\n\nexport { getStorageStrategy, STORAGE_STRATEGY_DESCRIPTIONS }\n\n/**\n * Get the current configuration\n */\nexport function getConfig(): EenToolkitConfig {\n return config\n}\n\n/**\n * Get the proxy URL\n */\nexport function getProxyUrl(): string | undefined {\n return config.proxyUrl ?? import.meta.env?.VITE_PROXY_URL\n}\n\n/**\n * Get the client ID\n */\nexport function getClientId(): string | undefined {\n return config.clientId ?? import.meta.env?.VITE_EEN_CLIENT_ID\n}\n\n/**\n * Get the redirect URI\n */\nexport function getRedirectUri(): string {\n return config.redirectUri ?? import.meta.env?.VITE_REDIRECT_URI ?? 'http://127.0.0.1:3333'\n}\n","/**\n * Error codes returned by the toolkit.\n *\n * @remarks\n * All API functions return a {@link Result} type that contains either data or an error.\n * The error code helps you determine how to handle the failure.\n *\n * @category Types\n */\nexport type ErrorCode =\n | 'AUTH_REQUIRED'\n | 'AUTH_FAILED'\n | 'TOKEN_EXPIRED'\n | 'API_ERROR'\n | 'NETWORK_ERROR'\n | 'VALIDATION_ERROR'\n | 'NOT_FOUND'\n | 'FORBIDDEN'\n | 'RATE_LIMITED'\n | 'SERVICE_UNAVAILABLE'\n | 'UNKNOWN_ERROR'\n\n/**\n * Error object returned when an operation fails.\n *\n * @remarks\n * Contains structured error information including a machine-readable code,\n * human-readable message, and optional HTTP status code.\n *\n * @example\n * ```typescript\n * const { error } = await getUsers()\n * if (error) {\n * console.error(`${error.code}: ${error.message}`)\n * if (error.status === 401) {\n * redirectToLogin()\n * }\n * }\n * ```\n *\n * @category Types\n */\nexport interface EenError {\n /** Machine-readable error code for programmatic handling */\n code: ErrorCode\n /** Human-readable error message */\n message: string\n /** HTTP status code if the error came from an API response */\n status?: number\n /** Additional error details (varies by error type) */\n details?: unknown\n}\n\n/**\n * Result type for all API operations - functions never throw exceptions.\n *\n * @remarks\n * This is a discriminated union type. When `error` is `null`, `data` contains\n * the successful result. When `error` is not `null`, `data` is `null`.\n * TypeScript will narrow the type correctly after checking for errors.\n *\n * @example\n * ```typescript\n * const { data, error } = await getUsers()\n *\n * if (error) {\n * // TypeScript knows: data is null, error is EenError\n * console.error(error.message)\n * return\n * }\n *\n * // TypeScript knows: data is not null, error is null\n * console.log(data.results)\n * ```\n *\n * @typeParam T - The type of the data on success\n * @category Types\n */\nexport type Result<T> =\n | { data: T; error: null }\n | { data: null; error: EenError }\n\n/**\n * Pagination parameters for list operations.\n *\n * @remarks\n * Most list APIs in the EEN platform support pagination. Use `pageSize` to\n * control how many results are returned, and `pageToken` to fetch subsequent pages.\n *\n * @example\n * ```typescript\n * // First page\n * const { data } = await getUsers({ pageSize: 50 })\n *\n * // Next page (if available)\n * if (data.nextPageToken) {\n * const { data: page2 } = await getUsers({\n * pageSize: 50,\n * pageToken: data.nextPageToken\n * })\n * }\n * ```\n *\n * @category Types\n */\nexport interface PaginationParams {\n /** Number of results per page (default varies by endpoint, typically 100) */\n pageSize?: number\n /** Token for fetching a specific page (from previous response's nextPageToken) */\n pageToken?: string\n}\n\n/**\n * Paginated response from list operations.\n *\n * @remarks\n * Contains the results array and optional pagination tokens for navigating\n * through large result sets.\n *\n * @typeParam T - The type of items in the results array\n * @category Types\n */\nexport interface PaginatedResult<T> {\n /** Array of items for this page */\n results: T[]\n /** Token to fetch the next page (undefined if no more pages) */\n nextPageToken?: string\n /** Token to fetch the previous page (undefined if on first page) */\n prevPageToken?: string\n /** Total number of items across all pages (may not be provided by all endpoints) */\n totalSize?: number\n}\n\n/**\n * Storage strategy options for token persistence.\n *\n * @remarks\n * Different storage strategies offer different security/convenience tradeoffs:\n *\n * - **localStorage**: Tokens persist across browser sessions. Most convenient but\n * vulnerable to XSS attacks since JavaScript can access localStorage.\n *\n * - **sessionStorage**: Tokens persist within a single tab session. Cleared when\n * the tab is closed. Each tab has isolated storage, so opening a new tab\n * requires re-authentication.\n *\n * - **memory**: Tokens are only kept in memory (Pinia store). Most secure as\n * tokens are never written to disk, but any page refresh requires re-authentication.\n *\n * @category Configuration\n */\nexport type StorageStrategy = 'localStorage' | 'sessionStorage' | 'memory'\n\n/**\n * Configuration for initializing the toolkit.\n *\n * @remarks\n * Pass this to {@link initEenToolkit} to configure the library. All options\n * can also be set via environment variables (VITE_PROXY_URL, VITE_EEN_CLIENT_ID,\n * VITE_REDIRECT_URI, VITE_DEBUG).\n *\n * @example\n * ```typescript\n * import { initEenToolkit } from 'een-api-toolkit'\n *\n * initEenToolkit({\n * proxyUrl: 'https://your-proxy.workers.dev',\n * clientId: 'your-een-client-id',\n * redirectUri: 'http://localhost:5173/callback',\n * storageStrategy: 'sessionStorage', // More secure than default\n * debug: true\n * })\n * ```\n *\n * @category Configuration\n */\nexport interface EenToolkitConfig {\n /** URL of the OAuth proxy server (required for API calls) */\n proxyUrl?: string\n /** EEN OAuth client ID (required for authentication) */\n clientId?: string\n /** OAuth redirect URI (default: http://127.0.0.1:3333) */\n redirectUri?: string\n /**\n * Storage strategy for token persistence (default: 'localStorage').\n *\n * Security vs convenience tradeoffs:\n * - 'localStorage': Persists across sessions, vulnerable to XSS\n * - 'sessionStorage': Per-tab isolation, cleared on tab close\n * - 'memory': Most secure, lost on page refresh\n */\n storageStrategy?: StorageStrategy\n /** Enable debug logging to console */\n debug?: boolean\n}\n\n/**\n * Helper to create a success result.\n *\n * @param data - The successful result data\n * @returns A Result object with data and null error\n *\n * @internal\n */\nexport function success<T>(data: T): Result<T> {\n return { data, error: null }\n}\n\n/**\n * Helper to create an error result.\n *\n * @param code - The error code\n * @param message - Human-readable error message\n * @param status - Optional HTTP status code\n * @param details - Optional additional error details\n * @returns A Result object with null data and error\n *\n * @internal\n */\nexport function failure<T>(code: ErrorCode, message: string, status?: number, details?: unknown): Result<T> {\n return { data: null, error: { code, message, status, details } }\n}\n","/**\n * Convert ISO 8601 timestamp from Z format to +00:00 format.\n *\n * @remarks\n * The EEN API requires timestamps in +00:00 format, not Z format.\n * This function converts timestamps like `2024-01-01T00:00:00.000Z`\n * to `2024-01-01T00:00:00.000+00:00`.\n *\n * @param timestamp - ISO 8601 timestamp string\n * @returns Timestamp in +00:00 format\n *\n * @example\n * ```typescript\n * formatTimestamp('2024-01-01T00:00:00.000Z')\n * // Returns: '2024-01-01T00:00:00.000+00:00'\n *\n * formatTimestamp(new Date().toISOString())\n * // Returns: timestamp with +00:00 suffix\n * ```\n *\n * @category Utilities\n */\nexport function formatTimestamp(timestamp: string): string {\n // If already in +00:00 format, return as-is\n if (timestamp.endsWith('+00:00')) {\n return timestamp\n }\n // Convert Z to +00:00\n if (timestamp.endsWith('Z')) {\n return timestamp.replace('Z', '+00:00')\n }\n // Return original if format is not recognized\n return timestamp\n}\n","import { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport type { UserProfile } from '../types'\nimport type { Result } from '../types'\nimport { debug } from '../utils/debug'\nimport { getStorageAdapter } from '../utils/storage'\n\n// Lazy-loaded reference to refreshToken to avoid circular dependency at import time\n// Caches the promise (not the resolved value) to prevent race conditions with concurrent calls\nlet refreshTokenFnPromise: Promise<() => Promise<Result<{ accessToken: string; expiresIn: number }>>> | null = null\n\nfunction getRefreshTokenFn() {\n if (!refreshTokenFnPromise) {\n refreshTokenFnPromise = import('./service').then((service) => service.refreshToken)\n }\n return refreshTokenFnPromise\n}\n\n/**\n * Pinia store for authentication state management\n */\nexport const useAuthStore = defineStore('een-auth', () => {\n // State\n const token = ref<string | null>(null)\n const tokenExpiration = ref<number | null>(null)\n const refreshTokenMarker = ref<string | null>(null)\n const sessionId = ref<string | null>(null)\n const hostname = ref<string | null>(null)\n const port = ref<number>(443)\n const userProfile = ref<UserProfile | null>(null)\n const refreshTimerId = ref<ReturnType<typeof setTimeout> | null>(null)\n const isRefreshing = ref(false)\n let refreshPromise: Promise<void> | null = null\n const refreshFailed = ref(false)\n const refreshFailedMessage = ref<string | null>(null)\n\n // Computed\n const isAuthenticated = computed(() => !!token.value)\n\n const baseUrl = computed(() => {\n if (!hostname.value) return null\n return port.value === 443\n ? `https://${hostname.value}`\n : `https://${hostname.value}:${port.value}`\n })\n\n const isTokenExpired = computed(() => {\n if (!tokenExpiration.value) return true\n return Date.now() >= tokenExpiration.value\n })\n\n const tokenExpiresIn = computed(() => {\n if (!tokenExpiration.value) return 0\n return Math.max(0, tokenExpiration.value - Date.now())\n })\n\n // Actions\n function setToken(newToken: string, expiresIn: number) {\n token.value = newToken\n tokenExpiration.value = Date.now() + expiresIn * 1000\n saveToStorage()\n setupAutoRefresh()\n debug('Token set, expires in', expiresIn, 'seconds')\n }\n\n function setRefreshTokenMarker(marker: string) {\n refreshTokenMarker.value = marker\n saveToStorage()\n }\n\n function setSessionId(newSessionId: string) {\n sessionId.value = newSessionId\n saveToStorage()\n }\n\n function setBaseUrl(data: string | { hostname: string; port?: number }) {\n if (typeof data === 'string') {\n // Parse URL string\n try {\n const url = new URL(data.startsWith('http') ? data : `https://${data}`)\n hostname.value = url.hostname\n port.value = url.port ? parseInt(url.port, 10) : 443\n } catch (err: unknown) {\n // Invalid URL format, use as hostname directly\n debug('Failed to parse URL, using as hostname:', err instanceof Error ? err.message : String(err))\n hostname.value = data\n port.value = 443\n }\n } else {\n hostname.value = data.hostname\n port.value = data.port ?? 443\n }\n saveToStorage()\n debug('Base URL set:', baseUrl.value)\n }\n\n function setUserProfile(profile: UserProfile) {\n userProfile.value = profile\n saveToStorage()\n }\n\n function setupAutoRefresh() {\n // Clear existing timer\n if (refreshTimerId.value) {\n clearTimeout(refreshTimerId.value)\n refreshTimerId.value = null\n }\n\n if (!tokenExpiration.value || !token.value) {\n return\n }\n\n const now = Date.now()\n const expiresAt = tokenExpiration.value\n const timeUntilExpiry = expiresAt - now\n\n // Calculate refresh time: 5 minutes before expiration or 50% of TTL, whichever is earlier\n // Minimum: 1 minute before expiration, minimum timeout: 5 seconds\n const fiveMinutes = 5 * 60 * 1000\n const halfTtl = timeUntilExpiry / 2\n const refreshBuffer = Math.min(fiveMinutes, halfTtl)\n const refreshTime = Math.max(timeUntilExpiry - refreshBuffer, 60 * 1000)\n const timeout = Math.max(refreshTime, 5000)\n\n debug('Auto-refresh scheduled in', Math.round(timeout / 1000), 'seconds')\n\n refreshTimerId.value = setTimeout(async () => {\n await performAutoRefresh()\n }, timeout)\n }\n\n async function performAutoRefresh(): Promise<void> {\n // If refresh is already in progress, wait for the existing promise\n if (refreshPromise) {\n debug('Refresh already in progress, waiting for existing refresh')\n return refreshPromise\n }\n\n isRefreshing.value = true\n debug('Performing auto-refresh')\n\n refreshPromise = (async () => {\n try {\n const refreshToken = await getRefreshTokenFn()\n const result = await refreshToken()\n\n if (result.error) {\n refreshFailed.value = true\n refreshFailedMessage.value = result.error.message\n debug('Auto-refresh failed:', result.error.message)\n } else {\n refreshFailed.value = false\n refreshFailedMessage.value = null\n debug('Auto-refresh successful')\n }\n } catch (err: unknown) {\n refreshFailed.value = true\n refreshFailedMessage.value = err instanceof Error ? err.message : String(err)\n debug('Auto-refresh error:', err)\n } finally {\n isRefreshing.value = false\n refreshPromise = null\n }\n })()\n\n return refreshPromise\n }\n\n function clearRefreshFailed() {\n refreshFailed.value = false\n refreshFailedMessage.value = null\n }\n\n function logout() {\n // Clear timer\n if (refreshTimerId.value) {\n clearTimeout(refreshTimerId.value)\n refreshTimerId.value = null\n }\n\n // Clear state\n token.value = null\n tokenExpiration.value = null\n refreshTokenMarker.value = null\n sessionId.value = null\n hostname.value = null\n port.value = 443\n userProfile.value = null\n refreshFailed.value = false\n refreshFailedMessage.value = null\n\n // Clear storage\n clearStorage()\n debug('Logged out')\n }\n\n function initialize() {\n loadFromStorage()\n if (token.value && !isTokenExpired.value) {\n setupAutoRefresh()\n debug('Initialized from storage')\n } else if (token.value && isTokenExpired.value) {\n debug('Stored token expired, clearing')\n logout()\n }\n }\n\n // Storage helpers - use configured storage strategy\n function saveToStorage() {\n try {\n const storage = getStorageAdapter()\n if (token.value) storage.setItem('een_token', token.value)\n if (tokenExpiration.value) storage.setItem('een_tokenExpiration', String(tokenExpiration.value))\n if (refreshTokenMarker.value) storage.setItem('een_refreshTokenMarker', refreshTokenMarker.value)\n if (sessionId.value) storage.setItem('een_sessionId', sessionId.value)\n if (hostname.value) storage.setItem('een_hostname', hostname.value)\n if (port.value !== 443) storage.setItem('een_port', String(port.value))\n if (userProfile.value) storage.setItem('een_userProfile', JSON.stringify(userProfile.value))\n } catch (err: unknown) {\n // Storage might not be available (SSR, private browsing, etc.)\n debug('Failed to save to storage:', err instanceof Error ? err.message : String(err))\n }\n }\n\n function loadFromStorage() {\n try {\n const storage = getStorageAdapter()\n token.value = storage.getItem('een_token')\n const expStr = storage.getItem('een_tokenExpiration')\n tokenExpiration.value = expStr ? parseInt(expStr, 10) : null\n refreshTokenMarker.value = storage.getItem('een_refreshTokenMarker')\n sessionId.value = storage.getItem('een_sessionId')\n hostname.value = storage.getItem('een_hostname')\n const portStr = storage.getItem('een_port')\n port.value = portStr ? parseInt(portStr, 10) : 443\n const profileStr = storage.getItem('een_userProfile')\n userProfile.value = profileStr ? JSON.parse(profileStr) : null\n } catch (err: unknown) {\n // Storage might not be available (SSR, private browsing, etc.)\n debug('Failed to load from storage:', err instanceof Error ? err.message : String(err))\n }\n }\n\n function clearStorage() {\n try {\n const storage = getStorageAdapter()\n storage.removeItem('een_token')\n storage.removeItem('een_tokenExpiration')\n storage.removeItem('een_refreshTokenMarker')\n storage.removeItem('een_sessionId')\n storage.removeItem('een_hostname')\n storage.removeItem('een_port')\n storage.removeItem('een_userProfile')\n } catch (err: unknown) {\n // Storage might not be available (SSR, private browsing, etc.)\n debug('Failed to clear storage:', err instanceof Error ? err.message : String(err))\n }\n }\n\n return {\n // State\n token,\n tokenExpiration,\n refreshTokenMarker,\n sessionId,\n hostname,\n port,\n userProfile,\n isRefreshing,\n refreshFailed,\n refreshFailedMessage,\n\n // Computed\n isAuthenticated,\n baseUrl,\n isTokenExpired,\n tokenExpiresIn,\n\n // Actions\n setToken,\n setRefreshTokenMarker,\n setSessionId,\n setBaseUrl,\n setUserProfile,\n setupAutoRefresh,\n clearRefreshFailed,\n logout,\n initialize\n }\n})\n","import { useAuthStore } from './store'\nimport { getProxyUrl, getClientId, getRedirectUri } from '../config'\nimport { success, failure } from '../types'\nimport type { Result } from '../types'\nimport { debug } from '../utils/debug'\n\nconst EEN_AUTH_URL = 'https://auth.eagleeyenetworks.com/oauth2/authorize'\n\n/**\n * Token response from the OAuth proxy.\n *\n * @remarks\n * This is the response returned by the proxy's `/proxy/getAccessToken` endpoint\n * after successfully exchanging an authorization code for an access token.\n *\n * @category Authentication\n */\nexport interface TokenResponse {\n accessToken: string\n expiresIn: number\n httpsBaseUrl: string | { hostname: string; port?: number }\n userEmail: string\n sessionId: string\n}\n\n/**\n * Generate the OAuth authorization URL\n */\nexport function getAuthUrl(): string {\n const clientId = getClientId()\n if (!clientId) {\n throw new Error('Client ID not configured. Call initEenToolkit() or set VITE_EEN_CLIENT_ID')\n }\n\n // Generate and store state for CSRF protection\n const state = crypto.randomUUID()\n try {\n sessionStorage.setItem('een_oauth_state', state)\n } catch {\n // sessionStorage might not be available\n }\n\n const params = new URLSearchParams({\n client_id: clientId,\n response_type: 'code',\n scope: 'vms.all',\n redirect_uri: getRedirectUri(),\n state\n })\n\n debug('Generated auth URL with state:', state)\n return `${EEN_AUTH_URL}?${params.toString()}`\n}\n\n/**\n * Exchange authorization code for access token\n */\nexport async function getAccessToken(code: string): Promise<Result<TokenResponse>> {\n const proxyUrl = getProxyUrl()\n if (!proxyUrl) {\n return failure('AUTH_FAILED', 'Proxy URL not configured. Call initEenToolkit() or set VITE_PROXY_URL')\n }\n\n const params = new URLSearchParams({\n code,\n redirect_uri: getRedirectUri()\n })\n\n try {\n const response = await fetch(`${proxyUrl}/proxy/getAccessToken?${params.toString()}`, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n })\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error')\n return failure('AUTH_FAILED', `Token exchange failed: ${errorText}`, response.status)\n }\n\n const data = await response.json() as TokenResponse\n debug('Token received, expires in:', data.expiresIn)\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to exchange code: ${String(err)}`)\n }\n}\n\n/**\n * Refresh the access token using stored refresh token\n */\nexport async function refreshToken(): Promise<Result<{ accessToken: string; expiresIn: number }>> {\n const proxyUrl = getProxyUrl()\n if (!proxyUrl) {\n return failure('AUTH_FAILED', 'Proxy URL not configured')\n }\n\n const authStore = useAuthStore()\n\n try {\n const headers: HeadersInit = {\n 'Accept': 'application/json'\n }\n\n // Add session ID header as fallback for environments where cookies don't work\n if (authStore.sessionId) {\n headers['Authorization'] = `Bearer ${authStore.sessionId}`\n }\n\n const response = await fetch(`${proxyUrl}/proxy/refreshAccessToken`, {\n method: 'POST',\n credentials: 'include',\n headers\n })\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error')\n return failure('AUTH_FAILED', `Token refresh failed: ${errorText}`, response.status)\n }\n\n const data = await response.json() as { accessToken: string; expiresIn: number }\n\n // Update store with new token\n authStore.setToken(data.accessToken, data.expiresIn)\n\n debug('Token refreshed, expires in:', data.expiresIn)\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to refresh token: ${String(err)}`)\n }\n}\n\n/**\n * Revoke the current token and logout\n */\nexport async function revokeToken(): Promise<Result<void>> {\n const proxyUrl = getProxyUrl()\n if (!proxyUrl) {\n return failure('AUTH_FAILED', 'Proxy URL not configured')\n }\n\n const authStore = useAuthStore()\n\n try {\n const headers: HeadersInit = {\n 'Accept': 'application/json'\n }\n\n if (authStore.sessionId) {\n headers['Authorization'] = `Bearer ${authStore.sessionId}`\n }\n\n const response = await fetch(`${proxyUrl}/proxy/revoke`, {\n method: 'POST',\n credentials: 'include',\n headers\n })\n\n // Logout regardless of response\n authStore.logout()\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error')\n return failure('AUTH_FAILED', `Token revocation failed: ${errorText}`, response.status)\n }\n\n debug('Token revoked')\n return success(undefined)\n } catch (err) {\n // Still logout on error\n authStore.logout()\n return failure('NETWORK_ERROR', `Failed to revoke token: ${String(err)}`)\n }\n}\n\n/**\n * Handle OAuth callback - validates state and exchanges code for token\n */\nexport async function handleAuthCallback(code: string, state: string): Promise<Result<TokenResponse>> {\n // Validate state for CSRF protection\n let storedState: string | null = null\n try {\n storedState = sessionStorage.getItem('een_oauth_state')\n sessionStorage.removeItem('een_oauth_state')\n } catch {\n // sessionStorage might not be available\n }\n\n if (!storedState) {\n return failure('AUTH_FAILED', 'No OAuth state found. Please restart the login process.')\n }\n\n // Constant-time comparison to prevent timing attacks\n if (!constantTimeEquals(state, storedState)) {\n return failure('AUTH_FAILED', 'Invalid OAuth state. Possible CSRF attack.')\n }\n\n debug('State validated, exchanging code for token')\n\n // Exchange code for token\n const result = await getAccessToken(code)\n\n if (result.error) {\n return result\n }\n\n // Update auth store with received data\n const authStore = useAuthStore()\n const data = result.data\n\n authStore.setToken(data.accessToken, data.expiresIn)\n authStore.setRefreshTokenMarker('present')\n authStore.setSessionId(data.sessionId)\n authStore.setBaseUrl(data.httpsBaseUrl)\n\n debug('Auth callback complete, user:', data.userEmail)\n\n return success(data)\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks\n */\nfunction constantTimeEquals(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false\n }\n\n let result = 0\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\n }\n\n return result === 0\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, User, UserProfile, ListUsersParams, GetUserParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * Get the current authenticated user's profile.\n *\n * @remarks\n * Fetches the profile of the currently authenticated user from `/api/v3.0/users/self`.\n * The result is also stored in the auth store for easy access via `useAuthStore().userProfile`.\n *\n * @returns A Result containing the user profile or an error\n *\n * @example\n * ```typescript\n * import { getCurrentUser } from 'een-api-toolkit'\n *\n * const { data, error } = await getCurrentUser()\n *\n * if (error) {\n * if (error.code === 'AUTH_REQUIRED') {\n * router.push('/login')\n * }\n * return\n * }\n *\n * console.log(`Welcome, ${data.firstName} ${data.lastName}`)\n * ```\n *\n * @category Users\n */\nexport async function getCurrentUser(): Promise<Result<UserProfile>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/users/self`\n debug('Fetching current user:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as UserProfile\n debug('Current user fetched:', data.email)\n\n // Update profile in store\n authStore.setUserProfile(data)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch current user: ${String(err)}`)\n }\n}\n\n/**\n * List users with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of users from `/api/v3.0/users`. Use the `pageSize`\n * parameter to control how many results are returned per page, and `pageToken`\n * to navigate to subsequent pages.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getusers).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of users or an error\n *\n * @example\n * ```typescript\n * import { getUsers } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getUsers()\n * if (data) {\n * console.log(`Found ${data.results.length} users`)\n * }\n *\n * // With pagination\n * const { data } = await getUsers({ pageSize: 50 })\n * if (data?.nextPageToken) {\n * const { data: page2 } = await getUsers({\n * pageSize: 50,\n * pageToken: data.nextPageToken\n * })\n * }\n *\n * // Fetch all users\n * let allUsers: User[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getUsers({ pageSize: 100, pageToken })\n * if (error) break\n * allUsers.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Users\n */\nexport async function getUsers(params?: ListUsersParams): Promise<Result<PaginatedResult<User>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/users${queryString ? `?${queryString}` : ''}`\n debug('Fetching users:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<User>\n debug('Users fetched:', data.results?.length ?? 0, 'users')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch users: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific user by ID.\n *\n * @remarks\n * Fetches a single user from `/api/v3.0/users/{userId}`. Use the `include`\n * parameter to request additional fields like permissions.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getuser).\n *\n * @param userId - The unique identifier of the user to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the user or an error\n *\n * @example\n * ```typescript\n * import { getUser } from 'een-api-toolkit'\n *\n * const { data, error } = await getUser('user-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('User not found')\n * }\n * return\n * }\n *\n * console.log(`User: ${data.firstName} ${data.lastName}`)\n *\n * // With permissions\n * const { data: userWithPerms } = await getUser('user-123', {\n * include: ['permissions']\n * })\n * console.log('Permissions:', userWithPerms?.permissions)\n * ```\n *\n * @category Users\n */\nexport async function getUser(userId: string, params?: GetUserParams): Promise<Result<User>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!userId) {\n return failure('VALIDATION_ERROR', 'User ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/users/${encodeURIComponent(userId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching user:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as User\n debug('User fetched:', data.email)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch user: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, Camera, ListCamerasParams, GetCameraParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List cameras with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of cameras from `/api/v3.0/cameras`. Supports\n * extensive filtering options for location, status, tags, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listcameras).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of cameras or an error\n *\n * @example\n * ```typescript\n * import { getCameras } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getCameras()\n * if (data) {\n * console.log(`Found ${data.results.length} cameras`)\n * }\n *\n * // With filters\n * const { data } = await getCameras({\n * pageSize: 50,\n * status__in: ['online'],\n * include: ['deviceInfo', 'streamUrls']\n * })\n *\n * // Fetch all cameras\n * let allCameras: Camera[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getCameras({ pageSize: 100, pageToken })\n * if (error) break\n * allCameras.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Cameras\n */\nexport async function getCameras(params?: ListCamerasParams): Promise<Result<PaginatedResult<Camera>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include/Sort\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n // Location/Bridge filters\n if (params?.locationId__in && params.locationId__in.length > 0) {\n queryParams.append('locationId__in', params.locationId__in.join(','))\n }\n if (params?.bridgeId__in && params.bridgeId__in.length > 0) {\n queryParams.append('bridgeId__in', params.bridgeId__in.join(','))\n }\n\n // Multi-camera filters\n if (params?.multiCameraId) {\n queryParams.append('multiCameraId', params.multiCameraId)\n }\n if (params?.multiCameraId__ne) {\n queryParams.append('multiCameraId__ne', params.multiCameraId__ne)\n }\n if (params?.multiCameraId__in && params.multiCameraId__in.length > 0) {\n queryParams.append('multiCameraId__in', params.multiCameraId__in.join(','))\n }\n\n // Tag/Package filters\n if (params?.tags__contains && params.tags__contains.length > 0) {\n queryParams.append('tags__contains', params.tags__contains.join(','))\n }\n if (params?.tags__any && params.tags__any.length > 0) {\n queryParams.append('tags__any', params.tags__any.join(','))\n }\n if (params?.packages__contains && params.packages__contains.length > 0) {\n queryParams.append('packages__contains', params.packages__contains.join(','))\n }\n\n // Name filters\n if (params?.name) {\n queryParams.append('name', params.name)\n }\n if (params?.name__contains) {\n queryParams.append('name__contains', params.name__contains)\n }\n if (params?.name__in && params.name__in.length > 0) {\n queryParams.append('name__in', params.name__in.join(','))\n }\n\n // ID filters\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.id__notIn && params.id__notIn.length > 0) {\n queryParams.append('id__notIn', params.id__notIn.join(','))\n }\n if (params?.id__contains) {\n queryParams.append('id__contains', params.id__contains)\n }\n\n // Layout filter\n if (params?.layoutId) {\n queryParams.append('layoutId', params.layoutId)\n }\n\n // Share filters (use API nested field syntax)\n if (typeof params?.shared === 'boolean') {\n queryParams.append('shareDetails.shared', String(params.shared))\n }\n if (params?.sharedCameraAccount) {\n queryParams.append('shareDetails.accountId', params.sharedCameraAccount)\n }\n if (typeof params?.firstResponder === 'boolean') {\n queryParams.append('shareDetails.firstResponder', String(params.firstResponder))\n }\n\n // Device filters\n if (typeof params?.directToCloud === 'boolean') {\n queryParams.append('deviceInfo.directToCloud', String(params.directToCloud))\n }\n\n // Speaker filter\n if (params?.speakerId__in && params.speakerId__in.length > 0) {\n queryParams.append('speakerId__in', params.speakerId__in.join(','))\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n if (typeof params?.qRelevance__gte === 'number') {\n queryParams.append('qRelevance__gte', String(params.qRelevance__gte))\n }\n\n // Analytics filter\n if (params?.enabledAnalytics__contains && params.enabledAnalytics__contains.length > 0) {\n queryParams.append('enabledAnalytics__contains', params.enabledAnalytics__contains.join(','))\n }\n\n // Status filters\n if (params?.status__in && params.status__in.length > 0) {\n queryParams.append('status__in', params.status__in.join(','))\n }\n if (params?.status__ne) {\n queryParams.append('status__ne', params.status__ne)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/cameras${queryString ? `?${queryString}` : ''}`\n debug('Fetching cameras:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Camera>\n debug('Cameras fetched:', data.results?.length ?? 0, 'cameras')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch cameras: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific camera by ID.\n *\n * @remarks\n * Fetches a single camera from `/api/v3.0/cameras/{cameraId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getcamera).\n *\n * @param cameraId - The unique identifier of the camera to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the camera or an error\n *\n * @example\n * ```typescript\n * import { getCamera } from 'een-api-toolkit'\n *\n * const { data, error } = await getCamera('camera-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Camera not found')\n * }\n * return\n * }\n *\n * console.log(`Camera: ${data.name} (${data.status})`)\n *\n * // With additional fields\n * const { data: cameraWithDetails } = await getCamera('camera-123', {\n * include: ['deviceInfo', 'streamUrls', 'shareDetails']\n * })\n * ```\n *\n * @category Cameras\n */\nexport async function getCamera(cameraId: string, params?: GetCameraParams): Promise<Result<Camera>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!cameraId) {\n return failure('VALIDATION_ERROR', 'Camera ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/cameras/${encodeURIComponent(cameraId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching camera:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Camera\n debug('Camera fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch camera: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, Bridge, ListBridgesParams, GetBridgeParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List bridges with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of bridges from `/api/v3.0/bridges`. Supports\n * filtering options for location, status, tags, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listbridges).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of bridges or an error\n *\n * @example\n * ```typescript\n * import { getBridges } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getBridges()\n * if (data) {\n * console.log(`Found ${data.results.length} bridges`)\n * }\n *\n * // With filters\n * const { data } = await getBridges({\n * pageSize: 50,\n * status__in: ['online'],\n * include: ['deviceInfo', 'networkInfo']\n * })\n *\n * // Fetch all bridges\n * let allBridges: Bridge[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getBridges({ pageSize: 100, pageToken })\n * if (error) break\n * allBridges.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Bridges\n */\nexport async function getBridges(params?: ListBridgesParams): Promise<Result<PaginatedResult<Bridge>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include/Sort\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n // Location filters\n if (params?.locationId__in && params.locationId__in.length > 0) {\n queryParams.append('locationId__in', params.locationId__in.join(','))\n }\n\n // Tag filters\n if (params?.tags__contains && params.tags__contains.length > 0) {\n queryParams.append('tags__contains', params.tags__contains.join(','))\n }\n if (params?.tags__any && params.tags__any.length > 0) {\n queryParams.append('tags__any', params.tags__any.join(','))\n }\n\n // Name filters\n if (params?.name) {\n queryParams.append('name', params.name)\n }\n if (params?.name__contains) {\n queryParams.append('name__contains', params.name__contains)\n }\n if (params?.name__in && params.name__in.length > 0) {\n queryParams.append('name__in', params.name__in.join(','))\n }\n\n // ID filters\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.id__notIn && params.id__notIn.length > 0) {\n queryParams.append('id__notIn', params.id__notIn.join(','))\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n if (typeof params?.qRelevance__gte === 'number') {\n queryParams.append('qRelevance__gte', String(params.qRelevance__gte))\n }\n\n // Status filters\n if (params?.status__in && params.status__in.length > 0) {\n queryParams.append('status__in', params.status__in.join(','))\n }\n if (params?.status__ne) {\n queryParams.append('status__ne', params.status__ne)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/bridges${queryString ? `?${queryString}` : ''}`\n debug('Fetching bridges:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Bridge>\n debug('Bridges fetched:', data.results?.length ?? 0, 'bridges')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch bridges: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific bridge by ID.\n *\n * @remarks\n * Fetches a single bridge from `/api/v3.0/bridges/{bridgeId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getbridge).\n *\n * @param bridgeId - The unique identifier of the bridge to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the bridge or an error\n *\n * @example\n * ```typescript\n * import { getBridge } from 'een-api-toolkit'\n *\n * const { data, error } = await getBridge('bridge-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Bridge not found')\n * }\n * return\n * }\n *\n * console.log(`Bridge: ${data.name} (${data.status})`)\n *\n * // With additional fields\n * const { data: bridgeWithDetails } = await getBridge('bridge-123', {\n * include: ['deviceInfo', 'networkInfo', 'status']\n * })\n * ```\n *\n * @category Bridges\n */\nexport async function getBridge(bridgeId: string, params?: GetBridgeParams): Promise<Result<Bridge>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!bridgeId) {\n return failure('VALIDATION_ERROR', 'Bridge ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/bridges/${encodeURIComponent(bridgeId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching bridge:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Bridge\n debug('Bridge fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch bridge: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Layout,\n ListLayoutsParams,\n GetLayoutParams,\n CreateLayoutParams,\n UpdateLayoutParams\n} from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List layouts with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of layouts from `/api/v3.0/layouts`. Supports\n * filtering options for name, search, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listlayouts).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of layouts or an error\n *\n * @example\n * ```typescript\n * import { getLayouts } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await getLayouts()\n * if (data) {\n * console.log(`Found ${data.results.length} layouts`)\n * }\n *\n * // With filters\n * const { data } = await getLayouts({\n * pageSize: 50,\n * include: ['resourceCounts', 'effectivePermissions']\n * })\n *\n * // Fetch all layouts\n * let allLayouts: Layout[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await getLayouts({ pageSize: 100, pageToken })\n * if (error) break\n * allLayouts.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Layouts\n */\nexport async function getLayouts(params?: ListLayoutsParams): Promise<Result<PaginatedResult<Layout>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include/Sort\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n // Name filters\n if (params?.name) {\n queryParams.append('name', params.name)\n }\n if (params?.name__in && params.name__in.length > 0) {\n queryParams.append('name__in', params.name__in.join(','))\n }\n if (params?.name__contains) {\n queryParams.append('name__contains', params.name__contains)\n }\n\n // ID filters\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n\n // Bridge filter\n if (params?.['layoutPanes.cameras.bridgeId']) {\n queryParams.append('layoutPanes.cameras.bridgeId', params['layoutPanes.cameras.bridgeId'])\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n if (typeof params?.qRelevance__gte === 'number') {\n queryParams.append('qRelevance__gte', String(params.qRelevance__gte))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/layouts${queryString ? `?${queryString}` : ''}`\n debug('Fetching layouts:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Layout>\n debug('Layouts fetched:', data.results?.length ?? 0, 'layouts')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch layouts: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific layout by ID.\n *\n * @remarks\n * Fetches a single layout from `/api/v3.0/layouts/{layoutId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getlayout).\n *\n * @param layoutId - The unique identifier of the layout to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the layout or an error\n *\n * @example\n * ```typescript\n * import { getLayout } from 'een-api-toolkit'\n *\n * const { data, error } = await getLayout('layout-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Layout not found')\n * }\n * return\n * }\n *\n * console.log(`Layout: ${data.name} (${data.panes.length} panes)`)\n *\n * // With additional fields\n * const { data: layoutWithDetails } = await getLayout('layout-123', {\n * include: ['effectivePermissions', 'resourceStatusCounts']\n * })\n * ```\n *\n * @category Layouts\n */\nexport async function getLayout(layoutId: string, params?: GetLayoutParams): Promise<Result<Layout>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!layoutId) {\n return failure('VALIDATION_ERROR', 'Layout ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/layouts/${encodeURIComponent(layoutId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching layout:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Layout\n debug('Layout fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch layout: ${String(err)}`)\n }\n}\n\n/**\n * Create a new layout.\n *\n * @remarks\n * Creates a layout via `POST /api/v3.0/layouts`. Name and settings are required.\n * Panes can be added during creation or later via `updateLayout()`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/createlayout).\n *\n * @param params - The layout configuration\n * @returns A Result containing the created layout or an error\n *\n * @example\n * ```typescript\n * import { createLayout } from 'een-api-toolkit'\n *\n * const { data, error } = await createLayout({\n * name: 'Main Lobby View',\n * settings: {\n * showCameraBorder: true,\n * showCameraName: true,\n * cameraAspectRatio: '16x9',\n * paneColumns: 3\n * },\n * panes: [\n * { id: 1, name: 'Entrance', type: 'preview', size: 1, cameraId: 'cam-123' },\n * { id: 2, name: 'Lobby', type: 'preview', size: 2, cameraId: 'cam-456' }\n * ]\n * })\n *\n * if (data) {\n * console.log(`Created layout: ${data.id}`)\n * }\n * ```\n *\n * @category Layouts\n */\nexport async function createLayout(params: CreateLayoutParams): Promise<Result<Layout>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.name) {\n return failure('VALIDATION_ERROR', 'Layout name is required')\n }\n\n if (!params.settings) {\n return failure('VALIDATION_ERROR', 'Layout settings are required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/layouts`\n debug('Creating layout:', params.name)\n\n const body: Record<string, unknown> = {\n name: params.name,\n settings: params.settings\n }\n\n if (params.panes) {\n body.panes = params.panes\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(body)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Layout\n debug('Layout created:', data.id, data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to create layout: ${String(err)}`)\n }\n}\n\n/**\n * Update an existing layout.\n *\n * @remarks\n * Updates a layout via `PATCH /api/v3.0/layouts/{layoutId}`. Only provided\n * fields will be updated. Returns void on success (204 No Content).\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/updatelayout).\n *\n * @param layoutId - The unique identifier of the layout to update\n * @param params - The fields to update\n * @returns A Result containing void on success or an error\n *\n * @example\n * ```typescript\n * import { updateLayout } from 'een-api-toolkit'\n *\n * // Update name only\n * const { error } = await updateLayout('layout-123', {\n * name: 'Updated Layout Name'\n * })\n *\n * // Update settings\n * const { error } = await updateLayout('layout-123', {\n * settings: {\n * paneColumns: 4,\n * showCameraName: false\n * }\n * })\n *\n * // Replace panes\n * const { error } = await updateLayout('layout-123', {\n * panes: [\n * { id: 1, name: 'New Pane', type: 'preview', size: 1, cameraId: 'cam-789' }\n * ]\n * })\n *\n * if (error) {\n * console.error('Update failed:', error.message)\n * }\n * ```\n *\n * @category Layouts\n */\nexport async function updateLayout(layoutId: string, params: UpdateLayoutParams): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!layoutId) {\n return failure('VALIDATION_ERROR', 'Layout ID is required')\n }\n\n if (params.name === undefined && params.settings === undefined && params.panes === undefined) {\n return failure('VALIDATION_ERROR', 'At least one field (name, settings, or panes) must be provided for update')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/layouts/${encodeURIComponent(layoutId)}`\n debug('Updating layout:', layoutId)\n\n const body: Record<string, unknown> = {}\n\n if (params.name !== undefined) {\n body.name = params.name\n }\n if (params.settings !== undefined) {\n body.settings = params.settings\n }\n if (params.panes !== undefined) {\n body.panes = params.panes\n }\n\n try {\n const response = await fetch(url, {\n method: 'PATCH',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(body)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('Layout updated:', layoutId)\n\n return success(undefined)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to update layout: ${String(err)}`)\n }\n}\n\n/**\n * Delete a layout.\n *\n * @remarks\n * Deletes a layout via `DELETE /api/v3.0/layouts/{layoutId}`.\n * Returns void on success (204 No Content).\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/deletelayout).\n *\n * @param layoutId - The unique identifier of the layout to delete\n * @returns A Result containing void on success or an error\n *\n * @example\n * ```typescript\n * import { deleteLayout } from 'een-api-toolkit'\n *\n * const { error } = await deleteLayout('layout-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Layout already deleted')\n * } else {\n * console.error('Delete failed:', error.message)\n * }\n * } else {\n * console.log('Layout deleted successfully')\n * }\n * ```\n *\n * @category Layouts\n */\nexport async function deleteLayout(layoutId: string): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!layoutId) {\n return failure('VALIDATION_ERROR', 'Layout ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/layouts/${encodeURIComponent(layoutId)}`\n debug('Deleting layout:', layoutId)\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('Layout deleted:', layoutId)\n\n return success(undefined)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to delete layout: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 400:\n return failure('VALIDATION_ERROR', `Bad request: ${message}`, status)\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n MediaInterval,\n ListMediaParams,\n GetLiveImageParams,\n GetRecordedImageParams,\n LiveImageResult,\n RecordedImageResult,\n MediaSessionResponse,\n MediaSessionResult\n} from '../types'\nimport { debug } from '../utils/debug'\n\n/** Default timeout for media requests in milliseconds */\nconst DEFAULT_TIMEOUT_MS = 30000\n\n/**\n * Create an AbortController with a timeout.\n * @internal\n */\nfunction createTimeoutController(timeoutMs: number = DEFAULT_TIMEOUT_MS): { controller: AbortController; timeoutId: ReturnType<typeof setTimeout> } {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs)\n return { controller, timeoutId }\n}\n\n/**\n * Convert ArrayBuffer to base64 string.\n *\n * @remarks\n * **Memory Considerations**: This function loads the entire image into memory\n * as a string. For typical camera preview images (<500KB), this is efficient.\n * For larger images (>2MB), consider streaming or chunked processing in the\n * consuming application. Base64 encoding adds ~33% size overhead.\n *\n * @internal\n */\nfunction arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n // Use chunked approach with array join for O(n) complexity instead of O(n²) string concatenation\n // Iterate byte-by-byte within chunks to avoid call stack issues with String.fromCharCode.apply()\n const chunkSize = 8192\n const chunks: string[] = []\n for (let i = 0; i < bytes.byteLength; i += chunkSize) {\n const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.byteLength))\n let str = ''\n for (let j = 0; j < chunk.length; j++) {\n str += String.fromCharCode(chunk[j]!)\n }\n chunks.push(str)\n }\n const binary = chunks.join('')\n // Use btoa in browser, Buffer in Node.js\n if (typeof btoa === 'function') {\n return btoa(binary)\n }\n return Buffer.from(binary, 'binary').toString('base64')\n}\n\n/**\n * List media intervals (recording periods) for a device.\n *\n * @remarks\n * Fetches a paginated list of time intervals for which recordings exist.\n * Use this to find available recordings for a camera.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listmedia).\n *\n * @param params - Required parameters including deviceId, type, mediaType, and startTimestamp\n * @returns A Result containing a paginated list of media intervals or an error\n *\n * @example\n * ```typescript\n * import { listMedia } from 'een-api-toolkit'\n *\n * // Get video recordings from the last hour\n * const { data, error } = await listMedia({\n * deviceId: 'camera-123',\n * type: 'preview',\n * mediaType: 'video',\n * startTimestamp: new Date(Date.now() - 3600000).toISOString()\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} recording intervals`)\n * data.results.forEach(interval => {\n * console.log(`${interval.startTimestamp} - ${interval.endTimestamp}`)\n * })\n * }\n * ```\n *\n * @category Media\n */\nexport async function listMedia(params: ListMediaParams): Promise<Result<PaginatedResult<MediaInterval>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.deviceId) {\n return failure('VALIDATION_ERROR', 'Device ID is required')\n }\n if (!params.type) {\n return failure('VALIDATION_ERROR', 'Stream type is required (preview or main)')\n }\n if (!params.mediaType) {\n return failure('VALIDATION_ERROR', 'Media type is required (video or image)')\n }\n if (!params.startTimestamp) {\n return failure('VALIDATION_ERROR', 'Start timestamp is required')\n }\n\n const queryParams = new URLSearchParams()\n\n // Required parameters\n queryParams.append('deviceId', params.deviceId)\n queryParams.append('type', params.type)\n queryParams.append('mediaType', params.mediaType)\n queryParams.append('startTimestamp__gte', params.startTimestamp)\n\n // Optional parameters\n if (params.endTimestamp) {\n queryParams.append('endTimestamp__lte', params.endTimestamp)\n }\n if (typeof params.coalesce === 'boolean') {\n queryParams.append('coalesce', String(params.coalesce))\n }\n if (params.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n if (typeof params.pageSize === 'number') {\n queryParams.append('pageSize', String(params.pageSize))\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/media?${queryParams.toString()}`\n debug('Fetching media intervals:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<MediaInterval>\n debug('Media intervals fetched:', data.results?.length ?? 0, 'intervals')\n\n return success(data)\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch media intervals: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Get a live image from a camera.\n *\n * @remarks\n * Fetches a new live image from the specified camera. This call waits until\n * a new image is available from the device. The image is returned as a\n * base64 data URL that can be used directly in an HTML img element.\n *\n * Note: Live images only support the 'preview' stream type.\n *\n * **Memory Considerations**: Images are loaded into memory and base64 encoded,\n * adding ~33% size overhead. Typical preview images are <500KB. For high-frequency\n * polling, consider implementing error backoff and limiting concurrent requests.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getliveimage).\n *\n * @param params - Parameters including the required deviceId\n * @returns A Result containing the live image data or an error\n *\n * @example\n * ```typescript\n * import { getLiveImage } from 'een-api-toolkit'\n *\n * const { data, error } = await getLiveImage({ deviceId: 'camera-123' })\n *\n * if (data) {\n * // Display in an img element\n * document.getElementById('cameraImage').src = data.imageData\n * console.log('Image timestamp:', data.timestamp)\n * }\n *\n * // Continuously update the image with proper error handling\n * let isRunning = true\n * async function refreshLoop() {\n * const imgElement = document.getElementById('cameraImage') as HTMLImageElement\n * while (isRunning) {\n * const { data, error } = await getLiveImage({ deviceId: 'camera-123' })\n * if (error) {\n * console.error('Refresh failed:', error.message)\n * break // Stop on error\n * }\n * if (data) {\n * imgElement.src = data.imageData\n * }\n * await new Promise(r => setTimeout(r, 1000))\n * }\n * }\n * // Call refreshLoop() to start, set isRunning = false to stop\n * ```\n *\n * @category Media\n */\nexport async function getLiveImage(params: GetLiveImageParams): Promise<Result<LiveImageResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.deviceId) {\n return failure('VALIDATION_ERROR', 'Device ID is required')\n }\n\n // Live images only support 'preview' type (enforced by TypeScript)\n const type = params.type ?? 'preview'\n\n const queryParams = new URLSearchParams()\n queryParams.append('deviceId', params.deviceId)\n queryParams.append('type', type)\n\n const url = `${authStore.baseUrl}/api/v3.0/media/liveImage.jpeg?${queryParams.toString()}`\n debug('Fetching live image:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'image/jpeg',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n // Get headers before checking response.ok\n const timestamp = response.headers.get('X-Een-Timestamp')\n const prevToken = response.headers.get('X-Een-PrevToken')\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // Get image as base64\n const arrayBuffer = await response.arrayBuffer()\n const base64 = arrayBufferToBase64(arrayBuffer)\n const imageData = `data:image/jpeg;base64,${base64}`\n\n debug('Live image fetched, timestamp:', timestamp)\n\n return success({\n imageData,\n timestamp,\n prevToken\n })\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch live image: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Get a recorded image from a camera.\n *\n * @remarks\n * Fetches a recorded image from the specified camera at a specific timestamp.\n * You can specify the desired timestamp using various operators (exact, gte, lte, etc.)\n * or use a pageToken from a previous request to navigate through images.\n *\n * The image is returned as a base64 data URL that can be used directly in an HTML img element.\n *\n * Note: The 'main' type is rate-limited and requires an actual recording at the timestamp.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getrecordedimage).\n *\n * @param params - Parameters including deviceId/pageToken and timestamp options\n * @returns A Result containing the recorded image data or an error\n *\n * @example\n * ```typescript\n * import { getRecordedImage } from 'een-api-toolkit'\n *\n * // Get image at or after a specific time\n * const { data, error } = await getRecordedImage({\n * deviceId: 'camera-123',\n * type: 'preview',\n * timestamp__gte: '2024-01-15T10:00:00.000Z'\n * })\n *\n * if (data) {\n * imgElement.src = data.imageData\n * console.log('Actual timestamp:', data.timestamp)\n *\n * // Get the next image using the token\n * if (data.nextToken) {\n * const { data: nextImage } = await getRecordedImage({\n * pageToken: data.nextToken\n * })\n * }\n * }\n * ```\n *\n * @category Media\n */\nexport async function getRecordedImage(params: GetRecordedImageParams): Promise<Result<RecordedImageResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate: either deviceId or pageToken is required\n if (!params.deviceId && !params.pageToken) {\n return failure('VALIDATION_ERROR', 'Either deviceId or pageToken is required')\n }\n\n // If not using pageToken, validate at least one timestamp parameter\n if (!params.pageToken) {\n const hasTimestamp = params.timestamp__lt || params.timestamp__lte ||\n params.timestamp || params.timestamp__gte || params.timestamp__gt\n if (!hasTimestamp) {\n return failure('VALIDATION_ERROR', 'At least one timestamp parameter is required')\n }\n }\n\n // Validate overlay requirements\n if (params.include?.includes('overlaySvgHeader') &&\n (!params.overlayId__in || params.overlayId__in.length === 0)) {\n return failure('VALIDATION_ERROR', 'At least one overlayId must be provided when requesting overlay headers')\n }\n\n const queryParams = new URLSearchParams()\n\n // Add parameters\n if (params.deviceId) {\n queryParams.append('deviceId', params.deviceId)\n }\n if (params.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n if (params.type) {\n queryParams.append('type', params.type)\n }\n\n // Timestamp parameters\n if (params.timestamp__lt) {\n queryParams.append('timestamp__lt', params.timestamp__lt)\n }\n if (params.timestamp__lte) {\n queryParams.append('timestamp__lte', params.timestamp__lte)\n }\n if (params.timestamp) {\n queryParams.append('timestamp', params.timestamp)\n }\n if (params.timestamp__gte) {\n queryParams.append('timestamp__gte', params.timestamp__gte)\n }\n if (params.timestamp__gt) {\n queryParams.append('timestamp__gt', params.timestamp__gt)\n }\n\n // Overlay parameters\n if (params.overlayId__in && params.overlayId__in.length > 0) {\n queryParams.append('overlayId__in', params.overlayId__in.join(','))\n }\n if (params.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n // Size parameters\n if (typeof params.targetWidth === 'number') {\n queryParams.append('targetWidth', String(params.targetWidth))\n }\n if (typeof params.targetHeight === 'number') {\n queryParams.append('targetHeight', String(params.targetHeight))\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/media/recordedImage.jpeg?${queryParams.toString()}`\n debug('Fetching recorded image:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'image/jpeg',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n // Get headers before checking response.ok\n const timestamp = response.headers.get('X-Een-Timestamp')\n const nextToken = response.headers.get('X-Een-NextToken')\n const prevToken = response.headers.get('X-Een-PrevToken')\n const overlaySvg = response.headers.get('X-Een-OverlaySvg')\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // Get image as base64\n const arrayBuffer = await response.arrayBuffer()\n const base64 = arrayBufferToBase64(arrayBuffer)\n const imageData = `data:image/jpeg;base64,${base64}`\n\n debug('Recorded image fetched, timestamp:', timestamp)\n\n return success({\n imageData,\n timestamp,\n nextToken,\n prevToken,\n overlaySvg\n })\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch recorded image: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n case 503:\n return failure('SERVICE_UNAVAILABLE', `Service unavailable: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n\n/**\n * Get the media session URL for setting cookies.\n *\n * @remarks\n * Fetches the URL needed to set the media session cookie. The returned URL\n * must be called separately (with credentials included) to actually set the\n * cookie. This is the first step in the two-step media session initialization\n * process.\n *\n * For most use cases, prefer using {@link initMediaSession} which handles\n * both steps automatically.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/docs/watch-live-video).\n *\n * @returns A Result containing the media session URL or an error\n *\n * @example\n * ```typescript\n * import { getMediaSession } from 'een-api-toolkit'\n *\n * // Get the session URL (step 1)\n * const { data, error } = await getMediaSession()\n *\n * if (data) {\n * console.log('Session URL:', data.url)\n * // Now call data.url with credentials: 'include' to set the cookie\n * }\n * ```\n *\n * @category Media\n */\nexport async function getMediaSession(): Promise<Result<MediaSessionResponse>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/media/session`\n debug('Fetching media session:', url)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as MediaSessionResponse\n debug('Media session URL received:', data.url)\n\n return success(data)\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out')\n }\n return failure('NETWORK_ERROR', `Failed to fetch media session: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\n/**\n * Initialize the media session by setting the session cookie.\n *\n * @remarks\n * This function handles the two-step process of setting up a media session:\n * 1. Fetches the session URL from `/api/v3.0/media/session`\n * 2. Calls that URL with credentials to set the session cookie\n *\n * Once the session cookie is set, the browser can access media streams\n * (like multipart preview URLs) without explicit Authorization headers.\n * This is required for using media URLs directly in HTML elements like\n * `<img>` or `<video>`.\n *\n * **Important**: This function must be called in a browser environment\n * where cookies can be set. It uses `credentials: 'include'` to ensure\n * the cookie is stored.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/docs/watch-live-video).\n *\n * @returns A Result containing the session result or an error\n *\n * @example\n * ```typescript\n * import { initMediaSession, listFeeds } from 'een-api-toolkit'\n *\n * // Initialize the media session (do this once after login)\n * const { data, error } = await initMediaSession()\n *\n * if (error) {\n * console.error('Failed to init media session:', error.message)\n * return\n * }\n *\n * // Now you can use multipart URLs directly in <img> elements\n * const { data: feeds } = await listFeeds({\n * deviceId: 'camera-123',\n * include: ['multipartUrl']\n * })\n *\n * if (feeds?.results[0]?.multipartUrl) {\n * // This works because the session cookie is set\n * imgElement.src = feeds.results[0].multipartUrl\n * }\n * ```\n *\n * @category Media\n */\nexport async function initMediaSession(): Promise<Result<MediaSessionResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n // Step 1: Get the media session URL\n const sessionResult = await getMediaSession()\n\n if (sessionResult.error) {\n return failure(\n sessionResult.error.code,\n `Failed to get media session: ${sessionResult.error.message}`,\n sessionResult.error.status\n )\n }\n\n if (!sessionResult.data?.url) {\n return failure('API_ERROR', 'No session URL returned from media session endpoint')\n }\n\n const sessionUrl = sessionResult.data.url\n debug('Calling session URL to set cookie:', sessionUrl)\n\n const { controller, timeoutId } = createTimeoutController()\n\n try {\n // Step 2: Call the session URL to set the cookie\n const response = await fetch(sessionUrl, {\n method: 'GET',\n credentials: 'include', // Critical: include cookies in the request/response\n headers: {\n 'Accept': '*/*',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: controller.signal\n })\n\n // The session endpoint typically returns 204 No Content on success\n // but may also return 200 OK\n if (!response.ok && response.status !== 204) {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n return failure('API_ERROR', `Failed to set media session cookie: ${message}`, status)\n }\n\n debug('Media session cookie set successfully')\n\n return success({\n success: true,\n sessionUrl\n })\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n return failure('NETWORK_ERROR', 'Request timed out while setting session cookie')\n }\n return failure('NETWORK_ERROR', `Failed to set media session cookie: ${String(err)}`)\n } finally {\n clearTimeout(timeoutId)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, ListFeedsParams, ListFeedsResult } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List feeds with optional filtering and pagination.\n *\n * @remarks\n * Fetches a list of feeds from `/api/v3.0/feeds`. Feeds represent live or\n * recorded streams from devices (cameras, speakers). Use the `include` parameter\n * to request specific streaming URLs.\n *\n * A single device can have multiple feeds (main, preview, talkdown) with\n * different quality levels and purposes.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listfeeds).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a list of feeds or an error\n *\n * @example\n * ```typescript\n * import { listFeeds } from 'een-api-toolkit'\n * import type { Feed } from 'een-api-toolkit'\n *\n * // Get all feeds\n * const { data, error } = await listFeeds()\n * if (data) {\n * console.log(`Found ${data.results.length} feeds`)\n * }\n *\n * // Get feeds for a specific camera with streaming URLs\n * const { data: cameraFeeds } = await listFeeds({\n * deviceId: 'camera-123',\n * include: ['hlsUrl', 'multipartUrl']\n * })\n *\n * // Get preview feeds for multiple cameras\n * const { data: previewFeeds } = await listFeeds({\n * deviceId__in: ['camera-1', 'camera-2'],\n * type: 'preview',\n * include: ['hlsUrl']\n * })\n *\n * // Paginate through all feeds\n * let allFeeds: Feed[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listFeeds({ pageSize: 100, pageToken })\n * if (error) break\n * allFeeds.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Feeds\n */\nexport async function listFeeds(params?: ListFeedsParams): Promise<Result<ListFeedsResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (typeof params?.pageSize === 'number') {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Device filters\n if (params?.deviceId) {\n queryParams.append('deviceId', params.deviceId)\n }\n if (params?.deviceId__in && params.deviceId__in.length > 0) {\n queryParams.append('deviceId__in', params.deviceId__in.join(','))\n }\n\n // Type filter\n if (params?.type) {\n queryParams.append('type', params.type)\n }\n\n // Include URL fields\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/feeds${queryString ? `?${queryString}` : ''}`\n debug('Fetching feeds:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: params?.signal\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as ListFeedsResult\n debug('Feeds fetched:', data.results?.length ?? 0, 'feeds')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch feeds: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let apiMessage: string | undefined\n try {\n const errorData = await response.json()\n apiMessage = errorData.message ?? errorData.error\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', apiMessage || 'Authentication failed', status)\n case 403:\n return failure('FORBIDDEN', apiMessage || 'Access denied', status)\n case 404:\n return failure('NOT_FOUND', apiMessage || 'Not found', status)\n case 429:\n return failure('RATE_LIMITED', apiMessage || 'Rate limited', status)\n case 503:\n return failure('SERVICE_UNAVAILABLE', apiMessage || 'Service unavailable', status)\n default:\n return failure('API_ERROR', apiMessage || response.statusText || 'API error', status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Event,\n EventType,\n EventFieldValues,\n ListEventsParams,\n GetEventParams,\n ListEventTypesParams,\n ListEventFieldValuesParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * List events with required filters and optional pagination.\n *\n * @remarks\n * Fetches a paginated list of events from `/api/v3.0/events`. The `actor`,\n * `type__in`, and `startTimestamp__gte` parameters are required.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listevents).\n *\n * @param params - Required and optional filtering parameters\n * @returns A Result containing a paginated list of events or an error\n *\n * @example\n * ```typescript\n * import { listEvents } from 'een-api-toolkit'\n *\n * // Get motion events from a camera in the last hour\n * const { data, error } = await listEvents({\n * actor: 'camera:100d4c41',\n * type__in: ['een.motionDetectionEvent.v1'],\n * startTimestamp__gte: new Date(Date.now() - 3600000).toISOString()\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} events`)\n * data.results.forEach(event => {\n * console.log(`${event.type} at ${event.startTimestamp}`)\n * })\n * }\n *\n * // Fetch all events with pagination\n * let allEvents: Event[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listEvents({\n * actor: 'camera:100d4c41',\n * type__in: ['een.motionDetectionEvent.v1'],\n * startTimestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * pageSize: 100,\n * pageToken\n * })\n * if (error) break\n * allEvents.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Events\n */\nexport async function listEvents(params: ListEventsParams): Promise<Result<PaginatedResult<Event>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.actor) {\n return failure('VALIDATION_ERROR', 'actor parameter is required')\n }\n\n if (!params.type__in || params.type__in.length === 0) {\n return failure('VALIDATION_ERROR', 'type__in parameter is required and must not be empty')\n }\n\n if (!params.startTimestamp__gte) {\n return failure('VALIDATION_ERROR', 'startTimestamp__gte parameter is required')\n }\n\n const queryParams = new URLSearchParams()\n\n // Required filters\n queryParams.append('actor', params.actor)\n queryParams.append('type__in', params.type__in.join(','))\n queryParams.append('startTimestamp__gte', formatTimestamp(params.startTimestamp__gte))\n\n // Pagination\n if (params.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Optional time filters\n if (params.startTimestamp__lte) {\n queryParams.append('startTimestamp__lte', formatTimestamp(params.startTimestamp__lte))\n }\n if (params.endTimestamp__gte) {\n queryParams.append('endTimestamp__gte', formatTimestamp(params.endTimestamp__gte))\n }\n if (params.endTimestamp__lte) {\n queryParams.append('endTimestamp__lte', formatTimestamp(params.endTimestamp__lte))\n }\n\n // Sort\n if (params.sort) {\n queryParams.append('sort', params.sort)\n }\n\n // Include\n if (params.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/events${queryString ? `?${queryString}` : ''}`\n debug('Fetching events:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Event>\n debug('Events fetched:', data.results?.length ?? 0, 'events')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch events: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific event by ID.\n *\n * @remarks\n * Fetches a single event from `/api/v3.0/events/{eventId}`. Use the `include`\n * parameter to request additional data schemas.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getevent).\n *\n * @param eventId - The unique identifier of the event to fetch\n * @param params - Optional parameters (e.g., include additional data schemas)\n * @returns A Result containing the event or an error\n *\n * @example\n * ```typescript\n * import { getEvent } from 'een-api-toolkit'\n *\n * const { data, error } = await getEvent('event-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Event not found')\n * }\n * return\n * }\n *\n * console.log(`Event: ${data.type} at ${data.startTimestamp}`)\n *\n * // With additional data schemas\n * const { data: eventWithData } = await getEvent('event-123', {\n * include: ['data.een.objectDetection.v1', 'data.een.fullFrameImageUrl.v1']\n * })\n * ```\n *\n * @category Events\n */\nexport async function getEvent(eventId: string, params?: GetEventParams): Promise<Result<Event>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!eventId) {\n return failure('VALIDATION_ERROR', 'Event ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/events/${encodeURIComponent(eventId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching event:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Event\n debug('Event fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event: ${String(err)}`)\n }\n}\n\n/**\n * List all available event types.\n *\n * @remarks\n * Fetches a paginated list of event types from `/api/v3.0/eventTypes`. Event types\n * describe the different kinds of events that can be generated in the system.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listeventtypes).\n *\n * @param params - Optional pagination and language parameters\n * @returns A Result containing a paginated list of event types or an error\n *\n * @example\n * ```typescript\n * import { listEventTypes } from 'een-api-toolkit'\n *\n * const { data, error } = await listEventTypes()\n * if (data) {\n * data.results.forEach(eventType => {\n * console.log(`${eventType.name}: ${eventType.description}`)\n * })\n * }\n *\n * // With language parameter\n * const { data: localizedTypes } = await listEventTypes({ language: 'de' })\n * ```\n *\n * @category Events\n */\nexport async function listEventTypes(params?: ListEventTypesParams): Promise<Result<PaginatedResult<EventType>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Language\n if (params?.language) {\n queryParams.append('language', params.language)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventTypes${queryString ? `?${queryString}` : ''}`\n debug('Fetching event types:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EventType>\n debug('Event types fetched:', data.results?.length ?? 0, 'types')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event types: ${String(err)}`)\n }\n}\n\n/**\n * List available event field values for a specific actor.\n *\n * @remarks\n * Fetches available event types for a specific actor from\n * `/api/v3.0/events:listFieldValues`. This is useful for building filter UIs\n * to know which event types are available for a camera or other device.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listeventfieldvalues).\n *\n * @param params - Parameters including the actor to query\n * @returns A Result containing available field values or an error\n *\n * @example\n * ```typescript\n * import { listEventFieldValues } from 'een-api-toolkit'\n *\n * const { data, error } = await listEventFieldValues({\n * actor: 'camera:100d4c41'\n * })\n *\n * if (data) {\n * console.log('Available event types:', data.type)\n * // Use these types to filter the listEvents call\n * }\n * ```\n *\n * @category Events\n */\nexport async function listEventFieldValues(params: ListEventFieldValuesParams): Promise<Result<EventFieldValues>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameter\n if (!params.actor) {\n return failure('VALIDATION_ERROR', 'actor parameter is required')\n }\n\n const queryParams = new URLSearchParams()\n queryParams.append('actor', params.actor)\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/events:listFieldValues${queryString ? `?${queryString}` : ''}`\n debug('Fetching event field values:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventFieldValues\n debug('Event field values fetched:', data.type?.length ?? 0, 'types')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event field values: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n EventMetric,\n GetEventMetricsParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * Get event metrics (time-series data) for a specific actor and event type.\n *\n * @remarks\n * Fetches time-series metric data from `/api/v3.0/eventMetrics`. The `actor` and\n * `eventType` parameters are required. Returns an array of EventMetric objects\n * containing data points over time.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listmetrics).\n *\n * @param params - Required and optional filtering parameters\n * @returns A Result containing an array of event metrics or an error\n *\n * @example\n * ```typescript\n * import { getEventMetrics } from 'een-api-toolkit'\n *\n * // Get motion event metrics for a camera (last 7 days by default)\n * const { data, error } = await getEventMetrics({\n * actor: 'camera:100d4c41',\n * eventType: 'een.motionDetectionEvent.v1'\n * })\n *\n * if (data) {\n * data.forEach(metric => {\n * console.log(`${metric.eventType}: ${metric.dataPoints.length} data points`)\n * metric.dataPoints.forEach(([timestamp, count]) => {\n * console.log(` ${new Date(timestamp).toISOString()}: ${count}`)\n * })\n * })\n * }\n *\n * // With custom time range and aggregation\n * const { data: hourlyData } = await getEventMetrics({\n * actor: 'camera:100d4c41',\n * eventType: 'een.motionDetectionEvent.v1',\n * timestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * timestamp__lte: new Date().toISOString(),\n * aggregateByMinutes: 60\n * })\n * ```\n *\n * @category Event Metrics\n */\nexport async function getEventMetrics(params: GetEventMetricsParams): Promise<Result<EventMetric[]>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.actor) {\n return failure('VALIDATION_ERROR', 'actor parameter is required')\n }\n\n if (!params.eventType) {\n return failure('VALIDATION_ERROR', 'eventType parameter is required')\n }\n\n const queryParams = new URLSearchParams()\n\n // Required parameters\n queryParams.append('actor', params.actor)\n queryParams.append('eventType', params.eventType)\n\n // Optional time filters\n if (params.timestamp__gte) {\n queryParams.append('timestamp__gte', formatTimestamp(params.timestamp__gte))\n }\n if (params.timestamp__lte) {\n queryParams.append('timestamp__lte', formatTimestamp(params.timestamp__lte))\n }\n\n // Optional aggregation\n if (params.aggregateByMinutes !== undefined) {\n queryParams.append('aggregateByMinutes', String(params.aggregateByMinutes))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventMetrics${queryString ? `?${queryString}` : ''}`\n debug('Fetching event metrics:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventMetric[]\n debug('Event metrics fetched:', data.length, 'metrics')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event metrics: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Alert,\n AlertType,\n ListAlertsParams,\n GetAlertParams,\n ListAlertTypesParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * List alerts with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alerts from `/api/v3.0/alerts`. Supports various\n * filters including time range, actor, alert type, priority, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listalerts).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of alerts or an error\n *\n * @example\n * ```typescript\n * import { listAlerts } from 'een-api-toolkit'\n *\n * // Get recent alerts from a specific camera\n * const { data, error } = await listAlerts({\n * actorId__in: ['100d4c41'],\n * timestamp__gte: new Date(Date.now() - 3600000).toISOString(),\n * pageSize: 50,\n * include: ['data', 'actions']\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} alerts`)\n * data.results.forEach(alert => {\n * console.log(`${alert.alertType} at ${alert.timestamp}`)\n * })\n * }\n *\n * // Fetch all alerts with pagination\n * let allAlerts: Alert[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listAlerts({\n * timestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * pageSize: 100,\n * pageToken\n * })\n * if (error) break\n * allAlerts.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Alerts\n */\nexport async function listAlerts(params?: ListAlertsParams): Promise<Result<PaginatedResult<Alert>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Time filters\n if (params?.timestamp__lte) {\n queryParams.append('timestamp__lte', formatTimestamp(params.timestamp__lte))\n }\n if (params?.timestamp__gte) {\n queryParams.append('timestamp__gte', formatTimestamp(params.timestamp__gte))\n }\n\n // Entity filters\n if (params?.creatorId) {\n queryParams.append('creatorId', params.creatorId)\n }\n if (params?.alertType__in && params.alertType__in.length > 0) {\n queryParams.append('alertType__in', params.alertType__in.join(','))\n }\n if (params?.actorId__in && params.actorId__in.length > 0) {\n queryParams.append('actorId__in', params.actorId__in.join(','))\n }\n if (params?.actorType__in && params.actorType__in.length > 0) {\n queryParams.append('actorType__in', params.actorType__in.join(','))\n }\n if (params?.actorAccountId) {\n queryParams.append('actorAccountId', params.actorAccountId)\n }\n\n // Rule filters\n if (params?.ruleId) {\n queryParams.append('ruleId', params.ruleId)\n }\n if (params?.ruleId__in && params.ruleId__in.length > 0) {\n queryParams.append('ruleId__in', params.ruleId__in.join(','))\n }\n\n // Event and location filters\n if (params?.eventId) {\n queryParams.append('eventId', params.eventId)\n }\n if (params?.locationId__in && params.locationId__in.length > 0) {\n queryParams.append('locationId__in', params.locationId__in.join(','))\n }\n\n // Priority filters\n if (params?.priority__gte !== undefined) {\n queryParams.append('priority__gte', String(params.priority__gte))\n }\n if (params?.priority__lte !== undefined) {\n queryParams.append('priority__lte', String(params.priority__lte))\n }\n\n // Other filters\n if (params?.showInvalidAlerts !== undefined) {\n queryParams.append('showInvalidAlerts', String(params.showInvalidAlerts))\n }\n if (params?.alertActionId__in && params.alertActionId__in.length > 0) {\n queryParams.append('alertActionId__in', params.alertActionId__in.join(','))\n }\n if (params?.alertActionStatus__in && params.alertActionStatus__in.length > 0) {\n queryParams.append('alertActionStatus__in', params.alertActionStatus__in.join(','))\n }\n\n // Response options\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n if (params?.language) {\n queryParams.append('language', params.language)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alerts${queryString ? `?${queryString}` : ''}`\n debug('Fetching alerts:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Alert>\n debug('Alerts fetched:', data.results?.length ?? 0, 'alerts')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alerts: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert by ID.\n *\n * @remarks\n * Fetches a single alert from `/api/v3.0/alerts/{alertId}`. Use the `include`\n * parameter to request additional fields.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getalert).\n *\n * @param alertId - The unique identifier of the alert to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the alert or an error\n *\n * @example\n * ```typescript\n * import { getAlert } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlert('alert-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Alert not found')\n * }\n * return\n * }\n *\n * console.log(`Alert: ${data.alertType} at ${data.timestamp}`)\n *\n * // With additional fields\n * const { data: alertWithData } = await getAlert('alert-123', {\n * include: ['data', 'actions', 'description']\n * })\n * ```\n *\n * @category Alerts\n */\nexport async function getAlert(alertId: string, params?: GetAlertParams): Promise<Result<Alert>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!alertId) {\n return failure('VALIDATION_ERROR', 'Alert ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alerts/${encodeURIComponent(alertId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Alert\n debug('Alert fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert: ${String(err)}`)\n }\n}\n\n/**\n * List all available alert types.\n *\n * @remarks\n * Fetches a paginated list of alert types from `/api/v3.0/alertTypes`. Alert types\n * describe the different kinds of alerts that can be generated in the system.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listalerttypes).\n *\n * @param params - Optional pagination parameters\n * @returns A Result containing a paginated list of alert types or an error\n *\n * @example\n * ```typescript\n * import { listAlertTypes } from 'een-api-toolkit'\n *\n * const { data, error } = await listAlertTypes()\n * if (data) {\n * data.results.forEach(alertType => {\n * console.log(`${alertType.type}: ${alertType.description}`)\n * })\n * }\n *\n * // With pagination\n * const { data: pagedTypes } = await listAlertTypes({ pageSize: 20 })\n * ```\n *\n * @category Alerts\n */\nexport async function listAlertTypes(params?: ListAlertTypesParams): Promise<Result<PaginatedResult<AlertType>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertTypes${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert types:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AlertType>\n debug('Alert types fetched:', data.results?.length ?? 0, 'types')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert types: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n Notification,\n ListNotificationsParams\n} from '../types'\nimport { debug, formatTimestamp } from '../utils'\n\n/**\n * List notifications with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of notifications from `/api/v3.0/notifications`. Supports\n * various filters including time range, actor, alert type, category, and more.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listnotifications).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of notifications or an error\n *\n * @example\n * ```typescript\n * import { listNotifications } from 'een-api-toolkit'\n *\n * // Get recent notifications for a specific camera\n * const { data, error } = await listNotifications({\n * actorId: '100d4c41',\n * timestamp__gte: new Date(Date.now() - 3600000).toISOString(),\n * pageSize: 50\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} notifications`)\n * data.results.forEach(notification => {\n * console.log(`${notification.category}: ${notification.description}`)\n * })\n * }\n *\n * // Get unread notifications\n * const { data: unread } = await listNotifications({\n * read: false,\n * category: 'video'\n * })\n *\n * // Fetch all notifications with pagination\n * let allNotifications: Notification[] = []\n * let pageToken: string | undefined\n * do {\n * const { data, error } = await listNotifications({\n * timestamp__gte: new Date(Date.now() - 86400000).toISOString(),\n * pageSize: 100,\n * pageToken\n * })\n * if (error) break\n * allNotifications.push(...data.results)\n * pageToken = data.nextPageToken\n * } while (pageToken)\n * ```\n *\n * @category Notifications\n */\nexport async function listNotifications(params?: ListNotificationsParams): Promise<Result<PaginatedResult<Notification>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Time filters\n if (params?.timestamp__lte) {\n queryParams.append('timestamp__lte', formatTimestamp(params.timestamp__lte))\n }\n if (params?.timestamp__gte) {\n queryParams.append('timestamp__gte', formatTimestamp(params.timestamp__gte))\n }\n\n // Entity filters\n if (params?.alertId) {\n queryParams.append('alertId', params.alertId)\n }\n if (params?.alertType) {\n queryParams.append('alertType', params.alertType)\n }\n if (params?.actorId) {\n queryParams.append('actorId', params.actorId)\n }\n if (params?.actorType) {\n queryParams.append('actorType', params.actorType)\n }\n if (params?.actorAccountId) {\n queryParams.append('actorAccountId', params.actorAccountId)\n }\n\n // Category and status filters\n if (params?.category) {\n queryParams.append('category', params.category)\n }\n if (params?.userId) {\n queryParams.append('userId', params.userId)\n }\n if (params?.read !== undefined) {\n queryParams.append('read', String(params.read))\n }\n if (params?.status) {\n queryParams.append('status', params.status)\n }\n\n // Other options\n if (params?.includeV1Notifications !== undefined) {\n queryParams.append('includeV1Notifications', String(params.includeV1Notifications))\n }\n\n // Response options\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n if (params?.language) {\n queryParams.append('language', params.language)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/notifications${queryString ? `?${queryString}` : ''}`\n debug('Fetching notifications:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Notification>\n debug('Notifications fetched:', data.results?.length ?? 0, 'notifications')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch notifications: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific notification by ID.\n *\n * @remarks\n * Fetches a single notification from `/api/v3.0/notifications/{notificationId}`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getnotification).\n *\n * @param notificationId - The unique identifier of the notification to fetch\n * @returns A Result containing the notification or an error\n *\n * @example\n * ```typescript\n * import { getNotification } from 'een-api-toolkit'\n *\n * const { data, error } = await getNotification('notification-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Notification not found')\n * }\n * return\n * }\n *\n * console.log(`Notification: ${data.category} - ${data.description}`)\n * console.log(`Read: ${data.read}`)\n * ```\n *\n * @category Notifications\n */\nexport async function getNotification(notificationId: string): Promise<Result<Notification>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!notificationId) {\n return failure('VALIDATION_ERROR', 'Notification ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/notifications/${encodeURIComponent(notificationId)}`\n debug('Fetching notification:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Notification\n debug('Notification fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch notification: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n EventSubscription,\n CreateEventSubscriptionParams,\n ListEventSubscriptionsParams,\n SSEConnection,\n SSEConnectionOptions,\n SSEConnectionStatus,\n SSEEvent\n} from '../types'\nimport { debug } from '../utils'\n\n/**\n * List all event subscriptions for the current account.\n *\n * @remarks\n * Fetches a paginated list of event subscriptions from `/api/v3.0/eventSubscriptions`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listeventsubscriptions).\n *\n * @param params - Optional pagination parameters\n * @returns A Result containing a paginated list of event subscriptions or an error\n *\n * @example\n * ```typescript\n * import { listEventSubscriptions } from 'een-api-toolkit'\n *\n * const { data, error } = await listEventSubscriptions()\n * if (data) {\n * console.log(`Found ${data.results.length} subscriptions`)\n * data.results.forEach(sub => {\n * console.log(`${sub.id}: ${sub.deliveryConfig.type}`)\n * })\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function listEventSubscriptions(\n params?: ListEventSubscriptionsParams\n): Promise<Result<PaginatedResult<EventSubscription>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions${queryString ? `?${queryString}` : ''}`\n debug('Fetching event subscriptions:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EventSubscription>\n debug('Event subscriptions fetched:', data.results?.length ?? 0, 'subscriptions')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event subscriptions: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific event subscription by ID.\n *\n * @remarks\n * Fetches a single event subscription from `/api/v3.0/eventSubscriptions/{id}`.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/geteventsubscription).\n *\n * @param subscriptionId - The unique identifier of the subscription to fetch\n * @returns A Result containing the event subscription or an error\n *\n * @example\n * ```typescript\n * import { getEventSubscription } from 'een-api-toolkit'\n *\n * const { data, error } = await getEventSubscription('f3d6f55d5ba546168758a309508f4419')\n * if (data) {\n * console.log(`Subscription: ${data.id}`)\n * if (data.deliveryConfig.type === 'serverSentEvents.v1') {\n * console.log(`SSE URL: ${data.deliveryConfig.sseUrl}`)\n * }\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function getEventSubscription(\n subscriptionId: string\n): Promise<Result<EventSubscription>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!subscriptionId) {\n return failure('VALIDATION_ERROR', 'Subscription ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions/${encodeURIComponent(subscriptionId)}`\n debug('Fetching event subscription:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventSubscription\n debug('Event subscription fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event subscription: ${String(err)}`)\n }\n}\n\n/**\n * Create a new event subscription.\n *\n * @remarks\n * Creates a new event subscription at `/api/v3.0/eventSubscriptions`.\n * For SSE subscriptions, use `connectToEventSubscription()` with the returned\n * `sseUrl` to start receiving events.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/createeventsubscription).\n *\n * @param params - Parameters for creating the subscription\n * @returns A Result containing the created event subscription or an error\n *\n * @example\n * ```typescript\n * import { createEventSubscription, connectToEventSubscription } from 'een-api-toolkit'\n *\n * // Create an SSE subscription for motion events\n * const { data, error } = await createEventSubscription({\n * deliveryConfig: { type: 'serverSentEvents.v1' },\n * filters: [{\n * actors: ['camera:100d4c41'],\n * types: [{ id: 'een.motionDetectionEvent.v1' }]\n * }]\n * })\n *\n * if (data && data.deliveryConfig.type === 'serverSentEvents.v1') {\n * // Connect to the SSE stream\n * const { data: connection } = connectToEventSubscription(\n * data.deliveryConfig.sseUrl!,\n * { onEvent: (event) => console.log('Event:', event) }\n * )\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function createEventSubscription(\n params: CreateEventSubscriptionParams\n): Promise<Result<EventSubscription>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.deliveryConfig) {\n return failure('VALIDATION_ERROR', 'deliveryConfig is required')\n }\n\n if (!params.filters || params.filters.length === 0) {\n return failure('VALIDATION_ERROR', 'At least one filter is required')\n }\n\n // Validate each filter\n for (const filter of params.filters) {\n if (!filter.actors || filter.actors.length === 0) {\n return failure('VALIDATION_ERROR', 'Each filter must have at least one actor')\n }\n if (!filter.types || filter.types.length === 0) {\n return failure('VALIDATION_ERROR', 'Each filter must have at least one event type')\n }\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions`\n debug('Creating event subscription:', url)\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(params)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventSubscription\n debug('Event subscription created:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to create event subscription: ${String(err)}`)\n }\n}\n\n/**\n * Delete an event subscription.\n *\n * @remarks\n * Deletes an event subscription at `/api/v3.0/eventSubscriptions/{id}`.\n * Any active SSE connections to this subscription will be closed.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/deleteeventsubscription).\n *\n * @param subscriptionId - The unique identifier of the subscription to delete\n * @returns A Result with void data on success or an error\n *\n * @example\n * ```typescript\n * import { deleteEventSubscription } from 'een-api-toolkit'\n *\n * const { error } = await deleteEventSubscription('f3d6f55d5ba546168758a309508f4419')\n * if (error) {\n * console.error('Failed to delete:', error.message)\n * } else {\n * console.log('Subscription deleted successfully')\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport async function deleteEventSubscription(\n subscriptionId: string\n): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!subscriptionId) {\n return failure('VALIDATION_ERROR', 'Subscription ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventSubscriptions/${encodeURIComponent(subscriptionId)}`\n debug('Deleting event subscription:', url)\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('Event subscription deleted:', subscriptionId)\n return success(undefined)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to delete event subscription: ${String(err)}`)\n }\n}\n\n/**\n * Connect to an SSE event subscription to receive real-time events.\n *\n * @remarks\n * Opens an SSE connection to the provided URL and calls the `onEvent` callback\n * for each event received. The connection automatically handles reconnection\n * on errors.\n *\n * Note: SSE connections require authentication. The token is passed via the\n * `Authorization` header. Since EventSource doesn't support custom headers,\n * we use fetch with ReadableStream to implement SSE.\n *\n * @param sseUrl - The SSE URL from the event subscription's deliveryConfig\n * @param options - Connection options including event and error callbacks\n * @returns A Result containing the SSE connection handle or an error\n *\n * @example\n * ```typescript\n * import { createEventSubscription, connectToEventSubscription } from 'een-api-toolkit'\n *\n * // First create a subscription\n * const { data: subscription } = await createEventSubscription({\n * deliveryConfig: { type: 'serverSentEvents.v1' },\n * filters: [{\n * actors: ['camera:100d4c41'],\n * types: [{ id: 'een.motionDetectionEvent.v1' }]\n * }]\n * })\n *\n * if (subscription?.deliveryConfig.type === 'serverSentEvents.v1') {\n * // Connect to SSE stream\n * const { data: connection, error } = connectToEventSubscription(\n * subscription.deliveryConfig.sseUrl!,\n * {\n * onEvent: (event) => {\n * console.log(`Event: ${event.type} from ${event.actorId}`)\n * },\n * onError: (err) => {\n * console.error('SSE error:', err.message)\n * },\n * onStatusChange: (status) => {\n * console.log('Connection status:', status)\n * }\n * }\n * )\n *\n * // Later, disconnect\n * if (connection) {\n * connection.close()\n * }\n * }\n * ```\n *\n * @category EventSubscriptions\n */\nexport function connectToEventSubscription(\n sseUrl: string,\n options: SSEConnectionOptions\n): Result<SSEConnection> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.token) {\n return failure('AUTH_REQUIRED', 'Access token not available')\n }\n\n if (!sseUrl) {\n return failure('VALIDATION_ERROR', 'SSE URL is required')\n }\n\n // Validate SSE URL domain to prevent SSRF attacks\n // SSE URLs should only come from trusted EEN domains\n try {\n const sseUrlObj = new URL(sseUrl)\n const allowedDomains = ['.eagleeyenetworks.com', '.een.cloud']\n // Allow both exact domain match (e.g., eagleeyenetworks.com) and subdomain match (e.g., api.eagleeyenetworks.com)\n const isAllowedDomain = allowedDomains.some(domain =>\n sseUrlObj.hostname === domain.substring(1) || sseUrlObj.hostname.endsWith(domain)\n )\n if (!isAllowedDomain) {\n return failure('VALIDATION_ERROR', `SSE URL domain not allowed: ${sseUrlObj.hostname}`)\n }\n } catch {\n return failure('VALIDATION_ERROR', 'Invalid SSE URL format')\n }\n\n // Maximum buffer size to prevent memory exhaustion (1MB)\n const MAX_BUFFER_SIZE = 1024 * 1024\n\n let status: SSEConnectionStatus = 'connecting'\n let abortController: AbortController | null = new AbortController()\n let isClosing = false\n\n const setStatus = (newStatus: SSEConnectionStatus) => {\n status = newStatus\n options.onStatusChange?.(status)\n }\n\n const close = () => {\n if (isClosing) return\n isClosing = true\n debug('Closing SSE connection')\n abortController?.abort()\n abortController = null\n setStatus('disconnected')\n }\n\n const connect = async () => {\n if (isClosing || !abortController) return\n\n setStatus('connecting')\n debug('Connecting to SSE:', sseUrl)\n\n try {\n // Note: We intentionally omit Cache-Control header here.\n // While 'Cache-Control: no-cache' is common for SSE, it triggers CORS preflight\n // requests that fail because the EEN API doesn't include it in Access-Control-Allow-Headers.\n // The SSE endpoint handles caching appropriately server-side.\n const response = await fetch(sseUrl, {\n method: 'GET',\n headers: {\n 'Accept': 'text/event-stream',\n 'Authorization': `Bearer ${authStore.token}`\n },\n signal: abortController.signal\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n if (!response.body) {\n throw new Error('Response body is not available')\n }\n\n setStatus('connected')\n debug('SSE connected')\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (!isClosing) {\n const { done, value } = await reader.read()\n\n if (done) {\n debug('SSE stream ended')\n break\n }\n\n buffer += decoder.decode(value, { stream: true })\n\n // Prevent buffer from growing unbounded (protects against memory exhaustion)\n if (buffer.length > MAX_BUFFER_SIZE) {\n debug('SSE buffer exceeded maximum size, resetting')\n buffer = ''\n continue\n }\n\n const lines = buffer.split('\\n')\n buffer = lines.pop() || ''\n\n let eventData = ''\n for (const line of lines) {\n if (line.startsWith('data:')) {\n // Per SSE spec, multi-line data fields are concatenated with newlines\n const dataValue = line.substring(5).trimStart()\n eventData = eventData ? `${eventData}\\n${dataValue}` : dataValue\n } else if (line === '' && eventData) {\n // End of event\n try {\n const event = JSON.parse(eventData) as SSEEvent\n debug('SSE event received:', event.type, event.actorId)\n options.onEvent(event)\n } catch (parseError) {\n debug('Failed to parse SSE event:', parseError)\n }\n eventData = ''\n }\n }\n }\n } catch (err) {\n if (isClosing || (err instanceof Error && err.name === 'AbortError')) {\n // Expected when closing\n return\n }\n\n debug('SSE error:', err)\n setStatus('error')\n options.onError?.(err instanceof Error ? err : new Error(String(err)))\n }\n }\n\n // Start connection\n connect()\n\n const connection: SSEConnection = {\n close,\n get status() {\n return status\n }\n }\n\n return success(connection)\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', message, status)\n case 403:\n return failure('FORBIDDEN', message, status)\n case 404:\n return failure('NOT_FOUND', message, status)\n case 429:\n return failure('RATE_LIMITED', message, status)\n default:\n return failure('API_ERROR', message, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type {\n Result,\n PaginatedResult,\n EventAlertConditionRule,\n EventAlertConditionRuleFieldValues,\n AlertConditionRule,\n AlertActionRule,\n AutomationAlertAction,\n ListEventAlertConditionRulesParams,\n GetEventAlertConditionRuleFieldValuesParams,\n ListAlertConditionRulesParams,\n GetAlertConditionRuleParams,\n ListAlertActionRulesParams,\n ListAlertActionsParams\n} from '../types'\nimport { debug } from '../utils'\n\n// =============================================================================\n// Event Alert Condition Rules\n// =============================================================================\n\n/**\n * List event alert condition rules with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of event alert condition rules from\n * `/api/v3.0/eventAlertConditionRules`. These rules define conditions\n * under which events trigger alerts.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listalertconditionrules).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of rules or an error\n *\n * @example\n * ```typescript\n * import { listEventAlertConditionRules } from 'een-api-toolkit'\n *\n * // Get enabled rules\n * const { data, error } = await listEventAlertConditionRules({\n * enabled: true,\n * pageSize: 50\n * })\n *\n * if (data) {\n * console.log(`Found ${data.results.length} rules`)\n * data.results.forEach(rule => {\n * console.log(`${rule.name}: priority ${rule.priority}`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listEventAlertConditionRules(\n params?: ListEventAlertConditionRulesParams\n): Promise<Result<PaginatedResult<EventAlertConditionRule>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.outputAlertType__in && params.outputAlertType__in.length > 0) {\n queryParams.append('outputAlertType__in', params.outputAlertType__in.join(','))\n }\n if (params?.priority__gte !== undefined) {\n queryParams.append('priority__gte', String(params.priority__gte))\n }\n if (params?.priority__lte !== undefined) {\n queryParams.append('priority__lte', String(params.priority__lte))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventAlertConditionRules${queryString ? `?${queryString}` : ''}`\n debug('Fetching event alert condition rules:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EventAlertConditionRule>\n debug('Event alert condition rules fetched:', data.results?.length ?? 0, 'rules')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event alert condition rules: ${String(err)}`)\n }\n}\n\n/**\n * Get available field values for event alert condition rules.\n *\n * @remarks\n * Fetches available values that can be used for filtering event alert condition rules.\n * Useful for building filter UI components.\n *\n * @param params - Optional filter parameters\n * @returns A Result containing field values or an error\n *\n * @example\n * ```typescript\n * import { getEventAlertConditionRuleFieldValues } from 'een-api-toolkit'\n *\n * const { data, error } = await getEventAlertConditionRuleFieldValues()\n * if (data) {\n * console.log('Available event types:', data.eventTypes)\n * console.log('Available alert types:', data.outputAlertTypes)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getEventAlertConditionRuleFieldValues(\n params?: GetEventAlertConditionRuleFieldValuesParams\n): Promise<Result<EventAlertConditionRuleFieldValues>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/eventAlertConditionRules:listFieldValues${queryString ? `?${queryString}` : ''}`\n debug('Fetching event alert condition rule field values:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventAlertConditionRuleFieldValues\n debug('Event alert condition rule field values fetched')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch field values: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific event alert condition rule by ID.\n *\n * @remarks\n * Fetches a single event alert condition rule from\n * `/api/v3.0/eventAlertConditionRules/{id}`.\n *\n * @param ruleId - The unique identifier of the rule to fetch\n * @returns A Result containing the rule or an error\n *\n * @example\n * ```typescript\n * import { getEventAlertConditionRule } from 'een-api-toolkit'\n *\n * const { data, error } = await getEventAlertConditionRule('rule-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Rule not found')\n * }\n * return\n * }\n *\n * console.log(`Rule: ${data.name}, Priority: ${data.priority}`)\n * ```\n *\n * @category Automations\n */\nexport async function getEventAlertConditionRule(\n ruleId: string\n): Promise<Result<EventAlertConditionRule>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!ruleId) {\n return failure('VALIDATION_ERROR', 'Rule ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/eventAlertConditionRules/${encodeURIComponent(ruleId)}`\n debug('Fetching event alert condition rule:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EventAlertConditionRule\n debug('Event alert condition rule fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch event alert condition rule: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Alert Condition Rules\n// =============================================================================\n\n/**\n * List alert condition rules with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alert condition rules from\n * `/api/v3.0/alertConditionRules`. These rules process events and create alerts.\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of rules or an error\n *\n * @example\n * ```typescript\n * import { listAlertConditionRules } from 'een-api-toolkit'\n *\n * // Get enabled rules with actions\n * const { data, error } = await listAlertConditionRules({\n * enabled: true,\n * include: ['actions', 'insights']\n * })\n *\n * if (data) {\n * data.results.forEach(rule => {\n * console.log(`${rule.name}: ${rule.inputEventTypes.length} event types`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listAlertConditionRules(\n params?: ListAlertConditionRulesParams\n): Promise<Result<PaginatedResult<AlertConditionRule>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.actorId__in && params.actorId__in.length > 0) {\n queryParams.append('actorId__in', params.actorId__in.join(','))\n }\n if (params?.inputEventType__in && params.inputEventType__in.length > 0) {\n queryParams.append('inputEventType__in', params.inputEventType__in.join(','))\n }\n if (params?.outputAlertType) {\n queryParams.append('outputAlertType', params.outputAlertType)\n }\n if (params?.type) {\n queryParams.append('type', params.type)\n }\n\n // Response options\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertConditionRules${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert condition rules:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AlertConditionRule>\n debug('Alert condition rules fetched:', data.results?.length ?? 0, 'rules')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert condition rules: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert condition rule by ID.\n *\n * @remarks\n * Fetches a single alert condition rule from `/api/v3.0/alertConditionRules/{id}`.\n * Use the `include` parameter to request additional fields like actions or insights.\n *\n * @param ruleId - The unique identifier of the rule to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the rule or an error\n *\n * @example\n * ```typescript\n * import { getAlertConditionRule } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlertConditionRule('rule-123', {\n * include: ['actions', 'insights']\n * })\n *\n * if (data) {\n * console.log(`Rule: ${data.name}`)\n * console.log(`Actions: ${data.actions?.length ?? 0}`)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getAlertConditionRule(\n ruleId: string,\n params?: GetAlertConditionRuleParams\n): Promise<Result<AlertConditionRule>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!ruleId) {\n return failure('VALIDATION_ERROR', 'Rule ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertConditionRules/${encodeURIComponent(ruleId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert condition rule:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as AlertConditionRule\n debug('Alert condition rule fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert condition rule: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Alert Action Rules\n// =============================================================================\n\n/**\n * List alert action rules with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alert action rules from `/api/v3.0/alertActionRules`.\n * These rules connect alerts to actions - when an alert matches the rule's criteria,\n * the associated actions are executed.\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of rules or an error\n *\n * @example\n * ```typescript\n * import { listAlertActionRules } from 'een-api-toolkit'\n *\n * // Get enabled rules for specific alert types\n * const { data, error } = await listAlertActionRules({\n * enabled: true,\n * alertType__in: ['een.motionDetectionAlert.v1']\n * })\n *\n * if (data) {\n * data.results.forEach(rule => {\n * console.log(`${rule.name}: ${rule.alertActionIds.length} actions`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listAlertActionRules(\n params?: ListAlertActionRulesParams\n): Promise<Result<PaginatedResult<AlertActionRule>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.alertType__in && params.alertType__in.length > 0) {\n queryParams.append('alertType__in', params.alertType__in.join(','))\n }\n if (params?.actorId__in && params.actorId__in.length > 0) {\n queryParams.append('actorId__in', params.actorId__in.join(','))\n }\n if (params?.alertActionId__in && params.alertActionId__in.length > 0) {\n queryParams.append('alertActionId__in', params.alertActionId__in.join(','))\n }\n if (params?.ruleId__in && params.ruleId__in.length > 0) {\n queryParams.append('ruleId__in', params.ruleId__in.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertActionRules${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert action rules:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AlertActionRule>\n debug('Alert action rules fetched:', data.results?.length ?? 0, 'rules')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert action rules: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert action rule by ID.\n *\n * @remarks\n * Fetches a single alert action rule from `/api/v3.0/alertActionRules/{id}`.\n *\n * @param ruleId - The unique identifier of the rule to fetch\n * @returns A Result containing the rule or an error\n *\n * @example\n * ```typescript\n * import { getAlertActionRule } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlertActionRule('rule-123')\n *\n * if (data) {\n * console.log(`Rule: ${data.name}`)\n * console.log(`Alert types: ${data.alertTypes.join(', ')}`)\n * console.log(`Actions: ${data.alertActionIds.length}`)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getAlertActionRule(\n ruleId: string\n): Promise<Result<AlertActionRule>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!ruleId) {\n return failure('VALIDATION_ERROR', 'Rule ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/alertActionRules/${encodeURIComponent(ruleId)}`\n debug('Fetching alert action rule:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as AlertActionRule\n debug('Alert action rule fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert action rule: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Alert Actions\n// =============================================================================\n\n/**\n * List alert actions with optional filters and pagination.\n *\n * @remarks\n * Fetches a paginated list of alert actions from `/api/v3.0/alertActions`.\n * Alert actions define what happens when an alert is triggered (notifications,\n * webhooks, integrations, etc.).\n *\n * @param params - Optional filtering and pagination parameters\n * @returns A Result containing a paginated list of actions or an error\n *\n * @example\n * ```typescript\n * import { listAlertActions } from 'een-api-toolkit'\n *\n * // Get enabled webhook and notification actions\n * const { data, error } = await listAlertActions({\n * enabled: true,\n * type__in: ['notification', 'webhook']\n * })\n *\n * if (data) {\n * data.results.forEach(action => {\n * console.log(`${action.name} (${action.type})`)\n * })\n * }\n * ```\n *\n * @category Automations\n */\nexport async function listAlertActions(\n params?: ListAlertActionsParams\n): Promise<Result<PaginatedResult<AutomationAlertAction>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Filters\n if (params?.enabled !== undefined) {\n queryParams.append('enabled', String(params.enabled))\n }\n if (params?.id__in && params.id__in.length > 0) {\n queryParams.append('id__in', params.id__in.join(','))\n }\n if (params?.type__in && params.type__in.length > 0) {\n queryParams.append('type__in', params.type__in.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/alertActions${queryString ? `?${queryString}` : ''}`\n debug('Fetching alert actions:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<AutomationAlertAction>\n debug('Alert actions fetched:', data.results?.length ?? 0, 'actions')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert actions: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific alert action by ID.\n *\n * @remarks\n * Fetches a single alert action from `/api/v3.0/alertActions/{id}`.\n *\n * @param actionId - The unique identifier of the action to fetch\n * @returns A Result containing the action or an error\n *\n * @example\n * ```typescript\n * import { getAlertAction } from 'een-api-toolkit'\n *\n * const { data, error } = await getAlertAction('action-123')\n *\n * if (data) {\n * console.log(`Action: ${data.name} (${data.type})`)\n * console.log('Settings:', data.settings)\n * }\n * ```\n *\n * @category Automations\n */\nexport async function getAlertAction(\n actionId: string\n): Promise<Result<AutomationAlertAction>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!actionId) {\n return failure('VALIDATION_ERROR', 'Action ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/alertActions/${encodeURIComponent(actionId)}`\n debug('Fetching alert action:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as AutomationAlertAction\n debug('Alert action fetched:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch alert action: ${String(err)}`)\n }\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch (parseError) {\n debug('Failed to parse error response JSON:', parseError)\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, CreateExportParams, ExportJobResponse } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * Create a new export job.\n *\n * @remarks\n * Creates an asynchronous job to export video or images from a camera.\n * The job is queued and processed in the background. Use `getJob()` to\n * poll for completion.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/createexport).\n *\n * @param params - Export job parameters\n * @returns A Result containing the created job or an error\n *\n * @example\n * ```typescript\n * import { createExportJob, getJob, formatTimestamp } from 'een-api-toolkit'\n *\n * // Create an export job\n * const startTime = new Date(Date.now() - 60 * 60 * 1000) // 1 hour ago\n * const endTime = new Date()\n *\n * const { data: job, error } = await createExportJob({\n * name: 'Security Incident Export',\n * type: 'video',\n * cameraId: 'camera-123',\n * startTimestamp: formatTimestamp(startTime.toISOString()),\n * endTimestamp: formatTimestamp(endTime.toISOString())\n * })\n *\n * if (error) {\n * console.error('Failed to create export:', error.message)\n * return\n * }\n *\n * // Poll for completion\n * let completed = false\n * while (!completed) {\n * await new Promise(r => setTimeout(r, 2000)) // Wait 2 seconds\n * const { data: status } = await getJob(job.id)\n * if (status?.state === 'success') {\n * const fileUrl = status.result?.intervals?.[0]?.files?.[0]?.url\n * const fileId = fileUrl?.substring(fileUrl.lastIndexOf('/') + 1)\n * console.log('Export complete! File ID:', fileId)\n * completed = true\n * } else if (status?.state === 'failure') {\n * console.error('Export failed:', status.error)\n * completed = true\n * } else {\n * console.log('Progress:', status?.progress || 0, '%')\n * }\n * }\n * ```\n *\n * @category Exports\n */\nexport async function createExportJob(params: CreateExportParams): Promise<Result<ExportJobResponse>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n // Validate required parameters\n if (!params.cameraId) {\n return failure('VALIDATION_ERROR', 'Camera ID is required')\n }\n\n if (!params.type) {\n return failure('VALIDATION_ERROR', 'Export type is required')\n }\n\n if (!params.startTimestamp) {\n return failure('VALIDATION_ERROR', 'Start timestamp is required')\n }\n\n if (!params.endTimestamp) {\n return failure('VALIDATION_ERROR', 'End timestamp is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/exports`\n debug('Creating export job:', url)\n\n // Validate playbackMultiplier for timeLapse and bundle types\n if ((params.type === 'timeLapse' || params.type === 'bundle') && !params.playbackMultiplier) {\n return failure('VALIDATION_ERROR', 'Playback multiplier is required for timeLapse and bundle exports')\n }\n\n if (params.playbackMultiplier !== undefined) {\n if (params.playbackMultiplier < 1 || params.playbackMultiplier > 48) {\n return failure('VALIDATION_ERROR', 'Playback multiplier must be between 1 and 48')\n }\n }\n\n // Build request body according to EEN API v3.0 structure\n // API requires: deviceId, type, info{name, directory}, period{}\n const info: Record<string, unknown> = {\n name: params.name || `Export-${Date.now()}`,\n directory: params.directory || '/'\n }\n\n if (params.notes) {\n info.notes = params.notes\n }\n\n if (params.tags && params.tags.length > 0) {\n info.tags = params.tags\n }\n\n const period: Record<string, unknown> = {\n startTimestamp: params.startTimestamp,\n endTimestamp: params.endTimestamp\n }\n\n const body: Record<string, unknown> = {\n deviceId: params.cameraId, // API uses deviceId, not cameraId\n type: params.type,\n info,\n period\n }\n\n // playbackMultiplier is required for timeLapse and bundle\n if (params.playbackMultiplier !== undefined) {\n body.playbackMultiplier = params.playbackMultiplier\n }\n\n if (params.autoDelete !== undefined) {\n body.autoDelete = params.autoDelete\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(body)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as ExportJobResponse\n debug('Export job created:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to create export job: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, Job, ListJobsParams, GetJobParams } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List jobs with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of jobs from `/api/v3.0/jobs`. Supports\n * filtering by state, type, and time range.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listjobs).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of jobs or an error\n *\n * @example\n * ```typescript\n * import { listJobs } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await listJobs()\n * if (data) {\n * console.log(`Found ${data.results.length} jobs`)\n * }\n *\n * // Filter by state\n * const { data } = await listJobs({\n * state__in: ['pending', 'started'],\n * pageSize: 50\n * })\n *\n * // Get export jobs only\n * const { data: exports } = await listJobs({\n * type: 'export'\n * })\n * ```\n *\n * @category Jobs\n */\nexport async function listJobs(params?: ListJobsParams): Promise<Result<PaginatedResult<Job>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // State filter\n if (params?.state__in && params.state__in.length > 0) {\n queryParams.append('state__in', params.state__in.join(','))\n }\n\n // Type filters\n if (params?.type) {\n queryParams.append('type', params.type)\n }\n if (params?.type__in && params.type__in.length > 0) {\n queryParams.append('type__in', params.type__in.join(','))\n }\n\n // Time filters\n if (params?.createTimestamp__gte) {\n queryParams.append('createTimestamp__gte', params.createTimestamp__gte)\n }\n if (params?.createTimestamp__lte) {\n queryParams.append('createTimestamp__lte', params.createTimestamp__lte)\n }\n\n // User filter\n if (params?.userId) {\n queryParams.append('userId', params.userId)\n }\n\n // Sort\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/jobs${queryString ? `?${queryString}` : ''}`\n debug('Fetching jobs:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Job>\n debug('Jobs fetched:', data.results?.length ?? 0, 'jobs')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch jobs: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific job by ID.\n *\n * @remarks\n * Fetches a single job from `/api/v3.0/jobs/{jobId}`. Use this to poll\n * for job completion after creating an export.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getjob).\n *\n * @param jobId - The unique identifier of the job to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the job or an error\n *\n * @example\n * ```typescript\n * import { getJob } from 'een-api-toolkit'\n *\n * const { data, error } = await getJob('job-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Job not found')\n * }\n * return\n * }\n *\n * console.log(`Job state: ${data.state}`)\n * if (data.state === 'started') {\n * console.log(`Progress: ${data.progress}%`)\n * }\n * if (data.state === 'success') {\n * const fileUrl = data.result?.intervals?.[0]?.files?.[0]?.url\n * const fileId = fileUrl?.substring(fileUrl.lastIndexOf('/') + 1)\n * console.log(`File ID: ${fileId}`)\n * }\n * ```\n *\n * @category Jobs\n */\nexport async function getJob(jobId: string, params?: GetJobParams): Promise<Result<Job>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!jobId) {\n return failure('VALIDATION_ERROR', 'Job ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/jobs/${encodeURIComponent(jobId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching job:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Job\n debug('Job fetched:', data.arguments?.originalRequest?.name || data.id, 'state:', data.state)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch job: ${String(err)}`)\n }\n}\n\n/**\n * Delete (revoke) a job by ID.\n *\n * @remarks\n * Deletes a job from `/api/v3.0/jobs/{jobId}` regardless of its state.\n * This can be used to:\n * - Cancel a **pending** job before it starts processing\n * - Revoke a **started** job to stop processing\n * - Remove a **completed** job record\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/deletejob).\n *\n * @param jobId - The unique identifier of the job to delete\n * @returns A Result with void data on success, or an error\n *\n * @example\n * ```typescript\n * import { deleteJob } from 'een-api-toolkit'\n *\n * // Cancel a pending export job\n * const { error } = await deleteJob('job-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Job not found or already deleted')\n * } else {\n * console.error('Failed to delete job:', error.message)\n * }\n * return\n * }\n *\n * console.log('Job successfully revoked')\n * ```\n *\n * @category Jobs\n */\nexport async function deleteJob(jobId: string): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!jobId) {\n return failure('VALIDATION_ERROR', 'Job ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/jobs/${encodeURIComponent(jobId)}`\n debug('Deleting job:', url)\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // 204 No Content is expected on success\n debug('Job deleted:', jobId)\n\n return success(undefined as void)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to delete job: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, EenFile, ListFilesParams, GetFileParams, CreateFileParams, DownloadFileResult } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List files with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of files from `/api/v3.0/files`. Supports\n * filtering by type, camera, and time range.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listfiles).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of files or an error\n *\n * @example\n * ```typescript\n * import { listFiles } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await listFiles()\n * if (data) {\n * console.log(`Found ${data.results.length} files`)\n * }\n *\n * // Filter by type\n * const { data } = await listFiles({\n * type__in: ['export'],\n * pageSize: 50\n * })\n *\n * // Files for a specific camera\n * const { data: cameraFiles } = await listFiles({\n * cameraId: 'camera-123'\n * })\n * ```\n *\n * @category Files\n */\nexport async function listFiles(params?: ListFilesParams): Promise<Result<PaginatedResult<EenFile>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Include additional fields\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n // Type filter\n if (params?.type__in && params.type__in.length > 0) {\n queryParams.append('type__in', params.type__in.join(','))\n }\n\n // Camera filters\n if (params?.cameraId) {\n queryParams.append('cameraId', params.cameraId)\n }\n if (params?.cameraId__in && params.cameraId__in.length > 0) {\n queryParams.append('cameraId__in', params.cameraId__in.join(','))\n }\n\n // Job filter\n if (params?.jobId) {\n queryParams.append('jobId', params.jobId)\n }\n\n // Time filters\n if (params?.createTimestamp__gte) {\n queryParams.append('createTimestamp__gte', params.createTimestamp__gte)\n }\n if (params?.createTimestamp__lte) {\n queryParams.append('createTimestamp__lte', params.createTimestamp__lte)\n }\n\n // Tags filter\n if (params?.tags__contains && params.tags__contains.length > 0) {\n queryParams.append('tags__contains', params.tags__contains.join(','))\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n\n // Sort\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/files${queryString ? `?${queryString}` : ''}`\n debug('Fetching files:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<EenFile>\n debug('Files fetched:', data.results?.length ?? 0, 'files')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch files: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific file by ID.\n *\n * @remarks\n * Fetches a single file's metadata from `/api/v3.0/files/{fileId}`.\n * Use this to get file details before downloading.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getfile).\n *\n * @param fileId - The unique identifier of the file to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the file or an error\n *\n * @example\n * ```typescript\n * import { getFile } from 'een-api-toolkit'\n *\n * const { data, error } = await getFile('file-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('File not found')\n * }\n * return\n * }\n *\n * console.log(`File: ${data.name} (${data.size} bytes)`)\n * ```\n *\n * @category Files\n */\nexport async function getFile(fileId: string, params?: GetFileParams): Promise<Result<EenFile>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!fileId) {\n return failure('VALIDATION_ERROR', 'File ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/files/${encodeURIComponent(fileId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching file:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EenFile\n debug('File fetched:', data.name)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch file: ${String(err)}`)\n }\n}\n\n/**\n * Add/create a new file entry.\n *\n * @remarks\n * Creates a new file entry from `/api/v3.0/files`. The actual file content\n * may be uploaded separately or referenced by URL.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/createfile).\n *\n * @param params - File creation parameters\n * @returns A Result containing the created file or an error\n *\n * @example\n * ```typescript\n * import { addFile } from 'een-api-toolkit'\n *\n * const { data, error } = await addFile({\n * name: 'Incident Report',\n * type: 'upload',\n * description: 'Security incident documentation'\n * })\n *\n * if (data) {\n * console.log('File created:', data.id)\n * }\n * ```\n *\n * @category Files\n */\nexport async function addFile(params: CreateFileParams): Promise<Result<EenFile>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!params.name) {\n return failure('VALIDATION_ERROR', 'File name is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/files`\n debug('Creating file:', url)\n\n // Build request body\n const body: Record<string, unknown> = {\n name: params.name\n }\n\n if (params.type) {\n body.type = params.type\n }\n\n if (params.filename) {\n body.filename = params.filename\n }\n\n if (params.description) {\n body.description = params.description\n }\n\n if (params.tags && params.tags.length > 0) {\n body.tags = params.tags\n }\n\n if (params.cameraId) {\n body.cameraId = params.cameraId\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n },\n body: JSON.stringify(body)\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as EenFile\n debug('File created:', data.id)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to create file: ${String(err)}`)\n }\n}\n\n/**\n * Download a file's binary content.\n *\n * @remarks\n * Downloads the actual file content from `/api/v3.0/files/{fileId}:download`.\n * Returns a Blob that can be used to create a download link or process the file.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/downloadfile).\n *\n * @param fileId - The unique identifier of the file to download\n * @returns A Result containing the download result with blob, filename, and metadata\n *\n * @example\n * ```typescript\n * import { downloadFile } from 'een-api-toolkit'\n *\n * const { data, error } = await downloadFile('file-123')\n *\n * if (error) {\n * console.error('Download failed:', error.message)\n * return\n * }\n *\n * // Create download link\n * const url = URL.createObjectURL(data.blob)\n * const a = document.createElement('a')\n * a.href = url\n * a.download = data.filename\n * a.click()\n * URL.revokeObjectURL(url)\n *\n * console.log(`Downloaded: ${data.filename} (${data.size} bytes)`)\n * ```\n *\n * @category Files\n */\nexport async function downloadFile(fileId: string): Promise<Result<DownloadFileResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!fileId) {\n return failure('VALIDATION_ERROR', 'File ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/files/${encodeURIComponent(fileId)}:download`\n debug('Downloading file:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // Get the blob data\n const blob = await response.blob()\n\n // Parse filename from Content-Disposition header\n const contentDisposition = response.headers.get('Content-Disposition')\n let filename = 'download'\n if (contentDisposition) {\n const filenameMatch = contentDisposition.match(/filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/)\n if (filenameMatch && filenameMatch[1]) {\n filename = filenameMatch[1].replace(/['\"]/g, '')\n }\n }\n\n // Get content type\n const contentType = response.headers.get('Content-Type') || 'application/octet-stream'\n\n const result: DownloadFileResult = {\n blob,\n filename,\n contentType,\n size: blob.size\n }\n\n debug('File downloaded:', filename, blob.size, 'bytes')\n\n return success(result)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to download file: ${String(err)}`)\n }\n}\n\n/**\n * Delete (recycle) a file by ID.\n *\n * @remarks\n * Moves a file to the recycle bin (trash) via DELETE `/api/v3.0/files/{fileId}`.\n * This does not permanently delete the file - it can be recovered from trash.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/deletefile).\n *\n * @param fileId - The unique identifier of the file to delete\n * @returns A Result indicating success or an error\n *\n * @example\n * ```typescript\n * import { deleteFile } from 'een-api-toolkit'\n *\n * async function recycleFile(fileId: string) {\n * const { error } = await deleteFile(fileId)\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('File not found or already deleted')\n * } else {\n * console.error('Failed to delete file:', error.message)\n * }\n * return false\n * }\n *\n * console.log('File moved to trash')\n * return true\n * }\n * ```\n *\n * @category Files\n */\nexport async function deleteFile(fileId: string): Promise<Result<void>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!fileId) {\n return failure('VALIDATION_ERROR', 'File ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/files/${encodeURIComponent(fileId)}`\n debug('Deleting file:', url)\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n debug('File deleted (recycled):', fileId)\n\n return success(undefined as void)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to delete file: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n","import { useAuthStore } from '../auth/store'\nimport { success, failure } from '../types'\nimport type { Result, PaginatedResult, Download, ListDownloadsParams, GetDownloadParams, DownloadDownloadResult } from '../types'\nimport { debug } from '../utils/debug'\n\n/**\n * List downloads with optional pagination and filtering.\n *\n * @remarks\n * Fetches a paginated list of downloads from `/api/v3.0/downloads`. Supports\n * filtering by status, camera, and time range.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/listdownloads).\n *\n * @param params - Optional pagination and filtering parameters\n * @returns A Result containing a paginated list of downloads or an error\n *\n * @example\n * ```typescript\n * import { listDownloads } from 'een-api-toolkit'\n *\n * // Basic usage\n * const { data, error } = await listDownloads()\n * if (data) {\n * console.log(`Found ${data.results.length} downloads`)\n * }\n *\n * // Filter by status\n * const { data } = await listDownloads({\n * status__in: ['available'],\n * pageSize: 50\n * })\n * ```\n *\n * @category Downloads\n */\nexport async function listDownloads(params?: ListDownloadsParams): Promise<Result<PaginatedResult<Download>>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n const queryParams = new URLSearchParams()\n\n // Pagination\n if (params?.pageSize) {\n queryParams.append('pageSize', String(params.pageSize))\n }\n if (params?.pageToken) {\n queryParams.append('pageToken', params.pageToken)\n }\n\n // Status filter\n if (params?.status__in && params.status__in.length > 0) {\n queryParams.append('status__in', params.status__in.join(','))\n }\n\n // Camera filters\n if (params?.cameraId) {\n queryParams.append('cameraId', params.cameraId)\n }\n if (params?.cameraId__in && params.cameraId__in.length > 0) {\n queryParams.append('cameraId__in', params.cameraId__in.join(','))\n }\n\n // Job filter\n if (params?.jobId) {\n queryParams.append('jobId', params.jobId)\n }\n\n // File filter\n if (params?.fileId) {\n queryParams.append('fileId', params.fileId)\n }\n\n // Time filters\n if (params?.createTimestamp__gte) {\n queryParams.append('createTimestamp__gte', params.createTimestamp__gte)\n }\n if (params?.createTimestamp__lte) {\n queryParams.append('createTimestamp__lte', params.createTimestamp__lte)\n }\n\n // Search\n if (params?.q) {\n queryParams.append('q', params.q)\n }\n\n // Sort\n if (params?.sort && params.sort.length > 0) {\n queryParams.append('sort', params.sort.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/downloads${queryString ? `?${queryString}` : ''}`\n debug('Fetching downloads:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as PaginatedResult<Download>\n debug('Downloads fetched:', data.results?.length ?? 0, 'downloads')\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch downloads: ${String(err)}`)\n }\n}\n\n/**\n * Get a specific download by ID.\n *\n * @remarks\n * Fetches a single download's metadata from `/api/v3.0/downloads/{downloadId}`.\n * Use this to get download details before downloading.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/getdownload).\n *\n * @param downloadId - The unique identifier of the download to fetch\n * @param params - Optional parameters (e.g., include additional fields)\n * @returns A Result containing the download or an error\n *\n * @example\n * ```typescript\n * import { getDownload } from 'een-api-toolkit'\n *\n * const { data, error } = await getDownload('download-123')\n *\n * if (error) {\n * if (error.code === 'NOT_FOUND') {\n * console.log('Download not found')\n * }\n * return\n * }\n *\n * console.log(`Download: ${data.name} (${data.status})`)\n * if (data.status === 'available') {\n * console.log(`Size: ${data.sizeBytes} bytes`)\n * }\n * ```\n *\n * @category Downloads\n */\nexport async function getDownload(downloadId: string, params?: GetDownloadParams): Promise<Result<Download>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!downloadId) {\n return failure('VALIDATION_ERROR', 'Download ID is required')\n }\n\n const queryParams = new URLSearchParams()\n\n if (params?.include && params.include.length > 0) {\n queryParams.append('include', params.include.join(','))\n }\n\n const queryString = queryParams.toString()\n const url = `${authStore.baseUrl}/api/v3.0/downloads/${encodeURIComponent(downloadId)}${queryString ? `?${queryString}` : ''}`\n debug('Fetching download:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n const data = await response.json() as Download\n debug('Download fetched:', data.name, 'status:', data.status)\n\n return success(data)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to fetch download: ${String(err)}`)\n }\n}\n\n/**\n * Download the binary content of a download entry.\n *\n * @remarks\n * Downloads the actual file content from `/api/v3.0/downloads/{downloadId}:download`.\n * Returns a Blob that can be used to create a download link or process the file.\n *\n * For more details, see the\n * [EEN API Documentation](https://developer.eagleeyenetworks.com/reference/downloaddownload).\n *\n * @param downloadId - The unique identifier of the download to fetch\n * @returns A Result containing the download result with blob, filename, and metadata\n *\n * @example\n * ```typescript\n * import { downloadDownload } from 'een-api-toolkit'\n *\n * const { data, error } = await downloadDownload('download-123')\n *\n * if (error) {\n * console.error('Download failed:', error.message)\n * return\n * }\n *\n * // Create download link\n * const url = URL.createObjectURL(data.blob)\n * const a = document.createElement('a')\n * a.href = url\n * a.download = data.filename\n * a.click()\n * URL.revokeObjectURL(url)\n *\n * console.log(`Downloaded: ${data.filename} (${data.size} bytes)`)\n * ```\n *\n * @category Downloads\n */\nexport async function downloadDownload(downloadId: string): Promise<Result<DownloadDownloadResult>> {\n const authStore = useAuthStore()\n\n if (!authStore.isAuthenticated) {\n return failure('AUTH_REQUIRED', 'Authentication required')\n }\n\n if (!authStore.baseUrl) {\n return failure('AUTH_REQUIRED', 'Base URL not configured')\n }\n\n if (!downloadId) {\n return failure('VALIDATION_ERROR', 'Download ID is required')\n }\n\n const url = `${authStore.baseUrl}/api/v3.0/downloads/${encodeURIComponent(downloadId)}:download`\n debug('Downloading:', url)\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${authStore.token}`\n }\n })\n\n if (!response.ok) {\n return handleErrorResponse(response)\n }\n\n // Get the blob data\n const blob = await response.blob()\n\n // Parse filename from Content-Disposition header\n const contentDisposition = response.headers.get('Content-Disposition')\n let filename = 'download'\n if (contentDisposition) {\n const filenameMatch = contentDisposition.match(/filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/)\n if (filenameMatch && filenameMatch[1]) {\n filename = filenameMatch[1].replace(/['\"]/g, '')\n }\n }\n\n // Get content type\n const contentType = response.headers.get('Content-Type') || 'application/octet-stream'\n\n const result: DownloadDownloadResult = {\n blob,\n filename,\n contentType,\n size: blob.size\n }\n\n debug('Downloaded:', filename, blob.size, 'bytes')\n\n return success(result)\n } catch (err) {\n return failure('NETWORK_ERROR', `Failed to download: ${String(err)}`)\n }\n}\n\n/**\n * Handle error responses from the API.\n * @internal\n */\nasync function handleErrorResponse<T>(response: Response): Promise<Result<T>> {\n const status = response.status\n\n let message: string\n try {\n const errorData = await response.json()\n message = errorData.message ?? errorData.error ?? response.statusText\n } catch {\n message = response.statusText || 'Unknown error'\n }\n\n switch (status) {\n case 401:\n return failure('AUTH_REQUIRED', `Authentication failed: ${message}`, status)\n case 403:\n return failure('FORBIDDEN', `Access denied: ${message}`, status)\n case 404:\n return failure('NOT_FOUND', `Not found: ${message}`, status)\n case 429:\n return failure('RATE_LIMITED', `Rate limited: ${message}`, status)\n default:\n return failure('API_ERROR', `API error: ${message}`, status)\n }\n}\n"],"names":["isDebugEnabled","__vite_import_meta_env__","debug","args","STORAGE_STRATEGY_DESCRIPTIONS","MemoryStorage","key","value","BrowserStorageAdapter","storage","currentStrategy","memoryStorageInstance","getMemoryStorage","setStorageStrategy","strategy","getStorageStrategy","getStorageAdapter","config","initEenToolkit","options","storageStrategy","getConfig","getProxyUrl","getClientId","getRedirectUri","success","data","failure","code","message","status","details","formatTimestamp","timestamp","refreshTokenFnPromise","getRefreshTokenFn","service","useAuthStore","defineStore","token","ref","tokenExpiration","refreshTokenMarker","sessionId","hostname","port","userProfile","refreshTimerId","isRefreshing","refreshPromise","refreshFailed","refreshFailedMessage","isAuthenticated","computed","baseUrl","isTokenExpired","tokenExpiresIn","setToken","newToken","expiresIn","saveToStorage","setupAutoRefresh","setRefreshTokenMarker","marker","setSessionId","newSessionId","setBaseUrl","url","err","setUserProfile","profile","now","timeUntilExpiry","fiveMinutes","halfTtl","refreshBuffer","refreshTime","timeout","performAutoRefresh","result","clearRefreshFailed","logout","clearStorage","initialize","loadFromStorage","expStr","portStr","profileStr","EEN_AUTH_URL","getAuthUrl","clientId","state","params","getAccessToken","proxyUrl","response","errorText","refreshToken","authStore","headers","revokeToken","handleAuthCallback","storedState","constantTimeEquals","a","b","i","getCurrentUser","handleErrorResponse","getUsers","queryParams","queryString","getUser","userId","errorData","getCameras","getCamera","cameraId","parseError","getBridges","getBridge","bridgeId","getLayouts","getLayout","layoutId","createLayout","body","updateLayout","deleteLayout","DEFAULT_TIMEOUT_MS","createTimeoutController","timeoutMs","controller","timeoutId","arrayBufferToBase64","buffer","bytes","chunkSize","chunks","chunk","str","j","binary","listMedia","getLiveImage","type","prevToken","arrayBuffer","imageData","getRecordedImage","nextToken","overlaySvg","getMediaSession","initMediaSession","sessionResult","sessionUrl","listFeeds","apiMessage","listEvents","getEvent","eventId","listEventTypes","listEventFieldValues","getEventMetrics","listAlerts","getAlert","alertId","listAlertTypes","listNotifications","getNotification","notificationId","listEventSubscriptions","getEventSubscription","subscriptionId","createEventSubscription","filter","deleteEventSubscription","connectToEventSubscription","sseUrl","sseUrlObj","domain","MAX_BUFFER_SIZE","abortController","isClosing","setStatus","newStatus","close","reader","decoder","done","lines","eventData","line","dataValue","event","listEventAlertConditionRules","getEventAlertConditionRuleFieldValues","getEventAlertConditionRule","ruleId","listAlertConditionRules","getAlertConditionRule","listAlertActionRules","getAlertActionRule","listAlertActions","getAlertAction","actionId","createExportJob","info","period","listJobs","getJob","jobId","deleteJob","listFiles","getFile","fileId","addFile","downloadFile","blob","contentDisposition","filename","filenameMatch","contentType","deleteFile","listDownloads","getDownload","downloadId","downloadDownload"],"mappings":"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"}
|