een-api-toolkit 0.0.18 → 0.1.4

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 (55) hide show
  1. package/CHANGELOG.md +8 -5
  2. package/README.md +29 -41
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +339 -821
  6. package/dist/index.js +295 -340
  7. package/dist/index.js.map +1 -1
  8. package/docs/AI-CONTEXT.md +151 -237
  9. package/examples/vue-bridges/.env.example +13 -0
  10. package/examples/vue-bridges/e2e/app.spec.ts +73 -0
  11. package/examples/vue-bridges/e2e/auth.spec.ts +206 -0
  12. package/examples/{vue-basic → vue-bridges}/index.html +1 -1
  13. package/examples/vue-bridges/package-lock.json +1583 -0
  14. package/examples/vue-bridges/package.json +28 -0
  15. package/examples/vue-bridges/playwright.config.ts +46 -0
  16. package/examples/vue-bridges/src/App.vue +108 -0
  17. package/examples/vue-bridges/src/router/index.ts +68 -0
  18. package/examples/vue-bridges/src/views/BridgeDetail.vue +279 -0
  19. package/examples/vue-bridges/src/views/Bridges.vue +297 -0
  20. package/examples/vue-bridges/src/views/Callback.vue +76 -0
  21. package/examples/vue-bridges/src/views/Home.vue +150 -0
  22. package/examples/vue-bridges/src/views/Login.vue +33 -0
  23. package/examples/vue-bridges/src/views/Logout.vue +66 -0
  24. package/examples/vue-bridges/src/vite-env.d.ts +12 -0
  25. package/examples/vue-cameras/e2e/app.spec.ts +2 -2
  26. package/examples/vue-cameras/e2e/auth.spec.ts +206 -0
  27. package/examples/vue-cameras/src/App.vue +4 -4
  28. package/examples/vue-cameras/src/views/CameraDetail.vue +57 -9
  29. package/examples/vue-cameras/src/views/Cameras.vue +69 -18
  30. package/examples/vue-cameras/src/views/Home.vue +36 -11
  31. package/examples/{vue-basic → vue-users}/README.md +4 -4
  32. package/examples/{vue-basic → vue-users}/e2e/app.spec.ts +3 -3
  33. package/examples/{vue-basic → vue-users}/e2e/auth.spec.ts +2 -2
  34. package/examples/vue-users/index.html +13 -0
  35. package/examples/{vue-basic → vue-users}/package-lock.json +3 -3
  36. package/examples/{vue-basic → vue-users}/package.json +1 -1
  37. package/examples/{vue-basic → vue-users}/src/App.vue +1 -1
  38. package/examples/vue-users/src/main.ts +23 -0
  39. package/examples/{vue-basic → vue-users}/src/views/Home.vue +27 -12
  40. package/examples/{vue-basic → vue-users}/src/views/Users.vue +51 -10
  41. package/examples/vue-users/tsconfig.json +21 -0
  42. package/examples/vue-users/tsconfig.node.json +10 -0
  43. package/examples/vue-users/vite.config.ts +12 -0
  44. package/package.json +1 -1
  45. /package/examples/{vue-basic → vue-bridges}/src/main.ts +0 -0
  46. /package/examples/{vue-basic → vue-bridges}/tsconfig.json +0 -0
  47. /package/examples/{vue-basic → vue-bridges}/tsconfig.node.json +0 -0
  48. /package/examples/{vue-basic → vue-bridges}/vite.config.ts +0 -0
  49. /package/examples/{vue-basic → vue-users}/.env.example +0 -0
  50. /package/examples/{vue-basic → vue-users}/playwright.config.ts +0 -0
  51. /package/examples/{vue-basic → vue-users}/src/router/index.ts +0 -0
  52. /package/examples/{vue-basic → vue-users}/src/views/Callback.vue +0 -0
  53. /package/examples/{vue-basic → vue-users}/src/views/Login.vue +0 -0
  54. /package/examples/{vue-basic → vue-users}/src/views/Logout.vue +0 -0
  55. /package/examples/{vue-basic → vue-users}/src/vite-env.d.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.0.18] - 2025-12-30
5
+ ## [0.1.4] - 2025-12-31
6
6
 
7
7
  ### Release Summary
8
8
 
@@ -10,12 +10,15 @@ No PR descriptions available for this release.
10
10
 
11
11
  ### Detailed Changes
12
12
 
13
- #### Other Changes
14
- - docs: Improve AI-CONTEXT.md with critical setup info at top
13
+ #### Features
14
+ - feat: Add bridges API with getBridges and getBridge functions
15
+
16
+ #### Bug Fixes
17
+ - fix: Address code review feedback for bridges API
15
18
 
16
19
  ### Links
17
20
  - [npm package](https://www.npmjs.com/package/een-api-toolkit)
18
- - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.17...v0.0.18)
21
+ - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.1.2...v0.1.4)
19
22
 
20
23
  ---
21
- *Released: 2025-12-30 10:05:39 CST*
24
+ *Released: 2025-12-31 11:11:58 CST*
package/README.md CHANGED
@@ -4,7 +4,7 @@ A TypeScript library for the [Eagle Eye Networks](https://een.com/) Video API v3
4
4
 
5
5
  ## Purpose
6
6
 
7
- This toolkit aims to **simplify and accelerate web application development** for the EEN Video Platform. By providing ready-to-use composables, type-safe APIs, and secure authentication patterns, developers can focus on building features rather than wrestling with API integration details.
7
+ This toolkit aims to **simplify and accelerate web application development** for the EEN Video Platform. By providing type-safe APIs and secure authentication patterns, developers can focus on building features rather than wrestling with API integration details.
8
8
 
9
9
  The project is also designed to **enable AI-assisted software development**. With comprehensive documentation, clear code patterns, and an AI-optimized context file (`docs/AI-CONTEXT.md`), AI coding assistants can effectively help developers build, extend, and maintain applications using this toolkit.
10
10
 
@@ -12,11 +12,11 @@ The project is also designed to **enable AI-assisted software development**. Wit
12
12
 
13
13
  ## Key Features
14
14
 
15
- - **Vue 3 Composables** - Reactive state with `useCurrentUser()`, `useUsers()`, `useUser()`
16
- - **Plain Functions** - Framework-agnostic `getCurrentUser()`, `getUsers()`, `getUser()`
15
+ - **Plain Async Functions** - Simple API calls with `getCurrentUser()`, `getUsers()`, `getUser()`, `getCameras()`, `getCamera()`
17
16
  - **Secure OAuth** - Token management via proxy (refresh tokens never exposed to client)
18
17
  - **Type-Safe** - Full TypeScript types from OpenAPI spec
19
18
  - **Predictable Errors** - Always returns `{data, error}`, no exceptions thrown
19
+ - **Pinia Auth Store** - Reactive authentication state management
20
20
 
21
21
  ## OAuth Proxy Requirement
22
22
 
@@ -94,33 +94,8 @@ const onCallback = async (code: string, state: string) => {
94
94
 
95
95
  ### 5. Use the API
96
96
 
97
- **Vue Composables (reactive):**
98
-
99
- ```vue
100
- <script setup>
101
- import { useCurrentUser, useUsers } from 'een-api-toolkit'
102
-
103
- const { user, loading, error } = useCurrentUser()
104
- const { users, hasNextPage, fetchNextPage } = useUsers({ pageSize: 10 })
105
- </script>
106
-
107
- <template>
108
- <div v-if="loading">Loading...</div>
109
- <div v-else-if="error">{{ error.message }}</div>
110
- <div v-else>
111
- <h1>Welcome, {{ user.firstName }}</h1>
112
- <ul>
113
- <li v-for="u in users" :key="u.id">{{ u.email }}</li>
114
- </ul>
115
- <button v-if="hasNextPage" @click="fetchNextPage">Load More</button>
116
- </div>
117
- </template>
118
- ```
119
-
120
- **Plain Functions (framework-agnostic):**
121
-
122
97
  ```typescript
123
- import { getUsers, getCurrentUser } from 'een-api-toolkit'
98
+ import { getUsers, getCurrentUser, getCameras } from 'een-api-toolkit'
124
99
 
125
100
  // Get current authenticated user
126
101
  const { data: currentUser, error: userError } = await getCurrentUser()
@@ -130,12 +105,25 @@ if (userError) {
130
105
  console.log('Current user:', currentUser.email)
131
106
  }
132
107
 
133
- // Get list of users
134
- const { data: users, error } = await getUsers()
108
+ // Get list of users with pagination
109
+ const { data: usersData, error } = await getUsers({ pageSize: 10 })
135
110
  if (error) {
136
111
  console.error(error.code, error.message)
137
112
  } else {
138
- console.log('Users:', users.results)
113
+ console.log('Users:', usersData.results)
114
+ if (usersData.nextPageToken) {
115
+ // Fetch next page
116
+ const { data: nextPage } = await getUsers({ pageToken: usersData.nextPageToken })
117
+ }
118
+ }
119
+
120
+ // Get list of cameras
121
+ const { data: camerasData, error: cameraError } = await getCameras({
122
+ pageSize: 20,
123
+ include: ['deviceInfo', 'status']
124
+ })
125
+ if (!cameraError) {
126
+ console.log('Cameras:', camerasData.results)
139
127
  }
140
128
  ```
141
129
 
@@ -146,16 +134,16 @@ if (error) {
146
134
  │ Your Vue 3 App │
147
135
  │ ┌────────────────────────────────────────────────────────────────┐ │
148
136
  │ │ import from 'een-api-toolkit' │ │
149
- │ │ ┌──────────────┐ ┌────────────────────┐ │ │
150
- │ │ Composables │ │ Plain Functions │ │
151
- │ │ useUsers() │ │ getUsers() │ │
152
- │ │ useUser() │ │ getUser() │ │ │
153
- │ │ └──────────────┘ └────────────────────┘ │ │
137
+ │ │ ┌────────────────────────────────────┐ │ │
138
+ │ │ Plain Async Functions │ │
139
+ │ │ getUsers(), getCameras() │ │
140
+ │ │ getUser(), getCamera() │ │ │
141
+ │ │ └────────────────────────────────────┘ │ │
154
142
  │ └────────────────────────────────────────────────────────────────┘ │
155
-
156
-
143
+
144
+
157
145
  │ ┌─────────────────────┐ ┌─────────────────────┐ │
158
- │ │ Pinia Auth Store │ │ API Calls with │ │
146
+ │ │ Pinia Auth Store │◄──────►│ API Calls with │ │
159
147
  │ │ (token, baseUrl) │ │ Bearer Token │ │
160
148
  │ └─────────────────────┘ └─────────────────────┘ │
161
149
  └────────────────────│─────────────────────────────│───────────────────┘
@@ -181,7 +169,7 @@ if (error) {
181
169
  | **[User Guide](./docs/USER-GUIDE.md)** | Installation, proxy setup, configuration, building apps |
182
170
  | **[Developer Guide](./docs/DEVELOPER-GUIDE.md)** | Architecture, testing, CI/CD, contributing |
183
171
  | **[API Reference](./docs/api/)** | Auto-generated TypeDoc documentation |
184
- | **[Example App](./examples/vue-basic/)** | Complete Vue 3 example with OAuth flow |
172
+ | **[Example App](./examples/vue-users/)** | Complete Vue 3 example with OAuth flow |
185
173
  | **[AI Context](./docs/AI-CONTEXT.md)** | Single-file reference for AI assistants (also in npm package) |
186
174
  | **[AI Prompts](./docs/Prompts.md)** | Example prompts for generating apps with AI |
187
175
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ie=require("pinia"),s=require("vue"),E={};let D={};function se(e={}){D={proxyUrl:e.proxyUrl??E?.VITE_PROXY_URL,clientId:e.clientId??E?.VITE_EEN_CLIENT_ID,redirectUri:e.redirectUri??E?.VITE_REDIRECT_URI,debug:e.debug??E?.VITE_DEBUG==="true"}}function ue(){return D}function x(){return D.proxyUrl??E?.VITE_PROXY_URL}function b(){return D.clientId??E?.VITE_EEN_CLIENT_ID}function C(){return D.redirectUri??E?.VITE_REDIRECT_URI??"http://127.0.0.1:3333"}function p(e){return{data:e,error:null}}function u(e,n,t,r){return{data:null,error:{code:e,message:n,status:t,details:r}}}const le={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},ce=()=>{try{return le?.VITE_DEBUG==="true"}catch{return!1}};function c(...e){ce()&&console.log("[een-api-toolkit]",...e)}let w=null;function fe(){return w||(w=Promise.resolve().then(()=>ge).then(e=>e.refreshToken)),w}const R=ie.defineStore("een-auth",()=>{const e=s.ref(null),n=s.ref(null),t=s.ref(null),r=s.ref(null),o=s.ref(null),a=s.ref(443),i=s.ref(null),d=s.ref(null),I=s.ref(!1);let h=null;const _=s.ref(!1),f=s.ref(null),S=s.computed(()=>!!e.value),k=s.computed(()=>o.value?a.value===443?`https://${o.value}`:`https://${o.value}:${a.value}`:null),U=s.computed(()=>n.value?Date.now()>=n.value:!0),m=s.computed(()=>n.value?Math.max(0,n.value-Date.now()):0);function T(l,g){e.value=l,n.value=Date.now()+g*1e3,y(),$(),c("Token set, expires in",g,"seconds")}function A(l){t.value=l,y()}function v(l){r.value=l,y()}function K(l){if(typeof l=="string")try{const g=new URL(l.startsWith("http")?l:`https://${l}`);o.value=g.hostname,a.value=g.port?parseInt(g.port,10):443}catch(g){c("Failed to parse URL, using as hostname:",g instanceof Error?g.message:String(g)),o.value=l,a.value=443}else o.value=l.hostname,a.value=l.port??443;y(),c("Base URL set:",k.value)}function J(l){i.value=l,y()}function $(){if(d.value&&(clearTimeout(d.value),d.value=null),!n.value||!e.value)return;const l=Date.now(),P=n.value-l,ne=300*1e3,re=P/2,oe=Math.min(ne,re),ae=Math.max(P-oe,60*1e3),F=Math.max(ae,5e3);c("Auto-refresh scheduled in",Math.round(F/1e3),"seconds"),d.value=setTimeout(async()=>{await X()},F)}async function X(){return h?(c("Refresh already in progress, waiting for existing refresh"),h):(I.value=!0,c("Performing auto-refresh"),h=(async()=>{try{const g=await(await fe())();g.error?(_.value=!0,f.value=g.error.message,c("Auto-refresh failed:",g.error.message)):(_.value=!1,f.value=null,c("Auto-refresh successful"))}catch(l){_.value=!0,f.value=l instanceof Error?l.message:String(l),c("Auto-refresh error:",l)}finally{I.value=!1,h=null}})(),h)}function Y(){_.value=!1,f.value=null}function j(){d.value&&(clearTimeout(d.value),d.value=null),e.value=null,n.value=null,t.value=null,r.value=null,o.value=null,a.value=443,i.value=null,_.value=!1,f.value=null,te(),c("Logged out")}function Z(){ee(),e.value&&!U.value?($(),c("Initialized from storage")):e.value&&U.value&&(c("Stored token expired, clearing"),j())}function y(){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),o.value&&localStorage.setItem("een_hostname",o.value),a.value!==443&&localStorage.setItem("een_port",String(a.value)),i.value&&localStorage.setItem("een_userProfile",JSON.stringify(i.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"),o.value=localStorage.getItem("een_hostname");const g=localStorage.getItem("een_port");a.value=g?parseInt(g,10):443;const P=localStorage.getItem("een_userProfile");i.value=P?JSON.parse(P):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:o,port:a,userProfile:i,isRefreshing:I,refreshFailed:_,refreshFailedMessage:f,isAuthenticated:S,baseUrl:k,isTokenExpired:U,tokenExpiresIn:m,setToken:T,setRefreshTokenMarker:A,setSessionId:v,setBaseUrl:K,setUserProfile:J,setupAutoRefresh:$,clearRefreshFailed:Y,logout:j,initialize:Z}}),de="https://auth.eagleeyenetworks.com/oauth2/authorize";function N(){const e=b();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:C(),state:n});return c("Generated auth URL with state:",n),`${de}?${t.toString()}`}async function O(e){const n=x();if(!n)return u("AUTH_FAILED","Proxy URL not configured. Call initEenToolkit() or set VITE_PROXY_URL");const t=new URLSearchParams({code:e,redirect_uri:C()});try{const r=await fetch(`${n}/proxy/getAccessToken?${t.toString()}`,{method:"POST",credentials:"include",headers:{Accept:"application/json"}});if(!r.ok){const a=await r.text().catch(()=>"Unknown error");return u("AUTH_FAILED",`Token exchange failed: ${a}`,r.status)}const o=await r.json();return c("Token received, expires in:",o.expiresIn),p(o)}catch(r){return u("NETWORK_ERROR",`Failed to exchange code: ${String(r)}`)}}async function q(){const e=x();if(!e)return u("AUTH_FAILED","Proxy URL not configured");const n=R();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 a=await r.text().catch(()=>"Unknown error");return u("AUTH_FAILED",`Token refresh failed: ${a}`,r.status)}const o=await r.json();return n.setToken(o.accessToken,o.expiresIn),c("Token refreshed, expires in:",o.expiresIn),p(o)}catch(t){return u("NETWORK_ERROR",`Failed to refresh token: ${String(t)}`)}}async function M(){const e=x();if(!e)return u("AUTH_FAILED","Proxy URL not configured");const n=R();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 o=await r.text().catch(()=>"Unknown error");return u("AUTH_FAILED",`Token revocation failed: ${o}`,r.status)}return c("Token revoked"),p(void 0)}catch(t){return n.logout(),u("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 u("AUTH_FAILED","No OAuth state found. Please restart the login process.");if(!_e(n,t))return u("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 o=R(),a=r.data;return o.setToken(a.accessToken,a.expiresIn),o.setRefreshTokenMarker("present"),o.setSessionId(a.sessionId),o.setBaseUrl(a.httpsBaseUrl),c("Auth callback complete, user:",a.userEmail),p(a)}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:O,getAuthUrl:N,handleAuthCallback:B,refreshToken:q,revokeToken:M},Symbol.toStringTag,{value:"Module"}));async function z(){const e=R();if(!e.isAuthenticated)return u("AUTH_REQUIRED","Authentication required");if(!e.baseUrl)return u("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),p(r)}catch(t){return u("NETWORK_ERROR",`Failed to fetch current user: ${String(t)}`)}}async function H(e){const n=R();if(!n.isAuthenticated)return u("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return u("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(),o=`${n.baseUrl}/api/v3.0/users${r?`?${r}`:""}`;c("Fetching users:",o);try{const a=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!a.ok)return L(a);const i=await a.json();return c("Users fetched:",i.results?.length??0,"users"),p(i)}catch(a){return u("NETWORK_ERROR",`Failed to fetch users: ${String(a)}`)}}async function V(e,n){const t=R();if(!t.isAuthenticated)return u("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return u("AUTH_REQUIRED","Base URL not configured");if(!e)return u("VALIDATION_ERROR","User ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const o=r.toString(),a=`${t.baseUrl}/api/v3.0/users/${encodeURIComponent(e)}${o?`?${o}`:""}`;c("Fetching user:",a);try{const i=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!i.ok)return L(i);const d=await i.json();return c("User fetched:",d.email),p(d)}catch(i){return u("NETWORK_ERROR",`Failed to fetch user: ${String(i)}`)}}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 u("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return u("FORBIDDEN",`Access denied: ${t}`,n);case 404:return u("NOT_FOUND",`Not found: ${t}`,n);case 429:return u("RATE_LIMITED",`Rate limited: ${t}`,n);default:return u("API_ERROR",`API error: ${t}`,n)}}function he(e){const n=s.ref(null),t=s.ref(!1),r=s.ref(null),o=async()=>{t.value=!0,r.value=null;const i=await z();return i.error?(r.value=i.error,n.value=null):n.value=i.data,t.value=!1,i},a=o;return e?.immediate!==!1&&s.onMounted(o),{user:n,loading:t,error:r,fetch:o,refresh:a}}function ve(e,n){const t=s.ref([]),r=s.ref(!1),o=s.ref(null),a=s.ref(void 0),i=s.ref(void 0),d=s.ref(void 0),I=s.computed(()=>!!a.value),h=s.computed(()=>!!i.value),_=s.ref(e??{}),f=async T=>{r.value=!0,o.value=null;const A={..._.value,...T},v=await H(A);return v.error?(o.value=v.error,t.value=[],a.value=void 0,i.value=void 0,d.value=void 0):(t.value=v.data.results,a.value=v.data.nextPageToken,i.value=v.data.prevPageToken,d.value=v.data.totalSize),r.value=!1,v},S=()=>f(),k=async()=>{if(a.value)return f({..._.value,pageToken:a.value})},U=async()=>{if(i.value)return f({..._.value,pageToken:i.value})},m=T=>{_.value=T};return n?.immediate!==!1&&s.onMounted(f),{users:t,loading:r,error:o,nextPageToken:a,prevPageToken:i,totalSize:d,hasNextPage:I,hasPrevPage:h,params:_,fetch:f,refresh:S,fetchNextPage:k,fetchPrevPage:U,setParams:m}}function Ie(e,n){const t=s.ref(null),r=s.ref(!1),o=s.ref(null),a=()=>typeof e=="function"?e():e,i=async I=>{const h=a();if(!h)return o.value={code:"VALIDATION_ERROR",message:"User ID is required"},{data:null,error:o.value};r.value=!0,o.value=null;const _={include:n?.include,...I},f=await V(h,_);return f.error?(o.value=f.error,t.value=null):t.value=f.data,r.value=!1,f},d=()=>i();return n?.immediate!==!1&&a()&&s.onMounted(i),{user:t,loading:r,error:o,fetch:i,refresh:d}}async function Q(e){const n=R();if(!n.isAuthenticated)return u("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return u("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(),o=`${n.baseUrl}/api/v3.0/cameras${r?`?${r}`:""}`;c("Fetching cameras:",o);try{const a=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!a.ok)return G(a);const i=await a.json();return c("Cameras fetched:",i.results?.length??0,"cameras"),p(i)}catch(a){return u("NETWORK_ERROR",`Failed to fetch cameras: ${String(a)}`)}}async function W(e,n){const t=R();if(!t.isAuthenticated)return u("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return u("AUTH_REQUIRED","Base URL not configured");if(!e)return u("VALIDATION_ERROR","Camera ID is required");const r=new URLSearchParams;n?.include&&n.include.length>0&&r.append("include",n.include.join(","));const o=r.toString(),a=`${t.baseUrl}/api/v3.0/cameras/${encodeURIComponent(e)}${o?`?${o}`:""}`;c("Fetching camera:",a);try{const i=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!i.ok)return G(i);const d=await i.json();return c("Camera fetched:",d.name),p(d)}catch(i){return u("NETWORK_ERROR",`Failed to fetch camera: ${String(i)}`)}}async function G(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 u("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return u("FORBIDDEN",`Access denied: ${t}`,n);case 404:return u("NOT_FOUND",`Not found: ${t}`,n);case 429:return u("RATE_LIMITED",`Rate limited: ${t}`,n);default:return u("API_ERROR",`API error: ${t}`,n)}}function pe(e,n){const t=s.ref([]),r=s.ref(!1),o=s.ref(null),a=s.ref(void 0),i=s.ref(void 0),d=s.ref(void 0),I=s.computed(()=>!!a.value),h=s.computed(()=>!!i.value),_=s.ref(e??{}),f=async T=>{r.value=!0,o.value=null;const A={..._.value,...T},v=await Q(A);return v.error?(o.value=v.error,t.value=[],a.value=void 0,i.value=void 0,d.value=void 0):(t.value=v.data.results,a.value=v.data.nextPageToken,i.value=v.data.prevPageToken,d.value=v.data.totalSize),r.value=!1,v},S=()=>f(),k=async()=>{if(a.value)return f({..._.value,pageToken:a.value})},U=async()=>{if(i.value)return f({..._.value,pageToken:i.value})},m=T=>{_.value=T};return n?.immediate!==!1&&s.onMounted(f),{cameras:t,loading:r,error:o,nextPageToken:a,prevPageToken:i,totalSize:d,hasNextPage:I,hasPrevPage:h,params:_,fetch:f,refresh:S,fetchNextPage:k,fetchPrevPage:U,setParams:m}}function Te(e,n){const t=s.ref(null),r=s.ref(!1),o=s.ref(null),a=()=>typeof e=="function"?e():e,i=async I=>{const h=a();if(!h)return o.value={code:"VALIDATION_ERROR",message:"Camera ID is required"},{data:null,error:o.value};r.value=!0,o.value=null;const _={include:n?.include,...I},f=await W(h,_);return f.error?(o.value=f.error,t.value=null):t.value=f.data,r.value=!1,f},d=()=>i();return n?.immediate!==!1&&a()&&s.onMounted(i),typeof e=="function"&&s.watch(e,(I,h)=>{I&&I!==h&&i()}),{camera:t,loading:r,error:o,fetch:i,refresh:d}}exports.failure=u;exports.getAccessToken=O;exports.getAuthUrl=N;exports.getCamera=W;exports.getCameras=Q;exports.getClientId=b;exports.getConfig=ue;exports.getCurrentUser=z;exports.getProxyUrl=x;exports.getRedirectUri=C;exports.getUser=V;exports.getUsers=H;exports.handleAuthCallback=B;exports.initEenToolkit=se;exports.refreshToken=q;exports.revokeToken=M;exports.success=p;exports.useAuthStore=R;exports.useCamera=Te;exports.useCameras=pe;exports.useCurrentUser=he;exports.useUser=Ie;exports.useUsers=ve;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ne=require("pinia"),_=require("vue"),h={};let p={};function re(e={}){p={proxyUrl:e.proxyUrl??h?.VITE_PROXY_URL,clientId:e.clientId??h?.VITE_EEN_CLIENT_ID,redirectUri:e.redirectUri??h?.VITE_REDIRECT_URI,debug:e.debug??h?.VITE_DEBUG==="true"}}function oe(){return p}function S(){return p.proxyUrl??h?.VITE_PROXY_URL}function x(){return p.clientId??h?.VITE_EEN_CLIENT_ID}function $(){return p.redirectUri??h?.VITE_REDIRECT_URI??"http://127.0.0.1:3333"}function f(e){return{data:e,error:null}}function o(e,n,t,r){return{data:null,error:{code:e,message:n,status:t,details:r}}}const ie={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},ae=()=>{try{return ie?.VITE_DEBUG==="true"}catch{return!1}};function c(...e){ae()&&console.log("[een-api-toolkit]",...e)}let y=null;function se(){return y||(y=Promise.resolve().then(()=>le).then(e=>e.refreshToken)),y}const g=ne.defineStore("een-auth",()=>{const e=_.ref(null),n=_.ref(null),t=_.ref(null),r=_.ref(null),a=_.ref(null),i=_.ref(443),u=_.ref(null),d=_.ref(null),v=_.ref(!1);let T=null;const R=_.ref(!1),I=_.ref(null),N=_.computed(()=>!!e.value),w=_.computed(()=>a.value?i.value===443?`https://${a.value}`:`https://${a.value}:${i.value}`:null),A=_.computed(()=>n.value?Date.now()>=n.value:!0),B=_.computed(()=>n.value?Math.max(0,n.value-Date.now()):0);function H(s,l){e.value=s,n.value=Date.now()+l*1e3,E(),k(),c("Token set, expires in",l,"seconds")}function z(s){t.value=s,E()}function M(s){r.value=s,E()}function Q(s){if(typeof s=="string")try{const l=new URL(s.startsWith("http")?s:`https://${s}`);a.value=l.hostname,i.value=l.port?parseInt(l.port,10):443}catch(l){c("Failed to parse URL, using as hostname:",l instanceof Error?l.message:String(l)),a.value=s,i.value=443}else a.value=s.hostname,i.value=s.port??443;E(),c("Base URL set:",w.value)}function V(s){u.value=s,E()}function k(){if(d.value&&(clearTimeout(d.value),d.value=null),!n.value||!e.value)return;const s=Date.now(),U=n.value-s,Y=300*1e3,Z=U/2,ee=Math.min(Y,Z),te=Math.max(U-ee,60*1e3),j=Math.max(te,5e3);c("Auto-refresh scheduled in",Math.round(j/1e3),"seconds"),d.value=setTimeout(async()=>{await W()},j)}async function W(){return T?(c("Refresh already in progress, waiting for existing refresh"),T):(v.value=!0,c("Performing auto-refresh"),T=(async()=>{try{const l=await(await se())();l.error?(R.value=!0,I.value=l.error.message,c("Auto-refresh failed:",l.error.message)):(R.value=!1,I.value=null,c("Auto-refresh successful"))}catch(s){R.value=!0,I.value=s instanceof Error?s.message:String(s),c("Auto-refresh error:",s)}finally{v.value=!1,T=null}})(),T)}function G(){R.value=!1,I.value=null}function O(){d.value&&(clearTimeout(d.value),d.value=null),e.value=null,n.value=null,t.value=null,r.value=null,a.value=null,i.value=443,u.value=null,R.value=!1,I.value=null,X(),c("Logged out")}function K(){J(),e.value&&!A.value?(k(),c("Initialized from storage")):e.value&&A.value&&(c("Stored token expired, clearing"),O())}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),a.value&&localStorage.setItem("een_hostname",a.value),i.value!==443&&localStorage.setItem("een_port",String(i.value)),u.value&&localStorage.setItem("een_userProfile",JSON.stringify(u.value))}catch(s){c("Failed to save to localStorage:",s instanceof Error?s.message:String(s))}}function J(){try{e.value=localStorage.getItem("een_token");const s=localStorage.getItem("een_tokenExpiration");n.value=s?parseInt(s,10):null,t.value=localStorage.getItem("een_refreshTokenMarker"),r.value=localStorage.getItem("een_sessionId"),a.value=localStorage.getItem("een_hostname");const l=localStorage.getItem("een_port");i.value=l?parseInt(l,10):443;const U=localStorage.getItem("een_userProfile");u.value=U?JSON.parse(U):null}catch(s){c("Failed to load from localStorage:",s instanceof Error?s.message:String(s))}}function X(){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(s){c("Failed to clear localStorage:",s instanceof Error?s.message:String(s))}}return{token:e,tokenExpiration:n,refreshTokenMarker:t,sessionId:r,hostname:a,port:i,userProfile:u,isRefreshing:v,refreshFailed:R,refreshFailedMessage:I,isAuthenticated:N,baseUrl:w,isTokenExpired:A,tokenExpiresIn:B,setToken:H,setRefreshTokenMarker:z,setSessionId:M,setBaseUrl:Q,setUserProfile:V,setupAutoRefresh:k,clearRefreshFailed:G,logout:O,initialize:K}}),ce="https://auth.eagleeyenetworks.com/oauth2/authorize";function b(){const e=x();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),`${ce}?${t.toString()}`}async function D(e){const n=S();if(!n)return o("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 i=await r.text().catch(()=>"Unknown error");return o("AUTH_FAILED",`Token exchange failed: ${i}`,r.status)}const a=await r.json();return c("Token received, expires in:",a.expiresIn),f(a)}catch(r){return o("NETWORK_ERROR",`Failed to exchange code: ${String(r)}`)}}async function P(){const e=S();if(!e)return o("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 i=await r.text().catch(()=>"Unknown error");return o("AUTH_FAILED",`Token refresh failed: ${i}`,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 o("NETWORK_ERROR",`Failed to refresh token: ${String(t)}`)}}async function C(){const e=S();if(!e)return o("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 a=await r.text().catch(()=>"Unknown error");return o("AUTH_FAILED",`Token revocation failed: ${a}`,r.status)}return c("Token revoked"),f(void 0)}catch(t){return n.logout(),o("NETWORK_ERROR",`Failed to revoke token: ${String(t)}`)}}async function L(e,n){let t=null;try{t=sessionStorage.getItem("een_oauth_state"),sessionStorage.removeItem("een_oauth_state")}catch{}if(!t)return o("AUTH_FAILED","No OAuth state found. Please restart the login process.");if(!ue(n,t))return o("AUTH_FAILED","Invalid OAuth state. Possible CSRF attack.");c("State validated, exchanging code for token");const r=await D(e);if(r.error)return r;const a=g(),i=r.data;return a.setToken(i.accessToken,i.expiresIn),a.setRefreshTokenMarker("present"),a.setSessionId(i.sessionId),a.setBaseUrl(i.httpsBaseUrl),c("Auth callback complete, user:",i.userEmail),f(i)}function ue(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 le=Object.freeze(Object.defineProperty({__proto__:null,getAccessToken:D,getAuthUrl:b,handleAuthCallback:L,refreshToken:P,revokeToken:C},Symbol.toStringTag,{value:"Module"}));async function de(){const e=g();if(!e.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!e.baseUrl)return o("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 m(t);const r=await t.json();return c("Current user fetched:",r.email),e.setUserProfile(r),f(r)}catch(t){return o("NETWORK_ERROR",`Failed to fetch current user: ${String(t)}`)}}async function _e(e){const n=g();if(!n.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return o("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 i=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!i.ok)return m(i);const u=await i.json();return c("Users fetched:",u.results?.length??0,"users"),f(u)}catch(i){return o("NETWORK_ERROR",`Failed to fetch users: ${String(i)}`)}}async function fe(e,n){const t=g();if(!t.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return o("AUTH_REQUIRED","Base URL not configured");if(!e)return o("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(),i=`${t.baseUrl}/api/v3.0/users/${encodeURIComponent(e)}${a?`?${a}`:""}`;c("Fetching user:",i);try{const u=await fetch(i,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!u.ok)return m(u);const d=await u.json();return c("User fetched:",d.email),f(d)}catch(u){return o("NETWORK_ERROR",`Failed to fetch user: ${String(u)}`)}}async function m(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 o("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return o("FORBIDDEN",`Access denied: ${t}`,n);case 404:return o("NOT_FOUND",`Not found: ${t}`,n);case 429:return o("RATE_LIMITED",`Rate limited: ${t}`,n);default:return o("API_ERROR",`API error: ${t}`,n)}}async function ge(e){const n=g();if(!n.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return o("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 i=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!i.ok)return F(i);const u=await i.json();return c("Cameras fetched:",u.results?.length??0,"cameras"),f(u)}catch(i){return o("NETWORK_ERROR",`Failed to fetch cameras: ${String(i)}`)}}async function he(e,n){const t=g();if(!t.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return o("AUTH_REQUIRED","Base URL not configured");if(!e)return o("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(),i=`${t.baseUrl}/api/v3.0/cameras/${encodeURIComponent(e)}${a?`?${a}`:""}`;c("Fetching camera:",i);try{const u=await fetch(i,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!u.ok)return F(u);const d=await u.json();return c("Camera fetched:",d.name),f(d)}catch(u){return o("NETWORK_ERROR",`Failed to fetch camera: ${String(u)}`)}}async function F(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 o("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return o("FORBIDDEN",`Access denied: ${t}`,n);case 404:return o("NOT_FOUND",`Not found: ${t}`,n);case 429:return o("RATE_LIMITED",`Rate limited: ${t}`,n);default:return o("API_ERROR",`API error: ${t}`,n)}}async function Re(e){const n=g();if(!n.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!n.baseUrl)return o("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 i=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${n.token}`}});if(!i.ok)return q(i);const u=await i.json();return c("Bridges fetched:",u.results?.length??0,"bridges"),f(u)}catch(i){return o("NETWORK_ERROR",`Failed to fetch bridges: ${String(i)}`)}}async function Ie(e,n){const t=g();if(!t.isAuthenticated)return o("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return o("AUTH_REQUIRED","Base URL not configured");if(!e)return o("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(),i=`${t.baseUrl}/api/v3.0/bridges/${encodeURIComponent(e)}${a?`?${a}`:""}`;c("Fetching bridge:",i);try{const u=await fetch(i,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!u.ok)return q(u);const d=await u.json();return c("Bridge fetched:",d.name),f(d)}catch(u){return o("NETWORK_ERROR",`Failed to fetch bridge: ${String(u)}`)}}async function q(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 o("AUTH_REQUIRED",`Authentication failed: ${t}`,n);case 403:return o("FORBIDDEN",`Access denied: ${t}`,n);case 404:return o("NOT_FOUND",`Not found: ${t}`,n);case 429:return o("RATE_LIMITED",`Rate limited: ${t}`,n);default:return o("API_ERROR",`API error: ${t}`,n)}}exports.failure=o;exports.getAccessToken=D;exports.getAuthUrl=b;exports.getBridge=Ie;exports.getBridges=Re;exports.getCamera=he;exports.getCameras=ge;exports.getClientId=x;exports.getConfig=oe;exports.getCurrentUser=de;exports.getProxyUrl=S;exports.getRedirectUri=$;exports.getUser=fe;exports.getUsers=_e;exports.handleAuthCallback=L;exports.initEenToolkit=re;exports.refreshToken=P;exports.revokeToken=C;exports.success=f;exports.useAuthStore=g;
2
2
  //# sourceMappingURL=index.cjs.map