dev_suite 0.2.7 → 0.2.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/ci.yml +1 -1
  4. data/.sonarcloud.properties +23 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +17 -33
  7. data/README.md +216 -0
  8. data/dev_suite.gemspec +1 -0
  9. data/examples/helpers/api_helper.rb +51 -0
  10. data/examples/helpers/data_helper.rb +72 -0
  11. data/examples/helpers/helpers.rb +4 -0
  12. data/examples/workflow/basic_workflow.rb +15 -0
  13. data/examples/workflow/composite_workflow.rb +21 -0
  14. data/examples/workflow/conditional_workflow.rb +17 -0
  15. data/examples/workflow/full_workflow.rb +79 -0
  16. data/examples/workflow/loop_workflow.rb +17 -0
  17. data/examples/workflow/order_processing_workflow.rb +163 -0
  18. data/examples/workflow/parallel_workflow.rb +17 -0
  19. data/lib/dev_suite/dev_suite.rb +3 -0
  20. data/lib/dev_suite/method_tracer/config/config.rb +11 -0
  21. data/lib/dev_suite/method_tracer/config/configuration.rb +16 -0
  22. data/lib/dev_suite/method_tracer/config.rb +9 -0
  23. data/lib/dev_suite/method_tracer/helpers.rb +41 -0
  24. data/lib/dev_suite/method_tracer/logger.rb +46 -0
  25. data/lib/dev_suite/method_tracer/method_tracer.rb +20 -0
  26. data/lib/dev_suite/method_tracer/tracer.rb +65 -0
  27. data/lib/dev_suite/method_tracer.rb +7 -0
  28. data/lib/dev_suite/request_builder/builder/base.rb +27 -0
  29. data/lib/dev_suite/request_builder/builder/builder.rb +10 -0
  30. data/lib/dev_suite/request_builder/builder/http.rb +32 -0
  31. data/lib/dev_suite/request_builder/builder.rb +9 -0
  32. data/lib/dev_suite/request_builder/config/config.rb +11 -0
  33. data/lib/dev_suite/request_builder/config/configuration.rb +24 -0
  34. data/lib/dev_suite/request_builder/config.rb +9 -0
  35. data/lib/dev_suite/request_builder/formatter/base.rb +13 -0
  36. data/lib/dev_suite/request_builder/formatter/formatter.rb +10 -0
  37. data/lib/dev_suite/request_builder/formatter/graphql.rb +19 -0
  38. data/lib/dev_suite/request_builder/formatter.rb +9 -0
  39. data/lib/dev_suite/request_builder/request_builder.rb +21 -0
  40. data/lib/dev_suite/request_builder/tool/base.rb +19 -0
  41. data/lib/dev_suite/request_builder/tool/curl.rb +91 -0
  42. data/lib/dev_suite/request_builder/tool/tool.rb +11 -0
  43. data/lib/dev_suite/request_builder/tool/validator/curl.rb +38 -0
  44. data/lib/dev_suite/request_builder/tool/validator/validator.rb +11 -0
  45. data/lib/dev_suite/request_builder/tool/validator.rb +11 -0
  46. data/lib/dev_suite/request_builder/tool.rb +9 -0
  47. data/lib/dev_suite/request_builder.rb +7 -0
  48. data/lib/dev_suite/request_logger/adapter/adapter.rb +11 -9
  49. data/lib/dev_suite/request_logger/adapter/faraday.rb +12 -1
  50. data/lib/dev_suite/request_logger/adapter/middleware/faraday.rb +3 -3
  51. data/lib/dev_suite/request_logger/adapter/net_http.rb +15 -6
  52. data/lib/dev_suite/request_logger/config/configuration.rb +1 -0
  53. data/lib/dev_suite/request_logger/extractor/base.rb +8 -2
  54. data/lib/dev_suite/request_logger/extractor/extractor.rb +5 -6
  55. data/lib/dev_suite/request_logger/extractor/faraday.rb +32 -14
  56. data/lib/dev_suite/request_logger/extractor/net_http.rb +53 -12
  57. data/lib/dev_suite/request_logger/logger.rb +9 -3
  58. data/lib/dev_suite/request_logger/request.rb +12 -0
  59. data/lib/dev_suite/request_logger/response.rb +34 -9
  60. data/lib/dev_suite/utils/construct/component/base.rb +13 -0
  61. data/lib/dev_suite/utils/construct/component/component.rb +1 -0
  62. data/lib/dev_suite/utils/construct/component/manager.rb +27 -10
  63. data/lib/dev_suite/utils/construct/component/validator/base.rb +25 -0
  64. data/lib/dev_suite/utils/construct/component/validator/validation_error.rb +21 -0
  65. data/lib/dev_suite/utils/construct/component/validator/validation_rule.rb +68 -0
  66. data/lib/dev_suite/utils/construct/component/validator/validator.rb +15 -0
  67. data/lib/dev_suite/utils/construct/component/validator.rb +13 -0
  68. data/lib/dev_suite/utils/construct/config/dependency_handler.rb +25 -34
  69. data/lib/dev_suite/utils/construct/config/settings/base.rb +43 -26
  70. data/lib/dev_suite/utils/data/base_operations.rb +61 -0
  71. data/lib/dev_suite/utils/data/data.rb +19 -0
  72. data/lib/dev_suite/utils/data/path_access.rb +172 -0
  73. data/lib/dev_suite/utils/data/search_filter.rb +60 -0
  74. data/lib/dev_suite/utils/data/serialization.rb +29 -0
  75. data/lib/dev_suite/utils/data/transformations.rb +45 -0
  76. data/lib/dev_suite/utils/data.rb +9 -0
  77. data/lib/dev_suite/utils/dependency_loader.rb +2 -2
  78. data/lib/dev_suite/utils/emoji.rb +19 -0
  79. data/lib/dev_suite/utils/file_loader/file_loader.rb +1 -5
  80. data/lib/dev_suite/utils/file_loader/loader/json.rb +4 -1
  81. data/lib/dev_suite/utils/file_loader/loader/loader.rb +23 -19
  82. data/lib/dev_suite/utils/file_loader/loader.rb +0 -2
  83. data/lib/dev_suite/utils/file_writer/atomic_writer.rb +53 -0
  84. data/lib/dev_suite/utils/file_writer/backup_manager.rb +21 -0
  85. data/lib/dev_suite/utils/file_writer/file_writer.rb +24 -0
  86. data/lib/dev_suite/utils/file_writer/writer/base.rb +43 -0
  87. data/lib/dev_suite/utils/file_writer/writer/json.rb +24 -0
  88. data/lib/dev_suite/utils/file_writer/writer/text.rb +27 -0
  89. data/lib/dev_suite/utils/file_writer/writer/writer.rb +14 -0
  90. data/lib/dev_suite/utils/file_writer/writer/yaml.rb +44 -0
  91. data/lib/dev_suite/utils/file_writer/writer.rb +11 -0
  92. data/lib/dev_suite/utils/file_writer/writer_manager.rb +32 -0
  93. data/lib/dev_suite/utils/file_writer.rb +9 -0
  94. data/lib/dev_suite/utils/logger.rb +7 -5
  95. data/lib/dev_suite/utils/store/config/config.rb +13 -0
  96. data/lib/dev_suite/utils/store/config/configuration.rb +30 -0
  97. data/lib/dev_suite/utils/store/config.rb +11 -0
  98. data/lib/dev_suite/utils/store/driver/base.rb +35 -0
  99. data/lib/dev_suite/utils/store/driver/driver.rb +18 -0
  100. data/lib/dev_suite/utils/store/driver/file.rb +61 -0
  101. data/lib/dev_suite/utils/store/driver/memory.rb +42 -0
  102. data/lib/dev_suite/utils/store/driver.rb +11 -0
  103. data/lib/dev_suite/utils/store/store.rb +69 -0
  104. data/lib/dev_suite/utils/store.rb +9 -0
  105. data/lib/dev_suite/utils/utils.rb +17 -5
  106. data/lib/dev_suite/utils/warning_handler.rb +25 -0
  107. data/lib/dev_suite/version.rb +1 -1
  108. data/lib/dev_suite/workflow/engine.rb +27 -0
  109. data/lib/dev_suite/workflow/step/base.rb +56 -0
  110. data/lib/dev_suite/workflow/step/composite.rb +27 -0
  111. data/lib/dev_suite/workflow/step/conditional.rb +23 -0
  112. data/lib/dev_suite/workflow/step/loop.rb +21 -0
  113. data/lib/dev_suite/workflow/step/parallel.rb +18 -0
  114. data/lib/dev_suite/workflow/step/step.rb +21 -0
  115. data/lib/dev_suite/workflow/step.rb +9 -0
  116. data/lib/dev_suite/workflow/step_context.rb +46 -0
  117. data/lib/dev_suite/workflow/workflow.rb +39 -0
  118. data/lib/dev_suite/workflow.rb +7 -0
  119. metadata +101 -3
  120. 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