@camstack/addon-mqtt-broker 1.2.57 → 1.2.59

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.
@@ -10556,6 +10556,89 @@ var LocationStatSchema = object({
10556
10556
  fileCount: number(),
10557
10557
  present: boolean()
10558
10558
  });
10559
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10560
+ var BackupRunStateSchema = _enum([
10561
+ "queued",
10562
+ "running",
10563
+ "succeeded",
10564
+ "failed",
10565
+ "cancelled"
10566
+ ]);
10567
+ /**
10568
+ * Where a running backup currently is. `queued` before it starts,
10569
+ * `building` while the tar.gz is being staged, `uploading` during the
10570
+ * per-destination fan-out, `done` once terminal.
10571
+ */
10572
+ var BackupRunPhaseSchema = _enum([
10573
+ "queued",
10574
+ "building",
10575
+ "uploading",
10576
+ "done"
10577
+ ]);
10578
+ /**
10579
+ * Observable state of one backup run — readable WHILE it runs via
10580
+ * `backup.listRuns`. This is what makes the execution queue and
10581
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10582
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10583
+ * diagnosable with `du` because nothing reported that runs existed or
10584
+ * how large the staged archive had grown.
10585
+ */
10586
+ var BackupRunSchema = object({
10587
+ /** Stable run id — the handle `backup.cancel` takes. */
10588
+ id: string(),
10589
+ state: BackupRunStateSchema,
10590
+ phase: BackupRunPhaseSchema,
10591
+ /**
10592
+ * Resolved destination location ids. Empty while queued (targets are
10593
+ * resolved when the run starts, against the then-current policies).
10594
+ */
10595
+ destinationIds: array(string()).readonly(),
10596
+ label: string().optional(),
10597
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10598
+ requestedAt: number(),
10599
+ /** ms-epoch when the run left the queue and started building. */
10600
+ startedAt: number().optional(),
10601
+ /** ms-epoch when the run reached a terminal state. */
10602
+ finishedAt: number().optional(),
10603
+ /** Compressed bytes of the staging archive written so far. */
10604
+ stagedBytes: number(),
10605
+ /** Final staged archive size, once the build phase completes. */
10606
+ archiveSizeBytes: number().optional(),
10607
+ /** Bytes pushed to the destination currently uploading. */
10608
+ uploadedBytes: number(),
10609
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10610
+ completedDestinationIds: array(string()).readonly(),
10611
+ /** Destinations that failed during the fan-out. */
10612
+ failedDestinationIds: array(string()).readonly(),
10613
+ /** Failure message when `state === 'failed'`. */
10614
+ error: string().optional(),
10615
+ /**
10616
+ * 1-based place in the execution queue — 1 = runs next. Present only
10617
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10618
+ * queue's OWN pending order, never derived from timestamps, so the
10619
+ * UI cannot show an order the executor will not honour.
10620
+ */
10621
+ queuePosition: number().int().min(1).optional()
10622
+ });
10623
+ /**
10624
+ * Result of `backup.trigger`. The call still resolves when the run
10625
+ * terminates (compat with schedule-driven runs and the admin UI), but
10626
+ * it now names the run and says whether it had to WAIT: a trigger that
10627
+ * arrives while another run is in flight is enqueued (or joined onto
10628
+ * an identical already-queued run), never started concurrently.
10629
+ */
10630
+ var BackupTriggerResultSchema = object({
10631
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10632
+ runId: string(),
10633
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10634
+ queued: boolean(),
10635
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10636
+ joined: boolean(),
10637
+ /** True when the run was cancelled before completing every destination. */
10638
+ cancelled: boolean(),
10639
+ /** One entry per destination the archive landed at (partial on cancel). */
10640
+ entries: array(BackupEntrySchema).readonly()
10641
+ });
10559
10642
  /**
10560
10643
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10561
10644
  * SET of destination locations. Supersedes the per-location cron on
@@ -10603,7 +10686,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10603
10686
  * retention (manual runs).
10604
10687
  */
10605
10688
  retentionCount: number().int().min(1).max(1e3).optional()
10606
- }).optional(), array(BackupEntrySchema).readonly(), {
10689
+ }).optional(), BackupTriggerResultSchema, {
10690
+ kind: "mutation",
10691
+ auth: "admin"
10692
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10607
10693
  kind: "mutation",
10608
10694
  auth: "admin"
10609
10695
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11369,6 +11455,14 @@ method(object({
11369
11455
  }), object({ success: literal(true) }), {
11370
11456
  kind: "mutation",
11371
11457
  auth: "admin"
11458
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11459
+ derivedStreamsDeleted: array(string()).readonly(),
11460
+ assignmentsPurged: boolean(),
11461
+ probeSnapshotsDropped: number().int().nonnegative(),
11462
+ rtspTokenRowsDeleted: number().int().nonnegative()
11463
+ }), {
11464
+ kind: "mutation",
11465
+ auth: "admin"
11372
11466
  }), method(object({
11373
11467
  deviceId: number(),
11374
11468
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -18938,7 +19032,20 @@ var RecentTracksQueryInput = object({
18938
19032
  projection: TrackProjectionSchema.optional(),
18939
19033
  /** Include stationary-promoted rows (parked objects). Default false: the
18940
19034
  * feed lists passages; parking records live on the stationary registry. */
18941
- includeStationary: boolean().optional()
19035
+ includeStationary: boolean().optional(),
19036
+ /**
19037
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19038
+ *
19039
+ * The same filter `listTracks` takes, because the timeline's class chips must
19040
+ * mean the same thing whether the scope is one camera or twelve. Until this
19041
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19042
+ * while the single-camera path narrowed the read — one filter, two costs.
19043
+ *
19044
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19045
+ * whose class list is unreadable are kept, and the client's rule stays the
19046
+ * exact one.
19047
+ */
19048
+ classes: array(string()).optional()
18942
19049
  });
18943
19050
  var RecentTracksPageSchema = object({
18944
19051
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -22976,8 +23083,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
22976
23083
  * threshold.
22977
23084
  */
22978
23085
  var BatteryStatusSchema = object({
22979
- /** 0..100 inclusive. Firmware-reported. */
22980
- percentage: number().min(0).max(100),
23086
+ /**
23087
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23088
+ * provider has registered the capability but no reading has landed.
23089
+ *
23090
+ * It is nullable because it was not, and the only value a provider could
23091
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23092
+ * itself at 0% on every start and corrected itself a moment later, which is
23093
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23094
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23095
+ * reading the difference is an alarm.
23096
+ *
23097
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23098
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23099
+ * declines to band a non-finite reading, which is the correct shape.
23100
+ */
23101
+ percentage: number().min(0).max(100).nullable(),
22981
23102
  /**
22982
23103
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
22983
23104
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -29456,6 +29577,12 @@ Object.freeze({
29456
29577
  addonId: null,
29457
29578
  access: "create"
29458
29579
  },
29580
+ "backup.cancel": {
29581
+ capName: "backup",
29582
+ capScope: "system",
29583
+ addonId: null,
29584
+ access: "create"
29585
+ },
29459
29586
  "backup.delete": {
29460
29587
  capName: "backup",
29461
29588
  capScope: "system",
@@ -29498,6 +29625,12 @@ Object.freeze({
29498
29625
  addonId: null,
29499
29626
  access: "view"
29500
29627
  },
29628
+ "backup.listRuns": {
29629
+ capName: "backup",
29630
+ capScope: "system",
29631
+ addonId: null,
29632
+ access: "view"
29633
+ },
29501
29634
  "backup.listSchedules": {
29502
29635
  capName: "backup",
29503
29636
  capScope: "system",
@@ -34064,6 +34197,12 @@ Object.freeze({
34064
34197
  addonId: null,
34065
34198
  access: "create"
34066
34199
  },
34200
+ "streamBroker.forgetDeviceHardware": {
34201
+ capName: "stream-broker",
34202
+ capScope: "system",
34203
+ addonId: null,
34204
+ access: "delete"
34205
+ },
34067
34206
  "streamBroker.getAllRtspEntries": {
34068
34207
  capName: "stream-broker",
34069
34208
  capScope: "system",
@@ -36522,6 +36661,11 @@ Object.freeze({
36522
36661
  form: "single",
36523
36662
  optional: false
36524
36663
  }],
36664
+ "streamBroker.forgetDeviceHardware": [{
36665
+ name: "deviceId",
36666
+ form: "single",
36667
+ optional: false
36668
+ }],
36525
36669
  "streamBroker.getDeviceAudioMute": [{
36526
36670
  name: "deviceId",
36527
36671
  form: "single",
@@ -10551,6 +10551,89 @@ var LocationStatSchema = object({
10551
10551
  fileCount: number(),
10552
10552
  present: boolean()
10553
10553
  });
10554
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10555
+ var BackupRunStateSchema = _enum([
10556
+ "queued",
10557
+ "running",
10558
+ "succeeded",
10559
+ "failed",
10560
+ "cancelled"
10561
+ ]);
10562
+ /**
10563
+ * Where a running backup currently is. `queued` before it starts,
10564
+ * `building` while the tar.gz is being staged, `uploading` during the
10565
+ * per-destination fan-out, `done` once terminal.
10566
+ */
10567
+ var BackupRunPhaseSchema = _enum([
10568
+ "queued",
10569
+ "building",
10570
+ "uploading",
10571
+ "done"
10572
+ ]);
10573
+ /**
10574
+ * Observable state of one backup run — readable WHILE it runs via
10575
+ * `backup.listRuns`. This is what makes the execution queue and
10576
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10577
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10578
+ * diagnosable with `du` because nothing reported that runs existed or
10579
+ * how large the staged archive had grown.
10580
+ */
10581
+ var BackupRunSchema = object({
10582
+ /** Stable run id — the handle `backup.cancel` takes. */
10583
+ id: string(),
10584
+ state: BackupRunStateSchema,
10585
+ phase: BackupRunPhaseSchema,
10586
+ /**
10587
+ * Resolved destination location ids. Empty while queued (targets are
10588
+ * resolved when the run starts, against the then-current policies).
10589
+ */
10590
+ destinationIds: array(string()).readonly(),
10591
+ label: string().optional(),
10592
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10593
+ requestedAt: number(),
10594
+ /** ms-epoch when the run left the queue and started building. */
10595
+ startedAt: number().optional(),
10596
+ /** ms-epoch when the run reached a terminal state. */
10597
+ finishedAt: number().optional(),
10598
+ /** Compressed bytes of the staging archive written so far. */
10599
+ stagedBytes: number(),
10600
+ /** Final staged archive size, once the build phase completes. */
10601
+ archiveSizeBytes: number().optional(),
10602
+ /** Bytes pushed to the destination currently uploading. */
10603
+ uploadedBytes: number(),
10604
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10605
+ completedDestinationIds: array(string()).readonly(),
10606
+ /** Destinations that failed during the fan-out. */
10607
+ failedDestinationIds: array(string()).readonly(),
10608
+ /** Failure message when `state === 'failed'`. */
10609
+ error: string().optional(),
10610
+ /**
10611
+ * 1-based place in the execution queue — 1 = runs next. Present only
10612
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10613
+ * queue's OWN pending order, never derived from timestamps, so the
10614
+ * UI cannot show an order the executor will not honour.
10615
+ */
10616
+ queuePosition: number().int().min(1).optional()
10617
+ });
10618
+ /**
10619
+ * Result of `backup.trigger`. The call still resolves when the run
10620
+ * terminates (compat with schedule-driven runs and the admin UI), but
10621
+ * it now names the run and says whether it had to WAIT: a trigger that
10622
+ * arrives while another run is in flight is enqueued (or joined onto
10623
+ * an identical already-queued run), never started concurrently.
10624
+ */
10625
+ var BackupTriggerResultSchema = object({
10626
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10627
+ runId: string(),
10628
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10629
+ queued: boolean(),
10630
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10631
+ joined: boolean(),
10632
+ /** True when the run was cancelled before completing every destination. */
10633
+ cancelled: boolean(),
10634
+ /** One entry per destination the archive landed at (partial on cancel). */
10635
+ entries: array(BackupEntrySchema).readonly()
10636
+ });
10554
10637
  /**
10555
10638
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10556
10639
  * SET of destination locations. Supersedes the per-location cron on
@@ -10598,7 +10681,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10598
10681
  * retention (manual runs).
10599
10682
  */
10600
10683
  retentionCount: number().int().min(1).max(1e3).optional()
10601
- }).optional(), array(BackupEntrySchema).readonly(), {
10684
+ }).optional(), BackupTriggerResultSchema, {
10685
+ kind: "mutation",
10686
+ auth: "admin"
10687
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10602
10688
  kind: "mutation",
10603
10689
  auth: "admin"
10604
10690
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11364,6 +11450,14 @@ method(object({
11364
11450
  }), object({ success: literal(true) }), {
11365
11451
  kind: "mutation",
11366
11452
  auth: "admin"
11453
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11454
+ derivedStreamsDeleted: array(string()).readonly(),
11455
+ assignmentsPurged: boolean(),
11456
+ probeSnapshotsDropped: number().int().nonnegative(),
11457
+ rtspTokenRowsDeleted: number().int().nonnegative()
11458
+ }), {
11459
+ kind: "mutation",
11460
+ auth: "admin"
11367
11461
  }), method(object({
11368
11462
  deviceId: number(),
11369
11463
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -18933,7 +19027,20 @@ var RecentTracksQueryInput = object({
18933
19027
  projection: TrackProjectionSchema.optional(),
18934
19028
  /** Include stationary-promoted rows (parked objects). Default false: the
18935
19029
  * feed lists passages; parking records live on the stationary registry. */
18936
- includeStationary: boolean().optional()
19030
+ includeStationary: boolean().optional(),
19031
+ /**
19032
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19033
+ *
19034
+ * The same filter `listTracks` takes, because the timeline's class chips must
19035
+ * mean the same thing whether the scope is one camera or twelve. Until this
19036
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19037
+ * while the single-camera path narrowed the read — one filter, two costs.
19038
+ *
19039
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19040
+ * whose class list is unreadable are kept, and the client's rule stays the
19041
+ * exact one.
19042
+ */
19043
+ classes: array(string()).optional()
18937
19044
  });
18938
19045
  var RecentTracksPageSchema = object({
18939
19046
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -22971,8 +23078,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
22971
23078
  * threshold.
22972
23079
  */
22973
23080
  var BatteryStatusSchema = object({
22974
- /** 0..100 inclusive. Firmware-reported. */
22975
- percentage: number().min(0).max(100),
23081
+ /**
23082
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23083
+ * provider has registered the capability but no reading has landed.
23084
+ *
23085
+ * It is nullable because it was not, and the only value a provider could
23086
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23087
+ * itself at 0% on every start and corrected itself a moment later, which is
23088
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23089
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23090
+ * reading the difference is an alarm.
23091
+ *
23092
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23093
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23094
+ * declines to band a non-finite reading, which is the correct shape.
23095
+ */
23096
+ percentage: number().min(0).max(100).nullable(),
22976
23097
  /**
22977
23098
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
22978
23099
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -29451,6 +29572,12 @@ Object.freeze({
29451
29572
  addonId: null,
29452
29573
  access: "create"
29453
29574
  },
29575
+ "backup.cancel": {
29576
+ capName: "backup",
29577
+ capScope: "system",
29578
+ addonId: null,
29579
+ access: "create"
29580
+ },
29454
29581
  "backup.delete": {
29455
29582
  capName: "backup",
29456
29583
  capScope: "system",
@@ -29493,6 +29620,12 @@ Object.freeze({
29493
29620
  addonId: null,
29494
29621
  access: "view"
29495
29622
  },
29623
+ "backup.listRuns": {
29624
+ capName: "backup",
29625
+ capScope: "system",
29626
+ addonId: null,
29627
+ access: "view"
29628
+ },
29496
29629
  "backup.listSchedules": {
29497
29630
  capName: "backup",
29498
29631
  capScope: "system",
@@ -34059,6 +34192,12 @@ Object.freeze({
34059
34192
  addonId: null,
34060
34193
  access: "create"
34061
34194
  },
34195
+ "streamBroker.forgetDeviceHardware": {
34196
+ capName: "stream-broker",
34197
+ capScope: "system",
34198
+ addonId: null,
34199
+ access: "delete"
34200
+ },
34062
34201
  "streamBroker.getAllRtspEntries": {
34063
34202
  capName: "stream-broker",
34064
34203
  capScope: "system",
@@ -36517,6 +36656,11 @@ Object.freeze({
36517
36656
  form: "single",
36518
36657
  optional: false
36519
36658
  }],
36659
+ "streamBroker.forgetDeviceHardware": [{
36660
+ name: "deviceId",
36661
+ form: "single",
36662
+ optional: false
36663
+ }],
36520
36664
  "streamBroker.getDeviceAudioMute": [{
36521
36665
  name: "deviceId",
36522
36666
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-mqtt-broker",
3
- "version": "1.2.57",
3
+ "version": "1.2.59",
4
4
  "description": "MQTT broker registry addon for CamStack — manages external broker entries + an optional embedded aedes broker. Consumers spin up their own `mqtt.js` clients via the `mqtt-broker` cap.",
5
5
  "keywords": [
6
6
  "camstack",