een-api-toolkit 0.0.13 → 0.0.18

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,20 @@
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.18] - 2025-12-30
6
6
 
7
7
  ### Release Summary
8
8
 
9
- #### PR #15: feat: Launch OAuth proxy in CI for e2e tests
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
-
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
141
-
142
- - ✅ Linting passed (1 warning - max-len in test file)
143
- - ✅ Unit tests: 7/7 passed
144
- - ✅ Build: successful
145
-
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
164
-
165
- ## Test Results
166
-
167
- - ✅ Lint: Passed (1 expected warning)
168
- - ✅ Unit tests: 7/7 passed
169
- - ✅ Build: Successful
170
-
171
- ## Version
172
-
173
- `0.0.11`
174
-
175
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
176
-
177
- #### PR #21: docs: Add In-Place Login pattern for single-page OAuth callbacks
178
- ## Summary
179
-
180
- This PR adds documentation for the "In-Place Login" pattern - handling OAuth callbacks on the same page that displays user data without navigation.
181
-
182
- ## Changes
183
-
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
187
-
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)
210
-
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
222
-
223
- ## Test Results
224
-
225
- - ✅ Lint: passed (1 warning - expected console in debug.ts)
226
- - ✅ Unit tests: 7 passed
227
- - ✅ Build: successful
228
-
229
- ## Version
230
-
231
- `0.0.11`
232
-
233
- ---
234
-
235
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
236
-
237
- #### PR #23: feat: Include AI-CONTEXT.md in npm package and trigger releases on changes
238
- ## Summary
239
-
240
- This PR adds `docs/AI-CONTEXT.md` to the npm package distribution and ensures that updates to this file trigger new releases.
241
-
242
- ### Changes
243
-
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.
252
-
253
- ### Commits
254
-
255
- - `3505d9d` feat: Include AI-CONTEXT.md in npm package and trigger releases on changes
256
-
257
- ### Test Results
258
-
259
- - ✅ Linting passed (1 warning - expected console statement in debug.ts)
260
- - ✅ Unit tests passed (7/7)
261
- - ✅ Build successful
262
-
263
- ### Version
264
-
265
- `0.0.11`
266
-
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
285
-
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.
289
-
9
+ No PR descriptions available for this release.
290
10
 
291
11
  ### Detailed Changes
292
12
 
293
- #### 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
297
-
298
- #### 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
311
-
312
13
  #### 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
14
+ - docs: Improve AI-CONTEXT.md with critical setup info at top
328
15
 
329
16
  ### Links
330
17
  - [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)
18
+ - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.17...v0.0.18)
332
19
 
333
20
  ---
334
- *Released: 2025-12-29 14:15:09 CST*
21
+ *Released: 2025-12-30 10:05:39 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