@camstack/system 1.2.169 → 1.2.171

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.
Files changed (62) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.mjs +1 -1
  13. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  14. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  15. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  16. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  19. package/dist/builtins/hub-forwarder/index.js +1 -1
  20. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  21. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  22. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  23. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  24. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  25. package/dist/builtins/local-network/local-network.addon.js +1 -1
  26. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  27. package/dist/builtins/loki-logging/index.js +1 -1
  28. package/dist/builtins/loki-logging/index.mjs +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  30. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  31. package/dist/builtins/platform-probe/index.js +1 -1
  32. package/dist/builtins/platform-probe/index.mjs +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  34. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  35. package/dist/builtins/snapshot/index.js +1 -1
  36. package/dist/builtins/snapshot/index.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  38. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  41. package/dist/builtins/storage-orchestrator/data-store-dispatch.d.ts +18 -6
  42. package/dist/builtins/storage-orchestrator/hub-settings-forward.d.ts +68 -0
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +27 -3
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +235 -57
  45. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +235 -57
  46. package/dist/builtins/system-config/system-config.addon.js +1 -1
  47. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  48. package/dist/builtins/winston-logging/index.js +1 -1
  49. package/dist/builtins/winston-logging/index.mjs +1 -1
  50. package/dist/{dist-digPByP6.mjs → dist-1DEQFmTq.mjs} +165 -6
  51. package/dist/{dist-D6kBG4fg.js → dist-DsoVfJSR.js} +165 -6
  52. package/dist/hub-cap-forward-BdT320dq.mjs +53 -0
  53. package/dist/hub-cap-forward-DmHNjbB0.js +70 -0
  54. package/dist/index.js +18 -199
  55. package/dist/index.mjs +22 -203
  56. package/dist/kernel/capability-registry.d.ts +8 -27
  57. package/dist/kernel/config-manager.d.ts +0 -33
  58. package/dist/{manifest-system-deps-onn-Eawl.mjs → manifest-system-deps-Da6sme9C.mjs} +3 -54
  59. package/dist/{manifest-system-deps-BjMNGEpl.js → manifest-system-deps-ir_XTNpe.js} +2 -71
  60. package/dist/{retired-settings-keys-B5D2hfoN.mjs → retired-settings-keys-ChS1Q2Kv.mjs} +1 -1
  61. package/dist/{retired-settings-keys-BywIz4dZ.js → retired-settings-keys-DTE5k4lU.js} +1 -1
  62. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { Mt as errMsg, Nt as BaseAddon, Xt as hydrateSchema } from "../../dist-digPByP6.mjs";
1
+ import { Mt as errMsg, Nt as BaseAddon, Xt as hydrateSchema } from "../../dist-1DEQFmTq.mjs";
2
2
  //#region src/builtins/system-config/system-config.addon.ts
3
3
  /**
4
4
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D6kBG4fg.js");
6
+ const require_dist = require("../../dist-DsoVfJSR.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_chunk.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { Nt as BaseAddon, st as logDestinationCapability } from "../../dist-digPByP6.mjs";
1
+ import { Nt as BaseAddon, st as logDestinationCapability } from "../../dist-1DEQFmTq.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";
@@ -17987,6 +17987,34 @@ var KeyEventsForDeviceSchema = z.object({
17987
17987
  deviceId: z.number(),
17988
17988
  events: z.array(KeyEventSchema).readonly()
17989
17989
  });
17990
+ /** One non-empty bucket of the timeline histogram. */
17991
+ var EventDensityBucketSchema = z.object({
17992
+ bucketStart: z.number(),
17993
+ motion: z.number().int(),
17994
+ object: z.number().int(),
17995
+ audio: z.number().int()
17996
+ });
17997
+ /**
17998
+ * One camera's row in a `getEventDensityBatch` answer.
17999
+ *
18000
+ * TWO facts, and the timeline draws them differently:
18001
+ *
18002
+ * - `read: 'read'` — the histogram for this camera. `buckets: []` is a real
18003
+ * claim: read, and nothing happened in the window.
18004
+ * - `read: 'unreadable'` — nobody could answer for this camera. `buckets` is
18005
+ * empty and that emptiness means NOTHING; the timeline must render unknown,
18006
+ * not quiet.
18007
+ *
18008
+ * Fanned out per camera the difference was free — one query rejected while the
18009
+ * others resolved — and collapsing to a batch is the exact moment it is lost
18010
+ * silently. Every requested id gets a row: a caller that asked for twelve and
18011
+ * got eleven cannot tell which one is missing, or that any is.
18012
+ */
18013
+ var EventDensityForDeviceSchema = z.object({
18014
+ deviceId: z.number(),
18015
+ read: z.enum(["read", "unreadable"]),
18016
+ buckets: z.array(EventDensityBucketSchema).readonly()
18017
+ });
17990
18018
  z.object({
17991
18019
  trackId: z.string(),
17992
18020
  className: z.string(),
@@ -18387,12 +18415,31 @@ var pipelineAnalyticsCapability = {
18387
18415
  since: z.number(),
18388
18416
  until: z.number(),
18389
18417
  bucketMs: z.number().int().positive()
18390
- }), z.array(z.object({
18391
- bucketStart: z.number(),
18392
- motion: z.number().int(),
18393
- object: z.number().int(),
18394
- audio: z.number().int()
18395
- })).readonly()),
18418
+ }), z.array(EventDensityBucketSchema).readonly()),
18419
+ /**
18420
+ * The same histogram, for a SET of cameras, in one round trip.
18421
+ *
18422
+ * A multi-camera timeline (the tablet grid) re-asks this of every camera in
18423
+ * the grid on every day change — N browser → hub → post-analysis round
18424
+ * trips for N independent, already-indexed store queries. The queries are
18425
+ * unchanged and still run per camera (`densityByKind`, one per deviceId,
18426
+ * concurrently INSIDE the owner); only the transport collapses.
18427
+ *
18428
+ * Deliberately per-device rather than pre-merged: a timeline lane belongs
18429
+ * to a camera, and a caller that merged would have to un-merge.
18430
+ * `getEventDensity` stays for single-camera callers.
18431
+ *
18432
+ * Every requested id gets a row, marked — see
18433
+ * {@link EventDensityForDeviceSchema}. `deviceIds` is capped at
18434
+ * {@link EVENT_DENSITY_BATCH_MAX}, and an over-cap ask is refused rather
18435
+ * than truncated.
18436
+ */
18437
+ getEventDensityBatch: method(z.object({
18438
+ deviceIds: z.array(z.number()).min(1).max(200),
18439
+ since: z.number(),
18440
+ until: z.number(),
18441
+ bucketMs: z.number().int().positive()
18442
+ }), z.array(EventDensityForDeviceSchema).readonly()),
18396
18443
  /**
18397
18444
  * @deprecated Prefer `pruneTracksBefore` — the track is the ROOT of the
18398
18445
  * analytics model and retention must cascade from it (design §5.1). This
@@ -29827,6 +29874,39 @@ var RecordingDaysSchema = z.object({
29827
29874
  /** Local-midnight epochs (UTC ms) of days that have ≥1 recorded segment. */
29828
29875
  days: z.array(z.number())
29829
29876
  });
29877
+ /**
29878
+ * One camera's row in a `getAvailabilityBatch` answer.
29879
+ *
29880
+ * `ranges` is EXACTLY what `getAvailability` returns for that camera — the
29881
+ * batch collapses the transport, not the work — plus the one thing the singular
29882
+ * method never had to say:
29883
+ *
29884
+ * - `read: 'read'` — answered. `ranges: []` means "read, and this camera has
29885
+ * no footage in the window", which is a real claim.
29886
+ * - `read: 'unreadable'` — the recorder could not answer for this camera (its
29887
+ * calendar rung threw, its location is unmounted). `ranges` is empty and
29888
+ * that emptiness means NOTHING.
29889
+ *
29890
+ * A timeline that renders the second as the first tells an operator there is no
29891
+ * footage when the truth is that nobody looked.
29892
+ */
29893
+ var RecordingAvailabilityForDeviceSchema = z.object({
29894
+ deviceId: z.number(),
29895
+ read: z.enum(["read", "unreadable"]),
29896
+ ranges: z.array(RecordingRangeSchema).readonly()
29897
+ });
29898
+ /**
29899
+ * One camera's row in a `getDaysWithRecordingsBatch` answer. Same rule as
29900
+ * {@link RecordingAvailabilityForDeviceSchema}: `days: []` on a `'read'` row is
29901
+ * "no footage in this month", `read: 'unreadable'` is "nobody could look", and
29902
+ * the date-picker's day dots must not spell them the same.
29903
+ */
29904
+ var RecordingDaysForDeviceSchema = z.object({
29905
+ deviceId: z.number(),
29906
+ read: z.enum(["read", "unreadable"]),
29907
+ /** Local-midnight epochs (UTC ms) of days that have ≥1 recorded segment. */
29908
+ days: z.array(z.number()).readonly()
29909
+ });
29830
29910
  var RecordingManifestSchema = z.object({
29831
29911
  deviceId: z.number(),
29832
29912
  /** Local filesystem path to the master playlist; null when no recording exists for the requested range. */
@@ -30072,6 +30152,32 @@ var recordingCapability = {
30072
30152
  kind: "query",
30073
30153
  auth: "protected"
30074
30154
  }),
30155
+ /**
30156
+ * `getAvailability` for a SET of cameras, in one round trip.
30157
+ *
30158
+ * A multi-camera timeline re-asks availability for every camera in the grid
30159
+ * on every day change; fanned out that is one request per camera for N
30160
+ * independent calendar walks. The per-camera work is IDENTICAL (the same
30161
+ * `availabilityProfileFor` + `rangesIn`, run concurrently inside the
30162
+ * recorder) — only the transport collapses.
30163
+ *
30164
+ * `protected` for the same reason the singular method is: every id in
30165
+ * `deviceIds` is a device reference, so the F1 #3 gate refuses any camera
30166
+ * outside the caller's scope — one id out of scope refuses the CALL, it
30167
+ * does not quietly drop a row.
30168
+ *
30169
+ * Every requested id gets a row, marked — see
30170
+ * {@link RecordingAvailabilityForDeviceSchema}. `deviceIds` is capped at
30171
+ * {@link RECORDING_TIMELINE_BATCH_MAX} and an over-cap ask is refused.
30172
+ */
30173
+ getAvailabilityBatch: method(z.object({
30174
+ deviceIds: z.array(z.number()).min(1).max(200),
30175
+ fromMs: z.number(),
30176
+ toMs: z.number()
30177
+ }), z.array(RecordingAvailabilityForDeviceSchema).readonly(), {
30178
+ kind: "query",
30179
+ auth: "protected"
30180
+ }),
30075
30181
  /** Which calendar days in [fromMs,toMs) have ≥1 recorded segment, bucketed by
30076
30182
  * the client's local day (`tzOffsetMinutes` = minutes to add to UTC). Drives
30077
30183
  * the theater date-picker's day dots. */
@@ -30084,6 +30190,26 @@ var recordingCapability = {
30084
30190
  kind: "query",
30085
30191
  auth: "protected"
30086
30192
  }),
30193
+ /**
30194
+ * `getDaysWithRecordings` for a SET of cameras, in one round trip.
30195
+ *
30196
+ * The cheapest question in the product, asked once per camera per month
30197
+ * change. One directory read per day per camera at the owner, unchanged;
30198
+ * what collapses is the N requests it took to ask.
30199
+ *
30200
+ * Every requested id gets a row, marked — see
30201
+ * {@link RecordingDaysForDeviceSchema}. `deviceIds` is capped at
30202
+ * {@link RECORDING_TIMELINE_BATCH_MAX} and an over-cap ask is refused.
30203
+ */
30204
+ getDaysWithRecordingsBatch: method(z.object({
30205
+ deviceIds: z.array(z.number()).min(1).max(200),
30206
+ fromMs: z.number(),
30207
+ toMs: z.number(),
30208
+ tzOffsetMinutes: z.number()
30209
+ }), z.array(RecordingDaysForDeviceSchema).readonly(), {
30210
+ kind: "query",
30211
+ auth: "protected"
30212
+ }),
30087
30213
  getPlaybackManifest: method(z.object({
30088
30214
  deviceId: z.number(),
30089
30215
  fromMs: z.number(),
@@ -37287,6 +37413,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
37287
37413
  addonId: null,
37288
37414
  access: "view"
37289
37415
  },
37416
+ "pipelineAnalytics.getEventDensityBatch": {
37417
+ capName: "pipeline-analytics",
37418
+ capScope: "device",
37419
+ addonId: null,
37420
+ access: "view"
37421
+ },
37290
37422
  "pipelineAnalytics.getEventMedia": {
37291
37423
  capName: "pipeline-analytics",
37292
37424
  capScope: "device",
@@ -38409,12 +38541,24 @@ var METHOD_ACCESS_MAP = Object.freeze({
38409
38541
  addonId: null,
38410
38542
  access: "view"
38411
38543
  },
38544
+ "recording.getAvailabilityBatch": {
38545
+ capName: "recording",
38546
+ capScope: "system",
38547
+ addonId: null,
38548
+ access: "view"
38549
+ },
38412
38550
  "recording.getDaysWithRecordings": {
38413
38551
  capName: "recording",
38414
38552
  capScope: "system",
38415
38553
  addonId: null,
38416
38554
  access: "view"
38417
38555
  },
38556
+ "recording.getDaysWithRecordingsBatch": {
38557
+ capName: "recording",
38558
+ capScope: "system",
38559
+ addonId: null,
38560
+ access: "view"
38561
+ },
38418
38562
  "recording.getDeviceConfig": {
38419
38563
  capName: "recording",
38420
38564
  capScope: "system",
@@ -41019,6 +41163,11 @@ Object.freeze({
41019
41163
  form: "single",
41020
41164
  optional: false
41021
41165
  }],
41166
+ "pipelineAnalytics.getEventDensityBatch": [{
41167
+ name: "deviceIds",
41168
+ form: "array",
41169
+ optional: false
41170
+ }],
41022
41171
  "pipelineAnalytics.getEventMedia": [{
41023
41172
  name: "deviceId",
41024
41173
  form: "single",
@@ -41434,11 +41583,21 @@ Object.freeze({
41434
41583
  form: "single",
41435
41584
  optional: false
41436
41585
  }],
41586
+ "recording.getAvailabilityBatch": [{
41587
+ name: "deviceIds",
41588
+ form: "array",
41589
+ optional: false
41590
+ }],
41437
41591
  "recording.getDaysWithRecordings": [{
41438
41592
  name: "deviceId",
41439
41593
  form: "single",
41440
41594
  optional: false
41441
41595
  }],
41596
+ "recording.getDaysWithRecordingsBatch": [{
41597
+ name: "deviceIds",
41598
+ form: "array",
41599
+ optional: false
41600
+ }],
41442
41601
  "recording.getDeviceConfig": [{
41443
41602
  name: "deviceId",
41444
41603
  form: "single",
@@ -17987,6 +17987,34 @@ var KeyEventsForDeviceSchema = zod.z.object({
17987
17987
  deviceId: zod.z.number(),
17988
17988
  events: zod.z.array(KeyEventSchema).readonly()
17989
17989
  });
17990
+ /** One non-empty bucket of the timeline histogram. */
17991
+ var EventDensityBucketSchema = zod.z.object({
17992
+ bucketStart: zod.z.number(),
17993
+ motion: zod.z.number().int(),
17994
+ object: zod.z.number().int(),
17995
+ audio: zod.z.number().int()
17996
+ });
17997
+ /**
17998
+ * One camera's row in a `getEventDensityBatch` answer.
17999
+ *
18000
+ * TWO facts, and the timeline draws them differently:
18001
+ *
18002
+ * - `read: 'read'` — the histogram for this camera. `buckets: []` is a real
18003
+ * claim: read, and nothing happened in the window.
18004
+ * - `read: 'unreadable'` — nobody could answer for this camera. `buckets` is
18005
+ * empty and that emptiness means NOTHING; the timeline must render unknown,
18006
+ * not quiet.
18007
+ *
18008
+ * Fanned out per camera the difference was free — one query rejected while the
18009
+ * others resolved — and collapsing to a batch is the exact moment it is lost
18010
+ * silently. Every requested id gets a row: a caller that asked for twelve and
18011
+ * got eleven cannot tell which one is missing, or that any is.
18012
+ */
18013
+ var EventDensityForDeviceSchema = zod.z.object({
18014
+ deviceId: zod.z.number(),
18015
+ read: zod.z.enum(["read", "unreadable"]),
18016
+ buckets: zod.z.array(EventDensityBucketSchema).readonly()
18017
+ });
17990
18018
  zod.z.object({
17991
18019
  trackId: zod.z.string(),
17992
18020
  className: zod.z.string(),
@@ -18387,12 +18415,31 @@ var pipelineAnalyticsCapability = {
18387
18415
  since: zod.z.number(),
18388
18416
  until: zod.z.number(),
18389
18417
  bucketMs: zod.z.number().int().positive()
18390
- }), zod.z.array(zod.z.object({
18391
- bucketStart: zod.z.number(),
18392
- motion: zod.z.number().int(),
18393
- object: zod.z.number().int(),
18394
- audio: zod.z.number().int()
18395
- })).readonly()),
18418
+ }), zod.z.array(EventDensityBucketSchema).readonly()),
18419
+ /**
18420
+ * The same histogram, for a SET of cameras, in one round trip.
18421
+ *
18422
+ * A multi-camera timeline (the tablet grid) re-asks this of every camera in
18423
+ * the grid on every day change — N browser → hub → post-analysis round
18424
+ * trips for N independent, already-indexed store queries. The queries are
18425
+ * unchanged and still run per camera (`densityByKind`, one per deviceId,
18426
+ * concurrently INSIDE the owner); only the transport collapses.
18427
+ *
18428
+ * Deliberately per-device rather than pre-merged: a timeline lane belongs
18429
+ * to a camera, and a caller that merged would have to un-merge.
18430
+ * `getEventDensity` stays for single-camera callers.
18431
+ *
18432
+ * Every requested id gets a row, marked — see
18433
+ * {@link EventDensityForDeviceSchema}. `deviceIds` is capped at
18434
+ * {@link EVENT_DENSITY_BATCH_MAX}, and an over-cap ask is refused rather
18435
+ * than truncated.
18436
+ */
18437
+ getEventDensityBatch: method(zod.z.object({
18438
+ deviceIds: zod.z.array(zod.z.number()).min(1).max(200),
18439
+ since: zod.z.number(),
18440
+ until: zod.z.number(),
18441
+ bucketMs: zod.z.number().int().positive()
18442
+ }), zod.z.array(EventDensityForDeviceSchema).readonly()),
18396
18443
  /**
18397
18444
  * @deprecated Prefer `pruneTracksBefore` — the track is the ROOT of the
18398
18445
  * analytics model and retention must cascade from it (design §5.1). This
@@ -29827,6 +29874,39 @@ var RecordingDaysSchema = zod.z.object({
29827
29874
  /** Local-midnight epochs (UTC ms) of days that have ≥1 recorded segment. */
29828
29875
  days: zod.z.array(zod.z.number())
29829
29876
  });
29877
+ /**
29878
+ * One camera's row in a `getAvailabilityBatch` answer.
29879
+ *
29880
+ * `ranges` is EXACTLY what `getAvailability` returns for that camera — the
29881
+ * batch collapses the transport, not the work — plus the one thing the singular
29882
+ * method never had to say:
29883
+ *
29884
+ * - `read: 'read'` — answered. `ranges: []` means "read, and this camera has
29885
+ * no footage in the window", which is a real claim.
29886
+ * - `read: 'unreadable'` — the recorder could not answer for this camera (its
29887
+ * calendar rung threw, its location is unmounted). `ranges` is empty and
29888
+ * that emptiness means NOTHING.
29889
+ *
29890
+ * A timeline that renders the second as the first tells an operator there is no
29891
+ * footage when the truth is that nobody looked.
29892
+ */
29893
+ var RecordingAvailabilityForDeviceSchema = zod.z.object({
29894
+ deviceId: zod.z.number(),
29895
+ read: zod.z.enum(["read", "unreadable"]),
29896
+ ranges: zod.z.array(RecordingRangeSchema).readonly()
29897
+ });
29898
+ /**
29899
+ * One camera's row in a `getDaysWithRecordingsBatch` answer. Same rule as
29900
+ * {@link RecordingAvailabilityForDeviceSchema}: `days: []` on a `'read'` row is
29901
+ * "no footage in this month", `read: 'unreadable'` is "nobody could look", and
29902
+ * the date-picker's day dots must not spell them the same.
29903
+ */
29904
+ var RecordingDaysForDeviceSchema = zod.z.object({
29905
+ deviceId: zod.z.number(),
29906
+ read: zod.z.enum(["read", "unreadable"]),
29907
+ /** Local-midnight epochs (UTC ms) of days that have ≥1 recorded segment. */
29908
+ days: zod.z.array(zod.z.number()).readonly()
29909
+ });
29830
29910
  var RecordingManifestSchema = zod.z.object({
29831
29911
  deviceId: zod.z.number(),
29832
29912
  /** Local filesystem path to the master playlist; null when no recording exists for the requested range. */
@@ -30072,6 +30152,32 @@ var recordingCapability = {
30072
30152
  kind: "query",
30073
30153
  auth: "protected"
30074
30154
  }),
30155
+ /**
30156
+ * `getAvailability` for a SET of cameras, in one round trip.
30157
+ *
30158
+ * A multi-camera timeline re-asks availability for every camera in the grid
30159
+ * on every day change; fanned out that is one request per camera for N
30160
+ * independent calendar walks. The per-camera work is IDENTICAL (the same
30161
+ * `availabilityProfileFor` + `rangesIn`, run concurrently inside the
30162
+ * recorder) — only the transport collapses.
30163
+ *
30164
+ * `protected` for the same reason the singular method is: every id in
30165
+ * `deviceIds` is a device reference, so the F1 #3 gate refuses any camera
30166
+ * outside the caller's scope — one id out of scope refuses the CALL, it
30167
+ * does not quietly drop a row.
30168
+ *
30169
+ * Every requested id gets a row, marked — see
30170
+ * {@link RecordingAvailabilityForDeviceSchema}. `deviceIds` is capped at
30171
+ * {@link RECORDING_TIMELINE_BATCH_MAX} and an over-cap ask is refused.
30172
+ */
30173
+ getAvailabilityBatch: method(zod.z.object({
30174
+ deviceIds: zod.z.array(zod.z.number()).min(1).max(200),
30175
+ fromMs: zod.z.number(),
30176
+ toMs: zod.z.number()
30177
+ }), zod.z.array(RecordingAvailabilityForDeviceSchema).readonly(), {
30178
+ kind: "query",
30179
+ auth: "protected"
30180
+ }),
30075
30181
  /** Which calendar days in [fromMs,toMs) have ≥1 recorded segment, bucketed by
30076
30182
  * the client's local day (`tzOffsetMinutes` = minutes to add to UTC). Drives
30077
30183
  * the theater date-picker's day dots. */
@@ -30084,6 +30190,26 @@ var recordingCapability = {
30084
30190
  kind: "query",
30085
30191
  auth: "protected"
30086
30192
  }),
30193
+ /**
30194
+ * `getDaysWithRecordings` for a SET of cameras, in one round trip.
30195
+ *
30196
+ * The cheapest question in the product, asked once per camera per month
30197
+ * change. One directory read per day per camera at the owner, unchanged;
30198
+ * what collapses is the N requests it took to ask.
30199
+ *
30200
+ * Every requested id gets a row, marked — see
30201
+ * {@link RecordingDaysForDeviceSchema}. `deviceIds` is capped at
30202
+ * {@link RECORDING_TIMELINE_BATCH_MAX} and an over-cap ask is refused.
30203
+ */
30204
+ getDaysWithRecordingsBatch: method(zod.z.object({
30205
+ deviceIds: zod.z.array(zod.z.number()).min(1).max(200),
30206
+ fromMs: zod.z.number(),
30207
+ toMs: zod.z.number(),
30208
+ tzOffsetMinutes: zod.z.number()
30209
+ }), zod.z.array(RecordingDaysForDeviceSchema).readonly(), {
30210
+ kind: "query",
30211
+ auth: "protected"
30212
+ }),
30087
30213
  getPlaybackManifest: method(zod.z.object({
30088
30214
  deviceId: zod.z.number(),
30089
30215
  fromMs: zod.z.number(),
@@ -37287,6 +37413,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
37287
37413
  addonId: null,
37288
37414
  access: "view"
37289
37415
  },
37416
+ "pipelineAnalytics.getEventDensityBatch": {
37417
+ capName: "pipeline-analytics",
37418
+ capScope: "device",
37419
+ addonId: null,
37420
+ access: "view"
37421
+ },
37290
37422
  "pipelineAnalytics.getEventMedia": {
37291
37423
  capName: "pipeline-analytics",
37292
37424
  capScope: "device",
@@ -38409,12 +38541,24 @@ var METHOD_ACCESS_MAP = Object.freeze({
38409
38541
  addonId: null,
38410
38542
  access: "view"
38411
38543
  },
38544
+ "recording.getAvailabilityBatch": {
38545
+ capName: "recording",
38546
+ capScope: "system",
38547
+ addonId: null,
38548
+ access: "view"
38549
+ },
38412
38550
  "recording.getDaysWithRecordings": {
38413
38551
  capName: "recording",
38414
38552
  capScope: "system",
38415
38553
  addonId: null,
38416
38554
  access: "view"
38417
38555
  },
38556
+ "recording.getDaysWithRecordingsBatch": {
38557
+ capName: "recording",
38558
+ capScope: "system",
38559
+ addonId: null,
38560
+ access: "view"
38561
+ },
38418
38562
  "recording.getDeviceConfig": {
38419
38563
  capName: "recording",
38420
38564
  capScope: "system",
@@ -41019,6 +41163,11 @@ Object.freeze({
41019
41163
  form: "single",
41020
41164
  optional: false
41021
41165
  }],
41166
+ "pipelineAnalytics.getEventDensityBatch": [{
41167
+ name: "deviceIds",
41168
+ form: "array",
41169
+ optional: false
41170
+ }],
41022
41171
  "pipelineAnalytics.getEventMedia": [{
41023
41172
  name: "deviceId",
41024
41173
  form: "single",
@@ -41434,11 +41583,21 @@ Object.freeze({
41434
41583
  form: "single",
41435
41584
  optional: false
41436
41585
  }],
41586
+ "recording.getAvailabilityBatch": [{
41587
+ name: "deviceIds",
41588
+ form: "array",
41589
+ optional: false
41590
+ }],
41437
41591
  "recording.getDaysWithRecordings": [{
41438
41592
  name: "deviceId",
41439
41593
  form: "single",
41440
41594
  optional: false
41441
41595
  }],
41596
+ "recording.getDaysWithRecordingsBatch": [{
41597
+ name: "deviceIds",
41598
+ form: "array",
41599
+ optional: false
41600
+ }],
41442
41601
  "recording.getDeviceConfig": [{
41443
41602
  name: "deviceId",
41444
41603
  form: "single",
@@ -0,0 +1,53 @@
1
+ //#region src/kernel/transport/hub-cap-forward.ts
2
+ /** The Moleculer service name the hub registers for agent→hub cap forwarding. */
3
+ var HUB_CAP_FWD_SERVICE = "$hub-cap-fwd";
4
+ /** The Moleculer action (service.action) for hub cap forwarding. */
5
+ var HUB_CAP_FWD_ACTION = `${HUB_CAP_FWD_SERVICE}.forward`;
6
+ /**
7
+ * Narrow Moleculer's loosely-typed `ctx.params` to {@link HubCapForwardParams}
8
+ * without unsafe casts — mirrors `agent-cap-dispatch-service.ts:narrowParams`.
9
+ */
10
+ function narrowParams(raw) {
11
+ if (raw === null || typeof raw !== "object") throw new Error("$hub-cap-fwd.forward: invalid params — capName and method are required strings");
12
+ const capName = Reflect.get(raw, "capName");
13
+ const method = Reflect.get(raw, "method");
14
+ if (typeof capName !== "string" || typeof method !== "string") throw new Error("$hub-cap-fwd.forward: invalid params — capName and method are required strings");
15
+ const deviceId = Reflect.get(raw, "deviceId");
16
+ const nodeId = Reflect.get(raw, "nodeId");
17
+ const native = Reflect.get(raw, "native");
18
+ return {
19
+ capName,
20
+ method,
21
+ args: Reflect.get(raw, "args"),
22
+ deviceId: typeof deviceId === "number" ? deviceId : void 0,
23
+ nodeId: typeof nodeId === "string" && nodeId.length > 0 ? nodeId : void 0,
24
+ native: native === true ? true : void 0
25
+ };
26
+ }
27
+ /**
28
+ * Build the `$hub-cap-fwd` Moleculer `ServiceSchema`. The hub registers this on
29
+ * its broker (only the hub registers it → an agent's `broker.call` for
30
+ * `$hub-cap-fwd.forward` discovers it on the hub with no explicit nodeID pin).
31
+ *
32
+ * @param onUnownedCall The hub's cap routing handler (from
33
+ * `createParentUnownedCallHandler`). Reused verbatim so
34
+ * forwarded calls route exactly like a hub-local child's.
35
+ */
36
+ function createHubCapForwardService(onUnownedCall) {
37
+ return {
38
+ name: HUB_CAP_FWD_SERVICE,
39
+ actions: { forward: { handler: async (ctx) => {
40
+ const { capName, method, args, deviceId, nodeId, native } = narrowParams(ctx.params);
41
+ return onUnownedCall({
42
+ capName,
43
+ method,
44
+ args,
45
+ ...deviceId !== void 0 ? { deviceId } : {},
46
+ ...nodeId !== void 0 ? { nodeId } : {},
47
+ ...native === true ? { native: true } : {}
48
+ });
49
+ } } }
50
+ };
51
+ }
52
+ //#endregion
53
+ export { HUB_CAP_FWD_SERVICE as n, createHubCapForwardService as r, HUB_CAP_FWD_ACTION as t };
@@ -0,0 +1,70 @@
1
+ //#region src/kernel/transport/hub-cap-forward.ts
2
+ /** The Moleculer service name the hub registers for agent→hub cap forwarding. */
3
+ var HUB_CAP_FWD_SERVICE = "$hub-cap-fwd";
4
+ /** The Moleculer action (service.action) for hub cap forwarding. */
5
+ var HUB_CAP_FWD_ACTION = `${HUB_CAP_FWD_SERVICE}.forward`;
6
+ /**
7
+ * Narrow Moleculer's loosely-typed `ctx.params` to {@link HubCapForwardParams}
8
+ * without unsafe casts — mirrors `agent-cap-dispatch-service.ts:narrowParams`.
9
+ */
10
+ function narrowParams(raw) {
11
+ if (raw === null || typeof raw !== "object") throw new Error("$hub-cap-fwd.forward: invalid params — capName and method are required strings");
12
+ const capName = Reflect.get(raw, "capName");
13
+ const method = Reflect.get(raw, "method");
14
+ if (typeof capName !== "string" || typeof method !== "string") throw new Error("$hub-cap-fwd.forward: invalid params — capName and method are required strings");
15
+ const deviceId = Reflect.get(raw, "deviceId");
16
+ const nodeId = Reflect.get(raw, "nodeId");
17
+ const native = Reflect.get(raw, "native");
18
+ return {
19
+ capName,
20
+ method,
21
+ args: Reflect.get(raw, "args"),
22
+ deviceId: typeof deviceId === "number" ? deviceId : void 0,
23
+ nodeId: typeof nodeId === "string" && nodeId.length > 0 ? nodeId : void 0,
24
+ native: native === true ? true : void 0
25
+ };
26
+ }
27
+ /**
28
+ * Build the `$hub-cap-fwd` Moleculer `ServiceSchema`. The hub registers this on
29
+ * its broker (only the hub registers it → an agent's `broker.call` for
30
+ * `$hub-cap-fwd.forward` discovers it on the hub with no explicit nodeID pin).
31
+ *
32
+ * @param onUnownedCall The hub's cap routing handler (from
33
+ * `createParentUnownedCallHandler`). Reused verbatim so
34
+ * forwarded calls route exactly like a hub-local child's.
35
+ */
36
+ function createHubCapForwardService(onUnownedCall) {
37
+ return {
38
+ name: HUB_CAP_FWD_SERVICE,
39
+ actions: { forward: { handler: async (ctx) => {
40
+ const { capName, method, args, deviceId, nodeId, native } = narrowParams(ctx.params);
41
+ return onUnownedCall({
42
+ capName,
43
+ method,
44
+ args,
45
+ ...deviceId !== void 0 ? { deviceId } : {},
46
+ ...nodeId !== void 0 ? { nodeId } : {},
47
+ ...native === true ? { native: true } : {}
48
+ });
49
+ } } }
50
+ };
51
+ }
52
+ //#endregion
53
+ Object.defineProperty(exports, "HUB_CAP_FWD_ACTION", {
54
+ enumerable: true,
55
+ get: function() {
56
+ return HUB_CAP_FWD_ACTION;
57
+ }
58
+ });
59
+ Object.defineProperty(exports, "HUB_CAP_FWD_SERVICE", {
60
+ enumerable: true,
61
+ get: function() {
62
+ return HUB_CAP_FWD_SERVICE;
63
+ }
64
+ });
65
+ Object.defineProperty(exports, "createHubCapForwardService", {
66
+ enumerable: true,
67
+ get: function() {
68
+ return createHubCapForwardService;
69
+ }
70
+ });