mushy 0.14.2 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|