een-api-toolkit 0.0.8 → 0.0.13

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/README.md CHANGED
@@ -1,30 +1,56 @@
1
1
  # een-api-toolkit
2
2
 
3
- A TypeScript library implementing the [Eagle Eye Networks (EEN)](https://een.com/) Video platform API v3.0 for Vue 3 Composition API applications. See also the [EEN Developer Portal](https://developer.eagleeyenetworks.com).
3
+ A TypeScript library for the [Eagle Eye Networks](https://een.com/) Video API v3.0, designed for Vue 3 applications.
4
4
 
5
- This repository is provided as-is without any warranty, functionality guarantee, or assurance of availability. This repository uses EEN services, but it is not associated with EEN.
5
+ ## Purpose
6
+
7
+ This toolkit aims to **simplify and accelerate web application development** for the EEN Video Platform. By providing ready-to-use composables, type-safe APIs, and secure authentication patterns, developers can focus on building features rather than wrestling with API integration details.
8
+
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.
6
10
 
7
11
  > **Note:** Work in progress - do not use in production yet.
8
12
 
9
- ## Installation
13
+ ## Key Features
14
+
15
+ - **Vue 3 Composables** - Reactive state with `useCurrentUser()`, `useUsers()`, `useUser()`
16
+ - **Plain Functions** - Framework-agnostic `getCurrentUser()`, `getUsers()`, `getUser()`
17
+ - **Secure OAuth** - Token management via proxy (refresh tokens never exposed to client)
18
+ - **Type-Safe** - Full TypeScript types from OpenAPI spec
19
+ - **Predictable Errors** - Always returns `{data, error}`, no exceptions thrown
20
+
21
+ ## OAuth Proxy Requirement
22
+
23
+ This toolkit's authentication is designed to work with [een-oauth-proxy](https://github.com/klaushofrichter/een-oauth-proxy), a secure OAuth proxy implementation that:
24
+
25
+ - Keeps refresh tokens server-side (never exposed to the browser)
26
+ - Handles token exchange and refresh automatically
27
+ - Provides session management via secure cookies
28
+
29
+ **Using a different proxy?** While other OAuth proxy implementations can be used, you may need to adapt the authentication flow. The toolkit expects specific proxy endpoints (`/proxy/getAccessToken`, `/proxy/refreshAccessToken`, `/proxy/revoke`).
30
+
31
+ ## Quick Start
32
+
33
+ ### 1. Install
10
34
 
11
35
  ```bash
12
36
  npm install een-api-toolkit
13
37
  ```
14
38
 
15
- **Development (from source):**
39
+ ### 2. Set Up OAuth Proxy
40
+
41
+ The toolkit requires an OAuth proxy to securely handle authentication. See [een-oauth-proxy](https://github.com/klaushofrichter/een-oauth-proxy) for a Cloudflare Worker implementation.
42
+
16
43
  ```bash
17
- git clone https://github.com/klaushofrichter/een-api-toolkit.git
18
- cd een-api-toolkit
44
+ # Clone and start the proxy
45
+ git clone https://github.com/klaushofrichter/een-oauth-proxy.git
46
+ cd een-oauth-proxy/proxy
19
47
  npm install
20
- npm run build
21
- npm link
22
-
23
- # In your project:
24
- npm link een-api-toolkit
48
+ npm run dev # Runs at http://localhost:8787
25
49
  ```
26
50
 
27
- ## Setup
51
+ > **Important:** Your app must run on `http://127.0.0.1:3333` (not `localhost`) and handle OAuth callbacks on the root path `/`. The EEN Identity Provider requires an exact URI match. See [Troubleshooting](./docs/USER-GUIDE.md#oauth-redirect-uri-requirements-critical) for details.
52
+
53
+ ### 3. Initialize in Your App
28
54
 
29
55
  ```typescript
30
56
  // main.ts
@@ -36,286 +62,138 @@ import App from './App.vue'
36
62
  const app = createApp(App)
37
63
  app.use(createPinia())
38
64
 
39
- // Initialize toolkit with proxy URL from environment
40
65
  initEenToolkit({
41
- proxyUrl: import.meta.env.VITE_PROXY_URL
66
+ proxyUrl: import.meta.env.VITE_PROXY_URL, // http://localhost:8787
67
+ clientId: import.meta.env.VITE_EEN_CLIENT_ID
42
68
  })
43
69
 
44
70
  app.mount('#app')
45
71
  ```
46
72
 
47
- ## Authentication
48
-
49
- The toolkit uses OAuth via a proxy server. Your app handles the redirect flow:
73
+ ### 4. Add Authentication
50
74
 
51
75
  ```typescript
52
- // Login.vue
53
76
  import { getAuthUrl, handleAuthCallback } from 'een-api-toolkit'
54
77
 
55
- // Redirect user to EEN login
78
+ // Redirect to EEN login
56
79
  const login = () => {
57
80
  window.location.href = getAuthUrl()
58
81
  }
59
82
 
60
- // Handle OAuth callback (after redirect back)
83
+ // Handle callback (after EEN redirects back)
61
84
  const onCallback = async (code: string, state: string) => {
62
- const { data, error } = await handleAuthCallback(code, state)
85
+ const { error } = await handleAuthCallback(code, state)
63
86
  if (error) {
64
87
  console.error('Auth failed:', error.message)
65
88
  return
66
89
  }
67
- // User is now authenticated, token stored in Pinia
90
+ // User is authenticated, token stored in Pinia
68
91
  router.push('/dashboard')
69
92
  }
70
93
  ```
71
94
 
72
- ## Usage
95
+ ### 5. Use the API
73
96
 
74
- ### Vue 3 Composables (Reactive)
97
+ **Vue Composables (reactive):**
75
98
 
76
99
  ```vue
77
100
  <script setup>
78
101
  import { useCurrentUser, useUsers } from 'een-api-toolkit'
79
102
 
80
- // Get current authenticated user
81
- const { user, loading, error, refresh } = useCurrentUser()
82
-
83
- // List all users with pagination
84
- const { users, loading: usersLoading, hasNextPage, fetchNextPage } = useUsers()
103
+ const { user, loading, error } = useCurrentUser()
104
+ const { users, hasNextPage, fetchNextPage } = useUsers({ pageSize: 10 })
85
105
  </script>
86
106
 
87
107
  <template>
88
108
  <div v-if="loading">Loading...</div>
89
- <div v-else-if="error">Error: {{ error.message }}</div>
109
+ <div v-else-if="error">{{ error.message }}</div>
90
110
  <div v-else>
91
111
  <h1>Welcome, {{ user.firstName }}</h1>
92
- <h2>All Users:</h2>
93
112
  <ul>
94
113
  <li v-for="u in users" :key="u.id">{{ u.email }}</li>
95
114
  </ul>
96
115
  <button v-if="hasNextPage" @click="fetchNextPage">Load More</button>
97
- <button @click="refresh">Refresh</button>
98
116
  </div>
99
117
  </template>
100
118
  ```
101
119
 
102
- ### Plain Functions (Framework-Agnostic)
120
+ **Plain Functions (framework-agnostic):**
103
121
 
104
122
  ```typescript
105
- import { getUsers, getCameras, getBridges } from 'een-api-toolkit'
123
+ import { getUsers, getCurrentUser } from 'een-api-toolkit'
106
124
 
107
- const fetchData = async () => {
108
- const { data: users, error } = await getUsers()
109
- if (error) {
110
- console.error(error.code, error.message)
111
- return
112
- }
113
- console.log('Users:', users)
125
+ // Get current authenticated user
126
+ const { data: currentUser, error: userError } = await getCurrentUser()
127
+ if (userError) {
128
+ console.error(userError.code, userError.message)
129
+ } else {
130
+ console.log('Current user:', currentUser.email)
114
131
  }
115
132
 
116
- // With pagination
117
- const { data, error } = await getCameras({
118
- pageSize: 50,
119
- pageToken: 'next-page-token'
120
- })
121
- ```
122
-
123
- ## Error Handling
124
-
125
- All functions return `{data, error}` objects - they never throw exceptions:
126
-
127
- ```typescript
128
- const { data, error } = await getCameras()
129
-
133
+ // Get list of users
134
+ const { data: users, error } = await getUsers()
130
135
  if (error) {
131
- switch (error.code) {
132
- case 'AUTH_REQUIRED':
133
- router.push('/login')
134
- break
135
- case 'API_ERROR':
136
- showNotification(`API Error: ${error.message}`)
137
- break
138
- case 'NETWORK_ERROR':
139
- showNotification('Network unavailable')
140
- break
141
- }
142
- return
136
+ console.error(error.code, error.message)
137
+ } else {
138
+ console.log('Users:', users.results)
143
139
  }
144
-
145
- // Safe to use data here
146
- console.log(data)
147
- ```
148
-
149
- ## Configuration
150
-
151
- ### Environment Variables
152
-
153
- Copy `.env.example` to `.env` and configure:
154
-
155
- ```env
156
- # EEN OAuth Client ID (required for authentication)
157
- VITE_EEN_CLIENT_ID=your-een-client-id
158
-
159
- # Test credentials for Playwright E2E tests
160
- TEST_USER=your-test-email@example.com
161
- TEST_PASSWORD=your-test-password
162
-
163
- # OAuth proxy URL (required for API calls)
164
- # Use local proxy for development to avoid Cloudflare rate limits
165
- VITE_PROXY_URL=http://localhost:8787
166
-
167
- # npm access token for publishing (Automation type from npmjs.com)
168
- NPM_TOKEN=npm_xxxxxxxxxxxx
169
-
170
- # Slack webhook for notifications
171
- SLACK_WEBHOOK=https://hooks.slack.com/services/xxx/xxx/xxx
172
-
173
- # Anthropic API key for Claude code review
174
- ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx
175
- ```
176
-
177
- ### GitHub Secrets
178
-
179
- GitHub Actions workflows require these secrets. Sync them from your `.env` file:
180
-
181
- ```bash
182
- # Preview what will be synced
183
- ./scripts/sync-secrets.sh --dry-run
184
-
185
- # Sync secrets to GitHub
186
- ./scripts/sync-secrets.sh
187
- ```
188
-
189
- Required secrets:
190
- | Secret | Purpose |
191
- |--------|---------|
192
- | `VITE_EEN_CLIENT_ID` | EEN OAuth client ID |
193
- | `TEST_USER` | E2E test user email |
194
- | `TEST_PASSWORD` | E2E test user password |
195
- | `VITE_PROXY_URL` | OAuth proxy URL |
196
- | `NPM_TOKEN` | npm publish token |
197
- | `SLACK_WEBHOOK` | Slack notifications |
198
- | `ANTHROPIC_API_KEY` | Claude code review |
199
-
200
- ### Local Proxy Server
201
-
202
- For development, run the local OAuth proxy to avoid Cloudflare rate limits:
203
-
204
- ```bash
205
- cd ../een-oauth-proxy/proxy
206
- npm run dev
207
- ```
208
-
209
- This starts the proxy at `http://localhost:8787`. The proxy must be running for authentication and API calls to work.
210
-
211
- ### Running E2E Tests
212
-
213
- E2E tests use Playwright to authenticate with EEN and test actual API calls.
214
-
215
- **Prerequisites:**
216
- 1. Ensure the OAuth proxy is running:
217
- ```bash
218
- ./scripts/restart-proxy.sh
219
- ```
220
-
221
- 2. Set test credentials in `.env`:
222
- ```env
223
- TEST_USER=your-test-email@example.com
224
- TEST_PASSWORD=your-test-password
225
- VITE_EEN_CLIENT_ID=your-client-id
226
- VITE_PROXY_URL=http://localhost:8787
227
- ```
228
-
229
- **Run tests:**
230
- ```bash
231
- npm run test:e2e # Run all E2E tests
232
- npm run test:e2e:ui # Run with Playwright UI
233
- ```
234
-
235
- **Token caching:** Auth tokens are cached in `e2e/.auth-state.json` (with 5-minute expiry buffer) to speed up repeated test runs. Delete this file to force re-authentication.
236
-
237
- **Security note:** The cached access token is stored in plaintext. This is acceptable for development/testing because:
238
- - The token is short-lived (~1 hour)
239
- - The file has restricted permissions (owner read/write only)
240
- - The file is excluded from git
241
-
242
- **Cleanup after tests:**
243
- ```bash
244
- ./scripts/cleanup-auth.sh # Revokes token and removes cache file
245
140
  ```
246
141
 
247
142
  ## Architecture
248
143
 
249
144
  ```
250
- ┌─────────────────────────────────────────────────────────┐
251
- Developer's Vue 3 App
252
- ┌─────────────────────────────────────────────────┐
253
- │ │ import from 'een-api-toolkit'
254
- │ │ ┌──────────────┐ ┌────────────────────┐
255
- │ │ │ Composables │ │ Plain Functions │
256
- │ │ │ useUsers() │ │ getUsers() │
257
- │ │ │ useCameras() │ │ getCameras()
258
- │ │ └──────────────┘ └────────────────────┘
259
- └─────────────────────────────────────────────────┘
260
- │ │
261
- ▼ │
262
- ┌─────────────────────┐
263
- │ Pinia Auth Store │
264
- │ (token, baseUrl) │
265
- └─────────────────────┘
266
- └─────────────────────────────────────────────────────────┘
267
-
268
-
269
- ┌─────────────────────┐
270
- │ OAuth Proxy │
271
- │ (Cloudflare Worker) │
272
- └─────────────────────┘
273
-
274
-
275
- ┌─────────────────────┐
276
- │ EEN API v3.0 │
277
- └─────────────────────┘
278
- ```
279
-
280
- ## Key Features
281
-
282
- - **No direct API credentials** - OAuth handled via proxy
283
- - **Reactive or plain** - Choose composables for Vue reactivity, plain functions for flexibility
284
- - **Predictable errors** - Always `{data, error}`, no try/catch needed
285
- - **Auto token refresh** - Handled internally by the toolkit
286
- - **Type-safe** - Full TypeScript types from OpenAPI spec
287
-
288
- ## Publishing (for maintainers)
289
-
290
- The package is published to npm automatically when changes are merged to the `production` branch.
291
-
292
- ### Version Management
293
- - Patch version auto-increments on each commit (via Husky pre-commit hook)
294
- - Minor/major versions updated manually in `package.json`
295
-
296
- ### Release Flow
297
- ```
298
- feature branch → develop → production → npm publish
299
- ```
300
-
301
- ### Manual Publish
302
- ```bash
303
- npm login
304
- npm run build
305
- npm publish
145
+ ┌──────────────────────────────────────────────────────────────────────┐
146
+ Your Vue 3 App
147
+ ┌────────────────────────────────────────────────────────────────┐
148
+ │ │ import from 'een-api-toolkit'
149
+ │ │ ┌──────────────┐ ┌────────────────────┐
150
+ │ │ │ Composables │ │ Plain Functions │
151
+ │ │ │ useUsers() │ │ getUsers() │
152
+ │ │ │ useUser() │ │ getUser()
153
+ │ │ └──────────────┘ └────────────────────┘
154
+ └────────────────────────────────────────────────────────────────┘
155
+ │ │
156
+
157
+ ┌─────────────────────┐ ┌─────────────────────┐
158
+ │ Pinia Auth Store │ API Calls with │ │
159
+ │ (token, baseUrl) │ Bearer Token │ │
160
+ └─────────────────────┘ └─────────────────────┘
161
+ └────────────────────│─────────────────────────────│───────────────────┘
162
+
163
+ Auth calls │ │ API calls
164
+ (login/refresh) │ │ (data)
165
+ ▼ ▼
166
+ ┌─────────────────────┐ ┌─────────────────────┐
167
+ │ OAuth Proxy │ │ EEN API v3.0 │
168
+ (local or cloud) │ │ │
169
+ └─────────────────────┘ └─────────────────────┘
170
+
171
+
172
+ ┌─────────────────────┐
173
+ │ EEN OAuth │
174
+ └─────────────────────┘
306
175
  ```
307
176
 
308
177
  ## Documentation
309
178
 
310
- - [AI-CONTEXT.md](./docs/AI-CONTEXT.md) - Comprehensive single-file reference for AI assistants
311
- - [API Reference](./docs/api/) - Auto-generated TypeDoc documentation
312
- - [Example App](./examples/vue-basic/) - Complete Vue 3 example application
179
+ | Document | Description |
180
+ |----------|-------------|
181
+ | **[User Guide](./docs/USER-GUIDE.md)** | Installation, proxy setup, configuration, building apps |
182
+ | **[Developer Guide](./docs/DEVELOPER-GUIDE.md)** | Architecture, testing, CI/CD, contributing |
183
+ | **[API Reference](./docs/api/)** | Auto-generated TypeDoc documentation |
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 |
313
186
 
314
- ## API Reference
187
+ ## External Resources
315
188
 
316
- - [EEN API 3.0 Documentation](https://developer.eagleeyenetworks.com/reference/using-the-api)
317
- - [EEN API 3.0 Spec](https://github.com/EENCloud/api-v3-documentation/tree/development/api/3.0)
189
+ - [EEN Developer Portal](https://developer.eagleeyenetworks.com/)
190
+ - [EEN API v3.0 Documentation](https://developer.eagleeyenetworks.com/reference/using-the-api)
191
+ - [een-oauth-proxy](https://github.com/klaushofrichter/een-oauth-proxy) - OAuth proxy server
318
192
 
319
193
  ## License
320
194
 
321
195
  MIT
196
+
197
+ ---
198
+
199
+ This repository is provided as-is without warranty. It uses EEN services but is not affiliated with Eagle Eye Networks.