@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,38 +1,204 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EventEmitter } from "events";
|
|
2
|
+
import type { NodeRedRuntimeSettings } from "../../../types";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// RED.log
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
interface NodeRedLog {
|
|
9
|
+
info(msg: any): void;
|
|
10
|
+
warn(msg: any): void;
|
|
11
|
+
error(msg: any, error?: any): void;
|
|
12
|
+
debug(msg: any): void;
|
|
13
|
+
trace(msg: any): void;
|
|
14
|
+
log(msg: { level: number; msg: string }): void;
|
|
15
|
+
metric(): boolean;
|
|
16
|
+
audit(msg: Record<string, any>, req?: any): void;
|
|
17
|
+
addHandler(handler: (msg: any) => void): void;
|
|
18
|
+
removeHandler(handler: (msg: any) => void): void;
|
|
19
|
+
FATAL: 10;
|
|
20
|
+
ERROR: 20;
|
|
21
|
+
WARN: 30;
|
|
22
|
+
INFO: 40;
|
|
23
|
+
DEBUG: 50;
|
|
24
|
+
TRACE: 60;
|
|
25
|
+
AUDIT: 98;
|
|
26
|
+
METRIC: 99;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Node-RED runtime node (the raw node object from RED.nodes.createNode)
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
interface NodeRedNode {
|
|
34
|
+
id: string;
|
|
35
|
+
type: string;
|
|
36
|
+
name?: string;
|
|
37
|
+
z?: string;
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
g?: string;
|
|
41
|
+
wires: string[][];
|
|
42
|
+
credentials: any;
|
|
43
|
+
_node?: any;
|
|
44
|
+
send(msg: any): void;
|
|
45
|
+
receive(msg: any): void;
|
|
46
|
+
status(
|
|
47
|
+
status: string | { fill?: string; shape?: string; text?: string },
|
|
48
|
+
): void;
|
|
49
|
+
updateWires(wires: string[][]): void;
|
|
50
|
+
on(event: string, callback: (...args: any[]) => void): void;
|
|
51
|
+
log(msg: any): void;
|
|
52
|
+
warn(msg: any): void;
|
|
53
|
+
error(msg: any, errorMsg?: any): void;
|
|
54
|
+
context(): NodeRedNodeContext;
|
|
55
|
+
[key: string]: any;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface NodeRedNodeContext extends NodeRedContextStore {
|
|
59
|
+
flow: NodeRedContextStore;
|
|
60
|
+
global: NodeRedContextStore;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// RED.nodes
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
interface NodeRedNodes {
|
|
68
|
+
registerType(type: string, constructor: any, opts?: any): void;
|
|
69
|
+
getNode(id: string): (NodeRedNode & { _node?: any }) | undefined;
|
|
70
|
+
createNode(node: NodeRedNode, config: Record<string, any>): void;
|
|
71
|
+
getCredentials(id: string): Record<string, any> | undefined;
|
|
72
|
+
eachNode(callback: (node: any) => void): void;
|
|
73
|
+
getType(type: string): any;
|
|
74
|
+
getNodeInfo(type: string): any;
|
|
75
|
+
getNodeList(filter?: any): any[];
|
|
76
|
+
getModuleInfo(module: string): any;
|
|
77
|
+
installModule(module: string, version?: string): Promise<any>;
|
|
78
|
+
uninstallModule(module: string): Promise<any>;
|
|
79
|
+
enableNode(id: string): Promise<any>;
|
|
80
|
+
disableNode(id: string): Promise<any>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// RED.util
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
interface NodeRedUtil {
|
|
88
|
+
evaluateNodeProperty(
|
|
89
|
+
value: any,
|
|
90
|
+
type: string,
|
|
91
|
+
node: any,
|
|
92
|
+
msg: Record<string, any> | undefined,
|
|
93
|
+
callback: (err: Error | null, result: any) => void,
|
|
94
|
+
): void;
|
|
95
|
+
generateId(): string;
|
|
96
|
+
cloneMessage<T = any>(msg: T): T;
|
|
97
|
+
ensureString(o: any): string;
|
|
98
|
+
ensureBuffer(o: any): Buffer;
|
|
99
|
+
compareObjects(obj1: any, obj2: any): boolean;
|
|
100
|
+
getMessageProperty(msg: any, expr: string): any;
|
|
101
|
+
setMessageProperty(
|
|
102
|
+
msg: any,
|
|
103
|
+
prop: string,
|
|
104
|
+
value: any,
|
|
105
|
+
createMissing?: boolean,
|
|
106
|
+
): void;
|
|
107
|
+
getObjectProperty(obj: any, expr: string): any;
|
|
108
|
+
setObjectProperty(
|
|
109
|
+
obj: any,
|
|
110
|
+
prop: string,
|
|
111
|
+
value: any,
|
|
112
|
+
createMissing?: boolean,
|
|
113
|
+
): void;
|
|
114
|
+
normalisePropertyExpression(
|
|
115
|
+
str: string,
|
|
116
|
+
msg?: any,
|
|
117
|
+
toString?: boolean,
|
|
118
|
+
): string[];
|
|
119
|
+
normaliseNodeTypeName(name: string): string;
|
|
120
|
+
prepareJSONataExpression(value: string, node: any): any;
|
|
121
|
+
evaluateJSONataExpression(
|
|
122
|
+
expr: any,
|
|
123
|
+
msg: any,
|
|
124
|
+
callback: (err: Error | null, result: any) => void,
|
|
125
|
+
): void;
|
|
126
|
+
parseContextStore(key: string): {
|
|
127
|
+
store: string | undefined;
|
|
128
|
+
key: string;
|
|
32
129
|
};
|
|
33
|
-
|
|
130
|
+
getSetting(node: any, name: string, flow?: any): any;
|
|
131
|
+
encodeObject(obj: any): any;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// RED.hooks
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
interface NodeRedHooks {
|
|
139
|
+
add(hookId: string, callback: (event: any) => void | Promise<void>): void;
|
|
140
|
+
remove(hookId: string): void;
|
|
141
|
+
trigger(
|
|
142
|
+
hookId: string,
|
|
143
|
+
event: any,
|
|
144
|
+
callback?: (err?: Error) => void,
|
|
145
|
+
): void | Promise<void>;
|
|
146
|
+
has(hookId: string): boolean;
|
|
147
|
+
clear(): void;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Express-like HTTP app (httpAdmin / httpNode)
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
type NodeRedRequestHandler = (req: any, res: any, next?: () => void) => void;
|
|
155
|
+
|
|
156
|
+
interface NodeRedExpressApp {
|
|
157
|
+
get(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
158
|
+
post(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
159
|
+
put(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
160
|
+
delete(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
161
|
+
patch(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
162
|
+
options(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
163
|
+
head(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
164
|
+
use(
|
|
165
|
+
path: string | NodeRedRequestHandler,
|
|
166
|
+
...handlers: NodeRedRequestHandler[]
|
|
167
|
+
): void;
|
|
168
|
+
all(path: string, ...handlers: NodeRedRequestHandler[]): void;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// RED (main interface)
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
|
|
175
|
+
interface RED {
|
|
176
|
+
/** Internationalization function */
|
|
177
|
+
_(key: string, substitutions?: Record<string, string>): string;
|
|
178
|
+
/** Logging API */
|
|
179
|
+
log: NodeRedLog;
|
|
180
|
+
/** Node registry and management */
|
|
181
|
+
nodes: NodeRedNodes;
|
|
182
|
+
/** Utility functions */
|
|
183
|
+
util: NodeRedUtil;
|
|
184
|
+
/** Hook system for message lifecycle and module events */
|
|
185
|
+
hooks: NodeRedHooks;
|
|
186
|
+
/** Runtime event emitter */
|
|
187
|
+
events: EventEmitter;
|
|
188
|
+
/** Express app for admin HTTP endpoints */
|
|
189
|
+
httpAdmin: NodeRedExpressApp;
|
|
190
|
+
/** Express app for node HTTP endpoints */
|
|
191
|
+
httpNode: NodeRedExpressApp;
|
|
192
|
+
/** Runtime settings (user-provided settings plus node-registered settings) */
|
|
193
|
+
settings: NodeRedRuntimeSettings & Record<string, any>;
|
|
194
|
+
/** Node-RED version string */
|
|
195
|
+
version(): string;
|
|
34
196
|
}
|
|
35
197
|
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
// Context store (internal)
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
|
|
36
202
|
interface NodeRedContextStore {
|
|
37
203
|
get(
|
|
38
204
|
key: string,
|
|
@@ -51,23 +217,4 @@ interface NodeRedContextStore {
|
|
|
51
217
|
): void;
|
|
52
218
|
}
|
|
53
219
|
|
|
54
|
-
|
|
55
|
-
type: string;
|
|
56
|
-
align?: "left" | "right";
|
|
57
|
-
category?: "config" | string;
|
|
58
|
-
color?: `#${string}`;
|
|
59
|
-
icon?: string;
|
|
60
|
-
labelStyle?: "node_label" | "node_label_italic" | string;
|
|
61
|
-
paletteLabel?: string;
|
|
62
|
-
inputs?: number;
|
|
63
|
-
outputs?: number;
|
|
64
|
-
inputLabels?: string | string[];
|
|
65
|
-
outputLabels?: string | string[];
|
|
66
|
-
configSchema: TObject | null;
|
|
67
|
-
credentialsSchema: TObject | null;
|
|
68
|
-
inputSchema?: TObject | null;
|
|
69
|
-
outputsSchema?: TObject | null;
|
|
70
|
-
settingsSchema?: TObject | null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export { RED, NodeDefinitionApiResponse, NodeRedContextStore };
|
|
220
|
+
export { RED, NodeRedNode, NodeRedNodeContext, NodeRedContextStore };
|
package/src/core/server/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TObject, SchemaOptions } from "@sinclair/typebox";
|
|
2
2
|
|
|
3
3
|
interface NodeSchemaOptions extends SchemaOptions {
|
|
4
|
-
"node-type"?: string;
|
|
4
|
+
"x-nrg-node-type"?: string;
|
|
5
5
|
default?: any;
|
|
6
6
|
format?: string;
|
|
7
7
|
}
|
|
@@ -25,7 +25,7 @@ function getDefaultsFromSchema(
|
|
|
25
25
|
required: false,
|
|
26
26
|
value: property.default ?? undefined,
|
|
27
27
|
// NOTE: I'm using a custom json schema keyword to determine the node type
|
|
28
|
-
type: property["node-type"],
|
|
28
|
+
type: property["x-nrg-node-type"],
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -5,9 +5,13 @@ class NodeRedValidator extends Validator {
|
|
|
5
5
|
constructor(RED: RED) {
|
|
6
6
|
super({
|
|
7
7
|
customKeywords: [
|
|
8
|
-
{ keyword: "skip-validation", schemaType: "boolean", valid: true },
|
|
9
8
|
{
|
|
10
|
-
keyword: "
|
|
9
|
+
keyword: "x-nrg-skip-validation",
|
|
10
|
+
schemaType: "boolean",
|
|
11
|
+
valid: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
keyword: "x-nrg-node-type",
|
|
11
15
|
type: "string",
|
|
12
16
|
validate: (schemaValue: string, dataValue: string) => {
|
|
13
17
|
if (!dataValue) return true;
|
package/src/vite/client/build.ts
CHANGED
|
@@ -39,13 +39,15 @@ async function build(
|
|
|
39
39
|
if (fs.existsSync(physicalEntryPath)) {
|
|
40
40
|
entryPath = physicalEntryPath;
|
|
41
41
|
} else {
|
|
42
|
-
// No physical entry — create a minimal empty file
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
// No physical entry — create a minimal empty file in the cache directory
|
|
43
|
+
// so the file watcher on srcDir is not triggered by the create/delete cycle.
|
|
44
|
+
const cacheDir = path.resolve("node_modules", ".nrg", "client");
|
|
45
|
+
const cachedEntryPath = path.resolve(cacheDir, entry);
|
|
46
|
+
if (!fs.existsSync(cacheDir)) {
|
|
47
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
46
48
|
}
|
|
47
|
-
fs.writeFileSync(
|
|
48
|
-
entryPath =
|
|
49
|
+
fs.writeFileSync(cachedEntryPath, "// auto-generated entry\n");
|
|
50
|
+
entryPath = cachedEntryPath;
|
|
49
51
|
generatedEntry = true;
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -215,7 +217,7 @@ async function build(
|
|
|
215
217
|
throw new BuildError("client", error as Error);
|
|
216
218
|
} finally {
|
|
217
219
|
if (generatedEntry) {
|
|
218
|
-
fs.unlinkSync(
|
|
220
|
+
fs.unlinkSync(entryPath);
|
|
219
221
|
}
|
|
220
222
|
}
|
|
221
223
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type NodeDefinitionApiResponse } from "../../server/types";
|
|
2
|
-
|
|
3
|
-
async function fetchNodeDefinition(
|
|
4
|
-
type: string,
|
|
5
|
-
): Promise<NodeDefinitionApiResponse> {
|
|
6
|
-
const response = await fetch(`/nrg/nodes/${type}`);
|
|
7
|
-
|
|
8
|
-
if (!response.ok) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
`Failed to fetch node definition for "${type}": ${response.status}`,
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return response.json() as Promise<NodeDefinitionApiResponse>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export { fetchNodeDefinition };
|