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 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