een-api-toolkit 0.3.47 → 0.3.51

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.
Files changed (44) hide show
  1. package/.claude/agents/een-events-agent.md +34 -1
  2. package/.claude/agents/een-jobs-agent.md +676 -0
  3. package/CHANGELOG.md +7 -8
  4. package/dist/index.cjs +3 -3
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.ts +1172 -28
  7. package/dist/index.js +796 -333
  8. package/dist/index.js.map +1 -1
  9. package/docs/AI-CONTEXT.md +22 -1
  10. package/docs/ai-reference/AI-AUTH.md +1 -1
  11. package/docs/ai-reference/AI-AUTOMATIONS.md +1 -1
  12. package/docs/ai-reference/AI-DEVICES.md +1 -1
  13. package/docs/ai-reference/AI-EVENTS.md +114 -4
  14. package/docs/ai-reference/AI-GROUPING.md +1 -1
  15. package/docs/ai-reference/AI-JOBS.md +1084 -0
  16. package/docs/ai-reference/AI-MEDIA.md +1 -1
  17. package/docs/ai-reference/AI-SETUP.md +1 -1
  18. package/docs/ai-reference/AI-USERS.md +1 -1
  19. package/examples/vue-events/src/components/EventsModal.vue +328 -3
  20. package/examples/vue-jobs/.env.example +11 -0
  21. package/examples/vue-jobs/README.md +245 -0
  22. package/examples/vue-jobs/e2e/app.spec.ts +79 -0
  23. package/examples/vue-jobs/e2e/auth.spec.ts +382 -0
  24. package/examples/vue-jobs/e2e/delete-features.spec.ts +564 -0
  25. package/examples/vue-jobs/e2e/timelapse.spec.ts +361 -0
  26. package/examples/vue-jobs/index.html +13 -0
  27. package/examples/vue-jobs/package-lock.json +1722 -0
  28. package/examples/vue-jobs/package.json +28 -0
  29. package/examples/vue-jobs/playwright.config.ts +47 -0
  30. package/examples/vue-jobs/src/App.vue +154 -0
  31. package/examples/vue-jobs/src/main.ts +25 -0
  32. package/examples/vue-jobs/src/router/index.ts +82 -0
  33. package/examples/vue-jobs/src/views/Callback.vue +76 -0
  34. package/examples/vue-jobs/src/views/CreateExport.vue +284 -0
  35. package/examples/vue-jobs/src/views/Files.vue +424 -0
  36. package/examples/vue-jobs/src/views/Home.vue +195 -0
  37. package/examples/vue-jobs/src/views/JobDetail.vue +392 -0
  38. package/examples/vue-jobs/src/views/Jobs.vue +297 -0
  39. package/examples/vue-jobs/src/views/Login.vue +33 -0
  40. package/examples/vue-jobs/src/views/Logout.vue +59 -0
  41. package/examples/vue-jobs/src/vite-env.d.ts +1 -0
  42. package/examples/vue-jobs/tsconfig.json +25 -0
  43. package/examples/vue-jobs/vite.config.ts +12 -0
  44. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # EEN API Toolkit - AI Reference
2
2
 
3
- > **Version:** 0.3.47
3
+ > **Version:** 0.3.51
4
4
  >
5
5
  > This documentation is optimized for AI assistants. It provides focused, domain-specific
6
6
  > references to help you understand and use the een-api-toolkit efficiently.
@@ -21,6 +21,7 @@
21
21
  | Live video, images, HLS playback | [AI-MEDIA.md](./ai-reference/AI-MEDIA.md) | ~4K |
22
22
  | Events, alerts, metrics, SSE | [AI-EVENTS.md](./ai-reference/AI-EVENTS.md) | ~3.5K |
23
23
  | Automation rules, alert actions | [AI-AUTOMATIONS.md](./ai-reference/AI-AUTOMATIONS.md) | ~4K |
24
+ | Jobs, exports, files, downloads | [AI-JOBS.md](./ai-reference/AI-JOBS.md) | ~3.5K |
24
25
 
25
26
  ## Specialized Agents
26
27
 
@@ -36,6 +37,7 @@ Specialized agents are available in `.claude/agents/` for domain-specific tasks:
36
37
  | `een-media-agent` | Live video, camera previews, HLS playback, recorded images |
37
38
  | `een-events-agent` | Events, alerts, metrics, real-time SSE subscriptions |
38
39
  | `een-automations-agent` | Automation rules, alert condition rules, alert actions |
40
+ | `een-jobs-agent` | Jobs, exports, files, downloads, video export workflows |
39
41
 
40
42
  **How to Use Agents:**
41
43
 
@@ -76,6 +78,7 @@ Then follow the context files and instructions specified within.
76
78
  | [vue-alerts-metrics](../examples/vue-alerts-metrics/) | Event metrics and alerts | `src/components/MetricsChart.vue` |
77
79
  | [vue-event-subscriptions](../examples/vue-event-subscriptions/) | Real-time SSE streaming | `src/views/LiveEvents.vue` |
78
80
  | [vue-automations](../examples/vue-automations/) | Automation rules listing | `src/views/Automations.vue` |
81
+ | [vue-jobs](../examples/vue-jobs/) | Jobs, exports, file downloads | `src/views/Jobs.vue` |
79
82
 
80
83
  ---
81
84
 
@@ -180,6 +183,24 @@ Then follow the context files and instructions specified within.
180
183
  | `listAlertActions(params?)` | List alert actions |
181
184
  | `getAlertAction(id)` | Get a specific alert action |
182
185
 
186
+ ### Exports & Jobs
187
+ | Function | Purpose |
188
+ |----------|---------|
189
+ | `createExportJob(params)` | Create video/timelapse export job |
190
+ | `listJobs(params?)` | List jobs with filtering |
191
+ | `getJob(jobId)` | Get a specific job |
192
+
193
+ ### Files & Downloads
194
+ | Function | Purpose |
195
+ |----------|---------|
196
+ | `listFiles(params?)` | List available files |
197
+ | `getFile(fileId)` | Get a specific file |
198
+ | `addFile(params)` | Add a new file |
199
+ | `downloadFile(fileId)` | Download file content |
200
+ | `listDownloads(params?)` | List available downloads |
201
+ | `getDownload(downloadId)` | Get a specific download |
202
+ | `downloadDownload(downloadId)` | Download from downloads endpoint |
203
+
183
204
  ### Utilities
184
205
  | Function | Purpose |
185
206
  |----------|---------|
@@ -1,6 +1,6 @@
1
1
  # Authentication - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.47
3
+ > **Version:** 0.3.51
4
4
  >
5
5
  > OAuth flow implementation, token management, and session handling.
6
6
  > Load this document when implementing login, logout, or auth guards.
@@ -1,6 +1,6 @@
1
1
  # Automations API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.47
3
+ > **Version:** 0.3.51
4
4
  >
5
5
  > Complete reference for automation rules and alert actions.
6
6
  > Load this document when working with automated alert workflows.
@@ -1,6 +1,6 @@
1
1
  # Cameras & Bridges API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.47
3
+ > **Version:** 0.3.51
4
4
  >
5
5
  > Complete reference for camera and bridge management.
6
6
  > Load this document when working with devices.
@@ -1,6 +1,6 @@
1
1
  # Events, Alerts & Real-Time Streaming - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.47
3
+ > **Version:** 0.3.51
4
4
  >
5
5
  > Complete reference for events, alerts, metrics, and SSE subscriptions.
6
6
  > Load this document when implementing event-driven features.
@@ -292,6 +292,7 @@ import {
292
292
  listEventFieldValues,
293
293
  listEventTypes,
294
294
  getRecordedImage,
295
+ getEvent,
295
296
  type Camera,
296
297
  type Event,
297
298
  type EventType,
@@ -374,6 +375,13 @@ const imageLoadingIds = ref<Set<string>>(new Set()) // Track which images are cu
374
375
  const boundingBoxCache = ref<Map<string, BoundingBox[]>>(new Map()) // Cache bounding boxes per event
375
376
  const enlargedEventId = ref<string | null>(null)
376
377
 
378
+ // JSON viewer state
379
+ const jsonViewerEventId = ref<string | null>(null)
380
+ const jsonViewerFullEvent = ref<Event | null>(null)
381
+ const jsonViewerLoading = ref(false)
382
+ const jsonViewerError = ref<string | null>(null)
383
+ const copySuccess = ref(false)
384
+
377
385
  // Lightbox media state
378
386
  const showVideo = ref(false)
379
387
  const hdImageUrl = ref<string | null>(null)
@@ -396,6 +404,21 @@ const enlargedBoundingBoxes = computed(() => {
396
404
  if (!enlargedEvent.value) return []
397
405
  return getBoundingBoxes(enlargedEvent.value)
398
406
  })
407
+ const jsonViewerEvent = computed(() => {
408
+ if (!jsonViewerEventId.value) return null
409
+ return events.value.find(e => e.id === jsonViewerEventId.value) || null
410
+ })
411
+ const jsonViewerContent = computed(() => {
412
+ // Use full event if loaded, otherwise fall back to list event
413
+ const eventToShow = jsonViewerFullEvent.value || jsonViewerEvent.value
414
+ if (!eventToShow) return ''
415
+ try {
416
+ return JSON.stringify(eventToShow, null, 2)
417
+ } catch (err) {
418
+ // Safely handle any JSON serialization errors
419
+ return `Error serializing event data: ${String(err)}`
420
+ }
421
+ })
399
422
 
400
423
  // Get start timestamp based on time range
401
424
  function getStartTimestamp(range: TimeRange): string {
@@ -698,6 +721,77 @@ function closeEnlargedImage() {
698
721
  resetVideo()
699
722
  }
700
723
 
724
+ // Open JSON viewer and fetch full event details
725
+ async function openJsonViewer(eventId: string) {
726
+ jsonViewerEventId.value = eventId
727
+ jsonViewerFullEvent.value = null
728
+ jsonViewerError.value = null
729
+ copySuccess.value = false
730
+
731
+ // Find the event in the list to get its dataSchemas
732
+ const listEvent = events.value.find(e => e.id === eventId)
733
+ if (!listEvent) {
734
+ jsonViewerError.value = 'Event not found in current list'
735
+ return
736
+ }
737
+
738
+ // Build include array from dataSchemas (prefix with "data.")
739
+ const includes = listEvent.dataSchemas?.map(schema => `data.${schema}`) || []
740
+
741
+ if (includes.length === 0) {
742
+ // No additional data to fetch, use the list event as-is
743
+ return
744
+ }
745
+
746
+ // Fetch full event details with all data schemas
747
+ jsonViewerLoading.value = true
748
+ const { data, error } = await getEvent(eventId, { include: includes })
749
+ jsonViewerLoading.value = false
750
+
751
+ if (error) {
752
+ jsonViewerError.value = error.message
753
+ return
754
+ }
755
+
756
+ if (data) {
757
+ jsonViewerFullEvent.value = data
758
+ }
759
+ }
760
+
761
+ // Close JSON viewer
762
+ function closeJsonViewer() {
763
+ jsonViewerEventId.value = null
764
+ jsonViewerFullEvent.value = null
765
+ jsonViewerError.value = null
766
+ copySuccess.value = false
767
+ }
768
+
769
+ // Copy JSON to clipboard
770
+ async function copyJsonToClipboard() {
771
+ if (!jsonViewerContent.value) return
772
+ try {
773
+ await navigator.clipboard.writeText(jsonViewerContent.value)
774
+ copySuccess.value = true
775
+ setTimeout(() => {
776
+ copySuccess.value = false
777
+ }, 2000)
778
+ } catch {
779
+ // Fallback for older browsers
780
+ const textarea = document.createElement('textarea')
781
+ textarea.value = jsonViewerContent.value
782
+ textarea.style.position = 'fixed'
783
+ textarea.style.opacity = '0'
784
+ document.body.appendChild(textarea)
785
+ textarea.select()
786
+ document.execCommand('copy')
787
+ document.body.removeChild(textarea)
788
+ copySuccess.value = true
789
+ setTimeout(() => {
790
+ copySuccess.value = false
791
+ }, 2000)
792
+ }
793
+ }
794
+
701
795
  // Switch to preview mode
702
796
  function showPreview() {
703
797
  currentMediaType.value = 'preview'
@@ -747,8 +841,12 @@ async function showVideoPlayer() {
747
841
 
748
842
  // Handle keyboard events for accessibility
749
843
  function handleKeydown(event: KeyboardEvent) {
750
- if (event.key === 'Escape' && enlargedEventId.value) {
751
- closeEnlargedImage()
844
+ if (event.key === 'Escape') {
845
+ if (jsonViewerEventId.value) {
846
+ closeJsonViewer()
847
+ } else if (enlargedEventId.value) {
848
+ closeEnlargedImage()
849
+ }
752
850
  }
753
851
  }
754
852
 
@@ -759,6 +857,9 @@ onMounted(() => {
759
857
 
760
858
  onUnmounted(() => {
761
859
  window.removeEventListener('keydown', handleKeydown)
860
+ // Clean up JSON viewer state to prevent memory leaks
861
+ jsonViewerFullEvent.value = null
862
+ jsonViewerEventId.value = null
762
863
  })
763
864
 
764
865
  // Watch for modal open/close
@@ -784,6 +885,7 @@ watch(() => props.isOpen, async (isOpen) => {
784
885
  boundingBoxCache.value.clear()
785
886
  events.value = []
786
887
  enlargedEventId.value = null
888
+ jsonViewerEventId.value = null
787
889
  }
788
890
  }, { immediate: true })
789
891
 
@@ -883,7 +985,15 @@ watch([timeRange, selectedEventTypes], () => {
883
985
  </div>
884
986
  </div>
885
987
  <div class="event-info">
886
- <div class="event-type">{{ getEventTypeName(event.type) }}</div>
988
+ <div class="event-type-row">
989
+ <span class="event-type">{{ getEventTypeName(event.type) }}</span>
990
+ <button
991
+ class="json-button"
992
+ @click="openJsonViewer(event.id)"
993
+ title="View JSON data"
994
+ data-testid="json-button"
995
+ >{ }</button>
996
+ </div>
887
997
  <div class="event-time">{{ formatTimestamp(event.startTimestamp) }}</div>
888
998
  <div v-if="getBoundingBoxCount(event) > 0" class="event-detections" data-testid="event-detections">
889
999
  {{ getBoundingBoxCount(event) }} detection{{ getBoundingBoxCount(event) !== 1 ? 's' : '' }}
@@ -1,6 +1,6 @@
1
1
  # Layouts API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.47
3
+ > **Version:** 0.3.51
4
4
  >
5
5
  > Complete reference for layout management (camera grouping).
6
6
  > Load this document when working with layouts.