mushy 0.14.2 → 0.16.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.
- checksums.yaml +4 -4
- data/lib/mushy/builder/api.rb +40 -6
- data/lib/mushy/builder/documentation.rb +37 -0
- data/lib/mushy/builder/index.rb +79 -18
- data/lib/mushy/fluxs/bash.rb +22 -0
- data/lib/mushy/fluxs/browser.rb +118 -0
- data/lib/mushy/fluxs/build_csv.rb +22 -0
- data/lib/mushy/fluxs/cli.rb +11 -0
- data/lib/mushy/fluxs/document.rb +14 -0
- data/lib/mushy/fluxs/filter.rb +29 -2
- data/lib/mushy/fluxs/ls.rb +110 -0
- data/lib/mushy/fluxs/pwd.rb +40 -1
- data/lib/mushy/fluxs/read_json.rb +20 -7
- data/lib/mushy/fluxs/stdout.rb +26 -0
- data/lib/mushy/fluxs/write_json.rb +15 -0
- data/mushy.gemspec +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f18a4ff7bf18c88f36a66481bd9fd56e7511ca276f5312b2f4bf2862e8d5aa5
|
4
|
+
data.tar.gz: 2d40205cd64f986cc7234c847173ed4dbf95f0ba2f3ccf5d81e71290fb23d6c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 183e5fe0556b562c1747d1005dc238ca034ca1745e0505a763e394d008a4315de63c65f53cab0435cf45a219e54e68bf705095218ab85e572d04e658b0c6d25b
|
7
|
+
data.tar.gz: d856b27867d3946ff2ca840ae1eff9c96b07b7a06757bde41d6475351be68a36b97d9395324c4e3ee0e198ec3b5cd4352bffb5637e2f76a78663c5da08565245
|
data/lib/mushy/builder/api.rb
CHANGED
@@ -80,24 +80,58 @@ module Mushy
|
|
80
80
|
puts "trying to get: #{file}"
|
81
81
|
file = "#{file}.mushy" unless file.downcase.end_with?('.mushy')
|
82
82
|
data = JSON.parse File.open(file).read
|
83
|
-
|
83
|
+
|
84
|
+
data['fluxs'] = standardize_these data['fluxs']
|
85
|
+
data['fluxs'] = organize_as_a_flattened_tree_based_on_parents data['fluxs']
|
86
|
+
|
87
|
+
data
|
88
|
+
rescue
|
89
|
+
{ fluxs: [] }
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.standardize_these fluxs
|
93
|
+
fluxs
|
84
94
|
.reject { |x| x['parents'] }
|
85
95
|
.each { |x| x['parents'] = [x['parent']].select { |y| y } }
|
86
|
-
|
96
|
+
fluxs
|
87
97
|
.select { |x| x['parent'] }
|
88
98
|
.each { |x| x.delete 'parent' }
|
89
|
-
|
99
|
+
fluxs
|
90
100
|
.select { |x| x['parents'] }
|
91
101
|
.each { |x| x['parents'] = x['parents'].select { |y| y } }
|
92
|
-
|
93
|
-
|
94
|
-
|
102
|
+
|
103
|
+
fluxs
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.organize_as_a_flattened_tree_based_on_parents fluxs
|
107
|
+
fluxs = fluxs.sort_by { |x| x['parents'].count }
|
108
|
+
|
109
|
+
new_fluxs = [fluxs.first]
|
110
|
+
|
111
|
+
loop do
|
112
|
+
|
113
|
+
next_fluxs = fluxs.select { |x| x['parents'].include? new_fluxs[-1]['id'] }
|
114
|
+
|
115
|
+
unless next_fluxs.any?
|
116
|
+
next_fluxs = [fluxs.reject { |x| new_fluxs.map { |y| y['id'] }.include?(x['id']) }[0]].select { |x| x }
|
117
|
+
end
|
118
|
+
|
119
|
+
new_fluxs = [new_fluxs, next_fluxs].flatten
|
120
|
+
|
121
|
+
break unless next_fluxs.any?
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
new_fluxs
|
95
126
|
end
|
96
127
|
|
97
128
|
def self.get_fluxs
|
98
129
|
{
|
99
130
|
fluxs: Mushy::Flux.all.select { |x| x.respond_to? :details }.select { |x| x.details }.map do |flux|
|
100
131
|
details = flux.details
|
132
|
+
|
133
|
+
details[:documentation] = Documentation.build_from details
|
134
|
+
|
101
135
|
details[:config][:incoming_split] = { type: 'text', shrink: true, description: 'Split an incoming event into multiple events by this key, an each event will be processed independently.', default: '' }
|
102
136
|
details[:config][:outgoing_split] = { type: 'text', shrink: true, description: 'Split an outgoing event into multiple events by this key.', default: '' }
|
103
137
|
details[:config][:merge] = { type: 'text', shrink: true, description: 'A comma-delimited list of fields from the event to carry through. Use * to merge all fields.', default: '' }
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Mushy
|
2
|
+
module Builder
|
3
|
+
module Documentation
|
4
|
+
|
5
|
+
def self.build_from config
|
6
|
+
basic_usage = "#{config[:description]}"
|
7
|
+
if config[:config]&.any?
|
8
|
+
rows = config[:config]
|
9
|
+
.map { |x| [x[0], x[1][:description], (x[1][:shrink] ? '(optional) ' : '')] }
|
10
|
+
.reduce("") { |t, i| "#{t}<tr><td>#{i[0]}</td><td>#{i[2]}#{i[1]}</td></tr>" }
|
11
|
+
basic_usage += '<table class="table is-bordered"><thead><tr><td>Field</td><td>Description</td></tr></thead>' + rows + "</table>"
|
12
|
+
end
|
13
|
+
|
14
|
+
{
|
15
|
+
"Basic Usage" => basic_usage,
|
16
|
+
}.tap do |documentation|
|
17
|
+
if config[:examples]
|
18
|
+
config[:examples].each do |item|
|
19
|
+
documentation[item[0]] = [
|
20
|
+
item[1][:description],
|
21
|
+
code_sample('Input', item[1][:input]),
|
22
|
+
code_sample('Config', item[1][:config]),
|
23
|
+
code_sample('Result', item[1][:result]),
|
24
|
+
].select { |x| x }.reduce('') { |t, i| t + i }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.code_sample title, value
|
31
|
+
return nil unless value
|
32
|
+
"<div><b>#{title}</b></div><pre><code>#{JSON.pretty_generate(value)}</code></pre>"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/mushy/builder/index.rb
CHANGED
@@ -52,29 +52,73 @@ module Mushy
|
|
52
52
|
<button v-on:click.prevent.stop="startNew({ setup: setup, configs: configs })" class="button is-link">Add a New Flux To This Flow</button>
|
53
53
|
</div>
|
54
54
|
</div>
|
55
|
+
|
56
|
+
<div v-bind:class="setup.fluxTypeSelect">
|
57
|
+
<div class="modal-background"></div>
|
58
|
+
<div class="modal-card">
|
59
|
+
<header class="modal-card-head">
|
60
|
+
<p class="modal-card-title">Flux Types</p>
|
61
|
+
<button class="delete" aria-label="close" v-on:click.prevent.stop="setup.fluxTypeSelect['is-active'] = false"></button>
|
62
|
+
</header>
|
63
|
+
<section class="modal-card-body">
|
64
|
+
<div class="content">
|
65
|
+
<div v-for="(fluxType, id) in fluxTypes">
|
66
|
+
<div class="level">
|
67
|
+
<div class="level-left"><h2>{{fluxType.title || fluxType.name}}</h2></div>
|
68
|
+
<div class="level-right">
|
69
|
+
<button class="button is-primary level-item" v-on:click.prevent.stop="setup.flux.value = fluxType.name;setup.fluxTypeSelect['is-active'] = false">
|
70
|
+
Select
|
71
|
+
</button>
|
72
|
+
<button class="button level-item" v-on:click.prevent.stop="fluxType.showDetails = true" v-if="fluxType['showDetails'] == false">
|
73
|
+
Open
|
74
|
+
</button>
|
75
|
+
<button class="button level-item" v-on:click.prevent.stop="fluxType.showDetails = false" v-if="fluxType['showDetails']">
|
76
|
+
Close
|
77
|
+
</button>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<div v-if="fluxType['showDetails']">
|
82
|
+
<div class="tabs">
|
83
|
+
<ul>
|
84
|
+
<li v-for="(a, b) in fluxType.documentation"><a v-on:click.prevent.stop="fluxType.detailsTab = b">{{b}}</a></li>
|
85
|
+
</ul>
|
86
|
+
</div>
|
87
|
+
<div v-for="(a, b) in fluxType.documentation" v-if="fluxType['detailsTab'] == b" v-html="a"></div>
|
88
|
+
</div>
|
89
|
+
</div>
|
90
|
+
</div>
|
91
|
+
</section>
|
92
|
+
<footer class="modal-card-foot">
|
93
|
+
<button class="button is-primary" v-on:click.prevent.stop="setup.fluxTypeSelect['is-active'] = false">Done</button>
|
94
|
+
</footer>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
|
55
98
|
<div class="column" v-if="setup.showFlux">
|
56
99
|
<div class="columns">
|
57
100
|
<div class="column is-half">
|
58
101
|
<mip-heavy :data="setup"></mip-heavy>
|
59
|
-
<mip-mediumred v-for="(data, id) in configs" v-show="setup.flux.value === id" :data="data" medium="hey"></mip-
|
102
|
+
<mip-mediumred v-for="(data, id) in configs" v-show="setup.flux.value === id" :data="data" medium="hey"></mip-mediumred>
|
60
103
|
</div>
|
61
104
|
<div class="column is-half">
|
62
|
-
<mip-mediumgreen v-for="(data, id) in configs" v-show="setup.flux.value === id" :data="data" medium="hey"></mip-
|
105
|
+
<mip-mediumgreen v-for="(data, id) in configs" v-show="setup.flux.value === id" :data="data" medium="hey"></mip-mediumgreen>
|
63
106
|
|
64
107
|
<div v-bind:class="setup.testResultModal">
|
65
108
|
<div class="modal-background"></div>
|
66
109
|
<div class="modal-card">
|
67
110
|
<header class="modal-card-head">
|
68
|
-
<p class="modal-card-title">
|
111
|
+
<p class="modal-card-title">Test Results</p>
|
112
|
+
<div v-if="results.errorMessage"></div>
|
113
|
+
<div v-else>{{results.length}} result{{results.length == 1 ? "" : "s"}}</div>
|
69
114
|
<button class="delete" aria-label="close" v-on:click.prevent.stop="setup.testResultModal['is-active'] = false"></button>
|
70
115
|
</header>
|
71
116
|
<section class="modal-card-body">
|
72
117
|
<div v-if="results.errorMessage">{{results.errorMessage}}</div>
|
73
|
-
<div v-else>{{results.length}} result{{results.length == 1 ? "" : "s"}}</div>
|
74
118
|
<mip-heavy v-for="data in results" :data="data"></mip-heavy>
|
75
119
|
</section>
|
76
120
|
<footer class="modal-card-foot">
|
77
|
-
<button class="button is-
|
121
|
+
<button class="button is-primary" v-on:click.prevent.stop="setup.testResultModal['is-active'] = false">Done</button>
|
78
122
|
</footer>
|
79
123
|
</div>
|
80
124
|
</div>
|
@@ -336,12 +380,18 @@ module Mushy
|
|
336
380
|
fluxdata = fluxdata.data;
|
337
381
|
flowdata = flowdata.data;
|
338
382
|
|
383
|
+
fluxdata.fluxs.map(function(x) {
|
384
|
+
x['showDetails'] = false;
|
385
|
+
x['detailsTab'] = Object.getOwnPropertyNames(x.documentation)[0];
|
386
|
+
} );
|
387
|
+
|
339
388
|
var configs = {};
|
340
389
|
fluxdata.fluxs.map(function(x){
|
341
390
|
configs[x.name] = x.config;
|
342
391
|
});
|
343
392
|
|
344
393
|
var options = [''];
|
394
|
+
fluxTypesWithDetails = fluxdata.fluxs;
|
345
395
|
fluxTypes = fluxdata.fluxs.map(function(x){ return x.name });
|
346
396
|
for(var type in fluxTypes)
|
347
397
|
options.push(fluxTypes[type]);
|
@@ -390,28 +440,26 @@ module Mushy
|
|
390
440
|
"modal": true,
|
391
441
|
"is-active": false,
|
392
442
|
},
|
443
|
+
fluxTypeSelect: {
|
444
|
+
"modal": true,
|
445
|
+
"is-active": false,
|
446
|
+
},
|
393
447
|
id: { type: 'hide', value: '' },
|
394
448
|
name: { type: 'text', value: '' },
|
395
449
|
flux: { type: 'select', value: fluxdata.fluxs[0].name, options: options},
|
450
|
+
open_flux: { type: 'button', name: 'Select a Flux', foghat: 'free', medium: 'hey', color: 'is-primary',
|
451
|
+
click: function() {
|
452
|
+
Vue.set(app.setup.fluxTypeSelect, 'is-active', true);
|
453
|
+
}
|
454
|
+
},
|
396
455
|
parents: { type: 'selectmanyrecords', label: 'Receive Events From', value: '', options: flowdata.fluxs },
|
397
456
|
};
|
398
457
|
|
399
458
|
for (var key in configs)
|
400
459
|
{
|
401
|
-
configs[key].save = { type: 'button', name: 'Save Changes', foghat: 'free', color: 'is-primary', click: function(config) {
|
402
|
-
saveTheFlux({ app: app, config: config });
|
403
|
-
saveTheFlow({ setup: app.setup, flow: app.flow });
|
404
|
-
app.setup.showFlux = false;
|
405
|
-
}
|
406
|
-
};
|
407
|
-
configs[key].cancel = { type: 'button', name: 'Ignore Changes', foghat: 'free', color: 'is-warning', click: function() {
|
408
|
-
app.setup.showFlux = false;
|
409
|
-
}
|
410
|
-
};
|
411
|
-
|
412
460
|
configs[key].test_event = { type: 'json', value: '{}', default: '{}', medium: 'hey' };
|
413
461
|
|
414
|
-
configs[key].run_test = { type: 'button', name: 'Test Run This Flux', click: function(c, hey) {
|
462
|
+
configs[key].run_test = { type: 'button', name: 'Test Run This Flux', medium: 'hey', color: 'is-link', click: function(c, hey) {
|
415
463
|
var previousName = hey.run_test.name;
|
416
464
|
Vue.set(hey.run_test, 'name', 'Loading');
|
417
465
|
app.results = [];
|
@@ -420,7 +468,7 @@ module Mushy
|
|
420
468
|
the_setup.event = c.test_event;
|
421
469
|
axios.post('/run', { config: c, setup: the_setup })
|
422
470
|
.then(function(r){
|
423
|
-
app.setup.testResultModal
|
471
|
+
Vue.set(app.setup.testResultModal, 'is-active', true);
|
424
472
|
var index = 1;
|
425
473
|
for (var key in r.data.result)
|
426
474
|
{
|
@@ -436,6 +484,18 @@ module Mushy
|
|
436
484
|
Vue.set(hey.run_test, 'name', previousName);
|
437
485
|
});
|
438
486
|
} };
|
487
|
+
|
488
|
+
configs[key].save = { type: 'button', name: 'Save Changes', foghat: 'free', medium: 'hey', color: 'is-primary', click: function(config) {
|
489
|
+
saveTheFlux({ app: app, config: config });
|
490
|
+
saveTheFlow({ setup: app.setup, flow: app.flow });
|
491
|
+
app.setup.showFlux = false;
|
492
|
+
}
|
493
|
+
};
|
494
|
+
configs[key].cancel = { type: 'button', name: 'Ignore Changes', foghat: 'free', medium: 'hey', color: 'is-warning', click: function() {
|
495
|
+
app.setup.showFlux = false;
|
496
|
+
}
|
497
|
+
};
|
498
|
+
|
439
499
|
}
|
440
500
|
|
441
501
|
var loadThisFlux = function(args)
|
@@ -505,6 +565,7 @@ module Mushy
|
|
505
565
|
});
|
506
566
|
},
|
507
567
|
configs: configs,
|
568
|
+
fluxTypes: fluxTypesWithDetails,
|
508
569
|
setup: setup,
|
509
570
|
flux_name_for: function(ids, fluxes) {
|
510
571
|
var fluxs = fluxes.filter(function(x){ return ids.includes(x.id) });
|
data/lib/mushy/fluxs/bash.rb
CHANGED
@@ -19,6 +19,28 @@ module Mushy
|
|
19
19
|
value: '',
|
20
20
|
},
|
21
21
|
},
|
22
|
+
examples: {
|
23
|
+
"Successful Call" => {
|
24
|
+
description: 'This will run the ls command and return the full bash result.',
|
25
|
+
input: {
|
26
|
+
command: "ls",
|
27
|
+
},
|
28
|
+
result: {
|
29
|
+
"text": "bin\nblue_heart.png\nthe_output.txt\n",
|
30
|
+
"success": true,
|
31
|
+
"exit_code": 0
|
32
|
+
}
|
33
|
+
},
|
34
|
+
"Failed Call" => {
|
35
|
+
description: 'This is an example of what happens when the command fails.',
|
36
|
+
input: { command: 'rm file_that_does_not_exist.txt' },
|
37
|
+
result: {
|
38
|
+
"text": "",
|
39
|
+
"success": false,
|
40
|
+
"exit_code": 256
|
41
|
+
}
|
42
|
+
},
|
43
|
+
}
|
22
44
|
}
|
23
45
|
end
|
24
46
|
|
data/lib/mushy/fluxs/browser.rb
CHANGED
@@ -75,6 +75,124 @@ module Mushy
|
|
75
75
|
value: '',
|
76
76
|
},
|
77
77
|
},
|
78
|
+
examples: {
|
79
|
+
"Successful Call" => {
|
80
|
+
description: 'This will open https://www.google.com and return the result.',
|
81
|
+
config: {
|
82
|
+
url: "https://www.google.com",
|
83
|
+
},
|
84
|
+
result: {
|
85
|
+
"url": "https://www.google.com/",
|
86
|
+
"status": 200,
|
87
|
+
"title": "Google",
|
88
|
+
"cookies": [
|
89
|
+
{
|
90
|
+
"name": "1P_JAR",
|
91
|
+
"value": "2021-10-06-12",
|
92
|
+
"domain": ".google.com",
|
93
|
+
"path": "/",
|
94
|
+
"expires": 1636117150.583117,
|
95
|
+
"size": 19,
|
96
|
+
"httpOnly": false,
|
97
|
+
"secure": true,
|
98
|
+
"session": false,
|
99
|
+
"sameSite": "None",
|
100
|
+
"priority": "Medium"
|
101
|
+
},
|
102
|
+
],
|
103
|
+
"headers": {},
|
104
|
+
"time": 1.486214604,
|
105
|
+
"body": "<html itemscope=\"\" itemtype=\"http://schema.org/WebPage\" lang=\"en\">...</html>"
|
106
|
+
}
|
107
|
+
},
|
108
|
+
"Login To a Site" => {
|
109
|
+
description: 'This will open https://www.yoursitepleasethankyou.com, login using javascript, and then return the state of the browser after logging in.',
|
110
|
+
input: {
|
111
|
+
url: "https://www.yoursitepleasethankyou.com",
|
112
|
+
username: "MYUSERNAME",
|
113
|
+
password: "MYPASSWORD",
|
114
|
+
},
|
115
|
+
config: {
|
116
|
+
url: "{{url}}",
|
117
|
+
timeout: 10,
|
118
|
+
execute: "$('#username').val('{{username}}');
|
119
|
+
$('#next').click();
|
120
|
+
$('#password').val('{{password}}');
|
121
|
+
$('#login').click();"
|
122
|
+
},
|
123
|
+
result: {
|
124
|
+
"url": "https://yoursitepleasethankyou/",
|
125
|
+
"status": 200,
|
126
|
+
"title": "",
|
127
|
+
"cookies": [
|
128
|
+
{
|
129
|
+
"name": "session_id",
|
130
|
+
"value": "1jfujsx5xbnuxmsjmgjhzfpi",
|
131
|
+
"domain": ".yoursitepleasethankyou",
|
132
|
+
"path": "/",
|
133
|
+
"expires": -1,
|
134
|
+
"size": 41,
|
135
|
+
"httpOnly": true,
|
136
|
+
"secure": true,
|
137
|
+
"session": true,
|
138
|
+
"sameSite": "Lax",
|
139
|
+
"priority": "Medium"
|
140
|
+
}
|
141
|
+
],
|
142
|
+
"headers": {},
|
143
|
+
"time": 4.633920809,
|
144
|
+
"body": "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head>...</html>"
|
145
|
+
}
|
146
|
+
},
|
147
|
+
"Access a Page After Logging In" => {
|
148
|
+
description: 'This will open a page using cookies from the previous request. Note that the cookies came from another browser flux event.',
|
149
|
+
input: {
|
150
|
+
"url": "https://yoursitepleasethankyou/",
|
151
|
+
"cookies": [
|
152
|
+
{
|
153
|
+
"name": "session_id",
|
154
|
+
"value": "1jfujsx5xbnuxmsjmgjhzfpi",
|
155
|
+
"domain": ".yoursitepleasethankyou",
|
156
|
+
"path": "/",
|
157
|
+
"expires": -1,
|
158
|
+
"size": 41,
|
159
|
+
"httpOnly": true,
|
160
|
+
"secure": true,
|
161
|
+
"session": true,
|
162
|
+
"sameSite": "Lax",
|
163
|
+
"priority": "Medium"
|
164
|
+
}
|
165
|
+
],
|
166
|
+
},
|
167
|
+
config: {
|
168
|
+
url: "https://www.yoursitepleasethankyou.com/myaccount",
|
169
|
+
carry_cookies_from: "{{cookies}}"
|
170
|
+
},
|
171
|
+
result: {
|
172
|
+
"url": "https://yoursitepleasethankyou/",
|
173
|
+
"status": 200,
|
174
|
+
"title": "",
|
175
|
+
"cookies": [
|
176
|
+
{
|
177
|
+
"name": "session_id",
|
178
|
+
"value": "1jfujsx5xbnuxmsjmgjhzfpi",
|
179
|
+
"domain": ".yoursitepleasethankyou",
|
180
|
+
"path": "/",
|
181
|
+
"expires": -1,
|
182
|
+
"size": 41,
|
183
|
+
"httpOnly": true,
|
184
|
+
"secure": true,
|
185
|
+
"session": true,
|
186
|
+
"sameSite": "Lax",
|
187
|
+
"priority": "Medium"
|
188
|
+
}
|
189
|
+
],
|
190
|
+
"headers": {},
|
191
|
+
"time": 4.633920809,
|
192
|
+
"body": "<html><head></head>Your name is John Doe...</html>"
|
193
|
+
}
|
194
|
+
}
|
195
|
+
}
|
78
196
|
}
|
79
197
|
end
|
80
198
|
|
@@ -7,6 +7,7 @@ module Mushy
|
|
7
7
|
def self.details
|
8
8
|
{
|
9
9
|
name: 'BuildCsv',
|
10
|
+
title: "Build CSV",
|
10
11
|
description: 'Build a CSV.',
|
11
12
|
config: {
|
12
13
|
input_path: {
|
@@ -30,6 +31,27 @@ module Mushy
|
|
30
31
|
value: true,
|
31
32
|
},
|
32
33
|
},
|
34
|
+
examples: {
|
35
|
+
"Build a Simple CSV" => {
|
36
|
+
description: 'Converts a set of records to a CSV.',
|
37
|
+
input: {
|
38
|
+
things: [
|
39
|
+
{ name: "Apple", color:"Red" },
|
40
|
+
{ name: "Banana", color: "Yellow" },
|
41
|
+
{ name: "Pear", color: "Green" }
|
42
|
+
]
|
43
|
+
},
|
44
|
+
config: {
|
45
|
+
input_path: "things",
|
46
|
+
output_path: "records",
|
47
|
+
headers: { name: "Name", color: "Color" },
|
48
|
+
header_row: true
|
49
|
+
},
|
50
|
+
result: {
|
51
|
+
records: "Name,Color\nApple,Red\nBanana,Yellow\nPear,Green\n"
|
52
|
+
}
|
53
|
+
},
|
54
|
+
}
|
33
55
|
}
|
34
56
|
end
|
35
57
|
|
data/lib/mushy/fluxs/cli.rb
CHANGED
@@ -5,9 +5,20 @@ module Mushy
|
|
5
5
|
def self.details
|
6
6
|
{
|
7
7
|
name: 'Cli',
|
8
|
+
title: 'Command Line Interface',
|
8
9
|
description: 'Accept CLI arguments from the run command.',
|
9
10
|
config: {
|
10
11
|
},
|
12
|
+
examples: {
|
13
|
+
"Calling From The Command Line" => {
|
14
|
+
description: 'Calling the CLI with command-line arguments.',
|
15
|
+
input: "mushy start file first:John last:Doe",
|
16
|
+
result: {
|
17
|
+
"first": "John",
|
18
|
+
"last": "Doe"
|
19
|
+
}
|
20
|
+
},
|
21
|
+
}
|
11
22
|
}
|
12
23
|
end
|
13
24
|
|
data/lib/mushy/fluxs/document.rb
CHANGED
@@ -13,6 +13,20 @@ module Mushy
|
|
13
13
|
value: '',
|
14
14
|
},
|
15
15
|
},
|
16
|
+
examples: {
|
17
|
+
"Example" => {
|
18
|
+
description: 'Using this Flux to build a document',
|
19
|
+
input: {
|
20
|
+
people: [ { name: "John" }, { name: "Jane" } ]
|
21
|
+
},
|
22
|
+
config: {
|
23
|
+
document: '{% for person in people %} {{ person.name }} {% endfor %}'
|
24
|
+
},
|
25
|
+
result: {
|
26
|
+
document: ' John Jane ',
|
27
|
+
}
|
28
|
+
},
|
29
|
+
}
|
16
30
|
}
|
17
31
|
end
|
18
32
|
|
data/lib/mushy/fluxs/filter.rb
CHANGED
@@ -21,13 +21,27 @@ module Mushy
|
|
21
21
|
type: 'keyvalue',
|
22
22
|
value: {},
|
23
23
|
},
|
24
|
+
contains: {
|
25
|
+
description: 'Provide key/value pairs that must be contained.',
|
26
|
+
shrink: true,
|
27
|
+
label: 'Contains',
|
28
|
+
type: 'keyvalue',
|
29
|
+
value: {},
|
30
|
+
},
|
31
|
+
notcontains: {
|
32
|
+
description: 'Provide key/value pairs that must NOT be contained.',
|
33
|
+
shrink: true,
|
34
|
+
label: 'Not Contains',
|
35
|
+
type: 'keyvalue',
|
36
|
+
value: {},
|
37
|
+
},
|
24
38
|
},
|
25
39
|
}
|
26
40
|
end
|
27
41
|
|
28
42
|
def process event, config
|
29
43
|
|
30
|
-
differences = [:equal, :notequal]
|
44
|
+
differences = [:equal, :notequal, :contains, :notcontains]
|
31
45
|
.select { |x| config[x].is_a? Hash }
|
32
46
|
.map { |x| config[x].map { |k, v| { m: x, k: k, v1: v } } }
|
33
47
|
.flatten
|
@@ -42,7 +56,7 @@ module Mushy
|
|
42
56
|
def equal a, b
|
43
57
|
[a, b]
|
44
58
|
.map { |x| numeric?(x) ? x.to_f : x }
|
45
|
-
.map { |x| x
|
59
|
+
.map { |x| nice_string x }
|
46
60
|
.group_by { |x| x }
|
47
61
|
.count == 1
|
48
62
|
end
|
@@ -51,10 +65,23 @@ module Mushy
|
|
51
65
|
equal(a, b) == false
|
52
66
|
end
|
53
67
|
|
68
|
+
def contains a, b
|
69
|
+
return false unless b
|
70
|
+
nice_string(b).include? a.downcase
|
71
|
+
end
|
72
|
+
|
73
|
+
def notcontains a, b
|
74
|
+
contains(a, b) == false
|
75
|
+
end
|
76
|
+
|
54
77
|
def numeric? value
|
55
78
|
Float(value) != nil rescue false
|
56
79
|
end
|
57
80
|
|
81
|
+
def nice_string value
|
82
|
+
value.to_s.strip.downcase
|
83
|
+
end
|
84
|
+
|
58
85
|
end
|
59
86
|
|
60
87
|
end
|
data/lib/mushy/fluxs/ls.rb
CHANGED
@@ -20,6 +20,114 @@ module Mushy
|
|
20
20
|
shrink: true,
|
21
21
|
value: '',
|
22
22
|
}
|
23
|
+
end.tap do |c|
|
24
|
+
c[:examples] = {
|
25
|
+
"Run In A Directory" => {
|
26
|
+
description: 'This will run the ls command in the specified directory.',
|
27
|
+
config: {
|
28
|
+
directory: '/home/pi/Desktop/mushy'
|
29
|
+
},
|
30
|
+
result: [{
|
31
|
+
inode: "416921",
|
32
|
+
hard_links: 1,
|
33
|
+
owner: "pi",
|
34
|
+
group: "pi",
|
35
|
+
size: 1270,
|
36
|
+
date: {
|
37
|
+
year: 2021,
|
38
|
+
month: 10,
|
39
|
+
day: 1,
|
40
|
+
hour: 10,
|
41
|
+
minute: 43,
|
42
|
+
second: 35,
|
43
|
+
nanosecond: 664409766,
|
44
|
+
utc_offset: -18000,
|
45
|
+
weekday: 5,
|
46
|
+
day_of_month: 1,
|
47
|
+
day_of_year: 274,
|
48
|
+
string: "2021-10-01 10:43:35 -0500",
|
49
|
+
epoch_integer: 1633103015,
|
50
|
+
epoch_float: 1633103015.6644099,
|
51
|
+
seconds_ago: 454725.436212074
|
52
|
+
},
|
53
|
+
name: "mushy.gemspec",
|
54
|
+
type: "-",
|
55
|
+
owner_permission: "rw-",
|
56
|
+
group_permission: "r--",
|
57
|
+
other_permission: "r--",
|
58
|
+
directory: "/home/pi/Desktop/mushy",
|
59
|
+
path: "/home/pi/Desktop/mushy/mushy.gemspec"
|
60
|
+
},
|
61
|
+
{
|
62
|
+
inode: "403479",
|
63
|
+
hard_links: 3,
|
64
|
+
owner: "pi",
|
65
|
+
group: "pi",
|
66
|
+
size: 4096,
|
67
|
+
date: {
|
68
|
+
year: 2021,
|
69
|
+
month: 3,
|
70
|
+
day: 18,
|
71
|
+
hour: 8,
|
72
|
+
minute: 58,
|
73
|
+
second: 51,
|
74
|
+
nanosecond: 149096220,
|
75
|
+
utc_offset: -18000,
|
76
|
+
weekday: 4,
|
77
|
+
day_of_month: 18,
|
78
|
+
day_of_year: 77,
|
79
|
+
string: "2021-03-18 08:58:51 -0500",
|
80
|
+
epoch_integer: 1616075931,
|
81
|
+
epoch_float: 1616075931.1490963,
|
82
|
+
seconds_ago: 17482042.0544623
|
83
|
+
},
|
84
|
+
name: "test",
|
85
|
+
type: "d",
|
86
|
+
owner_permission: "rwx",
|
87
|
+
group_permission: "r-x",
|
88
|
+
other_permission: "r-x",
|
89
|
+
directory: "test"
|
90
|
+
}
|
91
|
+
]
|
92
|
+
},
|
93
|
+
"Run For a Specific File" => {
|
94
|
+
description: 'This will run the ls command in the specified directory.',
|
95
|
+
config: {
|
96
|
+
path: 'mushy.gemspec'
|
97
|
+
},
|
98
|
+
result: {
|
99
|
+
inode: "416921",
|
100
|
+
hard_links: 1,
|
101
|
+
owner: "pi",
|
102
|
+
group: "pi",
|
103
|
+
size: 1270,
|
104
|
+
date: {
|
105
|
+
year: 2021,
|
106
|
+
month: 10,
|
107
|
+
day: 1,
|
108
|
+
hour: 10,
|
109
|
+
minute: 43,
|
110
|
+
second: 35,
|
111
|
+
nanosecond: 664409766,
|
112
|
+
utc_offset: -18000,
|
113
|
+
weekday: 5,
|
114
|
+
day_of_month: 1,
|
115
|
+
day_of_year: 274,
|
116
|
+
string: "2021-10-01 10:43:35 -0500",
|
117
|
+
epoch_integer: 1633103015,
|
118
|
+
epoch_float: 1633103015.6644099,
|
119
|
+
seconds_ago: 454725.436212074
|
120
|
+
},
|
121
|
+
name: "mushy.gemspec",
|
122
|
+
type: "-",
|
123
|
+
owner_permission: "rw-",
|
124
|
+
group_permission: "r--",
|
125
|
+
other_permission: "r--",
|
126
|
+
directory: "/home/pi/Desktop/mushy",
|
127
|
+
path: "/home/pi/Desktop/mushy/mushy.gemspec"
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
23
131
|
end
|
24
132
|
end
|
25
133
|
|
@@ -129,6 +237,8 @@ module Mushy
|
|
129
237
|
name_segments = result[:name].split "\/"
|
130
238
|
result[:name] = name_segments.pop
|
131
239
|
result[:directory] = name_segments.join "\/"
|
240
|
+
elsif result[:type] == 'd'
|
241
|
+
result[:directory] = result[:name]
|
132
242
|
else
|
133
243
|
result[:path] = File.join result[:directory], result[:name]
|
134
244
|
end
|
data/lib/mushy/fluxs/pwd.rb
CHANGED
@@ -7,7 +7,46 @@ module Mushy
|
|
7
7
|
name: 'Pwd',
|
8
8
|
description: 'Run the "pwd" command.',
|
9
9
|
config: Mushy::Bash.details[:config].tap { |c| c.delete :command },
|
10
|
-
}
|
10
|
+
}.tap do |c|
|
11
|
+
c[:examples] = {
|
12
|
+
"Example" => {
|
13
|
+
description: 'This will run the pwd command and return the directory information.',
|
14
|
+
result: {
|
15
|
+
pwd: {
|
16
|
+
inode: "403091",
|
17
|
+
hard_links: 5,
|
18
|
+
owner: "pi",
|
19
|
+
group: "pi",
|
20
|
+
size: 4095,
|
21
|
+
date: {
|
22
|
+
year: 2020,
|
23
|
+
month: 9,
|
24
|
+
day: 5,
|
25
|
+
hour: 10,
|
26
|
+
minute: 43,
|
27
|
+
second: 36,
|
28
|
+
nanosecond: 325720074,
|
29
|
+
utc_offset: -18001,
|
30
|
+
weekday: 2,
|
31
|
+
day_of_month: 5,
|
32
|
+
day_of_year: 278,
|
33
|
+
string: "2020-10-06 11:44:37 -0500",
|
34
|
+
epoch_integer: 1633538676,
|
35
|
+
epoch_float: 1633538676.32572,
|
36
|
+
seconds_ago: 17558.38995246
|
37
|
+
},
|
38
|
+
name: "mushy",
|
39
|
+
type: "d",
|
40
|
+
owner_permission: "rwx",
|
41
|
+
group_permission: "r-x",
|
42
|
+
other_permission: "r-x",
|
43
|
+
directory: "/home/pi/Desktop",
|
44
|
+
path: "/home/pi/Desktop/mushy"
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
end
|
11
50
|
end
|
12
51
|
|
13
52
|
def process event, config
|
@@ -7,20 +7,33 @@ module Mushy
|
|
7
7
|
def self.details
|
8
8
|
{
|
9
9
|
name: 'ReadJson',
|
10
|
+
title: 'Deserialize JSON',
|
10
11
|
description: 'Read JSON and output it as an event.',
|
11
12
|
config: {
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
key: {
|
14
|
+
description: 'The JSON contents that will be returned as an event.',
|
15
|
+
type: 'text',
|
16
|
+
value: 'json',
|
17
|
+
},
|
17
18
|
},
|
19
|
+
examples: {
|
20
|
+
"Example" => {
|
21
|
+
description: 'Using this Flux to deserialize a JSON string.',
|
22
|
+
input: {
|
23
|
+
orange: "{\"people\":[{\"name\":\"John\"},{\"name\":\"Jane\"}]}"
|
24
|
+
},
|
25
|
+
config: {
|
26
|
+
key: 'orange'
|
27
|
+
},
|
28
|
+
result: { people: [ { name: "John" }, { name: "Jane" } ] }
|
29
|
+
},
|
30
|
+
}
|
18
31
|
}
|
19
32
|
end
|
20
33
|
|
21
34
|
def process event, config
|
22
|
-
return nil unless config[:
|
23
|
-
JSON.parse config[:
|
35
|
+
return nil unless event[config[:key]].to_s != ''
|
36
|
+
JSON.parse event[config[:key]]
|
24
37
|
end
|
25
38
|
|
26
39
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Mushy
|
2
|
+
|
3
|
+
class Stdout < Flux
|
4
|
+
|
5
|
+
def self.details
|
6
|
+
{
|
7
|
+
name: 'Stdout',
|
8
|
+
description: 'Standard Out',
|
9
|
+
config: {
|
10
|
+
message: {
|
11
|
+
description: 'The message to display.',
|
12
|
+
type: 'text',
|
13
|
+
value: '{{message}}',
|
14
|
+
},
|
15
|
+
},
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def process event, config
|
20
|
+
puts config[:message]
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -7,6 +7,7 @@ module Mushy
|
|
7
7
|
def self.details
|
8
8
|
{
|
9
9
|
name: 'WriteJson',
|
10
|
+
title: 'Serialize as JSON',
|
10
11
|
description: 'Write the incoming event as JSON.',
|
11
12
|
config: {
|
12
13
|
key: {
|
@@ -15,6 +16,20 @@ module Mushy
|
|
15
16
|
value: 'json',
|
16
17
|
},
|
17
18
|
},
|
19
|
+
examples: {
|
20
|
+
"Example" => {
|
21
|
+
description: 'Using this Flux to convert input to a JSON string.',
|
22
|
+
input: {
|
23
|
+
people: [ { name: "John" }, { name: "Jane" } ]
|
24
|
+
},
|
25
|
+
config: {
|
26
|
+
key: 'apple'
|
27
|
+
},
|
28
|
+
result: {
|
29
|
+
apple: "{\"people\":[{\"name\":\"John\"},{\"name\":\"Jane\"}]}"
|
30
|
+
}
|
31
|
+
},
|
32
|
+
}
|
18
33
|
}
|
19
34
|
end
|
20
35
|
|
data/mushy.gemspec
CHANGED
@@ -4,7 +4,7 @@ require 'mushy/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'mushy'
|
7
|
-
s.version = '0.
|
7
|
+
s.version = '0.16.0'
|
8
8
|
s.date = '2020-11-23'
|
9
9
|
s.summary = 'Process streams of work using common modules.'
|
10
10
|
s.description = 'This tool assists in the creation and processing of workflows.'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mushy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darren Cauthon
|
@@ -177,6 +177,7 @@ files:
|
|
177
177
|
- lib/mushy/builder/axios.rb
|
178
178
|
- lib/mushy/builder/bulma.rb
|
179
179
|
- lib/mushy/builder/dark.rb
|
180
|
+
- lib/mushy/builder/documentation.rb
|
180
181
|
- lib/mushy/builder/index.rb
|
181
182
|
- lib/mushy/builder/vue.rb
|
182
183
|
- lib/mushy/date_parts.rb
|
@@ -210,6 +211,7 @@ files:
|
|
210
211
|
- lib/mushy/fluxs/sense_hat_led_matrix.rb
|
211
212
|
- lib/mushy/fluxs/simple_python_program.rb
|
212
213
|
- lib/mushy/fluxs/smtp.rb
|
214
|
+
- lib/mushy/fluxs/stdout.rb
|
213
215
|
- lib/mushy/fluxs/times.rb
|
214
216
|
- lib/mushy/fluxs/write_file.rb
|
215
217
|
- lib/mushy/fluxs/write_json.rb
|