@theotherwillembotha/node-red-plugincore 0.1.0 → 0.2.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.
- package/README.md +616 -220
- package/build/GenerateNodes.js +3 -6
- package/build/Nodes.html +3 -1504
- package/build/Nodes.js +5 -15
- package/build/Plugins.html +227 -0
- package/build/Plugins.js +18 -8
- package/build/core/NodeConstructor.d.ts +9 -16
- package/build/core/NodeConstructor.d.ts.map +1 -1
- package/build/core/NodeConstructor.js +109 -146
- package/build/core/NodeGenerator.d.ts.map +1 -1
- package/build/core/NodeGenerator.js +79 -28
- package/build/core/NodeManagerRuntime.d.ts +44 -0
- package/build/core/NodeManagerRuntime.d.ts.map +1 -0
- package/build/core/NodeManagerRuntime.js +140 -0
- package/build/core/Utils.d.ts.map +1 -1
- package/build/core/logger/service/LoggerService.d.ts +6 -5
- package/build/core/logger/service/LoggerService.d.ts.map +1 -1
- package/build/core/logger/service/LoggerService.js +51 -20
- package/build/core/logger/template/LoggerTemplate.d.ts.map +1 -1
- package/build/core/metrics/MetricsDecorator.d.ts +1 -2
- package/build/core/metrics/MetricsDecorator.d.ts.map +1 -1
- package/build/core/metrics/MetricsDecorator.js +89 -116
- package/build/core/metrics/node/CounterMetricConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/CounterMetricConfigNode.js +4 -5
- package/build/core/metrics/node/GaugeMetricConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/GaugeMetricConfigNode.js +5 -6
- package/build/core/metrics/node/MetricsConfigNode.d.ts +19 -9
- package/build/core/metrics/node/MetricsConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/MetricsConfigNode.js +14 -45
- package/build/core/metrics/node/TimerMetricConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/TimerMetricConfigNode.js +11 -17
- package/build/core/metrics/service/MetricsService.d.ts +110 -114
- package/build/core/metrics/service/MetricsService.d.ts.map +1 -1
- package/build/core/metrics/service/MetricsService.js +122 -339
- package/build/core/metrics/template/CounterMetricTemplate.d.ts.map +1 -1
- package/build/core/metrics/template/GaugeMetricTemplate.d.ts.map +1 -1
- package/build/core/metrics/template/MetricsTemplate.d.ts.map +1 -1
- package/build/core/metrics/template/MetricsTemplate.js +1 -2
- package/build/core/metrics/template/TimerMetricTemplate.d.ts.map +1 -1
- package/build/core/other/node/DelegatedConfigReferenceNode.d.ts +1 -1
- package/build/core/other/node/DelegatedConfigReferenceNode.d.ts.map +1 -1
- package/build/core/other/node/DelegatedConfigReferenceNode.js +1 -1
- package/build/core/other/service/InputService.d.ts.map +1 -1
- package/build/core/other/service/SettingsService.d.ts +1 -2
- package/build/core/other/service/SettingsService.d.ts.map +1 -1
- package/build/core/other/service/SettingsService.js +19 -5
- package/build/core/other/template/BasicTemplate.d.ts.map +1 -1
- package/build/core/other/template/SettingsTemplate.d.ts.map +1 -1
- package/build/core/state/node/InternalStateConfigNode.d.ts +16 -0
- package/build/core/state/node/InternalStateConfigNode.d.ts.map +1 -0
- package/build/core/state/node/InternalStateConfigNode.js +89 -0
- package/build/core/state/node/StateConfigNode.d.ts +24 -0
- package/build/core/state/node/StateConfigNode.d.ts.map +1 -0
- package/build/core/state/node/StateConfigNode.js +22 -0
- package/build/core/state/service/StateService.d.ts +34 -0
- package/build/core/state/service/StateService.d.ts.map +1 -0
- package/build/core/state/service/StateService.js +201 -0
- package/build/core/state/template/StateTemplate.d.ts +8 -0
- package/build/core/state/template/StateTemplate.d.ts.map +1 -0
- package/build/core/state/template/StateTemplate.js +11 -0
- package/build/core/tagging/ServiceDescriptionDecorator.d.ts +10 -0
- package/build/core/tagging/ServiceDescriptionDecorator.d.ts.map +1 -0
- package/build/core/tagging/ServiceDescriptionDecorator.js +10 -0
- package/build/core/tagging/service/NodeTypeService.d.ts +1 -2
- package/build/core/tagging/service/NodeTypeService.d.ts.map +1 -1
- package/build/core/tagging/service/NodeTypeService.js +19 -5
- package/build/core/ui/template/ScriptEditorTemplate.d.ts.map +1 -1
- package/build/core/ui/template/UIHelperTemplate.d.ts.map +1 -1
- package/build/core/webhook/node/WebhookServerConfigNode.d.ts.map +1 -1
- package/build/core/webhook/service/ReverseProxyTypeService.d.ts.map +1 -1
- package/build/core/webhook/service/WebhookServerService.d.ts +3 -4
- package/build/core/webhook/service/WebhookServerService.d.ts.map +1 -1
- package/build/core/webhook/service/WebhookServerService.js +48 -18
- package/build/core/webhook/template/WebhookTemplate.d.ts.map +1 -1
- package/build/index.d.ts +5 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -2
- package/build/runtime/NodeManagerRuntime.js +140 -0
- package/documentation/CounterMetricConfigNode.png +0 -0
- package/documentation/GaugeMetricConfigNode.png +0 -0
- package/documentation/LoggerTemplate.png +0 -0
- package/documentation/MetricsTemplate.png +0 -0
- package/documentation/StateTemplate.png +0 -0
- package/documentation/TimerMetricConfigNode_histogram.png +0 -0
- package/documentation/TimerMetricConfigNode_summary.png +0 -0
- package/documentation/WebhookServerConfigNode.png +0 -0
- package/documentation/WebhookTemplate.png +0 -0
- package/package.json +4 -10
- package/src/GenerateNodes.ts +7 -11
- package/src/core/NodeConstructor.ts +130 -186
- package/src/core/NodeGenerator.ts +88 -33
- package/src/core/NodeManagerRuntime.ts +179 -0
- package/src/core/logger/service/LoggerService.ts +39 -26
- package/src/core/logger/template/LoggerTemplate.html +11 -6
- package/src/core/metrics/MetricsDecorator.ts +140 -168
- package/src/core/metrics/node/CounterMetricConfigNode.ts +20 -20
- package/src/core/metrics/node/GaugeMetricConfigNode.ts +24 -25
- package/src/core/metrics/node/MetricsConfigNode.ts +29 -48
- package/src/core/metrics/node/TimerMetricConfigNode.ts +50 -59
- package/src/core/metrics/service/MetricsService.ts +214 -489
- package/src/core/metrics/template/CounterMetricTemplate.html +0 -1
- package/src/core/metrics/template/GaugeMetricTemplate.html +1 -1
- package/src/core/metrics/template/MetricsTemplate.html +132 -13
- package/src/core/metrics/template/MetricsTemplate.ts +3 -4
- package/src/core/other/node/DelegatedConfigReferenceNode.ts +1 -1
- package/src/core/other/service/SettingsService.ts +6 -10
- package/src/core/other/template/BasicTemplate.html +1 -1
- package/src/core/state/node/InternalStateConfigNode.html +77 -0
- package/src/core/state/node/InternalStateConfigNode.ts +102 -0
- package/src/core/state/node/StateConfigNode.ts +29 -0
- package/src/core/state/service/StateService.ts +180 -0
- package/src/core/state/template/StateTemplate.html +244 -0
- package/src/core/state/template/StateTemplate.ts +17 -0
- package/src/core/tagging/ServiceDescriptionDecorator.ts +23 -0
- package/src/core/tagging/service/NodeTypeService.ts +6 -11
- package/src/core/ui/template/UIHelperTemplate.html +41 -26
- package/src/core/webhook/service/WebhookServerService.ts +39 -23
- package/src/core/webhook/template/WebhookTemplate.html +28 -35
- package/src/index.ts +7 -2
- package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts +0 -20
- package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts.map +0 -1
- package/build/core/logger/node/ConsoleLoggerConfigNode.js +0 -62
- package/build/core/logger/node/RestLoggerConfigNode.d.ts +0 -40
- package/build/core/logger/node/RestLoggerConfigNode.d.ts.map +0 -1
- package/build/core/logger/node/RestLoggerConfigNode.js +0 -128
- package/documentation/ConsoleLoggerConfigNode.png +0 -0
- package/documentation/MetricsConfigNode.png +0 -0
- package/documentation/RestLoggerConfigNode.png +0 -0
- package/documentation/TimerMetricConfigNode.png +0 -0
- package/documentation/WebhookNode.png +0 -0
- package/src/core/logger/node/ConsoleLoggerConfigNode.html +0 -90
- package/src/core/logger/node/ConsoleLoggerConfigNode.ts +0 -71
- package/src/core/logger/node/RestLoggerConfigNode.html +0 -183
- package/src/core/logger/node/RestLoggerConfigNode.ts +0 -170
|
@@ -3,14 +3,15 @@ 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.
|
|
6
|
+
exports.buildNodeBuilder = exports.buildNode = exports.NodeBuilder = exports.BaseService = exports.Template = exports.ServiceDescriptor = exports.TemplateDescriptor = exports.NodeDescriptor = exports.ConfigNode = exports.BaseNode = exports.NodeManager = exports.runPostConstructInitializers = exports.POST_CONSTRUCT_KEY = exports.NODEMANAGER_API_VERSION = void 0;
|
|
7
7
|
exports.createPostConstructDecorator = createPostConstructDecorator;
|
|
8
8
|
require("reflect-metadata");
|
|
9
|
-
const jsdom_1 = __importDefault(require("jsdom"));
|
|
10
9
|
const fs_1 = __importDefault(require("fs"));
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const NodeManagerRuntime_1 = require("./NodeManagerRuntime");
|
|
11
|
+
Object.defineProperty(exports, "NODEMANAGER_API_VERSION", { enumerable: true, get: function () { return NodeManagerRuntime_1.NODEMANAGER_API_VERSION; } });
|
|
12
|
+
Object.defineProperty(exports, "POST_CONSTRUCT_KEY", { enumerable: true, get: function () { return NodeManagerRuntime_1.POST_CONSTRUCT_KEY; } });
|
|
13
|
+
Object.defineProperty(exports, "runPostConstructInitializers", { enumerable: true, get: function () { return NodeManagerRuntime_1.runPostConstructInitializers; } });
|
|
14
|
+
Object.defineProperty(exports, "NodeManager", { enumerable: true, get: function () { return NodeManagerRuntime_1.NodeManager; } });
|
|
14
15
|
class BaseNode {
|
|
15
16
|
node() { return this._node; }
|
|
16
17
|
config() { return this._config; }
|
|
@@ -135,7 +136,6 @@ class Template {
|
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
exports.Template = Template;
|
|
138
|
-
const POST_CONSTRUCT_KEY = Symbol('postConstructInitializers');
|
|
139
139
|
// Builder class for post-construct decorators
|
|
140
140
|
class PostConstructDecoratorBuilder {
|
|
141
141
|
constructor(decoratorName) {
|
|
@@ -201,10 +201,10 @@ class PostConstructDecoratorBuilder {
|
|
|
201
201
|
` Issue: Method returned a value (${typeof result}) but should return void or Promise<void>.`);
|
|
202
202
|
}
|
|
203
203
|
};
|
|
204
|
-
if (!target[POST_CONSTRUCT_KEY]) {
|
|
205
|
-
target[POST_CONSTRUCT_KEY] = [];
|
|
204
|
+
if (!target[NodeManagerRuntime_1.POST_CONSTRUCT_KEY]) {
|
|
205
|
+
target[NodeManagerRuntime_1.POST_CONSTRUCT_KEY] = [];
|
|
206
206
|
}
|
|
207
|
-
target[POST_CONSTRUCT_KEY].push((instance) => {
|
|
207
|
+
target[NodeManagerRuntime_1.POST_CONSTRUCT_KEY].push((instance) => {
|
|
208
208
|
if (initLogic) {
|
|
209
209
|
try {
|
|
210
210
|
initLogic(instance, propertyKey, config);
|
|
@@ -245,117 +245,6 @@ class PostConstructDecoratorBuilder {
|
|
|
245
245
|
function createPostConstructDecorator(decoratorName) {
|
|
246
246
|
return new PostConstructDecoratorBuilder(decoratorName);
|
|
247
247
|
}
|
|
248
|
-
// Single function to run all post-construct initializers
|
|
249
|
-
let runPostConstructInitializers = function (instance) {
|
|
250
|
-
const initializers = instance[POST_CONSTRUCT_KEY];
|
|
251
|
-
if (initializers && initializers.length > 0) {
|
|
252
|
-
const className = instance.constructor.name;
|
|
253
|
-
//console.log(`Running ${initializers.length} post-construct initializers for ${className}`);
|
|
254
|
-
initializers.forEach((init, index) => {
|
|
255
|
-
try {
|
|
256
|
-
init(instance);
|
|
257
|
-
}
|
|
258
|
-
catch (error) {
|
|
259
|
-
console.error(`Post-construct initialization failed:\n` +
|
|
260
|
-
` Class: ${className}\n` +
|
|
261
|
-
` Initializer: ${index + 1}/${initializers.length}\n` +
|
|
262
|
-
` Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
263
|
-
throw error;
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
// Clear the initializers after running
|
|
267
|
-
delete instance[POST_CONSTRUCT_KEY];
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
// ************************************************
|
|
271
|
-
class NodeManager {
|
|
272
|
-
static { this.PLUGINID = "node-red-contrib-theotherwillembotha/services-plugin"; }
|
|
273
|
-
constructor(RED) {
|
|
274
|
-
this.typeBacklog = [];
|
|
275
|
-
NodeManager._RED = RED;
|
|
276
|
-
let nodeTypeServiceListener = async (pluginID) => {
|
|
277
|
-
if (pluginID === "@theotherwillembotha/nodetypeservice") {
|
|
278
|
-
// disable the listener- the plugin has been installed.
|
|
279
|
-
RED.events.off('plugin.instantiated', nodeTypeServiceListener);
|
|
280
|
-
// get a handle on the NodeTypeService
|
|
281
|
-
let plugin = RED.plugins.get("@theotherwillembotha/nodetypeservice");
|
|
282
|
-
this.nodeTypeService = RED.plugins.get("@theotherwillembotha/nodetypeservice").instance;
|
|
283
|
-
// process the backlog.
|
|
284
|
-
for (let nodeType of this.typeBacklog) {
|
|
285
|
-
for (let tag of nodeType.getNodeDescriptor().tags()) {
|
|
286
|
-
this.nodeTypeService.registerNodeType(tag, nodeType);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
// check if the reverserproxyttypesewrvice is installed yet.
|
|
292
|
-
this.nodeTypeService = RED.plugins.get("@theotherwillembotha/nodetypeservice").instance;
|
|
293
|
-
if (!this.nodeTypeService) {
|
|
294
|
-
RED.events.on('plugin.instantiated', nodeTypeServiceListener);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
static get RED() {
|
|
298
|
-
return NodeManager._RED;
|
|
299
|
-
}
|
|
300
|
-
registerService(type) {
|
|
301
|
-
let servicePlugin = NodeManager.RED.plugins.get(NodeManager.PLUGINID);
|
|
302
|
-
if (servicePlugin) {
|
|
303
|
-
servicePlugin.instance.install(NodeManager.RED, type);
|
|
304
|
-
}
|
|
305
|
-
else {
|
|
306
|
-
let serviceName = `${type.getServiceDescriptor().sourceFile()}.${type.getServiceDescriptor().name()}`;
|
|
307
|
-
console.log(`ERROR: plugin ${NodeManager.PLUGINID} does not seem to be loaded. Cannot start service: ${serviceName}`);
|
|
308
|
-
}
|
|
309
|
-
return this;
|
|
310
|
-
}
|
|
311
|
-
registerNodeType(typeName, type) {
|
|
312
|
-
if (!type) {
|
|
313
|
-
console.error(`Type "${typeName}" has no associated type. Make sure that it was exported and included in the index.js file!`);
|
|
314
|
-
}
|
|
315
|
-
let nodeConstructor = function (config) {
|
|
316
|
-
//console.log("constructing node", typeName);
|
|
317
|
-
try {
|
|
318
|
-
// instantiate the node.
|
|
319
|
-
NodeManager.RED.nodes.createNode(this, config);
|
|
320
|
-
// assign an instance of it to the config.
|
|
321
|
-
//(config as any).__node = this;
|
|
322
|
-
// instatiate the actual node.
|
|
323
|
-
let node = new type(this, config);
|
|
324
|
-
//this.__node = node;
|
|
325
|
-
// run the constructor initializers.
|
|
326
|
-
runPostConstructInitializers(node);
|
|
327
|
-
// after the node has been instantiated, attempt to invole the onInit method.
|
|
328
|
-
if (node.onInit) {
|
|
329
|
-
node.onInit();
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
catch (error) {
|
|
333
|
-
console.log(error);
|
|
334
|
-
console.log("typeName:", typeName);
|
|
335
|
-
console.log("type:", type);
|
|
336
|
-
console.log("config:", config);
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
try {
|
|
340
|
-
NodeManager.RED.nodes.registerType(typeName, nodeConstructor, { settings: {} });
|
|
341
|
-
let nodeDescription = type.getNodeDescriptor();
|
|
342
|
-
// registger the node tags.
|
|
343
|
-
if (this.nodeTypeService) {
|
|
344
|
-
for (let tag of nodeDescription.tags()) {
|
|
345
|
-
this.nodeTypeService.registerNodeType(tag, type);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
this.typeBacklog.push(type);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
catch (error) {
|
|
353
|
-
console.error("registering node: " + typeName + " failed", error);
|
|
354
|
-
}
|
|
355
|
-
return this;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
exports.NodeManager = NodeManager;
|
|
359
248
|
class BaseService {
|
|
360
249
|
constructor(name) {
|
|
361
250
|
this._name = name;
|
|
@@ -371,23 +260,26 @@ class BaseService {
|
|
|
371
260
|
}
|
|
372
261
|
}
|
|
373
262
|
exports.BaseService = BaseService;
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
};
|
|
263
|
+
// Build-time deps - lazy loaded so they are never required at runtime in production bundles.
|
|
264
|
+
// These are only invoked during `npm run build` (GenerateNodes), never in the deployed container.
|
|
265
|
+
function getJSDOM() { return require('jsdom').JSDOM; }
|
|
266
|
+
function getBeautify() { return require('js-beautify'); }
|
|
267
|
+
function getHandlebars() { return require('handlebars'); }
|
|
268
|
+
let _md = null;
|
|
269
|
+
function getMd() {
|
|
270
|
+
if (!_md) {
|
|
271
|
+
_md = require('markdown-it')({ html: true, linkify: true, typographer: true });
|
|
272
|
+
_md.renderer.rules.heading_open = (tokens, idx) => {
|
|
273
|
+
const level = tokens[idx].tag.substring(1);
|
|
274
|
+
return `<h${level} class="custom-heading">`;
|
|
275
|
+
};
|
|
276
|
+
_md.renderer.rules.heading_close = (tokens, idx) => {
|
|
277
|
+
const level = tokens[idx].tag.substring(1);
|
|
278
|
+
return `</h${level}>`;
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
return _md;
|
|
282
|
+
}
|
|
391
283
|
let beautifyOptions = {
|
|
392
284
|
"indent_size": 4,
|
|
393
285
|
"preserve-newlines": false,
|
|
@@ -423,7 +315,7 @@ class NodeBuilder {
|
|
|
423
315
|
this._category = category;
|
|
424
316
|
}
|
|
425
317
|
addDefault(name, template) {
|
|
426
|
-
// if list:true, this is an array of config references
|
|
318
|
+
// if list:true, this is an array of config references - generate shadow defaults for each slot.
|
|
427
319
|
if (template.list === true) {
|
|
428
320
|
template.maxInstances = template.maxInstances ? template.maxInstances : 10;
|
|
429
321
|
this._defaults[name] = { value: "", required: (template.required) ? template.required : false, maxInstances: template.maxInstances };
|
|
@@ -466,8 +358,9 @@ class NodeBuilder {
|
|
|
466
358
|
}
|
|
467
359
|
addTemplate(template) {
|
|
468
360
|
let templateDescriptor = template.template.getTemplateDescriptor();
|
|
361
|
+
let templateConfig = template.config;
|
|
469
362
|
// load the html source file
|
|
470
|
-
let uiDom = new
|
|
363
|
+
let uiDom = new (getJSDOM())(fs_1.default.readFileSync(templateDescriptor.templateFile()));
|
|
471
364
|
// apply the onCompose section if available.
|
|
472
365
|
let onCompose = uiDom.window.document.querySelector("script[template-section='onCompose']")?.innerHTML;
|
|
473
366
|
if (onCompose) {
|
|
@@ -478,6 +371,14 @@ class NodeBuilder {
|
|
|
478
371
|
Object.values(sections).forEach(section => {
|
|
479
372
|
let sectionData = uiDom.window.document.querySelector(`[template-section='on${section}']`)?.innerHTML;
|
|
480
373
|
if (sectionData) {
|
|
374
|
+
if (section !== "IncludeOnce" && section !== "IncludeEditForm" && section !== "IncludeDocumentation") {
|
|
375
|
+
// add the packageing around the sectionData
|
|
376
|
+
sectionData = `{
|
|
377
|
+
let node = this;
|
|
378
|
+
let templateConfig = ${JSON.stringify(templateConfig)};
|
|
379
|
+
${sectionData}
|
|
380
|
+
}`;
|
|
381
|
+
}
|
|
481
382
|
this[`add${section}`](templateDescriptor.name(), sectionData);
|
|
482
383
|
}
|
|
483
384
|
});
|
|
@@ -511,6 +412,63 @@ class NodeBuilder {
|
|
|
511
412
|
this._onIncludeDocumentation.push({ source: source, script: script });
|
|
512
413
|
return this;
|
|
513
414
|
}
|
|
415
|
+
buildOnceHtml() {
|
|
416
|
+
return this._onIncludeOnce.map(entry => ({
|
|
417
|
+
source: entry.source,
|
|
418
|
+
html: this.serializeHTML(entry.source, entry.script)
|
|
419
|
+
}));
|
|
420
|
+
}
|
|
421
|
+
buildDeferredType() {
|
|
422
|
+
// Apply shadow defaults (same side-effect as buildType)
|
|
423
|
+
let shaddowDefaults = Object.entries(this._defaults).filter(([name, template]) => template.type && template.type.endsWith("[]"));
|
|
424
|
+
if (shaddowDefaults.length > 0) {
|
|
425
|
+
this.addIncludeEditSave(this._name + "_shaddowDefaults", `{ let node = this; ` +
|
|
426
|
+
shaddowDefaults
|
|
427
|
+
.map(([name, template]) => `
|
|
428
|
+
for(let i = 0; i < ${template.maxInstances}; i++){
|
|
429
|
+
node["_${name}_" + i] = (node.${name}[i] || {}).proxy || "";
|
|
430
|
+
}`)
|
|
431
|
+
.join("\n\n") +
|
|
432
|
+
`}`);
|
|
433
|
+
}
|
|
434
|
+
const registerTypeBody = `{
|
|
435
|
+
category: '${this._category}',
|
|
436
|
+
${(this._category !== "config" && this._icon) ? `icon: '${this._icon}',` : ""}
|
|
437
|
+
${(this._category !== "config" && this._color) ? `color: '${this._color}',` : ""}
|
|
438
|
+
${(this._category !== "config" && this._labelStyle) ? `labelStyle: '${this._labelStyle}',` : ""}
|
|
439
|
+
${(this._label) ? `label: ${this._label},` : ""}
|
|
440
|
+
${this._paletteLabel ? `paletteLabel: '${this._paletteLabel}',` : ""}
|
|
441
|
+
${(this._category !== "config") ? `inputs:${this._inputs ? "1" : "0"},` : ""}
|
|
442
|
+
${(this._category !== "config") ? `inputLabels:(i) => '${this._inputs}',` : ""}
|
|
443
|
+
${(this._category !== "config") ? `outputs:${this._outputs.length},` : ""}
|
|
444
|
+
${(this._category !== "config") ? `outputLabels:(i) => ${this.serializeProperty(this._outputs)}[i],` : ""}
|
|
445
|
+
defaults: {
|
|
446
|
+
${Object.entries(this._defaults).map(([key, value]) => this.serializeDefault(key, value)).join("\n")}
|
|
447
|
+
},
|
|
448
|
+
oneditprepare: function() {
|
|
449
|
+
${this._onIncludeEditPrepare.map(entry => this.serializeJavaScript(entry.source, entry.script)).join("")}
|
|
450
|
+
},
|
|
451
|
+
oneditsave: function() {
|
|
452
|
+
${this._onIncludeEditSave.map(entry => this.serializeJavaScript(entry.source, entry.script)).join("")}
|
|
453
|
+
},
|
|
454
|
+
oneditcancel: function() {
|
|
455
|
+
${this._onIncludeEditCancel.map(entry => this.serializeJavaScript(entry.source, entry.script)).join("")}
|
|
456
|
+
},
|
|
457
|
+
oneditdelete: function() {
|
|
458
|
+
${this._onIncludeEditDelete.map(entry => this.serializeJavaScript(entry.source, entry.script)).join("")}
|
|
459
|
+
},
|
|
460
|
+
}`;
|
|
461
|
+
return getBeautify().html_beautify(`
|
|
462
|
+
<script type="text/javascript">
|
|
463
|
+
(function () {
|
|
464
|
+
RED.events.on('registry:node-set-added', function (ns) {
|
|
465
|
+
if (ns.types && ns.types.indexOf('${this._name}') !== -1) {
|
|
466
|
+
RED.nodes.registerType('${this._name}', ${registerTypeBody});
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
}());
|
|
470
|
+
</script>`, beautifyOptions);
|
|
471
|
+
}
|
|
514
472
|
serializeProperty(value) {
|
|
515
473
|
switch (typeof value) {
|
|
516
474
|
case "boolean": {
|
|
@@ -540,7 +498,7 @@ class NodeBuilder {
|
|
|
540
498
|
: Object.fromEntries(Object.keys(this._defaults).map(k => [k, `node-input-${k}`]))
|
|
541
499
|
};
|
|
542
500
|
return `<!-- ${source} -->
|
|
543
|
-
${
|
|
501
|
+
${getHandlebars().compile(script)(context)}
|
|
544
502
|
`;
|
|
545
503
|
}
|
|
546
504
|
serializeJavaScript(source, script) {
|
|
@@ -549,7 +507,7 @@ class NodeBuilder {
|
|
|
549
507
|
? Object.fromEntries(Object.keys(this._defaults).map(k => [k, `node-config-input-${k}`]))
|
|
550
508
|
: Object.fromEntries(Object.keys(this._defaults).map(k => [k, `node-input-${k}`]))
|
|
551
509
|
};
|
|
552
|
-
let serialized =
|
|
510
|
+
let serialized = getHandlebars().compile(script)(context).trim();
|
|
553
511
|
if (!serialized.startsWith("{") && !serialized.endsWith("}")) {
|
|
554
512
|
serialized = "{\n" + serialized + "\n}";
|
|
555
513
|
}
|
|
@@ -564,7 +522,7 @@ class NodeBuilder {
|
|
|
564
522
|
: Object.fromEntries(Object.keys(this._defaults).map(k => [k, `node-input-${k}`]))
|
|
565
523
|
};
|
|
566
524
|
return `
|
|
567
|
-
<div id='section_${source}'>${
|
|
525
|
+
<div id='section_${source}'>${getHandlebars().compile(script)(context)}
|
|
568
526
|
</div>
|
|
569
527
|
`;
|
|
570
528
|
}
|
|
@@ -587,7 +545,7 @@ class NodeBuilder {
|
|
|
587
545
|
.join("\n\n") +
|
|
588
546
|
`}`);
|
|
589
547
|
}
|
|
590
|
-
return
|
|
548
|
+
return getBeautify().html_beautify(`
|
|
591
549
|
${this._onIncludeOnce.map(entry => this.serializeHTML(entry.source, entry.script)).join("")}
|
|
592
550
|
<script type="text/javascript">
|
|
593
551
|
RED.nodes.registerType('${this._name}',{
|
|
@@ -621,7 +579,7 @@ class NodeBuilder {
|
|
|
621
579
|
}
|
|
622
580
|
;
|
|
623
581
|
buildHtml() {
|
|
624
|
-
return
|
|
582
|
+
return getBeautify().html_beautify(`
|
|
625
583
|
<script type="text/html" data-template-name='${this._name}'>
|
|
626
584
|
${this._onIncludeEditForm.map(entry => this.serializeFormEntry(entry.source, entry.script)).join("")}
|
|
627
585
|
</script>
|
|
@@ -651,12 +609,12 @@ let evalInContext = (context, js) => {
|
|
|
651
609
|
throw error;
|
|
652
610
|
}
|
|
653
611
|
};
|
|
654
|
-
let
|
|
612
|
+
let buildNodeBuilder = function (node) {
|
|
655
613
|
// get the node descriptor and create the builder.
|
|
656
614
|
let nodeDescriptor = node.getNodeDescriptor();
|
|
657
615
|
let nodeBuilder = new NodeBuilder(nodeDescriptor.id(), nodeDescriptor.group());
|
|
658
616
|
// load the html source file
|
|
659
|
-
let uiDom = new
|
|
617
|
+
let uiDom = new (getJSDOM())(fs_1.default.readFileSync(nodeDescriptor.sourceFile()));
|
|
660
618
|
// apply the onCompose section if available.
|
|
661
619
|
let onCompose = uiDom.window.document.querySelector("script[template-section='onCompose']")?.innerHTML;
|
|
662
620
|
if (onCompose) {
|
|
@@ -672,6 +630,11 @@ let buildNode = function (node) {
|
|
|
672
630
|
});
|
|
673
631
|
// add some of the dependencies here.
|
|
674
632
|
nodeDescriptor.templates().forEach(template => nodeBuilder.addTemplate(template));
|
|
633
|
+
return nodeBuilder;
|
|
634
|
+
};
|
|
635
|
+
exports.buildNodeBuilder = buildNodeBuilder;
|
|
636
|
+
let buildNode = function (node) {
|
|
637
|
+
let nodeBuilder = buildNodeBuilder(node);
|
|
675
638
|
return [nodeBuilder.buildType(), nodeBuilder.buildHtml(), nodeBuilder.buildDocumentation()].join("\n\n");
|
|
676
639
|
};
|
|
677
640
|
exports.buildNode = buildNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeGenerator.d.ts","sourceRoot":"","sources":["../../src/core/NodeGenerator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NodeGenerator.d.ts","sourceRoot":"","sources":["../../src/core/NodeGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAA+B,QAAQ,EAAE,cAAc,EAAe,iBAAiB,EAA4B,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAIvK,MAAM,WAAW,cAAc;IAC3B,QAAQ,QAAQ,CAAC;IACjB,qBAAqB,IAAI,kBAAkB,CAAC;CAC/C;AAED,MAAM,WAAW,UAAU;IACvB,iBAAiB,IAAG,cAAc,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC1B,oBAAoB,IAAG,iBAAiB,CAAC;CAC5C;AAED,cAAM,aAAa;IAEf,OAAO,CAAC,MAAM,CAAC,WAAW,CAAM;IAChC,OAAO,CAAC,MAAM,CAAC,OAAO,CAKpB;IAEF,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,MAAM,CAA4E;IAC1F,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,UAAU,CAA2B;IAE7C,YAAmB,UAAU,EAAC,MAAM,EAEnC;IAED,OAAO,CAAC,aAAa;IAmBd,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,aAAa,CAe/D;IAEM,YAAY,CAAC,IAAI,EAAC,UAAU,GAAE,aAAa,CAejD;IAEM,eAAe,CAAC,OAAO,EAAE,aAAa,GAAE,aAAa,CAa3D;IAEM,QAAQ,CAAC,eAAe,EAAC,MAAM,EAAE,iBAAiB,EAAC,MAAM,QA6L/D;IAED,OAAO,CAAC,MAAM,CAAC,cAAc;CAQhC;AAID,OAAO,EACH,aAAa,EAChB,CAAA;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAC,MAAM,CAAC;CACf;AAmCD,qBAAa,aAAa;IAEtB,OAAc,aAAa,CAAC,SAAS,EAAC,MAAM,EAAE,UAAU,EAAC,MAAM,GAAE,MAAM,CA0BtE;CACJ;AAED,MAAM,MAAM,OAAO,GAAG;IAClB,CAAC,GAAG,EAAC,MAAM,GAAE,GAAG,CAAC;CACpB,CAAA"}
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.SourceUtility = exports.NodeGenerator = void 0;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
38
39
|
const NodeConstructor_1 = require("./NodeConstructor");
|
|
39
40
|
const templatePropertyKeys = ["onIncludeOnce", "onIncludeDefaults", "onIncludeEditPrepare", "onIncludeEditPrepare", "onIncludeEditSave", "onIncludeEditForm"];
|
|
40
41
|
class NodeGenerator {
|
|
@@ -111,28 +112,17 @@ class NodeGenerator {
|
|
|
111
112
|
return this;
|
|
112
113
|
}
|
|
113
114
|
generate(nodesOutputFile, pluginsOutputFile) {
|
|
114
|
-
// STEP 1.
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
// return template.onIncludeOnce();
|
|
119
|
-
// })
|
|
120
|
-
// .join("\n");
|
|
121
|
-
let templateInclude = "";
|
|
122
|
-
// STEP 2. compose the HTMLStructure of each of the nodes.
|
|
123
|
-
let nodeHTMLOutut = Object.values(this._nodes)
|
|
124
|
-
.map(node => {
|
|
125
|
-
console.log(`Processing node: ${node.descriptor.id()}`);
|
|
126
|
-
return (0, NodeConstructor_1.buildNode)(node.nodeClass);
|
|
127
|
-
})
|
|
128
|
-
.join("\n");
|
|
115
|
+
// STEP 1. Write an empty Nodes.html.
|
|
116
|
+
// Client-side node type definitions live in Plugins.html (generated below)
|
|
117
|
+
// to prevent HTML-scanning conflicts when multiple plugins bundle the same
|
|
118
|
+
// plugincore infrastructure nodes.
|
|
129
119
|
fs.writeFileSync(nodesOutputFile + ".html", `
|
|
130
120
|
<!--
|
|
131
121
|
${NodeGenerator.warning}
|
|
122
|
+
Client-side node type definitions have been moved to Plugins.html to prevent
|
|
123
|
+
duplicate type registration conflicts when multiple plugins share the same
|
|
124
|
+
plugincore infrastructure nodes.
|
|
132
125
|
-->
|
|
133
|
-
${templateInclude}
|
|
134
|
-
${nodeHTMLOutut}
|
|
135
|
-
|
|
136
126
|
`);
|
|
137
127
|
// Step 3. compose the JS structure for each of the nodes.
|
|
138
128
|
// 1. get a list of the files to import.
|
|
@@ -153,14 +143,34 @@ ${nodeHTMLOutut}
|
|
|
153
143
|
${NodeGenerator.warning}
|
|
154
144
|
*/
|
|
155
145
|
"use strict";
|
|
156
|
-
const NodeManager = require("
|
|
146
|
+
const { NodeManager } = require("./runtime/NodeManagerRuntime");
|
|
157
147
|
${importList}
|
|
158
148
|
module.exports = (RED) => {
|
|
159
149
|
let manager = new NodeManager(RED);
|
|
160
150
|
${moduleExports}
|
|
161
|
-
}
|
|
162
|
-
|
|
151
|
+
}
|
|
152
|
+
|
|
163
153
|
`);
|
|
154
|
+
// Copy NodeManagerRuntime.js into the plugin's build/runtime/ folder so that
|
|
155
|
+
// the generated Nodes.js require("./runtime/NodeManagerRuntime") resolves locally
|
|
156
|
+
// with no dependency on plugincore being installed in the user's environment.
|
|
157
|
+
const outputDir = path.dirname(nodesOutputFile);
|
|
158
|
+
const runtimeDestDir = path.join(outputDir, 'runtime');
|
|
159
|
+
const runtimeDestPath = path.join(runtimeDestDir, 'NodeManagerRuntime.js');
|
|
160
|
+
let runtimeSrcPath;
|
|
161
|
+
try {
|
|
162
|
+
// Resolves when this is a consumer plugin - plugincore is in node_modules.
|
|
163
|
+
runtimeSrcPath = require.resolve('@theotherwillembotha/node-red-plugincore/build/runtime/NodeManagerRuntime');
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// We ARE plugincore - NodeManagerRuntime.js is compiled alongside us in build/core/.
|
|
167
|
+
runtimeSrcPath = path.join(__dirname, 'NodeManagerRuntime.js');
|
|
168
|
+
}
|
|
169
|
+
if (path.resolve(runtimeSrcPath) !== path.resolve(runtimeDestPath)) {
|
|
170
|
+
fs.mkdirSync(runtimeDestDir, { recursive: true });
|
|
171
|
+
fs.copyFileSync(runtimeSrcPath, runtimeDestPath);
|
|
172
|
+
}
|
|
173
|
+
console.log(`NodeManagerRuntime.js → ${runtimeDestPath}`);
|
|
164
174
|
console.log(`Done building ${Object.keys(this._nodes).length} nodes\n${Object.values(this._nodes).map(node => " - " + node.descriptor.id() + "\n").join("")}\n`);
|
|
165
175
|
let serviceExports = this._services.map(service => {
|
|
166
176
|
return ` manager.registerService(${service.name()}.${service.name()});`;
|
|
@@ -192,29 +202,38 @@ module.exports = function (RED) {
|
|
|
192
202
|
|
|
193
203
|
if(addedPlugin && plugin.instantiate && !plugin.instance){
|
|
194
204
|
plugin.instance = new plugin.class();
|
|
195
|
-
|
|
205
|
+
|
|
196
206
|
// instantiate the plugin.
|
|
197
207
|
await plugin.instance.init(RED);
|
|
198
208
|
|
|
209
|
+
// Eagerly call onDeploy with any pre-existing saved flows so that
|
|
210
|
+
// service registries (MetricsService, WebhookServerService, etc.) are
|
|
211
|
+
// populated before config nodes are constructed during flow startup.
|
|
212
|
+
// Without this, MetricsConfigNode._metrics is undefined on first boot.
|
|
213
|
+
const existingFlows = await runtime.flows.getFlows({});
|
|
214
|
+
const hasExistingFlows = existingFlows && existingFlows.flows && existingFlows.flows.length > 0;
|
|
215
|
+
if (hasExistingFlows) {
|
|
216
|
+
await plugin.instance.onDeploy(existingFlows);
|
|
217
|
+
}
|
|
218
|
+
|
|
199
219
|
// publish an event that it has ben deployed.
|
|
200
220
|
RED.events.emit("plugin.instantiated", pluginID);
|
|
201
|
-
|
|
221
|
+
|
|
202
222
|
pluginList.splice(pluginList.findIndex(current => current.id() === addedPlugin.id()), 1);
|
|
203
223
|
|
|
204
224
|
// register a flow deployment listener.
|
|
205
|
-
|
|
225
|
+
// startupDeployment is only needed for a truly fresh Node-RED with no saved flows.
|
|
226
|
+
let startupDeployment = !hasExistingFlows;
|
|
206
227
|
RED.events.on('runtime-event', async (event) => {
|
|
207
|
-
// startup deployment.
|
|
228
|
+
// startup deployment (fresh Node-RED with no pre-existing flows).
|
|
208
229
|
if ("runtime-deploy" === event?.id && startupDeployment) {
|
|
209
|
-
//console.log("STARTUP DEPLOYMENT");
|
|
210
230
|
startupDeployment = false;
|
|
211
231
|
const flows = await runtime.flows.getFlows({});
|
|
212
232
|
await plugin.instance.onDeploy(flows);
|
|
213
233
|
}
|
|
214
|
-
|
|
234
|
+
|
|
215
235
|
// stopping flows on redeployment.
|
|
216
236
|
if ("runtime-state" === event?.id && event?.payload?.state === "stop" && event?.payload?.deploy) {
|
|
217
|
-
//console.log("REDEPLOY!");
|
|
218
237
|
const flows = await runtime.flows.getFlows({});
|
|
219
238
|
await plugin.instance.onDeploy(flows);
|
|
220
239
|
}
|
|
@@ -235,6 +254,38 @@ module.exports = function (RED) {
|
|
|
235
254
|
`;
|
|
236
255
|
fs.writeFileSync(pluginsOutputFile + ".js", output);
|
|
237
256
|
console.log(`Done building ${this._services.length} services\n${this._services.map(service => " - " + service.name() + "\n").join("")}\n`);
|
|
257
|
+
// STEP 4. Generate Plugins.html with deferred client-side node definitions.
|
|
258
|
+
// All nodes are registered via registry:node-set-added so that:
|
|
259
|
+
// a) registerType is only called after typeToId/nodeSets are populated, and
|
|
260
|
+
// b) data-template-name declarations are absent from Nodes.html, avoiding
|
|
261
|
+
// the HTML-scanning conflict that causes Node-RED to reject an entire
|
|
262
|
+
// plugin when a second package declares the same node type.
|
|
263
|
+
const seenOnce = new Set();
|
|
264
|
+
const onceHtmlParts = [];
|
|
265
|
+
const nodePluginParts = [];
|
|
266
|
+
Object.values(this._nodes).forEach(node => {
|
|
267
|
+
console.log(`Building Plugins.html for: ${node.descriptor.id()}`);
|
|
268
|
+
const nb = (0, NodeConstructor_1.buildNodeBuilder)(node.nodeClass);
|
|
269
|
+
nb.buildOnceHtml().forEach(({ source, html }) => {
|
|
270
|
+
if (!seenOnce.has(source)) {
|
|
271
|
+
seenOnce.add(source);
|
|
272
|
+
onceHtmlParts.push(html);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
nodePluginParts.push([
|
|
276
|
+
nb.buildDeferredType(),
|
|
277
|
+
nb.buildHtml(),
|
|
278
|
+
nb.buildDocumentation()
|
|
279
|
+
].join('\n\n'));
|
|
280
|
+
});
|
|
281
|
+
fs.writeFileSync(pluginsOutputFile + ".html", `
|
|
282
|
+
<!--
|
|
283
|
+
${NodeGenerator.warning}
|
|
284
|
+
-->
|
|
285
|
+
${onceHtmlParts.join('\n')}
|
|
286
|
+
${nodePluginParts.join('\n\n')}
|
|
287
|
+
`);
|
|
288
|
+
console.log(`Done building Plugins.html\n`);
|
|
238
289
|
}
|
|
239
290
|
static generateHeader(node) {
|
|
240
291
|
let padding = ' '.repeat(Math.max(0, Math.floor(NodeGenerator.headerWidth - node.id().length) / 2));
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NodeManagerRuntime.ts
|
|
3
|
+
*
|
|
4
|
+
* STANDALONE - zero imports from the rest of plugincore.
|
|
5
|
+
*
|
|
6
|
+
* This file is compiled and copied into every plugin's build output so that
|
|
7
|
+
* plugins are self-contained and do not require plugincore to be separately
|
|
8
|
+
* installed in the user's Node-RED environment.
|
|
9
|
+
*
|
|
10
|
+
* When multiple plugins are deployed, each ships its own copy of this file.
|
|
11
|
+
* The first plugin to load registers its NodeManager and nodes; subsequent
|
|
12
|
+
* copies operate independently on their own node types with no conflict.
|
|
13
|
+
*
|
|
14
|
+
* POST_CONSTRUCT_KEY is intentionally a plain string (not a Symbol) so that
|
|
15
|
+
* the decorators (from plugincore's NodeConstructor, loaded via the plugin's
|
|
16
|
+
* dependency on plugincore) and this runtime file (a separate module instance)
|
|
17
|
+
* resolve to the same property key on node instances.
|
|
18
|
+
*/
|
|
19
|
+
import type { NodeAPI, NodeAPISettingsWithData } from "node-red";
|
|
20
|
+
export declare const NODEMANAGER_API_VERSION = "1.0.0";
|
|
21
|
+
export declare const POST_CONSTRUCT_KEY = "__plugincore_postConstructInitializers__";
|
|
22
|
+
export interface BaseNodeConfig {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
type: string;
|
|
26
|
+
}
|
|
27
|
+
interface INodeDescriptor {
|
|
28
|
+
id(): string;
|
|
29
|
+
tags(): string[];
|
|
30
|
+
}
|
|
31
|
+
interface INodeClass {
|
|
32
|
+
new (node: any, config: any): any;
|
|
33
|
+
getNodeDescriptor(): INodeDescriptor;
|
|
34
|
+
}
|
|
35
|
+
export declare function runPostConstructInitializers(instance: any): void;
|
|
36
|
+
export declare class NodeManager {
|
|
37
|
+
private nodeTypeService;
|
|
38
|
+
private typeBacklog;
|
|
39
|
+
constructor(RED: NodeAPI<NodeAPISettingsWithData>);
|
|
40
|
+
static get RED(): NodeAPI<NodeAPISettingsWithData>;
|
|
41
|
+
registerNodeType(typeName: string, type: INodeClass): NodeManager;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=NodeManagerRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeManagerRuntime.d.ts","sourceRoot":"","sources":["../../src/core/NodeManagerRuntime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAMjE,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAI/C,eAAO,MAAM,kBAAkB,6CAA6C,CAAC;AAI7E,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAe;IACrB,EAAE,IAAI,MAAM,CAAC;IACb,IAAI,IAAI,MAAM,EAAE,CAAC;CACpB;AAED,UAAU,UAAU;IAChB,KAAI,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IACjC,iBAAiB,IAAI,eAAe,CAAC;CACxC;AAID,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,CAoBhE;AA0BD,qBAAa,WAAW;IAGpB,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,WAAW,CAAoB;IAEvC,YAAmB,GAAG,EAAE,OAAO,CAAC,uBAAuB,CAAC,EAuBvD;IAED,WAAkB,GAAG,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAExD;IAEM,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,WAAW,CA6CvE;CACJ"}
|