@camstack/addon-provider-amcrest 0.2.58 → 0.2.60

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
@@ -10520,6 +10520,89 @@ var LocationStatSchema = object({
10520
10520
  fileCount: number(),
10521
10521
  present: boolean()
10522
10522
  });
10523
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10524
+ var BackupRunStateSchema = _enum([
10525
+ "queued",
10526
+ "running",
10527
+ "succeeded",
10528
+ "failed",
10529
+ "cancelled"
10530
+ ]);
10531
+ /**
10532
+ * Where a running backup currently is. `queued` before it starts,
10533
+ * `building` while the tar.gz is being staged, `uploading` during the
10534
+ * per-destination fan-out, `done` once terminal.
10535
+ */
10536
+ var BackupRunPhaseSchema = _enum([
10537
+ "queued",
10538
+ "building",
10539
+ "uploading",
10540
+ "done"
10541
+ ]);
10542
+ /**
10543
+ * Observable state of one backup run — readable WHILE it runs via
10544
+ * `backup.listRuns`. This is what makes the execution queue and
10545
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10546
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10547
+ * diagnosable with `du` because nothing reported that runs existed or
10548
+ * how large the staged archive had grown.
10549
+ */
10550
+ var BackupRunSchema = object({
10551
+ /** Stable run id — the handle `backup.cancel` takes. */
10552
+ id: string(),
10553
+ state: BackupRunStateSchema,
10554
+ phase: BackupRunPhaseSchema,
10555
+ /**
10556
+ * Resolved destination location ids. Empty while queued (targets are
10557
+ * resolved when the run starts, against the then-current policies).
10558
+ */
10559
+ destinationIds: array(string()).readonly(),
10560
+ label: string().optional(),
10561
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10562
+ requestedAt: number(),
10563
+ /** ms-epoch when the run left the queue and started building. */
10564
+ startedAt: number().optional(),
10565
+ /** ms-epoch when the run reached a terminal state. */
10566
+ finishedAt: number().optional(),
10567
+ /** Compressed bytes of the staging archive written so far. */
10568
+ stagedBytes: number(),
10569
+ /** Final staged archive size, once the build phase completes. */
10570
+ archiveSizeBytes: number().optional(),
10571
+ /** Bytes pushed to the destination currently uploading. */
10572
+ uploadedBytes: number(),
10573
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10574
+ completedDestinationIds: array(string()).readonly(),
10575
+ /** Destinations that failed during the fan-out. */
10576
+ failedDestinationIds: array(string()).readonly(),
10577
+ /** Failure message when `state === 'failed'`. */
10578
+ error: string().optional(),
10579
+ /**
10580
+ * 1-based place in the execution queue — 1 = runs next. Present only
10581
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10582
+ * queue's OWN pending order, never derived from timestamps, so the
10583
+ * UI cannot show an order the executor will not honour.
10584
+ */
10585
+ queuePosition: number().int().min(1).optional()
10586
+ });
10587
+ /**
10588
+ * Result of `backup.trigger`. The call still resolves when the run
10589
+ * terminates (compat with schedule-driven runs and the admin UI), but
10590
+ * it now names the run and says whether it had to WAIT: a trigger that
10591
+ * arrives while another run is in flight is enqueued (or joined onto
10592
+ * an identical already-queued run), never started concurrently.
10593
+ */
10594
+ var BackupTriggerResultSchema = object({
10595
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10596
+ runId: string(),
10597
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10598
+ queued: boolean(),
10599
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10600
+ joined: boolean(),
10601
+ /** True when the run was cancelled before completing every destination. */
10602
+ cancelled: boolean(),
10603
+ /** One entry per destination the archive landed at (partial on cancel). */
10604
+ entries: array(BackupEntrySchema).readonly()
10605
+ });
10523
10606
  /**
10524
10607
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10525
10608
  * SET of destination locations. Supersedes the per-location cron on
@@ -10567,7 +10650,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10567
10650
  * retention (manual runs).
10568
10651
  */
10569
10652
  retentionCount: number().int().min(1).max(1e3).optional()
10570
- }).optional(), array(BackupEntrySchema).readonly(), {
10653
+ }).optional(), BackupTriggerResultSchema, {
10654
+ kind: "mutation",
10655
+ auth: "admin"
10656
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10571
10657
  kind: "mutation",
10572
10658
  auth: "admin"
10573
10659
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11284,6 +11370,14 @@ method(object({
11284
11370
  }), object({ success: literal(true) }), {
11285
11371
  kind: "mutation",
11286
11372
  auth: "admin"
11373
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11374
+ derivedStreamsDeleted: array(string()).readonly(),
11375
+ assignmentsPurged: boolean(),
11376
+ probeSnapshotsDropped: number().int().nonnegative(),
11377
+ rtspTokenRowsDeleted: number().int().nonnegative()
11378
+ }), {
11379
+ kind: "mutation",
11380
+ auth: "admin"
11287
11381
  }), method(object({
11288
11382
  deviceId: number(),
11289
11383
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19176,7 +19270,20 @@ var RecentTracksQueryInput = object({
19176
19270
  projection: TrackProjectionSchema.optional(),
19177
19271
  /** Include stationary-promoted rows (parked objects). Default false: the
19178
19272
  * feed lists passages; parking records live on the stationary registry. */
19179
- includeStationary: boolean().optional()
19273
+ includeStationary: boolean().optional(),
19274
+ /**
19275
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19276
+ *
19277
+ * The same filter `listTracks` takes, because the timeline's class chips must
19278
+ * mean the same thing whether the scope is one camera or twelve. Until this
19279
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19280
+ * while the single-camera path narrowed the read — one filter, two costs.
19281
+ *
19282
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19283
+ * whose class list is unreadable are kept, and the client's rule stays the
19284
+ * exact one.
19285
+ */
19286
+ classes: array(string()).optional()
19180
19287
  });
19181
19288
  var RecentTracksPageSchema = object({
19182
19289
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23450,8 +23557,22 @@ var automationControlCapability = {
23450
23557
  * threshold.
23451
23558
  */
23452
23559
  var BatteryStatusSchema = object({
23453
- /** 0..100 inclusive. Firmware-reported. */
23454
- percentage: number().min(0).max(100),
23560
+ /**
23561
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23562
+ * provider has registered the capability but no reading has landed.
23563
+ *
23564
+ * It is nullable because it was not, and the only value a provider could
23565
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23566
+ * itself at 0% on every start and corrected itself a moment later, which is
23567
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23568
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23569
+ * reading the difference is an alarm.
23570
+ *
23571
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23572
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23573
+ * declines to band a non-finite reading, which is the correct shape.
23574
+ */
23575
+ percentage: number().min(0).max(100).nullable(),
23455
23576
  /**
23456
23577
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23457
23578
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33704,6 +33825,12 @@ Object.freeze({
33704
33825
  addonId: null,
33705
33826
  access: "create"
33706
33827
  },
33828
+ "backup.cancel": {
33829
+ capName: "backup",
33830
+ capScope: "system",
33831
+ addonId: null,
33832
+ access: "create"
33833
+ },
33707
33834
  "backup.delete": {
33708
33835
  capName: "backup",
33709
33836
  capScope: "system",
@@ -33746,6 +33873,12 @@ Object.freeze({
33746
33873
  addonId: null,
33747
33874
  access: "view"
33748
33875
  },
33876
+ "backup.listRuns": {
33877
+ capName: "backup",
33878
+ capScope: "system",
33879
+ addonId: null,
33880
+ access: "view"
33881
+ },
33749
33882
  "backup.listSchedules": {
33750
33883
  capName: "backup",
33751
33884
  capScope: "system",
@@ -38312,6 +38445,12 @@ Object.freeze({
38312
38445
  addonId: null,
38313
38446
  access: "create"
38314
38447
  },
38448
+ "streamBroker.forgetDeviceHardware": {
38449
+ capName: "stream-broker",
38450
+ capScope: "system",
38451
+ addonId: null,
38452
+ access: "delete"
38453
+ },
38315
38454
  "streamBroker.getAllRtspEntries": {
38316
38455
  capName: "stream-broker",
38317
38456
  capScope: "system",
@@ -40770,6 +40909,11 @@ Object.freeze({
40770
40909
  form: "single",
40771
40910
  optional: false
40772
40911
  }],
40912
+ "streamBroker.forgetDeviceHardware": [{
40913
+ name: "deviceId",
40914
+ form: "single",
40915
+ optional: false
40916
+ }],
40773
40917
  "streamBroker.getDeviceAudioMute": [{
40774
40918
  name: "deviceId",
40775
40919
  form: "single",
package/dist/addon.mjs CHANGED
@@ -10521,6 +10521,89 @@ var LocationStatSchema = object({
10521
10521
  fileCount: number(),
10522
10522
  present: boolean()
10523
10523
  });
10524
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10525
+ var BackupRunStateSchema = _enum([
10526
+ "queued",
10527
+ "running",
10528
+ "succeeded",
10529
+ "failed",
10530
+ "cancelled"
10531
+ ]);
10532
+ /**
10533
+ * Where a running backup currently is. `queued` before it starts,
10534
+ * `building` while the tar.gz is being staged, `uploading` during the
10535
+ * per-destination fan-out, `done` once terminal.
10536
+ */
10537
+ var BackupRunPhaseSchema = _enum([
10538
+ "queued",
10539
+ "building",
10540
+ "uploading",
10541
+ "done"
10542
+ ]);
10543
+ /**
10544
+ * Observable state of one backup run — readable WHILE it runs via
10545
+ * `backup.listRuns`. This is what makes the execution queue and
10546
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10547
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10548
+ * diagnosable with `du` because nothing reported that runs existed or
10549
+ * how large the staged archive had grown.
10550
+ */
10551
+ var BackupRunSchema = object({
10552
+ /** Stable run id — the handle `backup.cancel` takes. */
10553
+ id: string(),
10554
+ state: BackupRunStateSchema,
10555
+ phase: BackupRunPhaseSchema,
10556
+ /**
10557
+ * Resolved destination location ids. Empty while queued (targets are
10558
+ * resolved when the run starts, against the then-current policies).
10559
+ */
10560
+ destinationIds: array(string()).readonly(),
10561
+ label: string().optional(),
10562
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10563
+ requestedAt: number(),
10564
+ /** ms-epoch when the run left the queue and started building. */
10565
+ startedAt: number().optional(),
10566
+ /** ms-epoch when the run reached a terminal state. */
10567
+ finishedAt: number().optional(),
10568
+ /** Compressed bytes of the staging archive written so far. */
10569
+ stagedBytes: number(),
10570
+ /** Final staged archive size, once the build phase completes. */
10571
+ archiveSizeBytes: number().optional(),
10572
+ /** Bytes pushed to the destination currently uploading. */
10573
+ uploadedBytes: number(),
10574
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10575
+ completedDestinationIds: array(string()).readonly(),
10576
+ /** Destinations that failed during the fan-out. */
10577
+ failedDestinationIds: array(string()).readonly(),
10578
+ /** Failure message when `state === 'failed'`. */
10579
+ error: string().optional(),
10580
+ /**
10581
+ * 1-based place in the execution queue — 1 = runs next. Present only
10582
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10583
+ * queue's OWN pending order, never derived from timestamps, so the
10584
+ * UI cannot show an order the executor will not honour.
10585
+ */
10586
+ queuePosition: number().int().min(1).optional()
10587
+ });
10588
+ /**
10589
+ * Result of `backup.trigger`. The call still resolves when the run
10590
+ * terminates (compat with schedule-driven runs and the admin UI), but
10591
+ * it now names the run and says whether it had to WAIT: a trigger that
10592
+ * arrives while another run is in flight is enqueued (or joined onto
10593
+ * an identical already-queued run), never started concurrently.
10594
+ */
10595
+ var BackupTriggerResultSchema = object({
10596
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10597
+ runId: string(),
10598
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10599
+ queued: boolean(),
10600
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10601
+ joined: boolean(),
10602
+ /** True when the run was cancelled before completing every destination. */
10603
+ cancelled: boolean(),
10604
+ /** One entry per destination the archive landed at (partial on cancel). */
10605
+ entries: array(BackupEntrySchema).readonly()
10606
+ });
10524
10607
  /**
10525
10608
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10526
10609
  * SET of destination locations. Supersedes the per-location cron on
@@ -10568,7 +10651,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10568
10651
  * retention (manual runs).
10569
10652
  */
10570
10653
  retentionCount: number().int().min(1).max(1e3).optional()
10571
- }).optional(), array(BackupEntrySchema).readonly(), {
10654
+ }).optional(), BackupTriggerResultSchema, {
10655
+ kind: "mutation",
10656
+ auth: "admin"
10657
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10572
10658
  kind: "mutation",
10573
10659
  auth: "admin"
10574
10660
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11285,6 +11371,14 @@ method(object({
11285
11371
  }), object({ success: literal(true) }), {
11286
11372
  kind: "mutation",
11287
11373
  auth: "admin"
11374
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11375
+ derivedStreamsDeleted: array(string()).readonly(),
11376
+ assignmentsPurged: boolean(),
11377
+ probeSnapshotsDropped: number().int().nonnegative(),
11378
+ rtspTokenRowsDeleted: number().int().nonnegative()
11379
+ }), {
11380
+ kind: "mutation",
11381
+ auth: "admin"
11288
11382
  }), method(object({
11289
11383
  deviceId: number(),
11290
11384
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19177,7 +19271,20 @@ var RecentTracksQueryInput = object({
19177
19271
  projection: TrackProjectionSchema.optional(),
19178
19272
  /** Include stationary-promoted rows (parked objects). Default false: the
19179
19273
  * feed lists passages; parking records live on the stationary registry. */
19180
- includeStationary: boolean().optional()
19274
+ includeStationary: boolean().optional(),
19275
+ /**
19276
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19277
+ *
19278
+ * The same filter `listTracks` takes, because the timeline's class chips must
19279
+ * mean the same thing whether the scope is one camera or twelve. Until this
19280
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19281
+ * while the single-camera path narrowed the read — one filter, two costs.
19282
+ *
19283
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19284
+ * whose class list is unreadable are kept, and the client's rule stays the
19285
+ * exact one.
19286
+ */
19287
+ classes: array(string()).optional()
19181
19288
  });
19182
19289
  var RecentTracksPageSchema = object({
19183
19290
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23451,8 +23558,22 @@ var automationControlCapability = {
23451
23558
  * threshold.
23452
23559
  */
23453
23560
  var BatteryStatusSchema = object({
23454
- /** 0..100 inclusive. Firmware-reported. */
23455
- percentage: number().min(0).max(100),
23561
+ /**
23562
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23563
+ * provider has registered the capability but no reading has landed.
23564
+ *
23565
+ * It is nullable because it was not, and the only value a provider could
23566
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23567
+ * itself at 0% on every start and corrected itself a moment later, which is
23568
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23569
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23570
+ * reading the difference is an alarm.
23571
+ *
23572
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23573
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23574
+ * declines to band a non-finite reading, which is the correct shape.
23575
+ */
23576
+ percentage: number().min(0).max(100).nullable(),
23456
23577
  /**
23457
23578
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23458
23579
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33705,6 +33826,12 @@ Object.freeze({
33705
33826
  addonId: null,
33706
33827
  access: "create"
33707
33828
  },
33829
+ "backup.cancel": {
33830
+ capName: "backup",
33831
+ capScope: "system",
33832
+ addonId: null,
33833
+ access: "create"
33834
+ },
33708
33835
  "backup.delete": {
33709
33836
  capName: "backup",
33710
33837
  capScope: "system",
@@ -33747,6 +33874,12 @@ Object.freeze({
33747
33874
  addonId: null,
33748
33875
  access: "view"
33749
33876
  },
33877
+ "backup.listRuns": {
33878
+ capName: "backup",
33879
+ capScope: "system",
33880
+ addonId: null,
33881
+ access: "view"
33882
+ },
33750
33883
  "backup.listSchedules": {
33751
33884
  capName: "backup",
33752
33885
  capScope: "system",
@@ -38313,6 +38446,12 @@ Object.freeze({
38313
38446
  addonId: null,
38314
38447
  access: "create"
38315
38448
  },
38449
+ "streamBroker.forgetDeviceHardware": {
38450
+ capName: "stream-broker",
38451
+ capScope: "system",
38452
+ addonId: null,
38453
+ access: "delete"
38454
+ },
38316
38455
  "streamBroker.getAllRtspEntries": {
38317
38456
  capName: "stream-broker",
38318
38457
  capScope: "system",
@@ -40771,6 +40910,11 @@ Object.freeze({
40771
40910
  form: "single",
40772
40911
  optional: false
40773
40912
  }],
40913
+ "streamBroker.forgetDeviceHardware": [{
40914
+ name: "deviceId",
40915
+ form: "single",
40916
+ optional: false
40917
+ }],
40774
40918
  "streamBroker.getDeviceAudioMute": [{
40775
40919
  name: "deviceId",
40776
40920
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-amcrest",
3
- "version": "0.2.58",
3
+ "version": "0.2.60",
4
4
  "description": "Amcrest/Dahua camera device provider addon for CamStack — Dahua CGI over HTTP(S) with digest auth (snapshot, RTSP catalog, PTZ, image/day-night config)",
5
5
  "keywords": [
6
6
  "camstack",