@bonsae/nrg 0.3.0 → 0.5.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/build/server/index.cjs +10 -17
- package/build/server/resources/nrg-client.js +3387 -3211
- package/build/vite/index.js +8 -6
- package/package.json +2 -1
- package/src/core/client/app.vue +2 -8
- package/src/core/client/components/node-red-config-input.vue +22 -0
- package/src/core/client/components/node-red-editor-input.vue +22 -0
- package/src/core/client/components/node-red-input-label.vue +53 -0
- package/src/core/client/components/node-red-input.vue +22 -0
- package/src/core/client/components/node-red-json-schema-form.vue +89 -44
- package/src/core/client/components/node-red-select-input.vue +22 -0
- package/src/core/client/components/node-red-typed-input.vue +22 -0
- package/src/core/client/globals.d.ts +307 -4
- package/src/core/client/index.ts +2 -0
- package/src/core/server/nodes/node.ts +3 -3
- package/src/core/server/schemas/type.ts +5 -19
- package/src/core/server/schemas/types/index.ts +9 -1
- package/src/core/server/types/index.ts +198 -51
- package/src/core/server/utils.ts +2 -2
- package/src/core/server/validator.ts +6 -2
- package/src/vite/client/build.ts +9 -7
- package/src/vite/client/plugins/node-definitions-inliner.ts +1 -1
- package/src/core/client/api/index.ts +0 -17
- package/src/core/client/virtual.d.ts +0 -5
|
@@ -1,17 +1,320 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Global type declarations for the Node-RED editor environment.
|
|
3
3
|
* These are provided by Node-RED at runtime, not imported.
|
|
4
|
+
*
|
|
5
|
+
* Based on: https://github.com/GogoVega/node-red/blob/33d83d016a0c990c/packages/node_modules/%40node-red/editor-client/types/index.d.ts
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
/// <reference types="jquery" />
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// jQuery Node-RED widget extensions
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
interface JQuery<TElement = HTMLElement> {
|
|
15
|
+
// Node-RED TypedInput widget
|
|
16
|
+
typedInput(options: NodeRED.TypedInputOptions): this;
|
|
17
|
+
typedInput(action: "value"): string;
|
|
18
|
+
typedInput(action: "value", value: string): void;
|
|
19
|
+
typedInput(action: "type"): string;
|
|
20
|
+
typedInput(action: "type", value: string): void;
|
|
21
|
+
typedInput(action: "types", value: any[]): void;
|
|
22
|
+
typedInput(action: "validate"): boolean;
|
|
23
|
+
typedInput(
|
|
24
|
+
action: "validate",
|
|
25
|
+
options: { returnErrorMessage: boolean },
|
|
26
|
+
): string | boolean;
|
|
27
|
+
typedInput(action: "disable", value?: boolean): void;
|
|
28
|
+
typedInput(action: "enable"): void;
|
|
29
|
+
typedInput(action: "focus"): void;
|
|
30
|
+
typedInput(action: "hide"): void;
|
|
31
|
+
typedInput(action: "show"): void;
|
|
32
|
+
typedInput(action: "width", value: string | number): void;
|
|
33
|
+
|
|
34
|
+
// Node-RED i18n
|
|
35
|
+
i18n(): this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Node-RED editor types
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
declare namespace NodeRED {
|
|
43
|
+
type UID = string;
|
|
44
|
+
|
|
45
|
+
// -- Nodes --
|
|
46
|
+
|
|
47
|
+
interface BaseNode {
|
|
48
|
+
id: UID;
|
|
49
|
+
type: string;
|
|
50
|
+
changed: boolean;
|
|
51
|
+
z?: string;
|
|
52
|
+
_def: any;
|
|
53
|
+
[key: string]: any;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface Node extends BaseNode {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
w: number;
|
|
60
|
+
h: number;
|
|
61
|
+
name: string;
|
|
62
|
+
wires: UID[][];
|
|
63
|
+
inputs: number;
|
|
64
|
+
outputs: number;
|
|
65
|
+
g?: string;
|
|
66
|
+
_: (key: string) => string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ConfigNode extends BaseNode {
|
|
70
|
+
name: string;
|
|
71
|
+
credentials?: Record<string, any>;
|
|
72
|
+
users: BaseNode[];
|
|
73
|
+
_def: {
|
|
74
|
+
category: "config";
|
|
75
|
+
[key: string]: any;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface Link {
|
|
80
|
+
source: BaseNode;
|
|
81
|
+
target: BaseNode;
|
|
82
|
+
sourcePort: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface Workspace {
|
|
86
|
+
id: UID;
|
|
87
|
+
type: "tab";
|
|
88
|
+
label: string;
|
|
89
|
+
disabled: boolean;
|
|
90
|
+
info: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// -- Editor --
|
|
94
|
+
|
|
95
|
+
interface EditorOptions {
|
|
96
|
+
id: string;
|
|
97
|
+
stateId?: string;
|
|
98
|
+
mode?: string;
|
|
99
|
+
value?: string;
|
|
100
|
+
focus?: boolean;
|
|
101
|
+
globals?: Record<string, boolean>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface TrayButton {
|
|
105
|
+
id?: string;
|
|
106
|
+
class?: string;
|
|
107
|
+
click?: (event: JQuery.ClickEvent) => void;
|
|
108
|
+
text?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
interface TrayOptions {
|
|
112
|
+
title?: string;
|
|
113
|
+
buttons?: TrayButton[];
|
|
114
|
+
focusElement?: boolean;
|
|
115
|
+
maximized?: boolean;
|
|
116
|
+
width?: "inherit" | number | string;
|
|
117
|
+
overlay?: boolean;
|
|
118
|
+
open?: (tray: JQuery, done?: () => void) => void;
|
|
119
|
+
close?: () => void;
|
|
120
|
+
resize?: (options: { width: number; height?: number }) => void;
|
|
121
|
+
show?: () => void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// -- Popover --
|
|
125
|
+
|
|
126
|
+
interface PopoverOptions {
|
|
127
|
+
target: JQuery;
|
|
128
|
+
direction?: string;
|
|
129
|
+
trigger?: "hover" | "click" | "modal";
|
|
130
|
+
content: string | JQuery | (() => string | JQuery);
|
|
131
|
+
delay?: { show: number; hide: number };
|
|
132
|
+
autoClose?: number;
|
|
133
|
+
width?: number | string;
|
|
134
|
+
maxWidth?: number | string;
|
|
135
|
+
tooltip?: boolean;
|
|
136
|
+
interactive?: boolean;
|
|
137
|
+
class?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface PopoverInstance {
|
|
141
|
+
readonly element: JQuery | null;
|
|
142
|
+
close(instant?: boolean): PopoverInstance;
|
|
143
|
+
open(instant?: boolean): PopoverInstance;
|
|
144
|
+
setContent(content: PopoverOptions["content"]): PopoverInstance;
|
|
145
|
+
move(options: Partial<PopoverOptions>): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
interface TooltipInstance extends PopoverInstance {
|
|
149
|
+
delete(): void;
|
|
150
|
+
setAction(action: string): void;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// -- Notifications --
|
|
154
|
+
|
|
155
|
+
interface NotificationOptions {
|
|
156
|
+
type?: "warning" | "compact" | "success" | "error";
|
|
157
|
+
fixed?: boolean;
|
|
158
|
+
modal?: boolean;
|
|
159
|
+
timeout?: number;
|
|
160
|
+
buttons?: Array<{
|
|
161
|
+
text: string;
|
|
162
|
+
class?: string;
|
|
163
|
+
click?: (event: JQuery.ClickEvent) => void;
|
|
164
|
+
}>;
|
|
165
|
+
id?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface NotificationElement {
|
|
169
|
+
update(msg: string | JQuery, options?: NotificationOptions): void;
|
|
170
|
+
close(): void;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// -- TypedInput --
|
|
174
|
+
|
|
175
|
+
type DefaultTypedInputType =
|
|
176
|
+
(typeof import("../constants").TYPED_INPUT_TYPES)[number];
|
|
177
|
+
|
|
178
|
+
interface TypedInputTypeDefinition {
|
|
179
|
+
value: string;
|
|
180
|
+
label?: string;
|
|
181
|
+
icon?: string;
|
|
182
|
+
hasValue?: boolean;
|
|
183
|
+
multiple?: boolean;
|
|
184
|
+
options?: string[] | Array<{ value: string; label: string }>;
|
|
185
|
+
validate?: ((value: string) => boolean) | RegExp;
|
|
186
|
+
valueLabel?: (container: JQuery, value: string) => void;
|
|
187
|
+
autoComplete?: (
|
|
188
|
+
value: string,
|
|
189
|
+
done: (result?: Array<{ value: string; label: string | JQuery }>) => void,
|
|
190
|
+
) => void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
interface TypedInputOptions {
|
|
194
|
+
default?: DefaultTypedInputType | string;
|
|
195
|
+
types: Array<DefaultTypedInputType | TypedInputTypeDefinition>;
|
|
196
|
+
typeField?: JQuery.Selector | JQuery;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// RED global object
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
8
203
|
|
|
9
|
-
// Node-RED editor API — injected by Node-RED editor
|
|
10
204
|
declare const RED: {
|
|
205
|
+
/** Internationalization / translation function */
|
|
206
|
+
_: (key: string, substitutions?: Record<string, string>) => string;
|
|
207
|
+
|
|
208
|
+
/** Node management */
|
|
11
209
|
nodes: {
|
|
12
210
|
registerType(type: string, definition: any): void;
|
|
13
|
-
node(id:
|
|
211
|
+
node(id: NodeRED.UID): NodeRED.BaseNode | null;
|
|
14
212
|
dirty(): boolean;
|
|
213
|
+
dirty(dirty: boolean): void;
|
|
214
|
+
eachNode(callback: (node: NodeRED.Node) => void | false): void;
|
|
215
|
+
eachConfig(callback: (node: NodeRED.ConfigNode) => void | false): void;
|
|
216
|
+
filterNodes(filter: { z?: NodeRED.UID; type?: string }): NodeRED.BaseNode[];
|
|
217
|
+
filterLinks(filter: {
|
|
218
|
+
source?: NodeRED.BaseNode;
|
|
219
|
+
target?: NodeRED.BaseNode;
|
|
220
|
+
}): NodeRED.Link[];
|
|
221
|
+
getType(type: string): any;
|
|
222
|
+
id(): NodeRED.UID;
|
|
223
|
+
add(node: any): NodeRED.BaseNode;
|
|
224
|
+
remove(id: NodeRED.UID): {
|
|
225
|
+
links: NodeRED.Link[];
|
|
226
|
+
nodes: NodeRED.BaseNode[];
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/** Code editor (ACE/Monaco) */
|
|
231
|
+
editor: {
|
|
232
|
+
createEditor(options: NodeRED.EditorOptions): any;
|
|
233
|
+
edit(node: NodeRED.Node, defaultTab?: any): void;
|
|
234
|
+
editConfig(
|
|
235
|
+
name: string,
|
|
236
|
+
type: string,
|
|
237
|
+
id: string,
|
|
238
|
+
prefix?: string,
|
|
239
|
+
editContext?: NodeRED.Node,
|
|
240
|
+
): void;
|
|
241
|
+
prepareConfigNodeSelect(
|
|
242
|
+
node: NodeRED.BaseNode,
|
|
243
|
+
property: string,
|
|
244
|
+
type: string,
|
|
245
|
+
prefix?: string,
|
|
246
|
+
filter?: (configNode: NodeRED.ConfigNode) => boolean,
|
|
247
|
+
): void;
|
|
248
|
+
validateNode(node: NodeRED.BaseNode): boolean;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/** Side panel tray */
|
|
252
|
+
tray: {
|
|
253
|
+
show(options: NodeRED.TrayOptions): void;
|
|
254
|
+
close(): void;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/** Popover / tooltip */
|
|
258
|
+
popover: {
|
|
259
|
+
create(options: NodeRED.PopoverOptions): NodeRED.PopoverInstance;
|
|
260
|
+
tooltip(
|
|
261
|
+
target: JQuery,
|
|
262
|
+
text: string,
|
|
263
|
+
direction?: string,
|
|
264
|
+
): NodeRED.TooltipInstance;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
/** Toast notifications */
|
|
268
|
+
notify(
|
|
269
|
+
message: string | JQuery,
|
|
270
|
+
options?: NodeRED.NotificationOptions,
|
|
271
|
+
): NodeRED.NotificationElement;
|
|
272
|
+
|
|
273
|
+
/** Event system */
|
|
274
|
+
events: {
|
|
275
|
+
on(event: string, listener: (...args: any[]) => void): void;
|
|
276
|
+
off(event: string, listener: (...args: any[]) => void): void;
|
|
277
|
+
emit(event: string, ...args: any[]): void;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
/** Undo/redo */
|
|
281
|
+
history: {
|
|
282
|
+
push(event: any): void;
|
|
283
|
+
pop(): any;
|
|
284
|
+
peek(): any;
|
|
285
|
+
list(): any[];
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/** Keyboard shortcuts */
|
|
289
|
+
keyboard: {
|
|
290
|
+
add(scope: string, key: string, callback: () => void): void;
|
|
291
|
+
remove(key: string): void;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
/** Runtime communication (WebSocket) */
|
|
295
|
+
comms: {
|
|
296
|
+
subscribe(topic: string, callback: (topic: string, msg: any) => void): void;
|
|
297
|
+
unsubscribe(
|
|
298
|
+
topic: string,
|
|
299
|
+
callback: (topic: string, msg: any) => void,
|
|
300
|
+
): void;
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
/** Editor settings */
|
|
304
|
+
settings: {
|
|
305
|
+
get(key: string): any;
|
|
306
|
+
set(key: string, value: any): any;
|
|
307
|
+
remove(key: string): any;
|
|
308
|
+
[key: string]: any;
|
|
15
309
|
};
|
|
310
|
+
|
|
311
|
+
/** Canvas view */
|
|
312
|
+
view: {
|
|
313
|
+
focus(): void;
|
|
314
|
+
selection(): { nodes?: NodeRED.Node[] };
|
|
315
|
+
redraw(updateActive?: boolean): void;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/** Catch-all for untyped properties */
|
|
16
319
|
[key: string]: any;
|
|
17
320
|
};
|
package/src/core/client/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import NodeRedTypedInput from "./components/node-red-typed-input.vue";
|
|
|
8
8
|
import NodeRedConfigInput from "./components/node-red-config-input.vue";
|
|
9
9
|
import NodeRedSelectInput from "./components/node-red-select-input.vue";
|
|
10
10
|
import NodeRedEditorInput from "./components/node-red-editor-input.vue";
|
|
11
|
+
import NodeRedInputLabel from "./components/node-red-input-label.vue";
|
|
11
12
|
import NodeRedJsonSchemaForm from "./components/node-red-json-schema-form.vue";
|
|
12
13
|
|
|
13
14
|
const _schemas: Record<string, any> = {};
|
|
@@ -163,6 +164,7 @@ function createNodeRedVueApp(
|
|
|
163
164
|
features,
|
|
164
165
|
});
|
|
165
166
|
|
|
167
|
+
app.component("NodeRedInputLabel", NodeRedInputLabel);
|
|
166
168
|
app.component("NodeRedInput", NodeRedInput);
|
|
167
169
|
app.component("NodeRedTypedInput", NodeRedTypedInput);
|
|
168
170
|
app.component("NodeRedConfigInput", NodeRedConfigInput);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Schema } from "../schemas/types";
|
|
2
|
-
import { type RED } from "../../server/types";
|
|
2
|
+
import { type RED, type NodeRedNode } from "../../server/types";
|
|
3
3
|
import type {
|
|
4
4
|
ConfigNodeContext,
|
|
5
5
|
IONodeContext,
|
|
@@ -80,7 +80,7 @@ abstract class Node<TConfig = any, TCredentials = any, TSettings = any> {
|
|
|
80
80
|
RED.log.info("Settings are valid");
|
|
81
81
|
}
|
|
82
82
|
protected readonly RED: RED;
|
|
83
|
-
protected readonly node:
|
|
83
|
+
protected readonly node: NodeRedNode;
|
|
84
84
|
protected readonly context!: ConfigNodeContext | IONodeContext;
|
|
85
85
|
public readonly config!: NodeConfig<TConfig>;
|
|
86
86
|
|
|
@@ -89,7 +89,7 @@ abstract class Node<TConfig = any, TCredentials = any, TSettings = any> {
|
|
|
89
89
|
|
|
90
90
|
constructor(
|
|
91
91
|
RED: RED,
|
|
92
|
-
node:
|
|
92
|
+
node: NodeRedNode,
|
|
93
93
|
config: NodeConfig<TConfig>,
|
|
94
94
|
credentials: NodeCredentials<TCredentials>,
|
|
95
95
|
) {
|
|
@@ -15,40 +15,26 @@ function NodeRef<T extends new (...args: any[]) => any>(
|
|
|
15
15
|
options?: SchemaOptions,
|
|
16
16
|
): TNodeRef<InstanceType<T>> {
|
|
17
17
|
return {
|
|
18
|
-
...
|
|
18
|
+
...BaseType.String({
|
|
19
19
|
description:
|
|
20
20
|
options?.description || `Reference to ${(nodeClass as any).type}`,
|
|
21
21
|
format: "node-id",
|
|
22
22
|
}),
|
|
23
|
-
"node-type": (nodeClass as any).type,
|
|
23
|
+
"x-nrg-node-type": (nodeClass as any).type,
|
|
24
24
|
...options,
|
|
25
25
|
[Kind]: "NodeRef",
|
|
26
26
|
} as unknown as TNodeRef<InstanceType<T>>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function TypedInput(
|
|
30
|
-
options?: SchemaOptions & { types?: string[] },
|
|
31
|
-
): TTypedInput {
|
|
32
|
-
const { types, ...rest } = options ?? {};
|
|
29
|
+
function TypedInput(options?: SchemaOptions): TTypedInput {
|
|
33
30
|
return {
|
|
34
31
|
...TypedInputSchema,
|
|
35
|
-
...
|
|
36
|
-
...(types ? { "x-typed-types": types } : {}),
|
|
32
|
+
...options,
|
|
37
33
|
[Kind]: "TypedInput",
|
|
38
34
|
} as unknown as TTypedInput;
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
const _OriginalString = BaseType.String.bind(BaseType);
|
|
42
|
-
function StringWithLang(options?: SchemaOptions & { lang?: string }) {
|
|
43
|
-
const { lang, ...rest } = options ?? {};
|
|
44
|
-
return _OriginalString({
|
|
45
|
-
...rest,
|
|
46
|
-
...(lang ? { "x-editor-language": lang } : {}),
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
37
|
const SchemaType = Object.assign({}, BaseType, {
|
|
51
|
-
String: StringWithLang,
|
|
52
38
|
NodeRef,
|
|
53
39
|
TypedInput,
|
|
54
40
|
});
|
|
@@ -62,7 +48,7 @@ function markNonValidatable<T extends TSchema>(schema: T): T {
|
|
|
62
48
|
|
|
63
49
|
// NOTE: if the type is non serializable, like Functions or Constructor, we must skip validation and avoid applying defaults
|
|
64
50
|
if (hasInvalidType) {
|
|
65
|
-
(schema as any)["skip-validation"] = true;
|
|
51
|
+
(schema as any)["x-nrg-skip-validation"] = true;
|
|
66
52
|
|
|
67
53
|
if ((schema as any).default !== undefined) {
|
|
68
54
|
(schema as any)._default = (schema as any).default;
|
|
@@ -11,7 +11,7 @@ interface TNodeRef<T = any> extends TSchema {
|
|
|
11
11
|
[Kind]: "NodeRef";
|
|
12
12
|
static: T;
|
|
13
13
|
type: "string";
|
|
14
|
-
"node-type"?: string;
|
|
14
|
+
"x-nrg-node-type"?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
type ResolveNodeRefs<T> =
|
|
@@ -37,9 +37,17 @@ interface TTypedInput extends TSchema {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
interface NrgFormOptions {
|
|
41
|
+
icon?: string;
|
|
42
|
+
typedInputTypes?: string[];
|
|
43
|
+
editorLanguage?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
declare module "@sinclair/typebox" {
|
|
41
47
|
interface SchemaOptions {
|
|
42
48
|
exportable?: boolean;
|
|
49
|
+
"x-nrg-node-type"?: string;
|
|
50
|
+
"x-nrg-form"?: NrgFormOptions;
|
|
43
51
|
}
|
|
44
52
|
}
|
|
45
53
|
|