@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,209 @@
1
+
2
+ <script type="text/javascript" template-section="onCompose">
3
+ node
4
+ .addDefault("name", {value:"Logger Example", required:true})
5
+ .addDefault("template", {value:`message:{{msg}}`, required:true})
6
+ .addDefault("level", {value:"info", required:true})
7
+
8
+ // platform rest:
9
+ .addDefault("est_url", {})
10
+ .addDefault("est_ignoresslerror", {})
11
+ .addDefault("rest_auth_type", {})
12
+ .addDefault("rest_auth_basic_username", {})
13
+ .addDefault("rest_auth_basic_password", {})
14
+ .addDefault("rest_auth_apikey_mechanism", {})
15
+ .addDefault("rest_auth_apikey_name", {})
16
+ .addDefault("rest_auth_apikey_value", {})
17
+
18
+ .setPaletteLabel("Rest Logger Config Node")
19
+ .setLabel(function() {return this.name })
20
+
21
+ </script>
22
+
23
+ <script type="text/javascript" template-section="onIncludeEditPrepare">
24
+ {
25
+ let node = this;
26
+
27
+ let showSelectedRestAuthMethod = (value) => {
28
+ $("#LoggerConfig")
29
+ .find(".platform.platform-rest").first()
30
+ .find(".platform-rest-auth")
31
+ .each((i, t) => {
32
+ t = $(t);
33
+ if(t.hasClass(`auth-${value}`)){ t.show(); }
34
+ else { t.hide(); }
35
+ });
36
+ }
37
+
38
+ let levelSelection = $("#node-config-input-level");
39
+ levelSelection.typedInput({type:"level", types:[{
40
+ value: "level",
41
+ options: [
42
+ { value: "DEBUG", label: "debug"},
43
+ { value: "INFO", label: "info"},
44
+ { value: "WARNING", label: "warning"},
45
+ { value: "ERROR", label: "error"},
46
+ ]
47
+ }]});
48
+
49
+ let platformRestAuthType = $("#node-config-input-rest_auth_type");
50
+ platformRestAuthType.typedInput({type:"authtype", types:[{
51
+ value: "authtype",
52
+ options: [
53
+ { value: "none", label: "None"},
54
+ { value: "basic", label: "Basic"},
55
+ { value: "apikey", label: "ApiKey"}
56
+ ]
57
+ }]});
58
+ platformRestAuthType.on("change", () => showSelectedRestAuthMethod(platformRestAuthType.val()));
59
+
60
+ let apiKeyMechanism = $("#node-config-input-rest_auth_apikey_mechanism");
61
+ apiKeyMechanism.typedInput({type:"apikeymechansim", types:[{
62
+ value: "apikeymechansim",
63
+ options: [
64
+ { value: "header", label: "Header"},
65
+ { value: "queryparam", label: "Query Param"},
66
+ { value: "matrixparam", label: "Matrix Param"}
67
+ ]
68
+ }]});
69
+
70
+ this.editor = RED.editor.createEditor({
71
+ id: 'node-config-input-templateEditor',
72
+ mode: 'ace/mode/handlebars',
73
+ value: this.template
74
+ });
75
+ }
76
+ </script>
77
+
78
+ <script type="text/javascript" template-section="onIncludeEditSave">
79
+ {
80
+ let node = this;
81
+ this.template = this.editor.getValue();
82
+ this.editor.destroy();
83
+ delete this.editor;
84
+ }
85
+
86
+ </script>
87
+
88
+ <script type="text/html" template-section="onIncludeEditForm">
89
+ <div id="LoggerConfig">
90
+ <div class="form-row">
91
+ <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
92
+ <input type="text" id="node-config-input-name" />
93
+ </div>
94
+
95
+ <div class="form-row">
96
+ <label for="node-config-input-level"><i class="fa fa-tag"></i> Level</label>
97
+ <input type="text" id="node-config-input-level" />
98
+ </div>
99
+
100
+ <div class="platform platform-rest">
101
+ <div class="form-row">
102
+ <label for="node-config-input-rest_url"><i class="fa fa-tag"></i> URL</label>
103
+ <input class="platform-rest-input required" type="text" id="node-config-input-rest_url" />
104
+ </div>
105
+ <div class="form-row">
106
+ <label></label>
107
+ <input type="checkbox" id="node-config-input-rest_ignoresslerror" style="width:20px; margin-right:5px;" />
108
+ <label style="width:auto" for="node-config-input-rest_ignoresslerror"><span>Ignore Invalid SSL certificates</span></label>
109
+ </div>
110
+ <div class="form-row">
111
+ <label for="node-config-input-rest_auth_type"><i class="fa fa-tag"></i> Authentication</label>
112
+ <input class="platform-rest-input required" type="text" id="node-config-input-rest_auth_type" />
113
+ </div>
114
+ <div class="form-row platform-rest-auth auth-basic">
115
+ <label for="node-config-input-rest_auth_basic_username"><i class="fa fa-tag"></i> Username</label>
116
+ <input class="platform-rest-input" type="text" id="node-config-input-rest_auth_basic_username" />
117
+ </div>
118
+ <div class="form-row platform-rest-auth auth-basic">
119
+ <label for="node-config-input-rest_auth_basic_password"><i class="fa fa-tag"></i> Password</label>
120
+ <input class="platform-rest-input" type="password" id="node-config-input-rest_auth_basic_password" />
121
+ </div>
122
+ <div class="form-row platform-rest-auth auth-apikey">
123
+ <label for="node-config-input-rest_auth_apikey_mechanism"><i class="fa fa-tag"></i> Mechanism</label>
124
+ <input class="platform-rest-input" type="text" id="node-config-input-rest_auth_apikey_mechanism" />
125
+ </div>
126
+ <div class="form-row platform-rest-auth auth-apikey">
127
+ <label for="node-config-input-rest_auth_apikey_name"><i class="fa fa-tag"></i> APIKey name</label>
128
+ <input class="platform-rest-input" type="text" id="node-config-input-rest_auth_apikey_name" />
129
+ </div>
130
+ <div class="form-row platform-rest-auth auth-apikey">
131
+ <label for="node-config-input-rest_auth_apikey_value"><i class="fa fa-tag"></i> APIKey value</label>
132
+ <input class="platform-rest-input" type="text" id="node-config-input-rest_auth_apikey_value" />
133
+ </div>
134
+ </div>
135
+
136
+ <div class="form-row">
137
+ <label for="node-config-input-templateEditor"><i class="fa fa-tag"></i> Template</label>
138
+ <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-config-input-templateEditor"></div>
139
+ </div>
140
+ </div>
141
+ </script>
142
+
143
+ <script type="text/markdown" template-section="onIncludeDocumentation">
144
+ Configuration node for the Logger Integration
145
+
146
+ ## Inputs
147
+ : *name* (string) : The common name for the logger Configuration
148
+ : *level* (level) : The logging level - debug, info, warning, error
149
+ : *platform*(string) : The common name for the logger Configuration
150
+ : *template*(mustache) : A template for the log messages.
151
+
152
+ ## Logger platform
153
+ Currently supported logging platforms
154
+
155
+ ### Console
156
+ The log message will be printed out to stdio
157
+
158
+ ### Http / Https
159
+ Publish the message to an http endpoint using a http / https POST command.
160
+
161
+ : *url* (url) : The endpoint for the url where requests are to be posted to.
162
+ : *ignore ssl errors* (boolean) : If enabled, the invalid ssl certificates will be ignored.
163
+ : *authentication* (auth method) : what auth method should be used for the http request. (none, basic, api key)
164
+
165
+ #### Authentication
166
+ ##### Basic
167
+ Provides basic authentication using the Authorization header
168
+
169
+ : *username* (string) : the username used for basic authentication
170
+ : *password* (string) : the password used for basic authentication
171
+
172
+ ##### APIKey
173
+ Provides authentication using a matrix parameter, header or query parameter and an apikey
174
+
175
+ : *mechanism* (mechanism) : the mechanism that will be used for transmitting the key (header, queryparam, matrixparam)
176
+ : *apikey name* (string) : the name of the key used for api authentication. (path variable or query param name)
177
+ : *apikey value*(string) : the value of the api key that will be transmitted. (beware of special characters)
178
+
179
+ ### Loki
180
+ Publish the message to a loki endpoint.
181
+
182
+ : *host* (string) : the host and port\ of the loki instance that it being logged to
183
+ : *tenant* (string) : the tenant id that will be used to log to
184
+ : *username* (string) : the username for the loki instance.
185
+ : *authtoken* (string) : the authtoken for the loki instance.
186
+
187
+ # Mustache Templating
188
+ Mustache / Handlebars are used for building up the logged message payloads that are sent to the logging backend.
189
+ The resultant message will be interpreted as a string, meaning care should be taken in the event that a string representation of a json object is built.
190
+
191
+ ### Provided Properties
192
+ A couple of values are provided to the logging context by default.
193
+
194
+ : *msg* (object) : an object containing the payload or message that should be parsed through the template.
195
+ : *currentTime* (object) : a string containing the current time in ISO8601 format
196
+
197
+ ### Mustache Helpers
198
+ In addition to the provided properties, some "helpers" have also been provided to assist in serialization.
199
+
200
+ : *json* (helper) : converts a json object to a string using the JSON.stringify method.
201
+
202
+ ## Examples
203
+ - {{{json msg}}} - serializes the the msg object to json format.
204
+
205
+ # References
206
+ - [Mustache - Wikipedia](https://en.wikipedia.org/wiki/Mustache_(template_system))
207
+ - [Mustache - Playground](https://jgonggrijp.gitlab.io/wontache/playground.html)
208
+ </script>
209
+
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RestLoggerConfigNode = void 0;
13
+ const NodeConstructor_1 = require("../../NodeConstructor");
14
+ const LoggerService_1 = require("../service/LoggerService");
15
+ const NodeGenerator_1 = require("../../NodeGenerator");
16
+ const LoggerServiceTypes_1 = require("../service/LoggerServiceTypes");
17
+ const NodeDescriptionDecorator_1 = require("../../tagging/NodeDescriptionDecorator");
18
+ let RestLoggerConfigNode = class RestLoggerConfigNode extends NodeConstructor_1.ConfigNode {
19
+ constructor(node, config) {
20
+ super(node, config);
21
+ let _this = this;
22
+ // instantiate the logger.
23
+ let loggerConfig;
24
+ if (config.platform === LoggerServiceTypes_1.PlatformType.rest) {
25
+ loggerConfig = {
26
+ id: this.id(),
27
+ type: LoggerServiceTypes_1.PlatformType.rest,
28
+ template: config.template,
29
+ level: config.level,
30
+ url: config.rest_url,
31
+ auth_type: config.rest_auth_type,
32
+ auth_basic_username: config.rest_auth_basic_username,
33
+ auth_basic_password: config.rest_auth_basic_password,
34
+ auth_apikey_mechanism: config.rest_auth_apikey_mechanism,
35
+ auth_apikey_name: config.rest_auth_apikey_name,
36
+ auth_apikey_value: config.rest_auth_apikey_value,
37
+ };
38
+ }
39
+ this._logger = LoggerService_1.LoggerService.get(loggerConfig);
40
+ }
41
+ registerLogger(registration) {
42
+ return this._logger.register(registration);
43
+ }
44
+ };
45
+ exports.RestLoggerConfigNode = RestLoggerConfigNode;
46
+ exports.RestLoggerConfigNode = RestLoggerConfigNode = __decorate([
47
+ (0, NodeDescriptionDecorator_1.NodeDescription)({
48
+ id: "RestLoggerConfigNode",
49
+ name: "Console Logger",
50
+ group: "config",
51
+ sourceFile: NodeGenerator_1.SourceUtility.getSourcePath("/build/", "/src/") + "RestLoggerConfigNode.html",
52
+ package: "@theotherwillembotha/node-red-plugincore",
53
+ dependencies: [LoggerService_1.LoggerService],
54
+ tags: ["LoggerType"]
55
+ }),
56
+ __metadata("design:paramtypes", [Object, Object])
57
+ ], RestLoggerConfigNode);
@@ -0,0 +1,88 @@
1
+ import { BaseService, ServiceDescriptor } from "../../NodeConstructor";
2
+ import { NodeAPI, NodeAPISettingsWithData } from "node-red";
3
+ import { ApiKeyMechanismType, Level, PlatformType, RestAuthType } from "./LoggerServiceTypes";
4
+ type TagMap = {
5
+ instance: string;
6
+ flow: string;
7
+ node: string;
8
+ type: string;
9
+ id: string;
10
+ };
11
+ export type Log = {
12
+ log(message: {
13
+ [key: string]: any;
14
+ } | string): void;
15
+ };
16
+ export declare class LogImplementation implements Log {
17
+ private root;
18
+ private config;
19
+ private template?;
20
+ private tagMap;
21
+ constructor(root: NewLogger<any>, config: LoggerRegistration);
22
+ log(message: {
23
+ [key: string]: any;
24
+ } | string): void;
25
+ serialize(content: {
26
+ [key: string]: any;
27
+ }): string;
28
+ getTags(): TagMap;
29
+ }
30
+ export interface BaseLoggerConfig {
31
+ id: string;
32
+ type: PlatformType;
33
+ level: Level;
34
+ template: string;
35
+ }
36
+ export declare abstract class NewLogger<ConfigType extends BaseLoggerConfig> {
37
+ private _config;
38
+ private template;
39
+ constructor(config: ConfigType);
40
+ log(reference: LogImplementation, content: {
41
+ [key: string]: any;
42
+ }): void;
43
+ register(registration: LoggerRegistration): Log;
44
+ serialize(content: any): string;
45
+ config(): ConfigType;
46
+ protected abstract writeToLog(serializedContent: string, tags: TagMap): void;
47
+ }
48
+ export interface ConsoleLoggerConfig extends BaseLoggerConfig {
49
+ }
50
+ export interface LokiLoggerConfig extends BaseLoggerConfig {
51
+ type: PlatformType.loki;
52
+ host: string;
53
+ userid?: string;
54
+ authtoken?: string;
55
+ tenantID?: string;
56
+ }
57
+ export interface RestLoggerConfig extends BaseLoggerConfig {
58
+ type: PlatformType.rest;
59
+ url: string;
60
+ ignoresslerror: boolean;
61
+ auth_type: RestAuthType;
62
+ auth_basic_username: string;
63
+ auth_basic_password: string;
64
+ auth_apikey_mechanism: ApiKeyMechanismType;
65
+ auth_apikey_name: string;
66
+ auth_apikey_value: string;
67
+ }
68
+ export declare class LoggerService extends BaseService {
69
+ static instanceID: string;
70
+ private static loggers;
71
+ private red;
72
+ constructor();
73
+ init(red: NodeAPI<NodeAPISettingsWithData>): void | Promise<void>;
74
+ deinit(red: NodeAPI<NodeAPISettingsWithData>): void | Promise<void>;
75
+ static get<ConfigType extends BaseLoggerConfig>(config: ConfigType): NewLogger<ConfigType>;
76
+ static getServiceDescriptor(): ServiceDescriptor;
77
+ }
78
+ export type LoggerRegistration = {
79
+ id: string;
80
+ flow: string;
81
+ type: string;
82
+ name: string;
83
+ enabled: boolean;
84
+ template?: string;
85
+ override?: boolean;
86
+ };
87
+ export {};
88
+ //# sourceMappingURL=LoggerService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoggerService.d.ts","sourceRoot":"","sources":["../../../../src/core/logger/service/LoggerService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LoggerService = exports.NewLogger = exports.LogImplementation = void 0;
7
+ const NodeConstructor_1 = require("../../NodeConstructor");
8
+ const handlebars_1 = __importDefault(require("handlebars"));
9
+ const winston_1 = require("winston");
10
+ const winston_loki_1 = __importDefault(require("winston-loki"));
11
+ const whatwg_url_1 = require("whatwg-url");
12
+ const LoggerConfigNode_1 = require("../node/LoggerConfigNode");
13
+ const LoggerTemplate_1 = require("../template/LoggerTemplate");
14
+ var network = require('network');
15
+ const deep_equal_1 = __importDefault(require("deep-equal"));
16
+ const LoggerServiceTypes_1 = require("./LoggerServiceTypes");
17
+ // helper for serializing json objects inside handlebars tags.
18
+ // you can then convert it like this: {{{json myobject}}}
19
+ handlebars_1.default.registerHelper('json', function (context) {
20
+ return JSON.stringify(context);
21
+ });
22
+ class LogImplementation {
23
+ constructor(root, config) {
24
+ this.root = root;
25
+ this.config = config;
26
+ this.template = (config.override && config.template) ? handlebars_1.default.compile(config.template) : undefined;
27
+ this.tagMap = {
28
+ instance: LoggerService.instanceID,
29
+ flow: config.flow,
30
+ node: config.name,
31
+ type: config.type,
32
+ id: config.id,
33
+ };
34
+ }
35
+ log(message) {
36
+ // enrich the logged content with additional properties.
37
+ let content = {
38
+ currentTime: new Date().toISOString(),
39
+ msg: message,
40
+ };
41
+ // send typ the logger.
42
+ this.root.log(this, content);
43
+ }
44
+ serialize(content) {
45
+ return !!this.template ? this.template(content) : this.root.serialize(content);
46
+ }
47
+ getTags() {
48
+ return this.tagMap;
49
+ }
50
+ }
51
+ exports.LogImplementation = LogImplementation;
52
+ class NewLogger {
53
+ constructor(config) {
54
+ this._config = config;
55
+ this.template = handlebars_1.default.compile(config.template);
56
+ }
57
+ log(reference, content) {
58
+ try {
59
+ // step 1, attempt to serialize the content.
60
+ let serializedContent = reference.serialize(content);
61
+ // step 2, get the tags.
62
+ let tags = reference.getTags();
63
+ // step 3. write to the logger.
64
+ this.writeToLog(serializedContent, tags);
65
+ }
66
+ catch (exception) {
67
+ console.log(exception.message);
68
+ }
69
+ }
70
+ register(registration) {
71
+ return new LogImplementation(this, registration);
72
+ }
73
+ serialize(content) {
74
+ return this.template(content);
75
+ }
76
+ config() {
77
+ return this._config;
78
+ }
79
+ }
80
+ exports.NewLogger = NewLogger;
81
+ class ConsoleLogger extends NewLogger {
82
+ constructor(config) {
83
+ super(config);
84
+ }
85
+ writeToLog(serializedContent, tags) {
86
+ console.log(tags, serializedContent);
87
+ }
88
+ }
89
+ class LokiLogger extends NewLogger {
90
+ constructor(config) {
91
+ super(config);
92
+ let transportConfig = {
93
+ host: config.host,
94
+ json: true,
95
+ format: winston_1.format.json(),
96
+ headers: {
97
+ "X-Scope-OrgID": (config.tenantID) ? config.tenantID : undefined
98
+ },
99
+ replaceTimestamp: true,
100
+ onConnectionError: (err) => console.error(err),
101
+ basicAuth: (config.userid && config.authtoken)
102
+ ? `${config.userid}:${config.authtoken}`
103
+ : undefined
104
+ };
105
+ this.logger = (0, winston_1.createLogger)({
106
+ level: this.config().level.toString().toLowerCase(),
107
+ format: winston_1.format.json(),
108
+ defaultMeta: {},
109
+ transports: [
110
+ new winston_loki_1.default(transportConfig),
111
+ ],
112
+ });
113
+ }
114
+ writeToLog(serializedContent, tags) {
115
+ this.logger.log({ message: serializedContent, level: this.logger.level, labels: tags });
116
+ }
117
+ }
118
+ class RestLogger extends NewLogger {
119
+ constructor(config) {
120
+ super(config);
121
+ let hosturl = (0, whatwg_url_1.parseURL)(config.url);
122
+ if (!hosturl) {
123
+ throw Error("could not parse url: " + config.url);
124
+ }
125
+ let httpOptions = {};
126
+ let httpParams = {
127
+ host: hosturl.host?.toString(),
128
+ path: "/" + (hosturl.path ? [...hosturl.path].join("/") : "") + (hosturl.query ? ("?" + hosturl.query) : ""),
129
+ port: (hosturl.port) ? hosturl.port : undefined,
130
+ ssl: hosturl.scheme.toLowerCase() === "https",
131
+ headers: {},
132
+ };
133
+ httpParams.options = httpOptions;
134
+ if (config.ignoresslerror) {
135
+ httpOptions.rejectUnauthorized = false;
136
+ }
137
+ if (config.auth_type === LoggerServiceTypes_1.RestAuthType.none) { }
138
+ if (config.auth_type === LoggerServiceTypes_1.RestAuthType.basic) {
139
+ httpParams.auth = {
140
+ username: config.auth_basic_username,
141
+ password: config.auth_basic_password
142
+ };
143
+ }
144
+ if (config.auth_type === LoggerServiceTypes_1.RestAuthType.apikey) {
145
+ if (config.auth_apikey_mechanism === LoggerServiceTypes_1.ApiKeyMechanismType.header) {
146
+ httpParams.headers[config.auth_apikey_name] = config.auth_apikey_value;
147
+ }
148
+ if (config.auth_apikey_mechanism === LoggerServiceTypes_1.ApiKeyMechanismType.matrixparam) {
149
+ httpParams.path = httpParams.path?.replace(`:${config.auth_apikey_name}`, config.auth_apikey_value);
150
+ }
151
+ if (config.auth_apikey_mechanism === LoggerServiceTypes_1.ApiKeyMechanismType.queryparam) {
152
+ httpParams.path = httpParams.path + (httpParams.path?.includes("?") ? "&" : "?") + config.auth_apikey_name + "=" + config.auth_apikey_value;
153
+ }
154
+ }
155
+ ;
156
+ this.logger = (0, winston_1.createLogger)({
157
+ level: config.level.toString().toLowerCase(),
158
+ format: winston_1.format.json(),
159
+ defaultMeta: {},
160
+ transports: [
161
+ new winston_1.transports.Http(httpParams),
162
+ ],
163
+ });
164
+ }
165
+ writeToLog(serializedContent, tags) {
166
+ this.logger.log({ level: this.logger.level, message: serializedContent, labels: tags });
167
+ }
168
+ }
169
+ let LoggerTypes = {
170
+ console: ConsoleLogger,
171
+ loki: LokiLogger,
172
+ rest: RestLogger
173
+ };
174
+ class LoggerService extends NodeConstructor_1.BaseService {
175
+ constructor() {
176
+ super("logger");
177
+ }
178
+ init(red) {
179
+ this.red = red;
180
+ return new Promise((resolve) => {
181
+ network.get_active_interface((err, obj) => {
182
+ LoggerService.instanceID = obj.ip_address;
183
+ });
184
+ });
185
+ }
186
+ deinit(red) { }
187
+ static get(config) {
188
+ let logger = this.loggers[config.id];
189
+ if (logger) {
190
+ if (!(0, deep_equal_1.default)(config, logger.config())) {
191
+ this.loggers[config.id] = (logger = new (LoggerTypes[config.type])(config));
192
+ }
193
+ }
194
+ else {
195
+ this.loggers[config.id] = (logger = new (LoggerTypes[config.type])(config));
196
+ }
197
+ return logger;
198
+ }
199
+ static getServiceDescriptor() {
200
+ return new NodeConstructor_1.ServiceDescriptor("@theotherwillembotha/loggerservice", "LoggerService", "services-plugin", "@theotherwillembotha/node-red-plugincore", LoggerService, [LoggerConfigNode_1.LoggerConfigNode, LoggerTemplate_1.LoggerTemplate]);
201
+ }
202
+ }
203
+ exports.LoggerService = LoggerService;
204
+ LoggerService.loggers = {};
@@ -0,0 +1,24 @@
1
+ export declare enum Level {
2
+ DEBUG = "DEBUG",
3
+ INFO = "INFO",
4
+ WARNING = "WARNING",
5
+ ERROR = "ERROR"
6
+ }
7
+ export declare enum PlatformType {
8
+ console = "console",
9
+ rest = "rest",
10
+ loki = "loki",
11
+ elasticsearch = "elasticsearch",
12
+ datadog = "datadog"
13
+ }
14
+ export declare enum RestAuthType {
15
+ none = "none",
16
+ basic = "basic",
17
+ apikey = "apikey"
18
+ }
19
+ export declare enum ApiKeyMechanismType {
20
+ header = "header",
21
+ queryparam = "queryparam",
22
+ matrixparam = "matrixparam"
23
+ }
24
+ //# sourceMappingURL=LoggerServiceTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoggerServiceTypes.d.ts","sourceRoot":"","sources":["../../../../src/core/logger/service/LoggerServiceTypes.ts"],"names":[],"mappings":"AAAA,oBAAY,KAAK;IACb,KAAK,UAAU;IACf,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,KAAK,UAAU;CAClB;AAED,oBAAY,YAAY;IACpB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,aAAa,kBAAkB;IAC/B,OAAO,YAAY;CACtB;AAED,oBAAY,YAAY;IACpB,IAAI,SAAO;IACX,KAAK,UAAQ;IACb,MAAM,WAAS;CAClB;AAED,oBAAY,mBAAmB;IAC3B,MAAM,WAAS;IACf,UAAU,eAAa;IACvB,WAAW,gBAAc;CAC5B"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApiKeyMechanismType = exports.RestAuthType = exports.PlatformType = exports.Level = void 0;
4
+ var Level;
5
+ (function (Level) {
6
+ Level["DEBUG"] = "DEBUG";
7
+ Level["INFO"] = "INFO";
8
+ Level["WARNING"] = "WARNING";
9
+ Level["ERROR"] = "ERROR";
10
+ })(Level || (exports.Level = Level = {}));
11
+ var PlatformType;
12
+ (function (PlatformType) {
13
+ PlatformType["console"] = "console";
14
+ PlatformType["rest"] = "rest";
15
+ PlatformType["loki"] = "loki";
16
+ PlatformType["elasticsearch"] = "elasticsearch";
17
+ PlatformType["datadog"] = "datadog";
18
+ })(PlatformType || (exports.PlatformType = PlatformType = {}));
19
+ var RestAuthType;
20
+ (function (RestAuthType) {
21
+ RestAuthType["none"] = "none";
22
+ RestAuthType["basic"] = "basic";
23
+ RestAuthType["apikey"] = "apikey";
24
+ })(RestAuthType || (exports.RestAuthType = RestAuthType = {}));
25
+ var ApiKeyMechanismType;
26
+ (function (ApiKeyMechanismType) {
27
+ ApiKeyMechanismType["header"] = "header";
28
+ ApiKeyMechanismType["queryparam"] = "queryparam";
29
+ ApiKeyMechanismType["matrixparam"] = "matrixparam";
30
+ })(ApiKeyMechanismType || (exports.ApiKeyMechanismType = ApiKeyMechanismType = {}));
@@ -0,0 +1,11 @@
1
+ import { BaseNodeConfig, Template, TemplateDescriptor } from "../../NodeConstructor";
2
+ export interface LoggerTemplateConfig extends BaseNodeConfig {
3
+ logEnabled: boolean;
4
+ logger: string;
5
+ logTemplateOverrideEnabled: boolean;
6
+ logTemplateOverride: string;
7
+ }
8
+ export declare class LoggerTemplate extends Template {
9
+ static getTemplateDescriptor(): TemplateDescriptor;
10
+ }
11
+ //# sourceMappingURL=LoggerTemplate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoggerTemplate.d.ts","sourceRoot":"","sources":["../../../../src/core/logger/template/LoggerTemplate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAGpF,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IACxD,UAAU,EAAC,OAAO,CAAC;IACnB,MAAM,EAAC,MAAM,CAAC;IACd,0BAA0B,EAAC,OAAO,CAAC;IACnC,mBAAmB,EAAC,MAAM,CAAC;CAC9B;AAED,qBAAa,cAAe,SAAQ,QAAQ;IAGxC,MAAM,CAAC,qBAAqB,IAAI,kBAAkB;CAQrD"}