speedflow 0.2.1 → 0.3.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
  SHA1:
3
- metadata.gz: 27374a1174d79f26fffb0eb47bbf2c59b89e315e
4
- data.tar.gz: 07e584e9c840f44764c33b92ee57302718aa42a0
3
+ metadata.gz: 0917a8d9f55cf6d722cbf1819dca1acf62d41262
4
+ data.tar.gz: d48c35ef4a5970b059a9d7b042100ce1bac65921
5
5
  SHA512:
6
- metadata.gz: e5bda2467bf65a6b4078a86e52cafcca8655cb991b23402557559f1ed228929b3f6768d7b965cd76f6fd0ebb6ca4f5eabd589bd66bc67a34933788711dbd6bf7
7
- data.tar.gz: 2691daaa4db69e66ffd1cc4e1f7f422a7a48dfb84ce2fab5e832c3d29912d6b96461fcab82d2627f1eee9fa816a43abd60d0bab61bd51fb2e43742fcd848c196
6
+ metadata.gz: 2797aaa19a525241bf15896d817f4a5c0f3f5b9fc275069590b866f35750e92e67e1906268485d88393be70e9bad117d0fb274f3364c5ed3995c852f058f87e2
7
+ data.tar.gz: a24938e6ed76a465575956ac154f2f73acef4714b9e64f95c8559943f5edda878baa2a845c2a1beddbb0e2837b80777aed15cf121f2edcd6e9b462203e3839b9
data/bin/speedflow CHANGED
@@ -4,6 +4,9 @@ STDOUT.sync = true
4
4
  require 'mercenary'
5
5
  require 'speedflow'
6
6
 
7
+ # Kill exiting error
8
+ Signal.trap('SIGINT') { exit 130 }
9
+
7
10
  # Speedflow program
8
11
  Mercenary.program(:speedflow) do |program|
9
12
  program.version Speedflow::VERSION
@@ -58,7 +58,7 @@ module Speedflow
58
58
  success "Trigger '#{trigger}' successful"
59
59
  rescue FlowTriggerNotFound => exception
60
60
  error "Trigger '#{trigger}' error: #{exception.message}"
61
- rescue PluginNotFound => exception
61
+ rescue Plugin::PluginNotFound => exception
62
62
  error "Plugin error: #{exception.message}"
63
63
  end
64
64
  end
@@ -12,33 +12,57 @@ module Speedflow
12
12
  #
13
13
  # Returns a Hash of config.
14
14
  def initialize(config)
15
+ # TODO: v0.4: Reinforce the SOI.
15
16
  @config = config
16
17
  end
17
18
 
18
19
  # Public: Trigger.
19
20
  #
20
21
  # trigger - Trigger name.
21
- # inputs - Inputs.
22
+ # input - Input Hash.
22
23
  #
23
24
  # Returns nothing.
24
- def trigger(trigger, inputs)
25
+ def trigger(trigger, input)
26
+ # TODO: v0.4: Change by: Configuration.not_empty_key?
27
+ # TODO: v0.4: Move to this class: Flow.trigger?
25
28
  unless @config.flow_trigger?(trigger)
26
29
  raise FlowTriggerNotFound, "Unable to trigger: #{trigger}"
27
30
  end
28
31
 
32
+ # TODO: v0.4: Move in a normal object tree: Flow > Trigger > Action
33
+ output_by_tag = {}
29
34
  output = {}
30
35
  @config['flow'][trigger.to_s].each do |step|
31
- arguments = step['arguments'] || {}
36
+ output = trigger_step(step, input, output, output_by_tag)
37
+ end
38
+ end
32
39
 
33
- step['arguments'] = transform_arguments(arguments, output, inputs)
34
- step['arguments'] = add_config_argument(arguments)
40
+ # Public: Trigger step
41
+ #
42
+ # step - Step Hash.
43
+ # input - Input Hash.
44
+ # output - Output Hash.
45
+ # output_by_tag - Output by tag Hash.
46
+ #
47
+ # Returns output Hash.
48
+ def trigger_step(step, input, output, output_by_tag)
49
+ arguments = step['arguments'] || {}
35
50
 
36
- output = plugin_manager.call_action_from_step(step)
37
- end
51
+ # TODO: v0.4: Move to a normal object: TriggerArgument
52
+ step['arguments'] = transform_arguments(arguments, output, input)
53
+ step['arguments'] = add_config_argument(arguments)
54
+
55
+ # TODO: v0.4: Move to a normal object: TriggerArgument
56
+ output = plugin_manager.action_from_step(step)
57
+ output_by_tag[step['tag']] = output if step.key? 'tag'
58
+
59
+ output.merge(output_by_tag)
38
60
  end
39
61
 
40
62
  # Public: Add config arguement
41
63
  #
64
+ # TODO: v0.4: Move to a normal object: TriggerArgument
65
+ #
42
66
  # arguments - Hash of arguments.
43
67
  #
44
68
  # Returns Hash of arguments.
@@ -53,6 +77,8 @@ module Speedflow
53
77
 
54
78
  # Public: Transform arguments (to add value)
55
79
  #
80
+ # TODO: v0.4: Move to a normal object: TriggerArgument
81
+ #
56
82
  # arguments - Hash of arguments.
57
83
  # prev_values - Hash of previous values.
58
84
  # inputs - Hash of inputs.
@@ -73,6 +99,8 @@ module Speedflow
73
99
 
74
100
  # Public: Get flat arguments from flow.
75
101
  #
102
+ # TODO: v0.4: Move to a normal object: TriggerArgument
103
+ #
76
104
  # Returns flat Array of arguments.
77
105
  def flat_arguments
78
106
  args = []
@@ -88,7 +116,7 @@ module Speedflow
88
116
  #
89
117
  # Returns an instance of plugin manager.
90
118
  def plugin_manager
91
- @plugin_manager ||= PluginManager.new(@config['plugins'])
119
+ @plugin_manager ||= Plugin::Manager.new(@config['plugins'])
92
120
  end
93
121
  end
94
122
 
@@ -1,5 +1,6 @@
1
1
  # Speedflow core
2
2
  module Speedflow
3
+ # TODO: v0.4: Remove, use TTY::Prompt.
3
4
  require 'colorize'
4
5
  # Used to manage the output message
5
6
  module Message
@@ -0,0 +1,30 @@
1
+ module Speedflow
2
+ module Plugin
3
+ # Plugin abstraction
4
+ class Abstract
5
+ # @return [Speedflow::Plugin::Configuration] Plugin configuration.
6
+ attr_reader :config
7
+
8
+ # @return [Speedflow::Plugin::Prompt] Plugin prompt.
9
+ attr_reader :prompt
10
+
11
+ # Public: Constructor
12
+ #
13
+ # config - Speedflow::Plugin::Configuration object.
14
+ # prompt - Speedflow::Plugin::Prompt object.
15
+ #
16
+ # Examples
17
+ #
18
+ # Manager.new(
19
+ # <Speedflow::Plugin::Configuration.new({})>,
20
+ # <Speedflow::Plugin::Prompt.new>)
21
+ # # => <Speedflow::Plugin::Abstract>
22
+ #
23
+ # Returns nothing.
24
+ def initialize(config, prompt)
25
+ @config = config
26
+ @prompt = prompt
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,97 @@
1
+ module Speedflow
2
+ module Plugin
3
+ # Plugin configuration
4
+ class Configuration
5
+ CONFIG_KEY = '_config'.freeze
6
+
7
+ # Initialize.
8
+ #
9
+ # arguments - Hash of arguments.
10
+ # plugin_name - Name of plugin.
11
+ #
12
+ # Examples
13
+ #
14
+ # Configuration.new({}, 'plugin')
15
+ # # => <Speedflow::Plugin::Configuration>
16
+ #
17
+ # Returns nothing.
18
+ def initialize(arguments, plugin_name)
19
+ @arguments = arguments
20
+ @plugin_name = plugin_name
21
+ end
22
+
23
+ # Public: All config.
24
+ #
25
+ # Returns Hash of all config.
26
+ def all_config
27
+ @arguments.key?(CONFIG_KEY) ? @arguments[CONFIG_KEY] : {}
28
+ end
29
+
30
+ # Public: All input.
31
+ #
32
+ # Returns Hash of all input.
33
+ def all_input
34
+ @arguments.select { |k, _| k != CONFIG_KEY }
35
+ end
36
+
37
+ # Public: Get a specific config.
38
+ #
39
+ # key - Key of config.
40
+ # default_value - Default value.
41
+ #
42
+ # Returns value of config key.
43
+ def by_config(key, default_value = '')
44
+ config = {}
45
+ if @arguments.key?(CONFIG_KEY)
46
+ if @arguments[CONFIG_KEY].key?(@plugin_name)
47
+ config = @arguments[CONFIG_KEY][@plugin_name]
48
+ end
49
+ end
50
+ config.key?(key) ? config[key].to_s : default_value.to_s
51
+ end
52
+
53
+ # Public: Get multiple config.
54
+ #
55
+ # keys_and_defaults - Hash of keys and defaults. { 'key' => 'default' }
56
+ #
57
+ # Returns Hash with values or defaults.
58
+ def by_multiple_config(keys_and_defaults)
59
+ keys_and_defaults.each { |k, v| keys_and_defaults[k] = by_config(k, v) }
60
+ end
61
+
62
+ # Public: Get an input config by key.
63
+ #
64
+ # key - Key of config.
65
+ # default_value - Default value.
66
+ #
67
+ # Returns value of input config key.
68
+ def by_input(key, default_value = '')
69
+ if @arguments.key?(key)
70
+ @arguments[key]['value'].to_s
71
+ else
72
+ default_value.to_s
73
+ end
74
+ end
75
+
76
+ # Public: Get an input config by key but required.
77
+ #
78
+ # key - Key of config.
79
+ # default_value - Default value.
80
+ #
81
+ # Returns value of input config key or Exception.
82
+ def by_required_input(key, default_value = '')
83
+ value = by_input(key, default_value)
84
+
85
+ if by_input(key).empty?
86
+ raise ConfigurationInputRequire, "Required value for '#{key}'."
87
+ end
88
+
89
+ value
90
+ end
91
+ end
92
+
93
+ # Input exception
94
+ class ConfigurationInputRequire < Exception
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,130 @@
1
+ module Speedflow
2
+ # Plugin
3
+ module Plugin
4
+ # Used to manage the plugins
5
+ class Manager
6
+ include ActiveSupport::Inflector
7
+ # TODO: V2: Remove underground prompt.
8
+ include Message
9
+
10
+ PLUGIN_BASE = 'speedflow-plugin-'.freeze
11
+
12
+ # @return [Speedflow::Plugin::Configuration] Plugin configuration object.
13
+ attr_writer :config
14
+
15
+ # @return [Speedflow::Plugin::Prompt] Plugin prompt object.
16
+ attr_writer :prompt
17
+
18
+ # Public: Constructor
19
+ #
20
+ # plugins - Array of plugins
21
+ #
22
+ # Examples
23
+ #
24
+ # Manager.new([])
25
+ # # => <Speedflow::Plugin::Manager>
26
+ #
27
+ # Returns an Arrays of plugins.
28
+ def initialize(plugins = [])
29
+ @plugins = plugins || []
30
+ load_plugins
31
+ end
32
+
33
+ # Public: Load plugins
34
+ #
35
+ # Returns nothing.
36
+ def load_plugins
37
+ @plugins.each { |plugin| require_plugin(plugin) }
38
+ end
39
+
40
+ # Public: Require a plugins (from Gem)
41
+ #
42
+ # Returns nothing.
43
+ def require_plugin(plugin)
44
+ require plugin.downcase.prepend(PLUGIN_BASE)
45
+ rescue LoadError
46
+ message = "Unable to load plugin '#{plugin}'.\n"
47
+ message << "Help: `gem install #{PLUGIN_BASE}#{plugin}`"
48
+ raise PluginNotFound, message
49
+ end
50
+
51
+ # Call action from flow step.
52
+ #
53
+ # step - Hash from flow. {plugin: '', action: '', arguments: ''}.
54
+ #
55
+ # Returns nothing.
56
+ def action_from_step(step)
57
+ plugin = plugin(step['plugin'], step['arguments'])
58
+ action(plugin, step['action'])
59
+ end
60
+
61
+ # Call plugin.
62
+ #
63
+ # plugin_name - Plugin name.
64
+ # arguments - List of arguments.
65
+ #
66
+ # Returns <Speedflow::Plugin::Abstract>.
67
+ def plugin(plugin_name, arguments)
68
+ configuration = config.new(arguments, plugin_name)
69
+ plugin_object(plugin_name).new(configuration, prompt.new)
70
+ end
71
+
72
+ # Call action.
73
+ #
74
+ # plugin_name - Plugin name.
75
+ # action_name - Action name.
76
+ # arguments - List of arguments.
77
+ #
78
+ # Returns Hash of action output.
79
+ def action(plugin, action_name)
80
+ plugin_name = plugin.class.name.split('::')[-2].downcase
81
+ action_name = action_name.prepend('action_').underscore
82
+
83
+ unless plugin.respond_to?(action_name) && plugin_name == 'test'
84
+ message = "Unable to call action: #{plugin_name}.#{action_name}"
85
+ raise PluginActionNotFound, message
86
+ end
87
+
88
+ # TODO: v0.4: Remove underground prompt.
89
+ success "Run action '#{action_name}' of '#{plugin_name}' plugin."
90
+
91
+ plugin.send action_name
92
+ end
93
+
94
+ # Public: Get plugin object from plugin name
95
+ #
96
+ # plugin_name - Plugin name.
97
+ #
98
+ # TODO: v0.4: Create Utils::name_to_object method.
99
+ #
100
+ # Returns Object.
101
+ def plugin_object(plugin_name)
102
+ plugin_name = plugin_name.downcase.capitalize
103
+
104
+ "Speedflow::Plugin::#{plugin_name}::Plugin".constantize
105
+ end
106
+
107
+ # Public: Plugin configuration object.
108
+ #
109
+ # Returns Speedflow::Plugin::Configuration.
110
+ def config
111
+ @config ||= Configuration
112
+ end
113
+
114
+ # Public: Plugin prompt object.
115
+ #
116
+ # Returns Speedflow::Plugin::Prompt.
117
+ def prompt
118
+ @prompt ||= ::TTY::Prompt
119
+ end
120
+ end
121
+
122
+ # Plugin exception
123
+ class PluginNotFound < Exception
124
+ end
125
+
126
+ # Plugin action exception
127
+ class PluginActionNotFound < Exception
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,39 @@
1
+ require 'tty-prompt'
2
+
3
+ module Speedflow
4
+ module Plugin
5
+ # Plugin prompt
6
+ class Prompt
7
+ # @return [TTY::Prompt] TTY::Prompt.
8
+ attr_writer :prompt
9
+
10
+ # Public: Errors.
11
+ #
12
+ # exception - StandardError.
13
+ #
14
+ # Returns nothing.
15
+ def errors(plugin_name, exception)
16
+ prompt.error "#{plugin_name.downcase.capitalize} errors"
17
+ prompt.warn exception.message
18
+ end
19
+
20
+ # Delegate.
21
+ #
22
+ # method - Method.
23
+ # args - Arguments.
24
+ # block - Block.
25
+ #
26
+ # Returns wathever.
27
+ def method_missing(method, *args, &block)
28
+ prompt.send(method, *args, &block)
29
+ end
30
+
31
+ # Public: TTY prompt.
32
+ #
33
+ # Returns ::TTY::Prompt instance.
34
+ def prompt
35
+ @prompt ||= ::TTY::Prompt.new
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,3 @@
1
1
  module Speedflow
2
- VERSION = '0.2.1'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/lib/speedflow.rb CHANGED
@@ -6,6 +6,7 @@ require 'safe_yaml/load'
6
6
  require_rel 'speedflow/*.rb'
7
7
  require_rel 'speedflow/core_ext/*.rb'
8
8
  require_rel 'speedflow/commands/*.rb'
9
+ require_rel 'speedflow/plugin/*.rb'
9
10
 
10
11
  # Speedflow core
11
12
  module Speedflow
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: speedflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Breux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-04 00:00:00.000000000 Z
11
+ date: 2016-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: require_all
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '4.2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '4.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: colorize
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +70,30 @@ dependencies:
70
70
  name: safe_yaml
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '1.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tty-prompt
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.5.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.5.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: speedflow-plugin-test
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -242,7 +256,10 @@ files:
242
256
  - lib/speedflow/core_ext/hash.rb
243
257
  - lib/speedflow/flow.rb
244
258
  - lib/speedflow/message.rb
245
- - lib/speedflow/plugin_manager.rb
259
+ - lib/speedflow/plugin/abstract.rb
260
+ - lib/speedflow/plugin/configuration.rb
261
+ - lib/speedflow/plugin/manager.rb
262
+ - lib/speedflow/plugin/prompt.rb
246
263
  - lib/speedflow/version.rb
247
264
  homepage: https://github.com/speedflow/speedflow
248
265
  licenses:
@@ -1,80 +0,0 @@
1
- module Speedflow
2
- # Used to manage the plugins
3
- class PluginManager
4
- include ActiveSupport::Inflector
5
- include Message
6
-
7
- PLUGIN_BASE = 'speedflow-plugin-'.freeze
8
-
9
- # Public: Constructor
10
- #
11
- # plugins - Array of plugins
12
- #
13
- # Examples
14
- #
15
- # PluginManager.new({})
16
- # # => <Speedflow::PluginManager>
17
- #
18
- # Returns an Arrays of plugins.
19
- def initialize(plugins = [])
20
- @plugins = plugins || []
21
- load_plugins
22
- end
23
-
24
- # Public: Load plugins
25
- #
26
- # Returns nothing.
27
- def load_plugins
28
- @plugins.each { |plugin| require_plugin(plugin) }
29
- end
30
-
31
- # Public: Require a plugins (from Gem)
32
- #
33
- # Returns nothing.
34
- def require_plugin(plugin)
35
- require plugin.downcase.prepend(PLUGIN_BASE)
36
- rescue LoadError
37
- message = "Unable to load plugin '#{plugin}'.\n"
38
- message << "Help: `gem install #{PLUGIN_BASE}#{plugin}`"
39
- raise PluginNotFound, message
40
- end
41
-
42
- # Call action from flow step.
43
- #
44
- # step - Hash from flow. {plugin: '', action: '', arguments: ''}.
45
- #
46
- # Returns nothing.
47
- def call_action_from_step(step)
48
- step['arguments'] ||= {}
49
- success "Run action '#{step['action']}' of '#{step['plugin']}' plugin."
50
- call_plugin_action(step['plugin'], step['action'], step['arguments'])
51
- end
52
-
53
- # Call plugin action.
54
- #
55
- # plugin - Plugin name.
56
- # action - Action name.
57
- # arguments - List of arguments
58
- #
59
- # Returns nothing.
60
- def call_plugin_action(plugin, action, arguments)
61
- action = underscore(action.prepend('action_'))
62
- module_name = plugin.downcase.capitalize.prepend('Speedflow::Plugin::')
63
- begin
64
- Kernel.const_get(module_name).send(action.to_s, arguments)
65
- rescue NoMethodError => exception
66
- message = "Unable to call action: #{module_name}.#{action}\n"
67
- message << exception.message
68
- raise PluginActionNotFound, message
69
- end
70
- end
71
- end
72
-
73
- # Plugin exception
74
- class PluginNotFound < Exception
75
- end
76
-
77
- # Plugin action exception
78
- class PluginActionNotFound < Exception
79
- end
80
- end