convoy 1.0.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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.irbrc +3 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +8 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +22 -0
  9. data/README.md +705 -0
  10. data/Rakefile +1 -0
  11. data/convoy.gemspec +24 -0
  12. data/examples/.my_apprc +24 -0
  13. data/examples/basic +10 -0
  14. data/examples/basic_config_file +16 -0
  15. data/examples/basic_conflicts +17 -0
  16. data/examples/basic_depends_on +25 -0
  17. data/examples/basic_flags +15 -0
  18. data/examples/basic_options +14 -0
  19. data/examples/basic_options_multi +15 -0
  20. data/examples/basic_require_arguments +17 -0
  21. data/examples/basic_texts +21 -0
  22. data/examples/basic_validations +21 -0
  23. data/examples/basic_with_everything +30 -0
  24. data/examples/commands/example_command.rb +13 -0
  25. data/examples/suite_complex +65 -0
  26. data/examples/suite_simple +19 -0
  27. data/examples/suite_with_sub_commands +94 -0
  28. data/lib/convoy.rb +83 -0
  29. data/lib/convoy/action_command/base.rb +85 -0
  30. data/lib/convoy/action_command/escort_utility_command.rb +53 -0
  31. data/lib/convoy/app.rb +127 -0
  32. data/lib/convoy/arguments.rb +20 -0
  33. data/lib/convoy/auto_options.rb +71 -0
  34. data/lib/convoy/error/error.rb +33 -0
  35. data/lib/convoy/formatter/command.rb +87 -0
  36. data/lib/convoy/formatter/commands.rb +37 -0
  37. data/lib/convoy/formatter/cursor_position.rb +29 -0
  38. data/lib/convoy/formatter/default_help_formatter.rb +117 -0
  39. data/lib/convoy/formatter/global_command.rb +17 -0
  40. data/lib/convoy/formatter/option.rb +152 -0
  41. data/lib/convoy/formatter/options.rb +28 -0
  42. data/lib/convoy/formatter/shell_command_executor.rb +49 -0
  43. data/lib/convoy/formatter/stream_output_formatter.rb +88 -0
  44. data/lib/convoy/formatter/string_grid.rb +108 -0
  45. data/lib/convoy/formatter/string_splitter.rb +50 -0
  46. data/lib/convoy/formatter/terminal.rb +30 -0
  47. data/lib/convoy/global_pre_parser.rb +43 -0
  48. data/lib/convoy/logger.rb +75 -0
  49. data/lib/convoy/option_dependency_validator.rb +82 -0
  50. data/lib/convoy/option_parser.rb +155 -0
  51. data/lib/convoy/setup/configuration/generator.rb +75 -0
  52. data/lib/convoy/setup/configuration/instance.rb +34 -0
  53. data/lib/convoy/setup/configuration/loader.rb +43 -0
  54. data/lib/convoy/setup/configuration/locator/base.rb +19 -0
  55. data/lib/convoy/setup/configuration/locator/chaining.rb +29 -0
  56. data/lib/convoy/setup/configuration/locator/descending_to_home.rb +23 -0
  57. data/lib/convoy/setup/configuration/locator/executing_script_directory.rb +15 -0
  58. data/lib/convoy/setup/configuration/locator/specified_directory.rb +21 -0
  59. data/lib/convoy/setup/configuration/merge_tool.rb +38 -0
  60. data/lib/convoy/setup/configuration/reader.rb +36 -0
  61. data/lib/convoy/setup/configuration/writer.rb +46 -0
  62. data/lib/convoy/setup/dsl/action.rb +17 -0
  63. data/lib/convoy/setup/dsl/command.rb +67 -0
  64. data/lib/convoy/setup/dsl/config_file.rb +13 -0
  65. data/lib/convoy/setup/dsl/global.rb +29 -0
  66. data/lib/convoy/setup/dsl/options.rb +81 -0
  67. data/lib/convoy/setup_accessor.rb +206 -0
  68. data/lib/convoy/trollop.rb +861 -0
  69. data/lib/convoy/utils.rb +21 -0
  70. data/lib/convoy/validator.rb +45 -0
  71. data/spec/integration/basic_config_file_spec.rb +126 -0
  72. data/spec/integration/basic_conflicts_spec.rb +47 -0
  73. data/spec/integration/basic_depends_on_spec.rb +275 -0
  74. data/spec/integration/basic_options_spec.rb +41 -0
  75. data/spec/integration/basic_options_with_multi_spec.rb +30 -0
  76. data/spec/integration/basic_spec.rb +38 -0
  77. data/spec/integration/basic_validations_spec.rb +77 -0
  78. data/spec/integration/basic_with_arguments_spec.rb +35 -0
  79. data/spec/integration/basic_with_text_fields_spec.rb +21 -0
  80. data/spec/integration/suite_simple_spec.rb +45 -0
  81. data/spec/integration/suite_sub_command_spec.rb +51 -0
  82. data/spec/lib/convoy/action_command/base_spec.rb +200 -0
  83. data/spec/lib/convoy/formatter/command_spec.rb +238 -0
  84. data/spec/lib/convoy/formatter/global_command_spec.rb +50 -0
  85. data/spec/lib/convoy/formatter/option_spec.rb +300 -0
  86. data/spec/lib/convoy/formatter/shell_command_executor_spec.rb +59 -0
  87. data/spec/lib/convoy/formatter/stream_output_formatter_spec.rb +214 -0
  88. data/spec/lib/convoy/formatter/string_grid_spec.rb +59 -0
  89. data/spec/lib/convoy/formatter/string_splitter_spec.rb +50 -0
  90. data/spec/lib/convoy/formatter/terminal_spec.rb +19 -0
  91. data/spec/lib/convoy/setup/configuration/generator_spec.rb +101 -0
  92. data/spec/lib/convoy/setup/configuration/loader_spec.rb +79 -0
  93. data/spec/lib/convoy/setup/configuration/locator/chaining_spec.rb +81 -0
  94. data/spec/lib/convoy/setup/configuration/locator/descending_to_home_spec.rb +57 -0
  95. data/spec/lib/convoy/setup/configuration/locator/executing_script_directory_spec.rb +29 -0
  96. data/spec/lib/convoy/setup/configuration/locator/specified_directory_spec.rb +33 -0
  97. data/spec/lib/convoy/setup/configuration/merge_tool_spec.rb +41 -0
  98. data/spec/lib/convoy/setup/configuration/reader_spec.rb +41 -0
  99. data/spec/lib/convoy/setup/configuration/writer_spec.rb +75 -0
  100. data/spec/lib/convoy/setup_accessor_spec.rb +226 -0
  101. data/spec/lib/convoy/utils_spec.rb +30 -0
  102. data/spec/spec_helper.rb +29 -0
  103. data/spec/support/integration_helpers.rb +2 -0
  104. data/spec/support/matchers/execute_action_for_command_matcher.rb +21 -0
  105. data/spec/support/matchers/execute_action_with_arguments_matcher.rb +25 -0
  106. data/spec/support/matchers/execute_action_with_options_matcher.rb +29 -0
  107. data/spec/support/matchers/exit_with_code_matcher.rb +29 -0
  108. data/spec/support/shared_contexts/integration_setup.rb +34 -0
  109. metadata +292 -0
data/lib/convoy.rb ADDED
@@ -0,0 +1,83 @@
1
+ autoload :Nesty, "nesty"
2
+
3
+ module Convoy
4
+ autoload :Trollop, "convoy/trollop"
5
+ autoload :Utils, "convoy/utils"
6
+ autoload :Arguments, "convoy/arguments"
7
+ autoload :Logger, "convoy/logger"
8
+ autoload :SetupAccessor, "convoy/setup_accessor"
9
+ autoload :OptionDependencyValidator, "convoy/option_dependency_validator"
10
+ autoload :Validator, "convoy/validator"
11
+ autoload :AutoOptions, "convoy/auto_options"
12
+ autoload :GlobalPreParser, "convoy/global_pre_parser"
13
+ autoload :OptionParser, "convoy/option_parser"
14
+ autoload :App, "convoy/app"
15
+
16
+ autoload :Error, "convoy/error/error"
17
+ autoload :BaseError, "convoy/error/error"
18
+ autoload :UserError, "convoy/error/error"
19
+ autoload :InternalError, "convoy/error/error"
20
+ autoload :ClientError, "convoy/error/error"
21
+ autoload :TransientError, "convoy/error/error"
22
+
23
+ module Formatter
24
+ autoload :Option, "convoy/formatter/option"
25
+ autoload :Options, "convoy/formatter/options"
26
+ autoload :Command, "convoy/formatter/command"
27
+ autoload :Commands, "convoy/formatter/commands"
28
+ autoload :GlobalCommand, "convoy/formatter/global_command"
29
+ autoload :ShellCommandExecutor, "convoy/formatter/shell_command_executor"
30
+ autoload :Terminal, "convoy/formatter/terminal"
31
+ autoload :StringSplitter, "convoy/formatter/string_splitter"
32
+ autoload :CursorPosition, "convoy/formatter/cursor_position"
33
+ autoload :StreamOutputFormatter, "convoy/formatter/stream_output_formatter"
34
+ autoload :StringGrid, "convoy/formatter/string_grid"
35
+ autoload :DefaultHelpFormatter, "convoy/formatter/default_help_formatter"
36
+ end
37
+
38
+ module Setup
39
+ module Dsl
40
+ autoload :Options, "convoy/setup/dsl/options"
41
+ autoload :Action, "convoy/setup/dsl/action"
42
+ autoload :Command, "convoy/setup/dsl/command"
43
+ autoload :ConfigFile, "convoy/setup/dsl/config_file"
44
+ autoload :Global, "convoy/setup/dsl/global"
45
+ end
46
+
47
+ module Configuration
48
+ module Locator
49
+ autoload :Base, "convoy/setup/configuration/locator/base"
50
+ autoload :DescendingToHome, "convoy/setup/configuration/locator/descending_to_home"
51
+ autoload :ExecutingScriptDirectory, "convoy/setup/configuration/locator/executing_script_directory"
52
+ autoload :SpecifiedDirectory, "convoy/setup/configuration/locator/specified_directory"
53
+ autoload :Chaining, "convoy/setup/configuration/locator/chaining"
54
+ end
55
+
56
+ autoload :MergeTool, "convoy/setup/configuration/merge_tool"
57
+ autoload :Instance, "convoy/setup/configuration/instance"
58
+ autoload :Reader, "convoy/setup/configuration/reader"
59
+ autoload :Writer, "convoy/setup/configuration/writer"
60
+ autoload :Generator, "convoy/setup/configuration/generator"
61
+ autoload :Loader, "convoy/setup/configuration/loader"
62
+ end
63
+ end
64
+
65
+ module ActionCommand
66
+ autoload :Base, "convoy/action_command/base"
67
+ autoload :ConvoyUtilityCommand, "convoy/action_command/convoy_utility_command"
68
+ end
69
+ end
70
+
71
+ at_exit do
72
+ Convoy::Logger.close
73
+ end
74
+
75
+ def error_logger
76
+ Convoy::Logger.error
77
+ end
78
+
79
+ def output_logger
80
+ Convoy::Logger.output
81
+ end
82
+
83
+
@@ -0,0 +1,85 @@
1
+ module Convoy
2
+ module ActionCommand
3
+ class Base
4
+ attr_reader :options, :arguments, :config
5
+
6
+ def initialize(options, arguments, config={})
7
+ @options = options
8
+ @arguments = arguments
9
+ @config = config
10
+ @command_context = nil
11
+ @command_options = nil
12
+ @parent_options = nil
13
+ @grandparent_options = nil
14
+ @global_options = nil
15
+ end
16
+
17
+ protected
18
+
19
+ def command_context
20
+ return @command_context if @command_context
21
+ @command_context = []
22
+ options[:global] ||= {}
23
+ current_command_hash = options[:global][:commands] || {}
24
+ until current_command_hash.keys.empty?
25
+ key = current_command_hash.keys.first
26
+ @command_context << key
27
+ current_command_hash = current_command_hash[key][:commands] || {}
28
+ end
29
+ @command_context
30
+ end
31
+
32
+ def command_name
33
+ command_context.last || :global
34
+ end
35
+
36
+ def command_options
37
+ @command_options ||= context_hash(command_context)[:options] || {}
38
+ end
39
+
40
+ def global_options
41
+ @global_options ||= (options[:global] || {})[:options] || {}
42
+ end
43
+
44
+ def parent_options
45
+ @parent_options ||= ensure_parent { |parent_context| context_hash(parent_context)[:options] || {} }
46
+ end
47
+
48
+ def grandparent_options
49
+ @grandparent_options ||= ensure_grandparent { |grandparent_context| context_hash(grandparent_context)[:options] || {} }
50
+ end
51
+
52
+ #generation_number 1 is parent, 2 is grandparent and so on
53
+ #default is 3 for great grandparent
54
+ def ancestor_options(generation_number = 3)
55
+ ensure_ancestor(generation_number) { |ancestor_context| context_hash(ancestor_context)[:options] || {} }
56
+ end
57
+
58
+ private
59
+
60
+ def context_hash(context)
61
+ context_hash = options[:global]
62
+ context.each do |command_name|
63
+ context_hash = context_hash[:commands][command_name]
64
+ end
65
+ context_hash
66
+ end
67
+
68
+ def ensure_parent(&block)
69
+ ensure_ancestor(1, &block)
70
+ end
71
+
72
+ def ensure_grandparent(&block)
73
+ ensure_ancestor(2, &block)
74
+ end
75
+
76
+ def ensure_ancestor(generation_number, &block)
77
+ return {} if generation_number < 0
78
+ #return {} if generation_number == 0
79
+ return {} unless command_context.size >= generation_number
80
+ ancestor_context = command_context.dup.slice(0, command_context.size - generation_number)
81
+ block.call(ancestor_context)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,53 @@
1
+ module Convoy
2
+ module ActionCommand
3
+ class ConvoyUtilityCommand < Base
4
+ attr_reader :setup
5
+
6
+ def initialize(setup, options, arguments, config = {})
7
+ super(options, arguments, config)
8
+ @setup = setup
9
+ end
10
+
11
+ def execute
12
+ current_command_options = command_options
13
+ if current_command_options[:create_config_given]
14
+ create_config(current_command_options[:create_config])
15
+ elsif current_command_options[:create_default_config_given]
16
+ create_default_config
17
+ elsif current_command_options[:update_config_given]
18
+ update_config(current_command_options[:update_config])
19
+ elsif current_command_options[:update_default_config_given]
20
+ update_default_config
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def create_config(path)
27
+ config_path = absolute_path(path)
28
+ Convoy::Setup::Configuration::Writer.new(config_path, Convoy::Setup::Configuration::Generator.new(setup).default_data).write
29
+ end
30
+
31
+ def create_default_config
32
+ Convoy::Setup::Configuration::Writer.new(default_config_path, Convoy::Setup::Configuration::Generator.new(setup).default_data).write
33
+ end
34
+
35
+ def update_config(path)
36
+ config_path = absolute_path(path)
37
+ Convoy::Setup::Configuration::Writer.new(config_path, Convoy::Setup::Configuration::Generator.new(setup).default_data).update
38
+ end
39
+
40
+ def update_default_config
41
+ Convoy::Setup::Configuration::Writer.new(default_config_path, Convoy::Setup::Configuration::Generator.new(setup).default_data).update
42
+ end
43
+
44
+ def absolute_path(path)
45
+ File.expand_path(path)
46
+ end
47
+
48
+ def default_config_path
49
+ Convoy::Setup::Configuration::Loader.new(setup, nil).default_config_path
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/convoy/app.rb ADDED
@@ -0,0 +1,127 @@
1
+ module Convoy
2
+ class App
3
+ #TODO ensure that every command must have an action
4
+ class << self
5
+ def create(option_string = '', &block)
6
+ self.new(option_string, &block).setup_application.execute
7
+ exit(0)
8
+ end
9
+ end
10
+
11
+ attr_reader :setup, :option_string
12
+
13
+ def initialize(option_string, &block)
14
+ @option_string = option_string
15
+ @setup = nil
16
+ @block = block
17
+ end
18
+
19
+ def setup_application
20
+ old_error_sev_threshold = error_logger.sev_threshold
21
+ begin
22
+ error_logger.sev_threshold = ::Logger::DEBUG
23
+ cli_app_configuration = Convoy::Setup::Dsl::Global.new(&@block)
24
+ @setup = Convoy::SetupAccessor.new(cli_app_configuration)
25
+ self
26
+ rescue => e
27
+ handle_convoy_error(e)
28
+ ensure
29
+ error_logger.sev_threshold = old_error_sev_threshold
30
+ end
31
+ end
32
+
33
+ def execute
34
+ begin
35
+ AutoOptions.augment(setup)
36
+
37
+ cli_options = current_cli_options(option_string)
38
+
39
+ auto_options = Convoy::GlobalPreParser.new(setup).parse(cli_options.dup)
40
+ Convoy::Logger.setup_error_logger(auto_options)
41
+
42
+ #now we can start doing error logging everything above here has to be rock solid
43
+
44
+ configuration = Convoy::Setup::Configuration::Loader.new(setup, auto_options).configuration
45
+
46
+ invoked_options, arguments = Convoy::OptionParser.new(configuration, setup).parse(cli_options)
47
+ context = context_from_options(invoked_options[:global])
48
+ action = setup.action_for(context)
49
+ current_command = context.empty? ? :global : context.last
50
+ raise Convoy::ClientError.new("No action defined for command '#{current_command}'") unless action
51
+ actual_arguments = Convoy::Arguments.read(arguments, setup.arguments_required_for(context))
52
+ rescue => e
53
+ handle_convoy_error(e)
54
+ end
55
+ execute_action(action, invoked_options, actual_arguments, configuration.user)
56
+ end
57
+
58
+ private
59
+
60
+ def current_cli_options(option_string)
61
+ passed_in_options = Convoy::Utils.tokenize_option_string(option_string)
62
+ passed_in_options.empty? ? ARGV.dup : passed_in_options
63
+ end
64
+
65
+ def execute_action(action, options, arguments, user_config)
66
+ begin
67
+ #execute before servants here
68
+ action.call(options, arguments, user_config)
69
+ #execute after servants here
70
+ rescue => e
71
+ handle_action_error(e)
72
+ end
73
+ end
74
+
75
+ def context_from_options(options)
76
+ commands_in_order(options)
77
+ end
78
+
79
+ def commands_in_order(options, commands = [])
80
+ if options[:commands].keys.empty?
81
+ commands
82
+ else
83
+ command = options[:commands].keys.first
84
+ commands << command
85
+ commands_in_order(options[:commands][command], commands)
86
+ end
87
+ end
88
+
89
+ def handle_convoy_error(e)
90
+ if e.kind_of?(Convoy::UserError)
91
+ print_stacktrace(e)
92
+ error_logger.debug {'Convoy app failed to execute successfully, due to user error'}
93
+ exit(Convoy::USER_ERROR_EXIT_CODE)
94
+ elsif e.kind_of?(Convoy::ClientError)
95
+ print_stacktrace(e)
96
+ error_logger.debug {'Convoy app failed to execute successfully, due to client setup error'}
97
+ exit(Convoy::CLIENT_ERROR_EXIT_CODE)
98
+ else
99
+ print_convoy_error_message(e)
100
+ error_logger.debug {'Convoy app failed to execute successfully, due to internal error'}
101
+ exit(Convoy::INTERNAL_ERROR_EXIT_CODE)
102
+ end
103
+ end
104
+
105
+ def handle_action_error(e)
106
+ if e.kind_of?(Convoy::Error)
107
+ print_convoy_error_message(e)
108
+ error_logger.debug {'Convoy app failed to execute successfully, due to internal error'}
109
+ exit(Convoy::INTERNAL_ERROR_EXIT_CODE)
110
+ else
111
+ print_stacktrace(e)
112
+ error_logger.debug {'Convoy app failed to execute successfully, due to unknown error'}
113
+ exit(Convoy::EXTERNAL_ERROR_EXIT_CODE)
114
+ end
115
+ end
116
+
117
+ def print_stacktrace(e)
118
+ error_logger.error { e.message }
119
+ error_logger.debug { e }
120
+ end
121
+
122
+ def print_convoy_error_message(e)
123
+ print_stacktrace(e)
124
+ error_logger.warn {"\n \x1B[48;5;196m ERROR \x1B[0m An internal Convoy error occurred.\n\n You should probably report it to \x1B[38;5;222mAlbert Rannetsperger\x1B[0m or create an issue on his \x1B[38;5;222mGitHub\x1B[0m page (https://github.com/alb3rtuk).\n Make sure to include the stacktrace above (although it probably won't be very helpful).bp\n\n"}
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,20 @@
1
+ require 'readline'
2
+
3
+ module Convoy
4
+ class Arguments
5
+ class << self
6
+ def read(arguments, requires_arguments=false)
7
+ if arguments.empty? && requires_arguments
8
+ while command = Readline.readline("> ", true)
9
+ arguments << command
10
+ end
11
+ arguments = arguments.compact.keep_if { |value| value.length > 0 }
12
+ if arguments.empty?
13
+ raise Convoy::UserError.new("You must provide some arguments to this script")
14
+ end
15
+ end
16
+ arguments
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,71 @@
1
+ module Convoy
2
+ class AutoOptions
3
+ class << self
4
+ def augment(setup)
5
+ if setup.has_config_file?
6
+ setup.add_global_option :config, "Configuration file to use for this execution", :short => :none, :long => '--config', :type => :string
7
+
8
+ setup.add_global_command :convoy, :aliases => [] do |command|
9
+ command.summary "Auto created utility command"
10
+ command.description "Auto created utility command"
11
+ command.requires_arguments false
12
+
13
+ command.options do |opts|
14
+ opts.opt :create_config, "Create configuration file at specified location", :short => :none, :long => '--create-config', :type => :string
15
+ opts.opt :create_default_config, "Create a default configuration file", :short => :none, :long => '--create-default-config', :type => :boolean, :default => false
16
+ opts.opt :update_config, "Update configuration file at specified location", :short => :none, :long => '--update-config', :type => :string
17
+ opts.opt :update_default_config, "Update the default configuration file", :short => :none, :long => '--update-default-config', :type => :boolean, :default => false
18
+
19
+ opts.conflict :create_config, :create_default_config, :update_config, :update_default_config
20
+ end
21
+
22
+ command.action do |options, arguments|
23
+ ActionCommand::ConvoyUtilityCommand.new(setup, options, arguments).execute
24
+ end
25
+ end
26
+ end
27
+ setup.add_global_option :verbosity, 'Verbosity level of output for current execution (e.g. INFO, DEBUG)', :short => :none, :long => '--verbosity', :type => :string, :default => 'WARN'
28
+ setup.add_global_option :error_output_format, 'The format to use when outputting errors (e.g. basic, advanced)', :short => :none, :long => '--error-output-format', :type => :string, :default => 'basic'
29
+ end
30
+ end
31
+
32
+ attr_reader :options
33
+
34
+ def initialize(options)
35
+ @options = options
36
+ end
37
+
38
+ def non_default_config_path
39
+ if options[:config_given] && File.exists?(config_path)
40
+ config_path
41
+ elsif !options[:config_given]
42
+ nil
43
+ else
44
+ error_logger.warn "The given config file '#{options[:config]}' does not exist, falling back to default"
45
+ nil
46
+ end
47
+ end
48
+
49
+ def verbosity
50
+ error_verbosity.upcase
51
+ end
52
+
53
+ def error_formatter
54
+ error_output_format.to_sym
55
+ end
56
+
57
+ private
58
+
59
+ def config_path
60
+ File.expand_path(options[:config])
61
+ end
62
+
63
+ def error_output_format
64
+ options[:error_output_format]
65
+ end
66
+
67
+ def error_verbosity
68
+ options[:verbosity]
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,33 @@
1
+ module Convoy
2
+ INTERNAL_ERROR_EXIT_CODE = 1
3
+ CLIENT_ERROR_EXIT_CODE = 2
4
+ USER_ERROR_EXIT_CODE = 3
5
+ EXTERNAL_ERROR_EXIT_CODE = 10
6
+
7
+ #module to tag all exceptions coming out of Convoy with
8
+ module Error
9
+ end
10
+
11
+ #all our exceptions will supported nesting other exceptions
12
+ #also all our exception will be a kind_of? Convoy::Error
13
+ class BaseError < StandardError
14
+ include Nesty::NestedError
15
+ include Error
16
+ end
17
+
18
+ #user did something invalid
19
+ class UserError < BaseError
20
+ end
21
+
22
+ #for errors with convoy itself
23
+ class InternalError < BaseError
24
+ end
25
+
26
+ #for errors with how convoy is being used
27
+ class ClientError < BaseError
28
+ end
29
+
30
+ #a dependency is temporarily unavailable
31
+ class TransientError < BaseError
32
+ end
33
+ end