total5 0.0.1 → 0.0.2

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/flowstream.js ADDED
@@ -0,0 +1,2061 @@
1
+ // Total.js FlowStream
2
+ // The MIT License
3
+ // Copyright 2021-2023 (c) Peter Širka <petersirka@gmail.com>
4
+
5
+ 'use strict';
6
+
7
+ const BLACKLISTID = { paused: 1, groups: 1, tabs: 1 };
8
+ const REG_ARGS = /\{{1,2}[a-z0-9_.-\s]+\}{1,2}/gi;
9
+ const D = '__';
10
+
11
+ function Message() {
12
+ this.ismessage = true;
13
+ this.cloned = 0;
14
+ }
15
+
16
+ Message.prototype = {
17
+
18
+ get user() {
19
+ return this.controller ? this.controller.user : null;
20
+ },
21
+
22
+ get session() {
23
+ return this.controller ? this.controller.session : null;
24
+ },
25
+
26
+ get sessionid() {
27
+ return this.controller && this.controller ? this.controller.req.sessionid : null;
28
+ },
29
+
30
+ get language() {
31
+ return (this.controller ? this.controller.language : '') || '';
32
+ },
33
+
34
+ get ip() {
35
+ return this.controller ? this.controller.ip : null;
36
+ },
37
+
38
+ get req() {
39
+ return this.controller ? this.controller.req : null;
40
+ },
41
+
42
+ get res() {
43
+ return this.controller ? this.controller.res : null;
44
+ },
45
+
46
+ get params() {
47
+ return this.controller ? this.controller.params : null;
48
+ },
49
+
50
+ get files() {
51
+ return this.controller ? this.controller.files : null;
52
+ },
53
+
54
+ get body() {
55
+ return this.controller ? this.controller.body : null;
56
+ },
57
+
58
+ get query() {
59
+ return this.controller ? this.controller.query : null;
60
+ },
61
+
62
+ get headers() {
63
+ return this.controller && this.controller.req ? this.controller.req.headers : null;
64
+ },
65
+
66
+ get ua() {
67
+ return this.controller && this.controller.req ? this.controller.req.ua : null;
68
+ }
69
+ };
70
+
71
+ var MP = Message.prototype;
72
+
73
+ MP.emit = function(name, a, b, c, d, e, f, g) {
74
+
75
+ var self = this;
76
+
77
+ if (!self.$events)
78
+ return self;
79
+
80
+ var evt = self.$events[name];
81
+ if (evt) {
82
+
83
+ var clean = false;
84
+
85
+ for (var e of evt) {
86
+ if (e.once)
87
+ clean = true;
88
+ e.fn.call(self, a, b, c, d, e, f, g);
89
+ }
90
+
91
+ if (clean) {
92
+ var index = 0;
93
+ while (true) {
94
+ if (!evt[index])
95
+ break;
96
+ if (evt[index].once)
97
+ evt.splice(index, 1);
98
+ else
99
+ index++;
100
+ }
101
+ self.$events[name] = evt.length ? evt : undefined;
102
+ }
103
+ }
104
+
105
+ return self;
106
+ };
107
+
108
+ MP.resume = function() {
109
+ sendmessage(this.to, this, this.$emitevent, true);
110
+ };
111
+
112
+ MP.emit2 = function(name, a, b, c, d, e, f, g) {
113
+
114
+ var self = this;
115
+
116
+ if (!self.$events)
117
+ return self;
118
+
119
+ var evt = self.$events[name];
120
+ if (evt) {
121
+
122
+ var clean = false;
123
+
124
+ for (var e of evt) {
125
+ if (e.cloned < self.cloned) {
126
+ if (e.once)
127
+ clean = true;
128
+ e.fn.call(self, a, b, c, d, e, f, g);
129
+ }
130
+ }
131
+
132
+ if (clean) {
133
+ var index = 0;
134
+ while (true) {
135
+ var e = evt[index];
136
+ if (!e)
137
+ break;
138
+ if (e.cloned < self.cloned) {
139
+ if (e.once)
140
+ evt.splice(index, 1);
141
+ else
142
+ index++;
143
+ } else
144
+ index++;
145
+ }
146
+ self.$events[name] = evt.length ? evt : undefined;
147
+ }
148
+ }
149
+
150
+ return self;
151
+ };
152
+
153
+ MP.on = function(name, fn, once) {
154
+ var self = this;
155
+ if (!self.$events)
156
+ self.$events = {};
157
+ var obj = { cloned: self.cloned, fn: fn, once: once };
158
+ if (self.$events[name])
159
+ self.$events[name].push(obj);
160
+ else
161
+ self.$events[name] = [obj];
162
+ return self;
163
+ };
164
+
165
+ MP.once = function(name, fn) {
166
+ return this.on(name, fn, true);
167
+ };
168
+
169
+ MP.off = function(name, fn) {
170
+ var self = this;
171
+
172
+ if (!name) {
173
+ delete self.$events;
174
+ return;
175
+ }
176
+
177
+ if (self.$events) {
178
+ var evt = self.$events[name];
179
+ if (evt) {
180
+ if (fn) {
181
+ evt = evt.remove(n => n.fn === fn);
182
+ self.$events[name] = evt.length ? evt : undefined;
183
+ } else
184
+ delete self.$events[name];
185
+ }
186
+ }
187
+ return self;
188
+ };
189
+
190
+ MP.clone = function() {
191
+
192
+ var self = this;
193
+ var obj = new Message();
194
+ obj.previd = self.id;
195
+ obj.$events = self.$events;
196
+ obj.duration = self.duration;
197
+ obj.repo = self.repo;
198
+ obj.vars = self.vars;
199
+ obj.main = self.main;
200
+ obj.refs = self.refs;
201
+ obj.count = self.count;
202
+ obj.data = self.data;
203
+ obj.used = self.used;
204
+ obj.processed = 0;
205
+ obj.controller = self.controller;
206
+ obj.cloned = self.cloned + 1;
207
+ obj.$timeoutidtotal = self.$timeoutidtotal;
208
+ obj.color = self.color;
209
+
210
+ if (obj.refs.pending)
211
+ obj.refs.pending++;
212
+ else
213
+ obj.refs.pending = 1;
214
+
215
+ // additional custom variables
216
+ obj.uid = self.uid;
217
+ obj.reference = self.reference;
218
+ obj.ref = self.ref;
219
+
220
+ if (obj.$events && obj.$events.timeout) {
221
+ var index = 0;
222
+ while (true) {
223
+ var e = obj.$events.timeout[index];
224
+ if (e) {
225
+ if ((e.cloned + 1) < obj.cloned)
226
+ obj.$events.timeout.splice(index, 1);
227
+ else
228
+ index++;
229
+ } else
230
+ break;
231
+ }
232
+ }
233
+
234
+ if (self.$timeoutid) {
235
+ clearTimeout(self.$timeoutid);
236
+ self.$timeoutid = null;
237
+ }
238
+
239
+ return obj;
240
+ };
241
+
242
+ MP.status = function(a, b, c, d) {
243
+ this.instance.status(a, b, c, d);
244
+ return this;
245
+ };
246
+
247
+ MP.dashboard = function(a, b, c, d) {
248
+ this.instance.dashboard(a, b, c, d);
249
+ return this;
250
+ };
251
+
252
+ MP.debug = function(a, b, c, d) {
253
+ this.instance.debug(a, b, c, d);
254
+ return this;
255
+ };
256
+
257
+ MP.throw = function(a, b, c, d) {
258
+ this.error = a;
259
+ this.instance.throw(a, b, c, d);
260
+ return this;
261
+ };
262
+
263
+ function variables(str, data, encoding) {
264
+
265
+ if (typeof(str) === 'object') {
266
+ var obj = {};
267
+ for (var key in str) {
268
+ var val = str[key];
269
+ if (typeof(val) === 'string')
270
+ obj[key] = variables.call(this, val, data, encoding);
271
+ else
272
+ obj[key] = val;
273
+ }
274
+ return obj;
275
+ }
276
+
277
+ if (typeof(str) !== 'string' || str.indexOf('{') === -1)
278
+ return str;
279
+
280
+ var main = this.main ? this.main : this;
281
+
282
+ if (data == null || data == true)
283
+ data = this;
284
+
285
+ return str.replace(REG_ARGS, function(text) {
286
+
287
+ var l = text[1] === '{' ? 2 : 1;
288
+ var key = text.substring(l, text.length - l).trim();
289
+ var val = null;
290
+
291
+ if (main.variables)
292
+ val = main.variables[key];
293
+
294
+ if (!val && main.variables2)
295
+ val = main.variables2[key];
296
+
297
+ if (!val && main.secrets)
298
+ val = main.secrets[key];
299
+
300
+ if (!val && key === 'hostname') {
301
+ val = (main.$schema.origin || '') + (main.$schema.proxypath || '');
302
+ if (val[val.length - 1] === '/')
303
+ val = val.substring(0, val.length - 1);
304
+ }
305
+
306
+ var customencoding = typeof(encoding) === 'function';
307
+
308
+ if (!val && data != null && typeof(data) === 'object') {
309
+ var nested = key.indexOf('.') !== -1;
310
+ val = nested ? F.TUtils.get(data, key) : data[key];
311
+ }
312
+
313
+ if (customencoding) {
314
+
315
+ val = encoding(val, key);
316
+
317
+ } else {
318
+
319
+ if (encoding !== 'json') {
320
+ if (val instanceof Date)
321
+ val = val.format();
322
+ }
323
+
324
+ switch (encoding) {
325
+ case 'urlencoded':
326
+ case 'url':
327
+ val = encodeURIComponent(val);
328
+ break;
329
+ case 'json':
330
+ val = JSON.stringify(val);
331
+ break;
332
+ case 'querify':
333
+ val = F.TUtils.querify(val).substring(1);
334
+ break;
335
+ }
336
+ }
337
+
338
+ return val == null ? text : val;
339
+
340
+ });
341
+ }
342
+
343
+ MP.replace = MP.variables = function(str, data, encoding) {
344
+ return variables.call(this, str, data, encoding);
345
+ };
346
+
347
+ function timeouthandler(msg) {
348
+ msg.error = 408;
349
+ msg.$events.timeout && msg.emit('timeout', msg);
350
+ msg.$events.timeout2 && msg.emit('timeout2', msg);
351
+ msg.end();
352
+ }
353
+
354
+ MP.send = function(outputindex, data, clonedata) {
355
+
356
+ var self = this;
357
+
358
+ if (clonedata == null)
359
+ clonedata = self.main.cloning;
360
+
361
+ if (self.isdestroyed || self.main.paused || (self.instance && self.instance.isdestroyed)) {
362
+ if (!self.isdestroyed)
363
+ self.destroy();
364
+ return 0;
365
+ }
366
+
367
+ var outputs;
368
+ var count = 0;
369
+
370
+ if (outputindex == null) {
371
+
372
+ if (self.instance.connections) {
373
+ for (var key in self.instance.connections)
374
+ count += self.send(key);
375
+ }
376
+
377
+ if (!count)
378
+ self.destroy();
379
+
380
+ return count;
381
+ }
382
+
383
+ var meta = self.main.meta;
384
+ var now = Date.now();
385
+
386
+ outputs = self.instance.connections ? (self.instance.connections[outputindex] || F.EMPTYARRAY) : F.EMPTYARRAY;
387
+
388
+ if (self.processed === 0) {
389
+ self.processed = 1;
390
+ self.main.stats.pending--;
391
+
392
+ if (self.main.stats.pending < 0)
393
+ self.main.stats.pending = 0;
394
+
395
+ self.instance.stats.pending--;
396
+
397
+ if (self.instance.stats.pending < 0)
398
+ self.instance.stats.pending = 0;
399
+
400
+ self.instance.stats.output++;
401
+ self.instance.stats.duration = now - self.ts;
402
+ }
403
+
404
+ if (!self.main.$can(false, self.instance.id, outputindex)) {
405
+ self.destroy();
406
+ return count;
407
+ }
408
+
409
+ var tid = self.toid + D + outputindex + (self.color || '');
410
+
411
+ if (self.main.stats.traffic[tid]) {
412
+ self.main.stats.traffic[tid]++;
413
+ } else {
414
+ self.main.stats.traffic[tid] = 1;
415
+ self.main.stats.traffic.priority.push(tid);
416
+ }
417
+
418
+ if (self.transformation === '1')
419
+ self.transformation = '_' + tid;
420
+
421
+ for (var i = 0; i < outputs.length; i++) {
422
+ var output = outputs[i];
423
+
424
+ if (output.disabled || output.paused)
425
+ continue;
426
+
427
+ var schema = meta.flow[output.id];
428
+ if (schema && (schema.message || schema['message_' + output.index]) && schema.component && schema.ready && self.main.$can(true, output.id, output.index)) {
429
+ var next = meta.components[schema.component];
430
+ if (next && next.connected && !next.isdestroyed && !next.disabled) {
431
+
432
+ if (output.color && self.color && self.color !== output.color)
433
+ continue;
434
+
435
+ var inputindex = output.index;
436
+ var message = self.clone();
437
+
438
+ if (data != undefined)
439
+ message.data = data;
440
+
441
+ if (clonedata && message.data && typeof(message.data) === 'object') {
442
+ if (message.data instanceof Buffer) {
443
+ var buf = Buffer.alloc(message.data.length);
444
+ buf.copy(message.data);
445
+ message.data = buf;
446
+ } else
447
+ message.data = F.TUtils.clone(message.data);
448
+ }
449
+
450
+ message.used++;
451
+ message.instance = schema;
452
+ message.from = self.to;
453
+ message.fromid = self.toid;
454
+ message.fromcomponent = self.instance.component;
455
+ message.to = schema;
456
+ message.toid = output.id;
457
+ message.output = outputindex;
458
+ message.input = message.index = inputindex;
459
+ message.tocomponent = schema.component;
460
+ message.cache = schema.cache;
461
+ message.ts = now;
462
+ message.color = output.color;
463
+
464
+ if (self.$timeout)
465
+ message.$timeoutid = setTimeout(timeouthandler, self.$timeout, message);
466
+
467
+ schema.stats.input++;
468
+ schema.stats.pending++;
469
+
470
+ self.main.stats.messages++;
471
+ self.main.stats.pending++;
472
+ self.main.mm++;
473
+
474
+ if (self.$events) {
475
+ self.$events.next && self.emit2('next', self, message);
476
+ self.$events.something && self.emit2('something', self, message);
477
+ self.$events.message && self.emit('message', message);
478
+ }
479
+
480
+ setImmediate(sendmessage, schema, message, true);
481
+ count++;
482
+ }
483
+ }
484
+ }
485
+
486
+ if (count) {
487
+ self.refs.pending--;
488
+ if (self.refs.pending < 0)
489
+ self.refs.pending = 0;
490
+ } else
491
+ self.destroy();
492
+
493
+ return count;
494
+ };
495
+
496
+ MP.rewrite = function(data) {
497
+ this.data = data;
498
+ return this;
499
+ };
500
+
501
+ MP.totaltimeout = function(callback, time) {
502
+
503
+ if (time == null)
504
+ time = callback;
505
+ else
506
+ this.on('timeout2', callback);
507
+
508
+ this.$timeoutidtotal && clearTimeout(this.$timeoutidtotal);
509
+ this.$timeoutidtotal = setTimeout(timeouthandler, time, this);
510
+ return this;
511
+ };
512
+
513
+ MP.timeout = function(callback, time) {
514
+
515
+ if (time == null)
516
+ time = callback;
517
+ else
518
+ this.on('timeout', callback);
519
+
520
+ this.$timeout = time;
521
+ return this;
522
+ };
523
+
524
+ MP.end = MP.destroy = function() {
525
+
526
+ var self = this;
527
+
528
+ if (self.isdestroyed)
529
+ return;
530
+
531
+ if (self.processed === 0) {
532
+ self.processed = 1;
533
+ self.main.stats.pending--;
534
+
535
+ if (self.main.stats.pending < 0)
536
+ self.main.stats.pending = 0;
537
+
538
+ self.instance.stats.pending--;
539
+
540
+ if (self.instance.stats.pending < 0)
541
+ self.instance.stats.pending = 0;
542
+
543
+ self.instance.stats.duration = Date.now() - self.ts;
544
+ self.instance.stats.destroyed++;
545
+ }
546
+
547
+ if (self.$timeoutid) {
548
+ clearTimeout(self.$timeoutid);
549
+ self.$timeoutid = null;
550
+ }
551
+
552
+ if (self.$timeoutidtotal) {
553
+ clearTimeout(self.$timeoutidtotal);
554
+ self.$timeoutidtotal = null;
555
+ }
556
+
557
+ if (self.refs.pending) {
558
+ self.refs.pending--;
559
+ if (self.refs.pending < 0)
560
+ self.refs.pending = 0;
561
+ }
562
+
563
+ if (self.$events) {
564
+ self.$events.something && self.emit('something', self);
565
+ self.$events.terminate && self.emit('terminate', self);
566
+ }
567
+
568
+ if (!self.refs.pending) {
569
+ if (self.$events) {
570
+ self.$events.end && self.emit('end', self);
571
+ self.$events.destroy && self.emit('destroy', self);
572
+ }
573
+ if (self.main.$events)
574
+ self.main.$events.end && self.main.emit('end', self);
575
+ }
576
+
577
+ self.isdestroyed = true;
578
+ self.repo = null;
579
+ self.main = null;
580
+ self.middleware = null;
581
+ self.from = null;
582
+ self.to = null;
583
+ self.data = null;
584
+ self.instance = null;
585
+ self.duration = null;
586
+ self.ts = null;
587
+ self.$events = null;
588
+ };
589
+
590
+ function FlowStream(name, errorhandler) {
591
+ var t = this;
592
+ t.strict = true;
593
+ t.loading = 0;
594
+ t.cloning = true;
595
+ t.error = errorhandler || console.error;
596
+ t.id = t.name = name;
597
+ t.uid = Date.now().toString(36) + 'X';
598
+ t.meta = {};
599
+ t.meta.components = {};
600
+ t.meta.flow = {};
601
+ t.meta.cache = {};
602
+ t.logger = [];
603
+ t.middleware = [];
604
+ t.stats = { messages: 0, pending: 0, traffic: { priority: [] }, mm: 0, minutes: 0 };
605
+ t.paused = false;
606
+ t.mm = 0;
607
+ new F.TUtils.EventEmitter2(t);
608
+ }
609
+
610
+ var FP = FlowStream.prototype;
611
+
612
+ FP.service = function(counter) {
613
+
614
+ var t = this;
615
+ var is = t.mm;
616
+
617
+ if (counter % 12 === 0) {
618
+
619
+ t.stats.minutes++;
620
+ t.stats.mm = t.mm;
621
+ t.mm = 0;
622
+
623
+ for (let key in t.meta.flow) {
624
+ let com = t.meta.flow[key];
625
+ com.service && com.service(t.stats.minutes);
626
+ }
627
+
628
+ if (t.stats.traffic.priority.length)
629
+ is = 1;
630
+
631
+ }
632
+
633
+ t.onstats && t.onstats(t.stats);
634
+ t.$events.stats && t.emit('stats', t.stats);
635
+
636
+ if (is)
637
+ t.stats.traffic = { priority: [] };
638
+
639
+ };
640
+
641
+ FP.pause = function(is) {
642
+ var self = this;
643
+ self.paused = is;
644
+ for (let m in self.meta.flow) {
645
+ let instance = self.meta.flow[m];
646
+ if (instance && instance.pause)
647
+ instance.pause(is);
648
+ }
649
+ return self;
650
+ };
651
+
652
+ FP.register = function(name, declaration, config, callback, extend) {
653
+
654
+ var self = this;
655
+ var type = typeof(declaration);
656
+
657
+ if (type === 'string') {
658
+
659
+ if (!declaration) {
660
+ let e = new Error('Invalid component declaration');
661
+ callback && callback(e);
662
+ self.error(e, 'register', name);
663
+ return;
664
+ }
665
+
666
+ try {
667
+ declaration = new Function('instance', declaration);
668
+ } catch (e) {
669
+ callback && callback(e);
670
+ self.error(e, 'register', name);
671
+ return;
672
+ }
673
+ }
674
+
675
+ var cache;
676
+ var prev = self.meta.components[name];
677
+ if (prev) {
678
+ cache = prev.cache;
679
+ prev.connected = false;
680
+ prev.disabled = true;
681
+ prev.destroy = null;
682
+ prev.disconnect && prev.disconnect();
683
+ }
684
+
685
+ var curr = { id: name, main: self, connected: true, disabled: false, cache: cache || {}, config: config || {}, stats: {}, ui: {}, iscomponent: true };
686
+
687
+ if (extend) {
688
+ try {
689
+ var cacheid = name;
690
+ if (type === 'object') {
691
+ for (let key in declaration)
692
+ curr[key] = declaration[key];
693
+ } else
694
+ declaration(curr, F.require);
695
+ curr.id = cacheid;
696
+ } catch (e) {
697
+ self.error(e, 'register', name);
698
+ callback && callback(e);
699
+ return;
700
+ }
701
+ } else
702
+ curr.make = type === 'object' ? declaration.make : declaration;
703
+
704
+ curr.config = F.TUtils.clone(curr.config || curr.options);
705
+
706
+ var errors = new F.ErrorBuilder();
707
+ var done = function() {
708
+
709
+ self.inc(-1);
710
+ self.meta.components[name] = curr;
711
+ self.onregister && self.onregister(curr);
712
+ self.$events.register && self.emit('register', name, curr);
713
+ curr.install && !prev && curr.install.call(curr, curr);
714
+
715
+ for (var key in self.meta.flow) {
716
+ if (!BLACKLISTID[key]) {
717
+ var f = self.meta.flow[key];
718
+ if (f.component === curr.id)
719
+ self.initcomponent(key, curr);
720
+ }
721
+ }
722
+
723
+ self.clean();
724
+ callback && callback(errors.length ? errors : null);
725
+ };
726
+
727
+ self.inc(1);
728
+
729
+ if (curr.npm && curr.npm.length) {
730
+ curr.npm.wait(function(name, next) {
731
+ NPMINSTALL(name, function(err) {
732
+ if (err) {
733
+ self.error(err, 'npm');
734
+ errors.push(err);
735
+ }
736
+ next();
737
+ });
738
+ }, done);
739
+ } else
740
+ setImmediate(done);
741
+
742
+ return curr;
743
+ };
744
+
745
+ FP.destroy = function() {
746
+ var self = this;
747
+
748
+ clearInterval(self.$interval);
749
+ self.$interval = null;
750
+
751
+ self.inc(1);
752
+ self.unload(function() {
753
+ self.inc(-1);
754
+ self.emit('destroy');
755
+ self.meta = null;
756
+ self.$events = null;
757
+ delete F.flowstreams[self.name];
758
+ });
759
+
760
+ };
761
+
762
+ FP.inc = function(num) {
763
+
764
+ var self = this;
765
+
766
+ if (num === 0)
767
+ self.loading = 0;
768
+ else if (num === -1)
769
+ self.loading--;
770
+ else
771
+ self.loading++;
772
+
773
+ // Assurance
774
+ if (self.loading < 0)
775
+ self.loading = 0;
776
+
777
+ return self;
778
+ };
779
+
780
+ FP.cleanforce = function() {
781
+
782
+ var self = this;
783
+
784
+ if (self.cleantimeout) {
785
+ clearTimeout(self.cleantimeout);
786
+ self.cleantimeout = null;
787
+ }
788
+
789
+ if (!self.meta)
790
+ return self;
791
+
792
+ for (var key in self.meta.flow) {
793
+ if (!BLACKLISTID[key]) {
794
+ var instance = self.meta.flow[key];
795
+ if (instance.connections) {
796
+
797
+ for (var key2 in instance.connections) {
798
+
799
+ var conns = instance.connections[key2];
800
+ var rem = {};
801
+
802
+ for (var conn of conns) {
803
+ if (conn) {
804
+ var target = self.meta.flow[conn.id];
805
+ if (target) {
806
+ var com = self.meta.components[target.component];
807
+ if (com) {
808
+ if (self.strict) {
809
+ if (target.inputs) {
810
+ if (!target.inputs.findItem('id', conn.index))
811
+ rem[conn.id] = 1;
812
+ } else if (!com.inputs || !com.inputs.findItem('id', conn.index))
813
+ rem[conn.id] = 1;
814
+ }
815
+ } else
816
+ rem[conn.id] = 1;
817
+ } else
818
+ rem[conn.id] = 1;
819
+ }
820
+ }
821
+
822
+ var arr = conns.remove(c => c == null || rem[c.id] === 1);
823
+ if (arr.length)
824
+ instance.connections[key2] = arr;
825
+ else
826
+ delete instance.connections[key2];
827
+ }
828
+ }
829
+ }
830
+ }
831
+
832
+ var paused = self.meta.flow.paused;
833
+ if (paused) {
834
+ for (var key in paused) {
835
+ var arr = key.split(D);
836
+ // arr[0] type
837
+ // arr[1] id
838
+ // arr[2] index
839
+ if (!self.meta.flow[arr[1]])
840
+ delete paused[key];
841
+ }
842
+ }
843
+
844
+ var fn = key => self.meta.flow[key] == null;
845
+ self.logger = self.logger.remove(fn);
846
+ self.middleware = self.middleware.remove(fn);
847
+ return self;
848
+ };
849
+
850
+ FP.unregister = function(name, callback) {
851
+
852
+ var self = this;
853
+
854
+ if (name == null) {
855
+ Object.keys(self.meta.components).wait(function(key, next) {
856
+ self.unregister(key, next);
857
+ }, callback);
858
+ return self;
859
+ }
860
+
861
+ var curr = self.meta.components[name];
862
+ if (curr) {
863
+ self.onunregister && self.onunregister(curr);
864
+ self.$events.unregister && self.emit('unregister', name, curr);
865
+ self.inc(1);
866
+ Object.keys(self.meta.flow).wait(function(key, next) {
867
+
868
+ var instance = self.meta.flow[key];
869
+ if (instance) {
870
+ if (instance.component === name) {
871
+ instance.ready = false;
872
+ try {
873
+ instance.isdestroyed = true;
874
+ self.ondisconnect && self.ondisconnect(instance);
875
+ self.$events.disconnect && self.emit('disconnect', instance);
876
+ instance.close && instance.close.call(instance, true);
877
+ instance.destroy && instance.destroy.call(instance);
878
+ } catch (e) {
879
+ self.onerror.call(instance, e, 'instance_close', key);
880
+ }
881
+ delete self.meta.flow[key];
882
+ }
883
+ } else
884
+ delete self.meta.flow[key];
885
+
886
+ next();
887
+
888
+ }, function() {
889
+ self.inc(-1);
890
+ curr.connected = false;
891
+ curr.disabled = true;
892
+ curr.uninstall && curr.uninstall.call(curr, curr);
893
+ curr.destroy = null;
894
+ curr.cache = null;
895
+ delete self.meta.components[name];
896
+ callback && callback();
897
+ self.clean();
898
+ });
899
+ } else if (callback)
900
+ callback();
901
+
902
+ return self;
903
+ };
904
+
905
+ FP.clean = function() {
906
+ var self = this;
907
+ if (!self.loading) {
908
+ self.cleantimeout && clearTimeout(self.cleantimeout);
909
+ self.cleantimeout = setTimeout(() => self.cleanforce(), 1000);
910
+ }
911
+ return self;
912
+ };
913
+
914
+ /*
915
+ FP.ondisconnect = function(instance) {
916
+ };
917
+
918
+ FP.onconnect = function(instance) {
919
+ };
920
+
921
+ FP.onregister = function(component) {
922
+ };
923
+
924
+ FP.onunregister = function(component) {
925
+ };
926
+
927
+ FP.onreconfigure = function(instance, init) {
928
+
929
+ };
930
+ */
931
+
932
+ FP.ondashboard = function(a, b, c, d) {
933
+ // this == instance
934
+ this.main.$events.dashboard && this.main.emit('dashboard', this, a, b, c, d);
935
+ };
936
+
937
+ FP.onstatus = function(a, b, c, d) {
938
+ // this == instance
939
+ this.main.$events.status && this.main.emit('status', this, a, b, c, d);
940
+ };
941
+
942
+ FP.onerror = function(a, b, c, d) {
943
+ // this == instance
944
+ this.main.$events.error && this.main.emit('error', this, a, b, c, d);
945
+ };
946
+
947
+ FP.ondebug = function(a, b, c, d) {
948
+ // this == instance
949
+ this.main.$events.debug && this.main.emit('debug', this, a, b, c, d);
950
+ };
951
+
952
+ function newlogger(callback) {
953
+
954
+ var self = this;
955
+ self.$logger = callback;
956
+
957
+ var index = self.main.logger.indexOf(self.id);
958
+ if (callback) {
959
+ if (index === -1)
960
+ self.main.logger.push(self.id);
961
+ } else {
962
+ if (index !== -1)
963
+ self.main.logger.splice(index, 1);
964
+ }
965
+
966
+ return self;
967
+ }
968
+
969
+ function newmiddleware(callback) {
970
+
971
+ var self = this;
972
+ self.$middleware = callback;
973
+
974
+ var index = self.main.middleware.indexOf(self.id);
975
+ if (callback) {
976
+ if (index === -1)
977
+ self.main.middleware.push(self.id);
978
+ } else {
979
+ if (index !== -1)
980
+ self.main.middleware.splice(index, 1);
981
+ }
982
+
983
+ return self;
984
+ }
985
+
986
+
987
+ function newmessage(data) {
988
+ var self = this;
989
+ var msg = new Message();
990
+ msg.refs = { pending: 1 };
991
+ msg.repo = {};
992
+ msg.vars = {};
993
+ msg.to = msg.instance = self;
994
+ msg.toid = self.id;
995
+ msg.tocomponent = self.component;
996
+ msg.data = data instanceof Message ? data.data : data;
997
+ msg.cloned = 0;
998
+ msg.count = 0;
999
+ msg.instance = self;
1000
+ msg.duration = msg.ts = Date.now();
1001
+ msg.used = 1;
1002
+ msg.main = self instanceof FlowStream ? self : self.main;
1003
+ msg.processed = 0;
1004
+ return msg;
1005
+ }
1006
+
1007
+ // New transform message
1008
+ function newtransform(output, data, callback) {
1009
+
1010
+ if (typeof(data) === 'function') {
1011
+ callback = data;
1012
+ data = undefined;
1013
+ }
1014
+
1015
+ var self = this;
1016
+ var msg = newmessage.call(self, data);
1017
+
1018
+ msg.on('destroy', function($) {
1019
+
1020
+ if (callback) {
1021
+ var tmp = msg.transformation;
1022
+ if (tmp && tmp !== '1') {
1023
+ if (self.main.stats.traffic[tmp]) {
1024
+ self.main.stats.traffic[tmp]++;
1025
+ } else {
1026
+ self.main.stats.traffic[tmp] = 1;
1027
+ self.main.stats.traffic.priority.push(tmp);
1028
+ }
1029
+ }
1030
+
1031
+ callback($);
1032
+ callback = null;
1033
+ }
1034
+
1035
+ });
1036
+
1037
+ msg.transformation = '1';
1038
+ msg.send(output);
1039
+ //setImmediate(() => msg.send(output));
1040
+ //return msg;
1041
+ }
1042
+
1043
+ FP.ontrigger = function(outputindex, data, controller, events) {
1044
+
1045
+ // this == instance
1046
+
1047
+ var schema = this;
1048
+ var self = schema.main;
1049
+ var count = 0;
1050
+
1051
+ if (self.paused)
1052
+ return count;
1053
+
1054
+ if (schema && schema.ready && schema.component && schema.connections) {
1055
+ var instance = self.meta.components[schema.component];
1056
+ if (instance && instance.connected && !instance.disabled && self.$can(false, schema.id, outputindex)) {
1057
+ var conn = schema.connections[outputindex];
1058
+ if (conn && conn.length) {
1059
+
1060
+ var ts = Date.now();
1061
+ for (var i = 0; i < conn.length; i++) {
1062
+
1063
+ var m = conn[i];
1064
+ var target = self.meta.flow[m.id];
1065
+
1066
+ if (!target || (!target.message && !target['message_' + m.index]) || !self.$can(true, m.id, m.index))
1067
+ continue;
1068
+
1069
+ var com = self.meta.components[target.component];
1070
+ if (!com)
1071
+ continue;
1072
+
1073
+ if (target.isdestroyed || (data && data.instance && data.instance.isdestroyed))
1074
+ continue;
1075
+
1076
+ var ismessage = data instanceof Message;
1077
+ if (ismessage && m.color && data.color && data.color !== m.color)
1078
+ continue;
1079
+
1080
+ var message = ismessage ? data.clone() : new Message();
1081
+
1082
+ if (ismessage) {
1083
+
1084
+ if (data.isdestroyed)
1085
+ return 0;
1086
+
1087
+ if (data.processed === 0) {
1088
+ data.processed = 1;
1089
+
1090
+ data.main.stats.pending--;
1091
+
1092
+ if (data.main.stats.pending < 0)
1093
+ data.main.stats.pending = 0;
1094
+
1095
+ if (data.instance) {
1096
+ data.instance.stats.pending--;
1097
+
1098
+ if (data.instance.stats.pending < 0)
1099
+ data.instance.stats.pending = 0;
1100
+
1101
+ data.instance.stats.output++;
1102
+ data.instance.stats.duration = ts - self.ts;
1103
+ }
1104
+ }
1105
+ } else {
1106
+ message.refs = { pending: 1 };
1107
+ message.$events = events || {};
1108
+ message.repo = {};
1109
+ message.vars = {};
1110
+ message.data = data;
1111
+ message.duration = message.ts = ts;
1112
+ message.used = 1;
1113
+ }
1114
+
1115
+ if (i && (self.cloning != false) && message.data && typeof(message.data) === 'object') {
1116
+ if (message.data instanceof Buffer) {
1117
+ var buf = Buffer.alloc(message.data.length);
1118
+ buf.copy(message.data);
1119
+ message.data = buf;
1120
+ } else
1121
+ message.data = F.TUtils.clone(message.data);
1122
+ }
1123
+
1124
+ message.main = self;
1125
+ message.controller = controller;
1126
+ message.instance = target;
1127
+ message.color = m.color;
1128
+
1129
+ message.from = schema;
1130
+ message.fromid = schema.id;
1131
+ message.fromcomponent = schema.component;
1132
+ message.output = outputindex;
1133
+
1134
+ message.to = message.instance = target;
1135
+ message.toid = m.id;
1136
+ message.input = message.index = m.index;
1137
+ message.tocomponent = target.component;
1138
+ message.cache = target.cache;
1139
+ message.processed = 0;
1140
+
1141
+ target.stats.pending++;
1142
+ target.stats.input++;
1143
+ schema.stats.output++;
1144
+ message.main.stats.pending++;
1145
+ message.main.stats.messages++;
1146
+ message.main.mm++;
1147
+
1148
+ message.id = message.main.uid + message.main.stats.messages;
1149
+ message.count = message.main.stats.messages;
1150
+
1151
+ if (message.fromid && !count) {
1152
+ var tid = message.fromid + D + message.output + (message.color || '');
1153
+ if (message.main.stats.traffic[tid])
1154
+ message.main.stats.traffic[tid]++;
1155
+ else {
1156
+ message.main.stats.traffic[tid] = 1;
1157
+ message.main.stats.traffic.priority.push(tid);
1158
+ }
1159
+ }
1160
+
1161
+ if (ismessage && data.$timeout)
1162
+ message.$timeoutid = setTimeout(timeouthandler, data.$timeout, message);
1163
+
1164
+ if (ismessage) {
1165
+ data.next && data.emit2('next', data, message);
1166
+ data.something && data.emit2('something', data, message);
1167
+ data.message && data.emit('message', message);
1168
+ }
1169
+
1170
+ count++;
1171
+ setImmediate(sendmessage, target, message, true);
1172
+ }
1173
+ }
1174
+ }
1175
+ }
1176
+
1177
+ return count;
1178
+ };
1179
+
1180
+ FP.reconfigure = function(id, config, rewrite) {
1181
+ var self = this;
1182
+ var instance = self.meta.flow[id];
1183
+ if (instance && !instance.isdestroyed) {
1184
+
1185
+ if (rewrite)
1186
+ instance.config = config;
1187
+ else
1188
+ F.TUtils.extend(instance.config, config);
1189
+
1190
+ instance.configure && instance.configure(instance.config);
1191
+ self.onreconfigure && self.onreconfigure(instance);
1192
+ self.$events.configure && self.emit('configure', instance);
1193
+ }
1194
+ return !!instance;
1195
+ };
1196
+
1197
+ FP.unload = function(callback) {
1198
+ var self = this;
1199
+ var keys = Object.keys(self.meta.flow);
1200
+ keys.wait(function(key, next) {
1201
+ var current = self.meta.flow[key];
1202
+ if (current) {
1203
+ current.isdestroyed = true;
1204
+ self.ondisconnect && self.ondisconnect(current);
1205
+ try {
1206
+ current.close && current.close.call(current, true);
1207
+ current.destroy && current.destroy.call(current);
1208
+ } catch(e) {
1209
+ self.onerror.call(current, e, 'instance_close', key);
1210
+ }
1211
+ }
1212
+ delete self.meta.flow[key];
1213
+ next();
1214
+ }, function() {
1215
+ // uninstall components
1216
+ self.unregister(null, callback);
1217
+ });
1218
+ return self;
1219
+ };
1220
+
1221
+ FP.loadvariables = function(variables, type = 'variables') {
1222
+
1223
+ // @type {String} variables (default), variables2, secrets
1224
+
1225
+ var self = this;
1226
+ if (JSON.stringify(self[type]) !== JSON.stringify(variables)) {
1227
+ self[type] = variables;
1228
+ for (let key in self.meta.flow) {
1229
+ let instance = self.meta.flow[key];
1230
+ instance[type] && instance[type](self[type]);
1231
+ instance.vary && instance.vary(type);
1232
+ }
1233
+ }
1234
+ return self;
1235
+ };
1236
+
1237
+ FP.load = function(data, callback) {
1238
+
1239
+ var self = this;
1240
+ if (self.loading) {
1241
+ setTimeout(() => self.load(data, callback), 200);
1242
+ return self;
1243
+ }
1244
+
1245
+ self.loading = 100000;
1246
+ self.unload(function() {
1247
+
1248
+ var keys = Object.keys(data.components);
1249
+ var error = new F.ErrorBuilder();
1250
+
1251
+ keys.wait(function(key, next) {
1252
+ var body = data.components[key];
1253
+ if (typeof(body) === 'string' && body.indexOf('<script ') !== -1) {
1254
+ self.add(key, body, function(err) {
1255
+ err && error.push(err);
1256
+ next();
1257
+ }, data.asfiles);
1258
+ } else {
1259
+ error.push('Invalid component: ' + key);
1260
+ next();
1261
+ }
1262
+ }, function() {
1263
+
1264
+ // Loads design
1265
+ self.inc(0);
1266
+ self.use(data.design, function(err) {
1267
+ self.inc(0);
1268
+ err && error.push(err);
1269
+ self.clean();
1270
+ callback && callback(err);
1271
+ });
1272
+
1273
+ });
1274
+ });
1275
+
1276
+ return self;
1277
+ };
1278
+
1279
+ FP.replace = variables;
1280
+ FP.rewrite = function(data, callback) {
1281
+
1282
+ var self = this;
1283
+ if (self.loading) {
1284
+ setTimeout(() => self.replace(data, callback), 200);
1285
+ return self;
1286
+ }
1287
+
1288
+ self.loading = 100000;
1289
+
1290
+ var keys = Object.keys(data.components);
1291
+ var error = new F.ErrorBuilder();
1292
+ var processed = {};
1293
+
1294
+ keys.wait(function(key, next) {
1295
+ var body = data.components[key];
1296
+ processed[key] = 1;
1297
+ if (typeof(body) === 'string' && body.indexOf('<script ') !== -1) {
1298
+ self.add(key, body, function(err) {
1299
+ err && error.push(err);
1300
+ next();
1301
+ }, data.asfiles);
1302
+ } else {
1303
+ error.push('Invalid component: ' + key);
1304
+ next();
1305
+ }
1306
+ }, function() {
1307
+ // Removed non-exist components
1308
+ Object.keys(self.meta.components).wait(function(key, next) {
1309
+ if (processed[key])
1310
+ next();
1311
+ else
1312
+ self.unregister(key, next);
1313
+ }, function() {
1314
+ // Loads design
1315
+ self.inc(0);
1316
+ self.use(data.design, function(err) {
1317
+
1318
+ if (data.variables)
1319
+ self.loadvariables(F.TUtils.clone(data.variables));
1320
+
1321
+ self.inc(0);
1322
+ err && error.push(err);
1323
+ self.clean();
1324
+ callback && callback(err);
1325
+ });
1326
+ });
1327
+ });
1328
+
1329
+ return self;
1330
+ };
1331
+
1332
+ FP.insert = function(schema, callback) {
1333
+ var self = this;
1334
+ if (callback)
1335
+ self._use(schema, callback, null, true);
1336
+ else
1337
+ return new Promise((resolve, reject) => self._use(schema, (err, res) => err ? reject(err) : resolve(res), null, true));
1338
+ };
1339
+
1340
+ FP.remove = function(keys, callback) {
1341
+ var self = this;
1342
+ if (callback)
1343
+ self._remove(keys, callback);
1344
+ else
1345
+ return new Promise((resolve, reject) => self._remove(keys, (err, res) => err ? reject(err) : resolve(res), null, true));
1346
+ };
1347
+
1348
+ FP._remove = function(keys, callback) {
1349
+ var self = this;
1350
+
1351
+ if (!(keys instanceof Array))
1352
+ keys = Object.keys(keys);
1353
+
1354
+ for (var key of keys) {
1355
+
1356
+ if (BLACKLISTID[key]) {
1357
+ delete self.meta.flow[key];
1358
+ continue;
1359
+ }
1360
+
1361
+ var instance = self.meta.flow[key];
1362
+ if (instance) {
1363
+ instance.ready = false;
1364
+ self.ondisconnect && self.ondisconnect(instance);
1365
+ self.$events.disconnect && self.emit('disconnect', instance);
1366
+ try {
1367
+ instance.close && instance.close.call(instance, true);
1368
+ instance.destroy && instance.destroy.call(instance);
1369
+ } catch (e) {
1370
+ self.onerror.call(instance, e, 'instance_close', key);
1371
+ }
1372
+ delete self.meta.flow[key];
1373
+ }
1374
+ }
1375
+
1376
+ self.clean();
1377
+ callback && callback();
1378
+ };
1379
+
1380
+ function use(self, schema, callback, reinit, insert) {
1381
+ self._use(schema, callback, reinit, insert);
1382
+ }
1383
+
1384
+ FP.use = function(schema, callback, reinit) {
1385
+ var self = this;
1386
+ if (callback)
1387
+ self._use(schema, callback, reinit);
1388
+ else
1389
+ return new Promise((resolve, reject) => self._use(schema, (err, res) => err ? reject(err) : resolve(res), reinit));
1390
+ };
1391
+
1392
+ FP._use = function(schema, callback, reinit, insert) {
1393
+
1394
+ var self = this;
1395
+
1396
+ if (self.loading) {
1397
+ setTimeout(use, 200, self, schema, callback, reinit, insert);
1398
+ return self;
1399
+ }
1400
+
1401
+ if (typeof(schema) === 'string')
1402
+ schema = schema.parseJSON(true);
1403
+ else
1404
+ schema = F.TUtils.clone(schema);
1405
+
1406
+ if (typeof(callback) === 'boolean') {
1407
+ var tmp = reinit;
1408
+ reinit = callback;
1409
+ callback = tmp;
1410
+ }
1411
+
1412
+ // schema.COMPONENT_ID.component = 'condition';
1413
+ // schema.COMPONENT_ID.config = {};
1414
+ // schema.COMPONENT_ID.connections = { '0': [{ id: 'COMPONENT_ID', index: '2' }] }
1415
+
1416
+ var err = new F.ErrorBuilder();
1417
+
1418
+ if (schema) {
1419
+
1420
+ var keys = Object.keys(schema);
1421
+ var ts = Date.now();
1422
+
1423
+ if (!insert) {
1424
+ if (self.meta.flow.paused)
1425
+ delete self.meta.flow.paused;
1426
+
1427
+ if (self.meta.flow.groups)
1428
+ delete self.meta.flow.groups;
1429
+
1430
+ if (self.meta.flow.tabs)
1431
+ delete self.meta.flow.tabs;
1432
+ }
1433
+
1434
+ self.inc(1);
1435
+ keys.wait(function(key, next) {
1436
+
1437
+ if (BLACKLISTID[key]) {
1438
+ self.meta.flow[key] = schema[key];
1439
+ next();
1440
+ return;
1441
+ }
1442
+
1443
+ var current = self.meta.flow[key];
1444
+ var instance = schema[key];
1445
+ var component = instance.component ? self.meta.components[instance.component] : null;
1446
+
1447
+ // Component not found
1448
+ if (!component) {
1449
+ err.push(key, '"' + instance.component + '" component not found.');
1450
+
1451
+ if (current) {
1452
+ current.isdestroyed = true;
1453
+ self.ondisconnect && self.ondisconnect(current);
1454
+ try {
1455
+ current.close && current.close.call(current, true);
1456
+ current.destroy && current.destroy.call(current);
1457
+ } catch (e) {
1458
+ self.onerror.call(current, e, 'instance_close', key);
1459
+ }
1460
+ }
1461
+
1462
+ delete self.meta.flow[key];
1463
+ next();
1464
+ return;
1465
+ }
1466
+
1467
+ var fi = self.meta.flow[key];
1468
+
1469
+ if (!fi || reinit) {
1470
+ self.meta.flow[key] = instance;
1471
+ var tmp = self.initcomponent(key, component);
1472
+ if (tmp) {
1473
+ tmp.ts = ts;
1474
+ tmp.newbie = true;
1475
+ }
1476
+ } else {
1477
+ fi.connections = instance.connections;
1478
+ fi.x = instance.x;
1479
+ fi.y = instance.y;
1480
+ fi.offset = instance.offset;
1481
+ fi.size = instance.size;
1482
+ fi.tab = instance.tab;
1483
+ fi.ts = ts;
1484
+ if (JSON.stringify(fi.config) !== JSON.stringify(instance.config)) {
1485
+ F.TUtils.extend(fi.config, instance.config);
1486
+ fi.configure && fi.configure(fi.config);
1487
+ self.onreconfigure && self.onreconfigure(fi, true);
1488
+ self.$events.configure && self.emit('configure', fi);
1489
+ }
1490
+ }
1491
+
1492
+ next();
1493
+
1494
+ }, function() {
1495
+
1496
+ if (!insert) {
1497
+ for (var key in self.meta.flow) {
1498
+ if (!BLACKLISTID[key]) {
1499
+ var instance = self.meta.flow[key];
1500
+ if (instance.ts !== ts) {
1501
+ instance.ready = false;
1502
+ instance.isdestroyed = true;
1503
+ self.ondisconnect && self.ondisconnect(instance);
1504
+ self.$events.disconnect && self.emit('disconnect', instance);
1505
+ try {
1506
+ instance.close && instance.close.call(instance, true);
1507
+ instance.destroy && instance.destroy.call(instance);
1508
+ } catch (e) {
1509
+ self.onerror.call(instance, e, 'instance_close', key);
1510
+ }
1511
+ delete self.meta.flow[key];
1512
+ }
1513
+ }
1514
+ }
1515
+ }
1516
+
1517
+ for (var key in self.meta.flow) {
1518
+ var instance = self.meta.flow[key];
1519
+ if (instance.newbie) {
1520
+ if (instance.init) {
1521
+ try {
1522
+ instance.init();
1523
+ } catch (e) {
1524
+ self.onerror.call(instance, e, 'instance_init', key);
1525
+ }
1526
+ }
1527
+ instance.newbie = false;
1528
+ }
1529
+ if (instance.refresh) {
1530
+ try {
1531
+ instance.refresh();
1532
+ } catch (e) {
1533
+ self.onerror.call(instance, e, 'instance_refresh', key);
1534
+ }
1535
+ }
1536
+ }
1537
+
1538
+ self.inc(-1);
1539
+
1540
+ self.cleanforce();
1541
+ self.$events.schema && self.emit('schema', self.meta.flow);
1542
+ callback && callback(err.length ? err : null);
1543
+
1544
+ });
1545
+
1546
+ } else {
1547
+ err.push('schema', 'Flow schema is invalid.');
1548
+ self.error(err, 'use');
1549
+ callback && callback(err);
1550
+ }
1551
+
1552
+ return self;
1553
+ };
1554
+
1555
+ FP.initcomponent = function(key, component) {
1556
+
1557
+ var self = this;
1558
+ var instance = self.meta.flow[key];
1559
+
1560
+ if (instance.ready) {
1561
+
1562
+ // Closes old instance
1563
+ instance.ready = false;
1564
+
1565
+ try {
1566
+ self.ondisconnect && self.ondisconnect(instance);
1567
+ self.$events.disconnect && self.emit('disconnect', instance);
1568
+ instance.close && instance.close.call(instance);
1569
+ } catch (e) {
1570
+ self.onerror.call(instance, e, 'instance_close', key);
1571
+ }
1572
+ }
1573
+
1574
+ instance.isinstance = true;
1575
+ instance.stats = { pending: 0, input: 0, output: 0, duration: 0, destroyed: 0 };
1576
+ instance.cache = {};
1577
+ instance.id = key;
1578
+ instance.module = component;
1579
+ instance.ready = false;
1580
+
1581
+ if (instance.options) {
1582
+ instance.config = instance.options;
1583
+ delete instance.options;
1584
+ }
1585
+
1586
+ var tmp = component.config;
1587
+ if (tmp)
1588
+ instance.config = instance.config ? F.TUtils.extend(F.TUtils.clone(tmp), instance.config) : F.TUtils.clone(tmp);
1589
+
1590
+ if (!instance.config)
1591
+ instance.config = {};
1592
+
1593
+ instance.main = self;
1594
+ instance.dashboard = self.ondashboard;
1595
+ instance.status = self.onstatus;
1596
+ instance.debug = self.ondebug;
1597
+ instance.throw = self.onerror;
1598
+ instance.send = self.ontrigger;
1599
+ instance.newmessage = newmessage;
1600
+ instance.logger = newlogger;
1601
+ instance.middleware = newmiddleware;
1602
+ instance.transform = newtransform;
1603
+ instance.replace = variables;
1604
+ instance.instances = self.meta.flow;
1605
+ instance.components = self.meta.components;
1606
+
1607
+ self.onconnect && self.onconnect(instance);
1608
+ self.$events.connect && self.emit('connect', instance);
1609
+
1610
+ try {
1611
+ component.make && component.make.call(instance, instance, instance.config);
1612
+ } catch (e) {
1613
+ self.error(e, 'instance_make', instance);
1614
+ return;
1615
+ }
1616
+
1617
+ if (instance.open) {
1618
+ instance.open.call(instance, (function(instance) {
1619
+ return function() {
1620
+ if (instance) {
1621
+ instance.ready = true;
1622
+ delete instance.open;
1623
+ }
1624
+ };
1625
+ })(instance));
1626
+ } else
1627
+ instance.ready = true;
1628
+
1629
+ // Notifies about the pause state
1630
+ if (self.paused && instance.pause)
1631
+ instance.pause(true);
1632
+
1633
+ self.meta.flow[key] = instance;
1634
+ return instance;
1635
+ };
1636
+
1637
+ function sendmessage(instance, message, event) {
1638
+
1639
+ if (instance.isdestroyed || message.isdestroyed || instance.main.paused) {
1640
+ message.destroy();
1641
+ return;
1642
+ }
1643
+
1644
+ if (message.middleware === undefined && instance.main.middleware.length) {
1645
+ message.middleware = instance.main.middleware.slice(0);
1646
+ if (message.middleware.length)
1647
+ message.$emitevent = event;
1648
+ else
1649
+ message.middleware = null;
1650
+ }
1651
+
1652
+ if (message.middleware && message.middleware.length) {
1653
+ var mid = message.middleware.shift();
1654
+ if (mid) {
1655
+ var tmp = instance.main.meta.flow[mid];
1656
+ if (tmp && tmp.$middleware) {
1657
+ // Executes middleware
1658
+ tmp.$middleware(message);
1659
+ } else {
1660
+ // Maybe another middleware
1661
+ sendmessage(instance, message, event);
1662
+ }
1663
+ return;
1664
+ }
1665
+ }
1666
+
1667
+ // Logger
1668
+ if (instance.main.logger.length) {
1669
+ var main = instance.main;
1670
+ for (var key of main.logger) {
1671
+ var tmp = main.meta.flow[key];
1672
+ if (tmp && tmp.$logger)
1673
+ tmp.$logger(message);
1674
+ }
1675
+ }
1676
+
1677
+ if (event) {
1678
+ message.$events && message.$events.message && message.emit('message', message);
1679
+ message.main.$events && message.main.$events.message && message.main.emit('message', message);
1680
+ }
1681
+
1682
+ try {
1683
+
1684
+ var is = false;
1685
+
1686
+ var key = 'message_' + message.input;
1687
+
1688
+ if (instance[key]) {
1689
+ is = true;
1690
+ instance[key](message);
1691
+ }
1692
+
1693
+ if (instance.message) {
1694
+ is = true;
1695
+ instance.message(message);
1696
+ }
1697
+
1698
+ if (!is)
1699
+ message.destroy();
1700
+
1701
+ } catch (e) {
1702
+ instance.main.error(e, 'instance_message', message);
1703
+ message.destroy();
1704
+ }
1705
+ }
1706
+
1707
+ FP.$can = function(isinput, id, index) {
1708
+ var self = this;
1709
+ if (self.paused)
1710
+ return false;
1711
+ if (!self.meta.flow.paused)
1712
+ return true;
1713
+ var key = (isinput ? 'input' : 'output') + D + id + D + index;
1714
+ if (!self.meta.flow.paused[key])
1715
+ return true;
1716
+ };
1717
+
1718
+ function trigger(self, path, data, controller, events) {
1719
+ self.trigger(path, data, controller, events);
1720
+ }
1721
+
1722
+ // path = ID__INPUTINDEX
1723
+ FP.trigger = function(path, data, controller, events) {
1724
+
1725
+ var self = this;
1726
+ if (self.loading) {
1727
+ setTimeout(trigger, 200, self, path, data, controller, events);
1728
+ return;
1729
+ }
1730
+
1731
+ if (self.paused)
1732
+ return;
1733
+
1734
+ path = path.split(D);
1735
+
1736
+ var inputindex = path.length === 1 ? 0 : path[1];
1737
+
1738
+ var schema = self.meta.flow[path[0]];
1739
+ if (schema && schema.ready && schema.component && (schema.message || schema['message_' + inputindex])) {
1740
+
1741
+ var instance = self.meta.components[schema.component];
1742
+ if (instance && instance.connected && !instance.disabled && self.$can(true, path[0], path[1])) {
1743
+
1744
+ var ismessage = data instanceof Message;
1745
+ var ts = Date.now();
1746
+ var message = ismessage ? data.clone(false) : new Message();
1747
+
1748
+ if (ismessage) {
1749
+ if (data.processed === 0) {
1750
+ data.processed = 1;
1751
+ data.main.stats.pending--;
1752
+
1753
+ if (data.main.stats.pending < 0)
1754
+ data.main.stats.pending = 0;
1755
+
1756
+ data.instance.stats.pending--;
1757
+
1758
+ if (data.instance.stats.pending < 0)
1759
+ data.instance.stats.pending = 0;
1760
+
1761
+ data.instance.stats.output++;
1762
+ data.instance.stats.duration = ts - self.ts;
1763
+ }
1764
+ } else {
1765
+ message.refs = { pending: 1 };
1766
+ message.$events = events || {};
1767
+ message.repo = {};
1768
+ message.data = data;
1769
+ message.duration = message.ts = ts;
1770
+ message.used = 1;
1771
+ }
1772
+
1773
+ message.controller = controller;
1774
+ message.instance = schema;
1775
+ message.main = self;
1776
+ message.to = schema;
1777
+ message.toid = path[0];
1778
+ message.input = message.index = inputindex;
1779
+ message.tocomponent = instance.id;
1780
+ message.cache = instance.cache;
1781
+ message.processed = 0;
1782
+
1783
+ schema.stats.input++;
1784
+ schema.stats.pending++;
1785
+
1786
+ message.main.stats.pending++;
1787
+ message.main.stats.messages++;
1788
+ message.main.mm++;
1789
+
1790
+ message.id = message.main.uid + message.main.stats.messages;
1791
+ message.count = message.main.stats.messages;
1792
+
1793
+ if (message.fromid) {
1794
+ var tid = message.fromid + D + message.output + (message.color || '');
1795
+ if (message.main.stats.traffic[tid])
1796
+ message.main.stats.traffic[tid]++;
1797
+ else {
1798
+ message.main.stats.traffic[tid] = 1;
1799
+ message.main.stats.traffic.priority.push(tid);
1800
+ }
1801
+ } else {
1802
+ message.from = null;
1803
+ message.fromid = null;
1804
+ message.fromcomponent = null;
1805
+ message.output = null;
1806
+ }
1807
+
1808
+ setImmediate(sendmessage, schema, message, true);
1809
+ return message;
1810
+ }
1811
+ }
1812
+ };
1813
+
1814
+ FP.trigger2 = function(path, data, controller) {
1815
+
1816
+ var self = this;
1817
+
1818
+ if (self.paused)
1819
+ return;
1820
+
1821
+ var events = {};
1822
+ var obj;
1823
+
1824
+ path = path.split(D);
1825
+
1826
+ var counter = 0;
1827
+ for (var key in self.meta.flow) {
1828
+ var flow = self.meta.flow[key];
1829
+ if (flow.component === path[0])
1830
+ obj = self.trigger(key + D + (path.length === 1 ? 0 : path[1]), data, controller, events, counter++);
1831
+ }
1832
+
1833
+ return obj;
1834
+ };
1835
+
1836
+ FP.clear = function() {
1837
+ var self = this;
1838
+ self.meta.flow = {};
1839
+ return self;
1840
+ };
1841
+
1842
+ FP.make = function(fn) {
1843
+ var self = this;
1844
+ fn.call(self, self);
1845
+ return self;
1846
+ };
1847
+
1848
+ FP.find = function(id) {
1849
+ return this.meta.flow[id];
1850
+ };
1851
+
1852
+ FP.send = function(path, body) {
1853
+ var self = this;
1854
+ if (!self.paused && self.meta && self.meta.flow) {
1855
+ path = path.split(D);
1856
+ var instance = self.meta.flow[path[0]];
1857
+ if (instance)
1858
+ instance.send(path[1], body);
1859
+ return !!instance;
1860
+ }
1861
+ };
1862
+
1863
+ FP.add = function(name, body, callback, asfile) {
1864
+
1865
+ var self = this;
1866
+ var meta = body.parseComponent({ readme: '<readme>', settings: '<settings>', css: '<style>', be: '<script total>', be2: '<script node>', js: '<script>', html: '<body>', schema: '<schema>', template: '<template>' });
1867
+ var node = (meta.be || meta.be2 || '').trim().replace(/\n\t/g, '\n');
1868
+
1869
+ if (!meta.be && !meta.be2) {
1870
+ var e = new Error('Invalid component content');
1871
+ self.error(e, 'add', name);
1872
+ callback && callback(e);
1873
+ return;
1874
+ }
1875
+
1876
+ meta.id = name;
1877
+ meta.checksum = HASH(node).toString(36);
1878
+
1879
+ var component = self.meta.components[name];
1880
+ if (component && component.ui && component.ui.checksum === meta.checksum) {
1881
+ component.ui = meta;
1882
+ component.ts = Date.now();
1883
+ callback && callback();
1884
+ } else {
1885
+
1886
+ var fn;
1887
+
1888
+ if (asfile) {
1889
+
1890
+ var filename = F.path.tmp(self.id + '_' + meta.id) + '.js';
1891
+
1892
+ F.Fs.writeFile(filename, node, function(err) {
1893
+
1894
+ if (err) {
1895
+ callback && callback(err);
1896
+ return;
1897
+ }
1898
+
1899
+ try {
1900
+
1901
+ fn = require(filename);
1902
+
1903
+ delete meta.be;
1904
+ delete meta.be2;
1905
+
1906
+ component = self.register(meta.id, fn, null, callback, true);
1907
+
1908
+ if (component) {
1909
+ component.ui = meta;
1910
+ component.ui.raw = body;
1911
+ }
1912
+
1913
+ } catch (e) {
1914
+ self.error(e, 'add', name);
1915
+ callback && callback(e);
1916
+ }
1917
+
1918
+ });
1919
+
1920
+ return;
1921
+ }
1922
+
1923
+ try {
1924
+
1925
+ fn = new Function('exports', 'require', node);
1926
+
1927
+ } catch (e) {
1928
+ self.error(e, 'add', name);
1929
+ callback && callback(e);
1930
+ return null;
1931
+ }
1932
+
1933
+ delete meta.be;
1934
+ delete meta.be2;
1935
+ component = self.register(meta.id, fn, null, callback, true);
1936
+
1937
+ if (component)
1938
+ component.ui = meta;
1939
+ else
1940
+ return null;
1941
+ }
1942
+
1943
+ component.ui.raw = body;
1944
+ return component;
1945
+ };
1946
+
1947
+ FP.instances = function() {
1948
+
1949
+ var self = this;
1950
+ var arr = [];
1951
+
1952
+ for (var key in self.meta.flow) {
1953
+ if (!BLACKLISTID[key]) {
1954
+ var instance = self.meta.flow[key];
1955
+ if (instance.ready)
1956
+ arr.push(instance);
1957
+ }
1958
+ }
1959
+
1960
+ return arr;
1961
+ };
1962
+
1963
+ FP.export_instance = function(id) {
1964
+
1965
+ var self = this;
1966
+ var instance = self.meta.flow[id];
1967
+ if (instance) {
1968
+
1969
+ if (BLACKLISTID[id])
1970
+ return F.TUtils.clone(instance);
1971
+
1972
+ var tmp = {};
1973
+ tmp.x = instance.x;
1974
+ tmp.y = instance.y;
1975
+ tmp.size = instance.size;
1976
+ tmp.offset = instance.offset;
1977
+ tmp.stats = F.TUtils.clone(instance.stats);
1978
+ tmp.connections = F.TUtils.clone(instance.connections);
1979
+ tmp.id = instance.id;
1980
+ tmp.config = F.TUtils.clone(instance.config);
1981
+ tmp.component = instance.component;
1982
+ tmp.connected = true;
1983
+ tmp.note = instance.note;
1984
+ tmp.tab = instance.tab;
1985
+ tmp.reference = instance.reference;
1986
+ tmp.meta = instance.meta;
1987
+
1988
+ if (instance.outputs)
1989
+ tmp.outputs = instance.outputs;
1990
+
1991
+ if (instance.inputs)
1992
+ tmp.inputs = instance.inputs;
1993
+
1994
+ return tmp;
1995
+ }
1996
+ };
1997
+
1998
+ FP.export_component = function(id) {
1999
+ var self = this;
2000
+ var com = self.meta.components[id];
2001
+ if (com) {
2002
+ var obj = {};
2003
+ obj.id = com.id;
2004
+ obj.name = com.name;
2005
+ obj.title = com.title;
2006
+ obj.meta = com.meta;
2007
+ obj.type = com.type;
2008
+ obj.css = com.ui.css;
2009
+ obj.js = com.ui.js;
2010
+ obj.icon = com.icon;
2011
+ obj.color = com.ui.color;
2012
+ obj.config = com.config;
2013
+ obj.html = com.ui.html;
2014
+ obj.readme = com.ui.readme;
2015
+ obj.template = com.ui.template;
2016
+ obj.settings = com.ui.settings;
2017
+ obj.inputs = com.inputs;
2018
+ obj.outputs = com.outputs;
2019
+ obj.group = com.group;
2020
+ obj.version = com.version;
2021
+ obj.author = com.author;
2022
+ obj.permissions = com.permissions;
2023
+ return obj;
2024
+ }
2025
+ };
2026
+
2027
+ FP.export = function(type) {
2028
+
2029
+ var self = this;
2030
+
2031
+ if (type === 'components')
2032
+ return self.components(true);
2033
+
2034
+ var output = {};
2035
+
2036
+ for (var key in self.meta.flow)
2037
+ output[key] = self.export_instance(key);
2038
+
2039
+ return output;
2040
+ };
2041
+
2042
+ FP.components = function(prepare_export) {
2043
+
2044
+ var self = this;
2045
+ var arr = [];
2046
+
2047
+ for (var key in self.meta.components) {
2048
+ if (prepare_export)
2049
+ arr.push(self.export_component(key));
2050
+ else
2051
+ arr.push(self.meta.components[key]);
2052
+ }
2053
+
2054
+ return arr;
2055
+ };
2056
+
2057
+ exports.create = function(id, errorhandler) {
2058
+ let flowstream = new FlowStream(id, errorhandler);
2059
+ F.flowstreams[id] = flowstream;
2060
+ return flowstream;
2061
+ };