Dashboards as documents, and messages as something to bind to

A dashboard is its own document rather than widgets placed in a flow.
Node-RED's dashboard tab is 260 nodes, about forty of them pure layout,
which is exactly what the small-graph principle exists to avoid — and
since the graph is already wired by message name, a widget can bind to a
name without belonging to any flow.

Stored beside the flows in the same repository, sharing their write lock
and commit, under a directory the flow listing ignores. No draft/publish
split: nothing executes a dashboard, so edit mode is its own staging area.

Two things it needs from the engine. A message catalog spanning every
flow, because a wall panel shows the heating next to the solar and the
flow-scoped API is the wrong shape for that. And a way to put a value in
without owning a node — a slider is a real value that happened to come
from a person — which runs whatever consumes it and applies the same type
check a node's output gets. Only a message some flow declares can be
published to; flows own the namespace.

Charts also need more past than the 120 points a sparkline wanted, so a
chart widget declares its depth and the engine keeps that message's
series that deep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LF61rxW1FG5YCD2J9YqjY
This commit is contained in:
2026-08-16 09:20:49 +02:00
co-authored by Claude Fable 5
parent 80acf342f4
commit 895bd89b2b
13 changed files with 1713 additions and 66 deletions
+471 -40
View File
@@ -200,6 +200,113 @@ Binary payloads (tensors, images) will arrive later as explicitly declared
codec fields; until then everything on the wire is JSON.`
} as const;
export const DashboardDef_InputSchema = {
properties: {
name: {
type: 'string',
title: 'Name'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
pages: {
items: {
'$ref': '#/components/schemas/PageDef-Input'
},
type: 'array',
title: 'Pages'
},
version: {
type: 'integer',
title: 'Version',
default: 1
}
},
type: 'object',
required: ['name'],
title: 'DashboardDef',
description: 'A dashboard as stored, and as the API hands it over.'
} as const;
export const DashboardDef_OutputSchema = {
properties: {
name: {
type: 'string',
title: 'Name'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
pages: {
items: {
'$ref': '#/components/schemas/PageDef-Output'
},
type: 'array',
title: 'Pages'
},
version: {
type: 'integer',
title: 'Version',
default: 1
}
},
type: 'object',
required: ['name'],
title: 'DashboardDef',
description: 'A dashboard as stored, and as the API hands it over.'
} as const;
export const DashboardSummarySchema = {
properties: {
name: {
type: 'string',
title: 'Name'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
page_count: {
type: 'integer',
title: 'Page Count',
default: 0
},
widget_count: {
type: 'integer',
title: 'Widget Count',
default: 0
}
},
type: 'object',
required: ['name'],
title: 'DashboardSummary',
description: 'A dashboard in a list, without its contents.'
} as const;
export const DashboardsPublicSchema = {
properties: {
data: {
items: {
'$ref': '#/components/schemas/DashboardSummary'
},
type: 'array',
title: 'Data'
},
count: {
type: 'integer',
title: 'Count'
}
},
type: 'object',
required: ['data', 'count'],
title: 'DashboardsPublic'
} as const;
export const FlowDef_InputSchema = {
properties: {
name: {
@@ -367,7 +474,7 @@ export const FlowStatePublicSchema = {
properties: {
values: {
additionalProperties: {
'$ref': '#/components/schemas/MessageValue'
'$ref': '#/components/schemas/app__flow__schemas__MessageValue'
},
type: 'object',
title: 'Values'
@@ -541,6 +648,85 @@ Only numbers are recorded, so \`\`numeric\`\` tells the panel whether an empty
series means "nothing plottable here" or "nothing has arrived yet".`
} as const;
export const MessageInfoSchema = {
properties: {
name: {
type: 'string',
title: 'Name'
},
flow: {
type: 'string',
title: 'Flow'
},
dtype: {
type: 'string',
title: 'Dtype'
},
providers: {
items: {
type: 'string'
},
type: 'array',
title: 'Providers',
default: []
},
writable: {
type: 'boolean',
title: 'Writable',
default: true
},
numeric: {
type: 'boolean',
title: 'Numeric',
default: false
},
value: {
title: 'Value'
},
ts: {
anyOf: [
{
type: 'number'
},
{
type: 'null'
}
],
title: 'Ts'
}
},
type: 'object',
required: ['name', 'flow', 'dtype'],
title: 'MessageInfo',
description: 'One message, as something to bind a widget to.'
} as const;
export const MessagePointsSchema = {
properties: {
message: {
type: 'string',
title: 'Message'
},
numeric: {
type: 'boolean',
title: 'Numeric'
},
points: {
items: {
additionalProperties: {
type: 'number'
},
type: 'object'
},
type: 'array',
title: 'Points'
}
},
type: 'object',
required: ['message', 'numeric', 'points'],
title: 'MessagePoints'
} as const;
export const MessageSpecSchema = {
properties: {
name: {
@@ -588,26 +774,23 @@ export const MessageSpecSchema = {
message it also produces without depending on itself.`
} as const;
export const MessageValueSchema = {
export const MessagesPublicSchema = {
properties: {
value: {
title: 'Value'
data: {
items: {
'$ref': '#/components/schemas/MessageInfo'
},
type: 'array',
title: 'Data'
},
ts: {
anyOf: [
{
type: 'number'
},
{
type: 'null'
}
],
title: 'Ts'
count: {
type: 'integer',
title: 'Count'
}
},
type: 'object',
title: 'MessageValue',
description: 'The last payload seen on a message.'
required: ['data', 'count'],
title: 'MessagesPublic'
} as const;
export const NewPasswordSchema = {
@@ -1006,6 +1189,94 @@ export const OAuthClientRegisterSchema = {
description: 'RFC 7591 dynamic client registration request.'
} as const;
export const PageDef_InputSchema = {
properties: {
id: {
type: 'string',
title: 'Id'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
icon: {
type: 'string',
title: 'Icon',
default: ''
},
sections: {
items: {
'$ref': '#/components/schemas/SectionDef-Input'
},
type: 'array',
title: 'Sections'
}
},
type: 'object',
required: ['id'],
title: 'PageDef',
description: 'One tab of a dashboard.'
} as const;
export const PageDef_OutputSchema = {
properties: {
id: {
type: 'string',
title: 'Id'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
icon: {
type: 'string',
title: 'Icon',
default: ''
},
sections: {
items: {
'$ref': '#/components/schemas/SectionDef-Output'
},
type: 'array',
title: 'Sections'
}
},
type: 'object',
required: ['id'],
title: 'PageDef',
description: 'One tab of a dashboard.'
} as const;
export const PlacementSchema = {
properties: {
x: {
type: 'integer',
title: 'X',
default: 0
},
y: {
type: 'integer',
title: 'Y',
default: 0
},
w: {
type: 'integer',
title: 'W',
default: 3
},
h: {
type: 'integer',
title: 'H',
default: 2
}
},
type: 'object',
title: 'Placement',
description: "Where a widget sits in its section's grid, in grid units."
} as const;
export const PositionSchema = {
properties: {
x: {
@@ -1049,30 +1320,6 @@ export const PrivateUserCreateSchema = {
title: 'PrivateUserCreate'
} as const;
export const PublishRequestSchema = {
properties: {
version: {
type: 'integer',
title: 'Version'
}
},
type: 'object',
required: ['version'],
title: 'PublishRequest'
} as const;
export const RenameRequestSchema = {
properties: {
new_name: {
type: 'string',
title: 'New Name'
}
},
type: 'object',
required: ['new_name'],
title: 'RenameRequest'
} as const;
export const RuleSchema = {
properties: {
events: {
@@ -1144,6 +1391,56 @@ export const SecretValueSchema = {
title: 'SecretValue'
} as const;
export const SectionDef_InputSchema = {
properties: {
id: {
type: 'string',
title: 'Id'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
widgets: {
items: {
'$ref': '#/components/schemas/WidgetDef'
},
type: 'array',
title: 'Widgets'
}
},
type: 'object',
required: ['id'],
title: 'SectionDef',
description: 'A grid of widgets under a heading.'
} as const;
export const SectionDef_OutputSchema = {
properties: {
id: {
type: 'string',
title: 'Id'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
widgets: {
items: {
'$ref': '#/components/schemas/WidgetDef'
},
type: 'array',
title: 'Widgets'
}
},
type: 'object',
required: ['id'],
title: 'SectionDef',
description: 'A grid of widgets under a heading.'
} as const;
export const ShareRequestSchema = {
properties: {
lib_name: {
@@ -1546,4 +1843,138 @@ export const ValidationResultSchema = {
},
type: 'object',
title: 'ValidationResult'
} as const;
export const WidgetDefSchema = {
properties: {
id: {
type: 'string',
title: 'Id'
},
type: {
type: 'string',
enum: ['stat', 'gauge', 'chart', 'markdown', 'button', 'switch', 'slider', 'input', 'dropdown'],
title: 'Type'
},
title: {
type: 'string',
title: 'Title',
default: ''
},
layout: {
additionalProperties: {
'$ref': '#/components/schemas/Placement'
},
type: 'object',
title: 'Layout'
},
config: {
additionalProperties: true,
type: 'object',
title: 'Config'
}
},
type: 'object',
required: ['id', 'type'],
title: 'WidgetDef',
description: `One tile: what it shows or does, and where it sits.
\`\`config\`\` is per type — a chart names its series, a button names the
message it publishes — and is validated against the type below rather than
by a schema per class, because the whole set is small and closed.`
} as const;
export const app__api__routes__dashboards__RenameRequestSchema = {
properties: {
name: {
type: 'string',
title: 'Name'
}
},
type: 'object',
required: ['name'],
title: 'RenameRequest'
} as const;
export const app__api__routes__flows__PublishRequestSchema = {
properties: {
version: {
type: 'integer',
title: 'Version'
}
},
type: 'object',
required: ['version'],
title: 'PublishRequest'
} as const;
export const app__api__routes__flows__RenameRequestSchema = {
properties: {
new_name: {
type: 'string',
title: 'New Name'
}
},
type: 'object',
required: ['new_name'],
title: 'RenameRequest'
} as const;
export const app__api__routes__messages__MessageValueSchema = {
properties: {
name: {
type: 'string',
title: 'Name'
},
value: {
title: 'Value'
},
ts: {
anyOf: [
{
type: 'number'
},
{
type: 'null'
}
],
title: 'Ts'
}
},
type: 'object',
required: ['name', 'value'],
title: 'MessageValue'
} as const;
export const app__api__routes__messages__PublishRequestSchema = {
properties: {
value: {
title: 'Value'
}
},
type: 'object',
required: ['value'],
title: 'PublishRequest'
} as const;
export const app__flow__schemas__MessageValueSchema = {
properties: {
value: {
title: 'Value'
},
ts: {
anyOf: [
{
type: 'number'
},
{
type: 'null'
}
],
title: 'Ts'
}
},
type: 'object',
title: 'MessageValue',
description: 'The last payload seen on a message.'
} as const;
+187 -1
View File
@@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
import type { AlertsReadAlertsConfigResponse, AlertsSaveAlertsConfigData, AlertsSaveAlertsConfigResponse, AlertsTestChannelData, AlertsTestChannelResponse, FlowsReadFlowsResponse, FlowsReadNodeTypesResponse, FlowsReadLibraryResponse, FlowsDeleteSharedNodeData, FlowsDeleteSharedNodeResponse, FlowsReadFlowData, FlowsReadFlowResponse, FlowsSaveFlowData, FlowsSaveFlowResponse, FlowsDeleteFlowData, FlowsDeleteFlowResponse, FlowsPublishFlowData, FlowsPublishFlowResponse, FlowsDiscardDraftData, FlowsDiscardDraftResponse, FlowsRenameFlowData, FlowsRenameFlowResponse, FlowsReadNodeSourceData, FlowsReadNodeSourceResponse, FlowsSaveNodeSourceData, FlowsSaveNodeSourceResponse, FlowsShareNodeData, FlowsShareNodeResponse, FlowsUnshareNodeData, FlowsUnshareNodeResponse, FlowsStartFlowData, FlowsStartFlowResponse, FlowsStopFlowData, FlowsStopFlowResponse, FlowsPauseFlowData, FlowsPauseFlowResponse, FlowsResumeFlowData, FlowsResumeFlowResponse, FlowsValidateFlowData, FlowsValidateFlowResponse, FlowsRunFlowData, FlowsRunFlowResponse, FlowsTriggerNodeData, FlowsTriggerNodeResponse, FlowsReadFlowStateData, FlowsReadFlowStateResponse, FlowsReadMessageHistoryData, FlowsReadMessageHistoryResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, OauthRegisterClientData, OauthRegisterClientResponse, OauthAuthorizeValidateData, OauthAuthorizeValidateResponse, OauthAuthorizeData, OauthAuthorizeResponse, OauthTokenData, OauthTokenResponse, PrivateCreateUserData, PrivateCreateUserResponse, SecretsReadSecretsResponse, SecretsSaveSecretData, SecretsSaveSecretResponse, SecretsDeleteSecretData, SecretsDeleteSecretResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse, UtilsHealthResponse } from './types.gen';
import type { AlertsReadAlertsConfigResponse, AlertsSaveAlertsConfigData, AlertsSaveAlertsConfigResponse, AlertsTestChannelData, AlertsTestChannelResponse, DashboardsReadDashboardsResponse, DashboardsReadDashboardData, DashboardsReadDashboardResponse, DashboardsCreateDashboardData, DashboardsCreateDashboardResponse, DashboardsSaveDashboardData, DashboardsSaveDashboardResponse, DashboardsDeleteDashboardData, DashboardsDeleteDashboardResponse, DashboardsRenameDashboardData, DashboardsRenameDashboardResponse, FlowsReadFlowsResponse, FlowsReadNodeTypesResponse, FlowsReadLibraryResponse, FlowsDeleteSharedNodeData, FlowsDeleteSharedNodeResponse, FlowsReadFlowData, FlowsReadFlowResponse, FlowsSaveFlowData, FlowsSaveFlowResponse, FlowsDeleteFlowData, FlowsDeleteFlowResponse, FlowsPublishFlowData, FlowsPublishFlowResponse, FlowsDiscardDraftData, FlowsDiscardDraftResponse, FlowsRenameFlowData, FlowsRenameFlowResponse, FlowsReadNodeSourceData, FlowsReadNodeSourceResponse, FlowsSaveNodeSourceData, FlowsSaveNodeSourceResponse, FlowsShareNodeData, FlowsShareNodeResponse, FlowsUnshareNodeData, FlowsUnshareNodeResponse, FlowsStartFlowData, FlowsStartFlowResponse, FlowsStopFlowData, FlowsStopFlowResponse, FlowsPauseFlowData, FlowsPauseFlowResponse, FlowsResumeFlowData, FlowsResumeFlowResponse, FlowsValidateFlowData, FlowsValidateFlowResponse, FlowsRunFlowData, FlowsRunFlowResponse, FlowsTriggerNodeData, FlowsTriggerNodeResponse, FlowsReadFlowStateData, FlowsReadFlowStateResponse, FlowsReadMessageHistoryData, FlowsReadMessageHistoryResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, MessagesReadMessagesResponse, MessagesPublishMessageData, MessagesPublishMessageResponse, MessagesReadMessageHistoryData, MessagesReadMessageHistoryResponse, OauthRegisterClientData, OauthRegisterClientResponse, OauthAuthorizeValidateData, OauthAuthorizeValidateResponse, OauthAuthorizeData, OauthAuthorizeResponse, OauthTokenData, OauthTokenResponse, PrivateCreateUserData, PrivateCreateUserResponse, SecretsReadSecretsResponse, SecretsSaveSecretData, SecretsSaveSecretResponse, SecretsDeleteSecretData, SecretsDeleteSecretResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse, UtilsHealthResponse } from './types.gen';
export class AlertsService {
/**
@@ -61,6 +61,129 @@ export class AlertsService {
}
}
export class DashboardsService {
/**
* Read Dashboards
* Every dashboard, without its contents.
* @returns DashboardsPublic Successful Response
* @throws ApiError
*/
public static readDashboards(): CancelablePromise<DashboardsReadDashboardsResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v1/dashboards/'
});
}
/**
* Read Dashboard
* @param data The data for the request.
* @param data.name
* @returns DashboardDef_Output Successful Response
* @throws ApiError
*/
public static readDashboard(data: DashboardsReadDashboardData): CancelablePromise<DashboardsReadDashboardResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v1/dashboards/{name}',
path: {
name: data.name
},
errors: {
422: 'Validation Error'
}
});
}
/**
* Create Dashboard
* Start a dashboard: one page, one section, nothing on it yet.
* @param data The data for the request.
* @param data.name
* @returns DashboardDef_Output Successful Response
* @throws ApiError
*/
public static createDashboard(data: DashboardsCreateDashboardData): CancelablePromise<DashboardsCreateDashboardResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/v1/dashboards/{name}',
path: {
name: data.name
},
errors: {
422: 'Validation Error'
}
});
}
/**
* Save Dashboard
* Replace a dashboard, refusing a save someone else has moved past.
* @param data The data for the request.
* @param data.name
* @param data.requestBody
* @returns DashboardDef_Output Successful Response
* @throws ApiError
*/
public static saveDashboard(data: DashboardsSaveDashboardData): CancelablePromise<DashboardsSaveDashboardResponse> {
return __request(OpenAPI, {
method: 'PUT',
url: '/api/v1/dashboards/{name}',
path: {
name: data.name
},
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Delete Dashboard
* @param data The data for the request.
* @param data.name
* @returns Message Successful Response
* @throws ApiError
*/
public static deleteDashboard(data: DashboardsDeleteDashboardData): CancelablePromise<DashboardsDeleteDashboardResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/api/v1/dashboards/{name}',
path: {
name: data.name
},
errors: {
422: 'Validation Error'
}
});
}
/**
* Rename Dashboard
* @param data The data for the request.
* @param data.name
* @param data.requestBody
* @returns DashboardDef_Output Successful Response
* @throws ApiError
*/
public static renameDashboard(data: DashboardsRenameDashboardData): CancelablePromise<DashboardsRenameDashboardResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/v1/dashboards/{name}/rename',
path: {
name: data.name
},
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
}
export class FlowsService {
/**
* Read Flows
@@ -671,6 +794,69 @@ export class LoginService {
}
}
export class MessagesService {
/**
* Read Messages
* Every message any published flow declares, with its last value.
* @returns MessagesPublic Successful Response
* @throws ApiError
*/
public static readMessages(): CancelablePromise<MessagesReadMessagesResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v1/messages/'
});
}
/**
* Publish Message
* Put a value into the graph, as a dashboard control does.
*
* Only a message some flow declares can be published to: flows own the
* namespace, and a dashboard is a client of it rather than a second author.
* @param data The data for the request.
* @param data.name
* @param data.requestBody
* @returns app__api__routes__messages__MessageValue Successful Response
* @throws ApiError
*/
public static publishMessage(data: MessagesPublishMessageData): CancelablePromise<MessagesPublishMessageResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/v1/messages/{name}',
path: {
name: data.name
},
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Read Message History
* The series behind a chart. Numbers only — nothing else plots.
* @param data The data for the request.
* @param data.name
* @returns MessagePoints Successful Response
* @throws ApiError
*/
public static readMessageHistory(data: MessagesReadMessageHistoryData): CancelablePromise<MessagesReadMessageHistoryResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v1/messages/{name}/history',
path: {
name: data.name
},
errors: {
422: 'Validation Error'
}
});
}
}
export class OauthService {
/**
* Register Client
+211 -17
View File
@@ -9,6 +9,36 @@ export type AlertsConfig = {
rules?: Array<Rule>;
};
export type app__api__routes__dashboards__RenameRequest = {
name: string;
};
export type app__api__routes__flows__PublishRequest = {
version: number;
};
export type app__api__routes__flows__RenameRequest = {
new_name: string;
};
export type app__api__routes__messages__MessageValue = {
name: string;
value: unknown;
ts?: (number | null);
};
export type app__api__routes__messages__PublishRequest = {
value: unknown;
};
/**
* The last payload seen on a message.
*/
export type app__flow__schemas__MessageValue = {
value?: unknown;
ts?: (number | null);
};
export type Body_login_login_access_token = {
grant_type?: (string | null);
username: string;
@@ -42,6 +72,41 @@ export type Channel = {
export type kind = 'ntfy' | 'smtp' | 'webhook';
/**
* A dashboard as stored, and as the API hands it over.
*/
export type DashboardDef_Input = {
name: string;
title?: string;
pages?: Array<PageDef_Input>;
version?: number;
};
/**
* A dashboard as stored, and as the API hands it over.
*/
export type DashboardDef_Output = {
name: string;
title?: string;
pages?: Array<PageDef_Output>;
version?: number;
};
export type DashboardsPublic = {
data: Array<DashboardSummary>;
count: number;
};
/**
* A dashboard in a list, without its contents.
*/
export type DashboardSummary = {
name: string;
title?: string;
page_count?: number;
widget_count?: number;
};
/**
* Serializable payload types.
*
@@ -111,7 +176,7 @@ export type FlowsPublic = {
export type FlowStatePublic = {
values?: {
[key: string]: MessageValue;
[key: string]: app__flow__schemas__MessageValue;
};
nodes?: Array<NodeStatusPublic>;
};
@@ -163,6 +228,28 @@ export type MessageHistory = {
points?: Array<HistoryPoint>;
};
/**
* One message, as something to bind a widget to.
*/
export type MessageInfo = {
name: string;
flow: string;
dtype: string;
providers?: Array<(string)>;
writable?: boolean;
numeric?: boolean;
value?: unknown;
ts?: (number | null);
};
export type MessagePoints = {
message: string;
numeric: boolean;
points: Array<{
[key: string]: (number);
}>;
};
/**
* A single port of a node, and the message it is bound to.
*
@@ -188,12 +275,9 @@ export type MessageSpec = {
trigger?: boolean;
};
/**
* The last payload seen on a message.
*/
export type MessageValue = {
value?: unknown;
ts?: (number | null);
export type MessagesPublic = {
data: Array<MessageInfo>;
count: number;
};
export type NewPassword = {
@@ -302,6 +386,36 @@ export type OAuthClientRegister = {
token_endpoint_auth_method?: (string | null);
};
/**
* One tab of a dashboard.
*/
export type PageDef_Input = {
id: string;
title?: string;
icon?: string;
sections?: Array<SectionDef_Input>;
};
/**
* One tab of a dashboard.
*/
export type PageDef_Output = {
id: string;
title?: string;
icon?: string;
sections?: Array<SectionDef_Output>;
};
/**
* Where a widget sits in its section's grid, in grid units.
*/
export type Placement = {
x?: number;
y?: number;
w?: number;
h?: number;
};
/**
* Where a node sits on the canvas.
*/
@@ -317,14 +431,6 @@ export type PrivateUserCreate = {
is_verified?: boolean;
};
export type PublishRequest = {
version: number;
};
export type RenameRequest = {
new_name: string;
};
/**
* Which events go to which channels.
*/
@@ -349,6 +455,24 @@ export type SecretValue = {
value: string;
};
/**
* A grid of widgets under a heading.
*/
export type SectionDef_Input = {
id: string;
title?: string;
widgets?: Array<WidgetDef>;
};
/**
* A grid of widgets under a heading.
*/
export type SectionDef_Output = {
id: string;
title?: string;
widgets?: Array<WidgetDef>;
};
export type ShareRequest = {
lib_name: string;
};
@@ -435,6 +559,27 @@ export type ValidationResult = {
issues?: Array<ValidationIssue>;
};
/**
* One tile: what it shows or does, and where it sits.
*
* ``config`` is per type — a chart names its series, a button names the
* message it publishes — and is validated against the type below rather than
* by a schema per class, because the whole set is small and closed.
*/
export type WidgetDef = {
id: string;
type: 'stat' | 'gauge' | 'chart' | 'markdown' | 'button' | 'switch' | 'slider' | 'input' | 'dropdown';
title?: string;
layout?: {
[key: string]: Placement;
};
config?: {
[key: string]: unknown;
};
};
export type type = 'stat' | 'gauge' | 'chart' | 'markdown' | 'button' | 'switch' | 'slider' | 'input' | 'dropdown';
export type AlertsReadAlertsConfigResponse = (AlertsConfig);
export type AlertsSaveAlertsConfigData = {
@@ -449,6 +594,40 @@ export type AlertsTestChannelData = {
export type AlertsTestChannelResponse = (Message);
export type DashboardsReadDashboardsResponse = (DashboardsPublic);
export type DashboardsReadDashboardData = {
name: string;
};
export type DashboardsReadDashboardResponse = (DashboardDef_Output);
export type DashboardsCreateDashboardData = {
name: string;
};
export type DashboardsCreateDashboardResponse = (DashboardDef_Output);
export type DashboardsSaveDashboardData = {
name: string;
requestBody: DashboardDef_Input;
};
export type DashboardsSaveDashboardResponse = (DashboardDef_Output);
export type DashboardsDeleteDashboardData = {
name: string;
};
export type DashboardsDeleteDashboardResponse = (Message);
export type DashboardsRenameDashboardData = {
name: string;
requestBody: app__api__routes__dashboards__RenameRequest;
};
export type DashboardsRenameDashboardResponse = (DashboardDef_Output);
export type FlowsReadFlowsResponse = (FlowsPublic);
export type FlowsReadNodeTypesResponse = (Array<NodeTypeInfo>);
@@ -482,7 +661,7 @@ export type FlowsDeleteFlowResponse = (Message);
export type FlowsPublishFlowData = {
name: string;
requestBody: PublishRequest;
requestBody: app__api__routes__flows__PublishRequest;
};
export type FlowsPublishFlowResponse = (FlowDetail);
@@ -495,7 +674,7 @@ export type FlowsDiscardDraftResponse = (FlowDetail);
export type FlowsRenameFlowData = {
name: string;
requestBody: RenameRequest;
requestBody: app__api__routes__flows__RenameRequest;
};
export type FlowsRenameFlowResponse = (FlowDetail);
@@ -614,6 +793,21 @@ export type LoginRecoverPasswordHtmlContentData = {
export type LoginRecoverPasswordHtmlContentResponse = (string);
export type MessagesReadMessagesResponse = (MessagesPublic);
export type MessagesPublishMessageData = {
name: string;
requestBody: app__api__routes__messages__PublishRequest;
};
export type MessagesPublishMessageResponse = (app__api__routes__messages__MessageValue);
export type MessagesReadMessageHistoryData = {
name: string;
};
export type MessagesReadMessageHistoryResponse = (MessagePoints);
export type OauthRegisterClientData = {
requestBody: OAuthClientRegister;
};