@camstack/addon-provider-velux 0.2.57 → 0.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.
package/dist/addon.js CHANGED
@@ -10527,6 +10527,89 @@ var LocationStatSchema = object({
10527
10527
  fileCount: number(),
10528
10528
  present: boolean()
10529
10529
  });
10530
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10531
+ var BackupRunStateSchema = _enum([
10532
+ "queued",
10533
+ "running",
10534
+ "succeeded",
10535
+ "failed",
10536
+ "cancelled"
10537
+ ]);
10538
+ /**
10539
+ * Where a running backup currently is. `queued` before it starts,
10540
+ * `building` while the tar.gz is being staged, `uploading` during the
10541
+ * per-destination fan-out, `done` once terminal.
10542
+ */
10543
+ var BackupRunPhaseSchema = _enum([
10544
+ "queued",
10545
+ "building",
10546
+ "uploading",
10547
+ "done"
10548
+ ]);
10549
+ /**
10550
+ * Observable state of one backup run — readable WHILE it runs via
10551
+ * `backup.listRuns`. This is what makes the execution queue and
10552
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10553
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10554
+ * diagnosable with `du` because nothing reported that runs existed or
10555
+ * how large the staged archive had grown.
10556
+ */
10557
+ var BackupRunSchema = object({
10558
+ /** Stable run id — the handle `backup.cancel` takes. */
10559
+ id: string(),
10560
+ state: BackupRunStateSchema,
10561
+ phase: BackupRunPhaseSchema,
10562
+ /**
10563
+ * Resolved destination location ids. Empty while queued (targets are
10564
+ * resolved when the run starts, against the then-current policies).
10565
+ */
10566
+ destinationIds: array(string()).readonly(),
10567
+ label: string().optional(),
10568
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10569
+ requestedAt: number(),
10570
+ /** ms-epoch when the run left the queue and started building. */
10571
+ startedAt: number().optional(),
10572
+ /** ms-epoch when the run reached a terminal state. */
10573
+ finishedAt: number().optional(),
10574
+ /** Compressed bytes of the staging archive written so far. */
10575
+ stagedBytes: number(),
10576
+ /** Final staged archive size, once the build phase completes. */
10577
+ archiveSizeBytes: number().optional(),
10578
+ /** Bytes pushed to the destination currently uploading. */
10579
+ uploadedBytes: number(),
10580
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10581
+ completedDestinationIds: array(string()).readonly(),
10582
+ /** Destinations that failed during the fan-out. */
10583
+ failedDestinationIds: array(string()).readonly(),
10584
+ /** Failure message when `state === 'failed'`. */
10585
+ error: string().optional(),
10586
+ /**
10587
+ * 1-based place in the execution queue — 1 = runs next. Present only
10588
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10589
+ * queue's OWN pending order, never derived from timestamps, so the
10590
+ * UI cannot show an order the executor will not honour.
10591
+ */
10592
+ queuePosition: number().int().min(1).optional()
10593
+ });
10594
+ /**
10595
+ * Result of `backup.trigger`. The call still resolves when the run
10596
+ * terminates (compat with schedule-driven runs and the admin UI), but
10597
+ * it now names the run and says whether it had to WAIT: a trigger that
10598
+ * arrives while another run is in flight is enqueued (or joined onto
10599
+ * an identical already-queued run), never started concurrently.
10600
+ */
10601
+ var BackupTriggerResultSchema = object({
10602
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10603
+ runId: string(),
10604
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10605
+ queued: boolean(),
10606
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10607
+ joined: boolean(),
10608
+ /** True when the run was cancelled before completing every destination. */
10609
+ cancelled: boolean(),
10610
+ /** One entry per destination the archive landed at (partial on cancel). */
10611
+ entries: array(BackupEntrySchema).readonly()
10612
+ });
10530
10613
  /**
10531
10614
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10532
10615
  * SET of destination locations. Supersedes the per-location cron on
@@ -10574,7 +10657,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10574
10657
  * retention (manual runs).
10575
10658
  */
10576
10659
  retentionCount: number().int().min(1).max(1e3).optional()
10577
- }).optional(), array(BackupEntrySchema).readonly(), {
10660
+ }).optional(), BackupTriggerResultSchema, {
10661
+ kind: "mutation",
10662
+ auth: "admin"
10663
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10578
10664
  kind: "mutation",
10579
10665
  auth: "admin"
10580
10666
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11291,6 +11377,14 @@ method(object({
11291
11377
  }), object({ success: literal(true) }), {
11292
11378
  kind: "mutation",
11293
11379
  auth: "admin"
11380
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11381
+ derivedStreamsDeleted: array(string()).readonly(),
11382
+ assignmentsPurged: boolean(),
11383
+ probeSnapshotsDropped: number().int().nonnegative(),
11384
+ rtspTokenRowsDeleted: number().int().nonnegative()
11385
+ }), {
11386
+ kind: "mutation",
11387
+ auth: "admin"
11294
11388
  }), method(object({
11295
11389
  deviceId: number(),
11296
11390
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19183,7 +19277,20 @@ var RecentTracksQueryInput = object({
19183
19277
  projection: TrackProjectionSchema.optional(),
19184
19278
  /** Include stationary-promoted rows (parked objects). Default false: the
19185
19279
  * feed lists passages; parking records live on the stationary registry. */
19186
- includeStationary: boolean().optional()
19280
+ includeStationary: boolean().optional(),
19281
+ /**
19282
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19283
+ *
19284
+ * The same filter `listTracks` takes, because the timeline's class chips must
19285
+ * mean the same thing whether the scope is one camera or twelve. Until this
19286
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19287
+ * while the single-camera path narrowed the read — one filter, two costs.
19288
+ *
19289
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19290
+ * whose class list is unreadable are kept, and the client's rule stays the
19291
+ * exact one.
19292
+ */
19293
+ classes: array(string()).optional()
19187
19294
  });
19188
19295
  var RecentTracksPageSchema = object({
19189
19296
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23353,8 +23460,22 @@ var automationControlCapability = {
23353
23460
  * threshold.
23354
23461
  */
23355
23462
  var BatteryStatusSchema = object({
23356
- /** 0..100 inclusive. Firmware-reported. */
23357
- percentage: number().min(0).max(100),
23463
+ /**
23464
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23465
+ * provider has registered the capability but no reading has landed.
23466
+ *
23467
+ * It is nullable because it was not, and the only value a provider could
23468
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23469
+ * itself at 0% on every start and corrected itself a moment later, which is
23470
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23471
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23472
+ * reading the difference is an alarm.
23473
+ *
23474
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23475
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23476
+ * declines to band a non-finite reading, which is the correct shape.
23477
+ */
23478
+ percentage: number().min(0).max(100).nullable(),
23358
23479
  /**
23359
23480
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23360
23481
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33115,6 +33236,12 @@ Object.freeze({
33115
33236
  addonId: null,
33116
33237
  access: "create"
33117
33238
  },
33239
+ "backup.cancel": {
33240
+ capName: "backup",
33241
+ capScope: "system",
33242
+ addonId: null,
33243
+ access: "create"
33244
+ },
33118
33245
  "backup.delete": {
33119
33246
  capName: "backup",
33120
33247
  capScope: "system",
@@ -33157,6 +33284,12 @@ Object.freeze({
33157
33284
  addonId: null,
33158
33285
  access: "view"
33159
33286
  },
33287
+ "backup.listRuns": {
33288
+ capName: "backup",
33289
+ capScope: "system",
33290
+ addonId: null,
33291
+ access: "view"
33292
+ },
33160
33293
  "backup.listSchedules": {
33161
33294
  capName: "backup",
33162
33295
  capScope: "system",
@@ -37723,6 +37856,12 @@ Object.freeze({
37723
37856
  addonId: null,
37724
37857
  access: "create"
37725
37858
  },
37859
+ "streamBroker.forgetDeviceHardware": {
37860
+ capName: "stream-broker",
37861
+ capScope: "system",
37862
+ addonId: null,
37863
+ access: "delete"
37864
+ },
37726
37865
  "streamBroker.getAllRtspEntries": {
37727
37866
  capName: "stream-broker",
37728
37867
  capScope: "system",
@@ -40181,6 +40320,11 @@ Object.freeze({
40181
40320
  form: "single",
40182
40321
  optional: false
40183
40322
  }],
40323
+ "streamBroker.forgetDeviceHardware": [{
40324
+ name: "deviceId",
40325
+ form: "single",
40326
+ optional: false
40327
+ }],
40184
40328
  "streamBroker.getDeviceAudioMute": [{
40185
40329
  name: "deviceId",
40186
40330
  form: "single",
package/dist/addon.mjs CHANGED
@@ -10526,6 +10526,89 @@ var LocationStatSchema = object({
10526
10526
  fileCount: number(),
10527
10527
  present: boolean()
10528
10528
  });
10529
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10530
+ var BackupRunStateSchema = _enum([
10531
+ "queued",
10532
+ "running",
10533
+ "succeeded",
10534
+ "failed",
10535
+ "cancelled"
10536
+ ]);
10537
+ /**
10538
+ * Where a running backup currently is. `queued` before it starts,
10539
+ * `building` while the tar.gz is being staged, `uploading` during the
10540
+ * per-destination fan-out, `done` once terminal.
10541
+ */
10542
+ var BackupRunPhaseSchema = _enum([
10543
+ "queued",
10544
+ "building",
10545
+ "uploading",
10546
+ "done"
10547
+ ]);
10548
+ /**
10549
+ * Observable state of one backup run — readable WHILE it runs via
10550
+ * `backup.listRuns`. This is what makes the execution queue and
10551
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10552
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10553
+ * diagnosable with `du` because nothing reported that runs existed or
10554
+ * how large the staged archive had grown.
10555
+ */
10556
+ var BackupRunSchema = object({
10557
+ /** Stable run id — the handle `backup.cancel` takes. */
10558
+ id: string(),
10559
+ state: BackupRunStateSchema,
10560
+ phase: BackupRunPhaseSchema,
10561
+ /**
10562
+ * Resolved destination location ids. Empty while queued (targets are
10563
+ * resolved when the run starts, against the then-current policies).
10564
+ */
10565
+ destinationIds: array(string()).readonly(),
10566
+ label: string().optional(),
10567
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10568
+ requestedAt: number(),
10569
+ /** ms-epoch when the run left the queue and started building. */
10570
+ startedAt: number().optional(),
10571
+ /** ms-epoch when the run reached a terminal state. */
10572
+ finishedAt: number().optional(),
10573
+ /** Compressed bytes of the staging archive written so far. */
10574
+ stagedBytes: number(),
10575
+ /** Final staged archive size, once the build phase completes. */
10576
+ archiveSizeBytes: number().optional(),
10577
+ /** Bytes pushed to the destination currently uploading. */
10578
+ uploadedBytes: number(),
10579
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10580
+ completedDestinationIds: array(string()).readonly(),
10581
+ /** Destinations that failed during the fan-out. */
10582
+ failedDestinationIds: array(string()).readonly(),
10583
+ /** Failure message when `state === 'failed'`. */
10584
+ error: string().optional(),
10585
+ /**
10586
+ * 1-based place in the execution queue — 1 = runs next. Present only
10587
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10588
+ * queue's OWN pending order, never derived from timestamps, so the
10589
+ * UI cannot show an order the executor will not honour.
10590
+ */
10591
+ queuePosition: number().int().min(1).optional()
10592
+ });
10593
+ /**
10594
+ * Result of `backup.trigger`. The call still resolves when the run
10595
+ * terminates (compat with schedule-driven runs and the admin UI), but
10596
+ * it now names the run and says whether it had to WAIT: a trigger that
10597
+ * arrives while another run is in flight is enqueued (or joined onto
10598
+ * an identical already-queued run), never started concurrently.
10599
+ */
10600
+ var BackupTriggerResultSchema = object({
10601
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10602
+ runId: string(),
10603
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10604
+ queued: boolean(),
10605
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10606
+ joined: boolean(),
10607
+ /** True when the run was cancelled before completing every destination. */
10608
+ cancelled: boolean(),
10609
+ /** One entry per destination the archive landed at (partial on cancel). */
10610
+ entries: array(BackupEntrySchema).readonly()
10611
+ });
10529
10612
  /**
10530
10613
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10531
10614
  * SET of destination locations. Supersedes the per-location cron on
@@ -10573,7 +10656,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10573
10656
  * retention (manual runs).
10574
10657
  */
10575
10658
  retentionCount: number().int().min(1).max(1e3).optional()
10576
- }).optional(), array(BackupEntrySchema).readonly(), {
10659
+ }).optional(), BackupTriggerResultSchema, {
10660
+ kind: "mutation",
10661
+ auth: "admin"
10662
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10577
10663
  kind: "mutation",
10578
10664
  auth: "admin"
10579
10665
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11290,6 +11376,14 @@ method(object({
11290
11376
  }), object({ success: literal(true) }), {
11291
11377
  kind: "mutation",
11292
11378
  auth: "admin"
11379
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11380
+ derivedStreamsDeleted: array(string()).readonly(),
11381
+ assignmentsPurged: boolean(),
11382
+ probeSnapshotsDropped: number().int().nonnegative(),
11383
+ rtspTokenRowsDeleted: number().int().nonnegative()
11384
+ }), {
11385
+ kind: "mutation",
11386
+ auth: "admin"
11293
11387
  }), method(object({
11294
11388
  deviceId: number(),
11295
11389
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19182,7 +19276,20 @@ var RecentTracksQueryInput = object({
19182
19276
  projection: TrackProjectionSchema.optional(),
19183
19277
  /** Include stationary-promoted rows (parked objects). Default false: the
19184
19278
  * feed lists passages; parking records live on the stationary registry. */
19185
- includeStationary: boolean().optional()
19279
+ includeStationary: boolean().optional(),
19280
+ /**
19281
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19282
+ *
19283
+ * The same filter `listTracks` takes, because the timeline's class chips must
19284
+ * mean the same thing whether the scope is one camera or twelve. Until this
19285
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19286
+ * while the single-camera path narrowed the read — one filter, two costs.
19287
+ *
19288
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19289
+ * whose class list is unreadable are kept, and the client's rule stays the
19290
+ * exact one.
19291
+ */
19292
+ classes: array(string()).optional()
19186
19293
  });
19187
19294
  var RecentTracksPageSchema = object({
19188
19295
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23352,8 +23459,22 @@ var automationControlCapability = {
23352
23459
  * threshold.
23353
23460
  */
23354
23461
  var BatteryStatusSchema = object({
23355
- /** 0..100 inclusive. Firmware-reported. */
23356
- percentage: number().min(0).max(100),
23462
+ /**
23463
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23464
+ * provider has registered the capability but no reading has landed.
23465
+ *
23466
+ * It is nullable because it was not, and the only value a provider could
23467
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23468
+ * itself at 0% on every start and corrected itself a moment later, which is
23469
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23470
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23471
+ * reading the difference is an alarm.
23472
+ *
23473
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23474
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23475
+ * declines to band a non-finite reading, which is the correct shape.
23476
+ */
23477
+ percentage: number().min(0).max(100).nullable(),
23357
23478
  /**
23358
23479
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23359
23480
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33114,6 +33235,12 @@ Object.freeze({
33114
33235
  addonId: null,
33115
33236
  access: "create"
33116
33237
  },
33238
+ "backup.cancel": {
33239
+ capName: "backup",
33240
+ capScope: "system",
33241
+ addonId: null,
33242
+ access: "create"
33243
+ },
33117
33244
  "backup.delete": {
33118
33245
  capName: "backup",
33119
33246
  capScope: "system",
@@ -33156,6 +33283,12 @@ Object.freeze({
33156
33283
  addonId: null,
33157
33284
  access: "view"
33158
33285
  },
33286
+ "backup.listRuns": {
33287
+ capName: "backup",
33288
+ capScope: "system",
33289
+ addonId: null,
33290
+ access: "view"
33291
+ },
33159
33292
  "backup.listSchedules": {
33160
33293
  capName: "backup",
33161
33294
  capScope: "system",
@@ -37722,6 +37855,12 @@ Object.freeze({
37722
37855
  addonId: null,
37723
37856
  access: "create"
37724
37857
  },
37858
+ "streamBroker.forgetDeviceHardware": {
37859
+ capName: "stream-broker",
37860
+ capScope: "system",
37861
+ addonId: null,
37862
+ access: "delete"
37863
+ },
37725
37864
  "streamBroker.getAllRtspEntries": {
37726
37865
  capName: "stream-broker",
37727
37866
  capScope: "system",
@@ -40180,6 +40319,11 @@ Object.freeze({
40180
40319
  form: "single",
40181
40320
  optional: false
40182
40321
  }],
40322
+ "streamBroker.forgetDeviceHardware": [{
40323
+ name: "deviceId",
40324
+ form: "single",
40325
+ optional: false
40326
+ }],
40183
40327
  "streamBroker.getDeviceAudioMute": [{
40184
40328
  name: "deviceId",
40185
40329
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-velux",
3
- "version": "0.2.57",
3
+ "version": "0.2.59",
4
4
  "description": "Velux KLF-200 device-provider addon for CamStack — local-gateway window + shutter covers (positional, no tilt)",
5
5
  "keywords": [
6
6
  "camstack",