dev_suite 0.2.10 → 0.2.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +49 -7
- data/Gemfile +4 -0
- data/Gemfile.lock +14 -1
- data/README.md +4 -0
- data/examples/setup.rb +3 -0
- data/examples/workflow/conditional_workflow.rb +1 -1
- data/examples/workflow/full_workflow.rb +2 -2
- data/examples/workflow/loop_workflow.rb +1 -1
- data/examples/workflow/order_processing_workflow.rb +13 -11
- data/lib/dev_suite/method_tracer/logger.rb +52 -21
- data/lib/dev_suite/utils/color/colorizer.rb +1 -1
- data/lib/dev_suite/utils/color/palette/default.rb +33 -0
- data/lib/dev_suite/utils/construct/component/manager.rb +6 -1
- data/lib/dev_suite/utils/data/path_access/data_traverser.rb +86 -0
- data/lib/dev_suite/utils/data/path_access/errors.rb +12 -0
- data/lib/dev_suite/utils/data/path_access/key_handler.rb +27 -0
- data/lib/dev_suite/utils/data/path_access/path_accessor.rb +36 -0
- data/lib/dev_suite/utils/data/path_access/path_parser.rb +35 -0
- data/lib/dev_suite/utils/data/path_access.rb +5 -151
- data/lib/dev_suite/utils/file_writer/file_writer.rb +14 -4
- data/lib/dev_suite/utils/file_writer/writer/base.rb +40 -15
- data/lib/dev_suite/utils/file_writer/writer/json.rb +1 -1
- data/lib/dev_suite/utils/file_writer/writer/text.rb +11 -9
- data/lib/dev_suite/utils/file_writer/writer/yaml.rb +1 -1
- data/lib/dev_suite/utils/file_writer/writer_manager.rb +40 -17
- data/lib/dev_suite/utils/logger/base.rb +54 -0
- data/lib/dev_suite/utils/logger/emoji.rb +17 -0
- data/lib/dev_suite/utils/logger/errors.rb +9 -0
- data/lib/dev_suite/utils/logger/formatter.rb +41 -0
- data/lib/dev_suite/utils/logger/logger.rb +29 -0
- data/lib/dev_suite/utils/logger.rb +1 -52
- data/lib/dev_suite/utils/store/store.rb +3 -1
- data/lib/dev_suite/utils/table/renderer/simple.rb +5 -5
- data/lib/dev_suite/version.rb +1 -1
- metadata +13 -2
@@ -4,167 +4,21 @@ module DevSuite
|
|
4
4
|
module Utils
|
5
5
|
module Data
|
6
6
|
module PathAccess
|
7
|
+
require_relative "path_access/path_accessor"
|
8
|
+
|
7
9
|
# Fetch value from a nested structure using a path
|
8
10
|
def get_value_by_path(data, path)
|
9
|
-
|
10
|
-
traverse_path_for_get(data, keys)
|
11
|
+
PathAccessor.get(data, path)
|
11
12
|
end
|
12
13
|
|
13
14
|
# Set value in a nested structure using a path
|
14
15
|
def set_value_by_path(data, path, value)
|
15
|
-
|
16
|
-
last_key = keys.pop
|
17
|
-
target = traverse_path_for_set(data, keys)
|
18
|
-
|
19
|
-
set_final_value(target, last_key, value)
|
16
|
+
PathAccessor.set(data, path, value)
|
20
17
|
end
|
21
18
|
|
22
19
|
# Delete a key from a nested structure using a path
|
23
20
|
def delete_key_by_path(data, path)
|
24
|
-
|
25
|
-
last_key = keys.pop
|
26
|
-
target = traverse_path_for_delete(data, keys)
|
27
|
-
|
28
|
-
delete_final_key(target, last_key)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
# Parse the path into an array of keys/symbols/integers
|
34
|
-
def parse_path(path)
|
35
|
-
return path if path.is_a?(Array)
|
36
|
-
return [path] if single_symbol_path?(path)
|
37
|
-
|
38
|
-
parse_symbol_or_string_path(path)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Check if the path is a symbol without dots
|
42
|
-
def single_symbol_path?(path)
|
43
|
-
path.is_a?(Symbol) && !path.to_s.include?(".")
|
44
|
-
end
|
45
|
-
|
46
|
-
# Parse a symbol or string path into an array of keys
|
47
|
-
def parse_symbol_or_string_path(path)
|
48
|
-
if path.is_a?(Symbol)
|
49
|
-
parse_symbol_path(path)
|
50
|
-
else
|
51
|
-
parse_string_path(path)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Parse a symbol path that contains dots (e.g., :"test.1")
|
56
|
-
def parse_symbol_path(path)
|
57
|
-
path.to_s.split(".").map { |part| parse_part(part) }
|
58
|
-
end
|
59
|
-
|
60
|
-
# Parse a string path into keys (e.g., 'users.1.name')
|
61
|
-
def parse_string_path(path)
|
62
|
-
path.to_s.split(/\.|\[|\]/).reject(&:empty?).map { |part| parse_part(part) }
|
63
|
-
end
|
64
|
-
|
65
|
-
# Parse each part into either a symbol or integer
|
66
|
-
def parse_part(part)
|
67
|
-
part.match?(/^\d+$/) ? part.to_i : part.to_sym
|
68
|
-
end
|
69
|
-
|
70
|
-
# Helper to traverse the path for getting values
|
71
|
-
def traverse_path_for_get(data, keys)
|
72
|
-
keys.reduce(data) do |current_data, key|
|
73
|
-
check_invalid_path(current_data, key)
|
74
|
-
|
75
|
-
case current_data
|
76
|
-
when Hash
|
77
|
-
fetch_from_hash(current_data, key)
|
78
|
-
when Array
|
79
|
-
fetch_from_array(current_data, key)
|
80
|
-
else
|
81
|
-
raise KeyError, "Invalid data type at '#{key}'"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# Helper to traverse the path for setting values
|
87
|
-
def traverse_path_for_set(data, keys)
|
88
|
-
keys.reduce(data) do |current_data, key|
|
89
|
-
check_invalid_path(current_data, key)
|
90
|
-
|
91
|
-
case current_data
|
92
|
-
when Hash
|
93
|
-
current_data[find_existing_key(current_data, key)] ||= {}
|
94
|
-
when Array
|
95
|
-
current_data[key.to_i] ||= {}
|
96
|
-
else
|
97
|
-
break nil
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Helper to check for invalid paths
|
103
|
-
def check_invalid_path(data, key)
|
104
|
-
raise KeyError, "Invalid path at '#{key}'" if data.nil?
|
105
|
-
end
|
106
|
-
|
107
|
-
# Fetch value from a hash, trying both symbol and string keys
|
108
|
-
def fetch_from_hash(hash, key)
|
109
|
-
hash[key.to_sym] || hash[key.to_s]
|
110
|
-
end
|
111
|
-
|
112
|
-
# Fetch value from an array if the key is an integer
|
113
|
-
def fetch_from_array(array, key)
|
114
|
-
key.is_a?(Integer) ? array[key] : nil
|
115
|
-
end
|
116
|
-
|
117
|
-
# Set the final value in a hash or array
|
118
|
-
def set_final_value(target, last_key, value)
|
119
|
-
case target
|
120
|
-
when Hash
|
121
|
-
target[find_existing_key(target, last_key)] = value
|
122
|
-
when Array
|
123
|
-
if last_key.is_a?(Integer)
|
124
|
-
target[last_key] = value
|
125
|
-
else
|
126
|
-
raise KeyError, "Invalid path or type at '#{last_key}'"
|
127
|
-
end
|
128
|
-
else
|
129
|
-
raise KeyError, "Invalid target type for path at '#{last_key}'"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Check if the key already exists and return the key in its original type (symbol or string)
|
134
|
-
def find_existing_key(hash, key)
|
135
|
-
return key if hash.key?(key) # Key already exists in original form
|
136
|
-
return key.to_s if hash.key?(key.to_s) # Exists as a string
|
137
|
-
return key.to_sym if hash.key?(key.to_sym) # Exists as a symbol
|
138
|
-
|
139
|
-
key # Otherwise, return the key as-is (use the incoming type)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Helper to traverse the path for deletion
|
143
|
-
def traverse_path_for_delete(data, keys)
|
144
|
-
keys.reduce(data) do |current_data, key|
|
145
|
-
check_invalid_path(current_data, key)
|
146
|
-
|
147
|
-
case current_data
|
148
|
-
when Hash
|
149
|
-
current_data[find_existing_key(current_data, key)]
|
150
|
-
when Array
|
151
|
-
current_data[key.to_i]
|
152
|
-
else
|
153
|
-
raise KeyError, "Invalid data type at '#{key}'"
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
# Helper to delete the final key in a hash or array
|
159
|
-
def delete_final_key(target, last_key)
|
160
|
-
case target
|
161
|
-
when Hash
|
162
|
-
target.delete(find_existing_key(target, last_key))
|
163
|
-
when Array
|
164
|
-
target.delete_at(last_key.to_i) if last_key.is_a?(Integer)
|
165
|
-
else
|
166
|
-
raise KeyError, "Cannot delete key from unsupported data type"
|
167
|
-
end
|
21
|
+
PathAccessor.delete(data, path)
|
168
22
|
end
|
169
23
|
end
|
170
24
|
end
|
@@ -10,13 +10,23 @@ module DevSuite
|
|
10
10
|
|
11
11
|
class << self
|
12
12
|
def write(path, content)
|
13
|
-
|
14
|
-
|
13
|
+
WriterManager.write(path, content)
|
14
|
+
end
|
15
|
+
|
16
|
+
def append(path, content)
|
17
|
+
WriterManager.append(path, content)
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete_lines(path, start_line, end_line = start_line)
|
21
|
+
WriterManager.delete_lines(path, start_line, end_line)
|
15
22
|
end
|
16
23
|
|
17
24
|
def update_key(path, key, value)
|
18
|
-
|
19
|
-
|
25
|
+
WriterManager.update_key(path, key, value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete_key(path, key)
|
29
|
+
WriterManager.delete_key(path, key)
|
20
30
|
end
|
21
31
|
end
|
22
32
|
end
|
@@ -5,21 +5,51 @@ module DevSuite
|
|
5
5
|
module FileWriter
|
6
6
|
module Writer
|
7
7
|
class Base < Utils::Construct::Component::Base
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
def initialize(path)
|
11
|
+
super()
|
12
|
+
@path = path
|
13
|
+
end
|
14
|
+
|
15
|
+
def read
|
16
|
+
FileLoader.load(path)
|
11
17
|
end
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
19
|
+
def write(content, backup: false)
|
20
|
+
create_backup if backup
|
21
|
+
AtomicWriter.new(path, content).write
|
22
|
+
end
|
17
23
|
|
18
|
-
|
24
|
+
def append(content)
|
25
|
+
current_content = read
|
26
|
+
updated_content = current_content.merge(content)
|
27
|
+
write(updated_content)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete_lines(start_line, end_line = start_line)
|
31
|
+
lines = ::File.readlines(path)
|
32
|
+
lines.slice!(start_line - 1, end_line - start_line + 1)
|
33
|
+
write(lines.join)
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_key(key, value, **options)
|
37
|
+
content = read
|
19
38
|
Utils::Data.set_value_by_path(content, key, value)
|
39
|
+
write(content, **options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete_key(key, **options)
|
43
|
+
content = read
|
44
|
+
Utils::Data.delete_key_by_path(content, key)
|
45
|
+
write(content, **options)
|
46
|
+
end
|
20
47
|
|
21
|
-
|
22
|
-
|
48
|
+
def append_array(array_key, new_elements)
|
49
|
+
data = read
|
50
|
+
data[array_key] ||= []
|
51
|
+
data[array_key].concat(new_elements)
|
52
|
+
write(data)
|
23
53
|
end
|
24
54
|
|
25
55
|
private
|
@@ -28,11 +58,6 @@ module DevSuite
|
|
28
58
|
::File.exist?(path)
|
29
59
|
end
|
30
60
|
|
31
|
-
# Load the file content using a file loader
|
32
|
-
def load_file_content(file_path)
|
33
|
-
FileLoader.load(file_path)
|
34
|
-
end
|
35
|
-
|
36
61
|
def create_backup(path)
|
37
62
|
BackupManager.new(path).create_backup if file_exists?(path)
|
38
63
|
end
|
@@ -5,20 +5,22 @@ module DevSuite
|
|
5
5
|
module FileWriter
|
6
6
|
module Writer
|
7
7
|
class Text < Base
|
8
|
-
def write(path, content, backup: false)
|
9
|
-
create_backup(path) if backup
|
10
|
-
|
11
|
-
AtomicWriter.new(path, content).write
|
12
|
-
end
|
13
|
-
|
14
8
|
# Updates a key-like pattern in a plain text file (find and replace)
|
15
|
-
def update_key(
|
16
|
-
content =
|
9
|
+
def update_key(key, value, backup: false)
|
10
|
+
content = read
|
17
11
|
|
18
12
|
# Simple pattern matching and replacement (e.g., `key: value`)
|
19
13
|
updated_content = content.gsub(/^#{Regexp.escape(key)}:.*/, "#{key}: #{value}")
|
20
14
|
|
21
|
-
write(
|
15
|
+
write(updated_content, backup: backup)
|
16
|
+
end
|
17
|
+
|
18
|
+
def append(content)
|
19
|
+
::File.open(path, "a") do |file|
|
20
|
+
file.write("\n") if ::File.size(path).nonzero?
|
21
|
+
|
22
|
+
file.write(content.strip)
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -5,7 +5,7 @@ module DevSuite
|
|
5
5
|
module FileWriter
|
6
6
|
module Writer
|
7
7
|
class Yaml < Base
|
8
|
-
def write(
|
8
|
+
def write(content, normalize: false, backup: false, yaml_options: {})
|
9
9
|
validate_content(content)
|
10
10
|
create_backup(path) if backup
|
11
11
|
|
@@ -3,27 +3,50 @@
|
|
3
3
|
module DevSuite
|
4
4
|
module Utils
|
5
5
|
module FileWriter
|
6
|
+
class UnsupportedFileTypeError < StandardError; end
|
7
|
+
|
6
8
|
class WriterManager
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
WRITERS = {
|
10
|
+
".json" => Writer::Json,
|
11
|
+
".yml" => Writer::Yaml,
|
12
|
+
".yaml" => Writer::Yaml,
|
13
|
+
".txt" => Writer::Text,
|
14
|
+
}.freeze
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
+
class << self
|
17
|
+
def write(path, content)
|
18
|
+
writer_instance(path).write(content)
|
19
|
+
end
|
20
|
+
|
21
|
+
def append(path, content)
|
22
|
+
writer_instance(path).append(content)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_lines(path, start_line, end_line = start_line)
|
26
|
+
writer_instance(path).delete_lines(start_line, end_line)
|
27
|
+
end
|
16
28
|
|
17
|
-
|
29
|
+
def update_key(path, key, value)
|
30
|
+
writer_instance(path).update_key(key, value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete_key(path, key)
|
34
|
+
writer_instance(path).delete_key(key)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Returns the appropriate writer instance based on the file extension
|
40
|
+
def writer_instance(path)
|
41
|
+
writer_class = WRITERS[file_extension(path)]
|
42
|
+
raise UnsupportedFileTypeError, "Unsupported file type: #{file_extension(path)}" unless writer_class
|
43
|
+
|
44
|
+
writer_class.new(path)
|
45
|
+
end
|
18
46
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
Writer::Json.new
|
23
|
-
when ".yml", ".yaml"
|
24
|
-
Writer::Yaml.new
|
25
|
-
else
|
26
|
-
Writer::Text.new
|
47
|
+
# Returns the file extension from the path
|
48
|
+
def file_extension(path)
|
49
|
+
::File.extname(path).downcase
|
27
50
|
end
|
28
51
|
end
|
29
52
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DevSuite
|
4
|
+
module Utils
|
5
|
+
module Logger
|
6
|
+
require_relative "formatter"
|
7
|
+
require_relative "emoji"
|
8
|
+
require_relative "errors"
|
9
|
+
|
10
|
+
class Base
|
11
|
+
LOG_LEVELS = [:none, :info, :warn, :error, :debug].freeze
|
12
|
+
|
13
|
+
attr_accessor :log_level
|
14
|
+
|
15
|
+
def initialize(log_level: :none)
|
16
|
+
validate_log_level(log_level)
|
17
|
+
@log_level = log_level
|
18
|
+
end
|
19
|
+
|
20
|
+
# Logs a message with optional emoji, prefix, and color.
|
21
|
+
def log(message, level: :none, emoji: nil, prefix: nil, color: nil)
|
22
|
+
validate_log_level(level)
|
23
|
+
return if skip_logging?(level)
|
24
|
+
|
25
|
+
options = {
|
26
|
+
level: level,
|
27
|
+
emoji: emoji,
|
28
|
+
prefix: prefix,
|
29
|
+
color: color,
|
30
|
+
}
|
31
|
+
|
32
|
+
formatted_message = Formatter.format(message, options)
|
33
|
+
output_log(formatted_message)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def validate_log_level(level)
|
39
|
+
return if LOG_LEVELS.include?(level)
|
40
|
+
|
41
|
+
raise InvalidLogLevelError, "Invalid log level: #{level}. Valid levels are: #{LOG_LEVELS.join(", ")}."
|
42
|
+
end
|
43
|
+
|
44
|
+
def skip_logging?(level)
|
45
|
+
LOG_LEVELS.index(level) < LOG_LEVELS.index(@log_level)
|
46
|
+
end
|
47
|
+
|
48
|
+
def output_log(formatted_message)
|
49
|
+
puts formatted_message if formatted_message
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DevSuite
|
4
|
+
module Utils
|
5
|
+
module Logger
|
6
|
+
module Emoji
|
7
|
+
class << self
|
8
|
+
def resolve(emoji)
|
9
|
+
return "" unless emoji
|
10
|
+
|
11
|
+
emoji.is_a?(Symbol) ? Utils::Emoji.get(emoji) : emoji
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DevSuite
|
4
|
+
module Utils
|
5
|
+
module Logger
|
6
|
+
module Formatter
|
7
|
+
LOG_DETAILS = {
|
8
|
+
none: { prefix: "", color: :white },
|
9
|
+
info: { prefix: "[INFO]", color: :green },
|
10
|
+
warn: { prefix: "[WARNING]", color: :yellow },
|
11
|
+
error: { prefix: "[ERROR]", color: :red },
|
12
|
+
debug: { prefix: "[DEBUG]", color: :blue },
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def format(message, options = {})
|
17
|
+
return "" if message.nil? || message.strip.empty?
|
18
|
+
|
19
|
+
details = fetch_log_details(options[:level])
|
20
|
+
prefix = options[:prefix] || details[:prefix]
|
21
|
+
color = options[:color] || details[:color]
|
22
|
+
emoji_icon = Emoji.resolve(options[:emoji])
|
23
|
+
|
24
|
+
formatted_message = build_message(prefix, emoji_icon, message)
|
25
|
+
Utils::Color.colorize(formatted_message, color: color)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def fetch_log_details(level)
|
31
|
+
LOG_DETAILS[level || :none]
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_message(prefix, emoji_icon, message)
|
35
|
+
"#{prefix} #{emoji_icon} #{message}".strip
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DevSuite
|
4
|
+
module Utils
|
5
|
+
module Logger
|
6
|
+
require_relative "base"
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# Provides access to the global logger instance
|
10
|
+
#
|
11
|
+
# @return [Base] the global logger instance
|
12
|
+
def logger
|
13
|
+
@logger ||= Base.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# Logs a message using the global logger instance
|
17
|
+
#
|
18
|
+
# @param message [String] The message to log.
|
19
|
+
# @param level [Symbol] The log level (:none, :info, :warn, :error, :debug).
|
20
|
+
# @param emoji [String, Symbol, nil] Optional emoji to prepend to the message.
|
21
|
+
# @param prefix [String, nil] Custom prefix for the message.
|
22
|
+
# @param color [Symbol, nil] Custom color for the message.
|
23
|
+
def log(message, level: :none, emoji: nil, prefix: nil, color: nil)
|
24
|
+
logger.log(message, level: level, emoji: emoji, prefix: prefix, color: color)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,58 +3,7 @@
|
|
3
3
|
module DevSuite
|
4
4
|
module Utils
|
5
5
|
module Logger
|
6
|
-
|
7
|
-
none: { prefix: "", color: :white },
|
8
|
-
info: { prefix: "[INFO]", color: :green },
|
9
|
-
warn: { prefix: "[WARNING]", color: :yellow },
|
10
|
-
error: { prefix: "[ERROR]", color: :red },
|
11
|
-
debug: { prefix: "[DEBUG]", color: :blue },
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
class << self
|
15
|
-
# Logs a message with an optional emoji and specified log level.
|
16
|
-
#
|
17
|
-
# @param message [String] The message to log.
|
18
|
-
# @param level [Symbol] The log level (:info, :warn, :error, :debug).
|
19
|
-
# @param emoji [String, Symbol] Optional emoji to prepend to the message.
|
20
|
-
def log(message, level: :none, emoji: nil, prefix: nil, color: nil)
|
21
|
-
emoji_icon = resolve_emoji(emoji)
|
22
|
-
formatted_message = format_message("#{emoji_icon} #{message}", level, prefix, color)
|
23
|
-
output_log(formatted_message)
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
# Resolves the emoji, either from a symbol or directly as a string.
|
29
|
-
#
|
30
|
-
# @param emoji [String, Symbol, nil] The emoji or its symbol key.
|
31
|
-
# @return [String] The resolved emoji or an empty string if none is provided.
|
32
|
-
def resolve_emoji(emoji)
|
33
|
-
return "" unless emoji
|
34
|
-
|
35
|
-
emoji.is_a?(Symbol) ? Emoji.get(emoji) : emoji
|
36
|
-
end
|
37
|
-
|
38
|
-
# Formats the log message with the appropriate prefix and color.
|
39
|
-
#
|
40
|
-
# @param message [String] The message to format.
|
41
|
-
# @param level [Symbol] The log level (:info, :warn, :error, :debug).
|
42
|
-
# @return [String] The formatted log message.
|
43
|
-
def format_message(message, level, custom_prefix, custom_color)
|
44
|
-
details = LOG_DETAILS[level]
|
45
|
-
prefix = custom_prefix || details[:prefix]
|
46
|
-
color = custom_color || details[:color]
|
47
|
-
|
48
|
-
Utils::Color.colorize("#{prefix} #{message}", color: color)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Outputs the formatted log message to the console.
|
52
|
-
#
|
53
|
-
# @param formatted_message [String] The message to output.
|
54
|
-
def output_log(formatted_message)
|
55
|
-
puts formatted_message if formatted_message
|
56
|
-
end
|
57
|
-
end
|
6
|
+
require_relative "logger/logger"
|
58
7
|
end
|
59
8
|
end
|
60
9
|
end
|
@@ -44,7 +44,9 @@ module DevSuite
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def build_driver(options)
|
47
|
-
|
47
|
+
driver_type = options.fetch(:driver)
|
48
|
+
driver_options = options.reject { |key, _| key == :driver }
|
49
|
+
Driver.build_component(driver_type, **driver_options)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -49,7 +49,7 @@ module DevSuite
|
|
49
49
|
|
50
50
|
total_width = column_widths.sum + column_widths.size * 3 - 1
|
51
51
|
title_str = "| #{table.title.center(total_width - 2)} |"
|
52
|
-
colorize(title_str, settings.get("colors.title"))
|
52
|
+
puts colorize(title_str, settings.get("colors.title"))
|
53
53
|
end
|
54
54
|
|
55
55
|
def render_header(table, column_widths)
|
@@ -59,13 +59,13 @@ module DevSuite
|
|
59
59
|
text_align(column.name, column_widths[index])
|
60
60
|
end
|
61
61
|
header_str = "| #{header.join(" | ")} |"
|
62
|
-
colorize(header_str, settings.get("colors.column"))
|
62
|
+
puts colorize(header_str, settings.get("colors.column"))
|
63
63
|
end
|
64
64
|
|
65
65
|
def render_separator(column_widths)
|
66
66
|
separator = column_widths.map { |width| "-" * width }.join("-+-")
|
67
67
|
separator_str = "+-#{separator}-+"
|
68
|
-
colorize(separator_str, settings.get("colors.border"))
|
68
|
+
puts colorize(separator_str, settings.get("colors.border"))
|
69
69
|
end
|
70
70
|
|
71
71
|
def render_rows(table, column_widths)
|
@@ -73,7 +73,7 @@ module DevSuite
|
|
73
73
|
render_row(row, column_widths)
|
74
74
|
end
|
75
75
|
cells_str = cells.join("\n")
|
76
|
-
colorize(cells_str, settings.get("colors.row"))
|
76
|
+
puts colorize(cells_str, settings.get("colors.row"))
|
77
77
|
end
|
78
78
|
|
79
79
|
def render_row(row, column_widths)
|
@@ -81,7 +81,7 @@ module DevSuite
|
|
81
81
|
text_align(cell.to_s, column_widths[index])
|
82
82
|
end
|
83
83
|
cell_str = "| #{cell.join(" | ")} |"
|
84
|
-
colorize(cell_str, settings.get("colors.row"))
|
84
|
+
puts colorize(cell_str, settings.get("colors.row"))
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
data/lib/dev_suite/version.rb
CHANGED