@camstack/addon-provider-unifi 0.2.30 → 0.2.31

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
@@ -15782,7 +15782,23 @@ var NcHistoryEntrySchema = object({
15782
15782
  updatedAt: number(),
15783
15783
  /** Failure detail — present on a `dead` row. */
15784
15784
  error: string().optional(),
15785
- subject: NcHistorySubjectSchema
15785
+ subject: NcHistorySubjectSchema,
15786
+ /**
15787
+ * Ids of the artefacts (still, then gif, then clip) this row's successful
15788
+ * delivery indexed in the artefact library — a REFERENCE, never the bytes
15789
+ * (an artefact is often megabytes; this row is durable JSON rewritten on
15790
+ * every delivery attempt). Absent on a row still pending/dead, a row
15791
+ * delivered before this field shipped, or a wiring with no artefact index.
15792
+ *
15793
+ * Resolve one to a fetchable URL with `resolveArtifactUrl` — an id
15794
+ * outlives any one URL's TTL, so a caller mints a fresh link on demand
15795
+ * rather than trusting one frozen at delivery time. `resolveArtifactUrl`
15796
+ * also answers `null` for an id whose artefact has since expired past the
15797
+ * retained shelf's own age bound — the degrade a caller (the Home
15798
+ * Assistant export) must render as "no image right now", never as a
15799
+ * broken link.
15800
+ */
15801
+ artifactIds: array(string().min(1)).optional()
15786
15802
  });
15787
15803
  /**
15788
15804
  * Query filter for `getHistory` (spec §4.2). Every field is a narrowing
@@ -16009,7 +16025,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
16009
16025
  }), method(object({}), object({
16010
16026
  catalog: array(NcConditionDescriptorSchema),
16011
16027
  taxonomy: NcTaxonomySchema.optional()
16012
- })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
16028
+ })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({ artifactId: string().min(1) }), object({ url: string().nullable() }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
16013
16029
  kind: "mutation",
16014
16030
  caller: "required"
16015
16031
  }), method(object({ snoozeId: string() }), object({ success: literal(true) }), {
@@ -27046,6 +27062,39 @@ var ReadGopBytesResultSchema = object({
27046
27062
  /** Media ms the returned fragment covers. */
27047
27063
  gopDurMs: number()
27048
27064
  });
27065
+ /**
27066
+ * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
27067
+ * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
27068
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
27069
+ * a replay needs several seconds of native pixels, not one frame.
27070
+ *
27071
+ * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
27072
+ * is `false` when the returned bytes were cut short by the read's own safety
27073
+ * byte cap before covering `[fromMs, toMs)` — a truncation, reported, not a
27074
+ * silently shorter answer. `spans-multiple-segments` is a REFUSAL, not a
27075
+ * degradation: a window whose end falls past the covering segment would need
27076
+ * bytes stitched from a second segment file (its own `ftyp`+`moov`), which is
27077
+ * not one standalone-demuxable stream — the caller's answer is to request a
27078
+ * shorter window or one aligned to a single segment, not to receive spliced
27079
+ * bytes nothing has proven decodable.
27080
+ */
27081
+ var ReadWindowBytesResultSchema = discriminatedUnion("kind", [object({
27082
+ kind: literal("ok"),
27083
+ data: _instanceof(Uint8Array),
27084
+ /** Absolute epoch ms of the returned bytes' first sample — at or before
27085
+ * the requested `fromMs` (anchored on the nearest keyframe). */
27086
+ gopStartMs: number(),
27087
+ /** Media ms the returned bytes cover, from `gopStartMs`. */
27088
+ gopDurMs: number(),
27089
+ /** `false` ⇒ the safety byte cap cut the read short before it reached
27090
+ * the requested `toMs`; the caller got fewer frames than asked for. */
27091
+ reachesRequestedEnd: boolean()
27092
+ }), object({
27093
+ kind: literal("spans-multiple-segments"),
27094
+ /** Where the covering segment's own footage runs out — informational,
27095
+ * not a retry hint (retrying the same window would refuse again). */
27096
+ segmentEndMs: number()
27097
+ })]);
27049
27098
  method(object({
27050
27099
  deviceId: number(),
27051
27100
  fromMs: number(),
@@ -27096,6 +27145,15 @@ method(object({
27096
27145
  }), ReadGopBytesResultSchema, {
27097
27146
  kind: "query",
27098
27147
  auth: "admin"
27148
+ }), method(object({
27149
+ deviceId: number(),
27150
+ profile: string(),
27151
+ startMs: number(),
27152
+ fromMs: number(),
27153
+ toMs: number()
27154
+ }), ReadWindowBytesResultSchema, {
27155
+ kind: "query",
27156
+ auth: "admin"
27099
27157
  }), method(object({
27100
27158
  deviceId: number(),
27101
27159
  config: RecordingConfigSchema
@@ -33183,6 +33241,12 @@ Object.freeze({
33183
33241
  addonId: null,
33184
33242
  access: "view"
33185
33243
  },
33244
+ "notificationRules.resolveArtifactUrl": {
33245
+ capName: "notification-rules",
33246
+ capScope: "system",
33247
+ addonId: null,
33248
+ access: "view"
33249
+ },
33186
33250
  "notificationRules.setAlarmConfig": {
33187
33251
  capName: "notification-rules",
33188
33252
  capScope: "system",
@@ -34587,6 +34651,12 @@ Object.freeze({
34587
34651
  addonId: null,
34588
34652
  access: "view"
34589
34653
  },
34654
+ "recording.readWindowBytes": {
34655
+ capName: "recording",
34656
+ capScope: "system",
34657
+ addonId: null,
34658
+ access: "view"
34659
+ },
34590
34660
  "recording.refreshStorageLocationsForMigration": {
34591
34661
  capName: "recording",
34592
34662
  capScope: "system",
@@ -37417,6 +37487,11 @@ Object.freeze({
37417
37487
  form: "single",
37418
37488
  optional: false
37419
37489
  }],
37490
+ "recording.readWindowBytes": [{
37491
+ name: "deviceId",
37492
+ form: "single",
37493
+ optional: false
37494
+ }],
37420
37495
  "recording.relocateFootage": [{
37421
37496
  name: "deviceId",
37422
37497
  form: "single",
package/dist/addon.mjs CHANGED
@@ -15781,7 +15781,23 @@ var NcHistoryEntrySchema = object({
15781
15781
  updatedAt: number(),
15782
15782
  /** Failure detail — present on a `dead` row. */
15783
15783
  error: string().optional(),
15784
- subject: NcHistorySubjectSchema
15784
+ subject: NcHistorySubjectSchema,
15785
+ /**
15786
+ * Ids of the artefacts (still, then gif, then clip) this row's successful
15787
+ * delivery indexed in the artefact library — a REFERENCE, never the bytes
15788
+ * (an artefact is often megabytes; this row is durable JSON rewritten on
15789
+ * every delivery attempt). Absent on a row still pending/dead, a row
15790
+ * delivered before this field shipped, or a wiring with no artefact index.
15791
+ *
15792
+ * Resolve one to a fetchable URL with `resolveArtifactUrl` — an id
15793
+ * outlives any one URL's TTL, so a caller mints a fresh link on demand
15794
+ * rather than trusting one frozen at delivery time. `resolveArtifactUrl`
15795
+ * also answers `null` for an id whose artefact has since expired past the
15796
+ * retained shelf's own age bound — the degrade a caller (the Home
15797
+ * Assistant export) must render as "no image right now", never as a
15798
+ * broken link.
15799
+ */
15800
+ artifactIds: array(string().min(1)).optional()
15785
15801
  });
15786
15802
  /**
15787
15803
  * Query filter for `getHistory` (spec §4.2). Every field is a narrowing
@@ -16008,7 +16024,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
16008
16024
  }), method(object({}), object({
16009
16025
  catalog: array(NcConditionDescriptorSchema),
16010
16026
  taxonomy: NcTaxonomySchema.optional()
16011
- })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
16027
+ })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({ artifactId: string().min(1) }), object({ url: string().nullable() }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
16012
16028
  kind: "mutation",
16013
16029
  caller: "required"
16014
16030
  }), method(object({ snoozeId: string() }), object({ success: literal(true) }), {
@@ -27045,6 +27061,39 @@ var ReadGopBytesResultSchema = object({
27045
27061
  /** Media ms the returned fragment covers. */
27046
27062
  gopDurMs: number()
27047
27063
  });
27064
+ /**
27065
+ * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
27066
+ * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
27067
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
27068
+ * a replay needs several seconds of native pixels, not one frame.
27069
+ *
27070
+ * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
27071
+ * is `false` when the returned bytes were cut short by the read's own safety
27072
+ * byte cap before covering `[fromMs, toMs)` — a truncation, reported, not a
27073
+ * silently shorter answer. `spans-multiple-segments` is a REFUSAL, not a
27074
+ * degradation: a window whose end falls past the covering segment would need
27075
+ * bytes stitched from a second segment file (its own `ftyp`+`moov`), which is
27076
+ * not one standalone-demuxable stream — the caller's answer is to request a
27077
+ * shorter window or one aligned to a single segment, not to receive spliced
27078
+ * bytes nothing has proven decodable.
27079
+ */
27080
+ var ReadWindowBytesResultSchema = discriminatedUnion("kind", [object({
27081
+ kind: literal("ok"),
27082
+ data: _instanceof(Uint8Array),
27083
+ /** Absolute epoch ms of the returned bytes' first sample — at or before
27084
+ * the requested `fromMs` (anchored on the nearest keyframe). */
27085
+ gopStartMs: number(),
27086
+ /** Media ms the returned bytes cover, from `gopStartMs`. */
27087
+ gopDurMs: number(),
27088
+ /** `false` ⇒ the safety byte cap cut the read short before it reached
27089
+ * the requested `toMs`; the caller got fewer frames than asked for. */
27090
+ reachesRequestedEnd: boolean()
27091
+ }), object({
27092
+ kind: literal("spans-multiple-segments"),
27093
+ /** Where the covering segment's own footage runs out — informational,
27094
+ * not a retry hint (retrying the same window would refuse again). */
27095
+ segmentEndMs: number()
27096
+ })]);
27048
27097
  method(object({
27049
27098
  deviceId: number(),
27050
27099
  fromMs: number(),
@@ -27095,6 +27144,15 @@ method(object({
27095
27144
  }), ReadGopBytesResultSchema, {
27096
27145
  kind: "query",
27097
27146
  auth: "admin"
27147
+ }), method(object({
27148
+ deviceId: number(),
27149
+ profile: string(),
27150
+ startMs: number(),
27151
+ fromMs: number(),
27152
+ toMs: number()
27153
+ }), ReadWindowBytesResultSchema, {
27154
+ kind: "query",
27155
+ auth: "admin"
27098
27156
  }), method(object({
27099
27157
  deviceId: number(),
27100
27158
  config: RecordingConfigSchema
@@ -33182,6 +33240,12 @@ Object.freeze({
33182
33240
  addonId: null,
33183
33241
  access: "view"
33184
33242
  },
33243
+ "notificationRules.resolveArtifactUrl": {
33244
+ capName: "notification-rules",
33245
+ capScope: "system",
33246
+ addonId: null,
33247
+ access: "view"
33248
+ },
33185
33249
  "notificationRules.setAlarmConfig": {
33186
33250
  capName: "notification-rules",
33187
33251
  capScope: "system",
@@ -34586,6 +34650,12 @@ Object.freeze({
34586
34650
  addonId: null,
34587
34651
  access: "view"
34588
34652
  },
34653
+ "recording.readWindowBytes": {
34654
+ capName: "recording",
34655
+ capScope: "system",
34656
+ addonId: null,
34657
+ access: "view"
34658
+ },
34589
34659
  "recording.refreshStorageLocationsForMigration": {
34590
34660
  capName: "recording",
34591
34661
  capScope: "system",
@@ -37416,6 +37486,11 @@ Object.freeze({
37416
37486
  form: "single",
37417
37487
  optional: false
37418
37488
  }],
37489
+ "recording.readWindowBytes": [{
37490
+ name: "deviceId",
37491
+ form: "single",
37492
+ optional: false
37493
+ }],
37419
37494
  "recording.relocateFootage": [{
37420
37495
  name: "deviceId",
37421
37496
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-unifi",
3
- "version": "0.2.30",
3
+ "version": "0.2.31",
4
4
  "description": "UniFi Network controller device-provider addon for CamStack — local-controller infra switches/APs (as containers) + network-client presence. NO cameras/Protect.",
5
5
  "keywords": [
6
6
  "camstack",