mushy 0.0.5 → 0.1.4
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 +140 -95
- data/lib/mushy/flow.rb +3 -1
- data/lib/mushy/flux.rb +1 -0
- data/lib/mushy/fluxs/browser.rb +23 -5
- 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: 2eaed069f8d37db0a6d58fea9c994e4a5135f43a18a7e7ad8421a601983bb954
|
|
4
|
+
data.tar.gz: 3224715b652898edaac99ad89a8378ccc4d2aa4ba21b891ca33fec0b99252a85
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df28cc21a604e023284ad3f88b2cd11a3ab4261c3cd9747a2033d07528203262de29daa2d12f82e404eb91109b79ee9a5e5a5bf71396c360e26ff270d08a2449
|
|
7
|
+
data.tar.gz: 05410eb4c9fee4afd4aa31397409b6c794bc152257cf599aa4fb1502cb7009c518b9fac2eb76b3f78ca1e58e2a31e28e6dcd6c5266febb8bddd7ea7fbe7fdea1
|
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, optional: true, type: :string
|
|
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
|
-
<
|
|
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>
|
|
24
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,23 +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>'
|
|
92
121
|
},
|
|
93
122
|
selectrecord: {
|
|
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 options" v-bind:value="option.id" :selected="value == option.id">{{option.name}}</option></select></div>'
|
|
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>'
|
|
96
125
|
},
|
|
97
126
|
boolean: {
|
|
98
|
-
props: ['label', 'value', 'options', 'description'],
|
|
99
|
-
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>'
|
|
100
129
|
},
|
|
101
130
|
table: {
|
|
102
131
|
props: ['value', 'description'],
|
|
@@ -117,12 +146,13 @@ module Mushy
|
|
|
117
146
|
}
|
|
118
147
|
};
|
|
119
148
|
},
|
|
120
|
-
props: ['value', 'editors', 'label', 'description'],
|
|
121
|
-
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>'
|
|
122
151
|
},
|
|
123
152
|
keyvalue: {
|
|
124
153
|
data: function() {
|
|
125
154
|
return {
|
|
155
|
+
actionText: function(value, others) { found = false; for(var i in others){ if (i == value) found = true; } return found ? 'Replace' : 'Add'; },
|
|
126
156
|
removeRecord: function(data, key) { Vue.delete(data, key) },
|
|
127
157
|
addRecord: function(editors, data) {
|
|
128
158
|
Vue.set(data, editors[0].field.value, editors[1].field.value)
|
|
@@ -131,12 +161,12 @@ module Mushy
|
|
|
131
161
|
}
|
|
132
162
|
};
|
|
133
163
|
},
|
|
134
|
-
props: ['value', 'label', 'editors', 'description'],
|
|
135
|
-
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>'
|
|
136
166
|
},
|
|
137
167
|
button: {
|
|
138
|
-
props: ['click', 'description'],
|
|
139
|
-
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>'
|
|
140
170
|
}
|
|
141
171
|
};
|
|
142
172
|
|
|
@@ -156,6 +186,7 @@ module Mushy
|
|
|
156
186
|
return {
|
|
157
187
|
console: console,
|
|
158
188
|
pull: function(x) { return thingToData(foundIt.data); },
|
|
189
|
+
thisComponent: function() { return foundIt.data; },
|
|
159
190
|
}
|
|
160
191
|
},
|
|
161
192
|
props: props,
|
|
@@ -188,32 +219,6 @@ module Mushy
|
|
|
188
219
|
template: '<div><mip-thing v-for="(d, id) in data" :data="d" :id="id"></mip-thing></div>',
|
|
189
220
|
});
|
|
190
221
|
|
|
191
|
-
var sample = {
|
|
192
|
-
email: { type: 'email', value: 'darren@cauthon.com' },
|
|
193
|
-
first_name: { type: 'text', value: 'Darren' },
|
|
194
|
-
description: { type: 'textarea', value: 'more data' },
|
|
195
|
-
size: { type: 'select', value: 'medium', options: ['small', 'medium', 'large']},
|
|
196
|
-
heynow: { type: 'keyvalue',
|
|
197
|
-
value: {
|
|
198
|
-
first_name: 'John',
|
|
199
|
-
last_name: 'Doe',
|
|
200
|
-
},
|
|
201
|
-
editors: [
|
|
202
|
-
{ id: 'new_key', target: 'key', field: { type: 'text', value: '', default: '' } },
|
|
203
|
-
{ id: 'new_value', target: 'value', field: { type: 'text', value: '', default: '' } }
|
|
204
|
-
] },
|
|
205
|
-
past: { type: 'editgrid',
|
|
206
|
-
value: [
|
|
207
|
-
{ name: 'Godzilla', quantity: 1 },
|
|
208
|
-
{ name: 'Mothra', quantity: 2 },
|
|
209
|
-
],
|
|
210
|
-
editors: [
|
|
211
|
-
{ id: 'new_name', target: 'name', field: { type: 'text', value: '', default: '' } },
|
|
212
|
-
{ id: 'new_quantity', target: 'quantity', field: { type: 'select', value: '1', options: [1, 2, 3], default: 1 } }
|
|
213
|
-
] },
|
|
214
|
-
super_action: { type: 'button', click: function(x) { console.log(x) } },
|
|
215
|
-
};
|
|
216
|
-
|
|
217
222
|
var app = null;
|
|
218
223
|
|
|
219
224
|
axios.get('/fluxs')
|
|
@@ -237,51 +242,80 @@ module Mushy
|
|
|
237
242
|
|
|
238
243
|
var setup = {
|
|
239
244
|
showFlux: false,
|
|
240
|
-
|
|
241
|
-
id: { type: 'text', value: '' },
|
|
245
|
+
id: { type: 'hide', value: '' },
|
|
242
246
|
name: { type: 'text', value: '' },
|
|
243
247
|
flux: { type: 'select', value: fluxdata.fluxs[0].name, options: options},
|
|
244
|
-
parent: { type: 'selectrecord', value: '', options: flowdata.fluxs },
|
|
248
|
+
parent: { type: 'selectrecord', label: 'Receive Events From', value: '', options: flowdata.fluxs },
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
var saveFlux = function(config, hey) {
|
|
252
|
+
var nameOfTheSaveButton = hey.save.name;
|
|
253
|
+
Vue.set(hey.save, 'name', 'Saving');
|
|
254
|
+
delete config.test_event;
|
|
255
|
+
var setup = thingToData(app.setup);
|
|
256
|
+
var flux = {
|
|
257
|
+
id: setup.id,
|
|
258
|
+
name: setup.name,
|
|
259
|
+
flux: setup.flux,
|
|
260
|
+
parent: setup.parent,
|
|
261
|
+
config: config,
|
|
262
|
+
};
|
|
263
|
+
var index = -1;
|
|
264
|
+
for(var i = 0; i < app.flow.fluxs.length; i++)
|
|
265
|
+
if (app.flow.fluxs[i].id == flux.id)
|
|
266
|
+
index = i;
|
|
267
|
+
|
|
268
|
+
if (index < 0)
|
|
269
|
+
app.flow.fluxs.push(flux);
|
|
270
|
+
else
|
|
271
|
+
app.flow.fluxs[index] = flux;
|
|
272
|
+
|
|
273
|
+
setTimeout(function(){
|
|
274
|
+
Vue.set(hey.save, 'name', nameOfTheSaveButton);
|
|
275
|
+
app.setup.id.value = '';
|
|
276
|
+
|
|
277
|
+
Vue.set(app.setup, 'showFlux', false);
|
|
278
|
+
}, 500);
|
|
245
279
|
};
|
|
246
280
|
|
|
247
281
|
for (var key in configs)
|
|
248
282
|
{
|
|
249
|
-
configs[key].
|
|
283
|
+
configs[key].save = { type: 'button', name: 'Save This Flux', click: saveFlux };
|
|
284
|
+
|
|
285
|
+
configs[key].test_event = { type: 'json', value: '{}', default: '{}' };
|
|
286
|
+
|
|
287
|
+
configs[key].run_test = { type: 'button', name: 'Test Run This Flux', click: function(c, hey) {
|
|
288
|
+
var previousName = hey.run_test.name;
|
|
289
|
+
Vue.set(hey.run_test, 'name', 'Loading');
|
|
250
290
|
app.results = [];
|
|
251
|
-
Vue.set(app.results, '
|
|
252
|
-
|
|
291
|
+
Vue.set(app.results, 'errorMessage', '');
|
|
292
|
+
var the_setup = thingToData(app.setup);
|
|
293
|
+
the_setup.event = c.test_event;
|
|
294
|
+
axios.post('/run', { config: c, setup: the_setup })
|
|
253
295
|
.then(function(r){
|
|
254
|
-
|
|
296
|
+
var index = 1;
|
|
255
297
|
for (var key in r.data.result)
|
|
256
|
-
|
|
298
|
+
{
|
|
299
|
+
var result = {};
|
|
300
|
+
result['event_' + index] = { type: 'jsonview', label: 'Event ' + index + ' of ' + r.data.result.length, value: r.data.result[key], view: 'thin' };
|
|
301
|
+
app.results.push(result);
|
|
302
|
+
index += 1;
|
|
303
|
+
}
|
|
304
|
+
}).catch(function(r){
|
|
305
|
+
console.log(r);
|
|
306
|
+
Vue.set(app.results, 'errorMessage', 'This app failed while trying to execute your flux.');
|
|
307
|
+
}).then(function(){
|
|
308
|
+
Vue.set(hey.run_test, 'name', previousName);
|
|
257
309
|
});
|
|
258
310
|
} };
|
|
259
|
-
|
|
260
|
-
configs[key].save = { type: 'button', click: function(config) {
|
|
261
|
-
var setup = thingToData(app.setup);
|
|
262
|
-
var flux = {
|
|
263
|
-
id: setup.id,
|
|
264
|
-
name: setup.name,
|
|
265
|
-
flux: setup.flux,
|
|
266
|
-
parent: setup.parent,
|
|
267
|
-
config: config,
|
|
268
|
-
};
|
|
269
|
-
var index = -1;
|
|
270
|
-
for(var i = 0; i < app.flow.fluxs.length; i++)
|
|
271
|
-
if (app.flow.fluxs[i].id == flux.id)
|
|
272
|
-
index = i;
|
|
273
|
-
if (index < 0)
|
|
274
|
-
app.flow.fluxs.push(flux);
|
|
275
|
-
else
|
|
276
|
-
app.flow.fluxs[index] = flux;
|
|
277
|
-
|
|
278
|
-
app.setup.id.value = '';
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
311
|
}
|
|
282
312
|
|
|
283
|
-
var loadThisFlux = function(
|
|
313
|
+
var loadThisFlux = function(args)
|
|
284
314
|
{
|
|
315
|
+
var flux = args.flux;
|
|
316
|
+
var setup = args.setup;
|
|
317
|
+
var config = args.config;
|
|
318
|
+
|
|
285
319
|
Vue.set(setup.id, 'value', flux.id);
|
|
286
320
|
Vue.set(setup.name, 'value', flux.name);
|
|
287
321
|
Vue.set(setup.flux, 'value', flux.flux);
|
|
@@ -294,12 +328,15 @@ module Mushy
|
|
|
294
328
|
else
|
|
295
329
|
Vue.set(applicable_config[key], 'value', applicable_config[key].default);
|
|
296
330
|
|
|
331
|
+
if (applicable_config)
|
|
332
|
+
Vue.set(applicable_config.test_event, 'value', '{}');
|
|
297
333
|
|
|
298
334
|
options = flowdata.fluxs.filter(function(x){ return x.id != flux.id });
|
|
299
335
|
options.unshift( { id: '', name: '' } );
|
|
300
336
|
setup.parent.options = options;
|
|
301
337
|
|
|
302
338
|
Vue.set(setup, 'showFlux', true);
|
|
339
|
+
app.results = [];
|
|
303
340
|
};
|
|
304
341
|
|
|
305
342
|
function uuidv4() {
|
|
@@ -315,15 +352,19 @@ module Mushy
|
|
|
315
352
|
startNew: function(x) {
|
|
316
353
|
flux = {
|
|
317
354
|
id: uuidv4(),
|
|
318
|
-
name: '
|
|
355
|
+
name: '',
|
|
319
356
|
config: {}
|
|
320
357
|
};
|
|
321
|
-
loadThisFlux(flux, x.setup, x.configs);
|
|
358
|
+
loadThisFlux({ flux: flux, setup: x.setup, configs: x.configs });
|
|
322
359
|
},
|
|
323
|
-
|
|
360
|
+
editFlux: function(x) {
|
|
324
361
|
var flux = x.flux;
|
|
325
362
|
|
|
326
|
-
loadThisFlux(x.flux, x.setup, x.configs);
|
|
363
|
+
loadThisFlux({ flux: x.flux, setup: x.setup, configs: x.configs });
|
|
364
|
+
},
|
|
365
|
+
deleteFlux: function(x) {
|
|
366
|
+
var set = x.flow.fluxs.filter( function(v){ return v.id != x.flux.id } );
|
|
367
|
+
Vue.set(x.flow, 'fluxs', set);
|
|
327
368
|
},
|
|
328
369
|
saveFlow: function(input)
|
|
329
370
|
{
|
|
@@ -331,11 +372,15 @@ module Mushy
|
|
|
331
372
|
var flow = input.flow;
|
|
332
373
|
axios.post('/save', flow)
|
|
333
374
|
.then(function(result){
|
|
334
|
-
Vue.set(setup, '
|
|
375
|
+
Vue.set(setup, 'showFlux', false);
|
|
335
376
|
});
|
|
336
377
|
},
|
|
337
378
|
configs: configs,
|
|
338
379
|
setup: setup,
|
|
380
|
+
flux_name_for: function(id, fluxes) {
|
|
381
|
+
var flux = fluxes.filter(function(x){ return x.id == id })[0];
|
|
382
|
+
return flux != undefined ? flux.name : '';
|
|
383
|
+
},
|
|
339
384
|
results: [],
|
|
340
385
|
}
|
|
341
386
|
});
|
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,27 +49,30 @@ 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
|
},
|
|
60
71
|
wait_before_closing: {
|
|
61
72
|
description: 'Wait this many seconds before closing the browser.',
|
|
62
73
|
type: 'integer',
|
|
63
|
-
|
|
74
|
+
shrink: true,
|
|
75
|
+
value: '',
|
|
64
76
|
},
|
|
65
77
|
},
|
|
66
78
|
}
|
|
@@ -68,7 +80,11 @@ module Mushy
|
|
|
68
80
|
|
|
69
81
|
def process event, config
|
|
70
82
|
|
|
71
|
-
|
|
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)
|
|
72
88
|
|
|
73
89
|
get_the_cookies_from(event, config).each { |c| browser.cookies.set(c) }
|
|
74
90
|
|
|
@@ -78,15 +94,17 @@ module Mushy
|
|
|
78
94
|
|
|
79
95
|
browser.execute(config[:execute]) if config[:execute]
|
|
80
96
|
|
|
97
|
+
sleep(config[:wait_before_closing].to_i) if config[:wait_before_closing] && config[:wait_before_closing].to_i > 0
|
|
98
|
+
|
|
81
99
|
result = {
|
|
82
100
|
url: browser.url,
|
|
101
|
+
status: browser.network.status,
|
|
102
|
+
title: browser.frames[0].title,
|
|
83
103
|
cookies: browser.cookies.all.map { |k, v| v.instance_variable_get('@attributes') },
|
|
84
104
|
headers: browser.headers.get,
|
|
85
105
|
body: browser.body
|
|
86
106
|
}
|
|
87
107
|
|
|
88
|
-
sleep(config[:wait_before_closing].to_i) if config[:wait_before_closing] && config[:wait_before_closing].to_i > 0
|
|
89
|
-
|
|
90
108
|
browser.quit
|
|
91
109
|
|
|
92
110
|
result
|
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.4'
|
|
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.4
|
|
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
|