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 +5 -318
- package/README.md +2 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +897 -0
- package/dist/index.js +395 -262
- package/dist/index.js.map +1 -1
- package/docs/AI-CONTEXT.md +362 -64
- package/examples/vue-cameras/.env.example +13 -0
- package/examples/vue-cameras/e2e/app.spec.ts +73 -0
- package/examples/vue-cameras/index.html +13 -0
- package/examples/vue-cameras/package-lock.json +1583 -0
- package/examples/vue-cameras/package.json +28 -0
- package/examples/vue-cameras/playwright.config.ts +46 -0
- package/examples/vue-cameras/src/App.vue +108 -0
- package/examples/vue-cameras/src/main.ts +23 -0
- package/examples/vue-cameras/src/router/index.ts +68 -0
- package/examples/vue-cameras/src/views/Callback.vue +76 -0
- package/examples/vue-cameras/src/views/CameraDetail.vue +315 -0
- package/examples/vue-cameras/src/views/Cameras.vue +249 -0
- package/examples/vue-cameras/src/views/Home.vue +125 -0
- package/examples/vue-cameras/src/views/Login.vue +33 -0
- package/examples/vue-cameras/src/views/Logout.vue +66 -0
- package/examples/vue-cameras/src/vite-env.d.ts +12 -0
- package/examples/vue-cameras/tsconfig.json +21 -0
- package/examples/vue-cameras/tsconfig.node.json +10 -0
- package/examples/vue-cameras/vite.config.ts +12 -0
- package/package.json +1 -1
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.
|
|
5
|
+
## [0.0.18] - 2025-12-30
|
|
6
6
|
|
|
7
7
|
### Release Summary
|
|
8
8
|
|
|
9
|
-
|
|
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:
|
|
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.
|
|
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-
|
|
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
|