@theotherwillembotha/node-red-plugincore 0.0.54 → 0.1.0

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 (93) hide show
  1. package/README.md +9 -9
  2. package/build/GenerateNodes.js +0 -1
  3. package/build/Nodes.html +23 -162
  4. package/build/Nodes.js +0 -2
  5. package/build/Plugins.js +2 -3
  6. package/build/core/NodeConstructor.d.ts +1 -0
  7. package/build/core/NodeConstructor.d.ts.map +1 -1
  8. package/build/core/NodeConstructor.js +20 -62
  9. package/build/core/NodeGenerator.d.ts.map +1 -1
  10. package/build/core/NodeGenerator.js +8 -11
  11. package/build/core/logger/LoggerDecorator.d.ts.map +1 -1
  12. package/build/core/logger/LoggerDecorator.js +34 -38
  13. package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts +11 -7
  14. package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts.map +1 -1
  15. package/build/core/logger/node/ConsoleLoggerConfigNode.js +24 -10
  16. package/build/core/logger/node/RestLoggerConfigNode.d.ts +22 -6
  17. package/build/core/logger/node/RestLoggerConfigNode.d.ts.map +1 -1
  18. package/build/core/logger/node/RestLoggerConfigNode.js +93 -23
  19. package/build/core/logger/service/LoggerService.d.ts +59 -68
  20. package/build/core/logger/service/LoggerService.d.ts.map +1 -1
  21. package/build/core/logger/service/LoggerService.js +76 -165
  22. package/build/core/logger/template/LoggerTemplate.d.ts +9 -1
  23. package/build/core/logger/template/LoggerTemplate.d.ts.map +1 -1
  24. package/build/core/metrics/node/CounterMetricConfigNode.js +0 -2
  25. package/build/core/metrics/node/GaugeMetricConfigNode.js +0 -2
  26. package/build/core/metrics/node/MetricsConfigNode.js +0 -1
  27. package/build/core/metrics/node/TimerMetricConfigNode.js +0 -2
  28. package/build/core/metrics/service/MetricsService.js +10 -24
  29. package/build/core/other/service/SettingsService.js +0 -2
  30. package/build/core/tagging/service/NodeTypeService.js +1 -2
  31. package/build/core/webhook/WebhookDecorator.d.ts.map +1 -1
  32. package/build/core/webhook/WebhookDecorator.js +47 -10
  33. package/build/core/webhook/node/WebhookServerConfigNode.js +0 -1
  34. package/build/core/webhook/service/ReverseProxyTypeService.d.ts +1 -2
  35. package/build/core/webhook/service/ReverseProxyTypeService.d.ts.map +1 -1
  36. package/build/core/webhook/service/ReverseProxyTypeService.js +1 -6
  37. package/build/core/webhook/service/WebhookServerService.d.ts +1 -1
  38. package/build/core/webhook/service/WebhookServerService.d.ts.map +1 -1
  39. package/build/core/webhook/service/WebhookServerService.js +6 -14
  40. package/build/core/webhook/template/WebhookTemplate.d.ts +1 -1
  41. package/build/core/webhook/template/WebhookTemplate.d.ts.map +1 -1
  42. package/build/index.d.ts +1 -2
  43. package/build/index.d.ts.map +1 -1
  44. package/build/index.js +1 -2
  45. package/build/resources/editorLanguageExtension.js +1 -2
  46. package/package.json +6 -5
  47. package/resources/editorLanguageExtension.js +1 -2
  48. package/src/GenerateNodes.ts +2 -2
  49. package/src/core/NodeConstructor.ts +7 -14
  50. package/src/core/NodeGenerator.ts +2 -3
  51. package/src/core/logger/LoggerDecorator.ts +56 -53
  52. package/src/core/logger/node/ConsoleLoggerConfigNode.ts +39 -14
  53. package/src/core/logger/node/RestLoggerConfigNode.ts +128 -25
  54. package/src/core/logger/service/LoggerService.ts +103 -239
  55. package/src/core/logger/template/LoggerTemplate.html +2 -2
  56. package/src/core/logger/template/LoggerTemplate.ts +11 -1
  57. package/src/core/metrics/node/TimerMetricConfigNode.html +2 -2
  58. package/src/core/other/template/BasicTemplate.html +5 -2
  59. package/src/core/webhook/WebhookDecorator.ts +54 -13
  60. package/src/core/webhook/service/ReverseProxyTypeService.ts +1 -4
  61. package/src/core/webhook/service/WebhookServerService.ts +1 -6
  62. package/src/core/webhook/template/WebhookTemplate.html +1 -1
  63. package/src/core/webhook/template/WebhookTemplate.ts +1 -1
  64. package/src/index.ts +2 -2
  65. package/build/core/logger/node/ConsoleLoggerConfigNode.html +0 -90
  66. package/build/core/logger/node/LokiLoggerConfigNode.d.ts +0 -20
  67. package/build/core/logger/node/LokiLoggerConfigNode.d.ts.map +0 -1
  68. package/build/core/logger/node/LokiLoggerConfigNode.html +0 -117
  69. package/build/core/logger/node/LokiLoggerConfigNode.js +0 -53
  70. package/build/core/logger/node/RestLoggerConfigNode.html +0 -183
  71. package/build/core/logger/service/LoggerServiceTypes.d.ts +0 -24
  72. package/build/core/logger/service/LoggerServiceTypes.d.ts.map +0 -1
  73. package/build/core/logger/service/LoggerServiceTypes.js +0 -30
  74. package/build/core/logger/template/LoggerTemplate.html +0 -331
  75. package/build/core/metrics/node/CounterMetricConfigNode.html +0 -48
  76. package/build/core/metrics/node/GaugeMetricConfigNode.html +0 -48
  77. package/build/core/metrics/node/MetricsConfigNode.html +0 -21
  78. package/build/core/metrics/node/TimerMetricConfigNode.html +0 -190
  79. package/build/core/metrics/template/CounterMetricTemplate.html +0 -40
  80. package/build/core/metrics/template/GaugeMetricTemplate.html +0 -39
  81. package/build/core/metrics/template/MetricsTemplate.html +0 -54
  82. package/build/core/metrics/template/TimerMetricTemplate.html +0 -39
  83. package/build/core/other/node/DelegatedConfigReferenceNode.html +0 -1
  84. package/build/core/other/template/BasicTemplate.html +0 -76
  85. package/build/core/other/template/SettingsTemplate.html +0 -128
  86. package/build/core/ui/template/ScriptEditorTemplate.html +0 -50
  87. package/build/core/ui/template/UIHelperTemplate.html +0 -229
  88. package/build/core/webhook/node/WebhookServerConfigNode.html +0 -61
  89. package/build/core/webhook/template/WebhookTemplate.html +0 -442
  90. package/documentation/LokiLoggerConfigNode.png +0 -0
  91. package/src/core/logger/node/LokiLoggerConfigNode.html +0 -117
  92. package/src/core/logger/node/LokiLoggerConfigNode.ts +0 -58
  93. package/src/core/logger/service/LoggerServiceTypes.ts +0 -26
@@ -3,185 +3,83 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.LoggerService = exports.NewLogger = exports.LogImplementation = void 0;
6
+ exports.DoNothingAppender = exports.LoggerConfigNode = exports.LoggerService = exports.AbstractLogger = exports.Log = exports.ApiKeyMechanismType = exports.RestAuthType = exports.Level = void 0;
7
7
  const NodeConstructor_1 = require("../../NodeConstructor");
8
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
9
  const LoggerTemplate_1 = require("../template/LoggerTemplate");
13
10
  var network = require('network');
14
- const deep_equal_1 = __importDefault(require("deep-equal"));
15
- const LoggerServiceTypes_1 = require("./LoggerServiceTypes");
16
11
  // helper for serializing json objects inside handlebars tags.
17
12
  // you can then convert it like this: {{{json myobject}}}
18
13
  handlebars_1.default.registerHelper('json', function (context) {
19
14
  return JSON.stringify(context);
20
15
  });
21
- class LogImplementation {
22
- root;
23
- config;
24
- template;
25
- tagMap;
26
- constructor(root, config) {
27
- this.root = root;
28
- this.config = config;
29
- this.template = (config.override && config.template) ? handlebars_1.default.compile(config.template) : undefined;
30
- this.tagMap = {
31
- instance: LoggerService.instanceID,
32
- flow: config.flow,
16
+ var Level;
17
+ (function (Level) {
18
+ Level["DEBUG"] = "DEBUG";
19
+ Level["INFO"] = "INFO";
20
+ Level["WARNING"] = "WARNING";
21
+ Level["ERROR"] = "ERROR";
22
+ })(Level || (exports.Level = Level = {}));
23
+ var RestAuthType;
24
+ (function (RestAuthType) {
25
+ RestAuthType["none"] = "none";
26
+ RestAuthType["basic"] = "basic";
27
+ RestAuthType["apikey"] = "apikey";
28
+ })(RestAuthType || (exports.RestAuthType = RestAuthType = {}));
29
+ var ApiKeyMechanismType;
30
+ (function (ApiKeyMechanismType) {
31
+ ApiKeyMechanismType["header"] = "header";
32
+ ApiKeyMechanismType["queryparam"] = "queryparam";
33
+ ApiKeyMechanismType["matrixparam"] = "matrixparam";
34
+ })(ApiKeyMechanismType || (exports.ApiKeyMechanismType = ApiKeyMechanismType = {}));
35
+ class Log {
36
+ constructor(config) {
37
+ this._config = config;
38
+ this.template = handlebars_1.default.compile(config.template);
39
+ this.tags = {
40
+ id: config.id,
33
41
  node: config.name,
34
42
  type: config.type,
35
- id: config.id,
36
- };
37
- }
38
- log(message) {
39
- // enrich the logged content with additional properties.
40
- let content = {
41
- currentTime: new Date().toISOString(),
42
- msg: message,
43
+ flow: config.flow,
44
+ instance: LoggerService.instanceID
43
45
  };
44
- // send typ the logger.
45
- this.root.log(this, content);
46
- }
47
- serialize(content) {
48
- return !!this.template ? this.template(content) : this.root.serialize(content);
49
46
  }
50
- getTags() {
51
- return this.tagMap;
52
- }
53
- }
54
- exports.LogImplementation = LogImplementation;
55
- class NewLogger {
56
- _config;
57
- template;
58
- constructor(config) {
59
- this._config = config;
60
- this.template = handlebars_1.default.compile(config.template);
47
+ config() {
48
+ return this._config;
61
49
  }
62
- log(reference, content) {
50
+ log(payload) {
63
51
  try {
64
- // step 1, attempt to serialize the content.
65
- let serializedContent = reference.serialize(content);
66
- // step 2, get the tags.
67
- let tags = reference.getTags();
68
- // step 3. write to the logger.
69
- this.writeToLog(serializedContent, tags);
52
+ // step 1. serialize the payload using the template engine.
53
+ let message = (payload instanceof String) ? payload : this.template({ msg: payload });
54
+ // step 2. write to the log appender.
55
+ this.writeToLog(this.config().level, message, this.tags);
70
56
  }
71
- catch (exception) {
72
- console.log(exception.message);
57
+ catch (e) {
58
+ console.log(e);
73
59
  }
74
60
  }
75
- register(registration) {
76
- return new LogImplementation(this, registration);
77
- }
78
- serialize(content) {
79
- return this.template(content);
80
- }
81
- config() {
82
- return this._config;
83
- }
84
- }
85
- exports.NewLogger = NewLogger;
86
- class ConsoleLogger extends NewLogger {
87
- constructor(config) {
88
- super(config);
89
- }
90
- writeToLog(serializedContent, tags) {
91
- console.log(tags, serializedContent);
92
- }
93
61
  }
94
- class LokiLogger extends NewLogger {
95
- logger;
62
+ exports.Log = Log;
63
+ class AbstractLogger {
96
64
  constructor(config) {
97
- super(config);
98
- let transportConfig = {
99
- host: config.host,
100
- json: true,
101
- format: winston_1.format.json(),
102
- headers: {
103
- "X-Scope-OrgID": (config.tenantid) ? config.tenantid : undefined
104
- },
105
- replaceTimestamp: true,
106
- onConnectionError: (err) => console.error(err),
107
- basicAuth: (config.userid && config.authtoken)
108
- ? `${config.userid}:${config.authtoken}`
109
- : undefined
110
- };
111
- this.logger = (0, winston_1.createLogger)({
112
- level: this.config().level.toString().toLowerCase(),
113
- format: winston_1.format.json(),
114
- defaultMeta: {},
115
- transports: [
116
- new winston_loki_1.default(transportConfig),
117
- ],
118
- });
65
+ this._appenders = {};
66
+ this._config = config;
119
67
  }
120
- writeToLog(serializedContent, tags) {
121
- this.logger.log({ message: serializedContent, level: this.logger.level, labels: tags });
68
+ config() {
69
+ return this._config;
122
70
  }
123
- }
124
- class RestLogger extends NewLogger {
125
- logger;
126
- constructor(config) {
127
- super(config);
128
- let hosturl = (0, whatwg_url_1.parseURL)(config.url);
129
- if (!hosturl) {
130
- throw Error("could not parse url: " + config.url);
71
+ registerTemplate(config) {
72
+ let appender = this._appenders[config.id];
73
+ if (appender) {
74
+ return appender;
131
75
  }
132
- let httpOptions = {};
133
- let httpParams = {
134
- host: hosturl.host?.toString(),
135
- path: "/" + (hosturl.path ? [...hosturl.path].join("/") : "") + (hosturl.query ? ("?" + hosturl.query) : ""),
136
- port: (hosturl.port) ? hosturl.port : undefined,
137
- ssl: hosturl.scheme.toLowerCase() === "https",
138
- headers: {},
139
- };
140
- httpParams.options = httpOptions;
141
- if (config.ignoresslerror) {
142
- httpOptions.rejectUnauthorized = false;
143
- }
144
- if (config.auth_type === LoggerServiceTypes_1.RestAuthType.none) { }
145
- if (config.auth_type === LoggerServiceTypes_1.RestAuthType.basic) {
146
- httpParams.auth = {
147
- username: config.auth_basic_username,
148
- password: config.auth_basic_password
149
- };
150
- }
151
- if (config.auth_type === LoggerServiceTypes_1.RestAuthType.apikey) {
152
- if (config.auth_apikey_mechanism === LoggerServiceTypes_1.ApiKeyMechanismType.header) {
153
- httpParams.headers[config.auth_apikey_name] = config.auth_apikey_value;
154
- }
155
- if (config.auth_apikey_mechanism === LoggerServiceTypes_1.ApiKeyMechanismType.matrixparam) {
156
- httpParams.path = httpParams.path?.replace(`:${config.auth_apikey_name}`, config.auth_apikey_value);
157
- }
158
- if (config.auth_apikey_mechanism === LoggerServiceTypes_1.ApiKeyMechanismType.queryparam) {
159
- httpParams.path = httpParams.path + (httpParams.path?.includes("?") ? "&" : "?") + config.auth_apikey_name + "=" + config.auth_apikey_value;
160
- }
161
- }
162
- ;
163
- this.logger = (0, winston_1.createLogger)({
164
- level: config.level.toString().toLowerCase(),
165
- format: winston_1.format.json(),
166
- defaultMeta: {},
167
- transports: [
168
- new winston_1.transports.Http(httpParams),
169
- ],
170
- });
171
- }
172
- writeToLog(serializedContent, tags) {
173
- this.logger.log({ level: this.logger.level, message: serializedContent, labels: tags });
76
+ let _this = this;
77
+ this._appenders[config.id] = appender = this.createLogger(config);
78
+ return appender;
174
79
  }
175
80
  }
176
- let LoggerTypes = {
177
- console: ConsoleLogger,
178
- loki: LokiLogger,
179
- rest: RestLogger
180
- };
81
+ exports.AbstractLogger = AbstractLogger;
181
82
  class LoggerService extends NodeConstructor_1.BaseService {
182
- static instanceID;
183
- static loggers = {};
184
- red;
185
83
  constructor() {
186
84
  super("logger");
187
85
  }
@@ -194,20 +92,33 @@ class LoggerService extends NodeConstructor_1.BaseService {
194
92
  });
195
93
  }
196
94
  deinit(red) { }
197
- static get(config) {
198
- let logger = this.loggers[config.id];
199
- if (logger) {
200
- if (!(0, deep_equal_1.default)(config, logger.config())) {
201
- this.loggers[config.id] = (logger = new (LoggerTypes[config.type])(config));
202
- }
203
- }
204
- else {
205
- this.loggers[config.id] = (logger = new (LoggerTypes[config.type])(config));
206
- }
207
- return logger;
208
- }
209
95
  static getServiceDescriptor() {
210
96
  return new NodeConstructor_1.ServiceDescriptor("@theotherwillembotha/loggerservice", "LoggerService", "services-plugin", "@theotherwillembotha/node-red-plugincore", LoggerService, [LoggerTemplate_1.LoggerTemplate]);
211
97
  }
212
98
  }
213
99
  exports.LoggerService = LoggerService;
100
+ class LoggerConfigNode extends NodeConstructor_1.ConfigNode {
101
+ constructor(node, config) {
102
+ super(node, config);
103
+ }
104
+ registerTemplate(config) {
105
+ return this.logger().registerTemplate(config);
106
+ }
107
+ }
108
+ exports.LoggerConfigNode = LoggerConfigNode;
109
+ class DoNothingAppender extends Log {
110
+ static { this.instance = new DoNothingAppender(); }
111
+ static get() {
112
+ return DoNothingAppender.instance;
113
+ }
114
+ constructor() {
115
+ super({ flow: "", id: "", level: "", name: "", template: "", type: "" });
116
+ }
117
+ log(payload) {
118
+ // do nothing.
119
+ }
120
+ writeToLog(level, message, tags) {
121
+ // do nothing.
122
+ }
123
+ }
124
+ exports.DoNothingAppender = DoNothingAppender;
@@ -1,10 +1,18 @@
1
1
  import { BaseNodeConfig, Template, TemplateDescriptor } from "../../NodeConstructor";
2
- export interface LoggerTemplateConfig extends BaseNodeConfig {
2
+ export interface LoggerTemplateNodeConfig extends BaseNodeConfig {
3
3
  logEnabled: boolean;
4
4
  logger: string;
5
5
  logTemplateOverrideEnabled: boolean;
6
6
  logTemplateOverride: string;
7
7
  }
8
+ export type LoggerTemplateConfig = {
9
+ id: string;
10
+ flow: string;
11
+ type: string;
12
+ name: string;
13
+ template: string;
14
+ level: string;
15
+ };
8
16
  export declare class LoggerTemplate extends Template {
9
17
  static getTemplateDescriptor(): TemplateDescriptor;
10
18
  }
@@ -1 +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;AAEpF,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"}
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,wBAAyB,SAAQ,cAAc;IAC5D,UAAU,EAAC,OAAO,CAAC;IACnB,MAAM,EAAC,MAAM,CAAC;IACd,0BAA0B,EAAC,OAAO,CAAC;IACnC,mBAAmB,EAAC,MAAM,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAAG;IAC/B,EAAE,EAAC,MAAM,CAAC;IACV,IAAI,EAAC,MAAM,CAAC;IACZ,IAAI,EAAC,MAAM,CAAC;IACZ,IAAI,EAAC,MAAM,CAAC;IACZ,QAAQ,EAAC,MAAM,CAAC;IAChB,KAAK,EAAC,MAAM,CAAC;CAChB,CAAA;AAED,qBAAa,cAAe,SAAQ,QAAQ;IAGxC,MAAM,CAAC,qBAAqB,IAAI,kBAAkB;CAQrD"}
@@ -17,8 +17,6 @@ const MetricsConfigNode_1 = require("./MetricsConfigNode");
17
17
  const MetricsTemplate_1 = require("../template/MetricsTemplate");
18
18
  const NodeDescriptionDecorator_1 = require("../../tagging/NodeDescriptionDecorator");
19
19
  let CounterMetricConfigNode = class CounterMetricConfigNode extends NodeConstructor_1.ConfigNode {
20
- _metrics;
21
- _counter;
22
20
  constructor(node, config) {
23
21
  super(node, config);
24
22
  let _this = this;
@@ -17,8 +17,6 @@ const MetricsConfigNode_1 = require("./MetricsConfigNode");
17
17
  const MetricsTemplate_1 = require("../template/MetricsTemplate");
18
18
  const NodeDescriptionDecorator_1 = require("../../tagging/NodeDescriptionDecorator");
19
19
  let GaugeMetricConfigNode = class GaugeMetricConfigNode extends NodeConstructor_1.ConfigNode {
20
- _metrics;
21
- _gauge;
22
20
  constructor(node, config) {
23
21
  super(node, config);
24
22
  let _this = this;
@@ -19,7 +19,6 @@ const WebhookServerService_1 = require("../../webhook/service/WebhookServerServi
19
19
  const prom_client_1 = require("prom-client");
20
20
  const NodeDescriptionDecorator_1 = require("../../tagging/NodeDescriptionDecorator");
21
21
  let MetricsConfigNode = class MetricsConfigNode extends NodeConstructor_1.ConfigNode {
22
- _metrics;
23
22
  constructor(node, config) {
24
23
  super(node, config);
25
24
  let _this = this;
@@ -18,8 +18,6 @@ const MetricsTemplate_1 = require("../template/MetricsTemplate");
18
18
  const MetricsDecorator_1 = require("../MetricsDecorator");
19
19
  const NodeDescriptionDecorator_1 = require("../../tagging/NodeDescriptionDecorator");
20
20
  let TimerMetricConfigNode = class TimerMetricConfigNode extends NodeConstructor_1.ConfigNode {
21
- _metrics;
22
- _timer;
23
21
  constructor(node, config) {
24
22
  super(node, config);
25
23
  let _this = this;
@@ -41,8 +41,6 @@ const NodeConstructor_1 = require("../../NodeConstructor");
41
41
  const prom_client_1 = __importStar(require("prom-client"));
42
42
  const deep_equal_1 = __importDefault(require("deep-equal"));
43
43
  class Metric {
44
- _config;
45
- _labels;
46
44
  constructor(config) {
47
45
  this._config = config;
48
46
  this._labels = { flow: config.node.flow, type: config.node.type, name: config.node.name, id: config.node.id, metric: config.metricname };
@@ -56,11 +54,9 @@ class Metric {
56
54
  }
57
55
  exports.Metric = Metric;
58
56
  class CounterMetric extends Metric {
59
- counter;
60
- internalCounter;
61
- subscribers = {};
62
57
  constructor(id, config, registry) {
63
58
  super(config);
59
+ this.subscribers = {};
64
60
  this.counter = new prom_client_1.Counter({
65
61
  name: id,
66
62
  help: (config.metricdescription) ? config.metricdescription : config.metricname,
@@ -90,11 +86,10 @@ class CounterMetric extends Metric {
90
86
  }
91
87
  exports.CounterMetric = CounterMetric;
92
88
  class GaugeMetric extends Metric {
93
- collector = 0;
94
- gauge;
95
- subscribers = {};
96
89
  constructor(id, config, registry) {
97
90
  super(config);
91
+ this.collector = 0;
92
+ this.subscribers = {};
98
93
  let _this = this;
99
94
  this.gauge = new prom_client_1.default.Gauge({
100
95
  name: id,
@@ -142,10 +137,9 @@ var BucketType;
142
137
  BucketType["exponential"] = "exponential";
143
138
  })(BucketType || (exports.BucketType = BucketType = {}));
144
139
  class HistogramMetric extends Metric {
145
- histogram;
146
- subscribers = {};
147
140
  constructor(id, config, registry) {
148
141
  super(config);
142
+ this.subscribers = {};
149
143
  // Build the Histogram Config.
150
144
  let histogramConfig = {
151
145
  name: id,
@@ -188,8 +182,6 @@ class HistogramMetric extends Metric {
188
182
  }
189
183
  exports.HistogramMetric = HistogramMetric;
190
184
  class HistogramState {
191
- _values;
192
- _average;
193
185
  constructor(values) {
194
186
  this._values = values;
195
187
  let sum = this._values.find(value => value.metricName?.endsWith("_sum"))?.value;
@@ -201,8 +193,6 @@ class HistogramState {
201
193
  }
202
194
  }
203
195
  class SummaryState {
204
- _values;
205
- _average;
206
196
  constructor(values) {
207
197
  this._values = values;
208
198
  let sum = this._values.find(value => value.metricName?.endsWith("_sum"))?.value;
@@ -219,10 +209,9 @@ var PercentileType;
219
209
  PercentileType["manual"] = "manual";
220
210
  })(PercentileType || (exports.PercentileType = PercentileType = {}));
221
211
  class SummaryMetric extends Metric {
222
- summary;
223
- subscribers = {};
224
212
  constructor(id, config, registry) {
225
213
  super(config);
214
+ this.subscribers = {};
226
215
  let summaryConfig = {
227
216
  name: id,
228
217
  help: (config.metricdescription) ? config.metricdescription : config.metricname,
@@ -257,13 +246,11 @@ class SummaryMetric extends Metric {
257
246
  }
258
247
  exports.SummaryMetric = SummaryMetric;
259
248
  class MetricsContainer {
260
- _config;
261
- _registry;
262
- counters = {};
263
- histograms = {};
264
- gauges = {};
265
- summaries = {};
266
249
  constructor(config) {
250
+ this.counters = {};
251
+ this.histograms = {};
252
+ this.gauges = {};
253
+ this.summaries = {};
267
254
  this._config = config;
268
255
  // create a registry with the config.
269
256
  this._registry = new prom_client_1.default.Registry();
@@ -341,8 +328,7 @@ class MetricsContainer {
341
328
  }
342
329
  exports.MetricsContainer = MetricsContainer;
343
330
  class MetricsService extends NodeConstructor_1.BaseService {
344
- static metrics = {};
345
- red;
331
+ static { this.metrics = {}; }
346
332
  constructor() {
347
333
  super("MetricsService");
348
334
  }
@@ -38,8 +38,6 @@ class SettingsService extends NodeConstructor_1.BaseService {
38
38
  }
39
39
  exports.SettingsService = SettingsService;
40
40
  class Settings {
41
- _settings;
42
- _config;
43
41
  constructor(settings, config) {
44
42
  this._settings = settings;
45
43
  this._config = config;
@@ -3,10 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NodeTypeService = void 0;
4
4
  const NodeConstructor_1 = require("../../NodeConstructor");
5
5
  class NodeTypeService extends NodeConstructor_1.BaseService {
6
- red;
7
- nodeTypes = {};
8
6
  constructor() {
9
7
  super("nodetypes");
8
+ this.nodeTypes = {};
10
9
  }
11
10
  init(red) {
12
11
  this.red = red;
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookDecorator.d.ts","sourceRoot":"","sources":["../../../src/core/webhook/WebhookDecorator.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,OAAO,KAoDD,CAAC;AAGb,OAAO,EACH,OAAO,EACV,CAAA"}
1
+ {"version":3,"file":"WebhookDecorator.d.ts","sourceRoot":"","sources":["../../../src/core/webhook/WebhookDecorator.ts"],"names":[],"mappings":"AAqBA,QAAA,MAAM,OAAO,KAoFD,CAAC;AAGb,OAAO,EACH,OAAO,EACV,CAAA"}
@@ -1,17 +1,24 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Webhook = void 0;
4
- const LoggerServiceTypes_1 = require("../logger/service/LoggerServiceTypes");
7
+ const os_1 = __importDefault(require("os"));
8
+ const LoggerService_1 = require("../logger/service/LoggerService");
5
9
  const NodeConstructor_1 = require("../NodeConstructor");
10
+ const ReverseProxyTypeService_1 = require("./service/ReverseProxyTypeService");
11
+ // In-memory registry: nodeId → managed proxy host entries from the last deploy.
12
+ const managedProxyHosts = new Map();
6
13
  const Webhook = (0, NodeConstructor_1.createPostConstructDecorator)('Webhook')
7
14
  .withInitLogic(async (instance, propertyKey, webhookconfig) => {
8
15
  //console.log(`Registering webhook callback`, "PROPERTYKEY", propertyKey, "WEBHOOK CONFIG", webhookconfig, "THIS", this);
9
16
  let node = instance;
10
17
  let nodeConfig = node.config();
11
18
  // create the authentication.
12
- let authentication = (nodeConfig.webhookAuth === LoggerServiceTypes_1.RestAuthType.basic) ? { type: LoggerServiceTypes_1.RestAuthType.basic, username: nodeConfig.webhookAuth_basic_username, password: nodeConfig.webhookAuth_basic_password } :
13
- (nodeConfig.webhookAuth === LoggerServiceTypes_1.RestAuthType.apikey) ? { type: LoggerServiceTypes_1.RestAuthType.apikey, mechanism: nodeConfig.webhookAuth_apikey_mechanism, key: nodeConfig.webhookAuth_apikey_key, value: nodeConfig.webhookAuth_apikey_value } :
14
- { type: LoggerServiceTypes_1.RestAuthType.none };
19
+ let authentication = (nodeConfig.webhookAuth === LoggerService_1.RestAuthType.basic) ? { type: LoggerService_1.RestAuthType.basic, username: nodeConfig.webhookAuth_basic_username, password: nodeConfig.webhookAuth_basic_password } :
20
+ (nodeConfig.webhookAuth === LoggerService_1.RestAuthType.apikey) ? { type: LoggerService_1.RestAuthType.apikey, mechanism: nodeConfig.webhookAuth_apikey_mechanism, key: nodeConfig.webhookAuth_apikey_key, value: nodeConfig.webhookAuth_apikey_value } :
21
+ { type: LoggerService_1.RestAuthType.none };
15
22
  // register a callback listener to the webserver.
16
23
  let endpointConfig = {
17
24
  path: nodeConfig.webhookPath,
@@ -21,20 +28,50 @@ const Webhook = (0, NodeConstructor_1.createPostConstructDecorator)('Webhook')
21
28
  let webhookServer = NodeConstructor_1.NodeManager.RED.nodes.getNode(nodeConfig.webhook).node().server();
22
29
  webhookServer.attach(endpointConfig, (request, respponse) => instance[propertyKey](request, respponse));
23
30
  if (nodeConfig.reverseProxies_enabled) {
31
+ let targetPort = webhookServer.config().port;
32
+ let targetHost = os_1.default.hostname();
33
+ let nodeId = nodeConfig.id;
34
+ let newlyManaged = [];
24
35
  await Promise.all(nodeConfig.reverseProxies_connections.map(async (proxy) => {
25
36
  try {
26
- // get a n instance of reverseProxNode.
27
- let reverseProxyNode = NodeConstructor_1.NodeManager.RED.nodes.getNode(proxy.proxy).node();
28
37
  // TODO: ReverseProxyConfigNodes need to become their own subtype of config nodes so we can enforce the ".client()" method.
38
+ let reverseProxyNode = NodeConstructor_1.NodeManager.RED.nodes.getNode(proxy.proxy).node();
39
+ let proxyClient = reverseProxyNode.client();
40
+ let hosts = await proxyClient.getHosts();
41
+ let matchingHost = hosts.find(h => h.domainNames?.includes(proxy.domainname));
42
+ if (!matchingHost) {
43
+ await proxyClient.updateHost({ domainNames: [proxy.domainname], forwardHost: targetHost, forwardPort: targetPort, scheme: ReverseProxyTypeService_1.HTTPScheme.HTTP });
44
+ // Fetch again to get the assigned ID of the newly created entry.
45
+ let updatedHosts = await proxyClient.getHosts();
46
+ matchingHost = updatedHosts.find(h => h.domainNames?.includes(proxy.domainname));
47
+ }
48
+ else if (matchingHost.forwardHost !== targetHost || matchingHost.forwardPort !== targetPort) {
49
+ await proxyClient.updateHost({ id: matchingHost.id, forwardHost: targetHost, forwardPort: targetPort, scheme: ReverseProxyTypeService_1.HTTPScheme.HTTP });
50
+ }
51
+ if (matchingHost?.id !== undefined) {
52
+ newlyManaged.push({ proxyNodeId: proxy.proxy, hostId: matchingHost.id });
53
+ }
54
+ }
55
+ catch (e) {
56
+ console.error(e);
57
+ }
58
+ }));
59
+ // Remove any stale proxy host entries that were managed last deploy but are no longer in the current config.
60
+ let previouslyManaged = managedProxyHosts.get(nodeId) ?? [];
61
+ let newHostIds = new Set(newlyManaged.map(m => m.hostId));
62
+ await Promise.all(previouslyManaged
63
+ .filter(m => !newHostIds.has(m.hostId))
64
+ .map(async (stale) => {
65
+ try {
66
+ let reverseProxyNode = NodeConstructor_1.NodeManager.RED.nodes.getNode(stale.proxyNodeId).node();
29
67
  let proxyClient = reverseProxyNode.client();
30
- console.log("List of known hosts: ", await proxyClient.getHosts());
31
- //console.log("ADD REVERSE PROXY:" + proxy.proxy + " to " + node.id(), proxyClient);
68
+ await proxyClient.deleteHost(stale.hostId);
32
69
  }
33
70
  catch (e) {
34
- console.log(e);
71
+ console.error(e);
35
72
  }
36
- return Promise.resolve();
37
73
  }));
74
+ managedProxyHosts.set(nodeId, newlyManaged);
38
75
  }
39
76
  // register a close listener to the node.
40
77
  node.node().on("close", () => {
@@ -15,7 +15,6 @@ const NodeGenerator_1 = require("../../NodeGenerator");
15
15
  const WebhookServerService_1 = require("../service/WebhookServerService");
16
16
  const NodeDescriptionDecorator_1 = require("../../tagging/NodeDescriptionDecorator");
17
17
  let WebhookServerConfigNode = class WebhookServerConfigNode extends NodeConstructor_1.ConfigNode {
18
- _server;
19
18
  constructor(node, config) {
20
19
  super(node, config);
21
20
  let _this = this;
@@ -8,8 +8,7 @@ export declare abstract class ReverseProxyType {
8
8
  export interface ProxyManagerClient {
9
9
  updateHost(data: Partial<HostEntry>): Promise<void>;
10
10
  getHosts(): Promise<Partial<HostEntry>[]>;
11
- }
12
- export declare abstract class ReverseProxyClient {
11
+ deleteHost(id: number): Promise<void>;
13
12
  }
14
13
  export type HostEntry = {
15
14
  id: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ReverseProxyTypeService.d.ts","sourceRoot":"","sources":["../../../../src/core/webhook/service/ReverseProxyTypeService.ts"],"names":[],"mappings":"AAGA,8BAAsB,gBAAgB;IAElC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAS;gBAEV,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM;IAK3B,EAAE,IAAG,MAAM;IAGX,IAAI,IAAG,MAAM;CAGvB;AAED,MAAM,WAAW,kBAAkB;IAC/B,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,IAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;CAC5C;AAED,8BAAsB,kBAAkB;CAEvC;AAED,MAAM,MAAM,SAAS,GAAG;IACpB,EAAE,EAAC,MAAM,CAAC;IACV,WAAW,EAAC,MAAM,EAAE,CAAC;IACrB,MAAM,EAAC,UAAU,CAAC;IAClB,WAAW,EAAC,MAAM,CAAC;IACnB,WAAW,EAAC,MAAM,CAAC;IACnB,UAAU,EAAC,MAAM,CAAC;IAClB,WAAW,EAAC,OAAO,CAAC;IACpB,mBAAmB,EAAC,OAAO,CAAC;IAC5B,gBAAgB,EAAC,OAAO,CAAC;CAC5B,CAAA;AAED,oBAAY,UAAU;IAClB,IAAI,SAAS;IACb,KAAK,UAAU;CAClB"}
1
+ {"version":3,"file":"ReverseProxyTypeService.d.ts","sourceRoot":"","sources":["../../../../src/core/webhook/service/ReverseProxyTypeService.ts"],"names":[],"mappings":"AAGA,8BAAsB,gBAAgB;IAElC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAS;gBAEV,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM;IAK3B,EAAE,IAAG,MAAM;IAGX,IAAI,IAAG,MAAM;CAGvB;AAED,MAAM,WAAW,kBAAkB;IAC/B,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,IAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,SAAS,GAAG;IACpB,EAAE,EAAC,MAAM,CAAC;IACV,WAAW,EAAC,MAAM,EAAE,CAAC;IACrB,MAAM,EAAC,UAAU,CAAC;IAClB,WAAW,EAAC,MAAM,CAAC;IACnB,WAAW,EAAC,MAAM,CAAC;IACnB,UAAU,EAAC,MAAM,CAAC;IAClB,WAAW,EAAC,OAAO,CAAC;IACpB,mBAAmB,EAAC,OAAO,CAAC;IAC5B,gBAAgB,EAAC,OAAO,CAAC;CAC5B,CAAA;AAED,oBAAY,UAAU;IAClB,IAAI,SAAS;IACb,KAAK,UAAU;CAClB"}
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HTTPScheme = exports.ReverseProxyClient = exports.ReverseProxyType = void 0;
3
+ exports.HTTPScheme = exports.ReverseProxyType = void 0;
4
4
  class ReverseProxyType {
5
- _id;
6
- _name;
7
5
  constructor(id, name) {
8
6
  this._id = id;
9
7
  this._name = name;
@@ -16,9 +14,6 @@ class ReverseProxyType {
16
14
  }
17
15
  }
18
16
  exports.ReverseProxyType = ReverseProxyType;
19
- class ReverseProxyClient {
20
- }
21
- exports.ReverseProxyClient = ReverseProxyClient;
22
17
  var HTTPScheme;
23
18
  (function (HTTPScheme) {
24
19
  HTTPScheme["HTTP"] = "http";
@@ -1,7 +1,7 @@
1
1
  import { BaseService, FlowDeployment, ServiceDescriptor } from "../../NodeConstructor";
2
2
  import { NodeAPI, NodeAPISettingsWithData } from "node-red";
3
3
  import { Request, Response } from "express";
4
- import { ApiKeyMechanismType, RestAuthType } from "../../logger/service/LoggerServiceTypes";
4
+ import { ApiKeyMechanismType, RestAuthType } from "../../logger/service/LoggerService";
5
5
  export declare enum EndpointMethodType {
6
6
  GET = "GET",
7
7
  POST = "POST"
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookServerService.d.ts","sourceRoot":"","sources":["../../../../src/core/webhook/service/WebhookServerService.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAgB,EAAU,OAAO,EAAE,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAI5F,oBAAY,kBAAkB;IAC1B,GAAG,QAAQ;IACX,IAAI,SAAS;CAChB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACjC,IAAI,EAAC,YAAY,CAAC,IAAI,CAAC;CAC1B,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC,IAAI,EAAC,YAAY,CAAC,KAAK,CAAA;IACvB,QAAQ,EAAC,MAAM,CAAC;IAChB,QAAQ,EAAC,MAAM,CAAC;CACnB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACrC,IAAI,EAAC,YAAY,CAAC,MAAM,CAAC;IACzB,SAAS,EAAC,mBAAmB,CAAC;IAC9B,GAAG,EAAC,MAAM,CAAC;IACX,KAAK,EAAC,MAAM,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAC,kBAAkB,EAAE,CAAC;IAC7B,cAAc,EAAE,sBAAsB,GAAG,yBAAyB,GAAG,0BAA0B,CAAC;CACnG,CAAA;AAED,qBAAa,aAAa;IAEtB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,SAAS,CAAS;gBAEP,MAAM,EAAC,mBAAmB;IAQtC,MAAM,CAAC,QAAQ,EAAC,cAAc,EAAE,QAAQ,EAAC,CAAC,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAC,QAAQ,KAAK,GAAG;IA+CpF,MAAM,CAAC,aAAa,EAAC,cAAc;IAsBnC,MAAM,IAAG,mBAAmB;CAGtC;AAED,MAAM,MAAO,mBAAmB,GAAG;IAC/B,EAAE,EAAC,MAAM,CAAA;IACT,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAC,MAAM,CAAC;IACpB,YAAY,EAAC,MAAM,CAAC;CACvB,CAAA;AAED,qBAAa,oBAAqB,SAAQ,WAAW;IAEjD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAmC;;IAMzD,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;WAyCvD,GAAG,CAAE,MAAM,EAAC,mBAAmB,GAAG,aAAa;WAS7C,oBAAoB,IAAG,iBAAiB;CAU3D"}
1
+ {"version":3,"file":"WebhookServerService.d.ts","sourceRoot":"","sources":["../../../../src/core/webhook/service/WebhookServerService.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAgB,EAAU,OAAO,EAAE,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAIvF,oBAAY,kBAAkB;IAC1B,GAAG,QAAQ;IACX,IAAI,SAAS;CAChB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACjC,IAAI,EAAC,YAAY,CAAC,IAAI,CAAC;CAC1B,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC,IAAI,EAAC,YAAY,CAAC,KAAK,CAAA;IACvB,QAAQ,EAAC,MAAM,CAAC;IAChB,QAAQ,EAAC,MAAM,CAAC;CACnB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACrC,IAAI,EAAC,YAAY,CAAC,MAAM,CAAC;IACzB,SAAS,EAAC,mBAAmB,CAAC;IAC9B,GAAG,EAAC,MAAM,CAAC;IACX,KAAK,EAAC,MAAM,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAC,kBAAkB,EAAE,CAAC;IAC7B,cAAc,EAAE,sBAAsB,GAAG,yBAAyB,GAAG,0BAA0B,CAAC;CACnG,CAAA;AAED,qBAAa,aAAa;IAEtB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,SAAS,CAAS;gBAEP,MAAM,EAAC,mBAAmB;IAQtC,MAAM,CAAC,QAAQ,EAAC,cAAc,EAAE,QAAQ,EAAC,CAAC,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAC,QAAQ,KAAK,GAAG;IA8CpF,MAAM,CAAC,aAAa,EAAC,cAAc;IAoBnC,MAAM,IAAG,mBAAmB;CAGtC;AAED,MAAM,MAAO,mBAAmB,GAAG;IAC/B,EAAE,EAAC,MAAM,CAAA;IACT,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAC,MAAM,CAAC;IACpB,YAAY,EAAC,MAAM,CAAC;CACvB,CAAA;AAED,qBAAa,oBAAqB,SAAQ,WAAW;IAEjD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAmC;;IAMzD,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;WAuCvD,GAAG,CAAE,MAAM,EAAC,mBAAmB,GAAG,aAAa;WAS7C,oBAAoB,IAAG,iBAAiB;CAU3D"}