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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a4f879064424ed8888d44a02b7223d4b07e1afa24780754933b85951acf3468
4
- data.tar.gz: 9496d922bf28efe4c15787f3d751a4ce34b4daae8870416f409cc96232d05556
3
+ metadata.gz: 9f18a4ff7bf18c88f36a66481bd9fd56e7511ca276f5312b2f4bf2862e8d5aa5
4
+ data.tar.gz: 2d40205cd64f986cc7234c847173ed4dbf95f0ba2f3ccf5d81e71290fb23d6c4
5
5
  SHA512:
6
- metadata.gz: e7f87ad8e48755047c36fdf5f6729e067840db6cfc46fbd1695a78f068412a882249d06aeb3124bb57887778832e668e5cf386145270e184b97f50cec99668e7
7
- data.tar.gz: f79420c48218b67eff39eb966d5a1414723cc6d74dd5678c36ee6fde3c6ec3a25e8ec351613f3c1802c51db19faebe077db83461220e196f53fe342495499eef
6
+ metadata.gz: 183e5fe0556b562c1747d1005dc238ca034ca1745e0505a763e394d008a4315de63c65f53cab0435cf45a219e54e68bf705095218ab85e572d04e658b0c6d25b
7
+ data.tar.gz: d856b27867d3946ff2ca840ae1eff9c96b07b7a06757bde41d6475351be68a36b97d9395324c4e3ee0e198ec3b5cd4352bffb5637e2f76a78663c5da08565245
@@ -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
- data['fluxs']
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
- data['fluxs']
96
+ fluxs
87
97
  .select { |x| x['parent'] }
88
98
  .each { |x| x.delete 'parent' }
89
- data['fluxs']
99
+ fluxs
90
100
  .select { |x| x['parents'] }
91
101
  .each { |x| x['parents'] = x['parents'].select { |y| y } }
92
- data
93
- rescue
94
- { fluxs: [] }
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
@@ -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-medium>
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-medium>
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">Modal title</p>
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-success">GO</button>
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["is-active"] = true;
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) });
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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.to_s.strip.downcase }
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
@@ -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
@@ -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
- json: {
13
- description: 'The JSON contents that will be returned as an event.',
14
- type: 'text',
15
- value: 'json',
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[:json].to_s != ''
23
- JSON.parse config[:json]
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.14.2'
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.14.2
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