vaporous 0.0.10 → 0.0.11

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 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 core.method.call(this, operation, name, options);
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
- * @param {string} [stageName] - Optional stage name for logging
112
- * @returns {Promise<Vaporous>} - Returns this instance for chaining
111
+ * @param {string} [stageName] - Optional stage name for logging
112
+ * @returns {Promise<Vaporous>} - Returns this instance for chaining
113
113
  */
114
- async begin(stageName) {
115
- return await core.begin.call(this, stageName);
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) {
@@ -246,15 +251,15 @@ class Vaporous {
246
251
  * @private
247
252
  */
248
253
  _fileScan(directory) {
249
- return fileOperations._fileScan?.call(this, directory);
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
- async _fileLoad(events, delim, parser) {
257
- return await fileOperations._fileLoad?.call(this, events, delim, parser);
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?.call(this, directory) || this;
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
- async csvLoad(parser) {
275
- return await fileOperations.csvLoad?.call(this, parser) || this;
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
- async fileLoad(delim, parser) {
285
- return await fileOperations.fileLoad?.call(this, delim, parser) || this;
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?.call(this, title) || this;
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?.call(this, ...args) || this;
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?.call(this, ...args) || this;
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?.call(this, ...args) || this;
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?.call(this, ...args) || this;
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?.call(this, ...args) || this;
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?.call(this, field, remapField, ...bys) || this;
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?.call(this, operation, name, data, options) || this;
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?.call(this, operation, name, options) || this;
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?.call(this, checkpointName, funct, options) || this;
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
- async storedCheckpoint(operation, name, partitionBy) {
406
- return await checkpoints.storedCheckpoint?.call(this, operation, name, partitionBy) || this;
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?.call(this, ...keys) || this;
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?.call(this, title, type, options) || this;
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?.call(this, options) || this;
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?.call(this, options) || this;
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?.call(this, callback, ms) || this;
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?.call(this, concurrency, callback, options) || this;
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?.call(this, callback)
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
 
@@ -0,0 +1,324 @@
1
+
2
+ <html>
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=0.5">
5
+ <style>
6
+ @import url('https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap');
7
+
8
+ /* Apply Roboto to all elements */
9
+ * {
10
+ font-family: 'Roboto', Arial, sans-serif !important;
11
+ }
12
+
13
+ body {
14
+ font-family: 'Roboto', Arial, sans-serif;
15
+ }
16
+
17
+ /* Chart-specific styles */
18
+ .chart,
19
+ .chart-container,
20
+ canvas,
21
+ svg,
22
+ .chartjs-render-monitor {
23
+ font-family: 'Roboto', Arial, sans-serif !important;
24
+ }
25
+
26
+ /* Third-party library overrides */
27
+ .ag-theme-quartz,
28
+ .ag-cell,
29
+ .ag-header-cell,
30
+ .tabulator,
31
+ .tabulator-cell,
32
+ .tabulator-header {
33
+ font-family: 'Roboto', Arial, sans-serif !important;
34
+ }
35
+
36
+ body {
37
+ margin: 0;
38
+ padding: 16px;
39
+ }
40
+
41
+ .tabBar {
42
+ display: flex;
43
+ overflow: auto;
44
+ box-shadow:
45
+ 0 3px 12px rgba(0, 0, 0, 0.09),
46
+ 0 6px 18px rgba(0, 0, 0, 0.06);
47
+ min-height: 32px;
48
+ margin-bottom: 24px;
49
+ margin-top: 8px;
50
+ margin-left: 8px;
51
+ margin-right: 8px;
52
+ position: relative;
53
+ background: #fff;
54
+ align-items: center;
55
+ }
56
+
57
+ .tabs {
58
+ border-radius: 8px;
59
+ padding: 8px 20px;
60
+ cursor: pointer;
61
+ background: none;
62
+ border: none;
63
+ outline: none;
64
+ font-size: 1rem;
65
+ color: #555;
66
+ transition: all 0.3s ease-in-out;
67
+ text-align: center;
68
+ margin: 12px;
69
+ position: relative;
70
+ z-index: 1;
71
+ }
72
+
73
+ .tabs:not(.selectedTab):hover {
74
+ color: #1976d2;
75
+ }
76
+
77
+ .selectedTab {
78
+ color: #fff;
79
+ font-weight: bold;
80
+ }
81
+
82
+ .selectedTab::before {
83
+ content: '';
84
+ position: absolute;
85
+ background: #1976d2;
86
+ border-radius: 8px;
87
+ z-index: -1;
88
+ top: 0;
89
+ left: 0;
90
+ width: 100%;
91
+ height: 100%;
92
+ transition: transform 0.3s ease-in-out;
93
+ box-shadow:
94
+ 0 4px 16px rgba(25, 118, 210, 0.3),
95
+ 0 8px 24px rgba(25, 118, 210, 0.2);
96
+ animation: slideInFromLeft 0.3s ease-in-out forwards;
97
+ }
98
+
99
+ .selectedTab.slideFromRight::before {
100
+ animation: slideInFromRight 0.3s ease-in-out forwards;
101
+ }
102
+
103
+ @keyframes slideInFromLeft {
104
+ 0% {
105
+ transform: translateX(-100%);
106
+ opacity: 0;
107
+ }
108
+
109
+ 100% {
110
+ transform: translateX(0);
111
+ opacity: 1;
112
+ }
113
+ }
114
+
115
+ @keyframes slideInFromRight {
116
+ 0% {
117
+ transform: translateX(100%);
118
+ opacity: 0;
119
+ }
120
+
121
+ 100% {
122
+ transform: translateX(0);
123
+ opacity: 1;
124
+ }
125
+ }
126
+
127
+ #content {
128
+ display: flex;
129
+ flex-wrap: wrap;
130
+ padding: 0px;
131
+ gap: 8px;
132
+ justify-content: flex-start;
133
+ }
134
+
135
+ .parentHolder {
136
+ display: flex;
137
+ margin: 2px;
138
+ border: 1px solid #d3d3d3;
139
+ }
140
+
141
+ .parentHolder::after {
142
+ border: 2px solid red;
143
+ /* Change color and width as needed */
144
+ pointer-events: none;
145
+ z-index: 2;
146
+ }
147
+
148
+ .tabContent {
149
+ opacity: 1;
150
+ transition: opacity 0.3s,
151
+ }
152
+
153
+ .graphTitle {
154
+ opacity: 0.7;
155
+ text-align: center;
156
+ display: 'flex';
157
+ }
158
+
159
+ .tableHolder {
160
+ margin-top: 8px;
161
+ width: 100%;
162
+ /* height: 600px; */
163
+ /* overflow: auto; */
164
+ }
165
+
166
+ #extendedDescription {
167
+ text-align: center;
168
+ opacity: 0.7;
169
+ margin-bottom: 16px;
170
+ }
171
+ </style>
172
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
173
+ <script src="https://cdn.jsdelivr.net/npm/ag-grid-community@34.2.0/dist/ag-grid-community.min.js"></script>
174
+
175
+
176
+ <script type="text/javascript">
177
+
178
+ const classSafe = (name) => name.replace(/[^a-zA-Z0-9]/g, "_")
179
+
180
+ var selectedTab = classSafe("User Stats")
181
+ var previousTab = null
182
+ const tokens = {}
183
+ const visualisationData = [[{"columnDefinitions":[{"field":"gender"},{"field":"avgHeight"}],"rowData":[{"gender":"female","avgHeight":177.5666666666667},{"gender":"male","avgHeight":173.15249999999997}],"title":"Average height"}],[{"type":"line","data":{"labels":["female","male"],"datasets":[{"label":"avgHeight","data":[177.5666666666667,173.15249999999997],"pointRadius":0}]},"options":{"scales":{"y":{"type":"linear","display":true,"position":"left","min":173.15249999999997,"max":[177.5666666666667]},"x":{"type":"category","ticks":{"display":false}}},"responsive":true,"plugins":{"legend":{"display":true,"position":"bottom"},"title":{"display":false,"text":"Average height"}}}}]]
184
+ const tabOrder = ["User_Stats"]
185
+
186
+ const _sort = (order, data, ...keys) => {
187
+ return data.sort((a, b) => {
188
+ let directive = 0;
189
+
190
+ keys.some(key => {
191
+ directive = typeof a[key] === 'number' ? a[key] - b[key] : a[key].localeCompare(b[key])
192
+ if (order === 'dsc') directive = directive * -1
193
+ if (directive !== 0) return true;
194
+ })
195
+
196
+ return directive;
197
+ })
198
+ }
199
+ const createElement = (name, type, visualisationOptions, eventData, { trellis, trellisName = "", columnDefinitions }) => {
200
+
201
+ if (classSafe(visualisationOptions.tab) !== selectedTab) return;
202
+
203
+ if (visualisationOptions.extendedDescription) {
204
+ const descriptions = document.getElementById('extendedDescription')
205
+ const thisDescription = document.createElement('div')
206
+ thisDescription.innerHTML = visualisationOptions.extendedDescription
207
+ descriptions.appendChild(thisDescription)
208
+ }
209
+
210
+ eventData = visualisationData[eventData]
211
+
212
+ // TODO: migrate trellis functionality from here to tograph
213
+ if (trellis) {
214
+ let pairs = trellisName.map((name, i) => [name, eventData[i]]);
215
+ pairs = pairs.sort((a, b) => a[0].localeCompare(b[0]))
216
+
217
+ // Unzip back into separate arrays
218
+ trellisName = pairs.map(p => p[0]);
219
+ eventData = pairs.map(p => p[1]);
220
+ }
221
+
222
+ const columnCount = visualisationOptions.columns || 2
223
+
224
+ eventData.forEach((trellisData, i) => {
225
+ const parentHolder = document.createElement('div')
226
+
227
+ const titleDiv = document.createElement('div')
228
+ titleDiv.classList.add('graphTitle')
229
+ parentHolder.appendChild(titleDiv)
230
+
231
+ if (trellisData.options) {
232
+ titleDiv.textContent = trellisData.options.plugins.title.text
233
+ } else {
234
+ titleDiv.textContent = trellisData.title
235
+ }
236
+
237
+ document.getElementById('content').appendChild(parentHolder)
238
+
239
+ parentHolder.style = `flex: 0 0 calc(${100 / columnCount}% - 8px); max-width: calc(${100 / columnCount}% - 8px);`
240
+ if (type === 'Table') {
241
+ const tableDiv = document.createElement('div')
242
+ tableDiv.classList.add('tableHolder')
243
+ document.documentElement.style.setProperty("--ag-spacing", `4px`);
244
+
245
+
246
+ // Need to do column defintiions here
247
+ parentHolder.appendChild(tableDiv)
248
+ new agGrid.createGrid(tableDiv, {
249
+ suppressFieldDotNotation: true,
250
+ rowData: trellisData.rowData,
251
+ // Columns to be displayed (Should match rowData properties)
252
+ columnDefs: trellisData.columnDefinitions,
253
+ defaultColDef: {
254
+ flex: 1,
255
+ resizable: true,
256
+ sortable: true,
257
+ filter: true
258
+ },
259
+ domLayout: 'autoHeight',
260
+ enableCellTextSelection: true,
261
+ // suppressHorizontalScroll: false,
262
+ // autoSizeStrategy: {
263
+ // type: 'fitGridWidth',
264
+ // defaultMinWidth: 100
265
+ // }
266
+ });
267
+ } else {
268
+ const graphEntity = document.createElement('canvas')
269
+ parentHolder.appendChild(graphEntity)
270
+ new Chart(graphEntity, trellisData)
271
+ }
272
+
273
+ })
274
+ }
275
+
276
+ function drawVis(tab) {
277
+ if (tab) {
278
+ if (selectedTab) {
279
+ document.getElementById(selectedTab).classList.remove('selectedTab')
280
+ document.getElementById(selectedTab).classList.remove('slideFromRight')
281
+ previousTab = selectedTab
282
+ }
283
+ selectedTab = tab
284
+ } else if (true) {
285
+ selectedTab = classSafe('User Stats')
286
+ }
287
+
288
+ if (selectedTab) {
289
+ const selectedElement = document.getElementById(selectedTab)
290
+ selectedElement.classList.add('selectedTab')
291
+
292
+ // Determine slide direction based on tab positions
293
+ if (previousTab) {
294
+ const previousIndex = tabOrder.indexOf(previousTab)
295
+ const currentIndex = tabOrder.indexOf(selectedTab)
296
+
297
+ if (currentIndex < previousIndex) {
298
+ // Moving to left tab, slide from right
299
+ selectedElement.classList.add('slideFromRight')
300
+ }
301
+ // For right movement or first load, use default slideFromLeft animation
302
+ }
303
+ }
304
+ document.getElementById('content').innerHTML = ''
305
+ document.getElementById('extendedDescription').innerHTML = ''
306
+ createElement('Average height', 'Table', {"tab":"User Stats","columns":2} ,0, {"xPrimary":"gender","columnDefinitions":[["gender","avgHeight"]]}),createElement('Average height', 'Line', {"tab":"User Stats","columns":2} ,1, {"xPrimary":"gender","columnDefinitions":[["gender","avgHeight"]]})
307
+ }
308
+
309
+ document.addEventListener("DOMContentLoaded", function(event) {
310
+ drawVis()
311
+ });
312
+
313
+ </script>
314
+ </head>
315
+ <body>
316
+ <div class='tabBar'>
317
+ <div id=User_Stats class='tabs' onclick="drawVis('User_Stats')">User Stats</div>
318
+ </div>
319
+
320
+ <div id='extendedDescription'></div>
321
+ <div id='content'></div>
322
+ </body>
323
+ </html>
324
+