mushy 0.0.4 → 0.1.3
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/bin/mushy +11 -9
- data/lib/mushy/builder/api.rb +17 -8
- data/lib/mushy/builder/index.rb +142 -85
- data/lib/mushy/flow.rb +3 -1
- data/lib/mushy/flux.rb +1 -0
- data/lib/mushy/fluxs/browser.rb +27 -2
- data/lib/mushy/fluxs/cli.rb +20 -0
- data/lib/mushy/fluxs/filter.rb +23 -0
- data/mushy.gemspec +4 -2
- metadata +30 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f516df95fc3919dd7d02ffe32228fd96364c06a56595ae8a7e986d406abc3af
|
4
|
+
data.tar.gz: c2dc07c4f8ad462134d674aeb4006eeabff5a07abee0d20d1ec5ff89312f80e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2e8a4bc112300daeb8089a455c10ef7c6842524a0a8dc3a00aa0c8715ecee836eff17f89c461ead76ae4ba716c56e49e436be57e8f163de3a57d8fe8249e816
|
7
|
+
data.tar.gz: ef23272c88796185deb60fd11ad9a326b3dd4a84d2df7aa86830727e72408811eda47a2fb13e59cb481b6a0fb0ad505a7ee4c606cf50b6478e7dc0d7303c0371
|
data/bin/mushy
CHANGED
@@ -3,18 +3,20 @@
|
|
3
3
|
require 'thor'
|
4
4
|
require 'mushy'
|
5
5
|
|
6
|
-
class
|
6
|
+
class MushyCLI < Thor
|
7
|
+
|
8
|
+
argument :file
|
9
|
+
argument :values, optional: true, type: :hash
|
7
10
|
|
8
11
|
desc "start FILE", "Run this workflow file."
|
9
|
-
def start
|
10
|
-
|
11
|
-
puts content
|
12
|
+
def start
|
13
|
+
Mushy::Builder::Api.start file, values
|
12
14
|
end
|
13
15
|
|
14
16
|
desc "build FILE", 'Build a flow.'
|
15
|
-
def build
|
17
|
+
def build
|
16
18
|
|
17
|
-
|
19
|
+
MushyCLI.set_special( { method: 'build', file: file } )
|
18
20
|
|
19
21
|
end
|
20
22
|
|
@@ -28,14 +30,14 @@ class RailsCLI < Thor
|
|
28
30
|
|
29
31
|
end
|
30
32
|
|
31
|
-
|
33
|
+
MushyCLI.start(ARGV)
|
32
34
|
|
33
|
-
exit unless
|
35
|
+
exit unless MushyCLI.get_special
|
34
36
|
|
35
37
|
require 'sinatra'
|
36
38
|
enable :run
|
37
39
|
|
38
|
-
the_file =
|
40
|
+
the_file = MushyCLI.get_special[:file]
|
39
41
|
|
40
42
|
get '/' do
|
41
43
|
Mushy::Builder::Index.file
|
data/lib/mushy/builder/api.rb
CHANGED
@@ -28,6 +28,15 @@ module Mushy
|
|
28
28
|
|
29
29
|
end
|
30
30
|
|
31
|
+
def self.start file, event
|
32
|
+
file = "#{file}.json" unless file.downcase.end_with?('.json')
|
33
|
+
flow = File.open(file).read
|
34
|
+
flow = Mushy::Flow.parse flow
|
35
|
+
flux = flow.fluxs.select { |x| x.type == 'Cli' }.first
|
36
|
+
|
37
|
+
Mushy::Runner.new.start event, flux, flow
|
38
|
+
end
|
39
|
+
|
31
40
|
def self.get_flow file
|
32
41
|
puts "trying to get: #{file}"
|
33
42
|
file = "#{file}.json" unless file.downcase.end_with?('.json')
|
@@ -40,14 +49,14 @@ module Mushy
|
|
40
49
|
{
|
41
50
|
fluxs: Mushy::Flux.all.select { |x| x.respond_to? :details }.map do |flux|
|
42
51
|
details = flux.details
|
43
|
-
details[:config][:incoming_split] = { type: 'text', description: 'Split an incoming event into multiple events by this key, an each event will be processed independently.', default: '' }
|
44
|
-
details[:config][:outgoing_split] = { type: 'text', description: 'Split an outgoing event into multiple events by this key.', default: '' }
|
45
|
-
details[:config][:merge] = { type: 'text', description: 'A comma-delimited list of fields from the event to carry through. Use * to merge all fields.', default: '' }
|
46
|
-
details[:config][:group] = { type: 'text', description: 'Group events by a field, which is stored in a key. The format is group_by|group_key.', default: '' }
|
47
|
-
details[:config][:limit] = { type: 'integer', description: 'Limit the number of events to this number.', default: '' }
|
48
|
-
details[:config][:join] = { type: 'text', description: 'Join all of the events from this flux into one event, under this name.', default: '' }
|
49
|
-
details[:config][:sort] = { type: 'text', description: 'Sort by this key.', default: '' }
|
50
|
-
details[:config][:model] = { type: 'keyvalue', description: 'Reshape the outgoing events.', value: {}, default: {} }
|
52
|
+
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: '' }
|
53
|
+
details[:config][:outgoing_split] = { type: 'text', shrink: true, description: 'Split an outgoing event into multiple events by this key.', default: '' }
|
54
|
+
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: '' }
|
55
|
+
details[:config][:group] = { type: 'text', shrink: true, description: 'Group events by a field, which is stored in a key. The format is group_by|group_key.', default: '' }
|
56
|
+
details[:config][:limit] = { type: 'integer', shrink: true, description: 'Limit the number of events to this number.', default: '' }
|
57
|
+
details[:config][:join] = { type: 'text', shrink: true, description: 'Join all of the events from this flux into one event, under this name.', default: '' }
|
58
|
+
details[:config][:sort] = { type: 'text', shrink: true, description: 'Sort by this key.', default: '' }
|
59
|
+
details[:config][:model] = { type: 'keyvalue', shrink: true, description: 'Reshape the outgoing events.', value: {}, default: {} }
|
51
60
|
|
52
61
|
details[:config]
|
53
62
|
.select { |_, v| v[:type] == 'keyvalue' }
|
data/lib/mushy/builder/index.rb
CHANGED
@@ -12,19 +12,28 @@ module Mushy
|
|
12
12
|
</head>
|
13
13
|
<body>
|
14
14
|
<div id="app">
|
15
|
-
<table>
|
15
|
+
<table v-if="setup.showFlux == false">
|
16
|
+
<tr>
|
17
|
+
<th>Name</th>
|
18
|
+
<th>Receives Events From</th>
|
19
|
+
<th>Actions</th>
|
20
|
+
</tr>
|
16
21
|
<tr v-for="flux in flow.fluxs">
|
17
22
|
<td>{{flux.name}}</td>
|
18
|
-
<td>{{flux.
|
19
|
-
<td
|
23
|
+
<td>{{flux_name_for(flux.parent, flow.fluxs)}}</td>
|
24
|
+
<td>
|
25
|
+
<button v-on:click.prevent.stop="editFlux({ flux: flux, setup: setup, configs: configs })">Edit</button>
|
26
|
+
<button v-on:click.prevent.stop="deleteFlux({ flux: flux, flow: flow })">Delete</button>
|
27
|
+
</td>
|
20
28
|
</tr>
|
21
29
|
</table>
|
22
|
-
<
|
23
|
-
<
|
24
|
-
<
|
30
|
+
<button v-if="setup.showFlux == false" v-on:click.prevent.stop="startNew({ setup: setup, configs: configs })">Start a New Flux</button>
|
31
|
+
<button v-if="setup.showFlux == false" v-on:click.prevent.stop="saveFlow({ setup: setup, flow: flow })">Save This Flow</button>
|
32
|
+
<button v-if="setup.showFlux" v-on:click.prevent.stop="setup.showFlux = false">< Go Back To List</button>
|
33
|
+
<div v-if="setup.showFlux">
|
25
34
|
<mip-heavy :data="setup"></mip-heavy>
|
26
35
|
<mip-heavy v-for="(data, id) in configs" v-show="setup.flux.value === id" :data="data"></mip-heavy>
|
27
|
-
<div v-if="results.
|
36
|
+
<div v-if="results.errorMessage">{{results.errorMessage}}</div>
|
28
37
|
<div v-else>{{results.length}} result{{results.length == 1 ? "" : "s"}}</div>
|
29
38
|
<mip-heavy v-for="data in results" :data="data"></mip-heavy>
|
30
39
|
</div>
|
@@ -48,28 +57,48 @@ module Mushy
|
|
48
57
|
|
49
58
|
var components = {
|
50
59
|
label: {
|
51
|
-
props: ['label', 'description'],
|
52
|
-
template: '<label :for="id" v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description">({{description}})</i></label>'
|
60
|
+
props: ['label', 'description', 'hide_description'],
|
61
|
+
template: '<label :for="id" v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></label>'
|
62
|
+
},
|
63
|
+
h1: {
|
64
|
+
props: ['label', 'description', 'hide_description'],
|
65
|
+
template: '<h1 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h1>'
|
66
|
+
},
|
67
|
+
h2: {
|
68
|
+
props: ['label', 'description', 'hide_description'],
|
69
|
+
template: '<h2 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h2>'
|
70
|
+
},
|
71
|
+
h3: {
|
72
|
+
props: ['label', 'description', 'hide_description'],
|
73
|
+
template: '<h3 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h3>'
|
74
|
+
},
|
75
|
+
h4: {
|
76
|
+
props: ['label', 'description', 'hide_description'],
|
77
|
+
template: '<h4 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h4>'
|
53
78
|
},
|
54
79
|
text: {
|
55
|
-
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
|
56
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><input type="text" :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
|
80
|
+
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
|
81
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><input type="text" :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
|
82
|
+
},
|
83
|
+
hide: {
|
84
|
+
props: ['label', 'description'],
|
85
|
+
template: '<mip-label :id="id" :label="label" :description="description" v-if="false"></mip-label>'
|
57
86
|
},
|
58
87
|
integer: {
|
59
|
-
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
|
60
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><input type="text" :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
|
88
|
+
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
|
89
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><input type="text" :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
|
61
90
|
},
|
62
91
|
email: {
|
63
|
-
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
|
64
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><input type="email" :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
|
92
|
+
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
|
93
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><input type="email" :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
|
65
94
|
},
|
66
95
|
textarea: {
|
67
|
-
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
|
68
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><textarea :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
|
96
|
+
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
|
97
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><textarea :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
|
69
98
|
},
|
70
99
|
json: {
|
71
|
-
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
|
72
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label
|
100
|
+
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
|
101
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><textarea :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
|
73
102
|
},
|
74
103
|
jsonview: {
|
75
104
|
data: function() {
|
@@ -80,19 +109,23 @@ module Mushy
|
|
80
109
|
};
|
81
110
|
},
|
82
111
|
props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'view'],
|
83
|
-
template: '<div><mip-
|
112
|
+
template: '<div><mip-h4 :id="id" :label="label" :description="description"></mip-h4> <pre><code>{{show(view, value)}}</code></pre><button :disabled="view==\\'beautiful\\'" v-on:click.prevent.stop="view=toggle(view)">{{(view == \\'beautiful\\' ? \\'View Smaller\\' : \\'View Pretty\\')}}</button><button :disabled="view!=\\'beautiful\\'" v-on:click.prevent.stop="view=toggle(view)">View Smaller</button><button v-on:click.prevent.stop="copy(view, value)">Copy</button></div>'
|
84
113
|
},
|
85
114
|
radio: {
|
86
|
-
props: ['label', 'value', 'options', 'description'],
|
87
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><div v-for="option in options"><input type="radio" :name="id" v-bind:value="option" v-on:input="$emit(\\'update:value\\', $event.target.value)" :checked="value == option"> <label for="option">{{option}}</label></div></div>'
|
115
|
+
props: ['label', 'value', 'options', 'description', 'shrink'],
|
116
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><div v-for="option in options"><input type="radio" :name="id" v-bind:value="option" v-if="value || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)" :checked="value == option"> <label for="option">{{option}}</label></div></div>'
|
88
117
|
},
|
89
118
|
select: {
|
90
|
-
props: ['label', 'value', 'options', 'description'],
|
91
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><select :name="id" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
|
119
|
+
props: ['label', 'value', 'options', 'description', 'shrink'],
|
120
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><select :name="id" v-if="value || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
|
121
|
+
},
|
122
|
+
selectrecord: {
|
123
|
+
props: ['label', 'value', 'options', 'description', 'shrink'],
|
124
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><select :name="id" v-if="value || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option.id" :selected="value == option.id">{{option.name}}</option></select></div>'
|
92
125
|
},
|
93
126
|
boolean: {
|
94
|
-
props: ['label', 'value', 'options', 'description'],
|
95
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><select :name="id" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in [true, false]" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
|
127
|
+
props: ['label', 'value', 'options', 'description', 'shrink'],
|
128
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><select :name="id" v-if="(value != undefined && value != null && value != \\'\\') || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in [true, false]" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
|
96
129
|
},
|
97
130
|
table: {
|
98
131
|
props: ['value', 'description'],
|
@@ -113,12 +146,13 @@ module Mushy
|
|
113
146
|
}
|
114
147
|
};
|
115
148
|
},
|
116
|
-
props: ['value', 'editors', 'label', 'description'],
|
117
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><table><tr><th v-for="(d, i) in value[0]">{{' + fancyName('i') + '}}</th></tr><tr v-for="(v, z) in value"><td v-for="(d, i) in v">{{d}}</td><td><a href="#" v-on:click.prevent.stop="removeRecord(v, value, z)">[x]</a></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><a href="#" v-on:click.prevent.stop="addRecord(editors, value)">[Add]</a></td></tr></table></div>'
|
149
|
+
props: ['value', 'editors', 'label', 'description', 'shrink'],
|
150
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && value.length == 0">[^]</a><table v-if="value.length > 0 || !shrink"><tr><th v-for="(d, i) in value[0]">{{' + fancyName('i') + '}}</th></tr><tr v-for="(v, z) in value"><td v-for="(d, i) in v">{{d}}</td><td><a href="#" v-on:click.prevent.stop="removeRecord(v, value, z)">[x]</a></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><a href="#" v-on:click.prevent.stop="addRecord(editors, value)">[Add]</a></td></tr></table></div>'
|
118
151
|
},
|
119
152
|
keyvalue: {
|
120
153
|
data: function() {
|
121
154
|
return {
|
155
|
+
actionText: function(value, others) { found = false; for(var i in others){ if (i == value) found = true; } return found ? 'Replace' : 'Add'; },
|
122
156
|
removeRecord: function(data, key) { Vue.delete(data, key) },
|
123
157
|
addRecord: function(editors, data) {
|
124
158
|
Vue.set(data, editors[0].field.value, editors[1].field.value)
|
@@ -127,12 +161,12 @@ module Mushy
|
|
127
161
|
}
|
128
162
|
};
|
129
163
|
},
|
130
|
-
props: ['value', 'label', 'editors', 'description'],
|
131
|
-
template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><table><tr v-for="(v, k) in value"><td>{{k}}</td><td>{{v}}</td><td><
|
164
|
+
props: ['value', 'label', 'editors', 'description', 'shrink'],
|
165
|
+
template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink">[^]</a><table v-if="JSON.stringify(value) != \\'{}\\' || !shrink"><tr v-for="(v, k) in value"><td>{{k}}</td><td>{{v}}</td><td><button v-on:click.prevent.stop="removeRecord(value, k)">Remove {{k}}</button></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><button v-on:click.prevent.stop="addRecord(editors, value)" v-show="editors[0].field.value">{{actionText(editors[0].field.value, value)}} {{editors[0].field.value}}</button></td></tr></table></div>'
|
132
166
|
},
|
133
167
|
button: {
|
134
|
-
props: ['click', 'description'],
|
135
|
-
template: '<button v-on:click.prevent.stop="click(pull(this))">{{id}}</button>'
|
168
|
+
props: ['click', 'description', 'name'],
|
169
|
+
template: '<button v-on:click.prevent.stop="click(pull(this), thisComponent())">{{name || id}}</button>'
|
136
170
|
}
|
137
171
|
};
|
138
172
|
|
@@ -152,6 +186,7 @@ module Mushy
|
|
152
186
|
return {
|
153
187
|
console: console,
|
154
188
|
pull: function(x) { return thingToData(foundIt.data); },
|
189
|
+
thisComponent: function() { return foundIt.data; },
|
155
190
|
}
|
156
191
|
},
|
157
192
|
props: props,
|
@@ -184,32 +219,6 @@ module Mushy
|
|
184
219
|
template: '<div><mip-thing v-for="(d, id) in data" :data="d" :id="id"></mip-thing></div>',
|
185
220
|
});
|
186
221
|
|
187
|
-
var sample = {
|
188
|
-
email: { type: 'email', value: 'darren@cauthon.com' },
|
189
|
-
first_name: { type: 'text', value: 'Darren' },
|
190
|
-
description: { type: 'textarea', value: 'more data' },
|
191
|
-
size: { type: 'select', value: 'medium', options: ['small', 'medium', 'large']},
|
192
|
-
heynow: { type: 'keyvalue',
|
193
|
-
value: {
|
194
|
-
first_name: 'John',
|
195
|
-
last_name: 'Doe',
|
196
|
-
},
|
197
|
-
editors: [
|
198
|
-
{ id: 'new_key', target: 'key', field: { type: 'text', value: '', default: '' } },
|
199
|
-
{ id: 'new_value', target: 'value', field: { type: 'text', value: '', default: '' } }
|
200
|
-
] },
|
201
|
-
past: { type: 'editgrid',
|
202
|
-
value: [
|
203
|
-
{ name: 'Godzilla', quantity: 1 },
|
204
|
-
{ name: 'Mothra', quantity: 2 },
|
205
|
-
],
|
206
|
-
editors: [
|
207
|
-
{ id: 'new_name', target: 'name', field: { type: 'text', value: '', default: '' } },
|
208
|
-
{ id: 'new_quantity', target: 'quantity', field: { type: 'select', value: '1', options: [1, 2, 3], default: 1 } }
|
209
|
-
] },
|
210
|
-
super_action: { type: 'button', click: function(x) { console.log(x) } },
|
211
|
-
};
|
212
|
-
|
213
222
|
var app = null;
|
214
223
|
|
215
224
|
axios.get('/fluxs')
|
@@ -232,27 +241,19 @@ module Mushy
|
|
232
241
|
options.push(fluxTypes[type]);
|
233
242
|
|
234
243
|
var setup = {
|
235
|
-
|
236
|
-
id: { type: '
|
244
|
+
showFlux: false,
|
245
|
+
id: { type: 'hide', value: '' },
|
237
246
|
name: { type: 'text', value: '' },
|
238
247
|
flux: { type: 'select', value: fluxdata.fluxs[0].name, options: options},
|
239
|
-
parent: { type: '
|
248
|
+
parent: { type: 'selectrecord', label: 'Receive Events From', value: '', options: flowdata.fluxs },
|
240
249
|
};
|
241
250
|
|
242
251
|
for (var key in configs)
|
243
252
|
{
|
244
|
-
configs[key].
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
.then(function(r){
|
249
|
-
Vue.set(app.results, 'loading', false);
|
250
|
-
for (var key in r.data.result)
|
251
|
-
app.results.push({darren: { type:'jsonview', value: r.data.result[key], view: 'thin' }});
|
252
|
-
});
|
253
|
-
} };
|
254
|
-
|
255
|
-
configs[key].save = { type: 'button', click: function(config) {
|
253
|
+
configs[key].save = { type: 'button', name: 'Save This Flux', click: function(config, hey) {
|
254
|
+
var nameOfTheSaveButton = hey.save.name;
|
255
|
+
Vue.set(hey.save, 'name', 'Saving');
|
256
|
+
delete config.test_event;
|
256
257
|
var setup = thingToData(app.setup);
|
257
258
|
var flux = {
|
258
259
|
id: setup.id,
|
@@ -270,13 +271,49 @@ module Mushy
|
|
270
271
|
else
|
271
272
|
app.flow.fluxs[index] = flux;
|
272
273
|
|
273
|
-
|
274
|
+
setTimeout(function(){
|
275
|
+
Vue.set(hey.save, 'name', nameOfTheSaveButton);
|
276
|
+
app.setup.id.value = '';
|
277
|
+
|
278
|
+
Vue.set(app.setup, 'showFlux', false);
|
279
|
+
}, 500);
|
274
280
|
}
|
275
281
|
};
|
282
|
+
|
283
|
+
configs[key].test_event = { type: 'json', value: '{}', default: '{}' };
|
284
|
+
|
285
|
+
configs[key].run_test = { type: 'button', name: 'Test Run This Flux', click: function(c, hey) {
|
286
|
+
var previousName = hey.run_test.name;
|
287
|
+
Vue.set(hey.run_test, 'name', 'Loading');
|
288
|
+
app.results = [];
|
289
|
+
Vue.set(app.results, 'errorMessage', '');
|
290
|
+
var the_setup = thingToData(app.setup);
|
291
|
+
the_setup.event = c.test_event;
|
292
|
+
axios.post('/run', { config: c, setup: the_setup })
|
293
|
+
.then(function(r){
|
294
|
+
var index = 1;
|
295
|
+
for (var key in r.data.result)
|
296
|
+
{
|
297
|
+
var result = {};
|
298
|
+
result['event_' + index] = { type: 'jsonview', label: 'Event ' + index + ' of ' + r.data.result.length, value: r.data.result[key], view: 'thin' };
|
299
|
+
app.results.push(result);
|
300
|
+
index += 1;
|
301
|
+
}
|
302
|
+
}).catch(function(r){
|
303
|
+
console.log(r);
|
304
|
+
Vue.set(app.results, 'errorMessage', 'This app failed while trying to execute your flux.');
|
305
|
+
}).then(function(){
|
306
|
+
Vue.set(hey.run_test, 'name', previousName);
|
307
|
+
});
|
308
|
+
} };
|
276
309
|
}
|
277
310
|
|
278
|
-
var loadThisFlux = function(
|
311
|
+
var loadThisFlux = function(args)
|
279
312
|
{
|
313
|
+
var flux = args.flux;
|
314
|
+
var setup = args.setup;
|
315
|
+
var config = args.config;
|
316
|
+
|
280
317
|
Vue.set(setup.id, 'value', flux.id);
|
281
318
|
Vue.set(setup.name, 'value', flux.name);
|
282
319
|
Vue.set(setup.flux, 'value', flux.flux);
|
@@ -289,39 +326,59 @@ module Mushy
|
|
289
326
|
else
|
290
327
|
Vue.set(applicable_config[key], 'value', applicable_config[key].default);
|
291
328
|
|
329
|
+
if (applicable_config)
|
330
|
+
Vue.set(applicable_config.test_event, 'value', '{}');
|
292
331
|
|
293
|
-
options = flowdata.fluxs.
|
294
|
-
options.unshift('');
|
332
|
+
options = flowdata.fluxs.filter(function(x){ return x.id != flux.id });
|
333
|
+
options.unshift( { id: '', name: '' } );
|
295
334
|
setup.parent.options = options;
|
335
|
+
|
336
|
+
Vue.set(setup, 'showFlux', true);
|
337
|
+
app.results = [];
|
296
338
|
};
|
297
339
|
|
340
|
+
function uuidv4() {
|
341
|
+
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
|
342
|
+
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
343
|
+
);
|
344
|
+
}
|
345
|
+
|
298
346
|
app = new Vue({
|
299
347
|
el: '#app',
|
300
348
|
data: {
|
301
349
|
flow: flowdata,
|
302
350
|
startNew: function(x) {
|
303
351
|
flux = {
|
304
|
-
id:
|
305
|
-
name: '
|
352
|
+
id: uuidv4(),
|
353
|
+
name: '',
|
306
354
|
config: {}
|
307
355
|
};
|
308
|
-
loadThisFlux(flux, x.setup, x.configs);
|
356
|
+
loadThisFlux({ flux: flux, setup: x.setup, configs: x.configs });
|
309
357
|
},
|
310
|
-
|
358
|
+
editFlux: function(x) {
|
311
359
|
var flux = x.flux;
|
312
360
|
|
313
|
-
loadThisFlux(x.flux, x.setup, x.configs);
|
361
|
+
loadThisFlux({ flux: x.flux, setup: x.setup, configs: x.configs });
|
362
|
+
},
|
363
|
+
deleteFlux: function(x) {
|
364
|
+
var set = x.flow.fluxs.filter( function(v){ return v.id != x.flux.id } );
|
365
|
+
Vue.set(x.flow, 'fluxs', set);
|
314
366
|
},
|
315
|
-
saveFlow: function(
|
367
|
+
saveFlow: function(input)
|
316
368
|
{
|
317
|
-
|
369
|
+
var setup = input.setup;
|
370
|
+
var flow = input.flow;
|
318
371
|
axios.post('/save', flow)
|
319
372
|
.then(function(result){
|
320
|
-
|
373
|
+
Vue.set(setup, 'showFlux', false);
|
321
374
|
});
|
322
375
|
},
|
323
376
|
configs: configs,
|
324
377
|
setup: setup,
|
378
|
+
flux_name_for: function(id, fluxes) {
|
379
|
+
var flux = fluxes.filter(function(x){ return x.id == id })[0];
|
380
|
+
return flux != undefined ? flux.name : '';
|
381
|
+
},
|
325
382
|
results: [],
|
326
383
|
}
|
327
384
|
});
|
data/lib/mushy/flow.rb
CHANGED
@@ -18,8 +18,10 @@ module Mushy
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.build_flux record
|
21
|
-
|
21
|
+
type = record[:type] || record['type'] || record[:flux] || record['flux'] || 'Flux'
|
22
|
+
flux = Object.const_get("Mushy::#{type}").new
|
22
23
|
flux.id = record[:id] || record['id'] || flux.id
|
24
|
+
flux.type = type
|
23
25
|
flux.config = SymbolizedHash.new(record[:config] || record['config'])
|
24
26
|
flux
|
25
27
|
end
|
data/lib/mushy/flux.rb
CHANGED
data/lib/mushy/fluxs/browser.rb
CHANGED
@@ -17,16 +17,25 @@ module Mushy
|
|
17
17
|
headless: {
|
18
18
|
description: 'Run this browser headless.',
|
19
19
|
type: 'boolean',
|
20
|
+
shrink: true,
|
20
21
|
value: 'true',
|
21
22
|
},
|
23
|
+
timeout: {
|
24
|
+
description: 'The default timeout (in seconds) before closing the browser. Default is 5 seconds.',
|
25
|
+
type: 'integer',
|
26
|
+
shrink: true,
|
27
|
+
value: '',
|
28
|
+
},
|
22
29
|
execute: {
|
23
30
|
description: 'Javascript to run after the page is loaded.',
|
24
31
|
type: 'textarea',
|
32
|
+
shrink: true,
|
25
33
|
value: '',
|
26
34
|
},
|
27
35
|
cookies: {
|
28
36
|
description: 'Cookies for the web request. These can be received from a previous browser event with {{cookies}}, or can be typed manually.',
|
29
37
|
type: 'editgrid',
|
38
|
+
shrink: true,
|
30
39
|
value: [],
|
31
40
|
editors: [
|
32
41
|
{ id: 'name', target: 'name', field: { type: 'text', value: '', default: '' } },
|
@@ -40,30 +49,42 @@ module Mushy
|
|
40
49
|
{ id: 'sameSite', target: 'sameSite', field: { type: 'text', value: 'None', default: 'None' } },
|
41
50
|
{ id: 'priority', target: 'priority', field: { type: 'text', value: 'Medium', default: 'Medium' } },
|
42
51
|
],
|
43
|
-
#{"name":"1P_JAR","value":"2021-01-21-13","domain":".google.com","path":"/","expires":1613828458.870408,"size":19,"httpOnly":false,"secure":true,"session":false,"sameSite":"None","priority":"Medium"
|
44
52
|
},
|
45
53
|
carry_cookies_from: {
|
46
54
|
description: 'Carry the cookies from this path in the event.',
|
47
55
|
type: 'text',
|
56
|
+
shrink: true,
|
48
57
|
value: 'cookies',
|
49
58
|
},
|
50
59
|
headers: {
|
51
60
|
description: 'Headers for the web request. These can be received from a previous browser event with {{headers}}, or can be typed manually.',
|
52
61
|
type: 'keyvalue',
|
62
|
+
shrink: true,
|
53
63
|
value: {},
|
54
64
|
},
|
55
65
|
carry_headers_from: {
|
56
66
|
description: 'Carry the headers from this path in the event.',
|
57
67
|
type: 'text',
|
68
|
+
shrink: true,
|
58
69
|
value: 'headers',
|
59
70
|
},
|
71
|
+
wait_before_closing: {
|
72
|
+
description: 'Wait this many seconds before closing the browser.',
|
73
|
+
type: 'integer',
|
74
|
+
shrink: true,
|
75
|
+
value: '',
|
76
|
+
},
|
60
77
|
},
|
61
78
|
}
|
62
79
|
end
|
63
80
|
|
64
81
|
def process event, config
|
65
82
|
|
66
|
-
|
83
|
+
timeout = config[:timeout] ? config[:timeout].to_i : 5
|
84
|
+
|
85
|
+
browser = Ferrum::Browser.new(
|
86
|
+
headless: (config[:headless].to_s != 'false'),
|
87
|
+
timeout: timeout)
|
67
88
|
|
68
89
|
get_the_cookies_from(event, config).each { |c| browser.cookies.set(c) }
|
69
90
|
|
@@ -73,8 +94,12 @@ module Mushy
|
|
73
94
|
|
74
95
|
browser.execute(config[:execute]) if config[:execute]
|
75
96
|
|
97
|
+
sleep(config[:wait_before_closing].to_i) if config[:wait_before_closing] && config[:wait_before_closing].to_i > 0
|
98
|
+
|
76
99
|
result = {
|
77
100
|
url: browser.url,
|
101
|
+
status: browser.network.status,
|
102
|
+
title: browser.frames[0].title,
|
78
103
|
cookies: browser.cookies.all.map { |k, v| v.instance_variable_get('@attributes') },
|
79
104
|
headers: browser.headers.get,
|
80
105
|
body: browser.body
|
data/lib/mushy/fluxs/filter.rb
CHANGED
@@ -2,6 +2,29 @@ module Mushy
|
|
2
2
|
|
3
3
|
class Filter < Flux
|
4
4
|
|
5
|
+
def self.details
|
6
|
+
{
|
7
|
+
name: 'Filter',
|
8
|
+
description: 'Filters events based on criteria.',
|
9
|
+
config: {
|
10
|
+
equal: {
|
11
|
+
description: 'Provide key/value pairs that must match in the event.',
|
12
|
+
shrink: true,
|
13
|
+
label: 'Equal To',
|
14
|
+
type: 'keyvalue',
|
15
|
+
value: {},
|
16
|
+
},
|
17
|
+
notequal: {
|
18
|
+
description: 'Provide key/value pairs that must NOT match in the event.',
|
19
|
+
shrink: true,
|
20
|
+
label: 'Not Equal To',
|
21
|
+
type: 'keyvalue',
|
22
|
+
value: {},
|
23
|
+
},
|
24
|
+
},
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
5
28
|
def process event, config
|
6
29
|
|
7
30
|
differences = [:equal, :notequal]
|
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.1.3'
|
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.'
|
@@ -17,9 +17,11 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.license = 'MIT'
|
18
18
|
|
19
19
|
s.add_development_dependency 'minitest'
|
20
|
+
s.add_runtime_dependency 'sinatra'
|
21
|
+
s.add_runtime_dependency 'symbolized'
|
20
22
|
s.add_runtime_dependency 'thor'
|
21
23
|
s.add_runtime_dependency 'liquid'
|
22
24
|
s.add_runtime_dependency 'ferrum'
|
23
25
|
s.add_runtime_dependency 'nokogiri'
|
24
26
|
s.add_runtime_dependency 'faraday'
|
25
|
-
end
|
27
|
+
end
|
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.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darren Cauthon
|
@@ -24,6 +24,34 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: symbolized
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: thor
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +142,7 @@ files:
|
|
114
142
|
- lib/mushy/fluxs/bash.rb
|
115
143
|
- lib/mushy/fluxs/browser.rb
|
116
144
|
- lib/mushy/fluxs/build_csv.rb
|
145
|
+
- lib/mushy/fluxs/cli.rb
|
117
146
|
- lib/mushy/fluxs/collection.rb
|
118
147
|
- lib/mushy/fluxs/filter.rb
|
119
148
|
- lib/mushy/fluxs/format.rb
|