@bonsae/nrg 0.5.4 → 0.6.1
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 +56 -7
- package/build/server/index.cjs +120 -39
- package/build/server/resources/nrg-client.js +1440 -1377
- package/build/vite/index.js +95 -0
- package/package.json +4 -1
- package/src/core/client/app.vue +15 -25
- package/src/core/client/components/node-red-json-schema-form.vue +21 -2
- package/src/core/client/components/node-red-toggle.vue +115 -0
- package/src/core/client/index.ts +2 -0
- package/src/core/server/api/index.ts +1 -0
- package/src/core/server/api/serve-nrg-resources.ts +54 -0
- package/src/core/server/index.ts +22 -57
- package/src/core/server/nodes/factories.ts +136 -0
- package/src/core/server/nodes/index.ts +1 -0
- package/src/core/server/nodes/io-node.ts +2 -1
- package/src/core/server/nodes/types/factories.ts +130 -0
- package/src/core/server/nodes/types/index.ts +1 -0
- package/src/core/server/nodes/types/io-node.ts +3 -0
- package/src/core/server/schemas/types/index.ts +1 -0
- package/src/vite/server/plugins/type-generator.ts +157 -0
package/README.md
CHANGED
|
@@ -47,23 +47,53 @@ export default defineConfig({
|
|
|
47
47
|
});
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
**src/server/
|
|
50
|
+
**src/server/schemas/my-node.ts**
|
|
51
51
|
|
|
52
52
|
```typescript
|
|
53
|
-
import
|
|
54
|
-
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
}
|
|
53
|
+
import { defineSchema, SchemaType } from "@bonsae/nrg/server";
|
|
54
|
+
|
|
55
|
+
export const ConfigsSchema = defineSchema(
|
|
56
|
+
{
|
|
57
|
+
name: SchemaType.String({ default: "" }),
|
|
58
|
+
prefix: SchemaType.String({ default: "hello" }),
|
|
59
|
+
},
|
|
60
|
+
{ $id: "my-node:configs" }
|
|
61
|
+
);
|
|
58
62
|
```
|
|
59
63
|
|
|
60
64
|
**src/server/nodes/my-node.ts**
|
|
61
65
|
|
|
66
|
+
NRG supports two ways to define nodes:
|
|
67
|
+
|
|
68
|
+
<table>
|
|
69
|
+
<tr><th>Functional API</th><th>Class API</th></tr>
|
|
70
|
+
<tr><td>
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { defineIONode } from "@bonsae/nrg/server";
|
|
74
|
+
import { ConfigsSchema } from "../schemas/my-node";
|
|
75
|
+
|
|
76
|
+
export default defineIONode({
|
|
77
|
+
type: "my-node",
|
|
78
|
+
color: "#ffffff",
|
|
79
|
+
inputs: 1,
|
|
80
|
+
outputs: 1,
|
|
81
|
+
configSchema: ConfigsSchema,
|
|
82
|
+
|
|
83
|
+
async input(msg) {
|
|
84
|
+
msg.payload = `${this.config.prefix}: ${msg.payload}`;
|
|
85
|
+
this.send(msg);
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
</td><td>
|
|
91
|
+
|
|
62
92
|
```typescript
|
|
63
93
|
import { IONode, type Schema, type Infer } from "@bonsae/nrg/server";
|
|
64
94
|
import { ConfigsSchema } from "../schemas/my-node";
|
|
65
95
|
|
|
66
|
-
|
|
96
|
+
type Config = Infer<typeof ConfigsSchema>;
|
|
67
97
|
|
|
68
98
|
export default class MyNode extends IONode<Config> {
|
|
69
99
|
static readonly type = "my-node";
|
|
@@ -74,11 +104,30 @@ export default class MyNode extends IONode<Config> {
|
|
|
74
104
|
static readonly configSchema: Schema = ConfigsSchema;
|
|
75
105
|
|
|
76
106
|
async input(msg: any) {
|
|
107
|
+
msg.payload = `${this.config.prefix}: ${msg.payload}`;
|
|
77
108
|
this.send(msg);
|
|
78
109
|
}
|
|
79
110
|
}
|
|
80
111
|
```
|
|
81
112
|
|
|
113
|
+
</td></tr>
|
|
114
|
+
<tr>
|
|
115
|
+
<td>Automatic type inference, less boilerplate</td>
|
|
116
|
+
<td>Custom methods, inheritance, mixins</td>
|
|
117
|
+
</tr>
|
|
118
|
+
</table>
|
|
119
|
+
|
|
120
|
+
**src/server/index.ts**
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { defineModule } from "@bonsae/nrg/server";
|
|
124
|
+
import MyNode from "./nodes/my-node";
|
|
125
|
+
|
|
126
|
+
export default defineModule({
|
|
127
|
+
nodes: [MyNode],
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
82
131
|
See the [consumer template](https://github.com/AllanOricil/node-red-vue-template) for a complete example.
|
|
83
132
|
|
|
84
133
|
## Project Structure
|
package/build/server/index.cjs
CHANGED
|
@@ -35,13 +35,14 @@ __export(index_exports, {
|
|
|
35
35
|
Node: () => Node,
|
|
36
36
|
NrgError: () => NrgError,
|
|
37
37
|
SchemaType: () => SchemaType,
|
|
38
|
+
defineConfigNode: () => defineConfigNode,
|
|
39
|
+
defineIONode: () => defineIONode,
|
|
40
|
+
defineModule: () => defineModule,
|
|
38
41
|
defineSchema: () => defineSchema,
|
|
39
42
|
registerType: () => registerType,
|
|
40
43
|
registerTypes: () => registerTypes
|
|
41
44
|
});
|
|
42
45
|
module.exports = __toCommonJS(index_exports);
|
|
43
|
-
var import_path = __toESM(require("path"), 1);
|
|
44
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
45
46
|
|
|
46
47
|
// src/core/server/utils.ts
|
|
47
48
|
function getCredentialsFromSchema(schema) {
|
|
@@ -657,6 +658,117 @@ var ConfigNode = class extends Node {
|
|
|
657
658
|
}
|
|
658
659
|
};
|
|
659
660
|
|
|
661
|
+
// src/core/server/nodes/factories.ts
|
|
662
|
+
function defineIONode(def) {
|
|
663
|
+
const NodeClass = class extends IONode {
|
|
664
|
+
static type = def.type;
|
|
665
|
+
static category = def.category ?? "function";
|
|
666
|
+
static color = def.color ?? "#a6bbcf";
|
|
667
|
+
static inputs = def.inputs ?? 1;
|
|
668
|
+
static outputs = def.outputs ?? 1;
|
|
669
|
+
static paletteLabel = def.paletteLabel;
|
|
670
|
+
static inputLabels = def.inputLabels;
|
|
671
|
+
static outputLabels = def.outputLabels;
|
|
672
|
+
static align = def.align;
|
|
673
|
+
static labelStyle = def.labelStyle;
|
|
674
|
+
static configSchema = def.configSchema;
|
|
675
|
+
static credentialsSchema = def.credentialsSchema;
|
|
676
|
+
static settingsSchema = def.settingsSchema;
|
|
677
|
+
static inputSchema = def.inputSchema;
|
|
678
|
+
static outputsSchema = def.outputsSchema;
|
|
679
|
+
static validateInput = def.validateInput ?? false;
|
|
680
|
+
static validateOutput = def.validateOutput ?? false;
|
|
681
|
+
static _registered(RED) {
|
|
682
|
+
this.validateSettings(RED);
|
|
683
|
+
return def.registered?.(RED);
|
|
684
|
+
}
|
|
685
|
+
async input(msg) {
|
|
686
|
+
if (def.input) return def.input.call(this, msg);
|
|
687
|
+
}
|
|
688
|
+
async created() {
|
|
689
|
+
if (def.created) return def.created.call(this);
|
|
690
|
+
}
|
|
691
|
+
async closed(removed) {
|
|
692
|
+
if (def.closed) return def.closed.call(this, removed);
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
Object.defineProperty(NodeClass, "name", {
|
|
696
|
+
value: def.type.replace(
|
|
697
|
+
/(^|-)(\w)/g,
|
|
698
|
+
(_, __, c) => c.toUpperCase()
|
|
699
|
+
),
|
|
700
|
+
configurable: true
|
|
701
|
+
});
|
|
702
|
+
return NodeClass;
|
|
703
|
+
}
|
|
704
|
+
function defineConfigNode(def) {
|
|
705
|
+
const NodeClass = class extends ConfigNode {
|
|
706
|
+
static type = def.type;
|
|
707
|
+
static configSchema = def.configSchema;
|
|
708
|
+
static credentialsSchema = def.credentialsSchema;
|
|
709
|
+
static settingsSchema = def.settingsSchema;
|
|
710
|
+
static _registered(RED) {
|
|
711
|
+
this.validateSettings(RED);
|
|
712
|
+
return def.registered?.(RED);
|
|
713
|
+
}
|
|
714
|
+
async created() {
|
|
715
|
+
if (def.created) return def.created.call(this);
|
|
716
|
+
}
|
|
717
|
+
async closed(removed) {
|
|
718
|
+
if (def.closed) return def.closed.call(this, removed);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
Object.defineProperty(NodeClass, "name", {
|
|
722
|
+
value: def.type.replace(
|
|
723
|
+
/(^|-)(\w)/g,
|
|
724
|
+
(_, __, c) => c.toUpperCase()
|
|
725
|
+
),
|
|
726
|
+
configurable: true
|
|
727
|
+
});
|
|
728
|
+
return NodeClass;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// src/core/server/api/serve-nrg-resources.ts
|
|
732
|
+
var import_path = __toESM(require("path"), 1);
|
|
733
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
734
|
+
var MIME = {
|
|
735
|
+
".js": "application/javascript",
|
|
736
|
+
".mjs": "application/javascript",
|
|
737
|
+
".css": "text/css",
|
|
738
|
+
".json": "application/json",
|
|
739
|
+
".map": "application/json",
|
|
740
|
+
".png": "image/png",
|
|
741
|
+
".svg": "image/svg+xml"
|
|
742
|
+
};
|
|
743
|
+
var _registered = false;
|
|
744
|
+
function serveNrgResources(RED) {
|
|
745
|
+
if (_registered) return;
|
|
746
|
+
_registered = true;
|
|
747
|
+
const clientDir = import_path.default.resolve(__dirname, "./resources");
|
|
748
|
+
if (!import_fs.default.existsSync(clientDir)) return;
|
|
749
|
+
const httpAdmin = RED.httpAdmin;
|
|
750
|
+
if (!httpAdmin) return;
|
|
751
|
+
httpAdmin.use(function(req, res, next) {
|
|
752
|
+
const prefix = "/nrg/assets/";
|
|
753
|
+
if (!req.path.startsWith(prefix)) return next();
|
|
754
|
+
let reqPath = req.path.slice(prefix.length);
|
|
755
|
+
if (reqPath === "vue.esm-browser.prod.js" && process.env.NODE_ENV !== "production") {
|
|
756
|
+
const devPath = import_path.default.resolve(clientDir, "vue.esm-browser.js");
|
|
757
|
+
if (import_fs.default.existsSync(devPath)) {
|
|
758
|
+
reqPath = "vue.esm-browser.js";
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
const filePath = import_path.default.resolve(clientDir, reqPath);
|
|
762
|
+
const rel = import_path.default.relative(clientDir, filePath);
|
|
763
|
+
if (rel.startsWith("..") || import_path.default.isAbsolute(rel)) return next();
|
|
764
|
+
if (!import_fs.default.existsSync(filePath) || !import_fs.default.statSync(filePath).isFile())
|
|
765
|
+
return next();
|
|
766
|
+
const ext = import_path.default.extname(filePath);
|
|
767
|
+
res.setHeader("Content-Type", MIME[ext] ?? "application/octet-stream");
|
|
768
|
+
import_fs.default.createReadStream(filePath).pipe(res);
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
|
|
660
772
|
// src/core/constants.ts
|
|
661
773
|
var TYPED_INPUT_TYPES = [
|
|
662
774
|
"msg",
|
|
@@ -790,43 +902,6 @@ var TypedInputSchema = SchemaType.Object(
|
|
|
790
902
|
);
|
|
791
903
|
|
|
792
904
|
// src/core/server/index.ts
|
|
793
|
-
var MIME = {
|
|
794
|
-
".js": "application/javascript",
|
|
795
|
-
".mjs": "application/javascript",
|
|
796
|
-
".css": "text/css",
|
|
797
|
-
".json": "application/json",
|
|
798
|
-
".map": "application/json",
|
|
799
|
-
".png": "image/png",
|
|
800
|
-
".svg": "image/svg+xml"
|
|
801
|
-
};
|
|
802
|
-
var _nrgResourcesRegistered = false;
|
|
803
|
-
function serveNrgResources(RED) {
|
|
804
|
-
if (_nrgResourcesRegistered) return;
|
|
805
|
-
_nrgResourcesRegistered = true;
|
|
806
|
-
const clientDir = import_path.default.resolve(__dirname, "./resources");
|
|
807
|
-
if (!import_fs.default.existsSync(clientDir)) return;
|
|
808
|
-
const httpAdmin = RED.httpAdmin;
|
|
809
|
-
if (!httpAdmin) return;
|
|
810
|
-
httpAdmin.use(function(req, res, next) {
|
|
811
|
-
const prefix = "/nrg/assets/";
|
|
812
|
-
if (!req.path.startsWith(prefix)) return next();
|
|
813
|
-
let reqPath = req.path.slice(prefix.length);
|
|
814
|
-
if (reqPath === "vue.esm-browser.prod.js" && process.env.NODE_ENV !== "production") {
|
|
815
|
-
const devPath = import_path.default.resolve(clientDir, "vue.esm-browser.js");
|
|
816
|
-
if (import_fs.default.existsSync(devPath)) {
|
|
817
|
-
reqPath = "vue.esm-browser.js";
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
const filePath = import_path.default.resolve(clientDir, reqPath);
|
|
821
|
-
const rel = import_path.default.relative(clientDir, filePath);
|
|
822
|
-
if (rel.startsWith("..") || import_path.default.isAbsolute(rel)) return next();
|
|
823
|
-
if (!import_fs.default.existsSync(filePath) || !import_fs.default.statSync(filePath).isFile())
|
|
824
|
-
return next();
|
|
825
|
-
const ext = import_path.default.extname(filePath);
|
|
826
|
-
res.setHeader("Content-Type", MIME[ext] ?? "application/octet-stream");
|
|
827
|
-
import_fs.default.createReadStream(filePath).pipe(res);
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
905
|
async function registerType(RED, NodeClass) {
|
|
831
906
|
const NC = NodeClass;
|
|
832
907
|
RED.log.debug(`Registering Type: ${NC.type}`);
|
|
@@ -939,6 +1014,9 @@ function registerTypes(nodes) {
|
|
|
939
1014
|
fn.nodes = nodes;
|
|
940
1015
|
return fn;
|
|
941
1016
|
}
|
|
1017
|
+
function defineModule(definition) {
|
|
1018
|
+
return definition;
|
|
1019
|
+
}
|
|
942
1020
|
// Annotate the CommonJS export names for ESM import in node:
|
|
943
1021
|
0 && (module.exports = {
|
|
944
1022
|
ConfigNode,
|
|
@@ -946,6 +1024,9 @@ function registerTypes(nodes) {
|
|
|
946
1024
|
Node,
|
|
947
1025
|
NrgError,
|
|
948
1026
|
SchemaType,
|
|
1027
|
+
defineConfigNode,
|
|
1028
|
+
defineIONode,
|
|
1029
|
+
defineModule,
|
|
949
1030
|
defineSchema,
|
|
950
1031
|
registerType,
|
|
951
1032
|
registerTypes
|