@camstack/types 1.2.140 → 1.2.142

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-BaEgqJNv.js");
3
- const require_sleep = require("./sleep-BwGJ_wL_.js");
3
+ const require_sleep = require("./sleep-BDmIj1HV.js");
4
4
  const require_canonical_hash = require("./canonical-hash-DNV8S5ET.js");
5
5
  const require_enums = require("./enums.js");
6
6
  const require_err_msg = require("./err-msg-COpsHMw2.js");
@@ -6616,6 +6616,89 @@ var LocationStatSchema = zod.z.object({
6616
6616
  fileCount: zod.z.number(),
6617
6617
  present: zod.z.boolean()
6618
6618
  });
6619
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
6620
+ var BackupRunStateSchema = zod.z.enum([
6621
+ "queued",
6622
+ "running",
6623
+ "succeeded",
6624
+ "failed",
6625
+ "cancelled"
6626
+ ]);
6627
+ /**
6628
+ * Where a running backup currently is. `queued` before it starts,
6629
+ * `building` while the tar.gz is being staged, `uploading` during the
6630
+ * per-destination fan-out, `done` once terminal.
6631
+ */
6632
+ var BackupRunPhaseSchema = zod.z.enum([
6633
+ "queued",
6634
+ "building",
6635
+ "uploading",
6636
+ "done"
6637
+ ]);
6638
+ /**
6639
+ * Observable state of one backup run — readable WHILE it runs via
6640
+ * `backup.listRuns`. This is what makes the execution queue and
6641
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
6642
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
6643
+ * diagnosable with `du` because nothing reported that runs existed or
6644
+ * how large the staged archive had grown.
6645
+ */
6646
+ var BackupRunSchema = zod.z.object({
6647
+ /** Stable run id — the handle `backup.cancel` takes. */
6648
+ id: zod.z.string(),
6649
+ state: BackupRunStateSchema,
6650
+ phase: BackupRunPhaseSchema,
6651
+ /**
6652
+ * Resolved destination location ids. Empty while queued (targets are
6653
+ * resolved when the run starts, against the then-current policies).
6654
+ */
6655
+ destinationIds: zod.z.array(zod.z.string()).readonly(),
6656
+ label: zod.z.string().optional(),
6657
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
6658
+ requestedAt: zod.z.number(),
6659
+ /** ms-epoch when the run left the queue and started building. */
6660
+ startedAt: zod.z.number().optional(),
6661
+ /** ms-epoch when the run reached a terminal state. */
6662
+ finishedAt: zod.z.number().optional(),
6663
+ /** Compressed bytes of the staging archive written so far. */
6664
+ stagedBytes: zod.z.number(),
6665
+ /** Final staged archive size, once the build phase completes. */
6666
+ archiveSizeBytes: zod.z.number().optional(),
6667
+ /** Bytes pushed to the destination currently uploading. */
6668
+ uploadedBytes: zod.z.number(),
6669
+ /** Destinations where the archive fully landed (uploaded + indexed). */
6670
+ completedDestinationIds: zod.z.array(zod.z.string()).readonly(),
6671
+ /** Destinations that failed during the fan-out. */
6672
+ failedDestinationIds: zod.z.array(zod.z.string()).readonly(),
6673
+ /** Failure message when `state === 'failed'`. */
6674
+ error: zod.z.string().optional(),
6675
+ /**
6676
+ * 1-based place in the execution queue — 1 = runs next. Present only
6677
+ * while `state === 'queued'`. Stamped by the orchestrator from the
6678
+ * queue's OWN pending order, never derived from timestamps, so the
6679
+ * UI cannot show an order the executor will not honour.
6680
+ */
6681
+ queuePosition: zod.z.number().int().min(1).optional()
6682
+ });
6683
+ /**
6684
+ * Result of `backup.trigger`. The call still resolves when the run
6685
+ * terminates (compat with schedule-driven runs and the admin UI), but
6686
+ * it now names the run and says whether it had to WAIT: a trigger that
6687
+ * arrives while another run is in flight is enqueued (or joined onto
6688
+ * an identical already-queued run), never started concurrently.
6689
+ */
6690
+ var BackupTriggerResultSchema = zod.z.object({
6691
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
6692
+ runId: zod.z.string(),
6693
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
6694
+ queued: zod.z.boolean(),
6695
+ /** True when this trigger was coalesced onto an identical already-queued run. */
6696
+ joined: zod.z.boolean(),
6697
+ /** True when the run was cancelled before completing every destination. */
6698
+ cancelled: zod.z.boolean(),
6699
+ /** One entry per destination the archive landed at (partial on cancel). */
6700
+ entries: zod.z.array(BackupEntrySchema).readonly()
6701
+ });
6619
6702
  /**
6620
6703
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
6621
6704
  * SET of destination locations. Supersedes the per-location cron on
@@ -6673,6 +6756,11 @@ var backupCapability = {
6673
6756
  * Trigger a backup. Without `destinations` the orchestrator fans
6674
6757
  * out to every destination flagged as enabled in the routing
6675
6758
  * config; with it, only the listed addons receive the archive.
6759
+ *
6760
+ * At most ONE backup run executes at a time — the source tree and
6761
+ * the staging disk are shared by every run, so a second trigger
6762
+ * while one is in flight is enqueued (or joined onto an identical
6763
+ * queued run) and the result says so. See D342.
6676
6764
  */
6677
6765
  trigger: require_sleep.method(zod.z.object({
6678
6766
  /** Subset of registered `backup-destination` addon ids to write to. */
@@ -6686,7 +6774,30 @@ var backupCapability = {
6686
6774
  * retention (manual runs).
6687
6775
  */
6688
6776
  retentionCount: zod.z.number().int().min(1).max(1e3).optional()
6689
- }).optional(), zod.z.array(BackupEntrySchema).readonly(), {
6777
+ }).optional(), BackupTriggerResultSchema, {
6778
+ kind: "mutation",
6779
+ auth: "admin"
6780
+ }),
6781
+ /**
6782
+ * Every run the orchestrator knows about, in EXECUTION order: the
6783
+ * running run first, then queued runs in the exact order they will
6784
+ * execute (each with `queuePosition`, 1 = next), then the bounded
6785
+ * finished history newest-first. Only one run executes at a time
6786
+ * (D342) — the queued section IS the line. Each run carries live
6787
+ * phase + byte counters so a runaway build is visible in seconds,
6788
+ * not via `du`.
6789
+ */
6790
+ listRuns: require_sleep.method(zod.z.void(), zod.z.array(BackupRunSchema).readonly(), { auth: "admin" }),
6791
+ /**
6792
+ * Stop a backup run. Mirrors `storage-migration.cancel` semantics:
6793
+ * id in, `{ cancelled }` out — `false` when the run is unknown or
6794
+ * already terminal. A QUEUED run is removed before it ever starts;
6795
+ * the RUNNING run has its tar/upload stream actually aborted, the
6796
+ * half-written staging archive is deleted, and the in-flight
6797
+ * destination upload is aborted server-side (partial discarded).
6798
+ * Destinations that already completed keep their archive.
6799
+ */
6800
+ cancel: require_sleep.method(zod.z.object({ runId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
6690
6801
  kind: "mutation",
6691
6802
  auth: "admin"
6692
6803
  }),
@@ -7570,6 +7681,38 @@ var streamBrokerCapability = {
7570
7681
  auth: "admin"
7571
7682
  }),
7572
7683
  /**
7684
+ * The HARDWARE behind a device number was replaced
7685
+ * (`deviceManager.migrateDevice`). Forget every piece of broker state that
7686
+ * described the old box, so the next catalog pull derives everything from
7687
+ * the camera that is actually there:
7688
+ *
7689
+ * - every `derived:*` stream definition — a derived is authored against a
7690
+ * specific profile layout, and against the wrong hardware its feeder
7691
+ * respawns forever (observed at attempt 2732 on the live hub,
7692
+ * 2026-09-01);
7693
+ * - the profile-slot assignment entry, PURGED (not unassigned — unassign
7694
+ * marks the slot manual, which would pin the stale choice instead of
7695
+ * letting `computeInitialAssignment` re-derive it);
7696
+ * - the probe snapshots (`<deviceId>/…` — probed codec/resolution of the
7697
+ * old hardware);
7698
+ * - the persisted RTSP token rows for the device's brokers (keyed
7699
+ * `<deviceId>/<camStreamId>`; the stream ids change with the hardware,
7700
+ * so the rows are dead URLs).
7701
+ *
7702
+ * An RPC, deliberately — an event is telemetry and may be dropped (D8),
7703
+ * and a dropped forget leaves a feeder respawning against a stream that
7704
+ * does not exist.
7705
+ */
7706
+ forgetDeviceHardware: require_sleep.method(zod.z.object({ deviceId: zod.z.number().int().nonnegative() }), zod.z.object({
7707
+ derivedStreamsDeleted: zod.z.array(zod.z.string()).readonly(),
7708
+ assignmentsPurged: zod.z.boolean(),
7709
+ probeSnapshotsDropped: zod.z.number().int().nonnegative(),
7710
+ rtspTokenRowsDeleted: zod.z.number().int().nonnegative()
7711
+ }), {
7712
+ kind: "mutation",
7713
+ auth: "admin"
7714
+ }),
7715
+ /**
7573
7716
  * Render a short GIF or MP4 from the broker's PRE-BUFFER around an instant.
7574
7717
  *
7575
7718
  * The pre-buffer is the only source that already holds the seconds BEFORE
@@ -18783,7 +18926,20 @@ var RecentTracksQueryInput = zod.z.object({
18783
18926
  projection: TrackProjectionSchema.optional(),
18784
18927
  /** Include stationary-promoted rows (parked objects). Default false: the
18785
18928
  * feed lists passages; parking records live on the stationary registry. */
18786
- includeStationary: zod.z.boolean().optional()
18929
+ includeStationary: zod.z.boolean().optional(),
18930
+ /**
18931
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
18932
+ *
18933
+ * The same filter `listTracks` takes, because the timeline's class chips must
18934
+ * mean the same thing whether the scope is one camera or twelve. Until this
18935
+ * existed the scoped feed downloaded a page and narrowed it on the phone
18936
+ * while the single-camera path narrowed the read — one filter, two costs.
18937
+ *
18938
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
18939
+ * whose class list is unreadable are kept, and the client's rule stays the
18940
+ * exact one.
18941
+ */
18942
+ classes: zod.z.array(zod.z.string()).optional()
18787
18943
  });
18788
18944
  var RecentTracksPageSchema = zod.z.object({
18789
18945
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -25123,8 +25279,22 @@ var automationControlCapability = {
25123
25279
  * threshold.
25124
25280
  */
25125
25281
  var BatteryStatusSchema = zod.z.object({
25126
- /** 0..100 inclusive. Firmware-reported. */
25127
- percentage: zod.z.number().min(0).max(100),
25282
+ /**
25283
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
25284
+ * provider has registered the capability but no reading has landed.
25285
+ *
25286
+ * It is nullable because it was not, and the only value a provider could
25287
+ * seed with was `0`. A battery camera behind an NVR therefore announced
25288
+ * itself at 0% on every start and corrected itself a moment later, which is
25289
+ * indistinguishable from a real flat battery: it fires the low-battery alert
25290
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
25291
+ * reading the difference is an alarm.
25292
+ *
25293
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
25294
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
25295
+ * declines to band a non-finite reading, which is the correct shape.
25296
+ */
25297
+ percentage: zod.z.number().min(0).max(100).nullable(),
25128
25298
  /**
25129
25299
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
25130
25300
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -35273,6 +35443,15 @@ var RUNTIME_DEFAULTS = {
35273
35443
  * Each carried the same list and a comment asking the others to stay in sync.
35274
35444
  * This is that list, in the one package all of them already depend on.
35275
35445
  *
35446
+ * `ui-library` and the server's linked-devices expansion IMPORT it. Two
35447
+ * consumers cannot, and keep a checked copy instead: the viewer resolves
35448
+ * `@camstack/types` from its own `node_modules` (an installed release, where a
35449
+ * newly added export simply is not there), and the Home Assistant provider
35450
+ * expresses the same precedence over the `DeviceType` enum because it answers
35451
+ * a different question from the same ordering. `scripts/check-container-
35452
+ * priority-in-sync.ts` fails the build when either drifts — the comment that
35453
+ * used to ask for this could not.
35454
+ *
35276
35455
  * The rule has two halves and the ORDER matters: an operator's explicit pick
35277
35456
  * wins outright, and only in its absence does type priority decide. The pick is
35278
35457
  * keyed on the child's re-sync-stable `entityId`, not its numeric id, so it
@@ -35328,7 +35507,7 @@ function rank(type) {
35328
35507
  */
35329
35508
  function resolveContainerPrimaryChild(children, overrideEntityId) {
35330
35509
  if (overrideEntityId !== void 0 && overrideEntityId !== null) {
35331
- const picked = children.find((c) => c.entityId === overrideEntityId);
35510
+ const picked = children.find((c) => c.stableId === overrideEntityId) ?? children.find((c) => c.entityId !== void 0 && c.entityId === overrideEntityId);
35332
35511
  if (picked !== void 0) return picked;
35333
35512
  }
35334
35513
  return [...children].toSorted((a, b) => rank(a.type) - rank(b.type))[0] ?? null;
@@ -39600,6 +39779,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
39600
39779
  addonId: null,
39601
39780
  access: "create"
39602
39781
  },
39782
+ "backup.cancel": {
39783
+ capName: "backup",
39784
+ capScope: "system",
39785
+ addonId: null,
39786
+ access: "create"
39787
+ },
39603
39788
  "backup.delete": {
39604
39789
  capName: "backup",
39605
39790
  capScope: "system",
@@ -39642,6 +39827,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
39642
39827
  addonId: null,
39643
39828
  access: "view"
39644
39829
  },
39830
+ "backup.listRuns": {
39831
+ capName: "backup",
39832
+ capScope: "system",
39833
+ addonId: null,
39834
+ access: "view"
39835
+ },
39645
39836
  "backup.listSchedules": {
39646
39837
  capName: "backup",
39647
39838
  capScope: "system",
@@ -44208,6 +44399,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
44208
44399
  addonId: null,
44209
44400
  access: "create"
44210
44401
  },
44402
+ "streamBroker.forgetDeviceHardware": {
44403
+ capName: "stream-broker",
44404
+ capScope: "system",
44405
+ addonId: null,
44406
+ access: "delete"
44407
+ },
44211
44408
  "streamBroker.getAllRtspEntries": {
44212
44409
  capName: "stream-broker",
44213
44410
  capScope: "system",
@@ -46929,6 +47126,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
46929
47126
  form: "single",
46930
47127
  optional: false
46931
47128
  }],
47129
+ "streamBroker.forgetDeviceHardware": [{
47130
+ name: "deviceId",
47131
+ form: "single",
47132
+ optional: false
47133
+ }],
46932
47134
  "streamBroker.getDeviceAudioMute": [{
46933
47135
  name: "deviceId",
46934
47136
  form: "single",
@@ -47302,6 +47504,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
47302
47504
  "recordingExport.listExports",
47303
47505
  "streamBroker.acquireEgressTranscode",
47304
47506
  "streamBroker.assignProfile",
47507
+ "streamBroker.forgetDeviceHardware",
47305
47508
  "streamBroker.getDeviceAudioMute",
47306
47509
  "streamBroker.getStreamWithCodec",
47307
47510
  "streamBroker.produceEventMedia",
@@ -47845,6 +48048,8 @@ function createSystemProxy(api) {
47845
48048
  backup: {
47846
48049
  listDestinations: (input) => dispatch("backup", "listDestinations", "query", input),
47847
48050
  trigger: (input) => dispatch("backup", "trigger", "mutation", input),
48051
+ listRuns: (input) => dispatch("backup", "listRuns", "query", input),
48052
+ cancel: (input) => dispatch("backup", "cancel", "mutation", input),
47848
48053
  list: (input) => dispatch("backup", "list", "query", input),
47849
48054
  listLocations: (input) => dispatch("backup", "listLocations", "query", input),
47850
48055
  getEntries: (input) => dispatch("backup", "getEntries", "query", input),
@@ -52414,6 +52619,10 @@ exports.BOOT_RECOVERY_BACKOFF_MS = require_sleep.BOOT_RECOVERY_BACKOFF_MS;
52414
52619
  exports.BacklightModeSchema = BacklightModeSchema;
52415
52620
  exports.BackupDestinationInfoSchema = BackupDestinationInfoSchema;
52416
52621
  exports.BackupEntrySchema = BackupEntrySchema;
52622
+ exports.BackupRunPhaseSchema = BackupRunPhaseSchema;
52623
+ exports.BackupRunSchema = BackupRunSchema;
52624
+ exports.BackupRunStateSchema = BackupRunStateSchema;
52625
+ exports.BackupTriggerResultSchema = BackupTriggerResultSchema;
52417
52626
  exports.BaseAddon = require_sleep.BaseAddon;
52418
52627
  exports.BaseDevice = BaseDevice;
52419
52628
  exports.BaseDeviceProvider = BaseDeviceProvider;