@theotherwillembotha/node-red-plugincore 0.0.50

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.
Files changed (180) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +190 -0
  3. package/build/GenerateNodes.d.ts +2 -0
  4. package/build/GenerateNodes.d.ts.map +1 -0
  5. package/build/GenerateNodes.js +36 -0
  6. package/build/Nodes.html +1729 -0
  7. package/build/Nodes.js +32 -0
  8. package/build/Plugins.js +74 -0
  9. package/build/core/NodeConstructor.d.ts +188 -0
  10. package/build/core/NodeConstructor.d.ts.map +1 -0
  11. package/build/core/NodeConstructor.js +679 -0
  12. package/build/core/NodeGenerator.d.ts +37 -0
  13. package/build/core/NodeGenerator.d.ts.map +1 -0
  14. package/build/core/NodeGenerator.js +300 -0
  15. package/build/core/Utils.d.ts +7 -0
  16. package/build/core/Utils.d.ts.map +1 -0
  17. package/build/core/Utils.js +19 -0
  18. package/build/core/logger/LoggerDecorator.d.ts +2 -0
  19. package/build/core/logger/LoggerDecorator.d.ts.map +1 -0
  20. package/build/core/logger/LoggerDecorator.js +93 -0
  21. package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts +16 -0
  22. package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts.map +1 -0
  23. package/build/core/logger/node/ConsoleLoggerConfigNode.html +131 -0
  24. package/build/core/logger/node/ConsoleLoggerConfigNode.js +47 -0
  25. package/build/core/logger/node/LoggerConfigNode.d.ts +30 -0
  26. package/build/core/logger/node/LoggerConfigNode.d.ts.map +1 -0
  27. package/build/core/logger/node/LoggerConfigNode.html +307 -0
  28. package/build/core/logger/node/LoggerConfigNode.js +60 -0
  29. package/build/core/logger/node/LokiLoggerConfigNode.d.ts +20 -0
  30. package/build/core/logger/node/LokiLoggerConfigNode.d.ts.map +1 -0
  31. package/build/core/logger/node/LokiLoggerConfigNode.html +153 -0
  32. package/build/core/logger/node/LokiLoggerConfigNode.js +52 -0
  33. package/build/core/logger/node/RestLoggerConfigNode.d.ts +24 -0
  34. package/build/core/logger/node/RestLoggerConfigNode.d.ts.map +1 -0
  35. package/build/core/logger/node/RestLoggerConfigNode.html +209 -0
  36. package/build/core/logger/node/RestLoggerConfigNode.js +57 -0
  37. package/build/core/logger/service/LoggerService.d.ts +88 -0
  38. package/build/core/logger/service/LoggerService.d.ts.map +1 -0
  39. package/build/core/logger/service/LoggerService.js +204 -0
  40. package/build/core/logger/service/LoggerServiceTypes.d.ts +24 -0
  41. package/build/core/logger/service/LoggerServiceTypes.d.ts.map +1 -0
  42. package/build/core/logger/service/LoggerServiceTypes.js +30 -0
  43. package/build/core/logger/template/LoggerTemplate.d.ts +11 -0
  44. package/build/core/logger/template/LoggerTemplate.d.ts.map +1 -0
  45. package/build/core/logger/template/LoggerTemplate.html +328 -0
  46. package/build/core/logger/template/LoggerTemplate.js +12 -0
  47. package/build/core/metrics/MetricsDecorator.d.ts +40 -0
  48. package/build/core/metrics/MetricsDecorator.d.ts.map +1 -0
  49. package/build/core/metrics/MetricsDecorator.js +166 -0
  50. package/build/core/metrics/node/CounterMetricConfigNode.d.ts +16 -0
  51. package/build/core/metrics/node/CounterMetricConfigNode.d.ts.map +1 -0
  52. package/build/core/metrics/node/CounterMetricConfigNode.html +48 -0
  53. package/build/core/metrics/node/CounterMetricConfigNode.js +61 -0
  54. package/build/core/metrics/node/GaugeMetricConfigNode.d.ts +17 -0
  55. package/build/core/metrics/node/GaugeMetricConfigNode.d.ts.map +1 -0
  56. package/build/core/metrics/node/GaugeMetricConfigNode.html +48 -0
  57. package/build/core/metrics/node/GaugeMetricConfigNode.js +61 -0
  58. package/build/core/metrics/node/MetricsConfigNode.d.ts +14 -0
  59. package/build/core/metrics/node/MetricsConfigNode.d.ts.map +1 -0
  60. package/build/core/metrics/node/MetricsConfigNode.html +21 -0
  61. package/build/core/metrics/node/MetricsConfigNode.js +56 -0
  62. package/build/core/metrics/node/TimerMetricConfigNode.d.ts +28 -0
  63. package/build/core/metrics/node/TimerMetricConfigNode.d.ts.map +1 -0
  64. package/build/core/metrics/node/TimerMetricConfigNode.html +190 -0
  65. package/build/core/metrics/node/TimerMetricConfigNode.js +101 -0
  66. package/build/core/metrics/service/MetricsService.d.ts +187 -0
  67. package/build/core/metrics/service/MetricsService.d.ts.map +1 -0
  68. package/build/core/metrics/service/MetricsService.js +385 -0
  69. package/build/core/metrics/template/CounterMetricTemplate.d.ts +5 -0
  70. package/build/core/metrics/template/CounterMetricTemplate.d.ts.map +1 -0
  71. package/build/core/metrics/template/CounterMetricTemplate.html +40 -0
  72. package/build/core/metrics/template/CounterMetricTemplate.js +12 -0
  73. package/build/core/metrics/template/GaugeMetricTemplate.d.ts +5 -0
  74. package/build/core/metrics/template/GaugeMetricTemplate.d.ts.map +1 -0
  75. package/build/core/metrics/template/GaugeMetricTemplate.html +39 -0
  76. package/build/core/metrics/template/GaugeMetricTemplate.js +12 -0
  77. package/build/core/metrics/template/MetricsTemplate.d.ts +8 -0
  78. package/build/core/metrics/template/MetricsTemplate.d.ts.map +1 -0
  79. package/build/core/metrics/template/MetricsTemplate.html +54 -0
  80. package/build/core/metrics/template/MetricsTemplate.js +12 -0
  81. package/build/core/metrics/template/TimerMetricTemplate.d.ts +5 -0
  82. package/build/core/metrics/template/TimerMetricTemplate.d.ts.map +1 -0
  83. package/build/core/metrics/template/TimerMetricTemplate.html +39 -0
  84. package/build/core/metrics/template/TimerMetricTemplate.js +12 -0
  85. package/build/core/other/InputDecorator.d.ts +3 -0
  86. package/build/core/other/InputDecorator.d.ts.map +1 -0
  87. package/build/core/other/InputDecorator.js +43 -0
  88. package/build/core/other/service/InputService.d.ts +16 -0
  89. package/build/core/other/service/InputService.d.ts.map +1 -0
  90. package/build/core/other/service/InputService.js +31 -0
  91. package/build/core/other/service/SettingsService.d.ts +25 -0
  92. package/build/core/other/service/SettingsService.d.ts.map +1 -0
  93. package/build/core/other/service/SettingsService.js +74 -0
  94. package/build/core/other/template/BasicTemplate.d.ts +5 -0
  95. package/build/core/other/template/BasicTemplate.d.ts.map +1 -0
  96. package/build/core/other/template/BasicTemplate.html +76 -0
  97. package/build/core/other/template/BasicTemplate.js +11 -0
  98. package/build/core/other/template/SettingsTemplate.d.ts +5 -0
  99. package/build/core/other/template/SettingsTemplate.d.ts.map +1 -0
  100. package/build/core/other/template/SettingsTemplate.html +128 -0
  101. package/build/core/other/template/SettingsTemplate.js +11 -0
  102. package/build/core/tagging/NodeDescriptionDecorator.d.ts +17 -0
  103. package/build/core/tagging/NodeDescriptionDecorator.d.ts.map +1 -0
  104. package/build/core/tagging/NodeDescriptionDecorator.js +25 -0
  105. package/build/core/tagging/service/NodeTypeService.d.ts +15 -0
  106. package/build/core/tagging/service/NodeTypeService.d.ts.map +1 -0
  107. package/build/core/tagging/service/NodeTypeService.js +47 -0
  108. package/build/core/webhook/WebhookDecorator.d.ts +3 -0
  109. package/build/core/webhook/WebhookDecorator.d.ts.map +1 -0
  110. package/build/core/webhook/WebhookDecorator.js +45 -0
  111. package/build/core/webhook/node/WebhookServerConfigNode.d.ts +16 -0
  112. package/build/core/webhook/node/WebhookServerConfigNode.d.ts.map +1 -0
  113. package/build/core/webhook/node/WebhookServerConfigNode.html +61 -0
  114. package/build/core/webhook/node/WebhookServerConfigNode.js +40 -0
  115. package/build/core/webhook/service/ReverseProxyTypeService.d.ts +29 -0
  116. package/build/core/webhook/service/ReverseProxyTypeService.d.ts.map +1 -0
  117. package/build/core/webhook/service/ReverseProxyTypeService.js +24 -0
  118. package/build/core/webhook/service/WebhookServerService.d.ts +52 -0
  119. package/build/core/webhook/service/WebhookServerService.d.ts.map +1 -0
  120. package/build/core/webhook/service/WebhookServerService.js +146 -0
  121. package/build/core/webhook/template/WebhookTemplate.d.ts +22 -0
  122. package/build/core/webhook/template/WebhookTemplate.d.ts.map +1 -0
  123. package/build/core/webhook/template/WebhookTemplate.html +434 -0
  124. package/build/core/webhook/template/WebhookTemplate.js +12 -0
  125. package/build/index.d.ts +33 -0
  126. package/build/index.d.ts.map +1 -0
  127. package/build/index.js +55 -0
  128. package/package.json +67 -0
  129. package/src/GenerateNodes.ts +42 -0
  130. package/src/core/NodeConstructor.ts +889 -0
  131. package/src/core/NodeGenerator.ts +331 -0
  132. package/src/core/Utils.ts +19 -0
  133. package/src/core/logger/LoggerDecorator.ts +105 -0
  134. package/src/core/logger/node/ConsoleLoggerConfigNode.html +131 -0
  135. package/src/core/logger/node/ConsoleLoggerConfigNode.ts +46 -0
  136. package/src/core/logger/node/LoggerConfigNode.html +307 -0
  137. package/src/core/logger/node/LoggerConfigNode.ts +95 -0
  138. package/src/core/logger/node/LokiLoggerConfigNode.html +153 -0
  139. package/src/core/logger/node/LokiLoggerConfigNode.ts +58 -0
  140. package/src/core/logger/node/RestLoggerConfigNode.html +209 -0
  141. package/src/core/logger/node/RestLoggerConfigNode.ts +67 -0
  142. package/src/core/logger/service/LoggerService.ts +317 -0
  143. package/src/core/logger/service/LoggerServiceTypes.ts +26 -0
  144. package/src/core/logger/template/LoggerTemplate.html +328 -0
  145. package/src/core/logger/template/LoggerTemplate.ts +23 -0
  146. package/src/core/metrics/MetricsDecorator.ts +227 -0
  147. package/src/core/metrics/node/CounterMetricConfigNode.html +48 -0
  148. package/src/core/metrics/node/CounterMetricConfigNode.ts +62 -0
  149. package/src/core/metrics/node/GaugeMetricConfigNode.html +48 -0
  150. package/src/core/metrics/node/GaugeMetricConfigNode.ts +62 -0
  151. package/src/core/metrics/node/MetricsConfigNode.html +21 -0
  152. package/src/core/metrics/node/MetricsConfigNode.ts +55 -0
  153. package/src/core/metrics/node/TimerMetricConfigNode.html +190 -0
  154. package/src/core/metrics/node/TimerMetricConfigNode.ts +118 -0
  155. package/src/core/metrics/service/MetricsService.ts +560 -0
  156. package/src/core/metrics/template/CounterMetricTemplate.html +40 -0
  157. package/src/core/metrics/template/CounterMetricTemplate.ts +15 -0
  158. package/src/core/metrics/template/GaugeMetricTemplate.html +39 -0
  159. package/src/core/metrics/template/GaugeMetricTemplate.ts +15 -0
  160. package/src/core/metrics/template/MetricsTemplate.html +54 -0
  161. package/src/core/metrics/template/MetricsTemplate.ts +18 -0
  162. package/src/core/metrics/template/TimerMetricTemplate.html +39 -0
  163. package/src/core/metrics/template/TimerMetricTemplate.ts +14 -0
  164. package/src/core/other/InputDecorator.ts +57 -0
  165. package/src/core/other/service/InputService.ts +36 -0
  166. package/src/core/other/service/SettingsService.ts +103 -0
  167. package/src/core/other/template/BasicTemplate.html +76 -0
  168. package/src/core/other/template/BasicTemplate.ts +15 -0
  169. package/src/core/other/template/SettingsTemplate.html +128 -0
  170. package/src/core/other/template/SettingsTemplate.ts +17 -0
  171. package/src/core/tagging/NodeDescriptionDecorator.ts +39 -0
  172. package/src/core/tagging/service/NodeTypeService.ts +67 -0
  173. package/src/core/webhook/WebhookDecorator.ts +70 -0
  174. package/src/core/webhook/node/WebhookServerConfigNode.html +61 -0
  175. package/src/core/webhook/node/WebhookServerConfigNode.ts +38 -0
  176. package/src/core/webhook/service/ReverseProxyTypeService.ts +46 -0
  177. package/src/core/webhook/service/WebhookServerService.ts +211 -0
  178. package/src/core/webhook/template/WebhookTemplate.html +434 -0
  179. package/src/core/webhook/template/WebhookTemplate.ts +36 -0
  180. package/src/index.ts +47 -0
@@ -0,0 +1,70 @@
1
+ import { RestAuthType } from "../logger/service/LoggerServiceTypes";
2
+ import { BaseNode, createPostConstructDecorator, NodeManager } from "../NodeConstructor";
3
+ import { ProxyManagerClient } from "./service/ReverseProxyTypeService";
4
+ import { ApiKeyAuthenticationConfig, BasicAuthenticationConfig, EndpointConfig, EndpointMethodType, NoAuthenticationConfig, WebhookServer } from "./service/WebhookServerService";
5
+ import { WebhookTemplateConfig } from "./template/WebhookTemplate";
6
+
7
+
8
+ type WebhookConfig = {
9
+ name?:string,
10
+ methods:EndpointMethodType[],
11
+ }
12
+
13
+ const Webhook = createPostConstructDecorator<WebhookConfig>('Webhook')
14
+ .withInitLogic(async (instance, propertyKey, webhookconfig:WebhookConfig) => {
15
+ //console.log(`Registering webhook callback`, "PROPERTYKEY", propertyKey, "WEBHOOK CONFIG", webhookconfig, "THIS", this);
16
+
17
+ let node = instance as BaseNode<WebhookTemplateConfig>;
18
+ let nodeConfig = node.config();
19
+
20
+ // create the authentication.
21
+ let authentication =
22
+ (nodeConfig.webhookAuth === RestAuthType.basic) ? {type:RestAuthType.basic, username:nodeConfig.webhookAuth_basic_username, password: nodeConfig.webhookAuth_basic_password} as BasicAuthenticationConfig :
23
+ (nodeConfig.webhookAuth === RestAuthType.apikey) ? {type:RestAuthType.apikey, mechanism:nodeConfig.webhookAuth_apikey_mechanism, key:nodeConfig.webhookAuth_apikey_key, value: nodeConfig.webhookAuth_apikey_value } as ApiKeyAuthenticationConfig :
24
+ {type:RestAuthType.none} as NoAuthenticationConfig;
25
+
26
+ // register a callback listener to the webserver.
27
+ let endpointConfig:EndpointConfig = {
28
+ path: nodeConfig.webhookPath,
29
+ methods: webhookconfig.methods,
30
+ authentication: authentication
31
+ }
32
+
33
+ let webhookServer:WebhookServer = (NodeManager.RED.nodes.getNode(nodeConfig.webhook) as any).node().server();
34
+ webhookServer.attach(endpointConfig, (request, respponse) => instance[propertyKey](request, respponse));
35
+
36
+ if(nodeConfig.reverseProxies_enabled){
37
+
38
+ await Promise.all(nodeConfig.reverseProxies_connections.map(async proxy => {
39
+
40
+ try{
41
+ // get a n instance of reverseProxNode.
42
+ let reverseProxyNode = (NodeManager.RED.nodes.getNode(proxy.proxy) as any).node();
43
+
44
+ // TODO: ReverseProxyConfigNodes need to become their own subtype of config nodes so we can enforce the ".client()" method.
45
+ let proxyClient = reverseProxyNode.client() as ProxyManagerClient;
46
+
47
+ console.log("List of known hosts: ", await proxyClient.getHosts());
48
+
49
+
50
+ //console.log("ADD REVERSE PROXY:" + proxy.proxy + " to " + node.id(), proxyClient);
51
+ }
52
+ catch(e){
53
+ console.log(e);
54
+ }
55
+
56
+ return Promise.resolve();
57
+ }));
58
+ }
59
+
60
+ // register a close listener to the node.
61
+ node.node().on("close", () => {
62
+ webhookServer.detach(endpointConfig);
63
+ })
64
+ })
65
+ .build();
66
+
67
+
68
+ export {
69
+ Webhook
70
+ }
@@ -0,0 +1,61 @@
1
+
2
+ <script type="text/javascript" template-section="onCompose">
3
+ node
4
+ .addDefault("name", { value:"Webhook Example", required:true})
5
+ .addDefault("port", { value:6644, required:true})
6
+ .addDefault("externalHost", { value:"localhost", required:true })
7
+ .addDefault("externalPort", { value:6644, required:true})
8
+ .addDefault("name", { value:"Example Test Node", required:true})
9
+ .setPaletteLabel("Webhook")
10
+ .setLabelStyle("node_label_white")
11
+ .setLabel(function() {return this.name })
12
+ .setColor("#0050E5")
13
+ .setInput("testInput")
14
+ .addOutputs("testOutput1","testOutput2","testOutput3")
15
+ </script>
16
+
17
+ <div template-section="onIncludeOnce">
18
+ </div>
19
+
20
+
21
+ <script type="text/html" template-section="onIncludeEditForm">\
22
+ <div id="WebhookServerConfig">
23
+ <div class="form-row">
24
+ <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
25
+ <input type="text" id="node-config-input-name" />
26
+ </div>
27
+
28
+ <div class="form-row">
29
+ <label for="node-config-input-port"><i class="fa fa-tag"></i> Port</label>
30
+ <input type="number" id="node-config-input-port" />
31
+ </div>
32
+
33
+ <div class="form-row">
34
+ <label for="node-config-input-externalHost"><i class="fa fa-tag"></i> External Host</label>
35
+ <input type="text" id="node-config-input-externalHost" />
36
+ </div>
37
+
38
+ <div class="form-row">
39
+ <label for="node-config-input-externalPort"><i class="fa fa-tag"></i> External Port</label>
40
+ <input type="number" id="node-config-input-externalPort" />
41
+ </div>
42
+ <!-- add a button here to autmatically find an open port -->
43
+ </div>
44
+
45
+ </script>
46
+
47
+ <script type="text/markdown" template-section="onIncludeDocumentation">
48
+ Configuration node for an Express HTTP server that webhook nodes attach to. A single server instance is shared by all webhook nodes that reference it. The server is started when the flow is first deployed and stopped when it is torn down.
49
+
50
+ ### Inputs
51
+ : *name* (string) : A descriptive name for this webhook server.
52
+ : *port* (number) : The local port the HTTP server will listen on. Defaults to `6644`. Each server instance must use a unique port.
53
+
54
+ ### Reverse Proxy
55
+ When this server sits behind a reverse proxy, configure the following fields so that webhook nodes know the externally-visible address. This is used when registering endpoints with a reverse proxy service.
56
+
57
+ : *external host* (string) : The public hostname or IP of the reverse proxy (e.g. `myserver.example.com`).
58
+ : *external port* (number) : The public port exposed by the reverse proxy.
59
+ </script>
60
+
61
+
@@ -0,0 +1,38 @@
1
+
2
+ import { Node } from "node-red";
3
+ import { ConfigNode, ConfigNodeConfig } from "../../NodeConstructor"
4
+ import { SourceUtility } from "../../NodeGenerator";
5
+ import { WebhookServer, WebhookServerService } from "../service/WebhookServerService";
6
+ import { NodeDescription } from "../../tagging/NodeDescriptionDecorator";
7
+
8
+ interface WebhookServerConfigNodeConfig extends ConfigNodeConfig {
9
+ id: string;
10
+ port: number;
11
+ externalHost:string;
12
+ externalPort:number;
13
+ }
14
+
15
+ @NodeDescription({
16
+ id:"WebhookServerConfigNode",
17
+ name:"Webhook Server Config Node",
18
+ group:"config",
19
+ sourceFile:SourceUtility.getSourcePath("/build/", "/src/") + "WebhookServerConfigNode.html",
20
+ package: "@theotherwillembotha/node-red-plugincore",
21
+ dependencies:[ WebhookServerService ],
22
+ tags: [ "Core" ]
23
+ })
24
+ export class WebhookServerConfigNode extends ConfigNode<WebhookServerConfigNodeConfig> {
25
+ private _server: WebhookServer;
26
+
27
+ constructor(node: Node, config: WebhookServerConfigNodeConfig){
28
+ super(node, config);
29
+ let _this = this;
30
+
31
+ // instantiate the webhook here.. or get a reference to it atleast.
32
+ this._server = WebhookServerService.get(config);
33
+ }
34
+
35
+ public server():WebhookServer {
36
+ return this._server;
37
+ }
38
+ }
@@ -0,0 +1,46 @@
1
+ import { BaseService, FlowDeployment, ServiceDescriptor } from "../../NodeConstructor";
2
+ import { NodeAPI, NodeAPISettingsWithData } from "node-red";
3
+
4
+ export abstract class ReverseProxyType {
5
+
6
+ private _id: string;
7
+ private _name: string;
8
+
9
+ constructor(id:string, name:string){
10
+ this._id = id;
11
+ this._name = name;
12
+ }
13
+
14
+ public id():string {
15
+ return this._id;
16
+ }
17
+ public name():string {
18
+ return this._name;
19
+ }
20
+ }
21
+
22
+ export interface ProxyManagerClient {
23
+ updateHost(data: Partial<HostEntry>):Promise<void>;
24
+ getHosts():Promise<Partial<HostEntry>[]>;
25
+ }
26
+
27
+ export abstract class ReverseProxyClient {
28
+
29
+ }
30
+
31
+ export type HostEntry = {
32
+ id:number,
33
+ domainNames:string[],
34
+ scheme:HTTPScheme,
35
+ forwardHost:string,
36
+ forwardPort:number,
37
+ accessList:string,
38
+ cacheAssets:boolean,
39
+ blockCommonExploits:boolean,
40
+ websocketSupport:boolean,
41
+ }
42
+
43
+ export enum HTTPScheme{
44
+ HTTP = "http",
45
+ HTTPS = "https"
46
+ }
@@ -0,0 +1,211 @@
1
+
2
+ import {BaseService, FlowDeployment, ServiceDescriptor } from "../../NodeConstructor";
3
+ import { NodeAPI, NodeAPISettingsWithData } from "node-red";
4
+ import { WebhookServerConfigNode } from "../node/WebhookServerConfigNode";
5
+ import { WebhookTemplate } from "../template/WebhookTemplate";
6
+ import express, {Express, Request, Response} from "express";
7
+ import { Server } from "http";
8
+ import { ApiKeyMechanismType, RestAuthType } from "../../logger/service/LoggerServiceTypes";
9
+
10
+ var bodyParser = require('body-parser');
11
+
12
+ export enum EndpointMethodType {
13
+ GET = "GET",
14
+ POST = "POST",
15
+ }
16
+
17
+ export type NoAuthenticationConfig = {
18
+ type:RestAuthType.none;
19
+ }
20
+
21
+ export type BasicAuthenticationConfig = {
22
+ type:RestAuthType.basic
23
+ username:string;
24
+ password:string;
25
+ }
26
+
27
+ export type ApiKeyAuthenticationConfig = {
28
+ type:RestAuthType.apikey,
29
+ mechanism:ApiKeyMechanismType,
30
+ key:string;
31
+ value:string;
32
+ }
33
+
34
+ export type EndpointConfig = {
35
+ path: string;
36
+ methods:EndpointMethodType[];
37
+ authentication: NoAuthenticationConfig | BasicAuthenticationConfig | ApiKeyAuthenticationConfig;
38
+ }
39
+
40
+ export class WebhookServer {
41
+
42
+ private _config: WebhookServerConfig;
43
+ private _app: Express;
44
+ private _listener: Server;
45
+
46
+ public constructor(config:WebhookServerConfig){
47
+ this._config = config;
48
+
49
+ this._app = express();
50
+ this._app.use(bodyParser.json({type: "application/json", limit: '50mb'}));
51
+ this._listener = this._app.listen(this._config.port, '0.0.0.0');
52
+ }
53
+
54
+ public attach(endpoint:EndpointConfig, callback:(request:Request, response:Response) => any){
55
+
56
+ let authenticator:((request:Request, response:Response) => Promise<boolean>);
57
+
58
+ if(endpoint.authentication.type === RestAuthType.none){
59
+ authenticator = (request, response) => Promise.resolve(true);
60
+ }
61
+
62
+ if(endpoint.authentication.type === RestAuthType.basic){
63
+ let header = "Basic " + Buffer.from(`${endpoint.authentication.username}:${endpoint.authentication.password}`).toString("base64");
64
+ authenticator = (request, response) => {
65
+ return Promise.resolve(header === request.headers.authorization);
66
+ }
67
+ }
68
+
69
+ if(endpoint.authentication.type === RestAuthType.apikey){
70
+ let auth = endpoint.authentication as ApiKeyAuthenticationConfig;
71
+ authenticator = (request, response) => {
72
+ if(auth.mechanism === ApiKeyMechanismType.header){
73
+ return Promise.resolve(request.headers[auth.key] === auth.value)
74
+ }
75
+ console.log("No APIKEY Authentication Handler Implementation for Type: " + auth.mechanism);
76
+ return Promise.resolve(false);
77
+ }
78
+ }
79
+
80
+ let handlerChain = (request:Request, response:Response) => authenticator(request, response)
81
+ .then(result => {
82
+ if(result) {
83
+ callback(request, response);
84
+ }
85
+ else{
86
+ response.status(401).send()
87
+ }
88
+ });
89
+
90
+ if(endpoint.methods.includes(EndpointMethodType.GET)){
91
+ this._app.get(endpoint.path, handlerChain);
92
+ }
93
+
94
+ if(endpoint.methods.includes(EndpointMethodType.POST)){
95
+ this._app.post(endpoint.path, handlerChain);
96
+ }
97
+
98
+ console.log("added endpoint to " + endpoint.path);
99
+ }
100
+
101
+ public detach(configuration:EndpointConfig){
102
+ configuration.methods.forEach(method => {
103
+ this._app.router.stack = this._app.router.stack.filter(layer => {
104
+ // if the path doesnt match, keep it.
105
+ if(layer.route?.path !== configuration.path){
106
+ return true;
107
+ }
108
+ switch(method){
109
+ case EndpointMethodType.GET:{
110
+ return !(layer.route as any)?.methods.get
111
+ }
112
+ case EndpointMethodType.POST:{
113
+ return !(layer.route as any)?.methods.post
114
+ }
115
+ };
116
+ })
117
+ });
118
+
119
+ console.log("ROUTES REMOVED!");
120
+ this._app.router.stack.forEach(route => console.log("KNOWN ROUTE", route, route.route?.path, (route.route as any).methods.post));
121
+ }
122
+
123
+ public config():WebhookServerConfig {
124
+ return this._config;
125
+ }
126
+ }
127
+
128
+ export type WebhookServerConfig = {
129
+ id:string
130
+ port: number;
131
+ externalHost:string;
132
+ externalPort:number;
133
+ }
134
+
135
+ export class WebhookServerService extends BaseService {
136
+
137
+ private static webhookServers:{[key:string]:WebhookServer} = {};
138
+
139
+ constructor(){
140
+ super("wehbookserver")
141
+ }
142
+
143
+ public init(red: NodeAPI<NodeAPISettingsWithData>): void | Promise<void> {
144
+ return Promise.resolve();
145
+ }
146
+
147
+ public deinit(red: NodeAPI<NodeAPISettingsWithData>): void | Promise<void> {
148
+ return Promise.resolve();
149
+ }
150
+
151
+ public onDeploy(flowDeployment: FlowDeployment): void | Promise<void> {
152
+ let removedServers:WebhookServerConfig[] = []
153
+ let addedServers:WebhookServerConfig[] = []
154
+
155
+ let webhookServerNodes = flowDeployment.flows.filter(node => node.type === "WebhookServerConfigNode") as any as WebhookServerConfig[];
156
+
157
+ // find all the nodes that have been removed or changed.
158
+ Object.entries(WebhookServerService.webhookServers).forEach(([key, serverService]) => {
159
+ let webhookServerNode = webhookServerNodes.find(node => node.id === key);
160
+ let serverServiceConfig = serverService.config();
161
+ // compare the properties.
162
+ if(!webhookServerNode){
163
+ // the node has been removed: TODO: alert the listeners that it has been removed.
164
+ console.log("Webhook Service Removed", serverServiceConfig)
165
+ removedServers.push(serverServiceConfig);
166
+ }
167
+ else{
168
+ // check if the node has changed at all.
169
+ let serviceChanged =
170
+ webhookServerNode.port !== serverServiceConfig.port ||
171
+ webhookServerNode.externalHost !== serverServiceConfig.externalHost ||
172
+ webhookServerNode.externalPort !== serverServiceConfig.externalPort;
173
+
174
+ if(serviceChanged){
175
+ // TODO: notify the subscribers that the server has chaned.
176
+ console.log("Notify the subscribers WebhookServer has changed.", serverServiceConfig, webhookServerNode);
177
+ removedServers.push(serverServiceConfig);
178
+ addedServers.push(webhookServerNode);
179
+ }
180
+ }
181
+ });
182
+
183
+ // find all the servers that have been added.
184
+ webhookServerNodes
185
+ .filter(node => !WebhookServerService.webhookServers[node.id])
186
+ .forEach(node => addedServers.push(node));
187
+
188
+ //console.log("REMOVED SERVERS:", removedServers);
189
+ //console.log("ADDED SERVERS:", addedServers);
190
+ }
191
+
192
+ public static get (config:WebhookServerConfig): WebhookServer{
193
+ let server = (this.webhookServers[config.id]);
194
+ if(!server){
195
+ this.webhookServers[config.id] = server = new WebhookServer(config);
196
+ console.log(`Creating webhook server on port ${config.port}`);
197
+ }
198
+ return server;
199
+ }
200
+
201
+ static override getServiceDescriptor():ServiceDescriptor {
202
+ return new ServiceDescriptor(
203
+ "@theotherwillembotha/webhookserverservice",
204
+ "WebhookServerService",
205
+ "services-plugin",
206
+ "@theotherwillembotha/node-red-plugincore",
207
+ WebhookServerService,
208
+ [WebhookServerConfigNode, WebhookTemplate]
209
+ );
210
+ }
211
+ }