vaporous 0.0.10 → 0.0.12
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/Vaporous.js +59 -37
- package/package.json +3 -1
- package/src/core.js +4 -31
- package/src/http.js +50 -45
- package/src/processing.js +37 -7
- package/src/statistics.js +3 -1
- package/src/transformations.js +12 -11
- package/src/visualization.js +4 -2
package/Vaporous.js
CHANGED
|
@@ -85,7 +85,7 @@ class Vaporous {
|
|
|
85
85
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
86
86
|
*/
|
|
87
87
|
method(operation, name, options) {
|
|
88
|
-
return
|
|
88
|
+
return processing.method.call(this, operation, name, options);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
@@ -108,13 +108,17 @@ class Vaporous {
|
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
110
|
* Execute all queued operations
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
* @param {string} [stageName] - Optional stage name for logging
|
|
112
|
+
* @returns {Promise<Vaporous>} - Returns this instance for chaining
|
|
113
113
|
*/
|
|
114
|
-
|
|
115
|
-
return
|
|
114
|
+
begin(stageName) {
|
|
115
|
+
return core.begin.call(this, stageName);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Serialize the Vaporous instance to a plain object
|
|
120
|
+
* @returns {Object} - Serialized instance data
|
|
121
|
+
*/
|
|
118
122
|
serialise({ } = {}) {
|
|
119
123
|
return core.serialise.call(this);
|
|
120
124
|
}
|
|
@@ -167,6 +171,7 @@ class Vaporous {
|
|
|
167
171
|
/**
|
|
168
172
|
* Evaluate and modify each event
|
|
169
173
|
* @param {Function} modifier - Function that receives an event and returns modifications to apply
|
|
174
|
+
* @param {boolean} [discard] - Whether to discard the event if modifier returns falsy
|
|
170
175
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
171
176
|
*/
|
|
172
177
|
eval(modifier, discard) {
|
|
@@ -233,8 +238,8 @@ class Vaporous {
|
|
|
233
238
|
* @param {string} target - Field name containing array to expand
|
|
234
239
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
235
240
|
*/
|
|
236
|
-
mvexpand(
|
|
237
|
-
return transformations.mvexpand.call(this,
|
|
241
|
+
mvexpand(...targets) {
|
|
242
|
+
return transformations.mvexpand.call(this, targets);
|
|
238
243
|
}
|
|
239
244
|
|
|
240
245
|
// ========================================
|
|
@@ -246,15 +251,15 @@ class Vaporous {
|
|
|
246
251
|
* @private
|
|
247
252
|
*/
|
|
248
253
|
_fileScan(directory) {
|
|
249
|
-
return fileOperations._fileScan
|
|
254
|
+
return fileOperations._fileScan.call(this, directory);
|
|
250
255
|
}
|
|
251
256
|
|
|
252
257
|
/**
|
|
253
258
|
* Internal file load helper
|
|
254
259
|
* @private
|
|
255
260
|
*/
|
|
256
|
-
|
|
257
|
-
return
|
|
261
|
+
_fileLoad(events, delim, parser) {
|
|
262
|
+
return fileOperations._fileLoad.call(this, events, delim, parser);
|
|
258
263
|
}
|
|
259
264
|
|
|
260
265
|
/**
|
|
@@ -263,7 +268,7 @@ class Vaporous {
|
|
|
263
268
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
264
269
|
*/
|
|
265
270
|
fileScan(directory) {
|
|
266
|
-
return fileOperations.fileScan
|
|
271
|
+
return fileOperations.fileScan.call(this, directory);
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
/**
|
|
@@ -271,8 +276,8 @@ class Vaporous {
|
|
|
271
276
|
* @param {Function} parser - Parser function for CSV rows
|
|
272
277
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
273
278
|
*/
|
|
274
|
-
|
|
275
|
-
return
|
|
279
|
+
csvLoad(parser) {
|
|
280
|
+
return fileOperations.csvLoad.call(this, parser);
|
|
276
281
|
}
|
|
277
282
|
|
|
278
283
|
/**
|
|
@@ -281,8 +286,8 @@ class Vaporous {
|
|
|
281
286
|
* @param {Function} parser - Parser function for lines
|
|
282
287
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
283
288
|
*/
|
|
284
|
-
|
|
285
|
-
return
|
|
289
|
+
fileLoad(delim, parser) {
|
|
290
|
+
return fileOperations.fileLoad.call(this, delim, parser);
|
|
286
291
|
}
|
|
287
292
|
|
|
288
293
|
/**
|
|
@@ -291,7 +296,7 @@ class Vaporous {
|
|
|
291
296
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
292
297
|
*/
|
|
293
298
|
writeFile(title) {
|
|
294
|
-
return fileOperations.writeFile
|
|
299
|
+
return fileOperations.writeFile.call(this, title);
|
|
295
300
|
}
|
|
296
301
|
|
|
297
302
|
/**
|
|
@@ -300,7 +305,7 @@ class Vaporous {
|
|
|
300
305
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
301
306
|
*/
|
|
302
307
|
output(...args) {
|
|
303
|
-
return fileOperations.output
|
|
308
|
+
return fileOperations.output.call(this, ...args);
|
|
304
309
|
}
|
|
305
310
|
|
|
306
311
|
// ========================================
|
|
@@ -321,7 +326,7 @@ class Vaporous {
|
|
|
321
326
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
322
327
|
*/
|
|
323
328
|
stats(...args) {
|
|
324
|
-
return statistics.stats
|
|
329
|
+
return statistics.stats.call(this, ...args);
|
|
325
330
|
}
|
|
326
331
|
|
|
327
332
|
/**
|
|
@@ -330,7 +335,7 @@ class Vaporous {
|
|
|
330
335
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
331
336
|
*/
|
|
332
337
|
eventstats(...args) {
|
|
333
|
-
return statistics.eventstats
|
|
338
|
+
return statistics.eventstats.call(this, ...args);
|
|
334
339
|
}
|
|
335
340
|
|
|
336
341
|
/**
|
|
@@ -338,7 +343,7 @@ class Vaporous {
|
|
|
338
343
|
* @private
|
|
339
344
|
*/
|
|
340
345
|
_streamstats(...args) {
|
|
341
|
-
return statistics._streamstats
|
|
346
|
+
return statistics._streamstats.call(this, ...args);
|
|
342
347
|
}
|
|
343
348
|
|
|
344
349
|
/**
|
|
@@ -347,7 +352,7 @@ class Vaporous {
|
|
|
347
352
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
348
353
|
*/
|
|
349
354
|
streamstats(...args) {
|
|
350
|
-
return statistics.streamstats
|
|
355
|
+
return statistics.streamstats.call(this, ...args);
|
|
351
356
|
}
|
|
352
357
|
|
|
353
358
|
/**
|
|
@@ -358,7 +363,7 @@ class Vaporous {
|
|
|
358
363
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
359
364
|
*/
|
|
360
365
|
delta(field, remapField, ...bys) {
|
|
361
|
-
return statistics.delta
|
|
366
|
+
return statistics.delta.call(this, field, remapField, ...bys);
|
|
362
367
|
}
|
|
363
368
|
|
|
364
369
|
// ========================================
|
|
@@ -370,7 +375,7 @@ class Vaporous {
|
|
|
370
375
|
* @private
|
|
371
376
|
*/
|
|
372
377
|
_checkpoint(operation, name, data, options) {
|
|
373
|
-
return checkpoints._checkpoint
|
|
378
|
+
return checkpoints._checkpoint.call(this, operation, name, data, options);
|
|
374
379
|
}
|
|
375
380
|
|
|
376
381
|
/**
|
|
@@ -381,7 +386,7 @@ class Vaporous {
|
|
|
381
386
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
382
387
|
*/
|
|
383
388
|
checkpoint(operation, name, options) {
|
|
384
|
-
return checkpoints.checkpoint
|
|
389
|
+
return checkpoints.checkpoint.call(this, operation, name, options);
|
|
385
390
|
}
|
|
386
391
|
|
|
387
392
|
/**
|
|
@@ -392,7 +397,7 @@ class Vaporous {
|
|
|
392
397
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
393
398
|
*/
|
|
394
399
|
filterIntoCheckpoint(checkpointName, funct, options) {
|
|
395
|
-
return checkpoints.filterIntoCheckpoint
|
|
400
|
+
return checkpoints.filterIntoCheckpoint.call(this, checkpointName, funct, options);
|
|
396
401
|
}
|
|
397
402
|
|
|
398
403
|
/**
|
|
@@ -402,8 +407,8 @@ class Vaporous {
|
|
|
402
407
|
* @param {string} partitionBy - Field to partition by
|
|
403
408
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
404
409
|
*/
|
|
405
|
-
|
|
406
|
-
return
|
|
410
|
+
storedCheckpoint(operation, name, partitionBy) {
|
|
411
|
+
return checkpoints.storedCheckpoint.call(this, operation, name, partitionBy);
|
|
407
412
|
}
|
|
408
413
|
|
|
409
414
|
// ========================================
|
|
@@ -416,7 +421,7 @@ class Vaporous {
|
|
|
416
421
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
417
422
|
*/
|
|
418
423
|
toGraph(...keys) {
|
|
419
|
-
return visualization.toGraph
|
|
424
|
+
return visualization.toGraph.call(this, ...keys);
|
|
420
425
|
}
|
|
421
426
|
|
|
422
427
|
/**
|
|
@@ -427,16 +432,17 @@ class Vaporous {
|
|
|
427
432
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
428
433
|
*/
|
|
429
434
|
build(title, type, options) {
|
|
430
|
-
return visualization.build
|
|
435
|
+
return visualization.build.call(this, title, type, options);
|
|
431
436
|
}
|
|
432
437
|
|
|
433
438
|
/**
|
|
434
439
|
* Render visualizations
|
|
440
|
+
* @param {string} location - Location to render visualizations
|
|
435
441
|
* @param {Object} [options] - Optional render options
|
|
436
442
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
437
443
|
*/
|
|
438
|
-
render(options) {
|
|
439
|
-
return visualization.render
|
|
444
|
+
render(location, options) {
|
|
445
|
+
return visualization.render.call(this, location, options);
|
|
440
446
|
}
|
|
441
447
|
|
|
442
448
|
// ========================================
|
|
@@ -449,7 +455,7 @@ class Vaporous {
|
|
|
449
455
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
450
456
|
*/
|
|
451
457
|
load_http(options) {
|
|
452
|
-
return http.load_http
|
|
458
|
+
return http.load_http.call(this, options);
|
|
453
459
|
}
|
|
454
460
|
|
|
455
461
|
// ========================================
|
|
@@ -463,7 +469,7 @@ class Vaporous {
|
|
|
463
469
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
464
470
|
*/
|
|
465
471
|
interval(callback, ms) {
|
|
466
|
-
return processing.interval
|
|
472
|
+
return processing.interval.call(this, callback, ms);
|
|
467
473
|
}
|
|
468
474
|
|
|
469
475
|
/**
|
|
@@ -474,19 +480,35 @@ class Vaporous {
|
|
|
474
480
|
* @returns {Vaporous} - Returns this instance for chaining
|
|
475
481
|
*/
|
|
476
482
|
parallel(concurrency, callback, options) {
|
|
477
|
-
return processing.parallel
|
|
483
|
+
return processing.parallel.call(this, concurrency, callback, options);
|
|
478
484
|
}
|
|
479
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Recursively process events
|
|
488
|
+
* @param {Function} callback - Function to execute recursively
|
|
489
|
+
* @returns {Vaporous} - Returns this instance for chaining
|
|
490
|
+
*/
|
|
480
491
|
recurse(callback) {
|
|
481
|
-
return processing.recurse
|
|
492
|
+
return processing.recurse.call(this, callback);
|
|
482
493
|
}
|
|
483
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Debug events by executing a callback
|
|
497
|
+
* @param {Function} callback - Debug callback function
|
|
498
|
+
* @returns {Vaporous} - Returns this instance for chaining
|
|
499
|
+
*/
|
|
484
500
|
debug(callback) {
|
|
485
|
-
return core.debug.call(this, callback)
|
|
501
|
+
return core.debug.call(this, callback);
|
|
486
502
|
}
|
|
487
503
|
|
|
504
|
+
/**
|
|
505
|
+
* Conditionally execute a callback
|
|
506
|
+
* @param {Function|boolean} condition - Condition to evaluate or boolean value
|
|
507
|
+
* @param {Function} callback - Function to execute if condition is true
|
|
508
|
+
* @returns {Vaporous} - Returns this instance for chaining
|
|
509
|
+
*/
|
|
488
510
|
doIf(condition, callback) {
|
|
489
|
-
return processing.doIf.call(this, condition, callback)
|
|
511
|
+
return processing.doIf.call(this, condition, callback);
|
|
490
512
|
}
|
|
491
513
|
}
|
|
492
514
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vaporous",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Transition data to different structured states for analytical processing",
|
|
5
5
|
"main": "Vaporous.js",
|
|
6
6
|
"scripts": {
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"dayjs": "^1.11.18",
|
|
13
|
+
"http-proxy-agent": "^7.0.2",
|
|
14
|
+
"https-proxy-agent": "^7.0.6",
|
|
13
15
|
"papaparse": "^5.5.3",
|
|
14
16
|
"split2": "^4.2.0"
|
|
15
17
|
}
|
package/src/core.js
CHANGED
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
method(operation, name, options) {
|
|
3
|
-
const operations = {
|
|
4
|
-
create: () => {
|
|
5
|
-
this.savedMethods[name] = options
|
|
6
|
-
},
|
|
7
|
-
retrieve: () => {
|
|
8
|
-
if (!this.savedMethods[name]) throw new Error('Method not found ' + name)
|
|
9
|
-
this.savedMethods[name](this, options)
|
|
10
|
-
},
|
|
11
|
-
delete: () => {
|
|
12
|
-
delete this.savedMethods[name]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
operations[operation]()
|
|
17
|
-
if (operation !== 'retrieve') return this;
|
|
18
|
-
return this;
|
|
19
|
-
},
|
|
20
|
-
|
|
21
2
|
async debug(callback) {
|
|
22
3
|
await callback(this)
|
|
23
4
|
return this;
|
|
@@ -71,20 +52,12 @@ module.exports = {
|
|
|
71
52
|
const Vaporous = require('../Vaporous').Vaporous;
|
|
72
53
|
const cloneInstance = new Vaporous()
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Object.keys(this).forEach(key => {
|
|
78
|
-
if (excludeCompletely.includes(key)) return;
|
|
79
|
-
cloneInstance[key] = (deep && !excludeStructualClone.includes(key)) ? structuredClone(this[key]) : this[key]
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const purge = ['checkpoints', 'events']
|
|
83
|
-
|
|
84
|
-
purge.forEach(purgeItem => {
|
|
85
|
-
cloneInstance[purgeItem] = []
|
|
55
|
+
Object.keys(this).forEach(prop => {
|
|
56
|
+
cloneInstance[prop] = this[prop]
|
|
86
57
|
})
|
|
87
58
|
|
|
59
|
+
cloneInstance.processingQueue = []
|
|
60
|
+
cloneInstance._isExecuting = false
|
|
88
61
|
return cloneInstance
|
|
89
62
|
},
|
|
90
63
|
|
package/src/http.js
CHANGED
|
@@ -3,59 +3,64 @@ const httpsLib = require('https')
|
|
|
3
3
|
const { HttpProxyAgent } = require('http-proxy-agent')
|
|
4
4
|
const { HttpsProxyAgent } = require('https-proxy-agent')
|
|
5
5
|
|
|
6
|
+
const request = async ({ uri, method, headers, body, options = {} }) => {
|
|
7
|
+
const response = await new Promise((resolve, reject) => {
|
|
8
|
+
const isHTTPs = uri.startsWith('https')
|
|
9
|
+
const lib = isHTTPs ? httpsLib : httpLib
|
|
10
|
+
const { hostname, port, pathname, search } = new URL(uri)
|
|
11
|
+
const path = pathname + (search || '')
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
const options = {
|
|
14
|
+
method,
|
|
15
|
+
hostname,
|
|
16
|
+
port,
|
|
17
|
+
path,
|
|
18
|
+
headers
|
|
19
|
+
}
|
|
8
20
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
method: _http_req_method,
|
|
23
|
-
hostname,
|
|
24
|
-
port,
|
|
25
|
-
path,
|
|
26
|
-
headers: _http_req_headers
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const proxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy
|
|
30
|
-
|
|
31
|
-
if (proxy) {
|
|
32
|
-
const isHttps = _http_req_uri.startsWith('https')
|
|
33
|
-
options.agent = isHttps ? new HttpsProxyAgent(proxy) : new HttpProxyAgent(proxy)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const req = lib.request(options, res => {
|
|
37
|
-
let body = '';
|
|
38
|
-
|
|
39
|
-
res.on('data', data => {
|
|
40
|
-
body += data
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
res.on('end', () => {
|
|
44
|
-
event._http_res_body = body
|
|
45
|
-
event._http_res_status = res.statusCode
|
|
46
|
-
event._http_res_headers = res.headers
|
|
47
|
-
resolve(body)
|
|
48
|
-
})
|
|
21
|
+
const proxy = isHTTPs ? (process.env.https_proxy || process.env.HTTPS_PROXY) : (process.env.http_proxy || process.env.HTTP_PROXY)
|
|
22
|
+
|
|
23
|
+
if (proxy) options.agent = isHTTPs ? new HttpsProxyAgent(proxy) : new HttpProxyAgent(proxy)
|
|
24
|
+
|
|
25
|
+
const req = lib.request(options, res => {
|
|
26
|
+
let body = '';
|
|
27
|
+
|
|
28
|
+
res.on('data', data => {
|
|
29
|
+
body += data
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
res.on('end', () => {
|
|
33
|
+
resolve({ body, statusCode: res.statusCode, headers: res.headers })
|
|
49
34
|
})
|
|
35
|
+
})
|
|
50
36
|
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
if (body) req.write(body)
|
|
38
|
+
req.end()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (response.statusCode === 307) {
|
|
42
|
+
return request({ uri: response.headers.location, method, headers, body, options })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return response;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function load_http() {
|
|
49
|
+
|
|
50
|
+
for (let event of this.events) {
|
|
51
|
+
const res = await request({
|
|
52
|
+
uri: event._http_req_uri,
|
|
53
|
+
method: event._http_req_method,
|
|
54
|
+
headers: event._http_req_headers,
|
|
55
|
+
body: event._http_req_body
|
|
53
56
|
})
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
event._http_res_status = res.statusCode
|
|
59
|
+
event._http_res_headers = res.headers
|
|
60
|
+
event._http_res_body = res.body
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
return this
|
|
63
|
+
return this
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
module.exports = {
|
package/src/processing.js
CHANGED
|
@@ -31,8 +31,9 @@ async function parallel(target, { multiThread = false } = {}, callbackPath) {
|
|
|
31
31
|
const instance = new Vaporous({ loggers })
|
|
32
32
|
instance.events = thisEvent
|
|
33
33
|
|
|
34
|
-
const task =
|
|
35
|
-
tasks.push(task
|
|
34
|
+
const task = funct(instance).begin()
|
|
35
|
+
tasks.push(task)
|
|
36
|
+
await task
|
|
36
37
|
|
|
37
38
|
await processSingleThread()
|
|
38
39
|
}
|
|
@@ -135,9 +136,11 @@ async function recurse(funct) {
|
|
|
135
136
|
for (let event of this.events) {
|
|
136
137
|
const target = new Vaporous({ loggers: this.loggers })
|
|
137
138
|
target.events = [event]
|
|
139
|
+
event._recursion = true
|
|
138
140
|
|
|
139
141
|
const localRecursion = async (target) => {
|
|
140
|
-
const
|
|
142
|
+
const executionChain = funct(target)
|
|
143
|
+
const val = await executionChain.begin()
|
|
141
144
|
if (val.events[0]._recursion) return localRecursion(target)
|
|
142
145
|
return val
|
|
143
146
|
}
|
|
@@ -150,9 +153,35 @@ async function recurse(funct) {
|
|
|
150
153
|
return this;
|
|
151
154
|
}
|
|
152
155
|
|
|
153
|
-
function doIf(condition, callback) {
|
|
154
|
-
const proceed = condition(this)
|
|
155
|
-
if (proceed)
|
|
156
|
+
async function doIf(condition, callback) {
|
|
157
|
+
const proceed = await condition(this)
|
|
158
|
+
if (proceed) {
|
|
159
|
+
const clone = this.clone()
|
|
160
|
+
const task = await callback(clone)
|
|
161
|
+
await task.begin()
|
|
162
|
+
this.events = clone.events
|
|
163
|
+
}
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function method(operation, name, options) {
|
|
168
|
+
const operations = {
|
|
169
|
+
create: () => {
|
|
170
|
+
this.savedMethods[name] = options
|
|
171
|
+
},
|
|
172
|
+
retrieve: async () => {
|
|
173
|
+
if (!this.savedMethods[name]) throw new Error('Method not found ' + name)
|
|
174
|
+
const clone = this.clone()
|
|
175
|
+
const task = await clone.savedMethods[name](clone, options)
|
|
176
|
+
await task.begin()
|
|
177
|
+
this.events = clone.events
|
|
178
|
+
},
|
|
179
|
+
delete: () => {
|
|
180
|
+
delete this.savedMethods[name]
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
await operations[operation]()
|
|
156
185
|
return this;
|
|
157
186
|
}
|
|
158
187
|
|
|
@@ -160,5 +189,6 @@ module.exports = {
|
|
|
160
189
|
parallel,
|
|
161
190
|
interval,
|
|
162
191
|
recurse,
|
|
163
|
-
doIf
|
|
192
|
+
doIf,
|
|
193
|
+
method
|
|
164
194
|
}
|
package/src/statistics.js
CHANGED
|
@@ -41,7 +41,9 @@ module.exports = {
|
|
|
41
41
|
const reference = map[key]._statsRaw[aggregation.field]
|
|
42
42
|
|
|
43
43
|
if (aggregation.sortable) {
|
|
44
|
-
sortedCache[aggregation.field]
|
|
44
|
+
if (sortedCache[aggregation.field] === undefined) {
|
|
45
|
+
sortedCache[aggregation.field] = reference.slice().sort((a, b) => a - b)
|
|
46
|
+
}
|
|
45
47
|
result[outputField] = aggregation.calculate(sortedCache[aggregation.field])
|
|
46
48
|
} else {
|
|
47
49
|
result[outputField] = aggregation.calculate(reference)
|
package/src/transformations.js
CHANGED
|
@@ -60,27 +60,28 @@ module.exports = {
|
|
|
60
60
|
return this;
|
|
61
61
|
},
|
|
62
62
|
|
|
63
|
-
mvexpand(
|
|
63
|
+
mvexpand(targets) {
|
|
64
64
|
|
|
65
65
|
const arr = []
|
|
66
66
|
this.events.forEach(event => {
|
|
67
67
|
if (event instanceof Array) {
|
|
68
|
-
if (
|
|
68
|
+
if (targets.length !== 0) throw new Error('Cannot mvexpand on a target value when source data is array')
|
|
69
|
+
|
|
69
70
|
event.forEach((item, i) => {
|
|
70
|
-
item.
|
|
71
|
+
item._mvExpand = i
|
|
71
72
|
arr.push(item)
|
|
72
73
|
})
|
|
73
74
|
} else {
|
|
75
|
+
// Identify max iterations
|
|
76
|
+
const max = targets.reduce((prev, curr) => Math.max(prev, event[curr].length), 0)
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
...event,
|
|
80
|
-
[target]: item,
|
|
81
|
-
[`_mvExpand_${target}`]: i
|
|
78
|
+
for (let i = 0; i < max; i++) {
|
|
79
|
+
const obj = { ...event, _mvExpand: i }
|
|
80
|
+
targets.forEach(target => {
|
|
81
|
+
obj[target] = event[target][i]
|
|
82
82
|
})
|
|
83
|
-
|
|
83
|
+
arr.push(obj)
|
|
84
|
+
}
|
|
84
85
|
}
|
|
85
86
|
})
|
|
86
87
|
|
package/src/visualization.js
CHANGED
|
@@ -372,12 +372,14 @@ module.exports = {
|
|
|
372
372
|
return this;
|
|
373
373
|
},
|
|
374
374
|
|
|
375
|
-
render(location = './Vaporous_generation.html',
|
|
375
|
+
render(location = './Vaporous_generation.html', options = {}) {
|
|
376
376
|
|
|
377
377
|
|
|
378
378
|
const classSafe = (name) => name.replace(/[^a-zA-Z0-9]/g, "_")
|
|
379
379
|
|
|
380
|
-
if (
|
|
380
|
+
if (typeof options === 'function') options = options()
|
|
381
|
+
|
|
382
|
+
if (options.tabOrder) this.tabs = options.tabOrder
|
|
381
383
|
|
|
382
384
|
const createElement = (name, type, visualisationOptions, eventData, { trellis, trellisName = "", columnDefinitions }) => {
|
|
383
385
|
|