een-api-toolkit 0.0.13 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,333 +2,132 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.0.13] - 2025-12-29
5
+ ## [0.0.17] - 2025-12-29
6
6
 
7
7
  ### Release Summary
8
8
 
9
- #### PR #15: feat: Launch OAuth proxy in CI for e2e tests
9
+ #### PR #26: feat: Add Camera API support (v0.0.14)
10
10
  ## Summary
11
- - Add proxy setup steps to test-release.yml workflow to run OAuth e2e tests in CI
12
- - Clone, install, and start OAuth proxy on port 8787 during CI
13
- - Create .dev.vars with required secrets for local proxy operation
14
- - Fix Slack release notes link to point to GitHub Release page instead of .md download
15
- - Add CLIENT_SECRET to secrets sync script and documentation
16
-
17
- ## Changes
18
- - `.github/workflows/test-release.yml`: Add steps to clone proxy, install deps, create secrets file, and start proxy
19
- - `.github/workflows/npm-publish.yml`: Fix Slack release notes link to avoid .md download
20
- - `scripts/sync-secrets.sh`: Add CLIENT_SECRET to sync list
21
- - `CLAUDE.md`: Document CLIENT_SECRET requirement
22
-
23
- ## Test plan
24
- - [ ] Verify test-release workflow runs and proxy starts successfully
25
- - [ ] Verify e2e OAuth tests execute against the local proxy
26
- - [ ] Verify Slack notification links to GitHub Release page (not .md download)
27
11
 
28
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
29
-
30
- #### PR #16: fix: Strip leading whitespace from .dev.vars heredoc
31
- ## Summary
32
- - Fix heredoc indentation issue in test-release.yml that caused proxy env vars to not be parsed
33
-
34
- ## Problem
35
- The `.dev.vars` heredoc content was indented for YAML readability, but those leading spaces became part of the file content:
36
- ```
37
- CLIENT_ID=xxx
38
- ALLOWED_ORIGINS=http://127.0.0.1:3333
39
- ```
40
-
41
- This caused wrangler to not recognize the environment variables, so `ALLOWED_ORIGINS` was empty and the proxy rejected OAuth callback requests with "Invalid redirect_uri: domain not allowed".
42
-
43
- ## Fix
44
- Added `sed -i 's/^[[:space:]]*//'` to strip leading whitespace after creating the file.
45
-
46
- ## Test plan
47
- - [ ] Verify test-release workflow passes
48
- - [ ] Verify OAuth e2e tests complete successfully
49
-
50
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
51
-
52
- #### PR #17: fix: Use printf with quoted values for .dev.vars
53
- ## Summary
54
- Fix special character handling in `.dev.vars` secrets file creation.
55
-
56
- ## Problem
57
- The `CLIENT_SECRET` contains special characters (like `#`) that were being interpreted as comment markers when written to `.dev.vars` without proper quoting, causing the value to be truncated.
58
-
59
- ## Solution
60
- Use `printf` with double-quoted values, matching the pattern from `een-oauth-proxy/test-demo1-pr.yml`:
61
-
62
- ```bash
63
- printf 'CLIENT_ID="%s"\n' "$CLIENT_ID" > .dev.vars
64
- printf 'CLIENT_SECRET="%s"\n' "$CLIENT_SECRET" >> .dev.vars
65
- ```
66
-
67
- This properly escapes special characters in secret values.
68
-
69
- ## Test plan
70
- - [ ] Verify test-release workflow passes
71
- - [ ] Verify OAuth e2e tests complete successfully
72
-
73
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
74
-
75
- #### PR #18: docs: Restructure documentation and add CI validation
76
- ## Summary
77
-
78
- - Restructure README.md into a concise overview with quick start guide
79
- - Create separate User Guide (docs/USER-GUIDE.md) for app developers
80
- - Create separate Developer Guide (docs/DEVELOPER-GUIDE.md) for contributors
81
- - Regenerate TypeDoc API reference for version 0.0.11
82
- - Fix broken EENCloud GitHub link in CLAUDE.md
83
- - Add documentation validation step to test-release workflow
84
-
85
- ## Changes
86
-
87
- ### Documentation Restructure
88
- - **README.md**: Simplified with key features first, quick start guide, architecture diagram
89
- - **docs/USER-GUIDE.md**: New comprehensive guide covering installation, proxy setup, auth flow, API usage, troubleshooting
90
- - **docs/DEVELOPER-GUIDE.md**: New guide for contributors covering architecture, testing, CI/CD, publishing
91
- - **docs/README.md**: Updated as documentation index with audience descriptions
92
-
93
- ### CI/CD
94
- - Added "Verify documentation is current" step to test-release.yml
95
- - Fails build if docs are stale, ensuring release docs always match code
96
-
97
- ### Fixes
98
- - Updated broken link to EENCloud/api-v3-documentation (404) → VMS-Developer-Portal (200)
99
- - Regenerated all TypeDoc files with version 0.0.11
100
-
101
- ## Test Results
102
- - Lint: Passed (1 warning)
103
- - Unit tests: 7/7 passed
104
- - Build: Success
105
-
106
- ## Version
107
- `0.0.11`
108
-
109
- ---
110
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
111
-
112
- #### PR #19: Release v0.0.11: Documentation restructure and OAuth requirements
113
- ## Summary
114
-
115
- This release focuses on comprehensive documentation improvements:
116
-
117
- - **Documentation restructure**: Split README into user-focused and developer-focused sections
118
- - `docs/USER-GUIDE.md` - For application developers using the toolkit
119
- - `docs/DEVELOPER-GUIDE.md` - For contributors to the toolkit
120
- - **OAuth redirect URI requirements**: Added critical documentation based on user testing feedback
121
- - EEN IDP requires exact string match: `http://127.0.0.1:3333` (not localhost, no /callback path)
122
- - Added router pattern examples for handling OAuth on root path
123
- - Added link to EEN Developer Portal for redirect URI configuration
124
- - **Architecture diagram fixes**: Corrected to show auth calls vs API calls use different paths
125
- - **CI documentation validation**: Added step to test-release workflow to fail if docs are stale
126
- - **AI-CONTEXT.md improvements**: Critical Requirements section now auto-generated
127
-
128
- ### Key Changes
129
-
130
- - Restructured documentation for better discoverability
131
- - Added comprehensive OAuth troubleshooting guidance
132
- - Fixed architecture diagrams to accurately show auth flow
133
- - Updated PR-and-check skill to support develop→production PRs
134
- - Added Purpose section to README explaining toolkit goals
135
-
136
- ### Version
137
-
138
- **Package version:** 0.0.11
139
-
140
- ### Test Results
12
+ Add comprehensive Camera API support to een-api-toolkit following the same patterns as the Users API.
141
13
 
142
- - Linting passed (1 warning - max-len in test file)
143
- - Unit tests: 7/7 passed
144
- - Build: successful
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
145
19
 
146
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
147
-
148
- #### PR #20: docs: Add Pinia prerequisite requirements to documentation
149
- ## Summary
150
-
151
- This PR adds comprehensive documentation about Pinia prerequisites to help users avoid the common "getActivePinia() was called but there was no active Pinia" error.
152
-
153
- ## Changes
154
-
155
- - **AI-CONTEXT.md**: Added "Prerequisites (IMPORTANT)" section with Pinia installation requirements and error message
156
- - **USER-GUIDE.md**: Enhanced toolkit initialization section and added troubleshooting entry for the Pinia error
157
- - **DEVELOPER-GUIDE.md**: Added Pinia as a key design decision explaining the dependency requirement
158
- - **generate-ai-context.ts**: Updated generation script to include Pinia prerequisites
159
-
160
- ## New Commits
161
-
162
- - `9308498` fix: Update AI-CONTEXT generator to include Pinia prerequisites
163
- - `f62490b` docs: Add Pinia prerequisite requirements to documentation
20
+ ### 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
164
24
 
165
25
  ## Test Results
166
-
167
- - ✅ Lint: Passed (1 expected warning)
168
- - ✅ Unit tests: 7/7 passed
169
- - ✅ Build: Successful
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
170
31
 
171
32
  ## Version
172
-
173
- `0.0.11`
33
+ `0.0.14`
174
34
 
175
35
  🤖 Generated with [Claude Code](https://claude.com/claude-code)
176
36
 
177
- #### PR #21: docs: Add In-Place Login pattern for single-page OAuth callbacks
37
+ #### PR #27: feat: Camera API support and AI Prompts guide (v0.0.16)
178
38
  ## Summary
179
39
 
180
- This PR adds documentation for the "In-Place Login" pattern - handling OAuth callbacks on the same page that displays user data without navigation.
40
+ This PR adds comprehensive Camera API support and developer documentation improvements.
181
41
 
182
- ## Changes
42
+ ### New Features
183
43
 
184
- - **AI-CONTEXT.md**: Added "In-Place Login (Single Page Callback)" to Common Patterns section
185
- - **USER-GUIDE.md**: Added same pattern to Authentication Flow section with expanded explanation
186
- - **generate-ai-context.ts**: Updated script to include the pattern in future regenerations
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
187
49
 
188
- ## Problem Addressed
189
-
190
- Developers implementing single-page OAuth flows were encountering issues where `useCurrentUser()` didn't update after successful login. The documentation now explains:
191
- - Why `refresh()` must be called after `handleAuthCallback()` when staying on the same page
192
- - That composables don't auto-refresh when auth state changes
193
- - Complete working example with login button and callback handling
194
-
195
- ## New Commits
196
-
197
- - `3b7b6a0` docs: Add In-Place Login pattern for single-page OAuth callbacks
198
-
199
- ## Test Results
200
-
201
- - ✅ Lint: Passed (1 expected warning)
202
- - ✅ Unit tests: 7/7 passed
203
- - ✅ Build: Successful
204
-
205
- ## Version
206
-
207
- `0.0.11`
208
-
209
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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
210
53
 
211
- #### PR #22: fix: Correct proxy endpoints and API references in README
212
- ## Summary
213
-
214
- - Fix incorrect proxy endpoints documentation (`/oauth/authorize`, `/oauth/token` → `/proxy/getAccessToken`)
215
- - Update Key Features to reflect actual implemented APIs (Users only, not Cameras/Bridges)
216
- - Fix code examples to use existing functions (`getCurrentUser`, `getUsers`, `getUser`)
217
- - Update architecture diagram to show implemented APIs
218
-
219
- ## Commits
220
-
221
- - `ff85054` fix: Correct proxy endpoints and API references in README
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
222
63
 
223
64
  ## Test Results
224
-
225
- - ✅ Lint: passed (1 warning - expected console in debug.ts)
226
- - ✅ Unit tests: 7 passed
227
- - ✅ Build: successful
65
+ - ✅ Lint: Pass (0 errors)
66
+ - ✅ Unit tests: 33 passed
67
+ - ✅ Build: Success
228
68
 
229
69
  ## Version
230
-
231
- `0.0.11`
232
-
233
- ---
70
+ `0.0.16`
234
71
 
235
72
  🤖 Generated with [Claude Code](https://claude.com/claude-code)
236
73
 
237
- #### PR #23: feat: Include AI-CONTEXT.md in npm package and trigger releases on changes
74
+ #### PR #28: Release v0.0.17: Documentation updates and CI fix
238
75
  ## Summary
239
76
 
240
- This PR adds `docs/AI-CONTEXT.md` to the npm package distribution and ensures that updates to this file trigger new releases.
77
+ This release includes documentation improvements and a CI fix for version mismatch issues.
241
78
 
242
79
  ### Changes
243
80
 
244
- - **package.json**: Added `docs/AI-CONTEXT.md` to the `files` array so it's included in the npm package
245
- - **.husky/pre-commit**: Modified to trigger version bump when `docs/AI-CONTEXT.md` changes
246
- - **CLAUDE.md**: Updated documentation to reflect the new behavior
247
- - **docs/DEVELOPER-GUIDE.md**: Updated documentation with explanation of why AI-CONTEXT.md triggers releases
248
-
249
- ### Rationale
250
-
251
- The README positions AI-assisted development as a key value proposition of this toolkit. Including `AI-CONTEXT.md` in the npm package makes it immediately accessible to consumers using AI assistants without requiring them to clone the repo or navigate to GitHub.
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
252
90
 
253
91
  ### Commits
254
92
 
255
- - `3505d9d` feat: Include AI-CONTEXT.md in npm package and trigger releases on changes
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
256
96
 
257
97
  ### Test Results
258
98
 
259
- - ✅ Linting passed (1 warning - expected console statement in debug.ts)
260
- - ✅ Unit tests passed (7/7)
261
- - ✅ Build successful
99
+ - ✅ Lint: Passed (1 warning - expected)
100
+ - ✅ Unit tests: 33 passed
101
+ - ✅ Build: Success
262
102
 
263
103
  ### Version
264
104
 
265
- `0.0.11`
105
+ `0.0.17`
266
106
 
267
- #### PR #24: chore: Release v0.0.13
268
- ## Summary
269
-
270
- Version bump to 0.0.13 for new release including:
271
- - AI-CONTEXT.md included in npm package
272
- - README.md changes now trigger version bumps
273
- - Updated Husky pre-commit hook configuration
274
- - **Fix:** Removed AI-CONTEXT.md from version bump triggers to prevent circular versioning
275
-
276
- ### Version
277
-
278
- `0.0.13`
279
-
280
- ### Previous Release
281
-
282
- v0.0.11 was published via PR #23
283
-
284
- ### Version Fix
107
+ ---
285
108
 
286
- This release fixes a circular dependency issue where updating AI-CONTEXT.md
287
- (a generated file) would trigger another version bump. AI-CONTEXT.md now
288
- correctly reflects the version without causing additional bumps.
109
+ 🤖 Generated with [Claude Code](https://claude.com/claude-code)
289
110
 
290
111
 
291
112
  ### Detailed Changes
292
113
 
293
114
  #### Features
294
- - feat: Add README.md to version bump triggers
295
- - feat: Include AI-CONTEXT.md in npm package and trigger releases on changes
296
- - feat: Launch OAuth proxy in CI for e2e tests
115
+ - feat: Add Camera API support with getCameras, getCamera, useCameras, useCamera
297
116
 
298
117
  #### Bug Fixes
299
- - fix: Remove AI-CONTEXT.md from version bump triggers
300
- - fix: Correct proxy endpoints and API references in README
301
- - fix: Address code review feedback for In-Place Login pattern
302
- - fix: Add redirectUri and debug to initEenToolkit examples
303
- - fix: Address code review feedback
304
- - fix: Update AI-CONTEXT generator to include Pinia prerequisites
305
- - fix: Update router example to handle OAuth on root path
306
- - fix: Address PR #17 review feedback
307
- - fix: Use printf with quoted values for .dev.vars
308
- - fix: Address PR #16 review feedback
309
- - fix: Strip leading whitespace from .dev.vars heredoc
310
- - fix: Address PR #15 review feedback
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
311
121
 
312
122
  #### Other Changes
313
- - docs: Regenerate API documentation for v0.0.13
314
- - docs: Update AI-CONTEXT.md version to 0.0.12
315
- - chore: Bump version to 0.0.12 for release
316
- - docs: Fix glob patterns to show deep matching (src/**/*)
317
- - docs: Add getCurrentUser example to README
318
- - docs: Fix API references in USER-GUIDE and DEVELOPER-GUIDE
319
- - docs: Add In-Place Login pattern for single-page OAuth callbacks
320
- - docs: Add Pinia prerequisite requirements to documentation
321
- - docs: Add OAuth requirements and update doc generation script
322
- - docs: Add OAuth requirements, proxy info, and EEN portal links
323
- - docs: Add purpose section and update PR-and-check skill
324
- - docs: Fix architecture diagrams and error handling example
325
- - ci: Add documentation validation to test-release workflow
326
- - docs: Regenerate docs for v0.0.11 and fix broken link
327
- - docs: Restructure documentation for users and developers
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
328
127
 
329
128
  ### Links
330
129
  - [npm package](https://www.npmjs.com/package/een-api-toolkit)
331
- - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.11...v0.0.13)
130
+ - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.13...v0.0.17)
332
131
 
333
132
  ---
334
- *Released: 2025-12-29 14:15:09 CST*
133
+ *Released: 2025-12-29 19:59:36 CST*
package/README.md CHANGED
@@ -182,7 +182,8 @@ if (error) {
182
182
  | **[Developer Guide](./docs/DEVELOPER-GUIDE.md)** | Architecture, testing, CI/CD, contributing |
183
183
  | **[API Reference](./docs/api/)** | Auto-generated TypeDoc documentation |
184
184
  | **[Example App](./examples/vue-basic/)** | Complete Vue 3 example with OAuth flow |
185
- | **[AI Context](./docs/AI-CONTEXT.md)** | Single-file reference for AI assistants |
185
+ | **[AI Context](./docs/AI-CONTEXT.md)** | Single-file reference for AI assistants (also in npm package) |
186
+ | **[AI Prompts](./docs/Prompts.md)** | Example prompts for generating apps with AI |
186
187
 
187
188
  ## External Resources
188
189
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ne=require("pinia"),u=require("vue"),U={};let k={};function oe(e={}){k={proxyUrl:e.proxyUrl??U?.VITE_PROXY_URL,clientId:e.clientId??U?.VITE_EEN_CLIENT_ID,redirectUri:e.redirectUri??U?.VITE_REDIRECT_URI,debug:e.debug??U?.VITE_DEBUG==="true"}}function ae(){return k}function y(){return k.proxyUrl??U?.VITE_PROXY_URL}function b(){return k.clientId??U?.VITE_EEN_CLIENT_ID}function O(){return k.redirectUri??U?.VITE_REDIRECT_URI??"http://127.0.0.1:3333"}function p(e){return{data:e,error:null}}function c(e,r,t,n){return{data:null,error:{code:e,message:r,status:t,details:n}}}const se={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},ue=()=>{try{return se?.VITE_DEBUG==="true"}catch{return!1}};function i(...e){ue()&&console.log("[een-api-toolkit]",...e)}let $=null;function le(){return $||($=Promise.resolve().then(()=>fe).then(e=>e.refreshToken)),$}const _=ne.defineStore("een-auth",()=>{const e=u.ref(null),r=u.ref(null),t=u.ref(null),n=u.ref(null),o=u.ref(null),a=u.ref(443),l=u.ref(null),h=u.ref(null),T=u.ref(!1);let v=null;const g=u.ref(!1),d=u.ref(null),x=u.computed(()=>!!e.value),A=u.computed(()=>o.value?a.value===443?`https://${o.value}`:`https://${o.value}:${a.value}`:null),I=u.computed(()=>r.value?Date.now()>=r.value:!0),P=u.computed(()=>r.value?Math.max(0,r.value-Date.now()):0);function E(s,f){e.value=s,r.value=Date.now()+f*1e3,R(),D(),i("Token set, expires in",f,"seconds")}function w(s){t.value=s,R()}function m(s){n.value=s,R()}function Q(s){if(typeof s=="string")try{const f=new URL(s.startsWith("http")?s:`https://${s}`);o.value=f.hostname,a.value=f.port?parseInt(f.port,10):443}catch(f){i("Failed to parse URL, using as hostname:",f instanceof Error?f.message:String(f)),o.value=s,a.value=443}else o.value=s.hostname,a.value=s.port??443;R(),i("Base URL set:",A.value)}function W(s){l.value=s,R()}function D(){if(h.value&&(clearTimeout(h.value),h.value=null),!r.value||!e.value)return;const s=Date.now(),S=r.value-s,Z=300*1e3,ee=S/2,te=Math.min(Z,ee),re=Math.max(S-te,60*1e3),C=Math.max(re,5e3);i("Auto-refresh scheduled in",Math.round(C/1e3),"seconds"),h.value=setTimeout(async()=>{await G()},C)}async function G(){return v?(i("Refresh already in progress, waiting for existing refresh"),v):(T.value=!0,i("Performing auto-refresh"),v=(async()=>{try{const f=await(await le())();f.error?(g.value=!0,d.value=f.error.message,i("Auto-refresh failed:",f.error.message)):(g.value=!1,d.value=null,i("Auto-refresh successful"))}catch(s){g.value=!0,d.value=s instanceof Error?s.message:String(s),i("Auto-refresh error:",s)}finally{T.value=!1,v=null}})(),v)}function K(){g.value=!1,d.value=null}function N(){h.value&&(clearTimeout(h.value),h.value=null),e.value=null,r.value=null,t.value=null,n.value=null,o.value=null,a.value=443,l.value=null,g.value=!1,d.value=null,J(),i("Logged out")}function X(){Y(),e.value&&!I.value?(D(),i("Initialized from storage")):e.value&&I.value&&(i("Stored token expired, clearing"),N())}function R(){try{e.value&&localStorage.setItem("een_token",e.value),r.value&&localStorage.setItem("een_tokenExpiration",String(r.value)),t.value&&localStorage.setItem("een_refreshTokenMarker",t.value),n.value&&localStorage.setItem("een_sessionId",n.value),o.value&&localStorage.setItem("een_hostname",o.value),a.value!==443&&localStorage.setItem("een_port",String(a.value)),l.value&&localStorage.setItem("een_userProfile",JSON.stringify(l.value))}catch(s){i("Failed to save to localStorage:",s instanceof Error?s.message:String(s))}}function Y(){try{e.value=localStorage.getItem("een_token");const s=localStorage.getItem("een_tokenExpiration");r.value=s?parseInt(s,10):null,t.value=localStorage.getItem("een_refreshTokenMarker"),n.value=localStorage.getItem("een_sessionId"),o.value=localStorage.getItem("een_hostname");const f=localStorage.getItem("een_port");a.value=f?parseInt(f,10):443;const S=localStorage.getItem("een_userProfile");l.value=S?JSON.parse(S):null}catch(s){i("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){i("Failed to clear localStorage:",s instanceof Error?s.message:String(s))}}return{token:e,tokenExpiration:r,refreshTokenMarker:t,sessionId:n,hostname:o,port:a,userProfile:l,isRefreshing:T,refreshFailed:g,refreshFailedMessage:d,isAuthenticated:x,baseUrl:A,isTokenExpired:I,tokenExpiresIn:P,setToken:E,setRefreshTokenMarker:w,setSessionId:m,setBaseUrl:Q,setUserProfile:W,setupAutoRefresh:D,clearRefreshFailed:K,logout:N,initialize:X}}),ie="https://auth.eagleeyenetworks.com/oauth2/authorize";function M(){const e=b();if(!e)throw new Error("Client ID not configured. Call initEenToolkit() or set VITE_EEN_CLIENT_ID");const r=crypto.randomUUID();try{sessionStorage.setItem("een_oauth_state",r)}catch{}const t=new URLSearchParams({client_id:e,response_type:"code",scope:"vms.all",redirect_uri:O(),state:r});return i("Generated auth URL with state:",r),`${ie}?${t.toString()}`}async function L(e){const r=y();if(!r)return c("AUTH_FAILED","Proxy URL not configured. Call initEenToolkit() or set VITE_PROXY_URL");const t=new URLSearchParams({code:e,redirect_uri:O()});try{const n=await fetch(`${r}/proxy/getAccessToken?${t.toString()}`,{method:"POST",credentials:"include",headers:{Accept:"application/json"}});if(!n.ok){const a=await n.text().catch(()=>"Unknown error");return c("AUTH_FAILED",`Token exchange failed: ${a}`,n.status)}const o=await n.json();return i("Token received, expires in:",o.expiresIn),p(o)}catch(n){return c("NETWORK_ERROR",`Failed to exchange code: ${String(n)}`)}}async function j(){const e=y();if(!e)return c("AUTH_FAILED","Proxy URL not configured");const r=_();try{const t={Accept:"application/json"};r.sessionId&&(t.Authorization=`Bearer ${r.sessionId}`);const n=await fetch(`${e}/proxy/refreshAccessToken`,{method:"POST",credentials:"include",headers:t});if(!n.ok){const a=await n.text().catch(()=>"Unknown error");return c("AUTH_FAILED",`Token refresh failed: ${a}`,n.status)}const o=await n.json();return r.setToken(o.accessToken,o.expiresIn),i("Token refreshed, expires in:",o.expiresIn),p(o)}catch(t){return c("NETWORK_ERROR",`Failed to refresh token: ${String(t)}`)}}async function B(){const e=y();if(!e)return c("AUTH_FAILED","Proxy URL not configured");const r=_();try{const t={Accept:"application/json"};r.sessionId&&(t.Authorization=`Bearer ${r.sessionId}`);const n=await fetch(`${e}/proxy/revoke`,{method:"POST",credentials:"include",headers:t});if(r.logout(),!n.ok){const o=await n.text().catch(()=>"Unknown error");return c("AUTH_FAILED",`Token revocation failed: ${o}`,n.status)}return i("Token revoked"),p(void 0)}catch(t){return r.logout(),c("NETWORK_ERROR",`Failed to revoke token: ${String(t)}`)}}async function H(e,r){let t=null;try{t=sessionStorage.getItem("een_oauth_state"),sessionStorage.removeItem("een_oauth_state")}catch{}if(!t)return c("AUTH_FAILED","No OAuth state found. Please restart the login process.");if(!ce(r,t))return c("AUTH_FAILED","Invalid OAuth state. Possible CSRF attack.");i("State validated, exchanging code for token");const n=await L(e);if(n.error)return n;const o=_(),a=n.data;return o.setToken(a.accessToken,a.expiresIn),o.setRefreshTokenMarker("present"),o.setSessionId(a.sessionId),o.setBaseUrl(a.httpsBaseUrl),i("Auth callback complete, user:",a.userEmail),p(a)}function ce(e,r){if(e.length!==r.length)return!1;let t=0;for(let n=0;n<e.length;n++)t|=e.charCodeAt(n)^r.charCodeAt(n);return t===0}const fe=Object.freeze(Object.defineProperty({__proto__:null,getAccessToken:L,getAuthUrl:M,handleAuthCallback:H,refreshToken:j,revokeToken:B},Symbol.toStringTag,{value:"Module"}));async function z(){const e=_();if(!e.isAuthenticated)return c("AUTH_REQUIRED","Authentication required");if(!e.baseUrl)return c("AUTH_REQUIRED","Base URL not configured");const r=`${e.baseUrl}/api/v3.0/users/self`;i("Fetching current user:",r);try{const t=await fetch(r,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e.token}`}});if(!t.ok)return F(t);const n=await t.json();return i("Current user fetched:",n.email),e.setUserProfile(n),p(n)}catch(t){return c("NETWORK_ERROR",`Failed to fetch current user: ${String(t)}`)}}async function V(e){const r=_();if(!r.isAuthenticated)return c("AUTH_REQUIRED","Authentication required");if(!r.baseUrl)return c("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 n=t.toString(),o=`${r.baseUrl}/api/v3.0/users${n?`?${n}`:""}`;i("Fetching users:",o);try{const a=await fetch(o,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${r.token}`}});if(!a.ok)return F(a);const l=await a.json();return i("Users fetched:",l.results?.length??0,"users"),p(l)}catch(a){return c("NETWORK_ERROR",`Failed to fetch users: ${String(a)}`)}}async function q(e,r){const t=_();if(!t.isAuthenticated)return c("AUTH_REQUIRED","Authentication required");if(!t.baseUrl)return c("AUTH_REQUIRED","Base URL not configured");if(!e)return c("VALIDATION_ERROR","User ID is required");const n=new URLSearchParams;r?.include&&r.include.length>0&&n.append("include",r.include.join(","));const o=n.toString(),a=`${t.baseUrl}/api/v3.0/users/${encodeURIComponent(e)}${o?`?${o}`:""}`;i("Fetching user:",a);try{const l=await fetch(a,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${t.token}`}});if(!l.ok)return F(l);const h=await l.json();return i("User fetched:",h.email),p(h)}catch(l){return c("NETWORK_ERROR",`Failed to fetch user: ${String(l)}`)}}async function F(e){const r=e.status;let t;try{const n=await e.json();t=n.message??n.error??e.statusText}catch{t=e.statusText||"Unknown error"}switch(r){case 401:return c("AUTH_REQUIRED",`Authentication failed: ${t}`,r);case 403:return c("FORBIDDEN",`Access denied: ${t}`,r);case 404:return c("NOT_FOUND",`Not found: ${t}`,r);case 429:return c("RATE_LIMITED",`Rate limited: ${t}`,r);default:return c("API_ERROR",`API error: ${t}`,r)}}function de(e){const r=u.ref(null),t=u.ref(!1),n=u.ref(null),o=async()=>{t.value=!0,n.value=null;const l=await z();return l.error?(n.value=l.error,r.value=null):r.value=l.data,t.value=!1,l},a=o;return e?.immediate!==!1&&u.onMounted(o),{user:r,loading:t,error:n,fetch:o,refresh:a}}function he(e,r){const t=u.ref([]),n=u.ref(!1),o=u.ref(null),a=u.ref(void 0),l=u.ref(void 0),h=u.ref(void 0),T=u.computed(()=>!!a.value),v=u.computed(()=>!!l.value),g=u.ref(e??{}),d=async E=>{n.value=!0,o.value=null;const w={...g.value,...E},m=await V(w);return m.error?(o.value=m.error,t.value=[],a.value=void 0,l.value=void 0,h.value=void 0):(t.value=m.data.results,a.value=m.data.nextPageToken,l.value=m.data.prevPageToken,h.value=m.data.totalSize),n.value=!1,m},x=()=>d(),A=async()=>{if(a.value)return d({...g.value,pageToken:a.value})},I=async()=>{if(l.value)return d({...g.value,pageToken:l.value})},P=E=>{g.value=E};return r?.immediate!==!1&&u.onMounted(d),{users:t,loading:n,error:o,nextPageToken:a,prevPageToken:l,totalSize:h,hasNextPage:T,hasPrevPage:v,params:g,fetch:d,refresh:x,fetchNextPage:A,fetchPrevPage:I,setParams:P}}function ge(e,r){const t=u.ref(null),n=u.ref(!1),o=u.ref(null),a=()=>typeof e=="function"?e():e,l=async T=>{const v=a();if(!v)return o.value={code:"VALIDATION_ERROR",message:"User ID is required"},{data:null,error:o.value};n.value=!0,o.value=null;const g={include:r?.include,...T},d=await q(v,g);return d.error?(o.value=d.error,t.value=null):t.value=d.data,n.value=!1,d},h=()=>l();return r?.immediate!==!1&&a()&&u.onMounted(l),{user:t,loading:n,error:o,fetch:l,refresh:h}}exports.failure=c;exports.getAccessToken=L;exports.getAuthUrl=M;exports.getClientId=b;exports.getConfig=ae;exports.getCurrentUser=z;exports.getProxyUrl=y;exports.getRedirectUri=O;exports.getUser=q;exports.getUsers=V;exports.handleAuthCallback=H;exports.initEenToolkit=oe;exports.refreshToken=j;exports.revokeToken=B;exports.success=p;exports.useAuthStore=_;exports.useCurrentUser=de;exports.useUser=ge;exports.useUsers=he;
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;
2
2
  //# sourceMappingURL=index.cjs.map