noflo 1.4.2 → 1.5.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/.ecrc +3 -0
- package/.eslintignore +2 -0
- package/{CHANGES.md → CHANGELOG.md} +520 -523
- package/README.md +1 -1
- package/bin/noflo-cache-preheat +17 -15
- package/components/Graph.d.ts +50 -15
- package/components/Graph.js +94 -68
- package/examples/http/HelloController.js +9 -6
- package/examples/spreadsheet/parse.fbp +3 -3
- package/lib/AsCallback.d.ts +22 -9
- package/lib/AsCallback.js +69 -18
- package/lib/AsComponent.d.ts +1 -1
- package/lib/AsComponent.js +5 -3
- package/lib/BaseNetwork.d.ts +16 -6
- package/lib/BaseNetwork.js +65 -31
- package/lib/BasePort.d.ts +39 -12
- package/lib/BasePort.js +34 -6
- package/lib/Component.d.ts +8 -8
- package/lib/Component.js +23 -20
- package/lib/ComponentLoader.d.ts +3 -4
- package/lib/ComponentLoader.js +9 -10
- package/lib/IP.d.ts +12 -8
- package/lib/IP.js +6 -4
- package/lib/InPort.d.ts +81 -10
- package/lib/InPort.js +83 -19
- package/lib/InternalSocket.d.ts +53 -7
- package/lib/InternalSocket.js +51 -14
- package/lib/LegacyNetwork.d.ts +12 -2
- package/lib/LegacyNetwork.js +5 -5
- package/lib/Network.d.ts +13 -2
- package/lib/Network.js +10 -10
- package/lib/NoFlo.d.ts +13 -13
- package/lib/NoFlo.js +29 -27
- package/lib/OutPort.d.ts +74 -32
- package/lib/OutPort.js +79 -23
- package/lib/Platform.d.ts +1 -1
- package/lib/Platform.js +9 -4
- package/lib/Ports.d.ts +14 -21
- package/lib/Ports.js +11 -13
- package/lib/ProcessInput.d.ts +5 -9
- package/lib/ProcessInput.js +8 -9
- package/lib/ProcessOutput.d.ts +2 -2
- package/lib/ProcessOutput.js +5 -5
- package/lib/loader/NodeJs.d.ts +0 -1
- package/lib/loader/NodeJs.js +104 -105
- package/lib/loader/register.d.ts +1 -1
- package/lib/loader/register.js +8 -4
- package/package.json +16 -11
- package/spec/.eslintrc +5 -2
- package/spec/AsCallback.js +9 -13
- package/spec/AsComponent.js +10 -4
- package/spec/AsPromise.js +38 -0
- package/spec/CommonJS.cjs +10 -0
- package/spec/ComponentLoader.js +2 -38
- package/spec/ESModule.mjs +11 -0
- package/spec/Network.js +32 -11
- package/spec/NetworkSync.js +892 -0
- package/spec/Scoping.js +27 -42
- package/spec/Subgraph.js +6 -11
- package/spec/fixtures/componentloader/components/Output.js +1 -1
- package/spec/fixtures/componentloader/components/Repeat.ts +1 -1
- package/spec/fixtures/componentloader/components/RepeatAsync.coffee +1 -1
- package/spec/fixtures/componentloader/node_modules/example/components/Forward.js +1 -1
- package/spec/fixtures/componentloader/node_modules/example/package.json +1 -1
- package/spec/fixtures/componentloader/package.json +1 -1
- package/spec/fixtures/componentloader/spec/Repeat.yaml +1 -1
- package/src/.eslintrc +9 -2
- package/src/components/Graph.js +105 -71
- package/src/lib/AsCallback.js +71 -16
- package/src/lib/AsComponent.js +4 -3
- package/src/lib/BaseNetwork.js +48 -15
- package/src/lib/BasePort.js +43 -9
- package/src/lib/Component.js +8 -8
- package/src/lib/ComponentLoader.js +3 -4
- package/src/lib/IP.js +7 -4
- package/src/lib/InPort.js +86 -21
- package/src/lib/InternalSocket.js +49 -9
- package/src/lib/LegacyNetwork.js +2 -2
- package/src/lib/Network.js +2 -2
- package/src/lib/NoFlo.js +15 -13
- package/src/lib/OutPort.js +83 -22
- package/src/lib/Platform.js +9 -4
- package/src/lib/Ports.js +9 -11
- package/src/lib/ProcessInput.js +7 -9
- package/src/lib/ProcessOutput.js +1 -1
- package/src/lib/loader/NodeJs.js +122 -116
- package/src/lib/loader/register.js +2 -2
- /package/{karma.config.js → karma.config.cjs} +0 -0
- /package/{webpack.config.js → webpack.config.cjs} +0 -0
package/src/lib/InPort.js
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
1
|
// NoFlo - Flow-Based Programming for JavaScript
|
|
2
2
|
// (c) 2014-2017 Flowhub UG
|
|
3
3
|
// NoFlo may be freely distributed under the MIT license
|
|
4
|
-
import BasePort from './BasePort';
|
|
4
|
+
import BasePort from './BasePort.js';
|
|
5
5
|
|
|
6
6
|
// ## NoFlo inport
|
|
7
7
|
//
|
|
8
8
|
// Input Port (inport) implementation for NoFlo components. These
|
|
9
9
|
// ports are the way a component receives Information Packets.
|
|
10
|
+
/**
|
|
11
|
+
* @typedef InPortOptions
|
|
12
|
+
* @property {any} [default]
|
|
13
|
+
* @property {Array<any>} [values]
|
|
14
|
+
* @property {boolean} [control]
|
|
15
|
+
* @property {boolean} [triggering]
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @callback HasValidationCallback
|
|
19
|
+
* @param {import("./IP").default} ip
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {import("./BasePort").BaseOptions & InPortOptions} PortOptions
|
|
24
|
+
*/
|
|
25
|
+
|
|
10
26
|
export default class InPort extends BasePort {
|
|
27
|
+
/**
|
|
28
|
+
* @param {PortOptions} [options]
|
|
29
|
+
*/
|
|
11
30
|
constructor(options = {}) {
|
|
12
31
|
const opts = options;
|
|
13
32
|
if (opts.control == null) { opts.control = false; }
|
|
14
33
|
if (opts.scoped == null) { opts.scoped = true; }
|
|
15
34
|
if (opts.triggering == null) { opts.triggering = true; }
|
|
16
35
|
|
|
17
|
-
if (opts.process) {
|
|
18
|
-
throw new Error('InPort process callback is deprecated. Please use Process API');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (opts.handle) {
|
|
22
|
-
throw new Error('InPort handle callback is deprecated. Please use Process API');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
36
|
super(opts);
|
|
26
37
|
|
|
38
|
+
const baseOptions = this.options;
|
|
39
|
+
this.options = /** @type {PortOptions} */ (baseOptions);
|
|
40
|
+
|
|
41
|
+
/** @type {import("./Component").Component|null} */
|
|
27
42
|
this.nodeInstance = null;
|
|
28
43
|
|
|
29
44
|
this.prepareBuffer();
|
|
30
45
|
}
|
|
31
46
|
|
|
32
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Assign a delegate for retrieving data should this inPort
|
|
49
|
+
*
|
|
50
|
+
* @param {import("./InternalSocket").InternalSocket} socket
|
|
51
|
+
* @param {number|null} [localId]
|
|
52
|
+
*/
|
|
33
53
|
attachSocket(socket, localId = null) {
|
|
34
54
|
// have a default value.
|
|
35
55
|
if (this.hasDefault()) {
|
|
@@ -47,11 +67,17 @@ export default class InPort extends BasePort {
|
|
|
47
67
|
socket.on('ip', (ip) => this.handleIP(ip, localId));
|
|
48
68
|
}
|
|
49
69
|
|
|
50
|
-
|
|
70
|
+
/**
|
|
71
|
+
* @param {import("./IP").default} packet
|
|
72
|
+
* @param {number|null} [index]
|
|
73
|
+
*/
|
|
74
|
+
handleIP(packet, index = null) {
|
|
51
75
|
if (this.options.control && (packet.type !== 'data')) { return; }
|
|
52
76
|
const ip = packet;
|
|
53
77
|
ip.owner = this.nodeInstance;
|
|
54
|
-
if (this.isAddressable()) {
|
|
78
|
+
if (this.isAddressable()) {
|
|
79
|
+
ip.index = index;
|
|
80
|
+
}
|
|
55
81
|
if (ip.datatype === 'all') {
|
|
56
82
|
// Stamp non-specific IP objects with port datatype
|
|
57
83
|
ip.datatype = this.getDataType();
|
|
@@ -68,6 +94,11 @@ export default class InPort extends BasePort {
|
|
|
68
94
|
this.emit('ip', ip, index);
|
|
69
95
|
}
|
|
70
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} event
|
|
99
|
+
* @param {any} payload
|
|
100
|
+
* @param {number} [id]
|
|
101
|
+
*/
|
|
71
102
|
handleSocketEvent(event, payload, id) {
|
|
72
103
|
// Emit port event
|
|
73
104
|
if (this.isAddressable()) {
|
|
@@ -134,6 +165,9 @@ export default class InPort extends BasePort {
|
|
|
134
165
|
return this.buffer;
|
|
135
166
|
}
|
|
136
167
|
|
|
168
|
+
/**
|
|
169
|
+
* @param {any} data
|
|
170
|
+
*/
|
|
137
171
|
validateData(data) {
|
|
138
172
|
if (!this.options.values) { return; }
|
|
139
173
|
if (this.options.values.indexOf(data) === -1) {
|
|
@@ -188,14 +222,25 @@ export default class InPort extends BasePort {
|
|
|
188
222
|
return buf.shift();
|
|
189
223
|
}
|
|
190
224
|
|
|
191
|
-
|
|
192
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Fetches a packet from the port
|
|
227
|
+
* @param {string|null} scope
|
|
228
|
+
* @param {number|null} [index]
|
|
229
|
+
*/
|
|
230
|
+
get(scope, index = null) {
|
|
193
231
|
const res = this.getFromBuffer(scope, index);
|
|
194
232
|
if (res !== undefined) { return res; }
|
|
195
233
|
// Try to find an IIP instead
|
|
196
234
|
return this.getFromBuffer(null, index, true);
|
|
197
235
|
}
|
|
198
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Fetches a packet from the port
|
|
239
|
+
* @param {string|null} scope
|
|
240
|
+
* @param {number|null} index
|
|
241
|
+
* @param {HasValidationCallback} validate
|
|
242
|
+
* @param {boolean} [initial]
|
|
243
|
+
*/
|
|
199
244
|
hasIPinBuffer(scope, index, validate, initial = false) {
|
|
200
245
|
const buf = this.getBuffer(scope, index, initial);
|
|
201
246
|
if (!(buf != null ? buf.length : undefined)) { return false; }
|
|
@@ -205,31 +250,51 @@ export default class InPort extends BasePort {
|
|
|
205
250
|
return false;
|
|
206
251
|
}
|
|
207
252
|
|
|
253
|
+
/**
|
|
254
|
+
* @param {number|null} index
|
|
255
|
+
* @param {HasValidationCallback} validate
|
|
256
|
+
*/
|
|
208
257
|
hasIIP(index, validate) {
|
|
209
258
|
return this.hasIPinBuffer(null, index, validate, true);
|
|
210
259
|
}
|
|
211
260
|
|
|
212
|
-
|
|
261
|
+
/**
|
|
262
|
+
* Returns true if port contains packet(s) matching the validator
|
|
263
|
+
* @param {string|null} scope
|
|
264
|
+
* @param {number|null|HasValidationCallback} index
|
|
265
|
+
* @param {HasValidationCallback} [validate]
|
|
266
|
+
*/
|
|
213
267
|
has(scope, index, validate) {
|
|
214
268
|
let valid = validate;
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
269
|
+
/** @type {number|null} */
|
|
270
|
+
let idx;
|
|
271
|
+
if (typeof index === 'function') {
|
|
272
|
+
valid = /** @type {HasValidationCallback} */ (index);
|
|
218
273
|
idx = null;
|
|
274
|
+
} else {
|
|
275
|
+
idx = index;
|
|
219
276
|
}
|
|
220
277
|
if (this.hasIPinBuffer(scope, idx, valid)) { return true; }
|
|
221
278
|
if (this.hasIIP(idx, valid)) { return true; }
|
|
222
279
|
return false;
|
|
223
280
|
}
|
|
224
281
|
|
|
225
|
-
|
|
226
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Returns the number of data packets in an inport
|
|
284
|
+
* @param {string|null} scope
|
|
285
|
+
* @param {number|null} [index]
|
|
286
|
+
* @returns {number}
|
|
287
|
+
*/
|
|
288
|
+
length(scope, index = null) {
|
|
227
289
|
const buf = this.getBuffer(scope, index);
|
|
228
290
|
if (!buf) { return 0; }
|
|
229
291
|
return buf.length;
|
|
230
292
|
}
|
|
231
293
|
|
|
232
|
-
|
|
294
|
+
/**
|
|
295
|
+
* Tells if buffer has packets or not
|
|
296
|
+
* @param {string|null} scope
|
|
297
|
+
*/
|
|
233
298
|
ready(scope) {
|
|
234
299
|
return this.length(scope) > 0;
|
|
235
300
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// (c) 2011-2012 Henri Bergius, Nemein
|
|
4
4
|
// NoFlo may be freely distributed under the MIT license
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
|
-
import IP from './IP';
|
|
6
|
+
import IP from './IP.js';
|
|
7
|
+
import { makeAsync } from './Platform.js';
|
|
7
8
|
|
|
8
9
|
function legacyToIp(event, payload) {
|
|
9
10
|
// No need to wrap modern IP Objects
|
|
@@ -44,6 +45,13 @@ function ipToLegacy(ip) {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @typedef SocketError
|
|
50
|
+
* @property {Error} error
|
|
51
|
+
* @property {string} [id]
|
|
52
|
+
* @property {import("fbp-graph/lib/Types").GraphNodeMetadata} [metadata]
|
|
53
|
+
*/
|
|
54
|
+
|
|
47
55
|
// ## Internal Sockets
|
|
48
56
|
//
|
|
49
57
|
// The default communications mechanism between NoFlo processes is
|
|
@@ -52,10 +60,16 @@ function ipToLegacy(ip) {
|
|
|
52
60
|
// events so that the packets can be caught to the inport of the
|
|
53
61
|
// connected process.
|
|
54
62
|
export class InternalSocket extends EventEmitter {
|
|
63
|
+
/**
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
55
66
|
regularEmitEvent(event, data) {
|
|
56
67
|
this.emit(event, data);
|
|
57
68
|
}
|
|
58
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
59
73
|
debugEmitEvent(event, data) {
|
|
60
74
|
try {
|
|
61
75
|
this.emit(event, data);
|
|
@@ -70,25 +84,51 @@ export class InternalSocket extends EventEmitter {
|
|
|
70
84
|
if (this.listeners('error').length === 0) { throw error; }
|
|
71
85
|
|
|
72
86
|
this.emit('error', {
|
|
73
|
-
id: this.to.process.id,
|
|
87
|
+
id: this.to ? this.to.process.id : null,
|
|
74
88
|
error,
|
|
75
89
|
metadata: this.metadata,
|
|
76
90
|
});
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
93
|
|
|
80
|
-
|
|
94
|
+
/**
|
|
95
|
+
* @typedef InternalSocketOptions
|
|
96
|
+
* @property {boolean} [debug] - Whether to catch exceptions caused by IP transmission
|
|
97
|
+
* @property {boolean} [async] - Whether IP transmission should be asynchronous
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {import("fbp-graph/lib/Types").GraphEdgeMetadata} [metadata]
|
|
102
|
+
* @param {InternalSocketOptions} [options]
|
|
103
|
+
*/
|
|
104
|
+
constructor(metadata = {}, options = {}) {
|
|
81
105
|
super();
|
|
82
106
|
this.metadata = metadata;
|
|
83
107
|
this.brackets = [];
|
|
84
108
|
this.connected = false;
|
|
85
109
|
this.dataDelegate = null;
|
|
86
|
-
this.debug = false;
|
|
87
|
-
this.
|
|
110
|
+
this.debug = options.debug || false;
|
|
111
|
+
this.async = options.async || false;
|
|
88
112
|
this.from = null;
|
|
89
113
|
this.to = null;
|
|
90
114
|
}
|
|
91
115
|
|
|
116
|
+
emitEvent(event, data) {
|
|
117
|
+
if (this.debug) {
|
|
118
|
+
if (this.async) {
|
|
119
|
+
makeAsync(() => this.debugEmitEvent(event, data));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.debugEmitEvent(event, data);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (this.async) {
|
|
126
|
+
makeAsync(() => this.regularEmitEvent(event, data));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.regularEmitEvent(event, data);
|
|
130
|
+
}
|
|
131
|
+
|
|
92
132
|
// ## Socket connections
|
|
93
133
|
//
|
|
94
134
|
// Sockets that are attached to the ports of processes may be
|
|
@@ -223,7 +263,6 @@ export class InternalSocket extends EventEmitter {
|
|
|
223
263
|
// notification to the developer.
|
|
224
264
|
setDebug(active) {
|
|
225
265
|
this.debug = active;
|
|
226
|
-
this.emitEvent = this.debug ? this.debugEmitEvent : this.regularEmitEvent;
|
|
227
266
|
}
|
|
228
267
|
|
|
229
268
|
// ## Socket identifiers
|
|
@@ -291,9 +330,10 @@ export class InternalSocket extends EventEmitter {
|
|
|
291
330
|
}
|
|
292
331
|
|
|
293
332
|
/**
|
|
294
|
-
* @param {
|
|
333
|
+
* @param {import("fbp-graph/lib/Types").GraphEdgeMetadata} [metadata]
|
|
334
|
+
* @param {InternalSocketOptions} [options]
|
|
295
335
|
* @returns {InternalSocket}
|
|
296
336
|
*/
|
|
297
|
-
export function createSocket(metadata = {}) {
|
|
298
|
-
return new InternalSocket(metadata);
|
|
337
|
+
export function createSocket(metadata = {}, options = {}) {
|
|
338
|
+
return new InternalSocket(metadata, options);
|
|
299
339
|
}
|
package/src/lib/LegacyNetwork.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// (c) 2013-2018 Flowhub UG
|
|
3
3
|
// (c) 2011-2012 Henri Bergius, Nemein
|
|
4
4
|
// NoFlo may be freely distributed under the MIT license
|
|
5
|
-
import { BaseNetwork } from './BaseNetwork';
|
|
6
|
-
import { deprecated } from './Platform';
|
|
5
|
+
import { BaseNetwork } from './BaseNetwork.js';
|
|
6
|
+
import { deprecated } from './Platform.js';
|
|
7
7
|
|
|
8
8
|
/* eslint-disable
|
|
9
9
|
import/prefer-default-export,
|
package/src/lib/Network.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// (c) 2013-2018 Flowhub UG
|
|
3
3
|
// (c) 2011-2012 Henri Bergius, Nemein
|
|
4
4
|
// NoFlo may be freely distributed under the MIT license
|
|
5
|
-
import { BaseNetwork } from './BaseNetwork';
|
|
6
|
-
import { deprecated } from './Platform';
|
|
5
|
+
import { BaseNetwork } from './BaseNetwork.js';
|
|
6
|
+
import { deprecated } from './Platform.js';
|
|
7
7
|
|
|
8
8
|
/* eslint-disable
|
|
9
9
|
no-param-reassign,
|
package/src/lib/NoFlo.js
CHANGED
|
@@ -52,6 +52,8 @@ import { graph } from 'fbp-graph';
|
|
|
52
52
|
// immediate execution
|
|
53
53
|
// * `flowtrace`: (default: NULL) Flowtrace instance to create a retroactive debugging
|
|
54
54
|
// trace of the network run.
|
|
55
|
+
// * `asyncDelivery`: (default: FALSE) Whether Information Packets should be
|
|
56
|
+
// delivered asynchronously.
|
|
55
57
|
// * `subscribeGraph`: (default: FALSE) Whether the network should monitor the underlying
|
|
56
58
|
// graph for changes
|
|
57
59
|
//
|
|
@@ -61,9 +63,9 @@ import { graph } from 'fbp-graph';
|
|
|
61
63
|
//
|
|
62
64
|
// The options object can also be used for setting ComponentLoader options in this
|
|
63
65
|
// network.
|
|
64
|
-
import { Network } from './Network';
|
|
65
|
-
import { LegacyNetwork } from './LegacyNetwork';
|
|
66
|
-
import { deprecated } from './Platform';
|
|
66
|
+
import { Network } from './Network.js';
|
|
67
|
+
import { LegacyNetwork } from './LegacyNetwork.js';
|
|
68
|
+
import { deprecated } from './Platform.js';
|
|
67
69
|
|
|
68
70
|
export {
|
|
69
71
|
graph,
|
|
@@ -76,7 +78,7 @@ export {
|
|
|
76
78
|
//
|
|
77
79
|
// NoFlo works on both Node.js and the browser. Because some dependencies are different,
|
|
78
80
|
// we need a way to detect which we're on.
|
|
79
|
-
export { isBrowser } from './Platform';
|
|
81
|
+
export { isBrowser } from './Platform.js';
|
|
80
82
|
|
|
81
83
|
// ### Component Loader
|
|
82
84
|
//
|
|
@@ -84,33 +86,33 @@ export { isBrowser } from './Platform';
|
|
|
84
86
|
// NoFlo components. Component Loader uses [fbp-manifest](https://github.com/flowbased/fbp-manifest)
|
|
85
87
|
// to find components and graphs by traversing the NPM dependency tree from a given root
|
|
86
88
|
// directory on the file system.
|
|
87
|
-
export { ComponentLoader } from './ComponentLoader';
|
|
89
|
+
export { ComponentLoader } from './ComponentLoader.js';
|
|
88
90
|
|
|
89
91
|
// ### Component baseclasses
|
|
90
92
|
//
|
|
91
93
|
// These baseclasses can be used for defining NoFlo components.
|
|
92
|
-
export { Component } from './Component';
|
|
94
|
+
export { Component } from './Component.js';
|
|
93
95
|
|
|
94
96
|
// ### NoFlo ports
|
|
95
97
|
//
|
|
96
98
|
// These classes are used for instantiating ports on NoFlo components.
|
|
97
|
-
export { InPorts, OutPorts } from './Ports';
|
|
99
|
+
export { InPorts, OutPorts } from './Ports.js';
|
|
98
100
|
|
|
99
|
-
export { default as InPort } from './InPort';
|
|
100
|
-
export { default as OutPort } from './OutPort';
|
|
101
|
+
export { default as InPort } from './InPort.js';
|
|
102
|
+
export { default as OutPort } from './OutPort.js';
|
|
101
103
|
|
|
102
104
|
// ### NoFlo sockets
|
|
103
105
|
//
|
|
104
106
|
// The NoFlo [internalSocket](InternalSocket.html) is used for connecting ports of
|
|
105
107
|
// different components together in a network.
|
|
106
|
-
import * as internalSocket from './InternalSocket';
|
|
108
|
+
import * as internalSocket from './InternalSocket.js';
|
|
107
109
|
|
|
108
110
|
export { internalSocket };
|
|
109
111
|
|
|
110
112
|
// ### Information Packets
|
|
111
113
|
//
|
|
112
114
|
// NoFlo Information Packets are defined as "IP" objects.
|
|
113
|
-
export { default as IP } from './IP';
|
|
115
|
+
export { default as IP } from './IP.js';
|
|
114
116
|
|
|
115
117
|
/**
|
|
116
118
|
* @callback NetworkCallback
|
|
@@ -221,7 +223,7 @@ export function saveFile(graphInstance, file, callback) {
|
|
|
221
223
|
// // Do something with results
|
|
222
224
|
// });
|
|
223
225
|
//
|
|
224
|
-
export { asCallback, asPromise } from './AsCallback';
|
|
226
|
+
export { asCallback, asPromise } from './AsCallback.js';
|
|
225
227
|
|
|
226
228
|
// ## Generating components from JavaScript functions
|
|
227
229
|
//
|
|
@@ -235,4 +237,4 @@ export { asCallback, asPromise } from './AsCallback';
|
|
|
235
237
|
// });
|
|
236
238
|
// };
|
|
237
239
|
//
|
|
238
|
-
export { asComponent } from './AsComponent';
|
|
240
|
+
export { asComponent } from './AsComponent.js';
|
package/src/lib/OutPort.js
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
// NoFlo - Flow-Based Programming for JavaScript
|
|
2
2
|
// (c) 2014-2017 Flowhub UG
|
|
3
3
|
// NoFlo may be freely distributed under the MIT license
|
|
4
|
-
import BasePort from './BasePort';
|
|
5
|
-
import IP from './IP';
|
|
4
|
+
import BasePort from './BasePort.js';
|
|
5
|
+
import IP from './IP.js';
|
|
6
6
|
|
|
7
7
|
// ## NoFlo outport
|
|
8
8
|
//
|
|
9
9
|
// Outport Port (outport) implementation for NoFlo components.
|
|
10
10
|
// These ports are the way a component sends Information Packets.
|
|
11
11
|
/**
|
|
12
|
-
* @typedef
|
|
13
|
-
* @property {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* @
|
|
17
|
-
* @property {boolean} [caching=false]
|
|
18
|
-
* @property {boolean} [scoped=true]
|
|
12
|
+
* @typedef OutPortOptions
|
|
13
|
+
* @property {boolean} [caching]
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {import("./BasePort").BaseOptions & OutPortOptions} PortOptions
|
|
19
17
|
*/
|
|
20
18
|
|
|
21
19
|
export default class OutPort extends BasePort {
|
|
22
20
|
/**
|
|
23
|
-
* @param {
|
|
21
|
+
* @param {PortOptions} options - Options for the outport
|
|
24
22
|
*/
|
|
25
23
|
constructor(options = {}) {
|
|
26
24
|
const opts = options;
|
|
@@ -29,16 +27,28 @@ export default class OutPort extends BasePort {
|
|
|
29
27
|
opts.caching = false;
|
|
30
28
|
}
|
|
31
29
|
super(opts);
|
|
30
|
+
|
|
31
|
+
const baseOptions = this.options;
|
|
32
|
+
this.options = /** @type {PortOptions} */ (baseOptions);
|
|
33
|
+
|
|
34
|
+
/** @type {Object<string, IP>} */
|
|
32
35
|
this.cache = {};
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @param {import("./InternalSocket").InternalSocket} socket
|
|
40
|
+
* @param {number|null} [index]
|
|
41
|
+
*/
|
|
35
42
|
attach(socket, index = null) {
|
|
36
43
|
super.attach(socket, index);
|
|
37
|
-
if (this.isCaching() && (this.cache[index] != null)) {
|
|
38
|
-
this.send(this.cache[index], index);
|
|
44
|
+
if (this.isCaching() && (this.cache[`${index}`] != null)) {
|
|
45
|
+
this.send(this.cache[`${index}`], index);
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {number|null} [index]
|
|
51
|
+
*/
|
|
42
52
|
connect(index = null) {
|
|
43
53
|
const sockets = this.getSockets(index);
|
|
44
54
|
this.checkRequired(sockets);
|
|
@@ -48,6 +58,10 @@ export default class OutPort extends BasePort {
|
|
|
48
58
|
});
|
|
49
59
|
}
|
|
50
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @param {string} group
|
|
63
|
+
* @param {number|null} [index]
|
|
64
|
+
*/
|
|
51
65
|
beginGroup(group, index = null) {
|
|
52
66
|
const sockets = this.getSockets(index);
|
|
53
67
|
this.checkRequired(sockets);
|
|
@@ -57,11 +71,15 @@ export default class OutPort extends BasePort {
|
|
|
57
71
|
});
|
|
58
72
|
}
|
|
59
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @param {any} data
|
|
76
|
+
* @param {number|null} [index]
|
|
77
|
+
*/
|
|
60
78
|
send(data, index = null) {
|
|
61
79
|
const sockets = this.getSockets(index);
|
|
62
80
|
this.checkRequired(sockets);
|
|
63
|
-
if (this.isCaching() && (data !== this.cache[index])) {
|
|
64
|
-
this.cache[index] = data;
|
|
81
|
+
if (this.isCaching() && (data !== this.cache[`${index}`])) {
|
|
82
|
+
this.cache[`${index}`] = data;
|
|
65
83
|
}
|
|
66
84
|
sockets.forEach((socket) => {
|
|
67
85
|
if (!socket) { return; }
|
|
@@ -69,6 +87,9 @@ export default class OutPort extends BasePort {
|
|
|
69
87
|
});
|
|
70
88
|
}
|
|
71
89
|
|
|
90
|
+
/**
|
|
91
|
+
* @param {number|null} [index]
|
|
92
|
+
*/
|
|
72
93
|
endGroup(index = null) {
|
|
73
94
|
const sockets = this.getSockets(index);
|
|
74
95
|
this.checkRequired(sockets);
|
|
@@ -78,6 +99,9 @@ export default class OutPort extends BasePort {
|
|
|
78
99
|
});
|
|
79
100
|
}
|
|
80
101
|
|
|
102
|
+
/**
|
|
103
|
+
* @param {number|null} [index]
|
|
104
|
+
*/
|
|
81
105
|
disconnect(index = null) {
|
|
82
106
|
const sockets = this.getSockets(index);
|
|
83
107
|
this.checkRequired(sockets);
|
|
@@ -87,14 +111,24 @@ export default class OutPort extends BasePort {
|
|
|
87
111
|
});
|
|
88
112
|
}
|
|
89
113
|
|
|
90
|
-
|
|
114
|
+
/**
|
|
115
|
+
* @param {string|IP} type
|
|
116
|
+
* @param {any} [data]
|
|
117
|
+
* @param {import("./IP").IPOptions} [options]
|
|
118
|
+
* @param {number|null} [index]
|
|
119
|
+
* @param {boolean} [autoConnect]
|
|
120
|
+
*/
|
|
121
|
+
sendIP(type, data, options, index = null, autoConnect = true) {
|
|
122
|
+
/** @type {IP} */
|
|
91
123
|
let ip;
|
|
92
124
|
let idx = index;
|
|
93
125
|
if (IP.isIP(type)) {
|
|
94
|
-
ip = type;
|
|
126
|
+
ip = /** @type {IP} */ (type);
|
|
95
127
|
idx = ip.index;
|
|
96
|
-
} else {
|
|
128
|
+
} else if (typeof type === 'string') {
|
|
97
129
|
ip = new IP(type, data, options);
|
|
130
|
+
} else {
|
|
131
|
+
throw new Error('Unknown type for IP type');
|
|
98
132
|
}
|
|
99
133
|
const sockets = this.getSockets(idx);
|
|
100
134
|
this.checkRequired(sockets);
|
|
@@ -108,9 +142,9 @@ export default class OutPort extends BasePort {
|
|
|
108
142
|
ip.schema = this.getSchema();
|
|
109
143
|
}
|
|
110
144
|
|
|
111
|
-
const cachedData = this.cache[idx] != null ? this.cache[idx].data : undefined;
|
|
145
|
+
const cachedData = this.cache[`${idx}`] != null ? this.cache[`${idx}`].data : undefined;
|
|
112
146
|
if (this.isCaching() && data !== cachedData) {
|
|
113
|
-
this.cache[idx] = ip;
|
|
147
|
+
this.cache[`${idx}`] = ip;
|
|
114
148
|
}
|
|
115
149
|
let pristine = true;
|
|
116
150
|
sockets.forEach((socket) => {
|
|
@@ -126,30 +160,57 @@ export default class OutPort extends BasePort {
|
|
|
126
160
|
return this;
|
|
127
161
|
}
|
|
128
162
|
|
|
163
|
+
/**
|
|
164
|
+
* @param {string|null} data
|
|
165
|
+
* @param {import("./IP").IPOptions} options
|
|
166
|
+
* @param {number|null} [index]
|
|
167
|
+
*/
|
|
129
168
|
openBracket(data = null, options = {}, index = null) {
|
|
130
169
|
return this.sendIP('openBracket', data, options, index);
|
|
131
170
|
}
|
|
132
171
|
|
|
172
|
+
/**
|
|
173
|
+
* @param {any} data
|
|
174
|
+
* @param {import("./IP").IPOptions} options
|
|
175
|
+
* @param {number|null} [index]
|
|
176
|
+
*/
|
|
133
177
|
data(data, options = {}, index = null) {
|
|
134
178
|
return this.sendIP('data', data, options, index);
|
|
135
179
|
}
|
|
136
180
|
|
|
181
|
+
/**
|
|
182
|
+
* @param {string|null} data
|
|
183
|
+
* @param {import("./IP").IPOptions} options
|
|
184
|
+
* @param {number|null} [index]
|
|
185
|
+
*/
|
|
137
186
|
closeBracket(data = null, options = {}, index = null) {
|
|
138
187
|
return this.sendIP('closeBracket', data, options, index);
|
|
139
188
|
}
|
|
140
189
|
|
|
190
|
+
/**
|
|
191
|
+
* @param {Array<import("./InternalSocket").InternalSocket|void>} sockets
|
|
192
|
+
*/
|
|
141
193
|
checkRequired(sockets) {
|
|
142
194
|
if ((sockets.length === 0) && this.isRequired()) {
|
|
143
195
|
throw new Error(`${this.getId()}: No connections available`);
|
|
144
196
|
}
|
|
145
197
|
}
|
|
146
198
|
|
|
199
|
+
/**
|
|
200
|
+
* @param {number|null} index
|
|
201
|
+
* @returns {Array<import("./InternalSocket").InternalSocket|void>}
|
|
202
|
+
*/
|
|
147
203
|
getSockets(index) {
|
|
148
204
|
// Addressable sockets affect only one connection at time
|
|
149
205
|
if (this.isAddressable()) {
|
|
150
|
-
if (index === null) {
|
|
151
|
-
|
|
152
|
-
|
|
206
|
+
if (index === null) {
|
|
207
|
+
throw new Error(`${this.getId()} Socket ID required`);
|
|
208
|
+
}
|
|
209
|
+
const idx = /** @type {number} */ (index);
|
|
210
|
+
if (!this.sockets[idx]) {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
return [this.sockets[idx]];
|
|
153
214
|
}
|
|
154
215
|
// Regular sockets affect all outbound connections
|
|
155
216
|
return this.sockets;
|
package/src/lib/Platform.js
CHANGED
|
@@ -41,12 +41,17 @@ export function deprecated(message) {
|
|
|
41
41
|
* @param {Function} func
|
|
42
42
|
* @returns {void}
|
|
43
43
|
*/
|
|
44
|
-
export function makeAsync(func) {
|
|
44
|
+
export function makeAsync(func, sameLoop = false) {
|
|
45
45
|
if (isBrowser()) {
|
|
46
|
+
// FIXME: Browsers don't have setImmediate yet so can't do same loop
|
|
46
47
|
setTimeout(func, 0);
|
|
47
48
|
return;
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (sameLoop) {
|
|
51
|
+
setImmediate(() => {
|
|
52
|
+
func();
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
process.nextTick(func);
|
|
52
57
|
}
|