@devicechain/dashboards 0.23.0 → 0.24.0-rc.1

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.
@@ -1,4 +1,4 @@
1
- import type { AlarmRow, CommandRow, LocationSample, MeasurementSample } from './types';
1
+ import type { AlarmRow, AlarmSeverityCount, AlarmTypeCount, CommandRow, LocationSample, MeasurementSample } from './types';
2
2
  export interface MeasurementStreamState {
3
3
  latest: Record<string, MeasurementSample>;
4
4
  samples: MeasurementSample[];
@@ -7,6 +7,18 @@ export interface MeasurementStreamState {
7
7
  gaps?: string[];
8
8
  members?: FleetState;
9
9
  }
10
+ export type MemberPresence = {
11
+ status: 'pending';
12
+ } | {
13
+ status: 'failed';
14
+ } | {
15
+ status: 'unknown';
16
+ } | {
17
+ status: 'ready';
18
+ active: boolean;
19
+ lastActivityTime: string | null;
20
+ inactivityTimeout: number;
21
+ };
10
22
  export interface FleetMember {
11
23
  token: string;
12
24
  name: string | null;
@@ -14,6 +26,8 @@ export interface FleetMember {
14
26
  seed: 'pending' | 'ready' | 'failed';
15
27
  observed: string[];
16
28
  unread?: string[];
29
+ declared?: string[];
30
+ presence?: MemberPresence;
17
31
  }
18
32
  export interface FleetState {
19
33
  status: 'loading' | 'ready' | 'unbound' | 'forbidden' | 'unsupported';
@@ -26,6 +40,21 @@ export interface AlarmStreamState {
26
40
  total: number;
27
41
  loading: boolean;
28
42
  error: unknown | null;
43
+ typeTabs?: AlarmTypeTabs;
44
+ typeCounts?: AlarmTypeCount[];
45
+ severityCounts?: AlarmSeverityCount[];
46
+ }
47
+ export interface AlarmTypeTab {
48
+ token: string;
49
+ name: string | null;
50
+ active: number;
51
+ worstSeverity: string | null;
52
+ }
53
+ export interface AlarmTypeTabs {
54
+ tabs: AlarmTypeTab[];
55
+ selected: string | null;
56
+ select: (token: string | null) => void;
57
+ loading: boolean;
29
58
  }
30
59
  export interface CommandStreamState {
31
60
  deviceToken: string | null;
@@ -53,11 +82,15 @@ export interface AggregateSpan {
53
82
  endTime: string;
54
83
  spanSeconds: number;
55
84
  }
85
+ export interface AggregateTrendPoint extends MeasurementAggregate {
86
+ bucketStart: string;
87
+ }
56
88
  export type AggregateResult = {
57
89
  status: 'loading';
58
90
  } | ({
59
91
  status: 'ready';
60
92
  byName: Record<string, MeasurementAggregate>;
93
+ series?: Record<string, AggregateTrendPoint[]>;
61
94
  } & AggregateSpan) | {
62
95
  status: 'unavailable';
63
96
  reason: 'unsupported' | 'failed';
@@ -0,0 +1,45 @@
1
+ import type { DeviceResolver } from './hub';
2
+ import type { DashboardDefinition, SlotBinding } from './types';
3
+ export declare const BIND_PARAM_PREFIX = "bind.";
4
+ export type BindParamIssue = {
5
+ kind: 'unknown-slot';
6
+ slot: string;
7
+ token: string;
8
+ } | {
9
+ kind: 'not-a-device-slot';
10
+ slot: string;
11
+ token: string;
12
+ } | {
13
+ kind: 'invalid-token';
14
+ slot: string;
15
+ token: string;
16
+ } | {
17
+ kind: 'duplicate-slot';
18
+ slot: string;
19
+ token: string;
20
+ } | {
21
+ kind: 'derived-slot';
22
+ slot: string;
23
+ token: string;
24
+ };
25
+ export interface ParsedBinds {
26
+ binds: Record<string, string>;
27
+ issues: BindParamIssue[];
28
+ }
29
+ export declare function parseBindParams(search: string, definition: DashboardDefinition): ParsedBinds;
30
+ export interface BindCheck {
31
+ ok: Record<string, string>;
32
+ missing: Array<{
33
+ slot: string;
34
+ token: string;
35
+ }>;
36
+ failed: Array<{
37
+ slot: string;
38
+ token: string;
39
+ }>;
40
+ }
41
+ export declare function validateBinds(binds: Record<string, string>, resolver: Pick<DeviceResolver, 'deviceExists'>): Promise<BindCheck>;
42
+ export declare function bindsToSelection(binds: Record<string, string>): Record<string, SlotBinding>;
43
+ export declare function selectionToBinds(selection: Record<string, SlotBinding>, definition: DashboardDefinition): Record<string, string>;
44
+ export declare function withBindParams(search: string, binds: Record<string, string>): string;
45
+ export declare function bindParamsOf(search: string): string;
@@ -0,0 +1,15 @@
1
+ import type { AlarmRow, CommandRow } from './types';
2
+ export interface EventWindow {
3
+ spanSeconds: number;
4
+ endAt?: number;
5
+ }
6
+ export declare function eventWindowBounds(window: EventWindow, now: number): {
7
+ from: number;
8
+ to: number | undefined;
9
+ };
10
+ export declare function windowCriteria(window: EventWindow | undefined, now: number): {
11
+ startTime: string | null;
12
+ endTime: string | null;
13
+ };
14
+ export declare function alarmOverlaps(row: Pick<AlarmRow, 'raisedTime' | 'clearedTime'>, window: EventWindow, now: number): boolean;
15
+ export declare function commandInRange(row: Pick<CommandRow, 'sentTime' | 'queuedTime'>, window: EventWindow, now: number): boolean;
package/dist/hub.d.ts CHANGED
@@ -1,8 +1,9 @@
1
+ import { type EventWindow } from './event-window';
1
2
  import { type HubConnectionState } from './connection';
2
3
  import type { HistoryWindow } from './history';
3
- import type { MemberRef, MemberSeed, MemberSeedPlan, MemberSink, SeedFailure } from './members';
4
+ import type { MemberRef, MemberSeed, MemberSeedPlan, MemberSink, PresenceSink, SeedFailure } from './members';
4
5
  import { type MeasurementBucket } from './queries';
5
- import type { AlarmRow, AnchorTarget, CommandRow, DatasourceSelector, LocationSample, MeasurementSample } from './types';
6
+ import type { AlarmRow, AlarmSeverityCount, AlarmTypeCount, AnchorTarget, CommandRow, DatasourceSelector, LocationSample, MeasurementSample } from './types';
6
7
  export interface DeviceResolver {
7
8
  devicesForAnchor(anchor: AnchorTarget): Promise<string[]>;
8
9
  deviceExists(deviceToken: string): Promise<boolean>;
@@ -10,6 +11,7 @@ export interface DeviceResolver {
10
11
  members: MemberRef[];
11
12
  total: number;
12
13
  }>;
14
+ declaredMetrics?(deviceType: string): Promise<string[] | null>;
13
15
  }
14
16
  export interface WidgetStreamSink {
15
17
  next: (sample: MeasurementSample) => void;
@@ -22,10 +24,17 @@ export interface AlarmSubscription {
22
24
  severity?: string;
23
25
  acknowledged?: boolean;
24
26
  pageSize: number;
27
+ enrichDeviceType?: boolean;
28
+ deviceType?: string;
29
+ countByDeviceType?: boolean;
30
+ countBySeverity?: boolean;
31
+ window?: EventWindow;
25
32
  }
26
33
  export interface AlarmSnapshot {
27
34
  alarms: AlarmRow[];
28
35
  total: number;
36
+ typeCounts?: AlarmTypeCount[];
37
+ severityCounts?: AlarmSeverityCount[];
29
38
  }
30
39
  export interface AlarmStreamSink {
31
40
  next: (snapshot: AlarmSnapshot) => void;
@@ -34,6 +43,7 @@ export interface AlarmStreamSink {
34
43
  export interface CommandSubscription {
35
44
  datasource?: DatasourceSelector;
36
45
  pageSize: number;
46
+ window?: EventWindow;
37
47
  }
38
48
  export interface CommandSnapshot {
39
49
  deviceToken: string | null;
@@ -87,6 +97,8 @@ export interface WidgetDataSource {
87
97
  bucketMeasurements?(datasource: DatasourceSelector, window: HistoryWindow): Promise<MeasurementBucket[]>;
88
98
  subscribeMembers?(datasource: DatasourceSelector, sink: MemberSink): () => void;
89
99
  readMemberSeeds?(deviceTokens: readonly string[], plan: MemberSeedPlan, onSeed: (deviceToken: string, seed: MemberSeed | null, failure?: SeedFailure) => void, cancelled?: () => boolean): Promise<void>;
100
+ declaredMetrics?(deviceType: string): Promise<readonly string[] | null>;
101
+ subscribePresence?(datasource: DatasourceSelector, sink: PresenceSink): () => void;
90
102
  }
91
103
  export declare class DashboardHub implements WidgetDataSource, WidgetActions {
92
104
  private readonly resolver;
@@ -97,6 +109,7 @@ export declare class DashboardHub implements WidgetDataSource, WidgetActions {
97
109
  private readonly alarmDisposers;
98
110
  private readonly commandDisposers;
99
111
  private readonly locationDisposers;
112
+ private readonly presenceDisposers;
100
113
  private readonly connection;
101
114
  private readonly deadStreams;
102
115
  constructor(config: DashboardHubConfig);
@@ -105,6 +118,8 @@ export declare class DashboardHub implements WidgetDataSource, WidgetActions {
105
118
  subscribeWidget(datasource: DatasourceSelector, sink: WidgetStreamSink): () => void;
106
119
  subscribeMembers(datasource: DatasourceSelector, sink: MemberSink): () => void;
107
120
  private resolveRoster;
121
+ private readonly declared;
122
+ declaredMetrics(deviceType: string): Promise<readonly string[] | null>;
108
123
  private readonly seedLimiter;
109
124
  private readonly seedReads;
110
125
  readMemberSeeds(deviceTokens: readonly string[], plan: MemberSeedPlan, onSeed: (deviceToken: string, seed: MemberSeed | null, failure?: SeedFailure) => void, cancelled?: () => boolean): Promise<void>;
@@ -115,12 +130,16 @@ export declare class DashboardHub implements WidgetDataSource, WidgetActions {
115
130
  subscribeAlarms(subscription: AlarmSubscription, sink: AlarmStreamSink): () => void;
116
131
  private resolveAlarmScope;
117
132
  private queryAlarms;
133
+ private readonly alarmDeviceTypes;
134
+ private withDeviceTypes;
118
135
  subscribeCommands(subscription: CommandSubscription, sink: CommandStreamSink): () => void;
119
136
  private resolveCommandScope;
120
137
  private queryCommands;
121
138
  subscribeLocations(subscription: LocationSubscription, sink: LocationStreamSink): () => void;
122
139
  private resolveLocationScope;
123
140
  private queryLocations;
141
+ subscribePresence(datasource: DatasourceSelector, sink: PresenceSink): () => void;
142
+ private queryPresence;
124
143
  can(authority: string): boolean;
125
144
  acknowledgeAlarm(alarmToken: string): Promise<void>;
126
145
  clearAlarm(alarmToken: string): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export type { DashboardDefinition, BoardTimeRange, Canvas, CanvasBackground, CanvasGrid, CanvasSizing, Breakpoints, BreakpointSpec, GridLength, GridPlacement, RelativePlacement, RelativeSize, Placement, PlacementAnchor, PlacementMode, FrameBorder, FrameBorderWidth, FrameHeader, FrameRadius, FrameVariant, ResolvedFrame, SpaceTokenName, ThemeColorToken, WidgetFrameSpec, WidgetInstance, KnownWidgetInstance, ExtensionWidgetInstance, ExtensionWidgetType, ResolvedWidgetInstance, UnknownWidgetInstance, UnknownWidgetType, UnresolvedWidgetCode, UnresolvedWidgetReason, WidgetImplementationRef, WidgetType, WidgetLayout, DatasourceSelector, DeviceSelector, AnchorSelector, AnchorTarget, AnchorAggregation, DevicesSelector, RelatedTraversalSelector, SlotSelector, UnboundSelector, SlotDefinition, SlotScope, SlotBinding, SelectionTarget, SelectionCandidate, EntityCandidateLister, EntityListKind, MeasurementSample, LocationSample, LocationSeries, LocationSelection, AlarmRow, CommandRow, CommandParameter, CommandParamDataType, } from './types';
1
+ export type { DashboardDefinition, BoardTimeRange, Canvas, CanvasBackground, CanvasGrid, CanvasSizing, Breakpoints, BreakpointSpec, GridLength, GridPlacement, RelativePlacement, RelativeSize, Placement, PlacementAnchor, PlacementMode, FrameBorder, FrameBorderWidth, FrameHeader, FrameRadius, FrameVariant, ResolvedFrame, SpaceTokenName, ThemeColorToken, WidgetFrameSpec, WidgetInstance, KnownWidgetInstance, ExtensionWidgetInstance, ExtensionWidgetType, ResolvedWidgetInstance, UnknownWidgetInstance, UnknownWidgetType, UnresolvedWidgetCode, UnresolvedWidgetReason, WidgetImplementationRef, WidgetType, WidgetLayout, DatasourceSelector, DeviceSelector, AnchorSelector, AnchorTarget, AnchorAggregation, DevicesSelector, RelatedTraversalSelector, SlotSelector, UnboundSelector, SlotDefinition, SlotScope, SlotBinding, SelectionTarget, SelectionCandidate, EntityCandidateLister, EntityListKind, MeasurementSample, LocationSample, DevicePresence, LocationSeries, LocationSelection, AlarmRow, AlarmDeviceType, AlarmTypeCount, AlarmSeverityCount, CommandRow, CommandParameter, CommandParamDataType, } from './types';
2
2
  export { COMMAND_STATUSES, isTerminalCommandStatus, isCancellableCommandStatus, type CommandStatus, } from './command-status';
3
3
  export { effectiveBindings, parseBindingManifest, resolveWidgetDatasource, stripDefaultBindings, type ParsedBindingManifest, } from './bindings';
4
4
  export { resolveContextBindings, hasScopedSlots, applySelection, bindingsWithoutScopedSlots, type MemberResolver, } from './context';
5
+ export { BIND_PARAM_PREFIX, parseBindParams, validateBinds, bindsToSelection, selectionToBinds, withBindParams, bindParamsOf, type BindCheck, type BindParamIssue, type ParsedBinds, } from './deep-link';
5
6
  export { migrateToSlots, bindWidgetSlot, clearWidgetDatasource, pruneSlots, widgetBinding, widgetSlotName, sameBinding, resolveConcrete, setSlotScope, anchorSlotNames, type ConcreteSelector, } from './slots';
6
7
  export { resolveSlotCandidates } from './candidates';
7
8
  export { createEntityLister } from './entity-lister';
@@ -20,10 +21,10 @@ export { WIDGET_CLIPBOARD_FORMAT, WIDGET_CLIPBOARD_VERSION, copyWidget, duplicat
20
21
  export { createDeviceResolver } from './resolver';
21
22
  export type { MeasurementBucket } from './queries';
22
23
  export { ANCHOR_PAGE_SIZE } from './resolver';
23
- export type { MemberBucketCriteria, MemberBucketRead, MemberRef, MemberRoster, MemberSeed, MemberSeedPlan, MemberSink, SeedFailure, } from './members';
24
+ export type { MemberBucketCriteria, MemberBucketRead, MemberRef, MemberRoster, MemberSeed, MemberSeedPlan, MemberSink, PresenceSink, SeedFailure, } from './members';
24
25
  export { defaultHistoryWindow, fetchWidgetHistory, historyWindowFor, type HistoryWindow } from './history';
25
26
  export { DEFAULT_TIME_RANGE_SECONDS, MAX_SEED_BUCKETS, MAX_TIME_RANGE_SECONDS, MIN_TIME_RANGE_SECONDS, TIME_RANGE_PRESETS, bucketSecondsFor, initialTimeRange, isValidSpanSeconds, parsePausedParam, parseRangeParam, pauseRange, presetIdOf, rangeEnd, rangeWindow, resumeRange, seedBucketCount, setBoardTimeRange, spanLabel, timeRangeFromSearch, withSpan, type RangeWindow, type TimeRangePresetId, type TimeRangeState, } from './time-range';
26
- export type { AggregateResult, AggregateSpan, AggregateStreamState, AlarmStreamState, CommandStreamState, FleetMember, FleetState, LocationStreamState, MeasurementAggregate, MeasurementStreamState, } from './channel-snapshots';
27
+ export type { AggregateResult, AggregateSpan, AggregateTrendPoint, AggregateStreamState, AlarmStreamState, AlarmTypeTab, AlarmTypeTabs, CommandStreamState, FleetMember, FleetState, MemberPresence, LocationStreamState, MeasurementAggregate, MeasurementStreamState, } from './channel-snapshots';
27
28
  export { applyOptionPatch, clampNumberOption, enumValues, numberSpec, validateOptions, HOST_OPTION_CONTROLS, type HostOptionControl, type BooleanOptionSpec, type DefaultsOf, type EnumOptionSpec, type ListItemFieldSpec, type ListOptionSpec, type GreaterThanConstraint, type NumberOptionSpec, type OptionConstraint, type OptionIssue, type OptionIssueCode, type OptionKeysOfKind, type OptionSpec, type OptionsOf, type RequiredOptionKeys, type SpecValue, type StringOptionSpec, type ValidateOptionsContext, type WidgetOptionSpecs, } from './option-schema';
28
29
  export { SDK_API_VERSION, defineWidgetDescriptor, isBuiltinWidgetId, isNamespacedWidgetId, type AckOptionRef, type BuiltinWidgetId, type ChannelBindingPolicy, type ChannelSnapshot, type ConstBinding, type DatasourcePolicy, type DatasourcePolicyFor, type DatasourceSelectorKind, type InteractionsFor, type NamespacedWidgetId, type NumberOptionRef, type StringOptionRef, type WidgetChannel, type WidgetDescriptor, type WidgetDisplay, type WidgetId, type WidgetInteractionDeclaration, FALLBACK_DEFAULT_SPAN, pinnedAxes, type WidgetLayoutSpec, type WidgetResizeMode, type WidgetSpan, } from './widget-descriptor';
29
30
  export { WidgetCatalogError, collectCatalogIssues, createWidgetCatalog, describeIssues, validateWidgetDescriptor, type DescriptorIssue, type WidgetCatalog, } from './widget-catalog';
@@ -32,3 +33,4 @@ export { DEFAULT_GRID, PHONE_MIN_COLUMNS, activeBreakpoint, anchorFraction, brea
32
33
  export { effectiveLayout, layoutShape, liveColumns, reflowGrid, STACK_BELOW_WIDTH, type EffectiveLayout, type LayoutShape, type ReflowItem, } from './reflow';
33
34
  export { LEGACY_REFERENCE_WIDTH } from './legacy-grid';
34
35
  export { blockingLayoutFindings, lintLayout, PUBLISH_BLOCKING_LAYOUT_CODES, spanLimitsOfLayout, type LayoutFinding, type LayoutLintCode, type LayoutLintOptions, type LayoutLintSeverity, type SpanLimits, } from './layout-lint';
36
+ export { type EventWindow, eventWindowBounds } from './event-window';