cuprum-cli 0.1.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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +34 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/LICENSE +21 -0
  5. data/README.md +163 -0
  6. data/lib/cuprum/cli/argument.rb +172 -0
  7. data/lib/cuprum/cli/arguments/class_methods.rb +283 -0
  8. data/lib/cuprum/cli/arguments.rb +16 -0
  9. data/lib/cuprum/cli/coercion.rb +131 -0
  10. data/lib/cuprum/cli/command.rb +102 -0
  11. data/lib/cuprum/cli/commands/ci/report.rb +121 -0
  12. data/lib/cuprum/cli/commands/ci/rspec_command.rb +108 -0
  13. data/lib/cuprum/cli/commands/ci/rspec_each_command.rb +185 -0
  14. data/lib/cuprum/cli/commands/ci.rb +12 -0
  15. data/lib/cuprum/cli/commands/echo_command.rb +76 -0
  16. data/lib/cuprum/cli/commands/file/generate_file.rb +141 -0
  17. data/lib/cuprum/cli/commands/file/new_command.rb +86 -0
  18. data/lib/cuprum/cli/commands/file/render_erb.rb +88 -0
  19. data/lib/cuprum/cli/commands/file/resolve_template.rb +136 -0
  20. data/lib/cuprum/cli/commands/file/templates/rspec.rb.erb +14 -0
  21. data/lib/cuprum/cli/commands/file/templates/ruby.rb.erb +29 -0
  22. data/lib/cuprum/cli/commands/file/templates.rb +71 -0
  23. data/lib/cuprum/cli/commands/file.rb +14 -0
  24. data/lib/cuprum/cli/commands.rb +12 -0
  25. data/lib/cuprum/cli/dependencies/file_system/mock.rb +297 -0
  26. data/lib/cuprum/cli/dependencies/file_system.rb +247 -0
  27. data/lib/cuprum/cli/dependencies/standard_io/helpers.rb +138 -0
  28. data/lib/cuprum/cli/dependencies/standard_io/mock.rb +85 -0
  29. data/lib/cuprum/cli/dependencies/standard_io.rb +110 -0
  30. data/lib/cuprum/cli/dependencies/system_command/mock.rb +57 -0
  31. data/lib/cuprum/cli/dependencies/system_command.rb +147 -0
  32. data/lib/cuprum/cli/dependencies.rb +25 -0
  33. data/lib/cuprum/cli/errors/files/file_not_writeable.rb +42 -0
  34. data/lib/cuprum/cli/errors/files/missing_parameter.rb +71 -0
  35. data/lib/cuprum/cli/errors/files/missing_template.rb +36 -0
  36. data/lib/cuprum/cli/errors/files/template_error.rb +37 -0
  37. data/lib/cuprum/cli/errors/files/template_not_resolved.rb +54 -0
  38. data/lib/cuprum/cli/errors/files.rb +19 -0
  39. data/lib/cuprum/cli/errors/system_command_failure.rb +44 -0
  40. data/lib/cuprum/cli/errors.rb +11 -0
  41. data/lib/cuprum/cli/integrations/thor/arguments_parser.rb +99 -0
  42. data/lib/cuprum/cli/integrations/thor/registry.rb +42 -0
  43. data/lib/cuprum/cli/integrations/thor/task.rb +211 -0
  44. data/lib/cuprum/cli/integrations/thor.rb +14 -0
  45. data/lib/cuprum/cli/integrations.rb +8 -0
  46. data/lib/cuprum/cli/metadata.rb +215 -0
  47. data/lib/cuprum/cli/option.rb +165 -0
  48. data/lib/cuprum/cli/options/class_methods.rb +232 -0
  49. data/lib/cuprum/cli/options/quiet.rb +32 -0
  50. data/lib/cuprum/cli/options/verbose.rb +32 -0
  51. data/lib/cuprum/cli/options.rb +18 -0
  52. data/lib/cuprum/cli/registry.rb +141 -0
  53. data/lib/cuprum/cli/rspec/deferred/arguments_examples.rb +203 -0
  54. data/lib/cuprum/cli/rspec/deferred/ci/report_examples.rb +450 -0
  55. data/lib/cuprum/cli/rspec/deferred/ci.rb +8 -0
  56. data/lib/cuprum/cli/rspec/deferred/dependencies/file_system_examples.rb +1469 -0
  57. data/lib/cuprum/cli/rspec/deferred/dependencies.rb +8 -0
  58. data/lib/cuprum/cli/rspec/deferred/metadata_examples.rb +856 -0
  59. data/lib/cuprum/cli/rspec/deferred/options_examples.rb +234 -0
  60. data/lib/cuprum/cli/rspec/deferred/registry_examples.rb +451 -0
  61. data/lib/cuprum/cli/rspec/deferred.rb +8 -0
  62. data/lib/cuprum/cli/rspec.rb +8 -0
  63. data/lib/cuprum/cli/version.rb +59 -0
  64. data/lib/cuprum/cli.rb +47 -0
  65. metadata +173 -0
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+
5
+ require 'cuprum/cli/dependencies/standard_io'
6
+
7
+ module Cuprum::Cli::Dependencies
8
+ # Mock implementation of StandardIo for testing purposes.
9
+ class StandardIo::Mock < Cuprum::Cli::Dependencies::StandardIo
10
+ # @overload append_for_read(*messages, io:)
11
+ # Utility method for appending readable data to a StringIO stream.
12
+ #
13
+ # @param messages [Array<String>] the messages to append. Will be appended
14
+ # to the stream in the provided order.
15
+ # @param io [IO] the io stream to append.
16
+ #
17
+ # @return [IO] the io stream.
18
+ def self.append_for_read(*messages, io:)
19
+ total_length = 0
20
+
21
+ messages.each do |message|
22
+ message += "\n" unless message.end_with?("\n")
23
+
24
+ io.print(message)
25
+
26
+ total_length += message.length
27
+ end
28
+
29
+ io.pos -= total_length
30
+
31
+ io
32
+ end
33
+
34
+ # @param error_stream [IO] the error stream. Defaults to an instance of
35
+ # StringIO.
36
+ # @param input_stream [IO] the input stream. Defaults to an instance of
37
+ # StringIO.
38
+ # @param output_stream [IO] the output stream. Defaulst to an instance of
39
+ # StringIO.
40
+ def initialize(
41
+ error_stream: StringIO.new,
42
+ input_stream: StringIO.new,
43
+ output_stream: StringIO.new
44
+ )
45
+ super
46
+
47
+ @combined_stream = StringIO.new
48
+ end
49
+
50
+ # @return [IO] a combined input/output stream representing all IO activity.
51
+ attr_reader :combined_stream
52
+
53
+ # @return [IO] the error stream
54
+ def error_stream = super # rubocop:disable Lint/UselessMethodDefinition
55
+
56
+ # @return [IO] the input stream.
57
+ def input_stream = super # rubocop:disable Lint/UselessMethodDefinition
58
+
59
+ # @return [IO] the output stream.
60
+ def output_stream = super # rubocop:disable Lint/UselessMethodDefinition
61
+
62
+ # (see Cuprum::Cli::Dependencies::StandardIo#read_input)
63
+ def read_input
64
+ message = super
65
+
66
+ combined_stream.print(message) if message
67
+
68
+ message
69
+ end
70
+
71
+ # (see Cuprum::Cli::Dependencies::StandardIo#write_output)
72
+ def write_output(message = nil, newline: true)
73
+ super
74
+
75
+ newline ? combined_stream.puts(message) : combined_stream.print(message)
76
+ end
77
+
78
+ # (see Cuprum::Cli::Dependencies::StandardIo#write_error)
79
+ def write_error(message = nil, newline: true)
80
+ super
81
+
82
+ newline ? combined_stream.puts(message) : combined_stream.print(message)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/dependencies'
4
+
5
+ module Cuprum::Cli::Dependencies
6
+ # Utility wrapping standard input, output, and error IO streams.
7
+ class StandardIo
8
+ autoload :Helpers, 'cuprum/cli/dependencies/standard_io/helpers'
9
+ autoload :Mock, 'cuprum/cli/dependencies/standard_io/mock'
10
+
11
+ ANSI_COLORS = {
12
+ 'black' => 0,
13
+ 'blue' => 34,
14
+ 'green' => 32,
15
+ 'purple' => 35,
16
+ 'red' => 31,
17
+ 'yellow' => 33
18
+ }.freeze
19
+ private_constant :ANSI_COLORS
20
+
21
+ # @param error_stream [IO] the error stream. Defaults to $stderr.
22
+ # @param input_stream [IO] the input stream. Defaults to $stdin.
23
+ # @param output_stream [IO] the output stream. Defaulst to $stdout.
24
+ def initialize(
25
+ error_stream: -> { $stderr },
26
+ input_stream: -> { $stdin },
27
+ output_stream: -> { $stdout }
28
+ )
29
+ @lazy_error_stream = error_stream
30
+ @lazy_input_stream = input_stream
31
+ @lazy_output_stream = output_stream
32
+ end
33
+
34
+ # Wraps the text in an ANSI color escape code.
35
+ #
36
+ # @param text [String] the text to colorize.
37
+ # @param color [String] the color to apply.
38
+ #
39
+ # @return [String] the colorized string.
40
+ #
41
+ # @raise [KeyError] if the requested color does not have an escape code.
42
+ def color(text, color)
43
+ color_code = ANSI_COLORS.fetch(color.to_s)
44
+
45
+ "\e[#{color_code}m#{text}\e[0m"
46
+ end
47
+
48
+ # Requests a newline-terminated string from the input stream.
49
+ #
50
+ # @return [String] the returned input string.
51
+ def read_input
52
+ input_stream.gets
53
+ end
54
+
55
+ # Writes the given message to the error stream.
56
+ #
57
+ # If no error message is given, prints a newline only.
58
+ #
59
+ # @param message [String, nil] the message to write.
60
+ # @param newline [true, false] if true, appends a newline to the message if
61
+ # it does not have a newline. Defaults to true.
62
+ #
63
+ # @return [nil]
64
+ def write_error(message = nil, newline: true)
65
+ newline ? error_stream.puts(message) : error_stream.print(message)
66
+ end
67
+
68
+ # Writes the given message to the output stream.
69
+ #
70
+ # If no message is given, prints a newline only.
71
+ #
72
+ # @param message [String, nil] the message to write.
73
+ # @param newline [true, false] if true, appends a newline to the message if
74
+ # it does not have a newline. Defaults to true.
75
+ #
76
+ # @return [nil]
77
+ def write_output(message = nil, newline: true)
78
+ newline ? output_stream.puts(message) : output_stream.print(message)
79
+ end
80
+
81
+ private
82
+
83
+ def error_stream
84
+ @error_stream ||=
85
+ if @lazy_error_stream.is_a?(Proc)
86
+ @lazy_error_stream.call
87
+ else
88
+ @lazy_error_stream
89
+ end
90
+ end
91
+
92
+ def input_stream
93
+ @input_stream ||=
94
+ if @lazy_input_stream.is_a?(Proc)
95
+ @lazy_input_stream.call
96
+ else
97
+ @lazy_input_stream
98
+ end
99
+ end
100
+
101
+ def output_stream
102
+ @output_stream ||=
103
+ if @lazy_output_stream.is_a?(Proc)
104
+ @lazy_output_stream.call
105
+ else
106
+ @lazy_output_stream
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/dependencies/system_command'
4
+
5
+ module Cuprum::Cli::Dependencies
6
+ # Mock implementation of SystemCommand for testing purposes.
7
+ class SystemCommand::Mock < Cuprum::Cli::Dependencies::SystemCommand
8
+ # Data class providing a mock implementation of Process::Status.
9
+ MockStatus = Data.define(:exitstatus) do
10
+ # @return [true, false] true if the exit status is zero, otherwise false.
11
+ def success? = exitstatus.zero?
12
+ end
13
+
14
+ # @param captures [Hash{String => Proc, Array[String, String, Integer]}]
15
+ # the captured values to return. If the captures Hash has a key matching
16
+ # the command, that value will be used to generate the result.
17
+ def initialize(captures: {})
18
+ super()
19
+
20
+ @captures = captures
21
+ @recorded_commands = []
22
+ end
23
+
24
+ # @return [Array<String>] the commands recorded by the mock service.
25
+ attr_reader :recorded_commands
26
+
27
+ private
28
+
29
+ attr_reader :captures
30
+
31
+ def capture_command(command, **rest)
32
+ recorded_commands << build_command(command, **rest)
33
+
34
+ output, error, exitstatus =
35
+ captures
36
+ .fetch(command, ['', '', 0])
37
+ .then { |capture| capture.is_a?(Proc) ? capture.call(**rest) : capture }
38
+
39
+ CapturedOutput.new(
40
+ output:,
41
+ error:,
42
+ status: MockStatus.new(exitstatus:)
43
+ )
44
+ end
45
+
46
+ def spawn_command(command, **rest)
47
+ recorded_commands << build_command(command, **rest)
48
+
49
+ _, _, exitstatus =
50
+ captures
51
+ .fetch(command, ['', '', 0])
52
+ .then { |capture| capture.is_a?(Proc) ? capture.call(**rest) : capture }
53
+
54
+ MockStatus.new(exitstatus:)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ require 'cuprum/cli/dependencies'
6
+ require 'cuprum/cli/errors/system_command_failure'
7
+
8
+ module Cuprum::Cli::Dependencies
9
+ # Utility wrapper for running system command and capturing output.
10
+ class SystemCommand
11
+ autoload :Mock, 'cuprum/cli/dependencies/system_command/mock'
12
+
13
+ # Data object representing the captured output and status of a process.
14
+ CapturedOutput = Data.define(:error, :output, :status) do
15
+ # @return [true, false] true if the process was successful, otherwise
16
+ # false.
17
+ def success? = status.success?
18
+ end
19
+
20
+ # @overload capture(command,.arguments: [], environment: {}, options: {})
21
+ # Executes the system command and returns the captured output.
22
+ #
23
+ # @param command [String] the command to run.
24
+ # @param arguments [Array<String>] command-line flags or arguments to pass
25
+ # to the command.
26
+ # @param enviroment [Hash<String, Object>] environment variables to set
27
+ # for the command.
28
+ # @param options [Hash<String, Object>] command line options and values to
29
+ # pass to the command.
30
+ #
31
+ # @return [Cuprum::Result<Cuprum::Cli::Dependencies::SystemCommand::CapturedOutput>]
32
+ # a Result wrapping the process status and captured output. The Result
33
+ # will have a status of :success if the process ran successfully;
34
+ # otherwise, the Result will have a status of :failure
35
+ def capture(command, **)
36
+ value = capture_command(command, **)
37
+
38
+ return Cuprum::Result.new(value:) if value.success?
39
+
40
+ error = Cuprum::Cli::Errors::SystemCommandFailure.new(
41
+ command:,
42
+ details: value.error,
43
+ exit_status: value.status.exitstatus
44
+ )
45
+
46
+ Cuprum::Result.new(error:, value:)
47
+ end
48
+
49
+ # @overload spawn(command, arguments: [], enviroment:, options: {})
50
+ # Spawns a process to run the system command.
51
+ #
52
+ # @param command [String] the command to run.
53
+ # @param arguments [Array<String>] command-line flags or arguments to pass
54
+ # to the command.
55
+ # @param enviroment [Hash<String, Object>] environment variables to set
56
+ # for the command.
57
+ # @param options [Hash<String, Object>] command line options and values to
58
+ # pass to the command.
59
+ #
60
+ # @return [Cuprum::Result<nil>] a result with status :success if the
61
+ # process ran successfully; otherwise, a result with status :failure and
62
+ # an Error.
63
+ def spawn(command, **)
64
+ status = spawn_command(command, **)
65
+
66
+ return Cuprum::Result.new if status.success?
67
+
68
+ error = Cuprum::Cli::Errors::SystemCommandFailure.new(
69
+ command:,
70
+ exit_status: status.exitstatus
71
+ )
72
+
73
+ Cuprum::Result.new(error:)
74
+ end
75
+
76
+ private
77
+
78
+ def blank?(value)
79
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
80
+ end
81
+
82
+ def build_command(command, arguments: nil, environment: nil, options: nil)
83
+ # @todo [RUBY_VERSION <= '3.3'] remove || {} fallbacks.
84
+ [
85
+ format_environment(**(environment || {})),
86
+ command,
87
+ format_arguments(*arguments),
88
+ format_options(**(options || {}))
89
+ ]
90
+ .reject { |value| value.nil? || value.empty? }
91
+ .join(' ')
92
+ end
93
+
94
+ def capture_command(command, **)
95
+ command = build_command(command, **)
96
+
97
+ output, error, status = Open3.capture3(command)
98
+
99
+ CapturedOutput.new(output:, error:, status:)
100
+ end
101
+
102
+ def format_arguments(*arguments)
103
+ arguments.join(' ')
104
+ end
105
+
106
+ def format_environment(**environment)
107
+ environment
108
+ .reject { |_, value| blank?(value) }
109
+ .map do |key, value|
110
+ key = tools.string_tools.underscore(key.to_s).upcase
111
+
112
+ "#{key}=#{value.inspect}"
113
+ end
114
+ .join(' ')
115
+ end
116
+
117
+ def format_options(**options) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
118
+ options
119
+ .reject { |_, value| blank?(value) }
120
+ .map do |key, value|
121
+ next if value.nil? || (value.respond_to?(:empty?) && value.empty?)
122
+
123
+ key = key.to_s
124
+ value = value.inspect
125
+
126
+ next "#{key}=#{value}" if key.start_with?('-')
127
+
128
+ key = tools.string_tools.underscore(key).tr('_', '-')
129
+
130
+ "#{key.length == 1 ? '-' : '--'}#{key}=#{value}"
131
+ end
132
+ .join(' ')
133
+ end
134
+
135
+ def spawn_command(command, **)
136
+ command = build_command(command, **)
137
+ pid = Process.spawn(command)
138
+ _, status = Process.wait2(pid)
139
+
140
+ status
141
+ end
142
+
143
+ def tools
144
+ SleepingKingStudios::Tools::Toolbelt.instance
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'plumbum'
4
+
5
+ require 'cuprum/cli'
6
+
7
+ module Cuprum::Cli
8
+ # Dependencies provide standard functionality to commands.
9
+ module Dependencies
10
+ autoload :FileSystem, 'cuprum/cli/dependencies/file_system'
11
+ autoload :StandardIo, 'cuprum/cli/dependencies/standard_io'
12
+ autoload :SystemCommand, 'cuprum/cli/dependencies/system_command'
13
+
14
+ # @return [Plumbum::Provider] the provider for the standard dependencies.
15
+ def self.provider
16
+ @provider ||= Plumbum::ManyProvider.new(
17
+ values: {
18
+ file_system: FileSystem.new,
19
+ standard_io: StandardIo.new,
20
+ system_command: SystemCommand.new
21
+ }
22
+ )
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/error'
4
+
5
+ require 'cuprum/cli/errors/files'
6
+
7
+ module Cuprum::Cli::Errors::Files
8
+ # Error returned when attempting to generate a file in an invalid location.
9
+ class FileNotWriteable < Cuprum::Error
10
+ # Short string used to identify the type of error.
11
+ TYPE = 'cuprum.cli.errors.files.file_not_writeable'
12
+
13
+ # @param file_path [String] the path to the expected file.
14
+ # @param message [String] message describing the nature of the error.
15
+ # @param reason [String] additional details on the error.
16
+ def initialize(file_path:, message: nil, reason: nil)
17
+ @file_path = file_path
18
+ @reason = reason
19
+ message = default_message(file_path:, message:, reason:)
20
+
21
+ super
22
+ end
23
+
24
+ # @return [String] the path to the expected file.
25
+ attr_reader :file_path
26
+
27
+ # @return [String] additional details on the error.
28
+ attr_reader :reason
29
+
30
+ private
31
+
32
+ def as_json_data = { 'file_path' => file_path, 'reason' => reason }.compact
33
+
34
+ def default_message(file_path:, message:, reason:)
35
+ message ||= "unable to write file #{file_path}"
36
+
37
+ return message unless reason
38
+
39
+ "#{message} - #{reason}"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/errors/files'
4
+ require 'cuprum/cli/errors/files/template_error'
5
+
6
+ module Cuprum::Cli::Errors::Files
7
+ # Error returned when a required parameter is missing when rendering content.
8
+ class MissingParameter < Cuprum::Cli::Errors::Files::TemplateError
9
+ # Short string used to identify the type of error.
10
+ TYPE = 'cuprum.cli.errors.files.missing_parameter'
11
+
12
+ # @param parameter_name [String, Symbol] the name of the missing parameter.
13
+ # @param details [String] additional information about the error.
14
+ # @param format [String] the content format.
15
+ # @param message [String] an optional message to display.
16
+ # @param template_name [String] the name of the rendered content, if any,
17
+ def initialize(
18
+ parameter_name:,
19
+ details: nil,
20
+ format: nil,
21
+ message: nil,
22
+ template_name: nil
23
+ )
24
+ @parameter_name = parameter_name
25
+ @format = format
26
+ @template_name = template_name
27
+
28
+ super(
29
+ details:,
30
+ format:,
31
+ message: default_message(message),
32
+ parameter_name:,
33
+ template_name:
34
+ )
35
+ end
36
+
37
+ # @return [String] the content format.
38
+ attr_reader :format
39
+
40
+ # @return [String, Symbol] the name of the missing parameter.
41
+ attr_reader :parameter_name
42
+
43
+ private
44
+
45
+ def as_json_data
46
+ super.merge(
47
+ 'format' => format,
48
+ 'parameter_name' => parameter_name.to_s
49
+ ).compact
50
+ end
51
+
52
+ def default_message(message)
53
+ str = "missing parameter #{parameter_name.inspect}"
54
+
55
+ if template_name?
56
+ str = "#{str} for template #{template_name}"
57
+ str = "#{str} with format #{format}" if format?
58
+ elsif format?
59
+ str = "#{str} for #{format} template"
60
+ end
61
+
62
+ return str unless message && !message.empty?
63
+
64
+ "#{message} - #{str}"
65
+ end
66
+
67
+ def format? = format && !format.empty?
68
+
69
+ def template_name? = template_name && !template_name.empty?
70
+ end
71
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/error'
4
+
5
+ require 'cuprum/cli/errors/files'
6
+
7
+ module Cuprum::Cli::Errors::Files
8
+ # Error returned when unable to load a template.
9
+ class MissingTemplate < Cuprum::Error
10
+ # Short string used to identify the type of error.
11
+ TYPE = 'cuprum.cli.errors.files.missing_template'
12
+
13
+ # @param template_path [String] the expected template path.
14
+ # @param message [String] an optional message to display.
15
+ def initialize(template_path:, message: nil)
16
+ @template_path = template_path
17
+
18
+ super(message: default_message(message), template_path:)
19
+ end
20
+
21
+ # @return [String] the expected template path.
22
+ attr_reader :template_path
23
+
24
+ private
25
+
26
+ def as_json_data = { 'template_path' => template_path }
27
+
28
+ def default_message(message)
29
+ str = "unable to load template #{template_path}"
30
+
31
+ return str unless message && !message.empty?
32
+
33
+ "#{message} - #{str}"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/error'
4
+
5
+ require 'cuprum/cli/errors/files'
6
+
7
+ module Cuprum::Cli::Errors::Files
8
+ # Error returned when an error occurs when generating templated content.
9
+ class TemplateError < Cuprum::Error
10
+ # Short string used to identify the type of error.
11
+ TYPE = 'cuprum.cli.errors.files.template_error'
12
+
13
+ # @param message [String] message describing the nature of the error.
14
+ # @param details [String] additional information about the error.
15
+ # @param template_name [String] the name of the rendered content, if any,
16
+ def initialize(message:, details: nil, template_name: nil, **)
17
+ @details = details
18
+ @template_name = template_name
19
+
20
+ super
21
+ end
22
+
23
+ # @return [String] additional information about the error.
24
+ attr_reader :details
25
+
26
+ # @return [String] the name of the rendered content, if any,
27
+ attr_reader :template_name
28
+
29
+ private
30
+
31
+ def as_json_data
32
+ super
33
+ .merge('details' => details, 'template_name' => template_name)
34
+ .compact
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/errors/files'
4
+ require 'cuprum/cli/errors/files/template_error'
5
+
6
+ module Cuprum::Cli::Errors::Files
7
+ # Error returned when unable to resolve a template for a templated file.
8
+ class TemplateNotResolved < Cuprum::Cli::Errors::Files::TemplateError
9
+ # Short string used to identify the type of error.
10
+ TYPE = 'cuprum.cli.errors.files.template_not_resolved'
11
+
12
+ # @param file_path [String] the file path for the templated file.
13
+ # @param details [String] additional information about the error.
14
+ # @param message [String] an optional message to display.
15
+ # @param options [Hash] options used when attempting to resolve the
16
+ # template.
17
+ def initialize(file_path:, details: nil, message: nil, options: {})
18
+ @file_path = file_path
19
+ @options = options
20
+
21
+ super(details:, file_path:, message: default_message(message), options:)
22
+ end
23
+
24
+ # @return [String] the file path for the templated file.
25
+ attr_reader :file_path
26
+
27
+ # @return [Hash] options used when attempting to resolve the template.
28
+ attr_reader :options
29
+
30
+ private
31
+
32
+ def as_json_data
33
+ hsh = super
34
+
35
+ hsh['file_path'] = file_path
36
+ hsh['options'] = options.transform_keys(&:to_s) unless options.empty?
37
+
38
+ hsh
39
+ end
40
+
41
+ def default_message(message)
42
+ str = "unable to resolve template for file #{file_path}"
43
+ str = "#{str} with options" unless options.empty?
44
+
45
+ options.each.with_index do |(key, value), index|
46
+ str += "#{',' unless index.zero?} #{key}: #{value.inspect}"
47
+ end
48
+
49
+ return str unless message && !message.empty?
50
+
51
+ "#{str} - #{message}"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/errors'
4
+
5
+ module Cuprum::Cli::Errors
6
+ # Namespace for errors returned when creating or managing files.
7
+ module Files
8
+ autoload :FileNotWriteable,
9
+ 'cuprum/cli/errors/files/file_not_writeable'
10
+ autoload :MissingParameter,
11
+ 'cuprum/cli/errors/files/missing_parameter'
12
+ autoload :MissingTemplate,
13
+ 'cuprum/cli/errors/files/missing_template'
14
+ autoload :TemplateError,
15
+ 'cuprum/cli/errors/files/template_error'
16
+ autoload :TemplateNotResolved,
17
+ 'cuprum/cli/errors/files/template_not_resolved'
18
+ end
19
+ end