een-api-toolkit 0.1.10 → 0.2.0

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +31 -66
  2. package/README.md +67 -3
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +119 -0
  6. package/dist/index.js +265 -184
  7. package/dist/index.js.map +1 -1
  8. package/docs/AI-CONTEXT.md +314 -1
  9. package/examples/vue-bridges/README.md +126 -0
  10. package/examples/vue-bridges/bridges-screenshot.png +0 -0
  11. package/examples/vue-bridges/package-lock.json +130 -42
  12. package/examples/vue-bridges/package.json +2 -2
  13. package/examples/vue-cameras/README.md +142 -0
  14. package/examples/vue-cameras/cameras-screenshot.png +0 -0
  15. package/examples/vue-cameras/package-lock.json +130 -42
  16. package/examples/vue-cameras/package.json +2 -2
  17. package/examples/vue-feeds/README.md +162 -0
  18. package/examples/vue-feeds/e2e/auth.spec.ts +174 -343
  19. package/examples/vue-feeds/feeds-screenshot.png +0 -0
  20. package/examples/vue-feeds/package-lock.json +137 -42
  21. package/examples/vue-feeds/package.json +3 -2
  22. package/examples/vue-feeds/playwright.config.ts +28 -7
  23. package/examples/vue-feeds/src/views/Feeds.vue +518 -2
  24. package/examples/vue-feeds/src/views/Home.vue +17 -1
  25. package/examples/vue-media/README.md +187 -0
  26. package/examples/vue-media/e2e/auth.spec.ts +198 -479
  27. package/examples/vue-media/media-screenshot.png +0 -0
  28. package/examples/vue-media/package-lock.json +130 -42
  29. package/examples/vue-media/package.json +2 -2
  30. package/examples/vue-media/playwright.config.ts +28 -7
  31. package/examples/vue-media/src/views/Home.vue +1 -1
  32. package/examples/vue-users/README.md +58 -15
  33. package/examples/vue-users/package-lock.json +132 -44
  34. package/examples/vue-users/package.json +3 -3
  35. package/examples/vue-users/users-screenshot.png +0 -0
  36. package/package.json +12 -11
package/CHANGELOG.md CHANGED
@@ -2,95 +2,60 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.1.10] - 2025-12-31
5
+ ## [0.2.0] - 2026-01-02
6
6
 
7
7
  ### Release Summary
8
8
 
9
- #### PR #35: feat: Add RecordedImage page with shared camera selection
9
+ #### PR #39: Release v0.1.13: Documentation updates and example improvements
10
10
  ## Summary
11
11
 
12
- Adds a new RecordedImage page to the vue-media example app with shared camera selection between Live and Recorded pages.
12
+ This release includes documentation improvements and developer experience enhancements:
13
13
 
14
- ### Changes
15
- - **RecordedImage.vue**: New page with date/time picker, prev/next navigation for browsing recorded images
16
- - **useSelectedCamera composable**: Shared camera state persisted via localStorage across pages
17
- - **LiveCamera.vue**: Added "View Recorded Images" button, uses shared camera composable
18
- - **Navigation**: Updated App.vue nav and Home.vue with links to Recorded page
19
- - **Router**: Added /recorded route
20
- - **E2E Tests**: Comprehensive tests for recorded image functionality and camera persistence
14
+ - **Example README files**: Added comprehensive README.md files with screenshots for all 5 example applications (vue-bridges, vue-cameras, vue-feeds, vue-media, vue-users)
15
+ - **Faster dev server startup**: Replaced slow `npx kill-port` (10-15 seconds) with native `lsof` command for instant port cleanup
16
+ - **Documentation fixes**: Fixed vue-users README to use functions instead of removed composables, updated docs/README.md to reference all example apps
21
17
 
22
- ### Commits
23
- - 61e4e88 feat: Add RecordedImage page with shared camera selection
18
+ ## Commits included
24
19
 
25
- ## Test Results
26
- - Lint: Passed (1 warning)
27
- - Unit tests: 131 passed
28
- - Build: Passed
29
-
30
- ## Version
31
- `0.1.7`
32
-
33
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
34
-
35
- #### PR #36: feat: RecordedImage page, code review fixes, and timestamp documentation
36
- ## Summary
37
-
38
- This PR adds the RecordedImage page to the vue-media example, addresses code review feedback, and documents the critical EEN timestamp format requirement.
39
-
40
- ### Features
41
- - **RecordedImage.vue**: New page with date/time picker, prev/next navigation for browsing recorded images
42
- - **Shared camera selection**: Camera selection persists between Live and Recorded pages via localStorage
43
- - **Time picker sync**: Automatically updates to show current image timestamp
44
-
45
- ### Security & Robustness Fixes
46
- - Camera ID validation with regex pattern to prevent XSS via localStorage
47
- - localStorage operations wrapped in try-catch for private browsing support
48
- - Initialization flag to prevent race conditions in composable
49
- - Extracted `_fetchImage` helper to eliminate duplication
50
- - Fixed stale data bug - image data cleared on error
51
- - Added ARIA labels for accessibility
52
-
53
- ### Documentation
54
- - Added Media API section to USER-GUIDE.md
55
- - Documented EEN timestamp format requirement (ISO 8601 with timezone offset, not Z suffix)
56
- - Added `toApiTimestamp()` helper function example
57
- - Updated AI-CONTEXT.md with same documentation
58
-
59
- ### Commits
60
- - 52f411b docs: Add EEN timestamp format documentation for recorded images
61
- - c635af2 Merge pull request #35 from klaushofrichter/develop
62
- - 6179fda fix: Address code review feedback for RecordedImage page
63
- - 61e4e88 feat: Add RecordedImage page with shared camera selection
20
+ - 9050e88 docs: Update README.md to reference all example apps
21
+ - 105051e docs: Fix vue-users README to use functions instead of composables
22
+ - 8d11c7a chore: Replace npx kill-port with faster native lsof command
23
+ - 741ca61 docs: Add README files and screenshots to example applications
24
+ - f4aa78b Merge pull request #38 from klaushofrichter/develop
25
+ - 6f3b0bf fix: Address code review feedback from PR #38
26
+ - 0432d7a feat: Add Media Session API and live video streaming to vue-feeds
64
27
 
65
28
  ## Test Results
66
- - Lint: ✅ Passed (1 warning)
67
- - Unit tests: 131 passed
68
- - Build: Passed
29
+
30
+ - Lint: Passed (1 expected warning for unused vars in test files)
31
+ - ✅ Unit tests: 164 passed
32
+ - ✅ Build: Succeeded
69
33
 
70
34
  ## Version
71
- `0.1.7`
35
+
36
+ **0.1.13**
72
37
 
73
38
  🤖 Generated with [Claude Code](https://claude.com/claude-code)
74
39
 
75
40
 
76
41
  ### Detailed Changes
77
42
 
78
- #### Features
79
- - feat: Add Feeds API with listFeeds function and vue-feeds example
80
- - feat: Add RecordedImage page with shared camera selection
81
-
82
43
  #### Bug Fixes
83
- - fix: Address additional code review concerns
84
- - fix: Address code review feedback from PR #37
85
- - fix: Address code review feedback for RecordedImage page
44
+ - fix: Address remaining code review recommendations
45
+ - fix: Address code review feedback for PR #40
46
+ - fix: Address code review feedback - macOS note, xargs safety, and skill fix
86
47
 
87
48
  #### Other Changes
88
- - docs: Fix timestamp examples and regenerate AI-CONTEXT
89
- - docs: Add EEN timestamp format documentation for recorded images
49
+ - chore: Bump version to 0.2.0 and add CHANGELOG
50
+ - chore: Update dependencies and fix E2E tests
51
+ - docs: Update README.md to reference all example apps
52
+ - docs: Fix vue-users README to use functions instead of composables
53
+ - chore: Replace npx kill-port with faster native lsof command
54
+ - docs: Add README files and screenshots to example applications
90
55
 
91
56
  ### Links
92
57
  - [npm package](https://www.npmjs.com/package/een-api-toolkit)
93
- - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.1.7...v0.1.10)
58
+ - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.1.13...v0.2.0)
94
59
 
95
60
  ---
96
- *Released: 2025-12-31 20:55:04 CST*
61
+ *Released: 2026-01-02 09:30:09 CST*
package/README.md CHANGED
@@ -131,9 +131,9 @@ if (!cameraError) {
131
131
 
132
132
  ```
133
133
  ┌──────────────────────────────────────────────────────────────────────┐
134
- │ Your Vue 3 App
134
+ │ Your Vue 3 App
135
135
  │ ┌────────────────────────────────────────────────────────────────┐ │
136
- │ │ import from 'een-api-toolkit' │ │
136
+ │ │ import from 'een-api-toolkit' │ │
137
137
  │ │ ┌────────────────────────────────────┐ │ │
138
138
  │ │ │ Plain Async Functions │ │ │
139
139
  │ │ │ getUsers(), getCameras() │ │ │
@@ -169,10 +169,74 @@ if (!cameraError) {
169
169
  | **[User Guide](./docs/USER-GUIDE.md)** | Installation, proxy setup, configuration, building apps |
170
170
  | **[Developer Guide](./docs/DEVELOPER-GUIDE.md)** | Architecture, testing, CI/CD, contributing |
171
171
  | **[API Reference](./docs/api/)** | Auto-generated TypeDoc documentation |
172
- | **[Example App](./examples/vue-users/)** | Complete Vue 3 example with OAuth flow |
173
172
  | **[AI Context](./docs/AI-CONTEXT.md)** | Single-file reference for AI assistants (also in npm package) |
174
173
  | **[AI Prompts](./docs/Prompts.md)** | Example prompts for generating apps with AI |
175
174
 
175
+ ## Example Applications
176
+
177
+ The `examples/` directory contains complete Vue 3 applications demonstrating toolkit features:
178
+
179
+ | Example | Description | APIs Used |
180
+ |---------|-------------|-----------|
181
+ | **[vue-users](./examples/vue-users/)** | User management with pagination | `getUsers()`, `getCurrentUser()` |
182
+ | **[vue-cameras](./examples/vue-cameras/)** | Camera listing with status filters | `getCameras()` |
183
+ | **[vue-bridges](./examples/vue-bridges/)** | Bridge listing with device info | `getBridges()` |
184
+ | **[vue-media](./examples/vue-media/)** | Live and recorded image viewing | `getCameras()`, `getLiveImage()`, `getRecordedImage()` |
185
+ | **[vue-feeds](./examples/vue-feeds/)** | Live video streaming with preview and main streams | `getCameras()`, `listFeeds()`, `initMediaSession()` |
186
+
187
+ Each example includes:
188
+ - Complete OAuth authentication flow
189
+ - E2E tests with Playwright
190
+ - Proper error handling patterns
191
+ - TypeScript types throughout
192
+
193
+ To run an example:
194
+ ```bash
195
+ cd examples/vue-users
196
+ npm install
197
+ npm run dev # Runs at http://127.0.0.1:3333
198
+ ```
199
+
200
+ > **Note:** Examples require a running OAuth proxy. See [Quick Start](#2-set-up-oauth-proxy).
201
+
202
+ ## Running E2E Tests
203
+
204
+ Each example includes Playwright E2E tests that test the full OAuth login flow. Tests are designed to skip gracefully when the OAuth proxy or credentials are unavailable.
205
+
206
+ ### Prerequisites
207
+
208
+ 1. **OAuth Proxy**: Start the proxy server:
209
+ ```bash
210
+ ./scripts/restart-proxy.sh # Starts proxy at http://127.0.0.1:8787
211
+ ```
212
+
213
+ 2. **Environment Variables**: Create a `.env` file in the project root:
214
+ ```bash
215
+ VITE_PROXY_URL=http://127.0.0.1:8787
216
+ VITE_EEN_CLIENT_ID=your_client_id
217
+ TEST_USER=your_test_email
218
+ TEST_PASSWORD=your_test_password
219
+ ```
220
+
221
+ ### Running Tests
222
+
223
+ ```bash
224
+ # Run E2E tests for a specific example
225
+ cd examples/vue-users
226
+ npm run test:e2e
227
+
228
+ # Run with UI for debugging
229
+ npm run test:e2e:ui
230
+ ```
231
+
232
+ ### Test Behavior
233
+
234
+ - **Proxy unavailable**: OAuth tests are automatically skipped with message "OAuth proxy not accessible"
235
+ - **Credentials missing**: OAuth tests are skipped with message "Test credentials not available"
236
+ - **Basic tests**: Tests that don't require OAuth (e.g., checking login button visibility) always run
237
+
238
+ > **Note:** All development and testing has been done on macOS. The `lsof` command used in scripts may behave differently on other platforms.
239
+
176
240
  ## External Resources
177
241
 
178
242
  - [EEN Developer Portal](https://developer.eagleeyenetworks.com/)
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const oe=require("pinia"),f=require("vue"),T={};let v={};function ae(e={}){v={proxyUrl:e.proxyUrl??T?.VITE_PROXY_URL,clientId:e.clientId??T?.VITE_EEN_CLIENT_ID,redirectUri:e.redirectUri??T?.VITE_REDIRECT_URI,debug:e.debug??T?.VITE_DEBUG==="true"}}function se(){return v}function y(){return v.proxyUrl??T?.VITE_PROXY_URL}function F(){return v.clientId??T?.VITE_EEN_CLIENT_ID}function $(){return v.redirectUri??T?.VITE_REDIRECT_URI??"http://127.0.0.1:3333"}function _(e){return{data:e,error:null}}function i(e,n,t,r){return{data:null,error:{code:e,message:n,status:t,details:r}}}const ce={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},ue=()=>{try{return ce?.VITE_DEBUG==="true"}catch{return!1}};function c(...e){ue()&&console.log("[een-api-toolkit]",...e)}let D=null;function le(){return D||(D=Promise.resolve().then(()=>fe).then(e=>e.refreshToken)),D}const g=oe.defineStore("een-auth",()=>{const e=f.ref(null),n=f.ref(null),t=f.ref(null),r=f.ref(null),s=f.ref(null),o=f.ref(443),a=f.ref(null),l=f.ref(null),p=f.ref(!1);let R=null;const h=f.ref(!1),I=f.ref(null),U=f.computed(()=>!!e.value),S=f.computed(()=>s.value?o.value===443?`https://${s.value}`:`https://${s.value}:${o.value}`:null),k=f.computed(()=>n.value?Date.now()>=n.value:!0),M=f.computed(()=>n.value?Math.max(0,n.value-Date.now()):0);function Q(u,d){e.value=u,n.value=Date.now()+d*1e3,E(),m(),c("Token set, expires in",d,"seconds")}function V(u){t.value=u,E()}function W(u){r.value=u,E()}function K(u){if(typeof u=="string")try{const d=new URL(u.startsWith("http")?u:`https://${u}`);s.value=d.hostname,o.value=d.port?parseInt(d.port,10):443}catch(d){c("Failed to parse URL, using as hostname:",d instanceof Error?d.message:String(d)),s.value=u,o.value=443}else s.value=u.hostname,o.value=u.port??443;E(),c("Base URL set:",S.value)}function G(u){a.value=u,E()}function m(){if(l.value&&(clearTimeout(l.value),l.value=null),!n.value||!e.value)return;const u=Date.now(),A=n.value-u,te=300*1e3,ne=A/2,re=Math.min(te,ne),ie=Math.max(A-re,60*1e3),N=Math.max(ie,5e3);c("Auto-refresh scheduled in",Math.round(N/1e3),"seconds"),l.value=setTimeout(async()=>{await X()},N)}async function X(){return R?(c("Refresh already in progress, waiting for existing refresh"),R):(p.value=!0,c("Performing auto-refresh"),R=(async()=>{try{const d=await(await le())();d.error?(h.value=!0,I.value=d.error.message,c("Auto-refresh failed:",d.error.message)):(h.value=!1,I.value=null,c("Auto-refresh successful"))}catch(u){h.value=!0,I.value=u instanceof Error?u.message:String(u),c("Auto-refresh error:",u)}finally{p.value=!1,R=null}})(),R)}function J(){h.value=!1,I.value=null}function j(){l.value&&(clearTimeout(l.value),l.value=null),e.value=null,n.value=null,t.value=null,r.value=null,s.value=null,o.value=443,a.value=null,h.value=!1,I.value=null,ee(),c("Logged out")}function Y(){Z(),e.value&&!k.value?(m(),c("Initialized from storage")):e.value&&k.value&&(c("Stored token expired, clearing"),j())}function E(){try{e.value&&localStorage.setItem("een_token",e.value),n.value&&localStorage.setItem("een_tokenExpiration",String(n.value)),t.value&&localStorage.setItem("een_refreshTokenMarker",t.value),r.value&&localStorage.setItem("een_sessionId",r.value),s.value&&localStorage.setItem("een_hostname",s.value),o.value!==443&&localStorage.setItem("een_port",String(o.value)),a.value&&localStorage.setItem("een_userProfile",JSON.stringify(a.value))}catch(u){c("Failed to save to localStorage:",u instanceof Error?u.message:String(u))}}function Z(){try{e.value=localStorage.getItem("een_token");const u=localStorage.getItem("een_tokenExpiration");n.value=u?parseInt(u,10):null,t.value=localStorage.getItem("een_refreshTokenMarker"),r.value=localStorage.getItem("een_sessionId"),s.value=localStorage.getItem("een_hostname");const d=localStorage.getItem("een_port");o.value=d?parseInt(d,10):443;const A=localStorage.getItem("een_userProfile");a.value=A?JSON.parse(A):null}catch(u){c("Failed to load from localStorage:",u instanceof Error?u.message:String(u))}}function ee(){try{localStorage.removeItem("een_token"),localStorage.removeItem("een_tokenExpiration"),localStorage.removeItem("een_refreshTokenMarker"),localStorage.removeItem("een_sessionId"),localStorage.removeItem("een_hostname"),localStorage.removeItem("een_port"),localStorage.removeItem("een_userProfile")}catch(u){c("Failed to clear localStorage:",u instanceof Error?u.message:String(u))}}return{token:e,tokenExpiration:n,refreshTokenMarker:t,sessionId:r,hostname:s,port:o,userProfile:a,isRefreshing:p,refreshFailed:h,refreshFailedMessage:I,isAuthenticated:U,baseUrl:S,isTokenExpired:k,tokenExpiresIn:M,setToken:Q,setRefreshTokenMarker:V,setSessionId:W,setBaseUrl:K,setUserProfile:G,setupAutoRefresh:m,clearRefreshFailed:J,logout:j,initialize:Y}}),de="https://auth.eagleeyenetworks.com/oauth2/authorize";function P(){const e=F();if(!e)throw new Error("Client ID not configured. Call initEenToolkit() or set VITE_EEN_CLIENT_ID");const n=crypto.randomUUID();try{sessionStorage.setItem("een_oauth_state",n)}catch{}const t=new URLSearchParams({client_id:e,response_type:"code",scope:"vms.all",redirect_uri:$(),state:n});return c("Generated auth URL with state:",n),`${de}?${t.toString()}`}async function O(e){const n=y();if(!n)return i("AUTH_FAILED","Proxy URL not configured. Call initEenToolkit() or set VITE_PROXY_URL");const t=new URLSearchParams({code:e,redirect_uri:$()});try{const r=await fetch(`${n}/proxy/getAccessToken?${t.toString()}`,{method:"POST",credentials:"include",headers:{Accept:"application/json"}});if(!r.ok){const o=await r.text().catch(()=>"Unknown error");return i("AUTH_FAILED",`Token exchange failed: ${o}`,r.status)}const s=await r.json();return c("Token received, expires in:",s.expiresIn),_(s)}catch(r){return i("NETWORK_ERROR",`Failed to exchange code: ${String(r)}`)}}async function q(){const e=y();if(!e)return i("AUTH_FAILED","Proxy URL not configured");const n=g();try{const t={Accept:"application/json"};n.sessionId&&(t.Authorization=`Bearer ${n.sessionId}`);const r=await fetch(`${e}/proxy/refreshAccessToken`,{method:"POST",credentials:"include",headers:t});if(!r.ok){const o=await r.text().catch(()=>"Unknown error");return i("AUTH_FAILED",`Token refresh failed: ${o}`,r.status)}const s=await r.json();return n.setToken(s.accessToken,s.expiresIn),c("Token refreshed, expires in:",s.expiresIn),_(s)}catch(t){return i("NETWORK_ERROR",`Failed to refresh token: ${String(t)}`)}}async function x(){const e=y();if(!e)return i("AUTH_FAILED","Proxy URL not configured");const n=g();try{const t={Accept:"application/json"};n.sessionId&&(t.Authorization=`Bearer ${n.sessionId}`);const r=await fetch(`${e}/proxy/revoke`,{method:"POST",credentials:"include",headers:t});if(n.logout(),!r.ok){const s=await r.text().catch(()=>"Unknown error");return i("AUTH_FAILED",`Token revocation failed: ${s}`,r.status)}return c("Token revoked"),_(void 0)}catch(t){return n.logout(),i("NETWORK_ERROR",`Failed to revoke token: ${String(t)}`)}}async function B(e,n){let t=null;try{t=sessionStorage.getItem("een_oauth_state"),sessionStorage.removeItem("een_oauth_state")}catch{}if(!t)return i("AUTH_FAILED","No OAuth state found. Please restart the login process.");if(!_e(n,t))return i("AUTH_FAILED","Invalid OAuth state. Possible CSRF attack.");c("State validated, exchanging code for token");const r=await O(e);if(r.error)return r;const s=g(),o=r.data;return s.setToken(o.accessToken,o.expiresIn),s.setRefreshTokenMarker("present"),s.setSessionId(o.sessionId),s.setBaseUrl(o.httpsBaseUrl),c("Auth callback complete, user:",o.userEmail),_(o)}function _e(e,n){if(e.length!==n.length)return!1;let t=0;for(let r=0;r<e.length;r++)t|=e.charCodeAt(r)^n.charCodeAt(r);return t===0}const fe=Object.freeze(Object.defineProperty({__proto__:null,getAccessToken:O,getAuthUrl:P,handleAuthCallback:B,refreshToken:q,revokeToken:x},Symbol.toStringTag,{value:"Module"}));async function ge(){const e=g();if(!e.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!e.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const n=`${e.baseUrl}/api/v3.0/users/self`;c("Fetching current user:",n);try{const t=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e.token}`}});if(!t.ok)return b(t);const r=await t.json();return c("Current user fetched:",r.email),e.setUserProfile(r),_(r)}catch(t){return i("NETWORK_ERROR",`Failed to fetch current user: ${String(t)}`)}}async function he(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;e?.pageSize&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.include&&e.include.length>0&&t.append("include",e.include.join(","));const r=t.toString(),s=`${n.baseUrl}/api/v3.0/users${r?`?${r}`:""}`;c("Fetching users:",s);try{const o=await fetch(s,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!o.ok)return b(o);const a=await o.json();return c("Users fetched:",a.results?.length??0,"users"),_(a)}catch(o){return i("NETWORK_ERROR",`Failed to fetch users: ${String(o)}`)}}async function Re(e,n){const t=g();if(!t.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e)return i("VALIDATION_ERROR","User ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const s=r.toString(),o=`${t.baseUrl}/api/v3.0/users/${encodeURIComponent(e)}${s?`?${s}`:""}`;c("Fetching user:",o);try{const a=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!a.ok)return b(a);const l=await a.json();return c("User fetched:",l.email),_(l)}catch(a){return i("NETWORK_ERROR",`Failed to fetch user: ${String(a)}`)}}async function b(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch{t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}async function Ie(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;e?.pageSize&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.include&&e.include.length>0&&t.append("include",e.include.join(",")),e?.sort&&e.sort.length>0&&t.append("sort",e.sort.join(",")),e?.locationId__in&&e.locationId__in.length>0&&t.append("locationId__in",e.locationId__in.join(",")),e?.bridgeId__in&&e.bridgeId__in.length>0&&t.append("bridgeId__in",e.bridgeId__in.join(",")),e?.multiCameraId&&t.append("multiCameraId",e.multiCameraId),e?.multiCameraId__ne&&t.append("multiCameraId__ne",e.multiCameraId__ne),e?.multiCameraId__in&&e.multiCameraId__in.length>0&&t.append("multiCameraId__in",e.multiCameraId__in.join(",")),e?.tags__contains&&e.tags__contains.length>0&&t.append("tags__contains",e.tags__contains.join(",")),e?.tags__any&&e.tags__any.length>0&&t.append("tags__any",e.tags__any.join(",")),e?.packages__contains&&e.packages__contains.length>0&&t.append("packages__contains",e.packages__contains.join(",")),e?.name&&t.append("name",e.name),e?.name__contains&&t.append("name__contains",e.name__contains),e?.name__in&&e.name__in.length>0&&t.append("name__in",e.name__in.join(",")),e?.id__in&&e.id__in.length>0&&t.append("id__in",e.id__in.join(",")),e?.id__notIn&&e.id__notIn.length>0&&t.append("id__notIn",e.id__notIn.join(",")),e?.id__contains&&t.append("id__contains",e.id__contains),e?.layoutId&&t.append("layoutId",e.layoutId),typeof e?.shared=="boolean"&&t.append("shareDetails.shared",String(e.shared)),e?.sharedCameraAccount&&t.append("shareDetails.accountId",e.sharedCameraAccount),typeof e?.firstResponder=="boolean"&&t.append("shareDetails.firstResponder",String(e.firstResponder)),typeof e?.directToCloud=="boolean"&&t.append("deviceInfo.directToCloud",String(e.directToCloud)),e?.speakerId__in&&e.speakerId__in.length>0&&t.append("speakerId__in",e.speakerId__in.join(",")),e?.q&&t.append("q",e.q),typeof e?.qRelevance__gte=="number"&&t.append("qRelevance__gte",String(e.qRelevance__gte)),e?.enabledAnalytics__contains&&e.enabledAnalytics__contains.length>0&&t.append("enabledAnalytics__contains",e.enabledAnalytics__contains.join(",")),e?.status__in&&e.status__in.length>0&&t.append("status__in",e.status__in.join(",")),e?.status__ne&&t.append("status__ne",e.status__ne);const r=t.toString(),s=`${n.baseUrl}/api/v3.0/cameras${r?`?${r}`:""}`;c("Fetching cameras:",s);try{const o=await fetch(s,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!o.ok)return C(o);const a=await o.json();return c("Cameras fetched:",a.results?.length??0,"cameras"),_(a)}catch(o){return i("NETWORK_ERROR",`Failed to fetch cameras: ${String(o)}`)}}async function pe(e,n){const t=g();if(!t.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e)return i("VALIDATION_ERROR","Camera ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const s=r.toString(),o=`${t.baseUrl}/api/v3.0/cameras/${encodeURIComponent(e)}${s?`?${s}`:""}`;c("Fetching camera:",o);try{const a=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!a.ok)return C(a);const l=await a.json();return c("Camera fetched:",l.name),_(l)}catch(a){return i("NETWORK_ERROR",`Failed to fetch camera: ${String(a)}`)}}async function C(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch(r){c("Failed to parse error response JSON:",r),t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}async function Te(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;e?.pageSize&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.include&&e.include.length>0&&t.append("include",e.include.join(",")),e?.sort&&e.sort.length>0&&t.append("sort",e.sort.join(",")),e?.locationId__in&&e.locationId__in.length>0&&t.append("locationId__in",e.locationId__in.join(",")),e?.tags__contains&&e.tags__contains.length>0&&t.append("tags__contains",e.tags__contains.join(",")),e?.tags__any&&e.tags__any.length>0&&t.append("tags__any",e.tags__any.join(",")),e?.name&&t.append("name",e.name),e?.name__contains&&t.append("name__contains",e.name__contains),e?.name__in&&e.name__in.length>0&&t.append("name__in",e.name__in.join(",")),e?.id__in&&e.id__in.length>0&&t.append("id__in",e.id__in.join(",")),e?.id__notIn&&e.id__notIn.length>0&&t.append("id__notIn",e.id__notIn.join(",")),e?.q&&t.append("q",e.q),typeof e?.qRelevance__gte=="number"&&t.append("qRelevance__gte",String(e.qRelevance__gte)),e?.status__in&&e.status__in.length>0&&t.append("status__in",e.status__in.join(",")),e?.status__ne&&t.append("status__ne",e.status__ne);const r=t.toString(),s=`${n.baseUrl}/api/v3.0/bridges${r?`?${r}`:""}`;c("Fetching bridges:",s);try{const o=await fetch(s,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!o.ok)return H(o);const a=await o.json();return c("Bridges fetched:",a.results?.length??0,"bridges"),_(a)}catch(o){return i("NETWORK_ERROR",`Failed to fetch bridges: ${String(o)}`)}}async function Ee(e,n){const t=g();if(!t.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e)return i("VALIDATION_ERROR","Bridge ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const s=r.toString(),o=`${t.baseUrl}/api/v3.0/bridges/${encodeURIComponent(e)}${s?`?${s}`:""}`;c("Fetching bridge:",o);try{const a=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!a.ok)return H(a);const l=await a.json();return c("Bridge fetched:",l.name),_(l)}catch(a){return i("NETWORK_ERROR",`Failed to fetch bridge: ${String(a)}`)}}async function H(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch(r){c("Failed to parse error response JSON:",r),t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}const Ae=3e4;function w(e=Ae){const n=new AbortController,t=setTimeout(()=>n.abort(),e);return{controller:n,timeoutId:t}}function z(e){const n=new Uint8Array(e),t=8192,r=[];for(let o=0;o<n.byteLength;o+=t){const a=n.subarray(o,Math.min(o+t,n.byteLength));r.push(String.fromCharCode.apply(null,a))}const s=r.join("");return typeof btoa=="function"?btoa(s):Buffer.from(s,"binary").toString("base64")}async function ve(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e.deviceId)return i("VALIDATION_ERROR","Device ID is required");if(!e.type)return i("VALIDATION_ERROR","Stream type is required (preview or main)");if(!e.mediaType)return i("VALIDATION_ERROR","Media type is required (video or image)");if(!e.startTimestamp)return i("VALIDATION_ERROR","Start timestamp is required");const t=new URLSearchParams;t.append("deviceId",e.deviceId),t.append("type",e.type),t.append("mediaType",e.mediaType),t.append("startTimestamp__gte",e.startTimestamp),e.endTimestamp&&t.append("endTimestamp__lte",e.endTimestamp),typeof e.coalesce=="boolean"&&t.append("coalesce",String(e.coalesce)),e.include&&e.include.length>0&&t.append("include",e.include.join(",")),e.pageToken&&t.append("pageToken",e.pageToken),typeof e.pageSize=="number"&&t.append("pageSize",String(e.pageSize));const r=`${n.baseUrl}/api/v3.0/media?${t.toString()}`;c("Fetching media intervals:",r);const{controller:s,timeoutId:o}=w();try{const a=await fetch(r,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`},signal:s.signal});if(!a.ok)return L(a);const l=await a.json();return c("Media intervals fetched:",l.results?.length??0,"intervals"),_(l)}catch(a){return a instanceof Error&&a.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch media intervals: ${String(a)}`)}finally{clearTimeout(o)}}async function Ue(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e.deviceId)return i("VALIDATION_ERROR","Device ID is required");const t=e.type??"preview",r=new URLSearchParams;r.append("deviceId",e.deviceId),r.append("type",t);const s=`${n.baseUrl}/api/v3.0/media/liveImage.jpeg?${r.toString()}`;c("Fetching live image:",s);const{controller:o,timeoutId:a}=w();try{const l=await fetch(s,{method:"GET",headers:{Accept:"image/jpeg",Authorization:`Bearer ${n.token}`},signal:o.signal}),p=l.headers.get("X-Een-Timestamp"),R=l.headers.get("X-Een-PrevToken");if(!l.ok)return L(l);const h=await l.arrayBuffer(),U=`data:image/jpeg;base64,${z(h)}`;return c("Live image fetched, timestamp:",p),_({imageData:U,timestamp:p,prevToken:R})}catch(l){return l instanceof Error&&l.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch live image: ${String(l)}`)}finally{clearTimeout(a)}}async function Se(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e.deviceId&&!e.pageToken)return i("VALIDATION_ERROR","Either deviceId or pageToken is required");if(!e.pageToken&&!(e.timestamp__lt||e.timestamp__lte||e.timestamp||e.timestamp__gte||e.timestamp__gt))return i("VALIDATION_ERROR","At least one timestamp parameter is required");if(e.include?.includes("overlaySvgHeader")&&(!e.overlayId__in||e.overlayId__in.length===0))return i("VALIDATION_ERROR","At least one overlayId must be provided when requesting overlay headers");const t=new URLSearchParams;e.deviceId&&t.append("deviceId",e.deviceId),e.pageToken&&t.append("pageToken",e.pageToken),e.type&&t.append("type",e.type),e.timestamp__lt&&t.append("timestamp__lt",e.timestamp__lt),e.timestamp__lte&&t.append("timestamp__lte",e.timestamp__lte),e.timestamp&&t.append("timestamp",e.timestamp),e.timestamp__gte&&t.append("timestamp__gte",e.timestamp__gte),e.timestamp__gt&&t.append("timestamp__gt",e.timestamp__gt),e.overlayId__in&&e.overlayId__in.length>0&&t.append("overlayId__in",e.overlayId__in.join(",")),e.include&&e.include.length>0&&t.append("include",e.include.join(",")),typeof e.targetWidth=="number"&&t.append("targetWidth",String(e.targetWidth)),typeof e.targetHeight=="number"&&t.append("targetHeight",String(e.targetHeight));const r=`${n.baseUrl}/api/v3.0/media/recordedImage.jpeg?${t.toString()}`;c("Fetching recorded image:",r);const{controller:s,timeoutId:o}=w();try{const a=await fetch(r,{method:"GET",headers:{Accept:"image/jpeg",Authorization:`Bearer ${n.token}`},signal:s.signal}),l=a.headers.get("X-Een-Timestamp"),p=a.headers.get("X-Een-NextToken"),R=a.headers.get("X-Een-PrevToken"),h=a.headers.get("X-Een-OverlaySvg");if(!a.ok)return L(a);const I=await a.arrayBuffer(),S=`data:image/jpeg;base64,${z(I)}`;return c("Recorded image fetched, timestamp:",l),_({imageData:S,timestamp:l,nextToken:p,prevToken:R,overlaySvg:h})}catch(a){return a instanceof Error&&a.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch recorded image: ${String(a)}`)}finally{clearTimeout(o)}}async function L(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch{t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);case 503:return i("SERVICE_UNAVAILABLE",`Service unavailable: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}async function ye(e){const n=g();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;typeof e?.pageSize=="number"&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.deviceId&&t.append("deviceId",e.deviceId),e?.deviceId__in&&e.deviceId__in.length>0&&t.append("deviceId__in",e.deviceId__in.join(",")),e?.type&&t.append("type",e.type),e?.include&&e.include.length>0&&t.append("include",e.include.join(","));const r=t.toString(),s=`${n.baseUrl}/api/v3.0/feeds${r?`?${r}`:""}`;c("Fetching feeds:",s);try{const o=await fetch(s,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`},signal:e?.signal});if(!o.ok)return ke(o);const a=await o.json();return c("Feeds fetched:",a.results?.length??0,"feeds"),_(a)}catch(o){return i("NETWORK_ERROR",`Failed to fetch feeds: ${String(o)}`)}}async function ke(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error}catch(r){c("Failed to parse error response JSON:",r)}switch(n){case 401:return i("AUTH_REQUIRED",t||"Authentication failed",n);case 403:return i("FORBIDDEN",t||"Access denied",n);case 404:return i("NOT_FOUND",t||"Not found",n);case 429:return i("RATE_LIMITED",t||"Rate limited",n);case 503:return i("SERVICE_UNAVAILABLE",t||"Service unavailable",n);default:return i("API_ERROR",t||e.statusText||"API error",n)}}exports.failure=i;exports.getAccessToken=O;exports.getAuthUrl=P;exports.getBridge=Ee;exports.getBridges=Te;exports.getCamera=pe;exports.getCameras=Ie;exports.getClientId=F;exports.getConfig=se;exports.getCurrentUser=ge;exports.getLiveImage=Ue;exports.getProxyUrl=y;exports.getRecordedImage=Se;exports.getRedirectUri=$;exports.getUser=Re;exports.getUsers=he;exports.handleAuthCallback=B;exports.initEenToolkit=ae;exports.listFeeds=ye;exports.listMedia=ve;exports.refreshToken=q;exports.revokeToken=x;exports.success=_;exports.useAuthStore=g;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ae=require("pinia"),h=require("vue"),p={};let U={};function se(e={}){U={proxyUrl:e.proxyUrl??p?.VITE_PROXY_URL,clientId:e.clientId??p?.VITE_EEN_CLIENT_ID,redirectUri:e.redirectUri??p?.VITE_REDIRECT_URI,debug:e.debug??p?.VITE_DEBUG==="true"}}function ce(){return U}function m(){return U.proxyUrl??p?.VITE_PROXY_URL}function F(){return U.clientId??p?.VITE_EEN_CLIENT_ID}function b(){return U.redirectUri??p?.VITE_REDIRECT_URI??"http://127.0.0.1:3333"}function f(e){return{data:e,error:null}}function i(e,n,t,r){return{data:null,error:{code:e,message:n,status:t,details:r}}}const ue={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},le=()=>{try{return ue?.VITE_DEBUG==="true"}catch{return!1}};function c(...e){le()&&console.log("[een-api-toolkit]",...e)}let D=null;function de(){return D||(D=Promise.resolve().then(()=>ge).then(e=>e.refreshToken)),D}const _=ae.defineStore("een-auth",()=>{const e=h.ref(null),n=h.ref(null),t=h.ref(null),r=h.ref(null),a=h.ref(null),o=h.ref(443),s=h.ref(null),u=h.ref(null),g=h.ref(!1);let I=null;const R=h.ref(!1),E=h.ref(null),S=h.computed(()=>!!e.value),y=h.computed(()=>a.value?o.value===443?`https://${a.value}`:`https://${a.value}:${o.value}`:null),O=h.computed(()=>n.value?Date.now()>=n.value:!0),Q=h.computed(()=>n.value?Math.max(0,n.value-Date.now()):0);function V(l,d){e.value=l,n.value=Date.now()+d*1e3,T(),$(),c("Token set, expires in",d,"seconds")}function W(l){t.value=l,T()}function K(l){r.value=l,T()}function G(l){if(typeof l=="string")try{const d=new URL(l.startsWith("http")?l:`https://${l}`);a.value=d.hostname,o.value=d.port?parseInt(d.port,10):443}catch(d){c("Failed to parse URL, using as hostname:",d instanceof Error?d.message:String(d)),a.value=l,o.value=443}else a.value=l.hostname,o.value=l.port??443;T(),c("Base URL set:",y.value)}function X(l){s.value=l,T()}function $(){if(u.value&&(clearTimeout(u.value),u.value=null),!n.value||!e.value)return;const l=Date.now(),A=n.value-l,ne=300*1e3,re=A/2,ie=Math.min(ne,re),oe=Math.max(A-ie,60*1e3),N=Math.max(oe,5e3);c("Auto-refresh scheduled in",Math.round(N/1e3),"seconds"),u.value=setTimeout(async()=>{await J()},N)}async function J(){return I?(c("Refresh already in progress, waiting for existing refresh"),I):(g.value=!0,c("Performing auto-refresh"),I=(async()=>{try{const d=await(await de())();d.error?(R.value=!0,E.value=d.error.message,c("Auto-refresh failed:",d.error.message)):(R.value=!1,E.value=null,c("Auto-refresh successful"))}catch(l){R.value=!0,E.value=l instanceof Error?l.message:String(l),c("Auto-refresh error:",l)}finally{g.value=!1,I=null}})(),I)}function Y(){R.value=!1,E.value=null}function j(){u.value&&(clearTimeout(u.value),u.value=null),e.value=null,n.value=null,t.value=null,r.value=null,a.value=null,o.value=443,s.value=null,R.value=!1,E.value=null,te(),c("Logged out")}function Z(){ee(),e.value&&!O.value?($(),c("Initialized from storage")):e.value&&O.value&&(c("Stored token expired, clearing"),j())}function T(){try{e.value&&localStorage.setItem("een_token",e.value),n.value&&localStorage.setItem("een_tokenExpiration",String(n.value)),t.value&&localStorage.setItem("een_refreshTokenMarker",t.value),r.value&&localStorage.setItem("een_sessionId",r.value),a.value&&localStorage.setItem("een_hostname",a.value),o.value!==443&&localStorage.setItem("een_port",String(o.value)),s.value&&localStorage.setItem("een_userProfile",JSON.stringify(s.value))}catch(l){c("Failed to save to localStorage:",l instanceof Error?l.message:String(l))}}function ee(){try{e.value=localStorage.getItem("een_token");const l=localStorage.getItem("een_tokenExpiration");n.value=l?parseInt(l,10):null,t.value=localStorage.getItem("een_refreshTokenMarker"),r.value=localStorage.getItem("een_sessionId"),a.value=localStorage.getItem("een_hostname");const d=localStorage.getItem("een_port");o.value=d?parseInt(d,10):443;const A=localStorage.getItem("een_userProfile");s.value=A?JSON.parse(A):null}catch(l){c("Failed to load from localStorage:",l instanceof Error?l.message:String(l))}}function te(){try{localStorage.removeItem("een_token"),localStorage.removeItem("een_tokenExpiration"),localStorage.removeItem("een_refreshTokenMarker"),localStorage.removeItem("een_sessionId"),localStorage.removeItem("een_hostname"),localStorage.removeItem("een_port"),localStorage.removeItem("een_userProfile")}catch(l){c("Failed to clear localStorage:",l instanceof Error?l.message:String(l))}}return{token:e,tokenExpiration:n,refreshTokenMarker:t,sessionId:r,hostname:a,port:o,userProfile:s,isRefreshing:g,refreshFailed:R,refreshFailedMessage:E,isAuthenticated:S,baseUrl:y,isTokenExpired:O,tokenExpiresIn:Q,setToken:V,setRefreshTokenMarker:W,setSessionId:K,setBaseUrl:G,setUserProfile:X,setupAutoRefresh:$,clearRefreshFailed:Y,logout:j,initialize:Z}}),fe="https://auth.eagleeyenetworks.com/oauth2/authorize";function P(){const e=F();if(!e)throw new Error("Client ID not configured. Call initEenToolkit() or set VITE_EEN_CLIENT_ID");const n=crypto.randomUUID();try{sessionStorage.setItem("een_oauth_state",n)}catch{}const t=new URLSearchParams({client_id:e,response_type:"code",scope:"vms.all",redirect_uri:b(),state:n});return c("Generated auth URL with state:",n),`${fe}?${t.toString()}`}async function w(e){const n=m();if(!n)return i("AUTH_FAILED","Proxy URL not configured. Call initEenToolkit() or set VITE_PROXY_URL");const t=new URLSearchParams({code:e,redirect_uri:b()});try{const r=await fetch(`${n}/proxy/getAccessToken?${t.toString()}`,{method:"POST",credentials:"include",headers:{Accept:"application/json"}});if(!r.ok){const o=await r.text().catch(()=>"Unknown error");return i("AUTH_FAILED",`Token exchange failed: ${o}`,r.status)}const a=await r.json();return c("Token received, expires in:",a.expiresIn),f(a)}catch(r){return i("NETWORK_ERROR",`Failed to exchange code: ${String(r)}`)}}async function q(){const e=m();if(!e)return i("AUTH_FAILED","Proxy URL not configured");const n=_();try{const t={Accept:"application/json"};n.sessionId&&(t.Authorization=`Bearer ${n.sessionId}`);const r=await fetch(`${e}/proxy/refreshAccessToken`,{method:"POST",credentials:"include",headers:t});if(!r.ok){const o=await r.text().catch(()=>"Unknown error");return i("AUTH_FAILED",`Token refresh failed: ${o}`,r.status)}const a=await r.json();return n.setToken(a.accessToken,a.expiresIn),c("Token refreshed, expires in:",a.expiresIn),f(a)}catch(t){return i("NETWORK_ERROR",`Failed to refresh token: ${String(t)}`)}}async function x(){const e=m();if(!e)return i("AUTH_FAILED","Proxy URL not configured");const n=_();try{const t={Accept:"application/json"};n.sessionId&&(t.Authorization=`Bearer ${n.sessionId}`);const r=await fetch(`${e}/proxy/revoke`,{method:"POST",credentials:"include",headers:t});if(n.logout(),!r.ok){const a=await r.text().catch(()=>"Unknown error");return i("AUTH_FAILED",`Token revocation failed: ${a}`,r.status)}return c("Token revoked"),f(void 0)}catch(t){return n.logout(),i("NETWORK_ERROR",`Failed to revoke token: ${String(t)}`)}}async function B(e,n){let t=null;try{t=sessionStorage.getItem("een_oauth_state"),sessionStorage.removeItem("een_oauth_state")}catch{}if(!t)return i("AUTH_FAILED","No OAuth state found. Please restart the login process.");if(!_e(n,t))return i("AUTH_FAILED","Invalid OAuth state. Possible CSRF attack.");c("State validated, exchanging code for token");const r=await w(e);if(r.error)return r;const a=_(),o=r.data;return a.setToken(o.accessToken,o.expiresIn),a.setRefreshTokenMarker("present"),a.setSessionId(o.sessionId),a.setBaseUrl(o.httpsBaseUrl),c("Auth callback complete, user:",o.userEmail),f(o)}function _e(e,n){if(e.length!==n.length)return!1;let t=0;for(let r=0;r<e.length;r++)t|=e.charCodeAt(r)^n.charCodeAt(r);return t===0}const ge=Object.freeze(Object.defineProperty({__proto__:null,getAccessToken:w,getAuthUrl:P,handleAuthCallback:B,refreshToken:q,revokeToken:x},Symbol.toStringTag,{value:"Module"}));async function he(){const e=_();if(!e.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!e.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const n=`${e.baseUrl}/api/v3.0/users/self`;c("Fetching current user:",n);try{const t=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e.token}`}});if(!t.ok)return L(t);const r=await t.json();return c("Current user fetched:",r.email),e.setUserProfile(r),f(r)}catch(t){return i("NETWORK_ERROR",`Failed to fetch current user: ${String(t)}`)}}async function Re(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;e?.pageSize&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.include&&e.include.length>0&&t.append("include",e.include.join(","));const r=t.toString(),a=`${n.baseUrl}/api/v3.0/users${r?`?${r}`:""}`;c("Fetching users:",a);try{const o=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!o.ok)return L(o);const s=await o.json();return c("Users fetched:",s.results?.length??0,"users"),f(s)}catch(o){return i("NETWORK_ERROR",`Failed to fetch users: ${String(o)}`)}}async function Ie(e,n){const t=_();if(!t.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e)return i("VALIDATION_ERROR","User ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const a=r.toString(),o=`${t.baseUrl}/api/v3.0/users/${encodeURIComponent(e)}${a?`?${a}`:""}`;c("Fetching user:",o);try{const s=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!s.ok)return L(s);const u=await s.json();return c("User fetched:",u.email),f(u)}catch(s){return i("NETWORK_ERROR",`Failed to fetch user: ${String(s)}`)}}async function L(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch{t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}async function Ee(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;e?.pageSize&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.include&&e.include.length>0&&t.append("include",e.include.join(",")),e?.sort&&e.sort.length>0&&t.append("sort",e.sort.join(",")),e?.locationId__in&&e.locationId__in.length>0&&t.append("locationId__in",e.locationId__in.join(",")),e?.bridgeId__in&&e.bridgeId__in.length>0&&t.append("bridgeId__in",e.bridgeId__in.join(",")),e?.multiCameraId&&t.append("multiCameraId",e.multiCameraId),e?.multiCameraId__ne&&t.append("multiCameraId__ne",e.multiCameraId__ne),e?.multiCameraId__in&&e.multiCameraId__in.length>0&&t.append("multiCameraId__in",e.multiCameraId__in.join(",")),e?.tags__contains&&e.tags__contains.length>0&&t.append("tags__contains",e.tags__contains.join(",")),e?.tags__any&&e.tags__any.length>0&&t.append("tags__any",e.tags__any.join(",")),e?.packages__contains&&e.packages__contains.length>0&&t.append("packages__contains",e.packages__contains.join(",")),e?.name&&t.append("name",e.name),e?.name__contains&&t.append("name__contains",e.name__contains),e?.name__in&&e.name__in.length>0&&t.append("name__in",e.name__in.join(",")),e?.id__in&&e.id__in.length>0&&t.append("id__in",e.id__in.join(",")),e?.id__notIn&&e.id__notIn.length>0&&t.append("id__notIn",e.id__notIn.join(",")),e?.id__contains&&t.append("id__contains",e.id__contains),e?.layoutId&&t.append("layoutId",e.layoutId),typeof e?.shared=="boolean"&&t.append("shareDetails.shared",String(e.shared)),e?.sharedCameraAccount&&t.append("shareDetails.accountId",e.sharedCameraAccount),typeof e?.firstResponder=="boolean"&&t.append("shareDetails.firstResponder",String(e.firstResponder)),typeof e?.directToCloud=="boolean"&&t.append("deviceInfo.directToCloud",String(e.directToCloud)),e?.speakerId__in&&e.speakerId__in.length>0&&t.append("speakerId__in",e.speakerId__in.join(",")),e?.q&&t.append("q",e.q),typeof e?.qRelevance__gte=="number"&&t.append("qRelevance__gte",String(e.qRelevance__gte)),e?.enabledAnalytics__contains&&e.enabledAnalytics__contains.length>0&&t.append("enabledAnalytics__contains",e.enabledAnalytics__contains.join(",")),e?.status__in&&e.status__in.length>0&&t.append("status__in",e.status__in.join(",")),e?.status__ne&&t.append("status__ne",e.status__ne);const r=t.toString(),a=`${n.baseUrl}/api/v3.0/cameras${r?`?${r}`:""}`;c("Fetching cameras:",a);try{const o=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!o.ok)return C(o);const s=await o.json();return c("Cameras fetched:",s.results?.length??0,"cameras"),f(s)}catch(o){return i("NETWORK_ERROR",`Failed to fetch cameras: ${String(o)}`)}}async function pe(e,n){const t=_();if(!t.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e)return i("VALIDATION_ERROR","Camera ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const a=r.toString(),o=`${t.baseUrl}/api/v3.0/cameras/${encodeURIComponent(e)}${a?`?${a}`:""}`;c("Fetching camera:",o);try{const s=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!s.ok)return C(s);const u=await s.json();return c("Camera fetched:",u.name),f(u)}catch(s){return i("NETWORK_ERROR",`Failed to fetch camera: ${String(s)}`)}}async function C(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch(r){c("Failed to parse error response JSON:",r),t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}async function Te(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;e?.pageSize&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.include&&e.include.length>0&&t.append("include",e.include.join(",")),e?.sort&&e.sort.length>0&&t.append("sort",e.sort.join(",")),e?.locationId__in&&e.locationId__in.length>0&&t.append("locationId__in",e.locationId__in.join(",")),e?.tags__contains&&e.tags__contains.length>0&&t.append("tags__contains",e.tags__contains.join(",")),e?.tags__any&&e.tags__any.length>0&&t.append("tags__any",e.tags__any.join(",")),e?.name&&t.append("name",e.name),e?.name__contains&&t.append("name__contains",e.name__contains),e?.name__in&&e.name__in.length>0&&t.append("name__in",e.name__in.join(",")),e?.id__in&&e.id__in.length>0&&t.append("id__in",e.id__in.join(",")),e?.id__notIn&&e.id__notIn.length>0&&t.append("id__notIn",e.id__notIn.join(",")),e?.q&&t.append("q",e.q),typeof e?.qRelevance__gte=="number"&&t.append("qRelevance__gte",String(e.qRelevance__gte)),e?.status__in&&e.status__in.length>0&&t.append("status__in",e.status__in.join(",")),e?.status__ne&&t.append("status__ne",e.status__ne);const r=t.toString(),a=`${n.baseUrl}/api/v3.0/bridges${r?`?${r}`:""}`;c("Fetching bridges:",a);try{const o=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!o.ok)return H(o);const s=await o.json();return c("Bridges fetched:",s.results?.length??0,"bridges"),f(s)}catch(o){return i("NETWORK_ERROR",`Failed to fetch bridges: ${String(o)}`)}}async function Ae(e,n){const t=_();if(!t.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e)return i("VALIDATION_ERROR","Bridge ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const a=r.toString(),o=`${t.baseUrl}/api/v3.0/bridges/${encodeURIComponent(e)}${a?`?${a}`:""}`;c("Fetching bridge:",o);try{const s=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!s.ok)return H(s);const u=await s.json();return c("Bridge fetched:",u.name),f(u)}catch(s){return i("NETWORK_ERROR",`Failed to fetch bridge: ${String(s)}`)}}async function H(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch(r){c("Failed to parse error response JSON:",r),t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}const Ue=3e4;function v(e=Ue){const n=new AbortController,t=setTimeout(()=>n.abort(),e);return{controller:n,timeoutId:t}}function z(e){const n=new Uint8Array(e),t=8192,r=[];for(let o=0;o<n.byteLength;o+=t){const s=n.subarray(o,Math.min(o+t,n.byteLength));let u="";for(let g=0;g<s.length;g++)u+=String.fromCharCode(s[g]);r.push(u)}const a=r.join("");return typeof btoa=="function"?btoa(a):Buffer.from(a,"binary").toString("base64")}async function ve(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e.deviceId)return i("VALIDATION_ERROR","Device ID is required");if(!e.type)return i("VALIDATION_ERROR","Stream type is required (preview or main)");if(!e.mediaType)return i("VALIDATION_ERROR","Media type is required (video or image)");if(!e.startTimestamp)return i("VALIDATION_ERROR","Start timestamp is required");const t=new URLSearchParams;t.append("deviceId",e.deviceId),t.append("type",e.type),t.append("mediaType",e.mediaType),t.append("startTimestamp__gte",e.startTimestamp),e.endTimestamp&&t.append("endTimestamp__lte",e.endTimestamp),typeof e.coalesce=="boolean"&&t.append("coalesce",String(e.coalesce)),e.include&&e.include.length>0&&t.append("include",e.include.join(",")),e.pageToken&&t.append("pageToken",e.pageToken),typeof e.pageSize=="number"&&t.append("pageSize",String(e.pageSize));const r=`${n.baseUrl}/api/v3.0/media?${t.toString()}`;c("Fetching media intervals:",r);const{controller:a,timeoutId:o}=v();try{const s=await fetch(r,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`},signal:a.signal});if(!s.ok)return k(s);const u=await s.json();return c("Media intervals fetched:",u.results?.length??0,"intervals"),f(u)}catch(s){return s instanceof Error&&s.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch media intervals: ${String(s)}`)}finally{clearTimeout(o)}}async function Se(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e.deviceId)return i("VALIDATION_ERROR","Device ID is required");const t=e.type??"preview",r=new URLSearchParams;r.append("deviceId",e.deviceId),r.append("type",t);const a=`${n.baseUrl}/api/v3.0/media/liveImage.jpeg?${r.toString()}`;c("Fetching live image:",a);const{controller:o,timeoutId:s}=v();try{const u=await fetch(a,{method:"GET",headers:{Accept:"image/jpeg",Authorization:`Bearer ${n.token}`},signal:o.signal}),g=u.headers.get("X-Een-Timestamp"),I=u.headers.get("X-Een-PrevToken");if(!u.ok)return k(u);const R=await u.arrayBuffer(),S=`data:image/jpeg;base64,${z(R)}`;return c("Live image fetched, timestamp:",g),f({imageData:S,timestamp:g,prevToken:I})}catch(u){return u instanceof Error&&u.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch live image: ${String(u)}`)}finally{clearTimeout(s)}}async function ye(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");if(!e.deviceId&&!e.pageToken)return i("VALIDATION_ERROR","Either deviceId or pageToken is required");if(!e.pageToken&&!(e.timestamp__lt||e.timestamp__lte||e.timestamp||e.timestamp__gte||e.timestamp__gt))return i("VALIDATION_ERROR","At least one timestamp parameter is required");if(e.include?.includes("overlaySvgHeader")&&(!e.overlayId__in||e.overlayId__in.length===0))return i("VALIDATION_ERROR","At least one overlayId must be provided when requesting overlay headers");const t=new URLSearchParams;e.deviceId&&t.append("deviceId",e.deviceId),e.pageToken&&t.append("pageToken",e.pageToken),e.type&&t.append("type",e.type),e.timestamp__lt&&t.append("timestamp__lt",e.timestamp__lt),e.timestamp__lte&&t.append("timestamp__lte",e.timestamp__lte),e.timestamp&&t.append("timestamp",e.timestamp),e.timestamp__gte&&t.append("timestamp__gte",e.timestamp__gte),e.timestamp__gt&&t.append("timestamp__gt",e.timestamp__gt),e.overlayId__in&&e.overlayId__in.length>0&&t.append("overlayId__in",e.overlayId__in.join(",")),e.include&&e.include.length>0&&t.append("include",e.include.join(",")),typeof e.targetWidth=="number"&&t.append("targetWidth",String(e.targetWidth)),typeof e.targetHeight=="number"&&t.append("targetHeight",String(e.targetHeight));const r=`${n.baseUrl}/api/v3.0/media/recordedImage.jpeg?${t.toString()}`;c("Fetching recorded image:",r);const{controller:a,timeoutId:o}=v();try{const s=await fetch(r,{method:"GET",headers:{Accept:"image/jpeg",Authorization:`Bearer ${n.token}`},signal:a.signal}),u=s.headers.get("X-Een-Timestamp"),g=s.headers.get("X-Een-NextToken"),I=s.headers.get("X-Een-PrevToken"),R=s.headers.get("X-Een-OverlaySvg");if(!s.ok)return k(s);const E=await s.arrayBuffer(),y=`data:image/jpeg;base64,${z(E)}`;return c("Recorded image fetched, timestamp:",u),f({imageData:y,timestamp:u,nextToken:g,prevToken:I,overlaySvg:R})}catch(s){return s instanceof Error&&s.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch recorded image: ${String(s)}`)}finally{clearTimeout(o)}}async function k(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error??e.statusText}catch{t=e.statusText||"Unknown error"}switch(n){case 401:return i("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return i("FORBIDDEN",`Access denied: ${t}`,n);case 404:return i("NOT_FOUND",`Not found: ${t}`,n);case 429:return i("RATE_LIMITED",`Rate limited: ${t}`,n);case 503:return i("SERVICE_UNAVAILABLE",`Service unavailable: ${t}`,n);default:return i("API_ERROR",`API error: ${t}`,n)}}async function M(){const e=_();if(!e.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!e.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const n=`${e.baseUrl}/api/v3.0/media/session`;c("Fetching media session:",n);const{controller:t,timeoutId:r}=v();try{const a=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e.token}`},signal:t.signal});if(!a.ok)return k(a);const o=await a.json();return c("Media session URL received:",o.url),f(o)}catch(a){return a instanceof Error&&a.name==="AbortError"?i("NETWORK_ERROR","Request timed out"):i("NETWORK_ERROR",`Failed to fetch media session: ${String(a)}`)}finally{clearTimeout(r)}}async function me(){const e=_();if(!e.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");const n=await M();if(n.error)return i(n.error.code,`Failed to get media session: ${n.error.message}`,n.error.status);if(!n.data?.url)return i("API_ERROR","No session URL returned from media session endpoint");const t=n.data.url;c("Calling session URL to set cookie:",t);const{controller:r,timeoutId:a}=v();try{const o=await fetch(t,{method:"GET",credentials:"include",headers:{Accept:"*/*",Authorization:`Bearer ${e.token}`},signal:r.signal});if(!o.ok&&o.status!==204){const s=o.status;let u;try{const g=await o.json();u=g.message??g.error??o.statusText}catch{u=o.statusText||"Unknown error"}return i("API_ERROR",`Failed to set media session cookie: ${u}`,s)}return c("Media session cookie set successfully"),f({success:!0,sessionUrl:t})}catch(o){return o instanceof Error&&o.name==="AbortError"?i("NETWORK_ERROR","Request timed out while setting session cookie"):i("NETWORK_ERROR",`Failed to set media session cookie: ${String(o)}`)}finally{clearTimeout(a)}}async function ke(e){const n=_();if(!n.isAuthenticated)return i("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return i("AUTH_REQUIRED","Base URL not configured");const t=new URLSearchParams;typeof e?.pageSize=="number"&&t.append("pageSize",String(e.pageSize)),e?.pageToken&&t.append("pageToken",e.pageToken),e?.deviceId&&t.append("deviceId",e.deviceId),e?.deviceId__in&&e.deviceId__in.length>0&&t.append("deviceId__in",e.deviceId__in.join(",")),e?.type&&t.append("type",e.type),e?.include&&e.include.length>0&&t.append("include",e.include.join(","));const r=t.toString(),a=`${n.baseUrl}/api/v3.0/feeds${r?`?${r}`:""}`;c("Fetching feeds:",a);try{const o=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`},signal:e?.signal});if(!o.ok)return Oe(o);const s=await o.json();return c("Feeds fetched:",s.results?.length??0,"feeds"),f(s)}catch(o){return i("NETWORK_ERROR",`Failed to fetch feeds: ${String(o)}`)}}async function Oe(e){const n=e.status;let t;try{const r=await e.json();t=r.message??r.error}catch(r){c("Failed to parse error response JSON:",r)}switch(n){case 401:return i("AUTH_REQUIRED",t||"Authentication failed",n);case 403:return i("FORBIDDEN",t||"Access denied",n);case 404:return i("NOT_FOUND",t||"Not found",n);case 429:return i("RATE_LIMITED",t||"Rate limited",n);case 503:return i("SERVICE_UNAVAILABLE",t||"Service unavailable",n);default:return i("API_ERROR",t||e.statusText||"API error",n)}}exports.failure=i;exports.getAccessToken=w;exports.getAuthUrl=P;exports.getBridge=Ae;exports.getBridges=Te;exports.getCamera=pe;exports.getCameras=Ee;exports.getClientId=F;exports.getConfig=ce;exports.getCurrentUser=he;exports.getLiveImage=Se;exports.getMediaSession=M;exports.getProxyUrl=m;exports.getRecordedImage=ye;exports.getRedirectUri=b;exports.getUser=Ie;exports.getUsers=Re;exports.handleAuthCallback=B;exports.initEenToolkit=se;exports.initMediaSession=me;exports.listFeeds=ke;exports.listMedia=ve;exports.refreshToken=q;exports.revokeToken=x;exports.success=f;exports.useAuthStore=_;
2
2
  //# sourceMappingURL=index.cjs.map