@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 CHANGED
@@ -47,23 +47,53 @@ export default defineConfig({
47
47
  });
48
48
  ```
49
49
 
50
- **src/server/index.ts**
50
+ **src/server/schemas/my-node.ts**
51
51
 
52
52
  ```typescript
53
- import MyNode from "./nodes/my-node";
54
-
55
- export default {
56
- nodes: [MyNode],
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
- export type Config = Infer<typeof ConfigsSchema>;
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
@@ -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