@camstack/types 1.1.35 → 1.1.36

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.
@@ -345,6 +345,17 @@ export interface TopologyNode {
345
345
  }>;
346
346
  readonly processes: readonly TopologyProcess[];
347
347
  readonly categories: readonly TopologyCategory[];
348
+ /**
349
+ * The node's runtime-updatable ROOT package (`@camstack/server` /
350
+ * `@camstack/agent`) from its `registerNode` manifest — version
351
+ * visibility for the Server management surface. Null for offline rows
352
+ * and nodes that never reported one. Mirrors `TopologyRootPackageSchema`
353
+ * in `nodes.cap.ts`.
354
+ */
355
+ readonly rootPackage: {
356
+ readonly name: string;
357
+ readonly version: string;
358
+ } | null;
348
359
  }
349
360
  /** All known event categories with their typed payloads */
350
361
  export interface EventCatalog {
@@ -739,6 +739,68 @@ function isValuelessField(field) {
739
739
  return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button";
740
740
  }
741
741
  /**
742
+ * Base collector: flatten a hydrated `ConfigUISchemaWithValues` into
743
+ * `key → { value, default }`, recursing through `group` and `sub-tabs`
744
+ * layout fields. Keeping `value` and `default` SEPARATE (rather than
745
+ * pre-resolving) lets callers both read the effective value AND detect
746
+ * overrides (`value` differs from `default`). Structural over `unknown`;
747
+ * malformed input yields an empty map, never throws.
748
+ */
749
+ function collectHydratedFieldEntries(schema) {
750
+ const out = /* @__PURE__ */ new Map();
751
+ if (typeof schema !== "object" || schema === null) return out;
752
+ const sections = schema.sections;
753
+ if (!Array.isArray(sections)) return out;
754
+ for (const section of sections) if (typeof section === "object" && section !== null) collectFieldEntriesInto(section.fields, out);
755
+ return out;
756
+ }
757
+ /** Recursive field walker for {@link collectHydratedFieldEntries}. */
758
+ function collectFieldEntriesInto(fields, into) {
759
+ if (!Array.isArray(fields)) return;
760
+ for (const field of fields) {
761
+ if (typeof field !== "object" || field === null) continue;
762
+ const type = field.type;
763
+ if (type === "group") {
764
+ collectFieldEntriesInto(field.fields, into);
765
+ continue;
766
+ }
767
+ if (type === "sub-tabs") {
768
+ const tabs = field.tabs;
769
+ if (Array.isArray(tabs)) {
770
+ for (const tab of tabs) if (typeof tab === "object" && tab !== null) collectFieldEntriesInto(tab.fields, into);
771
+ }
772
+ continue;
773
+ }
774
+ const key = field.key;
775
+ if (typeof key !== "string" || key.length === 0) continue;
776
+ if (!("value" in field)) continue;
777
+ into.set(key, {
778
+ value: field.value,
779
+ default: field.default
780
+ });
781
+ }
782
+ }
783
+ /**
784
+ * Flatten a hydrated settings payload into `key → EFFECTIVE value`
785
+ * (`value ?? default`). The read-side inverse of `hydrateSchema` for the
786
+ * common "just give me the resolved values" case. Built on
787
+ * {@link collectHydratedFieldEntries}.
788
+ */
789
+ function collectHydratedFieldValues(schema) {
790
+ const out = /* @__PURE__ */ new Map();
791
+ for (const [key, entry] of collectHydratedFieldEntries(schema)) out.set(key, entry.value ?? entry.default);
792
+ return out;
793
+ }
794
+ /**
795
+ * Read one field's effective value out of a hydrated settings payload —
796
+ * convenience wrapper over {@link collectHydratedFieldValues} for the
797
+ * single-field case. Returns `undefined` when the field is absent.
798
+ */
799
+ function resolveHydratedFieldValue(schema, key) {
800
+ const entry = collectHydratedFieldEntries(schema).get(key);
801
+ return entry === void 0 ? void 0 : entry.value ?? entry.default;
802
+ }
803
+ /**
742
804
  * Merge a `ConfigUISchema` with a raw `values` record into a
743
805
  * `ConfigUISchemaWithValues`. Used by every `get*Settings` backend endpoint
744
806
  * before returning to the admin UI. Groups are walked recursively.
@@ -795,10 +857,6 @@ function hydrateField(field, values) {
795
857
  };
796
858
  }
797
859
  const rawValue = storedValue !== void 0 ? storedValue : defaultValue !== void 0 ? defaultValue : null;
798
- if (field.type === "password") return {
799
- ...field,
800
- value: ""
801
- };
802
860
  const value = field.type === "textarea" && field.isJson && rawValue !== null && typeof rawValue === "object" ? JSON.stringify(rawValue, null, 2) : rawValue;
803
861
  return {
804
862
  ...field,
@@ -3589,13 +3647,34 @@ function createDeviceProxy(api, binding, opts) {
3589
3647
  }
3590
3648
  //#endregion
3591
3649
  //#region src/capabilities/admin-ui.cap.ts
3592
- var StaticDirOutputSchema = zod.z.object({ staticDir: zod.z.string() });
3593
- var VersionOutputSchema = zod.z.object({ version: zod.z.string() });
3650
+ var StaticDirOutputSchema$1 = zod.z.object({ staticDir: zod.z.string() });
3651
+ var VersionOutputSchema$1 = zod.z.object({ version: zod.z.string() });
3594
3652
  var adminUiCapability = {
3595
3653
  name: "admin-ui",
3596
3654
  scope: "system",
3597
3655
  mode: "singleton",
3598
3656
  internal: true,
3657
+ methods: {
3658
+ getStaticDir: method(zod.z.void(), StaticDirOutputSchema$1),
3659
+ getVersion: method(zod.z.void(), VersionOutputSchema$1)
3660
+ }
3661
+ };
3662
+ //#endregion
3663
+ //#region src/capabilities/viewer-ui.cap.ts
3664
+ var StaticDirOutputSchema = zod.z.object({ staticDir: zod.z.string() });
3665
+ var VersionOutputSchema = zod.z.object({ version: zod.z.string() });
3666
+ /**
3667
+ * viewer-ui — serves the CamStack VIEWER web build (the Expo/React-Native
3668
+ * universal client's PWA export) from the hub, alongside admin-ui. Mirrors
3669
+ * `admin-ui` exactly: a singleton, server-internal cap exposing the static
3670
+ * dist directory + build version so `main.ts` can mount the SPA under a
3671
+ * dedicated prefix.
3672
+ */
3673
+ var viewerUiCapability = {
3674
+ name: "viewer-ui",
3675
+ scope: "system",
3676
+ mode: "singleton",
3677
+ internal: true,
3599
3678
  methods: {
3600
3679
  getStaticDir: method(zod.z.void(), StaticDirOutputSchema),
3601
3680
  getVersion: method(zod.z.void(), VersionOutputSchema)
@@ -4025,6 +4104,18 @@ Object.defineProperty(exports, "asString", {
4025
4104
  return asString;
4026
4105
  }
4027
4106
  });
4107
+ Object.defineProperty(exports, "collectHydratedFieldEntries", {
4108
+ enumerable: true,
4109
+ get: function() {
4110
+ return collectHydratedFieldEntries;
4111
+ }
4112
+ });
4113
+ Object.defineProperty(exports, "collectHydratedFieldValues", {
4114
+ enumerable: true,
4115
+ get: function() {
4116
+ return collectHydratedFieldValues;
4117
+ }
4118
+ });
4028
4119
  Object.defineProperty(exports, "createDeviceProxy", {
4029
4120
  enumerable: true,
4030
4121
  get: function() {
@@ -4169,6 +4260,12 @@ Object.defineProperty(exports, "resolveCapMount", {
4169
4260
  return resolveCapMount;
4170
4261
  }
4171
4262
  });
4263
+ Object.defineProperty(exports, "resolveHydratedFieldValue", {
4264
+ enumerable: true,
4265
+ get: function() {
4266
+ return resolveHydratedFieldValue;
4267
+ }
4268
+ });
4172
4269
  Object.defineProperty(exports, "scopeKey", {
4173
4270
  enumerable: true,
4174
4271
  get: function() {
@@ -4193,3 +4290,9 @@ Object.defineProperty(exports, "sleepCancellable", {
4193
4290
  return sleepCancellable;
4194
4291
  }
4195
4292
  });
4293
+ Object.defineProperty(exports, "viewerUiCapability", {
4294
+ enumerable: true,
4295
+ get: function() {
4296
+ return viewerUiCapability;
4297
+ }
4298
+ });
@@ -739,6 +739,68 @@ function isValuelessField(field) {
739
739
  return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button";
740
740
  }
741
741
  /**
742
+ * Base collector: flatten a hydrated `ConfigUISchemaWithValues` into
743
+ * `key → { value, default }`, recursing through `group` and `sub-tabs`
744
+ * layout fields. Keeping `value` and `default` SEPARATE (rather than
745
+ * pre-resolving) lets callers both read the effective value AND detect
746
+ * overrides (`value` differs from `default`). Structural over `unknown`;
747
+ * malformed input yields an empty map, never throws.
748
+ */
749
+ function collectHydratedFieldEntries(schema) {
750
+ const out = /* @__PURE__ */ new Map();
751
+ if (typeof schema !== "object" || schema === null) return out;
752
+ const sections = schema.sections;
753
+ if (!Array.isArray(sections)) return out;
754
+ for (const section of sections) if (typeof section === "object" && section !== null) collectFieldEntriesInto(section.fields, out);
755
+ return out;
756
+ }
757
+ /** Recursive field walker for {@link collectHydratedFieldEntries}. */
758
+ function collectFieldEntriesInto(fields, into) {
759
+ if (!Array.isArray(fields)) return;
760
+ for (const field of fields) {
761
+ if (typeof field !== "object" || field === null) continue;
762
+ const type = field.type;
763
+ if (type === "group") {
764
+ collectFieldEntriesInto(field.fields, into);
765
+ continue;
766
+ }
767
+ if (type === "sub-tabs") {
768
+ const tabs = field.tabs;
769
+ if (Array.isArray(tabs)) {
770
+ for (const tab of tabs) if (typeof tab === "object" && tab !== null) collectFieldEntriesInto(tab.fields, into);
771
+ }
772
+ continue;
773
+ }
774
+ const key = field.key;
775
+ if (typeof key !== "string" || key.length === 0) continue;
776
+ if (!("value" in field)) continue;
777
+ into.set(key, {
778
+ value: field.value,
779
+ default: field.default
780
+ });
781
+ }
782
+ }
783
+ /**
784
+ * Flatten a hydrated settings payload into `key → EFFECTIVE value`
785
+ * (`value ?? default`). The read-side inverse of `hydrateSchema` for the
786
+ * common "just give me the resolved values" case. Built on
787
+ * {@link collectHydratedFieldEntries}.
788
+ */
789
+ function collectHydratedFieldValues(schema) {
790
+ const out = /* @__PURE__ */ new Map();
791
+ for (const [key, entry] of collectHydratedFieldEntries(schema)) out.set(key, entry.value ?? entry.default);
792
+ return out;
793
+ }
794
+ /**
795
+ * Read one field's effective value out of a hydrated settings payload —
796
+ * convenience wrapper over {@link collectHydratedFieldValues} for the
797
+ * single-field case. Returns `undefined` when the field is absent.
798
+ */
799
+ function resolveHydratedFieldValue(schema, key) {
800
+ const entry = collectHydratedFieldEntries(schema).get(key);
801
+ return entry === void 0 ? void 0 : entry.value ?? entry.default;
802
+ }
803
+ /**
742
804
  * Merge a `ConfigUISchema` with a raw `values` record into a
743
805
  * `ConfigUISchemaWithValues`. Used by every `get*Settings` backend endpoint
744
806
  * before returning to the admin UI. Groups are walked recursively.
@@ -795,10 +857,6 @@ function hydrateField(field, values) {
795
857
  };
796
858
  }
797
859
  const rawValue = storedValue !== void 0 ? storedValue : defaultValue !== void 0 ? defaultValue : null;
798
- if (field.type === "password") return {
799
- ...field,
800
- value: ""
801
- };
802
860
  const value = field.type === "textarea" && field.isJson && rawValue !== null && typeof rawValue === "object" ? JSON.stringify(rawValue, null, 2) : rawValue;
803
861
  return {
804
862
  ...field,
@@ -3589,13 +3647,34 @@ function createDeviceProxy(api, binding, opts) {
3589
3647
  }
3590
3648
  //#endregion
3591
3649
  //#region src/capabilities/admin-ui.cap.ts
3592
- var StaticDirOutputSchema = z.object({ staticDir: z.string() });
3593
- var VersionOutputSchema = z.object({ version: z.string() });
3650
+ var StaticDirOutputSchema$1 = z.object({ staticDir: z.string() });
3651
+ var VersionOutputSchema$1 = z.object({ version: z.string() });
3594
3652
  var adminUiCapability = {
3595
3653
  name: "admin-ui",
3596
3654
  scope: "system",
3597
3655
  mode: "singleton",
3598
3656
  internal: true,
3657
+ methods: {
3658
+ getStaticDir: method(z.void(), StaticDirOutputSchema$1),
3659
+ getVersion: method(z.void(), VersionOutputSchema$1)
3660
+ }
3661
+ };
3662
+ //#endregion
3663
+ //#region src/capabilities/viewer-ui.cap.ts
3664
+ var StaticDirOutputSchema = z.object({ staticDir: z.string() });
3665
+ var VersionOutputSchema = z.object({ version: z.string() });
3666
+ /**
3667
+ * viewer-ui — serves the CamStack VIEWER web build (the Expo/React-Native
3668
+ * universal client's PWA export) from the hub, alongside admin-ui. Mirrors
3669
+ * `admin-ui` exactly: a singleton, server-internal cap exposing the static
3670
+ * dist directory + build version so `main.ts` can mount the SPA under a
3671
+ * dedicated prefix.
3672
+ */
3673
+ var viewerUiCapability = {
3674
+ name: "viewer-ui",
3675
+ scope: "system",
3676
+ mode: "singleton",
3677
+ internal: true,
3599
3678
  methods: {
3600
3679
  getStaticDir: method(z.void(), StaticDirOutputSchema),
3601
3680
  getVersion: method(z.void(), VersionOutputSchema)
@@ -3773,4 +3852,4 @@ function sleepCancellable(ms, signal) {
3773
3852
  });
3774
3853
  }
3775
3854
  //#endregion
3776
- export { SubscribeAudioChunksResultSchema as $, ReadinessRegistry as A, CamStreamResolutionSchema as B, asJsonObject as C, parseJsonObject as D, parseJsonArray as E, BrokerStatsSchema as F, FrameHandleFormatSchema as G, DecodedAudioChunkSchema as H, BrokerStatusSchema as I, ProfileSlotSchema as J, FrameHandleSchema as K, CAM_PROFILE_ORDER as L, emitDownForOwnedCaps as M, readinessKey as N, parseJsonUnknown as O, scopeKey as P, SubscribeAudioChunksInputSchema as Q, CamProfileSchema as R, asJsonArray as S, asString as T, DecodedFrameSchema as U, CameraStreamSchema as V, EncodedPacketSchema as W, StreamSourceEntrySchema$1 as X, ProfileSlotStatusSchema as Y, StreamSourceSchema as Z, ChargingStatus as _, adminUiCapability as a, selectAssignedProfileSlots as at, DeviceType as b, createMirrorSource as c, createDurableState as ct, DEVICE_STATUS_METHOD as d, isEvent as dt, SubscribeFramesInputSchema as et, event as f, WELL_KNOWN_TABS as ft, resolveCapMount as g, DisposerChain as gt, method as h, EventCategory as ht, deviceOpsCapability as i, parseProfileBrokerId as it, ReadinessTimeoutError as j, DATAPLANE_SECRET_HEADER as k, createSliceHandle as l, createEvent as lt, isDeviceConfigCap as m, hydrateSchema as mt, sleepCancellable as n, makeProfileBrokerId as nt, createDeviceProxy as o, BaseAddon as ot, expandCapMethods as p, WELL_KNOWN_TAB_MAP as pt, ProfileRtspEntrySchema as q, RawStateResultSchema as r, makeSourceBrokerId as rt, createLazyTrpcSource as s, normalizeAddonInitResult as st, sleep as t, SubscribeFramesResultSchema as tt, DEVICE_SETTINGS_CONTRIBUTION_METHODS as u, emitReadiness as ut, DeviceFeature as v, asNumber as w, asBoolean as x, DeviceRole as y, CamStreamKindSchema as z };
3855
+ export { SubscribeAudioChunksInputSchema as $, DATAPLANE_SECRET_HEADER as A, CamStreamKindSchema as B, asJsonArray as C, parseJsonArray as D, asString as E, scopeKey as F, EncodedPacketSchema as G, CameraStreamSchema as H, BrokerStatsSchema as I, ProfileRtspEntrySchema as J, FrameHandleFormatSchema as K, BrokerStatusSchema as L, ReadinessTimeoutError as M, emitDownForOwnedCaps as N, parseJsonObject as O, readinessKey as P, StreamSourceSchema as Q, CAM_PROFILE_ORDER as R, asBoolean as S, asNumber as T, DecodedAudioChunkSchema as U, CamStreamResolutionSchema as V, DecodedFrameSchema as W, ProfileSlotStatusSchema as X, ProfileSlotSchema as Y, StreamSourceEntrySchema$1 as Z, resolveCapMount as _, hydrateSchema as _t, viewerUiCapability as a, parseProfileBrokerId as at, DeviceRole as b, DisposerChain as bt, createLazyTrpcSource as c, normalizeAddonInitResult as ct, DEVICE_SETTINGS_CONTRIBUTION_METHODS as d, emitReadiness as dt, SubscribeAudioChunksResultSchema as et, DEVICE_STATUS_METHOD as f, isEvent as ft, method as g, collectHydratedFieldValues as gt, isDeviceConfigCap as h, collectHydratedFieldEntries as ht, deviceOpsCapability as i, makeSourceBrokerId as it, ReadinessRegistry as j, parseJsonUnknown as k, createMirrorSource as l, createDurableState as lt, expandCapMethods as m, WELL_KNOWN_TAB_MAP as mt, sleepCancellable as n, SubscribeFramesResultSchema as nt, adminUiCapability as o, selectAssignedProfileSlots as ot, event as p, WELL_KNOWN_TABS as pt, FrameHandleSchema as q, RawStateResultSchema as r, makeProfileBrokerId as rt, createDeviceProxy as s, BaseAddon as st, sleep as t, SubscribeFramesInputSchema as tt, createSliceHandle as u, createEvent as ut, ChargingStatus as v, resolveHydratedFieldValue as vt, asJsonObject as w, DeviceType as x, DeviceFeature as y, EventCategory as yt, CamProfileSchema as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.1.35",
3
+ "version": "1.1.36",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",