@camstack/addon-smtp-nodemailer 1.1.22 → 1.1.24

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.
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  }) : target, mod));
37
37
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
38
  //#endregion
39
- //#region ../types/dist/event-category-CFZs3jI4.mjs
39
+ //#region ../types/dist/event-category-H4AVePnn.mjs
40
40
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
41
41
  EventCategory["SystemBoot"] = "system.boot";
42
42
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -186,6 +186,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
186
186
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
187
187
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
188
188
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
189
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
190
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
191
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
189
192
  EventCategory["DetectionEvent"] = "detection.event";
190
193
  EventCategory["SessionTrackNew"] = "session.track.new";
191
194
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -7255,6 +7258,24 @@ var RecordingRetentionSchema = object({
7255
7258
  maxSizeGb: number().min(0).optional()
7256
7259
  });
7257
7260
  /**
7261
+ * Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
7262
+ * sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
7263
+ * previews at. Five graduated steps; absent on a config = `standard` (the
7264
+ * shipped default, matching `sheet-geometry`/`sheet-composer`).
7265
+ *
7266
+ * Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
7267
+ * Each window's index sidecar carries its own tile dims, so a camera whose
7268
+ * preset changed over time renders every historical window at the dims it was
7269
+ * written with.
7270
+ */
7271
+ var ScrubThumbnailPresetSchema = _enum([
7272
+ "minimal",
7273
+ "low",
7274
+ "standard",
7275
+ "high",
7276
+ "max"
7277
+ ]);
7278
+ /**
7258
7279
  * The full per-camera recording intent — the wire shape of a RecordingTarget.
7259
7280
  *
7260
7281
  * `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
@@ -7291,7 +7312,14 @@ var RecordingConfigSchema = object({
7291
7312
  * derived into bands once via `migrateConfigToBands`.
7292
7313
  */
7293
7314
  bands: array(RecordingBandSchema).optional(),
7294
- retention: RecordingRetentionSchema.optional()
7315
+ retention: RecordingRetentionSchema.optional(),
7316
+ /**
7317
+ * Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
7318
+ * timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
7319
+ * windows only — existing sheets are immutable, and each window's index
7320
+ * carries its own tile dims so mixed-preset history renders correctly.
7321
+ */
7322
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7295
7323
  });
7296
7324
  /**
7297
7325
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
@@ -9850,7 +9878,7 @@ object({
9850
9878
  deviceId: number(),
9851
9879
  timestamp: number()
9852
9880
  });
9853
- DeviceType.Button;
9881
+ DeviceType.Button, DeviceType.Camera;
9854
9882
  /**
9855
9883
  * Enum-state sensor — a string value picked from a finite option set.
9856
9884
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14220,6 +14248,14 @@ var ConfigEntrySchema = object({
14220
14248
  value: unknown(),
14221
14249
  description: string().optional()
14222
14250
  });
14251
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14252
+ /** One resolved linked device — the compact projection consumers need. */
14253
+ var LinkedDeviceSchema = object({
14254
+ deviceId: number(),
14255
+ name: string(),
14256
+ location: string().nullable(),
14257
+ features: array(string())
14258
+ });
14223
14259
  var SavedDeviceRowSchema = object({
14224
14260
  /** Numeric id reserved at allocateDeviceId time. */
14225
14261
  id: number(),
@@ -14441,7 +14477,10 @@ method(object({
14441
14477
  }), _void(), {
14442
14478
  kind: "mutation",
14443
14479
  auth: "admin"
14444
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14480
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14481
+ mode: DeviceLinkModeSchema,
14482
+ devices: array(LinkedDeviceSchema)
14483
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14445
14484
  deviceId: number(),
14446
14485
  values: record(string(), unknown())
14447
14486
  }), object({ success: literal(true) }), {
@@ -15710,6 +15749,61 @@ var EventKindSchema = _enum([
15710
15749
  "object",
15711
15750
  "audio"
15712
15751
  ]);
15752
+ /**
15753
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15754
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15755
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15756
+ */
15757
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15758
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15759
+ var EventKindIconSchema = _enum([
15760
+ "motion",
15761
+ "audio",
15762
+ "person",
15763
+ "vehicle",
15764
+ "animal",
15765
+ "door",
15766
+ "pir",
15767
+ "smoke",
15768
+ "water",
15769
+ "button",
15770
+ "generic"
15771
+ ]);
15772
+ var EventKindCategorySchema = _enum([
15773
+ "motion",
15774
+ "audio",
15775
+ "detection",
15776
+ "sensor",
15777
+ "custom"
15778
+ ]);
15779
+ var EventKindDescriptorSchema = object({
15780
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15781
+ kind: string(),
15782
+ label: string(),
15783
+ /** Hex color for timeline/legend rendering. */
15784
+ color: string(),
15785
+ icon: EventKindIconSchema,
15786
+ category: EventKindCategorySchema,
15787
+ /** Which cap + device contributes this kind. For built-ins the camera
15788
+ * itself; for sensor kinds the LINKED source device. */
15789
+ source: object({
15790
+ capName: string(),
15791
+ deviceId: number()
15792
+ })
15793
+ });
15794
+ var SensorEventSchema = object({
15795
+ id: string(),
15796
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15797
+ * yields N rows, one per camera). */
15798
+ deviceId: number(),
15799
+ /** The linked sensor device whose state changed. */
15800
+ sourceDeviceId: number(),
15801
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15802
+ kind: string(),
15803
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15804
+ value: record(string(), unknown()).nullable(),
15805
+ timestamp: number()
15806
+ });
15713
15807
  var TrackPositionSchema = object({
15714
15808
  x: number(),
15715
15809
  y: number(),
@@ -15723,6 +15817,30 @@ var TrackSnapshotSchema = object({
15723
15817
  mediaKey: string()
15724
15818
  });
15725
15819
  /**
15820
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15821
+ * divided by the track's detection-frame dims), computed at persist time.
15822
+ * Absent when the frame dims were unknown when the track was persisted
15823
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15824
+ */
15825
+ var TrackEnvelopeSchema = object({
15826
+ minX: number(),
15827
+ minY: number(),
15828
+ maxX: number(),
15829
+ maxY: number()
15830
+ });
15831
+ /**
15832
+ * Row projection for track list queries. `full` (default) returns the
15833
+ * complete Track including the frame-rate `positions[]` history and the
15834
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15835
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15836
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15837
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15838
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15839
+ * `getTrack`. Mirrors the event-store `projection` convention
15840
+ * (`getObjectEvents` et al.).
15841
+ */
15842
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15843
+ /**
15726
15844
  * One audio-classification label heard on the track's camera while the
15727
15845
  * track was alive, aggregated per label. An "episode" is one persisted
15728
15846
  * audio event (the confident-classification path: score ≥ the device's
@@ -15773,7 +15891,11 @@ var TrackSchema = object({
15773
15891
  /** Audio-classification labels heard on the camera during the track's
15774
15892
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15775
15893
  * Absent on legacy rows / tracks with no confident audio. */
15776
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15894
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15895
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15896
+ * Populated from the persisted envelope columns on historical reads;
15897
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15898
+ envelope: TrackEnvelopeSchema.optional()
15777
15899
  });
15778
15900
  var BaseEventFields = {
15779
15901
  id: string(),
@@ -15883,11 +16005,13 @@ var MediaFileSchema = object({
15883
16005
  sizeBytes: number(),
15884
16006
  timestamp: number()
15885
16007
  });
16008
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16009
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15886
16010
  var DeviceEventQueryInput = object({
15887
16011
  deviceId: number(),
15888
16012
  since: number().optional(),
15889
16013
  until: number().optional(),
15890
- limit: number().int().min(1).max(5e3).default(1e3),
16014
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15891
16015
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15892
16016
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15893
16017
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -15895,6 +16019,27 @@ var DeviceEventQueryInput = object({
15895
16019
  projection: _enum(["full", "slim"]).optional()
15896
16020
  });
15897
16021
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16022
+ var RecentTracksQueryInput = object({
16023
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16024
+ deviceIds: array(number()),
16025
+ /** Window lower bound on `lastSeen` (inclusive). */
16026
+ since: number().optional(),
16027
+ /** Window upper bound on `lastSeen` (inclusive). */
16028
+ until: number().optional(),
16029
+ /** Page size. Default 200, max 1000. */
16030
+ limit: number().int().min(1).max(1e3).default(200),
16031
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16032
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16033
+ cursor: string().optional(),
16034
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16035
+ projection: TrackProjectionSchema.optional()
16036
+ });
16037
+ var RecentTracksPageSchema = object({
16038
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16039
+ tracks: array(TrackSchema).readonly(),
16040
+ /** Cursor for the next page, or null when this page is the last. */
16041
+ nextCursor: string().nullable()
16042
+ });
15898
16043
  var KeyEventQueryInput = object({
15899
16044
  deviceId: number(),
15900
16045
  /** Window lower bound (track firstSeen ≥ since). */
@@ -15977,11 +16122,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
15977
16122
  deviceId: number(),
15978
16123
  since: number().optional(),
15979
16124
  until: number().optional(),
15980
- limit: number().optional()
15981
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
15982
- kind: "mutation",
15983
- auth: "admin"
15984
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16125
+ limit: number().optional(),
16126
+ /** Spatial filter only tracks whose trajectory intersects the zone
16127
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16128
+ * envelope columns, then precisely tested per position. Tracks with
16129
+ * an unknown envelope (no frame dims at persist time) always match. */
16130
+ zone: TrackZoneFilterSchema.optional(),
16131
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16132
+ * compatible — omitting the field keeps today's exact behaviour). */
16133
+ projection: TrackProjectionSchema.optional()
16134
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16135
+ kind: "mutation",
16136
+ auth: "admin"
16137
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16138
+ deviceId: number(),
16139
+ since: number().optional(),
16140
+ until: number().optional(),
16141
+ kinds: array(string()).optional(),
16142
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16143
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
15985
16144
  deviceId: number(),
15986
16145
  since: number(),
15987
16146
  until: number(),
@@ -19195,7 +19354,12 @@ var RecordingStorageUsageSchema = object({
19195
19354
  /**
19196
19355
  * Result of locating footage at a wall-clock instant for one device/profile.
19197
19356
  * `segment` carries the covering segment's window; `gap` reports the forward
19198
- * nearest covered edge (`null` past the end of footage / when none exists).
19357
+ * nearest covered edge (`null` past the end of footage / when none exists)
19358
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19359
+ * footage behind the epoch; `null` when none — optional so older providers
19360
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19361
+ * small inter-segment cracks (durMs under-covers the span to the next
19362
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19199
19363
  */
19200
19364
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19201
19365
  kind: literal("segment"),
@@ -19204,7 +19368,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19204
19368
  bytes: number()
19205
19369
  }), object({
19206
19370
  kind: literal("gap"),
19207
- nearestEdgeMs: number().nullable()
19371
+ nearestEdgeMs: number().nullable(),
19372
+ prevEndMs: number().nullable().optional()
19208
19373
  })]);
19209
19374
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19210
19375
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20773,6 +20938,12 @@ Object.freeze({
20773
20938
  addonId: null,
20774
20939
  access: "view"
20775
20940
  },
20941
+ "deviceManager.getLinkedDevices": {
20942
+ capName: "device-manager",
20943
+ capScope: "system",
20944
+ addonId: null,
20945
+ access: "view"
20946
+ },
20776
20947
  "deviceManager.getRoleDisplayDefaults": {
20777
20948
  capName: "device-manager",
20778
20949
  capScope: "system",
@@ -22327,6 +22498,12 @@ Object.freeze({
22327
22498
  addonId: null,
22328
22499
  access: "view"
22329
22500
  },
22501
+ "pipelineAnalytics.getSensorEvents": {
22502
+ capName: "pipeline-analytics",
22503
+ capScope: "device",
22504
+ addonId: null,
22505
+ access: "view"
22506
+ },
22330
22507
  "pipelineAnalytics.getTrack": {
22331
22508
  capName: "pipeline-analytics",
22332
22509
  capScope: "device",
@@ -22339,6 +22516,18 @@ Object.freeze({
22339
22516
  addonId: null,
22340
22517
  access: "view"
22341
22518
  },
22519
+ "pipelineAnalytics.listEventKinds": {
22520
+ capName: "pipeline-analytics",
22521
+ capScope: "device",
22522
+ addonId: null,
22523
+ access: "view"
22524
+ },
22525
+ "pipelineAnalytics.listRecentTracks": {
22526
+ capName: "pipeline-analytics",
22527
+ capScope: "device",
22528
+ addonId: null,
22529
+ access: "view"
22530
+ },
22342
22531
  "pipelineAnalytics.listTracks": {
22343
22532
  capName: "pipeline-analytics",
22344
22533
  capScope: "device",
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
36
36
  //#endregion
37
- //#region ../types/dist/event-category-CFZs3jI4.mjs
37
+ //#region ../types/dist/event-category-H4AVePnn.mjs
38
38
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
39
39
  EventCategory["SystemBoot"] = "system.boot";
40
40
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -184,6 +184,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
184
184
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
185
185
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
186
186
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
187
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
188
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
189
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
187
190
  EventCategory["DetectionEvent"] = "detection.event";
188
191
  EventCategory["SessionTrackNew"] = "session.track.new";
189
192
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -7253,6 +7256,24 @@ var RecordingRetentionSchema = object({
7253
7256
  maxSizeGb: number().min(0).optional()
7254
7257
  });
7255
7258
  /**
7259
+ * Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
7260
+ * sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
7261
+ * previews at. Five graduated steps; absent on a config = `standard` (the
7262
+ * shipped default, matching `sheet-geometry`/`sheet-composer`).
7263
+ *
7264
+ * Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
7265
+ * Each window's index sidecar carries its own tile dims, so a camera whose
7266
+ * preset changed over time renders every historical window at the dims it was
7267
+ * written with.
7268
+ */
7269
+ var ScrubThumbnailPresetSchema = _enum([
7270
+ "minimal",
7271
+ "low",
7272
+ "standard",
7273
+ "high",
7274
+ "max"
7275
+ ]);
7276
+ /**
7256
7277
  * The full per-camera recording intent — the wire shape of a RecordingTarget.
7257
7278
  *
7258
7279
  * `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
@@ -7289,7 +7310,14 @@ var RecordingConfigSchema = object({
7289
7310
  * derived into bands once via `migrateConfigToBands`.
7290
7311
  */
7291
7312
  bands: array(RecordingBandSchema).optional(),
7292
- retention: RecordingRetentionSchema.optional()
7313
+ retention: RecordingRetentionSchema.optional(),
7314
+ /**
7315
+ * Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
7316
+ * timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
7317
+ * windows only — existing sheets are immutable, and each window's index
7318
+ * carries its own tile dims so mixed-preset history renders correctly.
7319
+ */
7320
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7293
7321
  });
7294
7322
  /**
7295
7323
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
@@ -9848,7 +9876,7 @@ object({
9848
9876
  deviceId: number(),
9849
9877
  timestamp: number()
9850
9878
  });
9851
- DeviceType.Button;
9879
+ DeviceType.Button, DeviceType.Camera;
9852
9880
  /**
9853
9881
  * Enum-state sensor — a string value picked from a finite option set.
9854
9882
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14218,6 +14246,14 @@ var ConfigEntrySchema = object({
14218
14246
  value: unknown(),
14219
14247
  description: string().optional()
14220
14248
  });
14249
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14250
+ /** One resolved linked device — the compact projection consumers need. */
14251
+ var LinkedDeviceSchema = object({
14252
+ deviceId: number(),
14253
+ name: string(),
14254
+ location: string().nullable(),
14255
+ features: array(string())
14256
+ });
14221
14257
  var SavedDeviceRowSchema = object({
14222
14258
  /** Numeric id reserved at allocateDeviceId time. */
14223
14259
  id: number(),
@@ -14439,7 +14475,10 @@ method(object({
14439
14475
  }), _void(), {
14440
14476
  kind: "mutation",
14441
14477
  auth: "admin"
14442
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14478
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14479
+ mode: DeviceLinkModeSchema,
14480
+ devices: array(LinkedDeviceSchema)
14481
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14443
14482
  deviceId: number(),
14444
14483
  values: record(string(), unknown())
14445
14484
  }), object({ success: literal(true) }), {
@@ -15708,6 +15747,61 @@ var EventKindSchema = _enum([
15708
15747
  "object",
15709
15748
  "audio"
15710
15749
  ]);
15750
+ /**
15751
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15752
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15753
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15754
+ */
15755
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15756
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15757
+ var EventKindIconSchema = _enum([
15758
+ "motion",
15759
+ "audio",
15760
+ "person",
15761
+ "vehicle",
15762
+ "animal",
15763
+ "door",
15764
+ "pir",
15765
+ "smoke",
15766
+ "water",
15767
+ "button",
15768
+ "generic"
15769
+ ]);
15770
+ var EventKindCategorySchema = _enum([
15771
+ "motion",
15772
+ "audio",
15773
+ "detection",
15774
+ "sensor",
15775
+ "custom"
15776
+ ]);
15777
+ var EventKindDescriptorSchema = object({
15778
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15779
+ kind: string(),
15780
+ label: string(),
15781
+ /** Hex color for timeline/legend rendering. */
15782
+ color: string(),
15783
+ icon: EventKindIconSchema,
15784
+ category: EventKindCategorySchema,
15785
+ /** Which cap + device contributes this kind. For built-ins the camera
15786
+ * itself; for sensor kinds the LINKED source device. */
15787
+ source: object({
15788
+ capName: string(),
15789
+ deviceId: number()
15790
+ })
15791
+ });
15792
+ var SensorEventSchema = object({
15793
+ id: string(),
15794
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15795
+ * yields N rows, one per camera). */
15796
+ deviceId: number(),
15797
+ /** The linked sensor device whose state changed. */
15798
+ sourceDeviceId: number(),
15799
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15800
+ kind: string(),
15801
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15802
+ value: record(string(), unknown()).nullable(),
15803
+ timestamp: number()
15804
+ });
15711
15805
  var TrackPositionSchema = object({
15712
15806
  x: number(),
15713
15807
  y: number(),
@@ -15721,6 +15815,30 @@ var TrackSnapshotSchema = object({
15721
15815
  mediaKey: string()
15722
15816
  });
15723
15817
  /**
15818
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15819
+ * divided by the track's detection-frame dims), computed at persist time.
15820
+ * Absent when the frame dims were unknown when the track was persisted
15821
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15822
+ */
15823
+ var TrackEnvelopeSchema = object({
15824
+ minX: number(),
15825
+ minY: number(),
15826
+ maxX: number(),
15827
+ maxY: number()
15828
+ });
15829
+ /**
15830
+ * Row projection for track list queries. `full` (default) returns the
15831
+ * complete Track including the frame-rate `positions[]` history and the
15832
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15833
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15834
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15835
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15836
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15837
+ * `getTrack`. Mirrors the event-store `projection` convention
15838
+ * (`getObjectEvents` et al.).
15839
+ */
15840
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15841
+ /**
15724
15842
  * One audio-classification label heard on the track's camera while the
15725
15843
  * track was alive, aggregated per label. An "episode" is one persisted
15726
15844
  * audio event (the confident-classification path: score ≥ the device's
@@ -15771,7 +15889,11 @@ var TrackSchema = object({
15771
15889
  /** Audio-classification labels heard on the camera during the track's
15772
15890
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15773
15891
  * Absent on legacy rows / tracks with no confident audio. */
15774
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15892
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15893
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15894
+ * Populated from the persisted envelope columns on historical reads;
15895
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15896
+ envelope: TrackEnvelopeSchema.optional()
15775
15897
  });
15776
15898
  var BaseEventFields = {
15777
15899
  id: string(),
@@ -15881,11 +16003,13 @@ var MediaFileSchema = object({
15881
16003
  sizeBytes: number(),
15882
16004
  timestamp: number()
15883
16005
  });
16006
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16007
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15884
16008
  var DeviceEventQueryInput = object({
15885
16009
  deviceId: number(),
15886
16010
  since: number().optional(),
15887
16011
  until: number().optional(),
15888
- limit: number().int().min(1).max(5e3).default(1e3),
16012
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15889
16013
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15890
16014
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15891
16015
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -15893,6 +16017,27 @@ var DeviceEventQueryInput = object({
15893
16017
  projection: _enum(["full", "slim"]).optional()
15894
16018
  });
15895
16019
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16020
+ var RecentTracksQueryInput = object({
16021
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16022
+ deviceIds: array(number()),
16023
+ /** Window lower bound on `lastSeen` (inclusive). */
16024
+ since: number().optional(),
16025
+ /** Window upper bound on `lastSeen` (inclusive). */
16026
+ until: number().optional(),
16027
+ /** Page size. Default 200, max 1000. */
16028
+ limit: number().int().min(1).max(1e3).default(200),
16029
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16030
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16031
+ cursor: string().optional(),
16032
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16033
+ projection: TrackProjectionSchema.optional()
16034
+ });
16035
+ var RecentTracksPageSchema = object({
16036
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16037
+ tracks: array(TrackSchema).readonly(),
16038
+ /** Cursor for the next page, or null when this page is the last. */
16039
+ nextCursor: string().nullable()
16040
+ });
15896
16041
  var KeyEventQueryInput = object({
15897
16042
  deviceId: number(),
15898
16043
  /** Window lower bound (track firstSeen ≥ since). */
@@ -15975,11 +16120,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
15975
16120
  deviceId: number(),
15976
16121
  since: number().optional(),
15977
16122
  until: number().optional(),
15978
- limit: number().optional()
15979
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
15980
- kind: "mutation",
15981
- auth: "admin"
15982
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16123
+ limit: number().optional(),
16124
+ /** Spatial filter only tracks whose trajectory intersects the zone
16125
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16126
+ * envelope columns, then precisely tested per position. Tracks with
16127
+ * an unknown envelope (no frame dims at persist time) always match. */
16128
+ zone: TrackZoneFilterSchema.optional(),
16129
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16130
+ * compatible — omitting the field keeps today's exact behaviour). */
16131
+ projection: TrackProjectionSchema.optional()
16132
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16133
+ kind: "mutation",
16134
+ auth: "admin"
16135
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16136
+ deviceId: number(),
16137
+ since: number().optional(),
16138
+ until: number().optional(),
16139
+ kinds: array(string()).optional(),
16140
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16141
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
15983
16142
  deviceId: number(),
15984
16143
  since: number(),
15985
16144
  until: number(),
@@ -19193,7 +19352,12 @@ var RecordingStorageUsageSchema = object({
19193
19352
  /**
19194
19353
  * Result of locating footage at a wall-clock instant for one device/profile.
19195
19354
  * `segment` carries the covering segment's window; `gap` reports the forward
19196
- * nearest covered edge (`null` past the end of footage / when none exists).
19355
+ * nearest covered edge (`null` past the end of footage / when none exists)
19356
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19357
+ * footage behind the epoch; `null` when none — optional so older providers
19358
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19359
+ * small inter-segment cracks (durMs under-covers the span to the next
19360
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19197
19361
  */
19198
19362
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19199
19363
  kind: literal("segment"),
@@ -19202,7 +19366,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19202
19366
  bytes: number()
19203
19367
  }), object({
19204
19368
  kind: literal("gap"),
19205
- nearestEdgeMs: number().nullable()
19369
+ nearestEdgeMs: number().nullable(),
19370
+ prevEndMs: number().nullable().optional()
19206
19371
  })]);
19207
19372
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19208
19373
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20771,6 +20936,12 @@ Object.freeze({
20771
20936
  addonId: null,
20772
20937
  access: "view"
20773
20938
  },
20939
+ "deviceManager.getLinkedDevices": {
20940
+ capName: "device-manager",
20941
+ capScope: "system",
20942
+ addonId: null,
20943
+ access: "view"
20944
+ },
20774
20945
  "deviceManager.getRoleDisplayDefaults": {
20775
20946
  capName: "device-manager",
20776
20947
  capScope: "system",
@@ -22325,6 +22496,12 @@ Object.freeze({
22325
22496
  addonId: null,
22326
22497
  access: "view"
22327
22498
  },
22499
+ "pipelineAnalytics.getSensorEvents": {
22500
+ capName: "pipeline-analytics",
22501
+ capScope: "device",
22502
+ addonId: null,
22503
+ access: "view"
22504
+ },
22328
22505
  "pipelineAnalytics.getTrack": {
22329
22506
  capName: "pipeline-analytics",
22330
22507
  capScope: "device",
@@ -22337,6 +22514,18 @@ Object.freeze({
22337
22514
  addonId: null,
22338
22515
  access: "view"
22339
22516
  },
22517
+ "pipelineAnalytics.listEventKinds": {
22518
+ capName: "pipeline-analytics",
22519
+ capScope: "device",
22520
+ addonId: null,
22521
+ access: "view"
22522
+ },
22523
+ "pipelineAnalytics.listRecentTracks": {
22524
+ capName: "pipeline-analytics",
22525
+ capScope: "device",
22526
+ addonId: null,
22527
+ access: "view"
22528
+ },
22340
22529
  "pipelineAnalytics.listTracks": {
22341
22530
  capName: "pipeline-analytics",
22342
22531
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-smtp-nodemailer",
3
- "version": "1.1.22",
3
+ "version": "1.1.24",
4
4
  "description": "SMTP email provider addon for CamStack — wraps `nodemailer` and registers a `smtp-provider` cap collection entry. Used by magic-link login + notifier addons.",
5
5
  "keywords": [
6
6
  "camstack",