@devicechain/dashboards 0.19.0 → 0.20.0
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/README.md +18 -6
- package/dist/bindings.d.ts +2 -1
- package/dist/channel-snapshots.d.ts +26 -0
- package/dist/definition.d.ts +10 -2
- package/dist/editor-model.d.ts +3 -2
- package/dist/history.d.ts +2 -2
- package/dist/hub.d.ts +1 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +1701 -80
- package/dist/index.js.map +4 -4
- package/dist/option-schema.d.ts +86 -0
- package/dist/recorded.d.ts +80 -0
- package/dist/recording.d.ts +104 -0
- package/dist/slots.d.ts +1 -1
- package/dist/types.d.ts +45 -2
- package/dist/widget-catalog.d.ts +19 -0
- package/dist/widget-compat.d.ts +16 -0
- package/dist/widget-descriptor.d.ts +91 -0
- package/package.json +5 -5
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
interface OptionSpecBase {
|
|
2
|
+
doc: string;
|
|
3
|
+
required?: true;
|
|
4
|
+
label?: string;
|
|
5
|
+
help?: string;
|
|
6
|
+
labelId?: string;
|
|
7
|
+
helpId?: string;
|
|
8
|
+
control?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const HOST_OPTION_CONTROLS: readonly ['command-vocabulary', 'slot-target', 'basemap'];
|
|
11
|
+
export type HostOptionControl = (typeof HOST_OPTION_CONTROLS)[number];
|
|
12
|
+
export interface StringOptionSpec extends OptionSpecBase {
|
|
13
|
+
kind: 'string';
|
|
14
|
+
format?: 'json';
|
|
15
|
+
}
|
|
16
|
+
export interface NumberOptionSpec extends OptionSpecBase {
|
|
17
|
+
kind: 'number';
|
|
18
|
+
min?: number;
|
|
19
|
+
max?: number;
|
|
20
|
+
integer?: true;
|
|
21
|
+
}
|
|
22
|
+
export interface BooleanOptionSpec extends OptionSpecBase {
|
|
23
|
+
kind: 'boolean';
|
|
24
|
+
}
|
|
25
|
+
export interface EnumOptionSpec<V extends string = string> extends OptionSpecBase {
|
|
26
|
+
kind: 'enum';
|
|
27
|
+
values: readonly V[];
|
|
28
|
+
valueLabels?: Readonly<Record<string, string>>;
|
|
29
|
+
valueLabelIds?: Readonly<Record<string, string>>;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
placeholderId?: string;
|
|
32
|
+
}
|
|
33
|
+
export type OptionSpec = StringOptionSpec | NumberOptionSpec | BooleanOptionSpec | EnumOptionSpec;
|
|
34
|
+
export type WidgetOptionSpecs = Record<string, OptionSpec>;
|
|
35
|
+
export interface GreaterThanConstraint<K extends string = string> {
|
|
36
|
+
kind: 'greater-than';
|
|
37
|
+
key: K;
|
|
38
|
+
than: K;
|
|
39
|
+
}
|
|
40
|
+
export type OptionConstraint<K extends string = string> = GreaterThanConstraint<K>;
|
|
41
|
+
export type SpecValue<S> = S extends {
|
|
42
|
+
kind: 'enum';
|
|
43
|
+
values: readonly (infer V)[];
|
|
44
|
+
} ? V extends string ? V : never : S extends {
|
|
45
|
+
kind: 'number';
|
|
46
|
+
} ? number : S extends {
|
|
47
|
+
kind: 'boolean';
|
|
48
|
+
} ? boolean : S extends {
|
|
49
|
+
kind: 'string';
|
|
50
|
+
} ? string : never;
|
|
51
|
+
export type RequiredOptionKeys<S> = {
|
|
52
|
+
[K in keyof S]: S[K] extends {
|
|
53
|
+
required: true;
|
|
54
|
+
} ? K : never;
|
|
55
|
+
}[keyof S];
|
|
56
|
+
export type OptionsOf<S> = {
|
|
57
|
+
[K in RequiredOptionKeys<S>]: SpecValue<S[K]>;
|
|
58
|
+
} & {
|
|
59
|
+
[K in Exclude<keyof S, RequiredOptionKeys<S>>]?: SpecValue<S[K]>;
|
|
60
|
+
};
|
|
61
|
+
export type DefaultsOf<S> = {
|
|
62
|
+
[K in keyof S]?: SpecValue<S[K]>;
|
|
63
|
+
};
|
|
64
|
+
export type OptionKeysOfKind<S, Kind extends OptionSpec['kind']> = {
|
|
65
|
+
[K in keyof S & string]: S[K] extends infer X ? (X extends {
|
|
66
|
+
kind: Kind;
|
|
67
|
+
} ? K : never) : never;
|
|
68
|
+
}[keyof S & string];
|
|
69
|
+
export type OptionIssueCode = 'unknown' | 'type' | 'enum' | 'range' | 'missing' | 'json' | 'invariant';
|
|
70
|
+
export interface OptionIssue {
|
|
71
|
+
widgetId: string;
|
|
72
|
+
key: string;
|
|
73
|
+
code: OptionIssueCode;
|
|
74
|
+
message: string;
|
|
75
|
+
}
|
|
76
|
+
export interface ValidateOptionsContext {
|
|
77
|
+
constraints?: readonly OptionConstraint[];
|
|
78
|
+
label: string;
|
|
79
|
+
}
|
|
80
|
+
export declare function hasOwn(obj: object, key: string): boolean;
|
|
81
|
+
export declare function validateOptions(specs: WidgetOptionSpecs, options: Record<string, unknown> | undefined, context: ValidateOptionsContext): OptionIssue[];
|
|
82
|
+
export declare function numberSpec(specs: WidgetOptionSpecs, key: string): NumberOptionSpec | undefined;
|
|
83
|
+
export declare function clampNumberOption(spec: NumberOptionSpec | undefined, value: number): number | undefined;
|
|
84
|
+
export declare function enumValues(specs: WidgetOptionSpecs, key: string): readonly string[] | undefined;
|
|
85
|
+
export declare function applyOptionPatch(specs: WidgetOptionSpecs, options: Readonly<Record<string, unknown>> | undefined, patch: Readonly<Record<string, unknown>>, label?: string): Record<string, unknown>;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { AlarmStreamSink, AlarmSubscription, CommandStreamSink, CommandSubscription, DeviceResolver, LocationStreamSink, LocationSubscription, WidgetDataSource, WidgetStreamSink } from './hub';
|
|
2
|
+
import type { AnchorTarget, DatasourceSelector, EntityCandidateLister } from './types';
|
|
3
|
+
import { type BoardRecording } from './recording';
|
|
4
|
+
export declare const RECORDED_HISTORY_WINDOW_MS: number;
|
|
5
|
+
export type RecordedChannel = 'measurements' | 'alarms' | 'locations' | 'commands';
|
|
6
|
+
export declare class NotInRecordingError extends Error {
|
|
7
|
+
readonly channel: RecordedChannel;
|
|
8
|
+
readonly detail: string;
|
|
9
|
+
constructor(channel: RecordedChannel, detail?: string);
|
|
10
|
+
toString(): string;
|
|
11
|
+
}
|
|
12
|
+
export declare const PLAYBACK_RATES: readonly [1, 4, 16];
|
|
13
|
+
export type PlaybackRate = (typeof PLAYBACK_RATES)[number];
|
|
14
|
+
export interface ClockEvent {
|
|
15
|
+
timeMs: number;
|
|
16
|
+
reason: 'tick' | 'seek' | 'state';
|
|
17
|
+
}
|
|
18
|
+
export interface ClockTicker {
|
|
19
|
+
start(onFrame: (wallDeltaMs: number) => void): () => void;
|
|
20
|
+
}
|
|
21
|
+
export declare class RecordedClock {
|
|
22
|
+
readonly durationMs: number;
|
|
23
|
+
readonly minMs: number;
|
|
24
|
+
private time;
|
|
25
|
+
private isPlaying;
|
|
26
|
+
private playbackRate;
|
|
27
|
+
private stopTicker;
|
|
28
|
+
private readonly ticker;
|
|
29
|
+
private readonly listeners;
|
|
30
|
+
constructor(durationMs: number, options?: {
|
|
31
|
+
ticker?: ClockTicker;
|
|
32
|
+
startMs?: number;
|
|
33
|
+
minMs?: number;
|
|
34
|
+
});
|
|
35
|
+
get timeMs(): number;
|
|
36
|
+
get playing(): boolean;
|
|
37
|
+
get rate(): PlaybackRate;
|
|
38
|
+
get ended(): boolean;
|
|
39
|
+
play(): void;
|
|
40
|
+
pause(): void;
|
|
41
|
+
seek(tMs: number): void;
|
|
42
|
+
setRate(rate: PlaybackRate): void;
|
|
43
|
+
advance(wallDeltaMs: number): void;
|
|
44
|
+
subscribe(listener: (ev: ClockEvent) => void): () => void;
|
|
45
|
+
private halt;
|
|
46
|
+
private clampTime;
|
|
47
|
+
private emit;
|
|
48
|
+
}
|
|
49
|
+
export declare function createRecordedClock(rec: BoardRecording, options?: {
|
|
50
|
+
ticker?: ClockTicker;
|
|
51
|
+
}): RecordedClock;
|
|
52
|
+
export interface RecordedSiteOptions {
|
|
53
|
+
siteAnchors?: readonly AnchorTarget[];
|
|
54
|
+
}
|
|
55
|
+
export declare function createRecordedResolver(rec: BoardRecording, options?: RecordedSiteOptions): DeviceResolver;
|
|
56
|
+
export declare function createRecordedLister(rec: BoardRecording, options?: RecordedSiteOptions): EntityCandidateLister;
|
|
57
|
+
export declare class RecordedDataSource implements WidgetDataSource {
|
|
58
|
+
private readonly rec;
|
|
59
|
+
private readonly site;
|
|
60
|
+
private readonly index;
|
|
61
|
+
private readonly startMs;
|
|
62
|
+
private readonly devices;
|
|
63
|
+
private readonly subs;
|
|
64
|
+
private readonly unlisten;
|
|
65
|
+
private cursor;
|
|
66
|
+
private stale;
|
|
67
|
+
constructor(rec: BoardRecording, clock: RecordedClock, options?: RecordedSiteOptions);
|
|
68
|
+
get isStale(): boolean;
|
|
69
|
+
private onClock;
|
|
70
|
+
private iso;
|
|
71
|
+
private open;
|
|
72
|
+
private resolve;
|
|
73
|
+
private failLater;
|
|
74
|
+
subscribeWidget(datasource: DatasourceSelector, sink: WidgetStreamSink): () => void;
|
|
75
|
+
subscribeAlarms(subscription: AlarmSubscription, sink: AlarmStreamSink): () => void;
|
|
76
|
+
subscribeCommands(_subscription: CommandSubscription, sink: CommandStreamSink): () => void;
|
|
77
|
+
subscribeLocations(subscription: LocationSubscription, sink: LocationStreamSink): () => void;
|
|
78
|
+
isDatasourceAvailable(datasource: DatasourceSelector | undefined): Promise<boolean>;
|
|
79
|
+
disposeAll(): void;
|
|
80
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export declare const RECORDING_FORMAT_VERSION = 1;
|
|
2
|
+
export declare const RECORDING_KIND = "sitepulse-board-recording";
|
|
3
|
+
declare const ALARM_STATES: readonly ['ACTIVE', 'CLEARED'];
|
|
4
|
+
declare const ALARM_SEVERITIES: readonly ['CRITICAL', 'MAJOR', 'MINOR', 'WARNING'];
|
|
5
|
+
export declare class RecordingFormatError extends Error {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
constructor(path: string, reason: string);
|
|
8
|
+
}
|
|
9
|
+
export interface RecordedClockSegment {
|
|
10
|
+
fromMs: number;
|
|
11
|
+
mode: string;
|
|
12
|
+
scale: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RecordedDevice {
|
|
15
|
+
id: string;
|
|
16
|
+
token: string;
|
|
17
|
+
kind: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RecordedChannels {
|
|
20
|
+
measurements: string[];
|
|
21
|
+
alarms: boolean;
|
|
22
|
+
locations: false;
|
|
23
|
+
commands: false;
|
|
24
|
+
}
|
|
25
|
+
export interface RecordedChapter {
|
|
26
|
+
tMs: number;
|
|
27
|
+
name: string;
|
|
28
|
+
note: string;
|
|
29
|
+
}
|
|
30
|
+
export interface RecordedMeasurementColumns {
|
|
31
|
+
d: number[];
|
|
32
|
+
n: number[];
|
|
33
|
+
t: number[];
|
|
34
|
+
v: number[];
|
|
35
|
+
s: Array<0 | 1>;
|
|
36
|
+
}
|
|
37
|
+
export interface RecordedAlarm {
|
|
38
|
+
id: string;
|
|
39
|
+
dev: string;
|
|
40
|
+
key: string;
|
|
41
|
+
metric: string;
|
|
42
|
+
state: (typeof ALARM_STATES)[number];
|
|
43
|
+
sev: (typeof ALARM_SEVERITIES)[number];
|
|
44
|
+
occ: string;
|
|
45
|
+
ack?: true;
|
|
46
|
+
}
|
|
47
|
+
export interface RecordedAlarmSnapshot {
|
|
48
|
+
tMs: number;
|
|
49
|
+
requestedAtMs: number;
|
|
50
|
+
total: number;
|
|
51
|
+
alarms: RecordedAlarm[];
|
|
52
|
+
}
|
|
53
|
+
export interface RecordedAlarmEvent extends RecordedAlarm {
|
|
54
|
+
tMs: number;
|
|
55
|
+
}
|
|
56
|
+
export interface BoardRecording {
|
|
57
|
+
kind: typeof RECORDING_KIND;
|
|
58
|
+
formatVersion: typeof RECORDING_FORMAT_VERSION;
|
|
59
|
+
runId: string;
|
|
60
|
+
startedAtUtc: string;
|
|
61
|
+
durationMs: number;
|
|
62
|
+
platformVersion: string;
|
|
63
|
+
instance: string;
|
|
64
|
+
tenant: string;
|
|
65
|
+
build: {
|
|
66
|
+
gitSha: string;
|
|
67
|
+
sdkCommit: string;
|
|
68
|
+
};
|
|
69
|
+
clock: RecordedClockSegment[];
|
|
70
|
+
devices: RecordedDevice[];
|
|
71
|
+
channels: RecordedChannels;
|
|
72
|
+
board: {
|
|
73
|
+
path: string;
|
|
74
|
+
sourceCommit: string;
|
|
75
|
+
sha256: string;
|
|
76
|
+
};
|
|
77
|
+
sourceHashes: Record<string, string>;
|
|
78
|
+
converter: {
|
|
79
|
+
version: number;
|
|
80
|
+
};
|
|
81
|
+
chapters: RecordedChapter[];
|
|
82
|
+
excerpt?: {
|
|
83
|
+
fromMs: number;
|
|
84
|
+
toMs: number;
|
|
85
|
+
};
|
|
86
|
+
measurements: RecordedMeasurementColumns;
|
|
87
|
+
alarms: {
|
|
88
|
+
snapshots: RecordedAlarmSnapshot[];
|
|
89
|
+
events: RecordedAlarmEvent[];
|
|
90
|
+
};
|
|
91
|
+
locations: [];
|
|
92
|
+
}
|
|
93
|
+
export declare function recordingBounds(rec: BoardRecording): {
|
|
94
|
+
fromMs: number;
|
|
95
|
+
toMs: number;
|
|
96
|
+
};
|
|
97
|
+
export declare function recordedWallTimeMs(rec: BoardRecording, tMs: number): number;
|
|
98
|
+
export declare function simulationScaleAt(rec: BoardRecording, tMs: number): {
|
|
99
|
+
mode: string;
|
|
100
|
+
scale: number;
|
|
101
|
+
} | null;
|
|
102
|
+
export declare function compareInstants(a: string, b: string): number;
|
|
103
|
+
export declare function parseBoardRecording(input: unknown): BoardRecording;
|
|
104
|
+
export {};
|
package/dist/slots.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AnchorTarget, type DashboardDefinition, type LocationSelection, type SlotBinding, type SlotScope, type WidgetInstance } from './types';
|
|
2
2
|
export declare function sameBinding(a: SlotBinding | undefined, b: SlotBinding | undefined): boolean;
|
|
3
3
|
export declare function migrateToSlots(def: DashboardDefinition): DashboardDefinition;
|
|
4
4
|
export declare function bindWidgetSlot(def: DashboardDefinition, widgetId: string, binding: SlotBinding, measurements: string[], location?: LocationSelection): DashboardDefinition;
|
package/dist/types.d.ts
CHANGED
|
@@ -43,7 +43,12 @@ export interface SlotSelector {
|
|
|
43
43
|
measurements: string[];
|
|
44
44
|
location?: LocationSelection;
|
|
45
45
|
}
|
|
46
|
-
export
|
|
46
|
+
export interface UnboundSelector {
|
|
47
|
+
kind: 'unbound';
|
|
48
|
+
measurements: string[];
|
|
49
|
+
location?: LocationSelection;
|
|
50
|
+
}
|
|
51
|
+
export type DatasourceSelector = DeviceSelector | AnchorSelector | DevicesSelector | RelatedTraversalSelector | SlotSelector | UnboundSelector;
|
|
47
52
|
export declare const WIDGET_TYPES: readonly ['timeseries-chart', 'latest-card', 'gauge', 'table', 'label', 'image', 'alarm-table', 'alarm-count', 'command-button', 'entity-selector', 'map'];
|
|
48
53
|
export type WidgetType = (typeof WIDGET_TYPES)[number];
|
|
49
54
|
export interface WidgetBox {
|
|
@@ -58,13 +63,51 @@ export interface WidgetBox {
|
|
|
58
63
|
};
|
|
59
64
|
}
|
|
60
65
|
export type WidgetLayout = Record<string, WidgetBox>;
|
|
61
|
-
export
|
|
66
|
+
export declare const UNKNOWN_WIDGET_TYPE = "unknown-widget";
|
|
67
|
+
export type UnknownWidgetType = typeof UNKNOWN_WIDGET_TYPE;
|
|
68
|
+
export interface WidgetImplementationRef {
|
|
69
|
+
version: string;
|
|
70
|
+
optionsVersion: number;
|
|
71
|
+
sdkApiVersion?: number;
|
|
72
|
+
}
|
|
73
|
+
export type ExtensionWidgetType = `${string}/${string}`;
|
|
74
|
+
export interface KnownWidgetInstance {
|
|
62
75
|
id: string;
|
|
63
76
|
type: WidgetType;
|
|
77
|
+
widget?: WidgetImplementationRef;
|
|
64
78
|
layout: WidgetLayout;
|
|
65
79
|
datasource?: DatasourceSelector;
|
|
66
80
|
options?: Record<string, unknown>;
|
|
81
|
+
raw?: undefined;
|
|
82
|
+
reason?: undefined;
|
|
67
83
|
}
|
|
84
|
+
export interface ExtensionWidgetInstance {
|
|
85
|
+
id: string;
|
|
86
|
+
type: ExtensionWidgetType;
|
|
87
|
+
widget: WidgetImplementationRef;
|
|
88
|
+
layout: WidgetLayout;
|
|
89
|
+
datasource?: DatasourceSelector;
|
|
90
|
+
options?: Record<string, unknown>;
|
|
91
|
+
raw?: undefined;
|
|
92
|
+
reason?: undefined;
|
|
93
|
+
}
|
|
94
|
+
export type UnresolvedWidgetCode = 'unregistered' | 'unversioned' | 'invalid-metadata' | 'options-version' | 'sdk-incompatible';
|
|
95
|
+
export interface UnresolvedWidgetReason {
|
|
96
|
+
code: UnresolvedWidgetCode;
|
|
97
|
+
message: string;
|
|
98
|
+
}
|
|
99
|
+
export interface UnknownWidgetInstance {
|
|
100
|
+
id: string;
|
|
101
|
+
type: UnknownWidgetType;
|
|
102
|
+
layout: WidgetLayout;
|
|
103
|
+
raw: Record<string, unknown>;
|
|
104
|
+
reason?: UnresolvedWidgetReason;
|
|
105
|
+
widget?: undefined;
|
|
106
|
+
datasource?: undefined;
|
|
107
|
+
options?: undefined;
|
|
108
|
+
}
|
|
109
|
+
export type WidgetInstance = KnownWidgetInstance | ExtensionWidgetInstance | UnknownWidgetInstance;
|
|
110
|
+
export type ResolvedWidgetInstance = KnownWidgetInstance | ExtensionWidgetInstance;
|
|
68
111
|
export interface CanvasBackground {
|
|
69
112
|
color?: string | null;
|
|
70
113
|
imageUrl?: string | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type WidgetDescriptor } from './widget-descriptor';
|
|
2
|
+
export interface DescriptorIssue {
|
|
3
|
+
id: string;
|
|
4
|
+
path: string;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WidgetCatalog {
|
|
8
|
+
has(id: string): boolean;
|
|
9
|
+
get(id: string): WidgetDescriptor | undefined;
|
|
10
|
+
list(): readonly WidgetDescriptor[];
|
|
11
|
+
}
|
|
12
|
+
export declare class WidgetCatalogError extends Error {
|
|
13
|
+
readonly issues: readonly DescriptorIssue[];
|
|
14
|
+
constructor(issues: readonly DescriptorIssue[], subject?: string);
|
|
15
|
+
}
|
|
16
|
+
export declare function describeIssues(subject: string, issues: readonly DescriptorIssue[]): string;
|
|
17
|
+
export declare function validateWidgetDescriptor(descriptor: unknown): DescriptorIssue[];
|
|
18
|
+
export declare function createWidgetCatalog(descriptors: readonly WidgetDescriptor[]): WidgetCatalog;
|
|
19
|
+
export declare function collectCatalogIssues(descriptors: readonly unknown[]): DescriptorIssue[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { WidgetCatalog } from './widget-catalog';
|
|
2
|
+
import type { WidgetDescriptor } from './widget-descriptor';
|
|
3
|
+
import type { DashboardDefinition, ResolvedWidgetInstance, UnresolvedWidgetReason, WidgetImplementationRef, WidgetInstance } from './types';
|
|
4
|
+
import { type KnownWidgetInstance } from './types';
|
|
5
|
+
export declare function isBuiltinWidget(widget: WidgetInstance): widget is KnownWidgetInstance;
|
|
6
|
+
export declare function isResolvedWidget(widget: WidgetInstance): widget is ResolvedWidgetInstance;
|
|
7
|
+
export declare function parseWidgetRef(raw: unknown): WidgetImplementationRef | undefined | null;
|
|
8
|
+
export declare function checkWidgetCompatibility(id: string, ref: WidgetImplementationRef, descriptor: WidgetDescriptor): UnresolvedWidgetReason | undefined;
|
|
9
|
+
export declare function widgetVersionNotice(id: string, ref: WidgetImplementationRef | undefined, descriptor: WidgetDescriptor): string | undefined;
|
|
10
|
+
export declare function unresolvedReason(type: string, rawRef: unknown, catalog: WidgetCatalog | undefined, builtin: boolean): UnresolvedWidgetReason | undefined;
|
|
11
|
+
export interface UnresolvedWidgetReport {
|
|
12
|
+
widgetId: string;
|
|
13
|
+
type: string;
|
|
14
|
+
reason: UnresolvedWidgetReason;
|
|
15
|
+
}
|
|
16
|
+
export declare function unresolvedWidgets(definition: Pick<DashboardDefinition, 'widgets'>): UnresolvedWidgetReport[];
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { AlarmStreamState, CommandStreamState, LocationStreamState, MeasurementStreamState } from './channel-snapshots';
|
|
2
|
+
import type { DefaultsOf, OptionConstraint, OptionKeysOfKind, WidgetOptionSpecs } from './option-schema';
|
|
3
|
+
import { type WidgetType } from './types';
|
|
4
|
+
export type WidgetChannel = 'measurement' | 'alarm' | 'control' | 'selection' | 'location' | 'none';
|
|
5
|
+
export type ChannelSnapshot<C extends WidgetChannel> = C extends 'measurement' ? MeasurementStreamState : C extends 'alarm' ? AlarmStreamState : C extends 'control' ? CommandStreamState : C extends 'location' ? LocationStreamState : null;
|
|
6
|
+
export type BuiltinWidgetId = WidgetType;
|
|
7
|
+
export type NamespacedWidgetId = `${string}/${string}`;
|
|
8
|
+
export type WidgetId = BuiltinWidgetId | NamespacedWidgetId;
|
|
9
|
+
export declare function isBuiltinWidgetId(id: unknown): id is BuiltinWidgetId;
|
|
10
|
+
export declare function isNamespacedWidgetId(id: unknown): id is NamespacedWidgetId;
|
|
11
|
+
export type DatasourceSelectorKind = 'device' | 'anchor' | 'slot';
|
|
12
|
+
export type DatasourcePolicy = {
|
|
13
|
+
mode: 'none';
|
|
14
|
+
} | {
|
|
15
|
+
mode: 'optional' | 'required';
|
|
16
|
+
selectors: readonly DatasourceSelectorKind[];
|
|
17
|
+
};
|
|
18
|
+
type ControlDatasourcePolicy = {
|
|
19
|
+
mode: 'none';
|
|
20
|
+
} | {
|
|
21
|
+
mode: 'optional' | 'required';
|
|
22
|
+
selectors: readonly ('device' | 'slot')[];
|
|
23
|
+
};
|
|
24
|
+
export type DatasourcePolicyFor<C extends WidgetChannel> = C extends 'none' | 'selection' ? {
|
|
25
|
+
mode: 'none';
|
|
26
|
+
} : C extends 'control' ? ControlDatasourcePolicy : DatasourcePolicy;
|
|
27
|
+
export interface ConstBinding<T> {
|
|
28
|
+
const: T;
|
|
29
|
+
}
|
|
30
|
+
export interface NumberOptionRef<S extends WidgetOptionSpecs = WidgetOptionSpecs> {
|
|
31
|
+
option: OptionKeysOfKind<S, 'number'>;
|
|
32
|
+
default?: number;
|
|
33
|
+
min?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface StringOptionRef<S extends WidgetOptionSpecs = WidgetOptionSpecs> {
|
|
36
|
+
option: OptionKeysOfKind<S, 'string' | 'enum'>;
|
|
37
|
+
default?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface AckOptionRef<S extends WidgetOptionSpecs = WidgetOptionSpecs> {
|
|
40
|
+
option: OptionKeysOfKind<S, 'enum'>;
|
|
41
|
+
default?: 'true' | 'false';
|
|
42
|
+
}
|
|
43
|
+
type PageSize<S extends WidgetOptionSpecs> = ConstBinding<number> | NumberOptionRef<S>;
|
|
44
|
+
export type ChannelBindingPolicy<C extends WidgetChannel, S extends WidgetOptionSpecs = WidgetOptionSpecs> = C extends 'measurement' ? {
|
|
45
|
+
window?: NumberOptionRef<S>;
|
|
46
|
+
} : C extends 'alarm' ? {
|
|
47
|
+
pageSize: PageSize<S>;
|
|
48
|
+
state?: StringOptionRef<S>;
|
|
49
|
+
severity?: StringOptionRef<S>;
|
|
50
|
+
acknowledged?: AckOptionRef<S>;
|
|
51
|
+
} : C extends 'control' ? {
|
|
52
|
+
pageSize: PageSize<S>;
|
|
53
|
+
} : Record<string, never>;
|
|
54
|
+
export interface WidgetInteractionDeclaration {
|
|
55
|
+
alarmActions?: true;
|
|
56
|
+
commandSend?: true;
|
|
57
|
+
selection?: true;
|
|
58
|
+
candidates?: true;
|
|
59
|
+
}
|
|
60
|
+
export type InteractionsFor<C extends WidgetChannel> = {
|
|
61
|
+
selection?: true;
|
|
62
|
+
candidates?: true;
|
|
63
|
+
} & ('alarm' extends C ? {
|
|
64
|
+
alarmActions?: true;
|
|
65
|
+
} : unknown) & ('control' extends C ? {
|
|
66
|
+
commandSend?: true;
|
|
67
|
+
} : unknown);
|
|
68
|
+
export interface WidgetDisplay {
|
|
69
|
+
title: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
category?: string;
|
|
72
|
+
titleId?: string;
|
|
73
|
+
categoryId?: string;
|
|
74
|
+
}
|
|
75
|
+
export declare const SDK_API_VERSION = 1;
|
|
76
|
+
export interface WidgetDescriptor<C extends WidgetChannel = WidgetChannel, S extends WidgetOptionSpecs = WidgetOptionSpecs> {
|
|
77
|
+
id: WidgetId;
|
|
78
|
+
version: string;
|
|
79
|
+
sdkApiVersion: 1;
|
|
80
|
+
optionsVersion: number;
|
|
81
|
+
display: WidgetDisplay;
|
|
82
|
+
channel: C;
|
|
83
|
+
datasource: DatasourcePolicyFor<C>;
|
|
84
|
+
binding: ChannelBindingPolicy<C, S>;
|
|
85
|
+
options: S;
|
|
86
|
+
constraints?: readonly OptionConstraint<OptionKeysOfKind<S, 'number'>>[];
|
|
87
|
+
defaults: DefaultsOf<S>;
|
|
88
|
+
interactions: InteractionsFor<C>;
|
|
89
|
+
}
|
|
90
|
+
export declare function defineWidgetDescriptor<const C extends WidgetChannel, const S extends WidgetOptionSpecs>(descriptor: WidgetDescriptor<C, S>): WidgetDescriptor<C, S>;
|
|
91
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devicechain/dashboards",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "DeviceChain dashboard runtime — the DashboardHub (telemetry subscription multiplexing over the client wire, plus the alarm, command and location channels) and the dashboard-definition, selector, slot, and binding-manifest types.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"devicechain",
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"@graphql-typed-document-node/core": "^3.2.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@devicechain/client": "0.
|
|
49
|
+
"@devicechain/client": "0.20.0",
|
|
50
50
|
"graphql": "^16.0.0 || ^17.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@devicechain/client": "0.
|
|
54
|
-
"@types/node": "^26.4
|
|
53
|
+
"@devicechain/client": "0.20.0",
|
|
54
|
+
"@types/node": "^26.6.4",
|
|
55
55
|
"graphql": "^17.0.2",
|
|
56
56
|
"typescript": "~7.0.2",
|
|
57
|
-
"vitest": "^5.0.
|
|
57
|
+
"vitest": "^5.0.3"
|
|
58
58
|
}
|
|
59
59
|
}
|