een-api-toolkit 0.3.15 → 0.3.16
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 +11 -5
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/docs/AI-CONTEXT.md +133 -1
- package/examples/vue-alerts-metrics/e2e/auth.spec.ts +8 -1
- package/examples/vue-alerts-metrics/package-lock.json +8 -1
- package/examples/vue-alerts-metrics/package.json +4 -3
- package/examples/vue-alerts-metrics/src/components/AlertsList.vue +567 -16
- package/examples/vue-alerts-metrics/src/components/CameraSelector.vue +16 -6
- package/examples/vue-alerts-metrics/src/components/MetricsChart.vue +23 -9
- package/examples/vue-alerts-metrics/src/components/NotificationsList.vue +579 -17
- package/examples/vue-alerts-metrics/src/components/TimeRangeSelector.vue +197 -12
- package/examples/vue-alerts-metrics/src/composables/useHlsPlayer.ts +285 -0
- package/examples/vue-alerts-metrics/src/views/Dashboard.vue +31 -9
- package/examples/vue-alerts-metrics/src/views/Home.vue +56 -7
- package/package.json +1 -1
package/docs/AI-CONTEXT.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# EEN API Toolkit - AI Reference
|
|
2
2
|
|
|
3
|
-
> **Version:** 0.3.
|
|
3
|
+
> **Version:** 0.3.16
|
|
4
4
|
>
|
|
5
5
|
> This file is optimized for AI assistants. It contains all API signatures,
|
|
6
6
|
> types, and usage patterns in a single, parseable document.
|
|
@@ -293,6 +293,12 @@ Complete Vue 3 applications demonstrating toolkit features:
|
|
|
293
293
|
| `listNotifications(params?)` | List notifications with filters | `Result<PaginatedResult<Notification>>` |
|
|
294
294
|
| `getNotification(id)` | Get a specific notification by ID | `Result<Notification>` |
|
|
295
295
|
|
|
296
|
+
### Utility Functions
|
|
297
|
+
|
|
298
|
+
| Function | Purpose | Returns |
|
|
299
|
+
|----------|---------|---------|
|
|
300
|
+
| `formatTimestamp(timestamp)` | Convert ISO timestamp from Z to +00:00 format (required by EEN API) | `string` |
|
|
301
|
+
|
|
296
302
|
---
|
|
297
303
|
|
|
298
304
|
## Core Types
|
|
@@ -1275,6 +1281,40 @@ console.log('Session URL:', data.url)
|
|
|
1275
1281
|
|
|
1276
1282
|
---
|
|
1277
1283
|
|
|
1284
|
+
## Utilities
|
|
1285
|
+
|
|
1286
|
+
### formatTimestamp
|
|
1287
|
+
|
|
1288
|
+
Converts ISO 8601 timestamps from `Z` (Zulu/UTC) format to `+00:00` format, as required by the EEN API.
|
|
1289
|
+
|
|
1290
|
+
**Why this is needed:** JavaScript's `Date.toISOString()` returns timestamps with a `Z` suffix (e.g., `2025-01-15T22:30:00.000Z`), but the EEN API requires the `+00:00` format (e.g., `2025-01-15T22:30:00.000+00:00`).
|
|
1291
|
+
|
|
1292
|
+
```typescript
|
|
1293
|
+
import { formatTimestamp } from 'een-api-toolkit'
|
|
1294
|
+
|
|
1295
|
+
// Convert Z format to +00:00 format
|
|
1296
|
+
formatTimestamp('2025-01-15T22:30:00.000Z')
|
|
1297
|
+
// Returns: '2025-01-15T22:30:00.000+00:00'
|
|
1298
|
+
|
|
1299
|
+
// Already in +00:00 format - returns unchanged
|
|
1300
|
+
formatTimestamp('2025-01-15T22:30:00.000+00:00')
|
|
1301
|
+
// Returns: '2025-01-15T22:30:00.000+00:00'
|
|
1302
|
+
|
|
1303
|
+
// Common usage with Date objects
|
|
1304
|
+
const now = new Date()
|
|
1305
|
+
const apiTimestamp = formatTimestamp(now.toISOString())
|
|
1306
|
+
// Returns timestamp in EEN API format
|
|
1307
|
+
```
|
|
1308
|
+
|
|
1309
|
+
**When to use:**
|
|
1310
|
+
- When displaying timestamps that match the exact format used in API calls (e.g., for debugging)
|
|
1311
|
+
- When making direct API calls outside of the toolkit
|
|
1312
|
+
- When building custom timestamp display components
|
|
1313
|
+
|
|
1314
|
+
**Note:** The toolkit's API functions (`listAlerts`, `getEventMetrics`, `listNotifications`, `listEvents`, etc.) automatically apply `formatTimestamp` internally, so you don't need to pre-format timestamps when using these functions.
|
|
1315
|
+
|
|
1316
|
+
---
|
|
1317
|
+
|
|
1278
1318
|
## Live Video Streaming
|
|
1279
1319
|
|
|
1280
1320
|
The EEN API Toolkit supports two methods for displaying live video from cameras:
|
|
@@ -1525,6 +1565,98 @@ video {
|
|
|
1525
1565
|
|
|
1526
1566
|
---
|
|
1527
1567
|
|
|
1568
|
+
## HLS Video Playback Troubleshooting
|
|
1569
|
+
|
|
1570
|
+
For detailed troubleshooting, see the [HLS Video Troubleshooting Guide](./guides/HLS-VIDEO-TROUBLESHOOTING.md).
|
|
1571
|
+
|
|
1572
|
+
### Overview
|
|
1573
|
+
|
|
1574
|
+
HLS video playback from the EEN API requires:
|
|
1575
|
+
|
|
1576
|
+
1. **Initialize media session** - `initMediaSession()`
|
|
1577
|
+
2. **Find recording intervals** - `listMedia()` with `include: ['hlsUrl']`
|
|
1578
|
+
3. **Extract HLS URL** - From interval containing target timestamp
|
|
1579
|
+
4. **Configure HLS.js with auth** - Bearer token in Authorization header
|
|
1580
|
+
|
|
1581
|
+
### Key Requirements
|
|
1582
|
+
|
|
1583
|
+
| Requirement | Details |
|
|
1584
|
+
|-------------|---------|
|
|
1585
|
+
| Feed Type | HLS only available for `main` feeds, not `preview` |
|
|
1586
|
+
| Timestamp Format | Use `formatTimestamp()` to convert `Z` to `+00:00` |
|
|
1587
|
+
| Authentication | HLS.js requires `xhr.setRequestHeader('Authorization', `Bearer ${token}`)` |
|
|
1588
|
+
| Recording Coverage | Target timestamp must fall within a recording interval |
|
|
1589
|
+
|
|
1590
|
+
### Common Issues
|
|
1591
|
+
|
|
1592
|
+
#### 401 Unauthorized
|
|
1593
|
+
|
|
1594
|
+
**Cause:** Using `withCredentials: true` instead of Authorization header.
|
|
1595
|
+
|
|
1596
|
+
```typescript
|
|
1597
|
+
// WRONG
|
|
1598
|
+
const hls = new Hls({
|
|
1599
|
+
xhrSetup: (xhr) => { xhr.withCredentials = true }
|
|
1600
|
+
})
|
|
1601
|
+
|
|
1602
|
+
// CORRECT
|
|
1603
|
+
import { useAuthStore } from 'een-api-toolkit'
|
|
1604
|
+
const authStore = useAuthStore()
|
|
1605
|
+
|
|
1606
|
+
const hls = new Hls({
|
|
1607
|
+
xhrSetup: (xhr) => {
|
|
1608
|
+
xhr.setRequestHeader('Authorization', `Bearer ${authStore.token}`)
|
|
1609
|
+
}
|
|
1610
|
+
})
|
|
1611
|
+
```
|
|
1612
|
+
|
|
1613
|
+
#### No Video Available for Timestamp
|
|
1614
|
+
|
|
1615
|
+
**Cause:** Search range too narrow or using wrong feed type.
|
|
1616
|
+
|
|
1617
|
+
```typescript
|
|
1618
|
+
import { listMedia, formatTimestamp } from 'een-api-toolkit'
|
|
1619
|
+
|
|
1620
|
+
const targetTime = new Date(alertTimestamp)
|
|
1621
|
+
const searchStart = new Date(targetTime.getTime() - 60 * 60 * 1000) // 1 hour before
|
|
1622
|
+
const searchEnd = new Date(targetTime.getTime() + 60 * 60 * 1000) // 1 hour after
|
|
1623
|
+
|
|
1624
|
+
const result = await listMedia({
|
|
1625
|
+
deviceId: cameraId,
|
|
1626
|
+
type: 'main', // MUST be 'main' for HLS
|
|
1627
|
+
mediaType: 'video',
|
|
1628
|
+
startTimestamp: formatTimestamp(searchStart.toISOString()),
|
|
1629
|
+
endTimestamp: formatTimestamp(searchEnd.toISOString()),
|
|
1630
|
+
include: ['hlsUrl'] // MUST include 'hlsUrl'
|
|
1631
|
+
})
|
|
1632
|
+
|
|
1633
|
+
// Find interval containing target timestamp
|
|
1634
|
+
const intervals = result.data?.results ?? []
|
|
1635
|
+
const targetTimeMs = targetTime.getTime()
|
|
1636
|
+
|
|
1637
|
+
const matchingInterval = intervals.find(i => {
|
|
1638
|
+
if (!i.hlsUrl) return false
|
|
1639
|
+
const start = new Date(i.startTimestamp).getTime()
|
|
1640
|
+
const end = new Date(i.endTimestamp).getTime()
|
|
1641
|
+
return targetTimeMs >= start && targetTimeMs <= end
|
|
1642
|
+
})
|
|
1643
|
+
```
|
|
1644
|
+
|
|
1645
|
+
#### Timestamp Format Error
|
|
1646
|
+
|
|
1647
|
+
**Cause:** Using `Z` suffix instead of `+00:00`.
|
|
1648
|
+
|
|
1649
|
+
```typescript
|
|
1650
|
+
// WRONG
|
|
1651
|
+
const timestamp = new Date().toISOString() // "2025-01-15T22:30:00.000Z"
|
|
1652
|
+
|
|
1653
|
+
// CORRECT
|
|
1654
|
+
import { formatTimestamp } from 'een-api-toolkit'
|
|
1655
|
+
const timestamp = formatTimestamp(new Date().toISOString()) // "2025-01-15T22:30:00.000+00:00"
|
|
1656
|
+
```
|
|
1657
|
+
|
|
1658
|
+
---
|
|
1659
|
+
|
|
1528
1660
|
## Common Patterns
|
|
1529
1661
|
|
|
1530
1662
|
### Error Handling
|
|
@@ -283,14 +283,21 @@ test.describe('Vue Alerts & Metrics Example - Auth', () => {
|
|
|
283
283
|
await expect(page.locator('[data-testid="dashboard-container"]')).toBeVisible({ timeout: TIMEOUTS.UI_UPDATE })
|
|
284
284
|
|
|
285
285
|
// Test time range buttons
|
|
286
|
+
const buttonNone = page.locator('[data-testid="time-range-none"]')
|
|
286
287
|
const button1h = page.locator('[data-testid="time-range-1h"]')
|
|
287
288
|
const button24h = page.locator('[data-testid="time-range-24h"]')
|
|
288
289
|
|
|
290
|
+
await expect(buttonNone).toBeVisible()
|
|
289
291
|
await expect(button1h).toBeVisible()
|
|
290
292
|
await expect(button24h).toBeVisible()
|
|
291
293
|
|
|
292
|
-
//
|
|
294
|
+
// 'None' should be active by default
|
|
295
|
+
await expect(buttonNone).toHaveClass(/active/)
|
|
296
|
+
|
|
297
|
+
// Click 24h and verify it becomes active
|
|
298
|
+
await button24h.click()
|
|
293
299
|
await expect(button24h).toHaveClass(/active/)
|
|
300
|
+
await expect(buttonNone).not.toHaveClass(/active/)
|
|
294
301
|
|
|
295
302
|
// Click 1h and verify it becomes active
|
|
296
303
|
await button1h.click()
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"chart.js": "^4.4.0",
|
|
12
12
|
"een-api-toolkit": "file:../..",
|
|
13
|
+
"hls.js": "^1.6.15",
|
|
13
14
|
"pinia": "^3.0.4",
|
|
14
15
|
"vue": "^3.4.0",
|
|
15
16
|
"vue-chartjs": "^5.3.0",
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
}
|
|
26
27
|
},
|
|
27
28
|
"../..": {
|
|
28
|
-
"version": "0.3.
|
|
29
|
+
"version": "0.3.15",
|
|
29
30
|
"license": "MIT",
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@eslint/js": "^9.39.2",
|
|
@@ -1296,6 +1297,12 @@
|
|
|
1296
1297
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
|
1297
1298
|
}
|
|
1298
1299
|
},
|
|
1300
|
+
"node_modules/hls.js": {
|
|
1301
|
+
"version": "1.6.15",
|
|
1302
|
+
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.15.tgz",
|
|
1303
|
+
"integrity": "sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==",
|
|
1304
|
+
"license": "Apache-2.0"
|
|
1305
|
+
},
|
|
1299
1306
|
"node_modules/hookable": {
|
|
1300
1307
|
"version": "5.5.3",
|
|
1301
1308
|
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
"test:e2e:ui": "playwright test --ui"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
+
"chart.js": "^4.4.0",
|
|
15
16
|
"een-api-toolkit": "file:../..",
|
|
17
|
+
"hls.js": "^1.6.15",
|
|
16
18
|
"pinia": "^3.0.4",
|
|
17
19
|
"vue": "^3.4.0",
|
|
18
|
-
"vue-
|
|
19
|
-
"
|
|
20
|
-
"vue-chartjs": "^5.3.0"
|
|
20
|
+
"vue-chartjs": "^5.3.0",
|
|
21
|
+
"vue-router": "^4.2.0"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@playwright/test": "^1.57.0",
|