@bonsae/nrg 0.6.0 → 0.6.2
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 +5 -5
- package/package.json +14 -75
- package/{build/server → server}/index.cjs +1 -1
- package/{src/core/client → shims}/components.d.ts +2 -0
- package/{src/tsconfig → tsconfig}/client.json +3 -3
- package/types/client.d.ts +37 -0
- package/types/index.d.ts +211 -0
- package/types/server.d.ts +2293 -0
- package/types/vite.d.ts +12 -0
- package/{build/vite → vite}/index.js +95 -0
- package/build/vite/utils.js +0 -56
- package/src/core/client/app.vue +0 -185
- package/src/core/client/components/node-red-config-input.vue +0 -79
- package/src/core/client/components/node-red-editor-input.vue +0 -307
- package/src/core/client/components/node-red-input-label.vue +0 -53
- package/src/core/client/components/node-red-input.vue +0 -93
- package/src/core/client/components/node-red-json-schema-form.vue +0 -444
- package/src/core/client/components/node-red-select-input.vue +0 -108
- package/src/core/client/components/node-red-toggle.vue +0 -115
- package/src/core/client/components/node-red-typed-input.vue +0 -158
- package/src/core/client/index.ts +0 -500
- package/src/core/client/tsconfig.json +0 -18
- package/src/core/constants.ts +0 -18
- package/src/core/errors.ts +0 -9
- package/src/core/server/api/index.ts +0 -1
- package/src/core/server/api/serve-nrg-resources.ts +0 -54
- package/src/core/server/index.ts +0 -190
- package/src/core/server/nodes/config-node.ts +0 -67
- package/src/core/server/nodes/factories.ts +0 -133
- package/src/core/server/nodes/index.ts +0 -5
- package/src/core/server/nodes/io-node.ts +0 -179
- package/src/core/server/nodes/node.ts +0 -259
- package/src/core/server/nodes/types/config-node.ts +0 -28
- package/src/core/server/nodes/types/factories.ts +0 -115
- package/src/core/server/nodes/types/index.ts +0 -4
- package/src/core/server/nodes/types/io-node.ts +0 -40
- package/src/core/server/nodes/types/node.ts +0 -41
- package/src/core/server/nodes/utils.ts +0 -106
- package/src/core/server/schemas/base.ts +0 -66
- package/src/core/server/schemas/index.ts +0 -3
- package/src/core/server/schemas/type.ts +0 -95
- package/src/core/server/schemas/types/index.ts +0 -82
- package/src/core/server/tsconfig.json +0 -17
- package/src/core/server/types/index.ts +0 -220
- package/src/core/server/utils.ts +0 -56
- package/src/core/server/validator.ts +0 -36
- package/src/core/validator.ts +0 -222
- package/src/index.ts +0 -2
- package/src/types.ts +0 -189
- package/src/utils.ts +0 -20
- package/src/vite/async-utils.ts +0 -61
- package/src/vite/client/build.ts +0 -227
- package/src/vite/client/index.ts +0 -1
- package/src/vite/client/plugins/html-generator.ts +0 -75
- package/src/vite/client/plugins/index.ts +0 -5
- package/src/vite/client/plugins/locales-generator.ts +0 -126
- package/src/vite/client/plugins/minifier.ts +0 -23
- package/src/vite/client/plugins/node-definitions-inliner.ts +0 -275
- package/src/vite/client/plugins/static-copy.ts +0 -43
- package/src/vite/defaults.ts +0 -77
- package/src/vite/errors.ts +0 -37
- package/src/vite/index.ts +0 -2
- package/src/vite/logger.ts +0 -94
- package/src/vite/node-red-launcher.ts +0 -344
- package/src/vite/plugin.ts +0 -61
- package/src/vite/plugins/build.ts +0 -85
- package/src/vite/plugins/index.ts +0 -2
- package/src/vite/plugins/server.ts +0 -267
- package/src/vite/server/build.ts +0 -124
- package/src/vite/server/index.ts +0 -1
- package/src/vite/server/plugins/index.ts +0 -3
- package/src/vite/server/plugins/output-wrapper.ts +0 -109
- package/src/vite/server/plugins/package-json-generator.ts +0 -203
- package/src/vite/server/plugins/type-generator.ts +0 -285
- package/src/vite/types.ts +0 -174
- package/src/vite/utils.ts +0 -72
- /package/{build/index.js → index.js} +0 -0
- /package/{build/server → server}/resources/nrg-client.js +0 -0
- /package/{build/server → server}/resources/vue.esm-browser.js +0 -0
- /package/{build/server → server}/resources/vue.esm-browser.prod.js +0 -0
- /package/{src/core/client → shims}/globals.d.ts +0 -0
- /package/{src/core/client → shims}/shims-vue.d.ts +0 -0
- /package/{src/tsconfig → tsconfig}/base.json +0 -0
- /package/{src/tsconfig → tsconfig}/server.json +0 -0
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import type { RED } from "../types";
|
|
4
|
-
|
|
5
|
-
const MIME: Record<string, string> = {
|
|
6
|
-
".js": "application/javascript",
|
|
7
|
-
".mjs": "application/javascript",
|
|
8
|
-
".css": "text/css",
|
|
9
|
-
".json": "application/json",
|
|
10
|
-
".map": "application/json",
|
|
11
|
-
".png": "image/png",
|
|
12
|
-
".svg": "image/svg+xml",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
let _registered = false;
|
|
16
|
-
|
|
17
|
-
function serveNrgResources(RED: RED): void {
|
|
18
|
-
if (_registered) return;
|
|
19
|
-
_registered = true;
|
|
20
|
-
|
|
21
|
-
const clientDir = path.resolve(__dirname, "./resources");
|
|
22
|
-
if (!fs.existsSync(clientDir)) return;
|
|
23
|
-
|
|
24
|
-
const httpAdmin = (RED as any).httpAdmin;
|
|
25
|
-
if (!httpAdmin) return;
|
|
26
|
-
|
|
27
|
-
// /nrg/assets/ is not handled by Node-RED's editorApp, so our handler
|
|
28
|
-
// appended via use() is reached normally without any stack manipulation.
|
|
29
|
-
httpAdmin.use(function (req: any, res: any, next: any) {
|
|
30
|
-
const prefix = "/nrg/assets/";
|
|
31
|
-
if (!(req.path as string).startsWith(prefix)) return next();
|
|
32
|
-
let reqPath = (req.path as string).slice(prefix.length);
|
|
33
|
-
// Serve the Vue dev build in development for devtools support
|
|
34
|
-
if (
|
|
35
|
-
reqPath === "vue.esm-browser.prod.js" &&
|
|
36
|
-
process.env.NODE_ENV !== "production"
|
|
37
|
-
) {
|
|
38
|
-
const devPath = path.resolve(clientDir, "vue.esm-browser.js");
|
|
39
|
-
if (fs.existsSync(devPath)) {
|
|
40
|
-
reqPath = "vue.esm-browser.js";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const filePath = path.resolve(clientDir, reqPath);
|
|
44
|
-
const rel = path.relative(clientDir, filePath);
|
|
45
|
-
if (rel.startsWith("..") || path.isAbsolute(rel)) return next();
|
|
46
|
-
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile())
|
|
47
|
-
return next();
|
|
48
|
-
const ext = path.extname(filePath);
|
|
49
|
-
res.setHeader("Content-Type", MIME[ext] ?? "application/octet-stream");
|
|
50
|
-
fs.createReadStream(filePath).pipe(res);
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export { serveNrgResources };
|
package/src/core/server/index.ts
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { getCredentialsFromSchema } from "./utils";
|
|
2
|
-
import { Node } from "./nodes";
|
|
3
|
-
import { type RED } from "./types";
|
|
4
|
-
import { initValidator } from "./validator";
|
|
5
|
-
import { serveNrgResources } from "./api";
|
|
6
|
-
import { NrgError } from "../errors";
|
|
7
|
-
|
|
8
|
-
type AnyNodeClass = (abstract new (...args: any[]) => Node) &
|
|
9
|
-
Partial<typeof Node>;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Registers a custom node with Node-RED.
|
|
13
|
-
*
|
|
14
|
-
* @param RED - The Node-RED runtime API object
|
|
15
|
-
* @param NodeClass - A node class extending Node, IONode, or ConfigNode
|
|
16
|
-
* @throws If NodeClass does not extend Node
|
|
17
|
-
* @throws If NodeClass.type is not defined
|
|
18
|
-
*/
|
|
19
|
-
async function registerType(RED: RED, NodeClass: AnyNodeClass) {
|
|
20
|
-
const NC = NodeClass as any;
|
|
21
|
-
RED.log.debug(`Registering Type: ${NC.type}`);
|
|
22
|
-
if (!(NC.prototype instanceof Node)) {
|
|
23
|
-
throw new NrgError(`${NC.name} must extend IONode or ConfigNode classes`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!NC.type) {
|
|
27
|
-
throw new NrgError("type must be provided when registering the node");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (NC.color && !/^#[0-9A-Fa-f]{6}$/.test(NC.color)) {
|
|
31
|
-
throw new NrgError(
|
|
32
|
-
`Invalid color for ${NodeClass.type}: ${NC.color} color must be in hex format`,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
NC.inputs !== undefined &&
|
|
38
|
-
(!Number.isInteger(NC.inputs) || (NC.inputs !== 0 && NC.inputs !== 1))
|
|
39
|
-
) {
|
|
40
|
-
throw new NrgError(
|
|
41
|
-
`Invalid number of inputs for ${NodeClass.type}: inputs must be 0 or 1`,
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
NC.outputs !== undefined &&
|
|
47
|
-
(!Number.isInteger(NC.outputs) || NC.outputs < 0)
|
|
48
|
-
) {
|
|
49
|
-
throw new NrgError(
|
|
50
|
-
`Invalid number of outputs for ${NodeClass.type}: outputs must be a positive integer`,
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
RED.nodes.registerType(
|
|
55
|
-
NC.type,
|
|
56
|
-
function (this: any, config: any) {
|
|
57
|
-
RED.nodes.createNode(this, config);
|
|
58
|
-
const node = new NC(RED, this, config, this.credentials);
|
|
59
|
-
// NOTE: save node instance inside node-red's node so that the proxy can resolve it lazily.
|
|
60
|
-
// Non-writable to prevent accidental clobbering by other code in the process.
|
|
61
|
-
Object.defineProperty(this, "_node", {
|
|
62
|
-
value: node,
|
|
63
|
-
writable: false,
|
|
64
|
-
configurable: false,
|
|
65
|
-
enumerable: false,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// NOTE: created promise must be here because we only want it to start after the whole object creation chain has been completed: child -> IONode -> Node -> IONode -> child -> done
|
|
69
|
-
const createdPromise = Promise.resolve(node.created?.()).catch(
|
|
70
|
-
(error: any) => {
|
|
71
|
-
this.error("Error during created hook: " + error.message);
|
|
72
|
-
throw error;
|
|
73
|
-
},
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
this.on(
|
|
77
|
-
"input",
|
|
78
|
-
async (
|
|
79
|
-
msg: unknown,
|
|
80
|
-
send: (msg: unknown) => void,
|
|
81
|
-
done: (err?: Error) => void,
|
|
82
|
-
) => {
|
|
83
|
-
try {
|
|
84
|
-
await createdPromise;
|
|
85
|
-
} catch {
|
|
86
|
-
done(new Error("Node failed to initialize"));
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
this.log("Calling input");
|
|
92
|
-
await Promise.resolve(node._input(msg, send));
|
|
93
|
-
done();
|
|
94
|
-
this.log("Input processed");
|
|
95
|
-
} catch (error) {
|
|
96
|
-
if (error instanceof Error) {
|
|
97
|
-
this.error("Error while processing input: " + error.message, msg);
|
|
98
|
-
done(error);
|
|
99
|
-
} else {
|
|
100
|
-
this.error("Unknown error occurred during input handling", msg);
|
|
101
|
-
done(new Error("Unknown error during input handling"));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
this.on(
|
|
108
|
-
"close",
|
|
109
|
-
async (removed: boolean, done: (err?: Error) => void) => {
|
|
110
|
-
try {
|
|
111
|
-
this.log("Calling closed");
|
|
112
|
-
await Promise.resolve(node._closed(removed));
|
|
113
|
-
this.log("Node was closed");
|
|
114
|
-
done();
|
|
115
|
-
} catch (error) {
|
|
116
|
-
if (error instanceof Error) {
|
|
117
|
-
this.error("Error while closing node: " + error.message);
|
|
118
|
-
done(error);
|
|
119
|
-
} else {
|
|
120
|
-
this.error("Unknown error occurred while closing node");
|
|
121
|
-
done(new Error("Unknown error occurred while closing node"));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
);
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
credentials: NC.credentialsSchema
|
|
129
|
-
? getCredentialsFromSchema(NC.credentialsSchema)
|
|
130
|
-
: {},
|
|
131
|
-
settings: NC._settings?.(),
|
|
132
|
-
},
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
await Promise.resolve(NC._registered?.(RED));
|
|
136
|
-
|
|
137
|
-
RED.log.debug(`Type registered: ${NC.type}`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
type RegistrationFunction = ((RED: RED) => Promise<void>) & {
|
|
141
|
-
nodes: AnyNodeClass[];
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Registers multiple node classes with Node-RED.
|
|
146
|
-
*
|
|
147
|
-
* Returns a Node-RED package function that Node-RED calls with the RED
|
|
148
|
-
* runtime object when loading the package.
|
|
149
|
-
*
|
|
150
|
-
* @param nodes - Array of node classes to register
|
|
151
|
-
*/
|
|
152
|
-
function registerTypes(nodes: AnyNodeClass[]): RegistrationFunction {
|
|
153
|
-
const fn = async function (RED: RED) {
|
|
154
|
-
initValidator(RED);
|
|
155
|
-
serveNrgResources(RED);
|
|
156
|
-
try {
|
|
157
|
-
RED.log.info("Registering node types in series");
|
|
158
|
-
for (const NodeClass of nodes) {
|
|
159
|
-
await registerType(RED, NodeClass);
|
|
160
|
-
}
|
|
161
|
-
RED.log.info("All node types registered in series");
|
|
162
|
-
} catch (error) {
|
|
163
|
-
RED.log.error("Error registering node types:", error);
|
|
164
|
-
throw error;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
(fn as RegistrationFunction).nodes = nodes;
|
|
168
|
-
return fn as RegistrationFunction;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
interface ModuleDefinition {
|
|
172
|
-
nodes: AnyNodeClass[];
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function defineModule(definition: ModuleDefinition): ModuleDefinition {
|
|
176
|
-
return definition;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export { registerType, registerTypes, defineModule };
|
|
180
|
-
export {
|
|
181
|
-
Node,
|
|
182
|
-
IONode,
|
|
183
|
-
ConfigNode,
|
|
184
|
-
defineIONode,
|
|
185
|
-
defineConfigNode,
|
|
186
|
-
} from "./nodes";
|
|
187
|
-
export { NrgError } from "../errors";
|
|
188
|
-
export type { RED } from "./types";
|
|
189
|
-
export { SchemaType, defineSchema } from "./schemas";
|
|
190
|
-
export type { Schema, Infer } from "./schemas/types";
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { RED } from "../../server/types";
|
|
2
|
-
import { Node } from "./node";
|
|
3
|
-
import type {
|
|
4
|
-
ConfigNodeConfig,
|
|
5
|
-
ConfigNodeContext,
|
|
6
|
-
ConfigNodeCredentials,
|
|
7
|
-
} from "./types";
|
|
8
|
-
import { setupContext } from "./utils";
|
|
9
|
-
|
|
10
|
-
abstract class ConfigNode<
|
|
11
|
-
TConfig = any,
|
|
12
|
-
TCredentials = any,
|
|
13
|
-
TSettings = any,
|
|
14
|
-
> extends Node<TConfig, TCredentials, TSettings> {
|
|
15
|
-
public static override readonly category: string = "config";
|
|
16
|
-
declare public readonly config: ConfigNodeConfig<TConfig>;
|
|
17
|
-
|
|
18
|
-
protected override readonly context: ConfigNodeContext;
|
|
19
|
-
|
|
20
|
-
// NOTE: used by the registered function. Had to be a different one to avoid calling the parent's input again
|
|
21
|
-
/** @internal */
|
|
22
|
-
public static override _registered(RED: RED): void | Promise<void> {
|
|
23
|
-
this.validateSettings(RED);
|
|
24
|
-
return this.registered?.(RED);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
constructor(
|
|
28
|
-
RED: RED,
|
|
29
|
-
node: any,
|
|
30
|
-
config: ConfigNodeConfig<TConfig>,
|
|
31
|
-
credentials: ConfigNodeCredentials<TCredentials>,
|
|
32
|
-
) {
|
|
33
|
-
super(RED, node, config, credentials);
|
|
34
|
-
|
|
35
|
-
const context = node.context();
|
|
36
|
-
const fn = (scope: "node" | "global", store?: string) => {
|
|
37
|
-
const target = scope === "global" ? context.global : context;
|
|
38
|
-
return setupContext(target, store);
|
|
39
|
-
};
|
|
40
|
-
fn.node = setupContext(context);
|
|
41
|
-
fn.global = setupContext(context.global);
|
|
42
|
-
|
|
43
|
-
this.context = fn as any;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
get userIds(): string[] {
|
|
47
|
-
return this.config._users;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
get users(): Node[] {
|
|
51
|
-
return this.userIds
|
|
52
|
-
.map((id) => this.RED.nodes.getNode(id)?._node)
|
|
53
|
-
.filter((node): node is Node => node != null);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
getUser<T extends Node = Node>(index: number): T | undefined {
|
|
57
|
-
const id = this.userIds[index];
|
|
58
|
-
if (!id) return undefined;
|
|
59
|
-
return this.RED.nodes.getNode(id)?._node as T | undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
override get credentials(): ConfigNodeCredentials<TCredentials> | undefined {
|
|
63
|
-
return this.node.credentials;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export { ConfigNode };
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { type TSchema } from "@sinclair/typebox";
|
|
2
|
-
import type { Schema } from "../schemas/types";
|
|
3
|
-
import type { RED } from "../types";
|
|
4
|
-
import type {
|
|
5
|
-
InferOr,
|
|
6
|
-
InferOutputs,
|
|
7
|
-
IONodeDefinition,
|
|
8
|
-
ConfigNodeDefinition,
|
|
9
|
-
HexColor,
|
|
10
|
-
} from "./types";
|
|
11
|
-
import { IONode } from "./io-node";
|
|
12
|
-
import { ConfigNode } from "./config-node";
|
|
13
|
-
|
|
14
|
-
function defineIONode<
|
|
15
|
-
TConfigSchema extends TSchema | undefined = undefined,
|
|
16
|
-
TCredsSchema extends TSchema | undefined = undefined,
|
|
17
|
-
TSettingsSchema extends TSchema | undefined = undefined,
|
|
18
|
-
TInputSchema extends TSchema | undefined = undefined,
|
|
19
|
-
TOutputsSchema extends TSchema | readonly TSchema[] | undefined = undefined,
|
|
20
|
-
>(
|
|
21
|
-
def: IONodeDefinition<
|
|
22
|
-
TConfigSchema,
|
|
23
|
-
TCredsSchema,
|
|
24
|
-
TSettingsSchema,
|
|
25
|
-
TInputSchema,
|
|
26
|
-
TOutputsSchema
|
|
27
|
-
>,
|
|
28
|
-
) {
|
|
29
|
-
const NodeClass = class extends IONode<
|
|
30
|
-
InferOr<TConfigSchema, any>,
|
|
31
|
-
InferOr<TCredsSchema, any>,
|
|
32
|
-
InferOr<TInputSchema, any>,
|
|
33
|
-
InferOutputs<TOutputsSchema>,
|
|
34
|
-
InferOr<TSettingsSchema, any>
|
|
35
|
-
> {
|
|
36
|
-
static override readonly type: string = def.type;
|
|
37
|
-
static override readonly category: string = def.category ?? "function";
|
|
38
|
-
static override readonly color: HexColor = def.color ?? "#a6bbcf";
|
|
39
|
-
static override readonly inputs: number = def.inputs ?? 1;
|
|
40
|
-
static override readonly outputs: number = def.outputs ?? 1;
|
|
41
|
-
static override readonly paletteLabel = def.paletteLabel;
|
|
42
|
-
static override readonly inputLabels = def.inputLabels;
|
|
43
|
-
static override readonly outputLabels = def.outputLabels;
|
|
44
|
-
static override readonly align = def.align;
|
|
45
|
-
static override readonly labelStyle = def.labelStyle;
|
|
46
|
-
|
|
47
|
-
static override readonly configSchema: Schema | undefined =
|
|
48
|
-
def.configSchema as Schema | undefined;
|
|
49
|
-
static override readonly credentialsSchema: Schema | undefined =
|
|
50
|
-
def.credentialsSchema as Schema | undefined;
|
|
51
|
-
static override readonly settingsSchema: Schema | undefined =
|
|
52
|
-
def.settingsSchema as Schema | undefined;
|
|
53
|
-
static override readonly inputSchema: Schema | undefined =
|
|
54
|
-
def.inputSchema as Schema | undefined;
|
|
55
|
-
static override readonly outputsSchema: Schema | Schema[] | undefined =
|
|
56
|
-
def.outputsSchema as Schema | Schema[] | undefined;
|
|
57
|
-
static override readonly validateInput: boolean =
|
|
58
|
-
def.validateInput ?? false;
|
|
59
|
-
static override readonly validateOutput: boolean =
|
|
60
|
-
def.validateOutput ?? false;
|
|
61
|
-
|
|
62
|
-
static override _registered(RED: RED) {
|
|
63
|
-
this.validateSettings(RED);
|
|
64
|
-
return def.registered?.(RED);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async input(msg: InferOr<TInputSchema, any>) {
|
|
68
|
-
return def.input.call(this as any, msg);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
override async created() {
|
|
72
|
-
if (def.created) return def.created.call(this as any);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
override async closed(removed?: boolean) {
|
|
76
|
-
if (def.closed) return def.closed.call(this as any, removed);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
Object.defineProperty(NodeClass, "name", {
|
|
81
|
-
value: def.type.replace(/(^|-)(\w)/g, (_, __, c: string) =>
|
|
82
|
-
c.toUpperCase(),
|
|
83
|
-
),
|
|
84
|
-
configurable: true,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return NodeClass;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function defineConfigNode<
|
|
91
|
-
TConfigSchema extends TSchema | undefined = undefined,
|
|
92
|
-
TCredsSchema extends TSchema | undefined = undefined,
|
|
93
|
-
TSettingsSchema extends TSchema | undefined = undefined,
|
|
94
|
-
>(def: ConfigNodeDefinition<TConfigSchema, TCredsSchema, TSettingsSchema>) {
|
|
95
|
-
const NodeClass = class extends ConfigNode<
|
|
96
|
-
InferOr<TConfigSchema, any>,
|
|
97
|
-
InferOr<TCredsSchema, any>,
|
|
98
|
-
InferOr<TSettingsSchema, any>
|
|
99
|
-
> {
|
|
100
|
-
static override readonly type: string = def.type;
|
|
101
|
-
|
|
102
|
-
static override readonly configSchema: Schema | undefined =
|
|
103
|
-
def.configSchema as Schema | undefined;
|
|
104
|
-
static override readonly credentialsSchema: Schema | undefined =
|
|
105
|
-
def.credentialsSchema as Schema | undefined;
|
|
106
|
-
static override readonly settingsSchema: Schema | undefined =
|
|
107
|
-
def.settingsSchema as Schema | undefined;
|
|
108
|
-
|
|
109
|
-
static override _registered(RED: RED) {
|
|
110
|
-
this.validateSettings(RED);
|
|
111
|
-
return def.registered?.(RED);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
override async created() {
|
|
115
|
-
if (def.created) return def.created.call(this as any);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
override async closed(removed?: boolean) {
|
|
119
|
-
if (def.closed) return def.closed.call(this as any, removed);
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
Object.defineProperty(NodeClass, "name", {
|
|
124
|
-
value: def.type.replace(/(^|-)(\w)/g, (_, __, c: string) =>
|
|
125
|
-
c.toUpperCase(),
|
|
126
|
-
),
|
|
127
|
-
configurable: true,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
return NodeClass;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export { defineIONode, defineConfigNode };
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import type { Schema } from "../schemas/types";
|
|
2
|
-
import type { RED } from "../../server/types";
|
|
3
|
-
import { validator } from "../validator";
|
|
4
|
-
import { Node } from "./node";
|
|
5
|
-
import type {
|
|
6
|
-
HexColor,
|
|
7
|
-
IONodeContext,
|
|
8
|
-
IONodeContextScope,
|
|
9
|
-
IONodeStatus,
|
|
10
|
-
IONodeConfig,
|
|
11
|
-
IONodeCredentials,
|
|
12
|
-
} from "./types";
|
|
13
|
-
import { setupContext } from "./utils";
|
|
14
|
-
|
|
15
|
-
abstract class IONode<
|
|
16
|
-
TConfig = any,
|
|
17
|
-
TCredentials = any,
|
|
18
|
-
TInput = any,
|
|
19
|
-
TOutput = any,
|
|
20
|
-
TSettings = any,
|
|
21
|
-
> extends Node<TConfig, TCredentials, TSettings> {
|
|
22
|
-
public static readonly align?: "left" | "right";
|
|
23
|
-
public static readonly color: HexColor;
|
|
24
|
-
public static readonly labelStyle?:
|
|
25
|
-
| "node_label"
|
|
26
|
-
| "node_label_italic"
|
|
27
|
-
| string;
|
|
28
|
-
public static readonly paletteLabel?: string;
|
|
29
|
-
public static readonly inputs?: number = 0;
|
|
30
|
-
public static readonly outputs?: number = 0;
|
|
31
|
-
public static readonly inputLabels?: string | string[];
|
|
32
|
-
public static readonly outputLabels?: string | string[];
|
|
33
|
-
public static readonly inputSchema?: Schema;
|
|
34
|
-
public static readonly outputsSchema?: Schema | Schema[];
|
|
35
|
-
public static readonly validateInput: boolean = false;
|
|
36
|
-
public static readonly validateOutput: boolean = false;
|
|
37
|
-
|
|
38
|
-
private _send: ((msg: any) => void) | undefined;
|
|
39
|
-
|
|
40
|
-
declare public readonly config: IONodeConfig<TConfig>;
|
|
41
|
-
protected override readonly context: IONodeContext;
|
|
42
|
-
|
|
43
|
-
// NOTE: used by the registered function. Had to be a different one to avoid calling the parent's input again
|
|
44
|
-
/** @internal */
|
|
45
|
-
public static override _registered(RED: RED): void | Promise<void> {
|
|
46
|
-
this.validateSettings(RED);
|
|
47
|
-
return this.registered?.(RED);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
constructor(
|
|
51
|
-
RED: RED,
|
|
52
|
-
node: any,
|
|
53
|
-
config: IONodeConfig<TConfig>,
|
|
54
|
-
credentials: IONodeCredentials<TCredentials>,
|
|
55
|
-
) {
|
|
56
|
-
super(RED, node, config, credentials);
|
|
57
|
-
|
|
58
|
-
const context = node.context();
|
|
59
|
-
const fn = (scope: IONodeContextScope, store?: string) => {
|
|
60
|
-
const target =
|
|
61
|
-
scope === "global"
|
|
62
|
-
? context.global
|
|
63
|
-
: scope === "flow"
|
|
64
|
-
? context.flow
|
|
65
|
-
: context;
|
|
66
|
-
return setupContext(target, store);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
fn.node = setupContext(context);
|
|
70
|
-
fn.flow = setupContext(context.flow);
|
|
71
|
-
fn.global = setupContext(context.global);
|
|
72
|
-
|
|
73
|
-
this.context = fn as any;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public abstract input(msg: TInput): void | Promise<void>;
|
|
77
|
-
|
|
78
|
-
// NOTE: used by the registered function. Had to be a different one to avoid calling the parent's input again
|
|
79
|
-
/** @internal */
|
|
80
|
-
public async _input(msg: TInput, send: (msg: any) => void) {
|
|
81
|
-
const NodeClass = this.constructor as typeof IONode;
|
|
82
|
-
const shouldValidateInput =
|
|
83
|
-
this.config.validateInput ?? NodeClass.validateInput;
|
|
84
|
-
if (shouldValidateInput && NodeClass.inputSchema) {
|
|
85
|
-
this.log("Validating input");
|
|
86
|
-
validator.validate(msg, NodeClass.inputSchema, {
|
|
87
|
-
cacheKey: NodeClass.inputSchema.$id || `${NodeClass.type}:input-schema`,
|
|
88
|
-
throwOnError: true,
|
|
89
|
-
});
|
|
90
|
-
this.log("Input is valid");
|
|
91
|
-
}
|
|
92
|
-
this._send = send;
|
|
93
|
-
try {
|
|
94
|
-
await Promise.resolve(this.input(msg));
|
|
95
|
-
} finally {
|
|
96
|
-
this._send = undefined;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
public send(msg: TOutput) {
|
|
101
|
-
const NodeClass = this.constructor as typeof IONode;
|
|
102
|
-
const shouldValidateOutput =
|
|
103
|
-
this.config.validateOutput ?? NodeClass.validateOutput;
|
|
104
|
-
if (shouldValidateOutput && NodeClass.outputsSchema) {
|
|
105
|
-
this.log("Validating output");
|
|
106
|
-
const schemas = NodeClass.outputsSchema;
|
|
107
|
-
|
|
108
|
-
if (Array.isArray(schemas)) {
|
|
109
|
-
// Per-port validation: schemas[i] validates msg[i]
|
|
110
|
-
const msgs = msg as any[];
|
|
111
|
-
for (let i = 0; i < schemas.length; i++) {
|
|
112
|
-
if (msgs[i] == null) continue;
|
|
113
|
-
validator.validate(msgs[i], schemas[i], {
|
|
114
|
-
cacheKey: schemas[i].$id || `${NodeClass.type}:output-schema:${i}`,
|
|
115
|
-
throwOnError: true,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
} else if (Array.isArray(msg)) {
|
|
119
|
-
// Single schema, array of messages: validate each non-null element
|
|
120
|
-
for (let i = 0; i < (msg as any[]).length; i++) {
|
|
121
|
-
if ((msg as any[])[i] == null) continue;
|
|
122
|
-
validator.validate((msg as any[])[i], schemas, {
|
|
123
|
-
cacheKey: schemas.$id || `${NodeClass.type}:output-schema`,
|
|
124
|
-
throwOnError: true,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
// Single schema, single message
|
|
129
|
-
validator.validate(msg, schemas, {
|
|
130
|
-
cacheKey: schemas.$id || `${NodeClass.type}:output-schema`,
|
|
131
|
-
throwOnError: true,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
this.log("Output is valid");
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (this._send) {
|
|
138
|
-
this._send(msg);
|
|
139
|
-
} else {
|
|
140
|
-
this.node.send(msg);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public status(status: IONodeStatus) {
|
|
145
|
-
this.node.status(status);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
public updateWires(wires: string[][]) {
|
|
149
|
-
this.node.updateWires(wires);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
public receive(msg: TInput) {
|
|
153
|
-
this.node.receive(msg);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
public get x(): number {
|
|
157
|
-
return this.node.x;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
public get y(): number {
|
|
161
|
-
return this.node.y;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public get g(): string | undefined {
|
|
165
|
-
return this.node.g;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
public get wires(): string[][] {
|
|
169
|
-
return this.node.wires;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
public override get credentials():
|
|
173
|
-
| IONodeCredentials<TCredentials>
|
|
174
|
-
| undefined {
|
|
175
|
-
return this.node.credentials;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export { IONode };
|