dev_suite 0.2.7 → 0.2.9

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +1 -1
  3. data/Gemfile.lock +9 -11
  4. data/README.md +142 -0
  5. data/dev_suite.gemspec +1 -0
  6. data/examples/workflow/basic_workflow.rb +15 -0
  7. data/examples/workflow/composite_workflow.rb +21 -0
  8. data/examples/workflow/conditional_workflow.rb +17 -0
  9. data/examples/workflow/full_workflow.rb +79 -0
  10. data/examples/workflow/loop_workflow.rb +17 -0
  11. data/examples/workflow/parallel_workflow.rb +17 -0
  12. data/lib/dev_suite/dev_suite.rb +2 -0
  13. data/lib/dev_suite/request_builder/builder/base.rb +27 -0
  14. data/lib/dev_suite/request_builder/builder/builder.rb +10 -0
  15. data/lib/dev_suite/request_builder/builder/http.rb +32 -0
  16. data/lib/dev_suite/request_builder/builder.rb +9 -0
  17. data/lib/dev_suite/request_builder/config/config.rb +11 -0
  18. data/lib/dev_suite/request_builder/config/configuration.rb +24 -0
  19. data/lib/dev_suite/request_builder/config.rb +9 -0
  20. data/lib/dev_suite/request_builder/formatter/base.rb +13 -0
  21. data/lib/dev_suite/request_builder/formatter/formatter.rb +10 -0
  22. data/lib/dev_suite/request_builder/formatter/graphql.rb +19 -0
  23. data/lib/dev_suite/request_builder/formatter.rb +9 -0
  24. data/lib/dev_suite/request_builder/request_builder.rb +21 -0
  25. data/lib/dev_suite/request_builder/tool/base.rb +19 -0
  26. data/lib/dev_suite/request_builder/tool/curl.rb +91 -0
  27. data/lib/dev_suite/request_builder/tool/tool.rb +11 -0
  28. data/lib/dev_suite/request_builder/tool/validator/curl.rb +38 -0
  29. data/lib/dev_suite/request_builder/tool/validator/validator.rb +11 -0
  30. data/lib/dev_suite/request_builder/tool/validator.rb +11 -0
  31. data/lib/dev_suite/request_builder/tool.rb +9 -0
  32. data/lib/dev_suite/request_builder.rb +7 -0
  33. data/lib/dev_suite/request_logger/adapter/adapter.rb +11 -9
  34. data/lib/dev_suite/request_logger/adapter/faraday.rb +12 -1
  35. data/lib/dev_suite/request_logger/adapter/middleware/faraday.rb +3 -3
  36. data/lib/dev_suite/request_logger/adapter/net_http.rb +15 -6
  37. data/lib/dev_suite/request_logger/config/configuration.rb +1 -0
  38. data/lib/dev_suite/request_logger/extractor/base.rb +8 -2
  39. data/lib/dev_suite/request_logger/extractor/extractor.rb +5 -6
  40. data/lib/dev_suite/request_logger/extractor/faraday.rb +32 -14
  41. data/lib/dev_suite/request_logger/extractor/net_http.rb +53 -12
  42. data/lib/dev_suite/request_logger/logger.rb +9 -3
  43. data/lib/dev_suite/request_logger/request.rb +12 -0
  44. data/lib/dev_suite/request_logger/response.rb +34 -9
  45. data/lib/dev_suite/utils/construct/component/base.rb +13 -0
  46. data/lib/dev_suite/utils/construct/component/component.rb +1 -0
  47. data/lib/dev_suite/utils/construct/component/manager.rb +27 -10
  48. data/lib/dev_suite/utils/construct/component/validator/base.rb +25 -0
  49. data/lib/dev_suite/utils/construct/component/validator/validation_error.rb +21 -0
  50. data/lib/dev_suite/utils/construct/component/validator/validation_rule.rb +68 -0
  51. data/lib/dev_suite/utils/construct/component/validator/validator.rb +15 -0
  52. data/lib/dev_suite/utils/construct/component/validator.rb +13 -0
  53. data/lib/dev_suite/utils/construct/config/dependency_handler.rb +25 -34
  54. data/lib/dev_suite/utils/construct/config/settings/base.rb +35 -26
  55. data/lib/dev_suite/utils/data/base_operations.rb +61 -0
  56. data/lib/dev_suite/utils/data/data.rb +19 -0
  57. data/lib/dev_suite/utils/data/path_access.rb +172 -0
  58. data/lib/dev_suite/utils/data/search_filter.rb +60 -0
  59. data/lib/dev_suite/utils/data/serialization.rb +29 -0
  60. data/lib/dev_suite/utils/data/transformations.rb +45 -0
  61. data/lib/dev_suite/utils/data.rb +9 -0
  62. data/lib/dev_suite/utils/dependency_loader.rb +2 -2
  63. data/lib/dev_suite/utils/emoji.rb +1 -0
  64. data/lib/dev_suite/utils/file_loader/file_loader.rb +1 -5
  65. data/lib/dev_suite/utils/file_loader/loader/json.rb +4 -1
  66. data/lib/dev_suite/utils/file_loader/loader/loader.rb +23 -19
  67. data/lib/dev_suite/utils/file_loader/loader.rb +0 -2
  68. data/lib/dev_suite/utils/file_writer/atomic_writer.rb +53 -0
  69. data/lib/dev_suite/utils/file_writer/backup_manager.rb +21 -0
  70. data/lib/dev_suite/utils/file_writer/file_writer.rb +24 -0
  71. data/lib/dev_suite/utils/file_writer/writer/base.rb +43 -0
  72. data/lib/dev_suite/utils/file_writer/writer/json.rb +24 -0
  73. data/lib/dev_suite/utils/file_writer/writer/text.rb +27 -0
  74. data/lib/dev_suite/utils/file_writer/writer/writer.rb +14 -0
  75. data/lib/dev_suite/utils/file_writer/writer/yaml.rb +44 -0
  76. data/lib/dev_suite/utils/file_writer/writer.rb +11 -0
  77. data/lib/dev_suite/utils/file_writer/writer_manager.rb +32 -0
  78. data/lib/dev_suite/utils/file_writer.rb +9 -0
  79. data/lib/dev_suite/utils/store/config/config.rb +13 -0
  80. data/lib/dev_suite/utils/store/config/configuration.rb +30 -0
  81. data/lib/dev_suite/utils/store/config.rb +11 -0
  82. data/lib/dev_suite/utils/store/driver/base.rb +35 -0
  83. data/lib/dev_suite/utils/store/driver/driver.rb +18 -0
  84. data/lib/dev_suite/utils/store/driver/file.rb +61 -0
  85. data/lib/dev_suite/utils/store/driver/memory.rb +42 -0
  86. data/lib/dev_suite/utils/store/driver.rb +11 -0
  87. data/lib/dev_suite/utils/store/store.rb +69 -0
  88. data/lib/dev_suite/utils/store.rb +9 -0
  89. data/lib/dev_suite/utils/utils.rb +17 -5
  90. data/lib/dev_suite/utils/warning_handler.rb +25 -0
  91. data/lib/dev_suite/version.rb +1 -1
  92. data/lib/dev_suite/workflow/engine.rb +27 -0
  93. data/lib/dev_suite/workflow/step/base.rb +48 -0
  94. data/lib/dev_suite/workflow/step/composite.rb +27 -0
  95. data/lib/dev_suite/workflow/step/conditional.rb +23 -0
  96. data/lib/dev_suite/workflow/step/loop.rb +21 -0
  97. data/lib/dev_suite/workflow/step/parallel.rb +18 -0
  98. data/lib/dev_suite/workflow/step/step.rb +13 -0
  99. data/lib/dev_suite/workflow/step.rb +9 -0
  100. data/lib/dev_suite/workflow/step_context.rb +32 -0
  101. data/lib/dev_suite/workflow/workflow.rb +35 -0
  102. data/lib/dev_suite/workflow.rb +7 -0
  103. metadata +87 -3
  104. data/lib/dev_suite/utils/construct/component/initializer.rb +0 -28
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ module Tool
6
+ class Curl < Base
7
+ def build_command(http_method:, url:, headers:, body: nil)
8
+ validate_parameters(http_method, url, headers, body)
9
+
10
+ command = build_base_command(http_method, url)
11
+
12
+ add_headers(command, headers)
13
+ add_body(command, body)
14
+ add_insecure_option(command)
15
+ add_verbose_option(command)
16
+ add_follow_redirects_option(command)
17
+ add_cookie_option(command)
18
+ add_user_agent_option(command)
19
+ add_max_time_option(command)
20
+ add_connect_timeout_option(command)
21
+
22
+ command.join(" ").strip
23
+ end
24
+
25
+ private
26
+
27
+ def validate_parameters(http_method, url, headers, body)
28
+ validator = Validator::Curl.new
29
+ validator.validate!(
30
+ http_method: http_method,
31
+ url: url,
32
+ headers: headers,
33
+ body: body,
34
+ )
35
+ end
36
+
37
+ def build_base_command(http_method, url)
38
+ ["curl", "-X #{http_method}", "'#{url}'"]
39
+ end
40
+
41
+ def add_headers(command, headers)
42
+ headers.each do |key, value|
43
+ command << "-H '#{key}: #{value}'"
44
+ end
45
+ end
46
+
47
+ def add_body(command, body)
48
+ return unless body
49
+
50
+ command << (raw_data? ? "--data-raw '#{body}'" : "-d '#{body}'")
51
+ end
52
+
53
+ def add_insecure_option(command)
54
+ command << "--insecure" if fetch_setting("tool.curl.use_insecure", default: false)
55
+ end
56
+
57
+ def add_verbose_option(command)
58
+ command << "-v" if fetch_setting("tool.curl.verbose", default: false)
59
+ end
60
+
61
+ def add_follow_redirects_option(command)
62
+ command << "-L" if fetch_setting("tool.curl.follow_redirects", default: true)
63
+ end
64
+
65
+ def add_cookie_option(command)
66
+ cookie = fetch_setting("tool.curl.cookie")
67
+ command << "-b '#{cookie}'" if cookie
68
+ end
69
+
70
+ def add_user_agent_option(command)
71
+ user_agent = fetch_setting("tool.curl.user_agent")
72
+ command << "-A '#{user_agent}'" if user_agent
73
+ end
74
+
75
+ def add_max_time_option(command)
76
+ max_time = fetch_setting("tool.curl.max_time")
77
+ command << "--max-time #{max_time}" if max_time
78
+ end
79
+
80
+ def add_connect_timeout_option(command)
81
+ connect_timeout = fetch_setting("tool.curl.connect_timeout")
82
+ command << "--connect-timeout #{connect_timeout}" if connect_timeout
83
+ end
84
+
85
+ def raw_data?
86
+ fetch_setting("tool.curl.raw_data", default: false)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ module Tool
6
+ require_relative "validator"
7
+ require_relative "base"
8
+ require_relative "curl"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ module Tool
6
+ module Validator
7
+ class Curl < Utils::Construct::Component::Validator::Base
8
+ VALID_HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"].freeze
9
+
10
+ def validate!(http_method:, url:, headers:, body: nil)
11
+ validate_http_method(http_method)
12
+ validate_url(url)
13
+ validate_headers(headers)
14
+ validate_body(body)
15
+ end
16
+
17
+ private
18
+
19
+ def validate_http_method(http_method)
20
+ validate_inclusion!(http_method, VALID_HTTP_METHODS, field_name: "HTTP Method")
21
+ end
22
+
23
+ def validate_url(url)
24
+ validate_url!(url, field_name: "URL")
25
+ end
26
+
27
+ def validate_headers(headers)
28
+ validate_hash!(headers, field_name: "Headers")
29
+ end
30
+
31
+ def validate_body(body)
32
+ validate_type!(body, [String, NilClass], field_name: "Body")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ module Tool
6
+ module Validator
7
+ require_relative "curl"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ module Tool
6
+ module Validator
7
+ require_relative "validator/validator"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ module Tool
6
+ require_relative "tool/tool"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module RequestBuilder
5
+ require_relative "request_builder/request_builder"
6
+ end
7
+ end
@@ -8,21 +8,23 @@ module DevSuite
8
8
  require_relative "base"
9
9
 
10
10
  class << self
11
- def handle_missing_dependencies(missing_dependencies)
12
- Config.configuration.delete_option_on_failure(:adapters, :faraday, *missing_dependencies)
11
+ def handle_missing_nethttp(missing_dependencies)
12
+ Config.configuration.remove_failed_dependency(:adapters, :net_http, *missing_dependencies)
13
+ end
14
+
15
+ def handle_missing_faraday(missing_dependencies)
16
+ Config.configuration.remove_failed_dependency(:adapters, :faraday, *missing_dependencies)
13
17
  end
14
18
  end
15
19
 
16
20
  # Load and register `net/http` adapter
17
- require "net/http"
18
- require_relative "net_http"
19
- register_component(NetHttp)
21
+ load_dependency(["net/http"], on_failure: method(:handle_missing_nethttp)) do
22
+ require_relative "net_http"
23
+ register_component(NetHttp)
24
+ end
20
25
 
21
26
  # Load and register `faraday` adapter
22
- Utils::DependencyLoader.safe_load_dependencies(
23
- "faraday",
24
- on_failure: method(:handle_missing_dependencies),
25
- ) do
27
+ load_dependency(["faraday"], on_failure: method(:handle_missing_faraday)) do
26
28
  require_relative "faraday"
27
29
  register_component(Faraday)
28
30
  end
@@ -7,6 +7,8 @@ module DevSuite
7
7
 
8
8
  class Faraday < Base
9
9
  def enable
10
+ return unless faraday_defined?
11
+
10
12
  ::Faraday::Connection.class_eval do
11
13
  alias_method(:_original_run_request, :run_request)
12
14
 
@@ -20,17 +22,26 @@ module DevSuite
20
22
 
21
23
  Middleware::Faraday.new(lambda do |e|
22
24
  _original_run_request(e.method, e.url, e.body, e.request_headers, &block)
23
- end).call(env)
25
+ end).call(env, self)
24
26
  end
25
27
  end
26
28
  end
27
29
 
28
30
  def disable
31
+ return unless faraday_defined?
32
+
29
33
  ::Faraday::Connection.class_eval do
30
34
  alias_method(:run_request, :_original_run_request)
31
35
  remove_method(:_original_run_request)
32
36
  end
33
37
  end
38
+
39
+ private
40
+
41
+ # Check if Faraday is defined
42
+ def faraday_defined?
43
+ defined?(::Faraday::Connection) && defined?(::Faraday::Env)
44
+ end
34
45
  end
35
46
  end
36
47
  end
@@ -5,14 +5,14 @@ module DevSuite
5
5
  module Adapter
6
6
  module Middleware
7
7
  class Faraday < ::Faraday::Middleware
8
- def call(env)
8
+ def call(env, instance = nil)
9
9
  # Log the request details
10
- Logger.log_request(self, env)
10
+ Logger.log_request(instance, env)
11
11
 
12
12
  # Perform the actual request
13
13
  @app.call(env).on_complete do |response_env|
14
14
  # Log the response details
15
- Logger.log_response(self, response_env)
15
+ Logger.log_response(instance, response_env)
16
16
  end
17
17
  end
18
18
  end
@@ -13,16 +13,25 @@ module DevSuite
13
13
 
14
14
  # Override the request method to add logging functionality
15
15
  def request(request, body = nil, &block)
16
- # Log the full URL of the HTTP request using the DevSuite::Utils::Logger
16
+ start_time = Time.now
17
+
17
18
  Logger.log_request(self, request)
18
19
 
19
- # Call the original request method (now aliased as _original_request) to perform the actual HTTP request
20
- response = _original_request(request, body, &block)
20
+ response = nil
21
+ begin
22
+ # Call the original request method (now aliased as _original_request) to perform the actual HTTP request
23
+ response = _original_request(request, body, &block)
24
+ ensure
25
+ end_time = Time.now
26
+ response ||= Net::HTTPResponse.new("1.1", "500", "Internal Server Error")
27
+ response.instance_variable_set(:@start_time, start_time)
28
+ response.instance_variable_set(:@end_time, end_time)
29
+ response.define_singleton_method(:start_time) { @start_time }
30
+ response.define_singleton_method(:end_time) { @end_time }
21
31
 
22
- # Optionally log the response details
23
- Logger.log_response(self, response)
32
+ Logger.log_response(self, response)
33
+ end
24
34
 
25
- # Return the response object so that the calling code receives the expected result
26
35
  response
27
36
  end
28
37
  end
@@ -8,6 +8,7 @@ module DevSuite
8
8
  log_headers: true,
9
9
  log_cookies: true,
10
10
  log_body: true,
11
+ log_response_time: true,
11
12
  log_level: :debug,
12
13
  )
13
14
 
@@ -4,11 +4,17 @@ module DevSuite
4
4
  module RequestLogger
5
5
  module Extractor
6
6
  class Base < Utils::Construct::Component::Base
7
- def extract_request(native_request)
7
+ # Extracts the request details from an HTTP request object
8
+ # @param instance [Object] The instance of the HTTP client that is making the request
9
+ # @param request [Object] The request object that is being made
10
+ def extract_request(_instance, _request)
8
11
  raise NotImplementedError
9
12
  end
10
13
 
11
- def extract_response(native_response)
14
+ # Extracts the response details from an HTTP response object
15
+ # @param instance [Object] The instance of the HTTP client that is making the request
16
+ # @param response [Object] The response object that is being returned
17
+ def extract_response(_instance, _response)
12
18
  raise NotImplementedError
13
19
  end
14
20
  end
@@ -6,14 +6,13 @@ module DevSuite
6
6
  include Utils::Construct::Component::Manager
7
7
 
8
8
  require_relative "base"
9
- require_relative "net_http"
10
9
 
11
- register_component(NetHttp)
10
+ load_dependency(["net/http"], on_failure: ->(_) {}) do
11
+ require_relative "net_http"
12
+ register_component(NetHttp)
13
+ end
12
14
 
13
- Utils::DependencyLoader.safe_load_dependencies(
14
- "faraday",
15
- on_failure: ->(_) {}, # Empty lambda to do nothing on failure
16
- ) do
15
+ load_dependency(["faraday"], on_failure: ->(_) {}) do
17
16
  require_relative "faraday"
18
17
  register_component(Faraday)
19
18
  end
@@ -4,31 +4,49 @@ module DevSuite
4
4
  module RequestLogger
5
5
  module Extractor
6
6
  class Faraday < Base
7
- COMPONENT_KEY = ::Faraday::Middleware
7
+ COMPONENT_KEY = ::Faraday::Connection
8
8
 
9
- def extract_request(native_request)
9
+ # Extracts the request details from a Faraday request object
10
+ # @param _instance [Faraday::Connection] The instance of the Faraday client that is making the request
11
+ # @param request [Faraday::Env] The request object that is being made
12
+ def extract_request(connection, request)
10
13
  Request.new(
11
- method: native_request.method.to_s.upcase,
12
- url: native_request.url.to_s,
13
- headers: native_request.request_headers.to_h,
14
- cookies: extract_cookies(native_request.request_headers),
15
- body: native_request.body,
14
+ method: request.method.to_s.upcase,
15
+ url: build_url(connection),
16
+ headers: build_headers_from_request(request),
17
+ cookies: build_cookies(request),
18
+ body: request.body,
16
19
  )
17
20
  end
18
21
 
19
- def extract_response(native_response)
22
+ # Extracts the response details from a Faraday response object
23
+ # @param _instance [Faraday::Connection] The instance of the Faraday client that received the response
24
+ # @param response [Faraday::Env] The response object received
25
+ def extract_response(_connection, response)
20
26
  Response.new(
21
- status: native_response.status,
22
- message: native_response.reason_phrase || "",
23
- headers: native_response.response_headers.to_h,
24
- body: native_response.body,
27
+ status: response.status,
28
+ message: response.reason_phrase || "",
29
+ headers: build_headers_from_response(response),
30
+ body: response.body,
25
31
  )
26
32
  end
27
33
 
28
34
  private
29
35
 
30
- def extract_cookies(headers)
31
- headers = headers.to_h
36
+ def build_url(connection)
37
+ connection.url_prefix.to_s
38
+ end
39
+
40
+ def build_headers_from_request(request)
41
+ request.request_headers.to_h
42
+ end
43
+
44
+ def build_headers_from_response(response)
45
+ response.response_headers.to_h
46
+ end
47
+
48
+ def build_cookies(request)
49
+ headers = build_headers_from_request(request)
32
50
  headers["Cookie"] ? [headers["Cookie"]] : []
33
51
  end
34
52
  end
@@ -6,30 +6,71 @@ module DevSuite
6
6
  class NetHttp < Base
7
7
  COMPONENT_KEY = ::Net::HTTP
8
8
 
9
- def extract_request(native_request)
9
+ # Extracts the request details from a Net::HTTP request object
10
+ # @param http [Net::HTTP] The Net::HTTP object that is making the request
11
+ # @param request [Net::HTTP::Request] The request object that is being made
12
+ def extract_request(http, request)
10
13
  Request.new(
11
- method: native_request.method,
12
- url: native_request.uri.to_s,
13
- headers: native_request.each_header.to_h,
14
- cookies: extract_cookies(native_request),
15
- body: native_request.body,
14
+ method: request.method,
15
+ url: build_url(http, request),
16
+ headers: request.each_header.to_h,
17
+ cookies: build_cookies(request),
18
+ body: request.body,
16
19
  )
17
20
  end
18
21
 
19
- def extract_response(native_response)
22
+ # Extracts the response details from a Net::HTTP response object
23
+ # @param http [Net::HTTP] The Net::HTTP object that received the response
24
+ # @param response [Net::HTTPResponse] The response object received
25
+ # @return [Response] The extracted response details
26
+ def extract_response(_http, response)
20
27
  Response.new(
21
- status: native_response.code.to_i,
22
- message: native_response.message,
23
- headers: native_response.each_header.to_h,
24
- body: native_response.body,
28
+ status: response.code.to_i,
29
+ message: response.message,
30
+ headers: response.each_header.to_h,
31
+ body: response.body,
32
+ response_time: calculate_response_time(response),
25
33
  )
26
34
  end
27
35
 
28
36
  private
29
37
 
30
- def extract_cookies(request)
38
+ # Builds the full URL for the request
39
+ # @param http [Net::HTTP] The Net::HTTP object
40
+ # @param request [Net::HTTP::Request] The request object
41
+ # @return [String] The fully constructed URL
42
+ def build_url(http, request)
43
+ scheme = determine_scheme(http)
44
+ host = http.address
45
+ port_part = determine_port(http, scheme)
46
+ path = request.path
47
+
48
+ "#{scheme}://#{host}#{port_part}#{path}"
49
+ end
50
+
51
+ # Extracts cookies from the request headers
52
+ # @param request [Net::HTTP::Request] The request object
53
+ # @return [Array<String>] Array of cookie strings
54
+ def build_cookies(request)
31
55
  request.to_hash["cookie"] || []
32
56
  end
57
+
58
+ # Calculates the response time (if available)
59
+ # This example assumes response time is tracked separately and stored in the `http` object
60
+ def calculate_response_time(response)
61
+ if response.respond_to?(:start_time) && response.respond_to?(:end_time)
62
+ response.end_time - response.start_time
63
+ end
64
+ end
65
+
66
+ def determine_scheme(http)
67
+ http.use_ssl? ? "https" : "http"
68
+ end
69
+
70
+ def determine_port(http, scheme)
71
+ default_port = (scheme == "https" ? 443 : 80)
72
+ http.port == default_port ? nil : ":#{http.port}"
73
+ end
33
74
  end
34
75
  end
35
76
  end
@@ -20,6 +20,7 @@ module DevSuite
20
20
  log_entry(format_response_line(instance, response), status_emoji, log_level)
21
21
  log_headers(response) if settings.get(:log_headers)
22
22
  log_body(response.body, "Response") if settings.get(:log_body)
23
+ log_response_time(response) if settings.get(:log_response_time)
23
24
  end
24
25
 
25
26
  private
@@ -34,12 +35,12 @@ module DevSuite
34
35
 
35
36
  def extract_request(instance, request)
36
37
  extractor = Extractor.build_component_from_instance(instance)
37
- extractor.extract_request(request)
38
+ extractor.extract_request(instance, request)
38
39
  end
39
40
 
40
41
  def extract_response(instance, response)
41
42
  extractor = Extractor.build_component_from_instance(instance)
42
- extractor.extract_response(response)
43
+ extractor.extract_response(instance, response)
43
44
  end
44
45
 
45
46
  def log_entry(message, emoji, level = settings.get(:log_level))
@@ -64,7 +65,7 @@ module DevSuite
64
65
 
65
66
  def log_headers(request)
66
67
  headers = request.headers
67
- log_entry("Headers: #{headers}", :document) unless headers.empty?
68
+ log_entry("Headers: #{headers}", :document)
68
69
  end
69
70
 
70
71
  def log_cookies(request)
@@ -81,6 +82,11 @@ module DevSuite
81
82
 
82
83
  log_entry("#{type} Body: #{body}", :code)
83
84
  end
85
+
86
+ def log_response_time(response)
87
+ response_time = response.response_time
88
+ log_entry("Response Time: #{response_time} seconds", :stop) if response_time
89
+ end
84
90
  end
85
91
  end
86
92
  end
@@ -5,6 +5,8 @@
5
5
  module DevSuite
6
6
  module RequestLogger
7
7
  class Request
8
+ include Utils::WarningHandler
9
+
8
10
  attr_reader :method, :url, :headers, :cookies, :body
9
11
 
10
12
  def initialize(method:, url:, headers:, cookies:, body:)
@@ -13,6 +15,16 @@ module DevSuite
13
15
  @headers = headers
14
16
  @cookies = cookies
15
17
  @body = body
18
+
19
+ validate_presence
20
+ end
21
+
22
+ private
23
+
24
+ def validate_presence
25
+ warn_if_missing("Request URL", @url)
26
+ warn_if_missing("Request Method", @method)
27
+ warn_if_missing("Request Headers", @headers)
16
28
  end
17
29
  end
18
30
  end
@@ -1,28 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # request_logger/response.rb
4
-
5
3
  module DevSuite
6
4
  module RequestLogger
7
5
  class Response
8
- attr_reader :status, :message, :headers, :body
6
+ include Utils::WarningHandler
7
+
8
+ attr_reader :status, :message, :headers, :body, :content_type, :content_length, :response_time
9
9
 
10
- def initialize(status:, message:, headers:, body:)
11
- @status = status.to_i # Ensure status is always an integer
10
+ def initialize(
11
+ status:,
12
+ message:,
13
+ headers:,
14
+ body:,
15
+ response_time: nil
16
+ )
17
+ @status = status.to_i
12
18
  @message = message
13
- @headers = headers || {} # Default to an empty hash if headers are nil
14
- @body = body || "" # Default to an empty string if body is nil
19
+ @headers = headers
20
+ @body = body
21
+ @content_type = extract_content_type
22
+ @content_length = extract_content_length
23
+ @response_time = response_time
24
+
25
+ validate_presence
15
26
  end
16
27
 
17
- # Check if the response is successful (2xx status codes)
18
28
  def success?
19
29
  status.between?(200, 299)
20
30
  end
21
31
 
22
- # Helper method to fetch specific headers in a case-insensitive way
23
32
  def header(key)
24
33
  headers[key.to_s.downcase] || headers[key.to_s]
25
34
  end
35
+
36
+ private
37
+
38
+ def extract_content_type
39
+ header("Content-Type") || "unknown"
40
+ end
41
+
42
+ def extract_content_length
43
+ length = header("Content-Length")
44
+ length ? length.to_i : 0
45
+ end
46
+
47
+ def validate_presence
48
+ warn_if_missing("Response Status", @status)
49
+ warn_if_missing("Response Headers", @headers)
50
+ end
26
51
  end
27
52
  end
28
53
  end
@@ -23,6 +23,19 @@ module DevSuite
23
23
  snake_case_class_name.to_sym
24
24
  end
25
25
  end
26
+
27
+ private
28
+
29
+ # Fetches a setting based on the provided key.
30
+ # This method should be overridden by subclasses to provide specific behavior.
31
+ #
32
+ # @param key [String] The key for the setting.
33
+ # @param default [Object] The default value to return if the key is not found.
34
+ def fetch_setting(_key, _default = nil)
35
+ # Example implementation
36
+ # Config.configuration.settings.get(key, default)
37
+ raise NotImplementedError
38
+ end
26
39
  end
27
40
  end
28
41
  end
@@ -6,6 +6,7 @@ module DevSuite
6
6
  module Component
7
7
  require_relative "base"
8
8
  require_relative "manager"
9
+ require_relative "validator"
9
10
  end
10
11
  end
11
12
  end