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.
@@ -1,6 +1,6 @@
1
1
  # EEN API Toolkit - AI Reference
2
2
 
3
- > **Version:** 0.3.15
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
- // 24h should be active by default
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.14",
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-router": "^4.2.0",
19
- "chart.js": "^4.4.0",
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",