een-api-toolkit 0.0.17 → 0.1.2

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 (35) hide show
  1. package/CHANGELOG.md +29 -94
  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 +23 -821
  6. package/dist/index.js +234 -357
  7. package/dist/index.js.map +1 -1
  8. package/docs/AI-CONTEXT.md +162 -313
  9. package/examples/vue-cameras/e2e/app.spec.ts +2 -2
  10. package/examples/vue-cameras/e2e/auth.spec.ts +206 -0
  11. package/examples/vue-cameras/src/App.vue +4 -4
  12. package/examples/vue-cameras/src/views/CameraDetail.vue +57 -9
  13. package/examples/vue-cameras/src/views/Cameras.vue +69 -18
  14. package/examples/vue-cameras/src/views/Home.vue +36 -11
  15. package/examples/{vue-basic → vue-users}/README.md +4 -4
  16. package/examples/{vue-basic → vue-users}/e2e/app.spec.ts +3 -3
  17. package/examples/{vue-basic → vue-users}/e2e/auth.spec.ts +2 -2
  18. package/examples/{vue-basic → vue-users}/index.html +1 -1
  19. package/examples/{vue-basic → vue-users}/package-lock.json +3 -3
  20. package/examples/{vue-basic → vue-users}/package.json +1 -1
  21. package/examples/{vue-basic → vue-users}/src/App.vue +1 -1
  22. package/examples/{vue-basic → vue-users}/src/views/Home.vue +27 -12
  23. package/examples/{vue-basic → vue-users}/src/views/Users.vue +51 -10
  24. package/package.json +1 -1
  25. /package/examples/{vue-basic → vue-users}/.env.example +0 -0
  26. /package/examples/{vue-basic → vue-users}/playwright.config.ts +0 -0
  27. /package/examples/{vue-basic → vue-users}/src/main.ts +0 -0
  28. /package/examples/{vue-basic → vue-users}/src/router/index.ts +0 -0
  29. /package/examples/{vue-basic → vue-users}/src/views/Callback.vue +0 -0
  30. /package/examples/{vue-basic → vue-users}/src/views/Login.vue +0 -0
  31. /package/examples/{vue-basic → vue-users}/src/views/Logout.vue +0 -0
  32. /package/examples/{vue-basic → vue-users}/src/vite-env.d.ts +0 -0
  33. /package/examples/{vue-basic → vue-users}/tsconfig.json +0 -0
  34. /package/examples/{vue-basic → vue-users}/tsconfig.node.json +0 -0
  35. /package/examples/{vue-basic → vue-users}/vite.config.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -2,97 +2,37 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.0.17] - 2025-12-29
5
+ ## [0.1.2] - 2025-12-30
6
6
 
7
7
  ### Release Summary
8
8
 
9
- #### PR #26: feat: Add Camera API support (v0.0.14)
9
+ #### PR #31: Release v0.0.18: Documentation improvements and PR validation
10
10
  ## Summary
11
11
 
12
- Add comprehensive Camera API support to een-api-toolkit following the same patterns as the Users API.
13
-
14
- ### New Features
15
- - **Camera Types**: `Camera`, `CameraStatus`, `CameraDeviceInfo`, `CameraShareDetails`, `CameraDevicePosition`, `CameraStreamUrls`, `CameraRtspConnectionSettings`, `CameraRecordingModes`
16
- - **Service Functions**: `getCameras()`, `getCamera()` with all 25+ filter parameters
17
- - **Vue 3 Composables**: `useCameras()`, `useCamera()` with pagination and filtering support
18
- - **Example App**: `examples/vue-cameras/` - Complete Vue 3 app demonstrating camera APIs
12
+ This release includes documentation improvements based on user feedback and a new CI workflow to validate PRs before merge.
19
13
 
20
14
  ### Changes
21
- - `04cb829` feat: Add Camera API support with getCameras, getCamera, useCameras, useCamera
22
- - `9765ed0` Merge pull request #25 from klaushofrichter/develop
23
- - `aa8b0e9` docs: Regenerate API documentation for v0.0.13
24
-
25
- ## Test Results
26
- - ✅ Lint: Pass (0 errors, 1 expected warning)
27
- - ✅ Unit tests: 33 passed (26 cameras + 7 types)
28
- - ✅ E2E tests: 14 passed
29
- - ✅ vue-cameras Playwright tests: 7 passed
30
- - ✅ Build: Success
31
-
32
- ## Version
33
- `0.0.14`
34
-
35
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
36
-
37
- #### PR #27: feat: Camera API support and AI Prompts guide (v0.0.16)
38
- ## Summary
39
-
40
- This PR adds comprehensive Camera API support and developer documentation improvements.
41
-
42
- ### New Features
43
15
 
44
- **Camera API Support:**
45
- - Camera types: `Camera`, `CameraStatus`, `CameraDeviceInfo`, `CameraShareDetails`, `CameraDevicePosition`, etc.
46
- - Service functions: `getCameras()`, `getCamera()` with 25+ filter parameters
47
- - Vue 3 composables: `useCameras()`, `useCamera()` with pagination and reactive ID watching
48
- - Example app: `examples/vue-cameras/` demonstrating camera APIs
16
+ **docs: Improve AI-CONTEXT.md with critical setup info at top**
17
+ - Added "Prerequisites & Installation (READ FIRST)" section
18
+ - Installation command now includes pinia: `npm install een-api-toolkit pinia`
19
+ - Complete main.ts example with numbered steps
20
+ - Common Errors section for Pinia and OAuth issues
49
21
 
50
- **Documentation:**
51
- - `docs/Prompts.md` - AI prompts guide for generating apps with AI assistants
52
- - Fixed AI-CONTEXT.md date issue causing CI failures
22
+ **docs: Address Gemini review feedback**
23
+ - OAuth Callback Route: Added sentence linking to beforeEnter guard
24
+ - Logout: Changed to full Vue component example with useRouter
53
25
 
54
- ### Commits
55
- - `43630ad` docs: Regenerate documentation for v0.0.16
56
- - `651d70b` docs: Add AI Prompts guide and fix CI date issue
57
- - `ed6817e` Merge pull request #26 (Camera API)
58
- - `f79ce5a` docs: Regenerate documentation for v0.0.15
59
- - `68ba14a` fix: Address code review feedback for Camera API
60
- - `04cb829` feat: Add Camera API support
61
- - `9765ed0` Merge pull request #25
62
- - `aa8b0e9` docs: Regenerate API documentation for v0.0.13
26
+ **ci: Add PR validation workflow**
27
+ - New `validate-pr.yml` workflow runs on PRs to production
28
+ - Validates version consistency across package.json, AI-CONTEXT.md, and docs/api
29
+ - Checks if version is already published to npm
30
+ - Runs quick validation tests (lint, typecheck, unit tests, build, docs)
63
31
 
64
- ## Test Results
65
- - ✅ Lint: Pass (0 errors)
66
- - ✅ Unit tests: 33 passed
67
- - ✅ Build: Success
32
+ ### New Commits (since last merge)
68
33
 
69
- ## Version
70
- `0.0.16`
71
-
72
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
73
-
74
- #### PR #28: Release v0.0.17: Documentation updates and CI fix
75
- ## Summary
76
-
77
- This release includes documentation improvements and a CI fix for version mismatch issues.
78
-
79
- ### Changes
80
-
81
- - **fix:** Regenerate AI-CONTEXT.md after version bump in pre-commit hook
82
- - Ensures version in AI-CONTEXT.md always matches package.json
83
- - Prevents CI failures due to version mismatch
84
-
85
- - **docs:** Update GitHub links to point to production branch
86
- - Changed typedoc.json gitRevision from develop to production
87
- - Updated AI-CONTEXT.md references in Prompts.md
88
- - Added note that AI-CONTEXT.md is included in npm package
89
- - Regenerated all API docs with production branch links
90
-
91
- ### Commits
92
-
93
- - `5379307` fix: Regenerate AI-CONTEXT.md after version bump in pre-commit hook
94
- - `68e98f3` docs: Update GitHub links to point to production branch
95
- - `651d70b` docs: Add AI Prompts guide and fix CI date issue
34
+ - `d62fadc` ci: Add PR validation workflow for version consistency
35
+ - `29ad8f6` docs: Address Gemini review feedback
96
36
 
97
37
  ### Test Results
98
38
 
@@ -102,7 +42,7 @@ This release includes documentation improvements and a CI fix for version mismat
102
42
 
103
43
  ### Version
104
44
 
105
- `0.0.17`
45
+ `0.0.18`
106
46
 
107
47
  ---
108
48
 
@@ -111,23 +51,18 @@ This release includes documentation improvements and a CI fix for version mismat
111
51
 
112
52
  ### Detailed Changes
113
53
 
114
- #### Features
115
- - feat: Add Camera API support with getCameras, getCamera, useCameras, useCamera
116
-
117
- #### Bug Fixes
118
- - fix: Regenerate ALL docs after version bump in pre-commit hook
119
- - fix: Regenerate AI-CONTEXT.md after version bump in pre-commit hook
120
- - fix: Address code review feedback for Camera API
121
-
122
54
  #### Other Changes
123
- - docs: Update GitHub links to point to production branch
124
- - docs: Regenerate documentation for v0.0.16
125
- - docs: Add AI Prompts guide and fix CI date issue
126
- - docs: Regenerate documentation for v0.0.15
55
+ - refactor: Rename vue-basic example to vue-users
56
+ - docs: Add v-else fallback to Vue template example
57
+ - test: Add service function unit tests, fix pagination, bump to 0.1.0
58
+ - refactor: Remove Vue 3 Composables, keep plain async functions only
59
+ - docs: Address code review feedback
60
+ - ci: Add PR validation workflow for version consistency
61
+ - docs: Address Gemini review feedback
127
62
 
128
63
  ### Links
129
64
  - [npm package](https://www.npmjs.com/package/een-api-toolkit)
130
- - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.13...v0.0.17)
65
+ - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.18...v0.1.2)
131
66
 
132
67
  ---
133
- *Released: 2025-12-29 19:59:36 CST*
68
+ *Released: 2025-12-30 19:11:38 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 te=require("pinia"),d=require("vue"),g={};let E={};function ne(e={}){E={proxyUrl:e.proxyUrl??g?.VITE_PROXY_URL,clientId:e.clientId??g?.VITE_EEN_CLIENT_ID,redirectUri:e.redirectUri??g?.VITE_REDIRECT_URI,debug:e.debug??g?.VITE_DEBUG==="true"}}function re(){return E}function U(){return E.proxyUrl??g?.VITE_PROXY_URL}function O(){return E.clientId??g?.VITE_EEN_CLIENT_ID}function m(){return E.redirectUri??g?.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 oe={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},ie=()=>{try{return oe?.VITE_DEBUG==="true"}catch{return!1}};function c(...e){ie()&&console.log("[een-api-toolkit]",...e)}let y=null;function ae(){return y||(y=Promise.resolve().then(()=>le).then(e=>e.refreshToken)),y}const h=te.defineStore("een-auth",()=>{const e=d.ref(null),n=d.ref(null),t=d.ref(null),r=d.ref(null),a=d.ref(null),o=d.ref(443),l=d.ref(null),f=d.ref(null),S=d.ref(!1);let T=null;const I=d.ref(!1),R=d.ref(null),N=d.computed(()=>!!e.value),w=d.computed(()=>a.value?o.value===443?`https://${a.value}`:`https://${a.value}:${o.value}`:null),A=d.computed(()=>n.value?Date.now()>=n.value:!0),q=d.computed(()=>n.value?Math.max(0,n.value-Date.now()):0);function B(s,u){e.value=s,n.value=Date.now()+u*1e3,p(),k(),c("Token set, expires in",u,"seconds")}function H(s){t.value=s,p()}function M(s){r.value=s,p()}function z(s){if(typeof s=="string")try{const u=new URL(s.startsWith("http")?s:`https://${s}`);a.value=u.hostname,o.value=u.port?parseInt(u.port,10):443}catch(u){c("Failed to parse URL, using as hostname:",u instanceof Error?u.message:String(u)),a.value=s,o.value=443}else a.value=s.hostname,o.value=s.port??443;p(),c("Base URL set:",w.value)}function V(s){l.value=s,p()}function k(){if(f.value&&(clearTimeout(f.value),f.value=null),!n.value||!e.value)return;const s=Date.now(),v=n.value-s,X=300*1e3,Y=v/2,Z=Math.min(X,Y),ee=Math.max(v-Z,60*1e3),C=Math.max(ee,5e3);c("Auto-refresh scheduled in",Math.round(C/1e3),"seconds"),f.value=setTimeout(async()=>{await Q()},C)}async function Q(){return T?(c("Refresh already in progress, waiting for existing refresh"),T):(S.value=!0,c("Performing auto-refresh"),T=(async()=>{try{const u=await(await ae())();u.error?(I.value=!0,R.value=u.error.message,c("Auto-refresh failed:",u.error.message)):(I.value=!1,R.value=null,c("Auto-refresh successful"))}catch(s){I.value=!0,R.value=s instanceof Error?s.message:String(s),c("Auto-refresh error:",s)}finally{S.value=!1,T=null}})(),T)}function W(){I.value=!1,R.value=null}function x(){f.value&&(clearTimeout(f.value),f.value=null),e.value=null,n.value=null,t.value=null,r.value=null,a.value=null,o.value=443,l.value=null,I.value=!1,R.value=null,J(),c("Logged out")}function G(){K(),e.value&&!A.value?(k(),c("Initialized from storage")):e.value&&A.value&&(c("Stored token expired, clearing"),x())}function p(){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)),l.value&&localStorage.setItem("een_userProfile",JSON.stringify(l.value))}catch(s){c("Failed to save to localStorage:",s instanceof Error?s.message:String(s))}}function K(){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 u=localStorage.getItem("een_port");o.value=u?parseInt(u,10):443;const v=localStorage.getItem("een_userProfile");l.value=v?JSON.parse(v):null}catch(s){c("Failed to load from localStorage:",s instanceof Error?s.message:String(s))}}function J(){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:o,userProfile:l,isRefreshing:S,refreshFailed:I,refreshFailedMessage:R,isAuthenticated:N,baseUrl:w,isTokenExpired:A,tokenExpiresIn:q,setToken:B,setRefreshTokenMarker:H,setSessionId:M,setBaseUrl:z,setUserProfile:V,setupAutoRefresh:k,clearRefreshFailed:W,logout:x,initialize:G}}),se="https://auth.eagleeyenetworks.com/oauth2/authorize";function P(){const e=O();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:m(),state:n});return c("Generated auth URL with state:",n),`${se}?${t.toString()}`}async function $(e){const n=U();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:m()});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),_(a)}catch(r){return i("NETWORK_ERROR",`Failed to exchange code: ${String(r)}`)}}async function L(){const e=U();if(!e)return i("AUTH_FAILED","Proxy URL not configured");const n=h();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),_(a)}catch(t){return i("NETWORK_ERROR",`Failed to refresh token: ${String(t)}`)}}async function j(){const e=U();if(!e)return i("AUTH_FAILED","Proxy URL not configured");const n=h();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"),_(void 0)}catch(t){return n.logout(),i("NETWORK_ERROR",`Failed to revoke token: ${String(t)}`)}}async function F(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(!ce(n,t))return i("AUTH_FAILED","Invalid OAuth state. Possible CSRF attack.");c("State validated, exchanging code for token");const r=await $(e);if(r.error)return r;const a=h(),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),_(o)}function ce(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:$,getAuthUrl:P,handleAuthCallback:F,refreshToken:L,revokeToken:j},Symbol.toStringTag,{value:"Module"}));async function ue(){const e=h();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 D(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 de(e){const n=h();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 D(o);const l=await o.json();return c("Users fetched:",l.results?.length??0,"users"),_(l)}catch(o){return i("NETWORK_ERROR",`Failed to fetch users: ${String(o)}`)}}async function fe(e,n){const t=h();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 l=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!l.ok)return D(l);const f=await l.json();return c("User fetched:",f.email),_(f)}catch(l){return i("NETWORK_ERROR",`Failed to fetch user: ${String(l)}`)}}async function D(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 _e(e){const n=h();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 b(o);const l=await o.json();return c("Cameras fetched:",l.results?.length??0,"cameras"),_(l)}catch(o){return i("NETWORK_ERROR",`Failed to fetch cameras: ${String(o)}`)}}async function he(e,n){const t=h();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 l=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!l.ok)return b(l);const f=await l.json();return c("Camera fetched:",f.name),_(f)}catch(l){return i("NETWORK_ERROR",`Failed to fetch camera: ${String(l)}`)}}async function b(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)}}exports.failure=i;exports.getAccessToken=$;exports.getAuthUrl=P;exports.getCamera=he;exports.getCameras=_e;exports.getClientId=O;exports.getConfig=re;exports.getCurrentUser=ue;exports.getProxyUrl=U;exports.getRedirectUri=m;exports.getUser=fe;exports.getUsers=de;exports.handleAuthCallback=F;exports.initEenToolkit=ne;exports.refreshToken=L;exports.revokeToken=j;exports.success=_;exports.useAuthStore=h;
2
2
  //# sourceMappingURL=index.cjs.map