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