een-api-toolkit 0.0.17 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -94
- 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 +162 -313
- 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,97 +2,37 @@
|
|
|
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
|
-
#### PR #
|
|
9
|
+
#### PR #31: Release v0.0.18: Documentation improvements and PR validation
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
### New Features
|
|
15
|
-
- **Camera Types**: `Camera`, `CameraStatus`, `CameraDeviceInfo`, `CameraShareDetails`, `CameraDevicePosition`, `CameraStreamUrls`, `CameraRtspConnectionSettings`, `CameraRecordingModes`
|
|
16
|
-
- **Service Functions**: `getCameras()`, `getCamera()` with all 25+ filter parameters
|
|
17
|
-
- **Vue 3 Composables**: `useCameras()`, `useCamera()` with pagination and filtering support
|
|
18
|
-
- **Example App**: `examples/vue-cameras/` - Complete Vue 3 app demonstrating camera APIs
|
|
12
|
+
This release includes documentation improvements based on user feedback and a new CI workflow to validate PRs before merge.
|
|
19
13
|
|
|
20
14
|
### Changes
|
|
21
|
-
- `04cb829` feat: Add Camera API support with getCameras, getCamera, useCameras, useCamera
|
|
22
|
-
- `9765ed0` Merge pull request #25 from klaushofrichter/develop
|
|
23
|
-
- `aa8b0e9` docs: Regenerate API documentation for v0.0.13
|
|
24
|
-
|
|
25
|
-
## Test Results
|
|
26
|
-
- ✅ Lint: Pass (0 errors, 1 expected warning)
|
|
27
|
-
- ✅ Unit tests: 33 passed (26 cameras + 7 types)
|
|
28
|
-
- ✅ E2E tests: 14 passed
|
|
29
|
-
- ✅ vue-cameras Playwright tests: 7 passed
|
|
30
|
-
- ✅ Build: Success
|
|
31
|
-
|
|
32
|
-
## Version
|
|
33
|
-
`0.0.14`
|
|
34
|
-
|
|
35
|
-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
36
|
-
|
|
37
|
-
#### PR #27: feat: Camera API support and AI Prompts guide (v0.0.16)
|
|
38
|
-
## Summary
|
|
39
|
-
|
|
40
|
-
This PR adds comprehensive Camera API support and developer documentation improvements.
|
|
41
|
-
|
|
42
|
-
### New Features
|
|
43
15
|
|
|
44
|
-
**
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
16
|
+
**docs: Improve AI-CONTEXT.md with critical setup info at top**
|
|
17
|
+
- Added "Prerequisites & Installation (READ FIRST)" section
|
|
18
|
+
- Installation command now includes pinia: `npm install een-api-toolkit pinia`
|
|
19
|
+
- Complete main.ts example with numbered steps
|
|
20
|
+
- Common Errors section for Pinia and OAuth issues
|
|
49
21
|
|
|
50
|
-
**
|
|
51
|
-
-
|
|
52
|
-
-
|
|
22
|
+
**docs: Address Gemini review feedback**
|
|
23
|
+
- OAuth Callback Route: Added sentence linking to beforeEnter guard
|
|
24
|
+
- Logout: Changed to full Vue component example with useRouter
|
|
53
25
|
|
|
54
|
-
|
|
55
|
-
- `
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
- `68ba14a` fix: Address code review feedback for Camera API
|
|
60
|
-
- `04cb829` feat: Add Camera API support
|
|
61
|
-
- `9765ed0` Merge pull request #25
|
|
62
|
-
- `aa8b0e9` docs: Regenerate API documentation for v0.0.13
|
|
26
|
+
**ci: Add PR validation workflow**
|
|
27
|
+
- New `validate-pr.yml` workflow runs on PRs to production
|
|
28
|
+
- Validates version consistency across package.json, AI-CONTEXT.md, and docs/api
|
|
29
|
+
- Checks if version is already published to npm
|
|
30
|
+
- Runs quick validation tests (lint, typecheck, unit tests, build, docs)
|
|
63
31
|
|
|
64
|
-
|
|
65
|
-
- ✅ Lint: Pass (0 errors)
|
|
66
|
-
- ✅ Unit tests: 33 passed
|
|
67
|
-
- ✅ Build: Success
|
|
32
|
+
### New Commits (since last merge)
|
|
68
33
|
|
|
69
|
-
|
|
70
|
-
`
|
|
71
|
-
|
|
72
|
-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
73
|
-
|
|
74
|
-
#### PR #28: Release v0.0.17: Documentation updates and CI fix
|
|
75
|
-
## Summary
|
|
76
|
-
|
|
77
|
-
This release includes documentation improvements and a CI fix for version mismatch issues.
|
|
78
|
-
|
|
79
|
-
### Changes
|
|
80
|
-
|
|
81
|
-
- **fix:** Regenerate AI-CONTEXT.md after version bump in pre-commit hook
|
|
82
|
-
- Ensures version in AI-CONTEXT.md always matches package.json
|
|
83
|
-
- Prevents CI failures due to version mismatch
|
|
84
|
-
|
|
85
|
-
- **docs:** Update GitHub links to point to production branch
|
|
86
|
-
- Changed typedoc.json gitRevision from develop to production
|
|
87
|
-
- Updated AI-CONTEXT.md references in Prompts.md
|
|
88
|
-
- Added note that AI-CONTEXT.md is included in npm package
|
|
89
|
-
- Regenerated all API docs with production branch links
|
|
90
|
-
|
|
91
|
-
### Commits
|
|
92
|
-
|
|
93
|
-
- `5379307` fix: Regenerate AI-CONTEXT.md after version bump in pre-commit hook
|
|
94
|
-
- `68e98f3` docs: Update GitHub links to point to production branch
|
|
95
|
-
- `651d70b` docs: Add AI Prompts guide and fix CI date issue
|
|
34
|
+
- `d62fadc` ci: Add PR validation workflow for version consistency
|
|
35
|
+
- `29ad8f6` docs: Address Gemini review feedback
|
|
96
36
|
|
|
97
37
|
### Test Results
|
|
98
38
|
|
|
@@ -102,7 +42,7 @@ This release includes documentation improvements and a CI fix for version mismat
|
|
|
102
42
|
|
|
103
43
|
### Version
|
|
104
44
|
|
|
105
|
-
`0.0.
|
|
45
|
+
`0.0.18`
|
|
106
46
|
|
|
107
47
|
---
|
|
108
48
|
|
|
@@ -111,23 +51,18 @@ This release includes documentation improvements and a CI fix for version mismat
|
|
|
111
51
|
|
|
112
52
|
### Detailed Changes
|
|
113
53
|
|
|
114
|
-
#### Features
|
|
115
|
-
- feat: Add Camera API support with getCameras, getCamera, useCameras, useCamera
|
|
116
|
-
|
|
117
|
-
#### Bug Fixes
|
|
118
|
-
- fix: Regenerate ALL docs after version bump in pre-commit hook
|
|
119
|
-
- fix: Regenerate AI-CONTEXT.md after version bump in pre-commit hook
|
|
120
|
-
- fix: Address code review feedback for Camera API
|
|
121
|
-
|
|
122
54
|
#### Other Changes
|
|
123
|
-
-
|
|
124
|
-
- docs:
|
|
125
|
-
-
|
|
126
|
-
-
|
|
55
|
+
- refactor: Rename vue-basic example to vue-users
|
|
56
|
+
- docs: Add v-else fallback to Vue template example
|
|
57
|
+
- test: Add service function unit tests, fix pagination, bump to 0.1.0
|
|
58
|
+
- refactor: Remove Vue 3 Composables, keep plain async functions only
|
|
59
|
+
- docs: Address code review feedback
|
|
60
|
+
- ci: Add PR validation workflow for version consistency
|
|
61
|
+
- docs: Address Gemini review feedback
|
|
127
62
|
|
|
128
63
|
### Links
|
|
129
64
|
- [npm package](https://www.npmjs.com/package/een-api-toolkit)
|
|
130
|
-
- [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.
|
|
65
|
+
- [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.0.18...v0.1.2)
|
|
131
66
|
|
|
132
67
|
---
|
|
133
|
-
*Released: 2025-12-
|
|
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
|