@camstack/addon-smtp-nodemailer 1.2.56 → 1.2.58

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.
@@ -10548,6 +10548,89 @@ var LocationStatSchema = object({
10548
10548
  fileCount: number(),
10549
10549
  present: boolean()
10550
10550
  });
10551
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10552
+ var BackupRunStateSchema = _enum([
10553
+ "queued",
10554
+ "running",
10555
+ "succeeded",
10556
+ "failed",
10557
+ "cancelled"
10558
+ ]);
10559
+ /**
10560
+ * Where a running backup currently is. `queued` before it starts,
10561
+ * `building` while the tar.gz is being staged, `uploading` during the
10562
+ * per-destination fan-out, `done` once terminal.
10563
+ */
10564
+ var BackupRunPhaseSchema = _enum([
10565
+ "queued",
10566
+ "building",
10567
+ "uploading",
10568
+ "done"
10569
+ ]);
10570
+ /**
10571
+ * Observable state of one backup run — readable WHILE it runs via
10572
+ * `backup.listRuns`. This is what makes the execution queue and
10573
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10574
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10575
+ * diagnosable with `du` because nothing reported that runs existed or
10576
+ * how large the staged archive had grown.
10577
+ */
10578
+ var BackupRunSchema = object({
10579
+ /** Stable run id — the handle `backup.cancel` takes. */
10580
+ id: string(),
10581
+ state: BackupRunStateSchema,
10582
+ phase: BackupRunPhaseSchema,
10583
+ /**
10584
+ * Resolved destination location ids. Empty while queued (targets are
10585
+ * resolved when the run starts, against the then-current policies).
10586
+ */
10587
+ destinationIds: array(string()).readonly(),
10588
+ label: string().optional(),
10589
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10590
+ requestedAt: number(),
10591
+ /** ms-epoch when the run left the queue and started building. */
10592
+ startedAt: number().optional(),
10593
+ /** ms-epoch when the run reached a terminal state. */
10594
+ finishedAt: number().optional(),
10595
+ /** Compressed bytes of the staging archive written so far. */
10596
+ stagedBytes: number(),
10597
+ /** Final staged archive size, once the build phase completes. */
10598
+ archiveSizeBytes: number().optional(),
10599
+ /** Bytes pushed to the destination currently uploading. */
10600
+ uploadedBytes: number(),
10601
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10602
+ completedDestinationIds: array(string()).readonly(),
10603
+ /** Destinations that failed during the fan-out. */
10604
+ failedDestinationIds: array(string()).readonly(),
10605
+ /** Failure message when `state === 'failed'`. */
10606
+ error: string().optional(),
10607
+ /**
10608
+ * 1-based place in the execution queue — 1 = runs next. Present only
10609
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10610
+ * queue's OWN pending order, never derived from timestamps, so the
10611
+ * UI cannot show an order the executor will not honour.
10612
+ */
10613
+ queuePosition: number().int().min(1).optional()
10614
+ });
10615
+ /**
10616
+ * Result of `backup.trigger`. The call still resolves when the run
10617
+ * terminates (compat with schedule-driven runs and the admin UI), but
10618
+ * it now names the run and says whether it had to WAIT: a trigger that
10619
+ * arrives while another run is in flight is enqueued (or joined onto
10620
+ * an identical already-queued run), never started concurrently.
10621
+ */
10622
+ var BackupTriggerResultSchema = object({
10623
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10624
+ runId: string(),
10625
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10626
+ queued: boolean(),
10627
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10628
+ joined: boolean(),
10629
+ /** True when the run was cancelled before completing every destination. */
10630
+ cancelled: boolean(),
10631
+ /** One entry per destination the archive landed at (partial on cancel). */
10632
+ entries: array(BackupEntrySchema).readonly()
10633
+ });
10551
10634
  /**
10552
10635
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10553
10636
  * SET of destination locations. Supersedes the per-location cron on
@@ -10595,7 +10678,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10595
10678
  * retention (manual runs).
10596
10679
  */
10597
10680
  retentionCount: number().int().min(1).max(1e3).optional()
10598
- }).optional(), array(BackupEntrySchema).readonly(), {
10681
+ }).optional(), BackupTriggerResultSchema, {
10682
+ kind: "mutation",
10683
+ auth: "admin"
10684
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10599
10685
  kind: "mutation",
10600
10686
  auth: "admin"
10601
10687
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11312,6 +11398,14 @@ method(object({
11312
11398
  }), object({ success: literal(true) }), {
11313
11399
  kind: "mutation",
11314
11400
  auth: "admin"
11401
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11402
+ derivedStreamsDeleted: array(string()).readonly(),
11403
+ assignmentsPurged: boolean(),
11404
+ probeSnapshotsDropped: number().int().nonnegative(),
11405
+ rtspTokenRowsDeleted: number().int().nonnegative()
11406
+ }), {
11407
+ kind: "mutation",
11408
+ auth: "admin"
11315
11409
  }), method(object({
11316
11410
  deviceId: number(),
11317
11411
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -18862,7 +18956,20 @@ var RecentTracksQueryInput = object({
18862
18956
  projection: TrackProjectionSchema.optional(),
18863
18957
  /** Include stationary-promoted rows (parked objects). Default false: the
18864
18958
  * feed lists passages; parking records live on the stationary registry. */
18865
- includeStationary: boolean().optional()
18959
+ includeStationary: boolean().optional(),
18960
+ /**
18961
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
18962
+ *
18963
+ * The same filter `listTracks` takes, because the timeline's class chips must
18964
+ * mean the same thing whether the scope is one camera or twelve. Until this
18965
+ * existed the scoped feed downloaded a page and narrowed it on the phone
18966
+ * while the single-camera path narrowed the read — one filter, two costs.
18967
+ *
18968
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
18969
+ * whose class list is unreadable are kept, and the client's rule stays the
18970
+ * exact one.
18971
+ */
18972
+ classes: array(string()).optional()
18866
18973
  });
18867
18974
  var RecentTracksPageSchema = object({
18868
18975
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -22913,8 +23020,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
22913
23020
  * threshold.
22914
23021
  */
22915
23022
  var BatteryStatusSchema = object({
22916
- /** 0..100 inclusive. Firmware-reported. */
22917
- percentage: number().min(0).max(100),
23023
+ /**
23024
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23025
+ * provider has registered the capability but no reading has landed.
23026
+ *
23027
+ * It is nullable because it was not, and the only value a provider could
23028
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23029
+ * itself at 0% on every start and corrected itself a moment later, which is
23030
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23031
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23032
+ * reading the difference is an alarm.
23033
+ *
23034
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23035
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23036
+ * declines to band a non-finite reading, which is the correct shape.
23037
+ */
23038
+ percentage: number().min(0).max(100).nullable(),
22918
23039
  /**
22919
23040
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
22920
23041
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -29393,6 +29514,12 @@ Object.freeze({
29393
29514
  addonId: null,
29394
29515
  access: "create"
29395
29516
  },
29517
+ "backup.cancel": {
29518
+ capName: "backup",
29519
+ capScope: "system",
29520
+ addonId: null,
29521
+ access: "create"
29522
+ },
29396
29523
  "backup.delete": {
29397
29524
  capName: "backup",
29398
29525
  capScope: "system",
@@ -29435,6 +29562,12 @@ Object.freeze({
29435
29562
  addonId: null,
29436
29563
  access: "view"
29437
29564
  },
29565
+ "backup.listRuns": {
29566
+ capName: "backup",
29567
+ capScope: "system",
29568
+ addonId: null,
29569
+ access: "view"
29570
+ },
29438
29571
  "backup.listSchedules": {
29439
29572
  capName: "backup",
29440
29573
  capScope: "system",
@@ -34001,6 +34134,12 @@ Object.freeze({
34001
34134
  addonId: null,
34002
34135
  access: "create"
34003
34136
  },
34137
+ "streamBroker.forgetDeviceHardware": {
34138
+ capName: "stream-broker",
34139
+ capScope: "system",
34140
+ addonId: null,
34141
+ access: "delete"
34142
+ },
34004
34143
  "streamBroker.getAllRtspEntries": {
34005
34144
  capName: "stream-broker",
34006
34145
  capScope: "system",
@@ -36459,6 +36598,11 @@ Object.freeze({
36459
36598
  form: "single",
36460
36599
  optional: false
36461
36600
  }],
36601
+ "streamBroker.forgetDeviceHardware": [{
36602
+ name: "deviceId",
36603
+ form: "single",
36604
+ optional: false
36605
+ }],
36462
36606
  "streamBroker.getDeviceAudioMute": [{
36463
36607
  name: "deviceId",
36464
36608
  form: "single",
@@ -10546,6 +10546,89 @@ var LocationStatSchema = object({
10546
10546
  fileCount: number(),
10547
10547
  present: boolean()
10548
10548
  });
10549
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10550
+ var BackupRunStateSchema = _enum([
10551
+ "queued",
10552
+ "running",
10553
+ "succeeded",
10554
+ "failed",
10555
+ "cancelled"
10556
+ ]);
10557
+ /**
10558
+ * Where a running backup currently is. `queued` before it starts,
10559
+ * `building` while the tar.gz is being staged, `uploading` during the
10560
+ * per-destination fan-out, `done` once terminal.
10561
+ */
10562
+ var BackupRunPhaseSchema = _enum([
10563
+ "queued",
10564
+ "building",
10565
+ "uploading",
10566
+ "done"
10567
+ ]);
10568
+ /**
10569
+ * Observable state of one backup run — readable WHILE it runs via
10570
+ * `backup.listRuns`. This is what makes the execution queue and
10571
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10572
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10573
+ * diagnosable with `du` because nothing reported that runs existed or
10574
+ * how large the staged archive had grown.
10575
+ */
10576
+ var BackupRunSchema = object({
10577
+ /** Stable run id — the handle `backup.cancel` takes. */
10578
+ id: string(),
10579
+ state: BackupRunStateSchema,
10580
+ phase: BackupRunPhaseSchema,
10581
+ /**
10582
+ * Resolved destination location ids. Empty while queued (targets are
10583
+ * resolved when the run starts, against the then-current policies).
10584
+ */
10585
+ destinationIds: array(string()).readonly(),
10586
+ label: string().optional(),
10587
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10588
+ requestedAt: number(),
10589
+ /** ms-epoch when the run left the queue and started building. */
10590
+ startedAt: number().optional(),
10591
+ /** ms-epoch when the run reached a terminal state. */
10592
+ finishedAt: number().optional(),
10593
+ /** Compressed bytes of the staging archive written so far. */
10594
+ stagedBytes: number(),
10595
+ /** Final staged archive size, once the build phase completes. */
10596
+ archiveSizeBytes: number().optional(),
10597
+ /** Bytes pushed to the destination currently uploading. */
10598
+ uploadedBytes: number(),
10599
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10600
+ completedDestinationIds: array(string()).readonly(),
10601
+ /** Destinations that failed during the fan-out. */
10602
+ failedDestinationIds: array(string()).readonly(),
10603
+ /** Failure message when `state === 'failed'`. */
10604
+ error: string().optional(),
10605
+ /**
10606
+ * 1-based place in the execution queue — 1 = runs next. Present only
10607
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10608
+ * queue's OWN pending order, never derived from timestamps, so the
10609
+ * UI cannot show an order the executor will not honour.
10610
+ */
10611
+ queuePosition: number().int().min(1).optional()
10612
+ });
10613
+ /**
10614
+ * Result of `backup.trigger`. The call still resolves when the run
10615
+ * terminates (compat with schedule-driven runs and the admin UI), but
10616
+ * it now names the run and says whether it had to WAIT: a trigger that
10617
+ * arrives while another run is in flight is enqueued (or joined onto
10618
+ * an identical already-queued run), never started concurrently.
10619
+ */
10620
+ var BackupTriggerResultSchema = object({
10621
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10622
+ runId: string(),
10623
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10624
+ queued: boolean(),
10625
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10626
+ joined: boolean(),
10627
+ /** True when the run was cancelled before completing every destination. */
10628
+ cancelled: boolean(),
10629
+ /** One entry per destination the archive landed at (partial on cancel). */
10630
+ entries: array(BackupEntrySchema).readonly()
10631
+ });
10549
10632
  /**
10550
10633
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10551
10634
  * SET of destination locations. Supersedes the per-location cron on
@@ -10593,7 +10676,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10593
10676
  * retention (manual runs).
10594
10677
  */
10595
10678
  retentionCount: number().int().min(1).max(1e3).optional()
10596
- }).optional(), array(BackupEntrySchema).readonly(), {
10679
+ }).optional(), BackupTriggerResultSchema, {
10680
+ kind: "mutation",
10681
+ auth: "admin"
10682
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10597
10683
  kind: "mutation",
10598
10684
  auth: "admin"
10599
10685
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11310,6 +11396,14 @@ method(object({
11310
11396
  }), object({ success: literal(true) }), {
11311
11397
  kind: "mutation",
11312
11398
  auth: "admin"
11399
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11400
+ derivedStreamsDeleted: array(string()).readonly(),
11401
+ assignmentsPurged: boolean(),
11402
+ probeSnapshotsDropped: number().int().nonnegative(),
11403
+ rtspTokenRowsDeleted: number().int().nonnegative()
11404
+ }), {
11405
+ kind: "mutation",
11406
+ auth: "admin"
11313
11407
  }), method(object({
11314
11408
  deviceId: number(),
11315
11409
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -18860,7 +18954,20 @@ var RecentTracksQueryInput = object({
18860
18954
  projection: TrackProjectionSchema.optional(),
18861
18955
  /** Include stationary-promoted rows (parked objects). Default false: the
18862
18956
  * feed lists passages; parking records live on the stationary registry. */
18863
- includeStationary: boolean().optional()
18957
+ includeStationary: boolean().optional(),
18958
+ /**
18959
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
18960
+ *
18961
+ * The same filter `listTracks` takes, because the timeline's class chips must
18962
+ * mean the same thing whether the scope is one camera or twelve. Until this
18963
+ * existed the scoped feed downloaded a page and narrowed it on the phone
18964
+ * while the single-camera path narrowed the read — one filter, two costs.
18965
+ *
18966
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
18967
+ * whose class list is unreadable are kept, and the client's rule stays the
18968
+ * exact one.
18969
+ */
18970
+ classes: array(string()).optional()
18864
18971
  });
18865
18972
  var RecentTracksPageSchema = object({
18866
18973
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -22911,8 +23018,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
22911
23018
  * threshold.
22912
23019
  */
22913
23020
  var BatteryStatusSchema = object({
22914
- /** 0..100 inclusive. Firmware-reported. */
22915
- percentage: number().min(0).max(100),
23021
+ /**
23022
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23023
+ * provider has registered the capability but no reading has landed.
23024
+ *
23025
+ * It is nullable because it was not, and the only value a provider could
23026
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23027
+ * itself at 0% on every start and corrected itself a moment later, which is
23028
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23029
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23030
+ * reading the difference is an alarm.
23031
+ *
23032
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23033
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23034
+ * declines to band a non-finite reading, which is the correct shape.
23035
+ */
23036
+ percentage: number().min(0).max(100).nullable(),
22916
23037
  /**
22917
23038
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
22918
23039
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -29391,6 +29512,12 @@ Object.freeze({
29391
29512
  addonId: null,
29392
29513
  access: "create"
29393
29514
  },
29515
+ "backup.cancel": {
29516
+ capName: "backup",
29517
+ capScope: "system",
29518
+ addonId: null,
29519
+ access: "create"
29520
+ },
29394
29521
  "backup.delete": {
29395
29522
  capName: "backup",
29396
29523
  capScope: "system",
@@ -29433,6 +29560,12 @@ Object.freeze({
29433
29560
  addonId: null,
29434
29561
  access: "view"
29435
29562
  },
29563
+ "backup.listRuns": {
29564
+ capName: "backup",
29565
+ capScope: "system",
29566
+ addonId: null,
29567
+ access: "view"
29568
+ },
29436
29569
  "backup.listSchedules": {
29437
29570
  capName: "backup",
29438
29571
  capScope: "system",
@@ -33999,6 +34132,12 @@ Object.freeze({
33999
34132
  addonId: null,
34000
34133
  access: "create"
34001
34134
  },
34135
+ "streamBroker.forgetDeviceHardware": {
34136
+ capName: "stream-broker",
34137
+ capScope: "system",
34138
+ addonId: null,
34139
+ access: "delete"
34140
+ },
34002
34141
  "streamBroker.getAllRtspEntries": {
34003
34142
  capName: "stream-broker",
34004
34143
  capScope: "system",
@@ -36457,6 +36596,11 @@ Object.freeze({
36457
36596
  form: "single",
36458
36597
  optional: false
36459
36598
  }],
36599
+ "streamBroker.forgetDeviceHardware": [{
36600
+ name: "deviceId",
36601
+ form: "single",
36602
+ optional: false
36603
+ }],
36460
36604
  "streamBroker.getDeviceAudioMute": [{
36461
36605
  name: "deviceId",
36462
36606
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-smtp-nodemailer",
3
- "version": "1.2.56",
3
+ "version": "1.2.58",
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",