vigiles 0.1.0.pre.beta3 → 0.1.0.pre.beta4

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -1
  3. data/lib/vigiles/archive/extras.rb +4 -3
  4. data/lib/vigiles/archive/metadata.rb +3 -2
  5. data/lib/vigiles/archive/request.rb +18 -4
  6. data/lib/vigiles/archive.rb +15 -3
  7. data/lib/vigiles/constants.rb +7 -0
  8. data/lib/vigiles/middleware/record_conversation.rb +6 -22
  9. data/lib/vigiles/spec.rb +1 -1
  10. data/lib/vigiles/utilities/uri.rb +18 -0
  11. data/lib/vigiles/version.rb +1 -1
  12. data/lib/vigiles.rb +4 -1
  13. data/sorbet/rbi/gems/{activemodel@7.0.5.rbi → actioncable@7.1.3.3.rbi} +2 -2
  14. data/sorbet/rbi/gems/actionmailbox@7.1.3.3.rbi +8 -0
  15. data/sorbet/rbi/gems/{activerecord@7.0.5.rbi → actionmailer@7.1.3.3.rbi} +2 -2
  16. data/sorbet/rbi/gems/actionpack@7.1.3.3.rbi +20046 -0
  17. data/sorbet/rbi/gems/actiontext@7.1.3.3.rbi +8 -0
  18. data/sorbet/rbi/gems/actionview@7.1.3.3.rbi +15953 -0
  19. data/sorbet/rbi/gems/activejob@7.1.3.3.rbi +8 -0
  20. data/sorbet/rbi/gems/activemodel@7.1.3.3.rbi +6657 -0
  21. data/sorbet/rbi/gems/activerecord@7.1.3.3.rbi +41520 -0
  22. data/sorbet/rbi/gems/activestorage@7.1.3.3.rbi +8 -0
  23. data/sorbet/rbi/gems/activesupport@7.1.3.3.rbi +20570 -0
  24. data/sorbet/rbi/gems/base64@0.2.0.rbi +508 -0
  25. data/sorbet/rbi/gems/bigdecimal@3.1.8.rbi +77 -0
  26. data/sorbet/rbi/gems/builder@3.2.4.rbi +8 -0
  27. data/sorbet/rbi/gems/connection_pool@2.4.1.rbi +8 -0
  28. data/sorbet/rbi/gems/crass@1.0.6.rbi +622 -0
  29. data/sorbet/rbi/gems/date@3.3.4.rbi +74 -0
  30. data/sorbet/rbi/gems/drb@2.2.1.rbi +1346 -0
  31. data/sorbet/rbi/gems/globalid@1.2.1.rbi +8 -0
  32. data/sorbet/rbi/gems/i18n@1.14.5.rbi +2358 -0
  33. data/sorbet/rbi/gems/io-console@0.7.2.rbi +8 -0
  34. data/sorbet/rbi/gems/loofah@2.22.0.rbi +1080 -0
  35. data/sorbet/rbi/gems/{i18n@1.14.1.rbi → mail@2.8.1.rbi} +2 -2
  36. data/sorbet/rbi/gems/marcel@1.0.4.rbi +8 -0
  37. data/sorbet/rbi/gems/mini_mime@1.1.5.rbi +8 -0
  38. data/sorbet/rbi/gems/mutex_m@0.2.0.rbi +93 -0
  39. data/sorbet/rbi/gems/net-imap@0.4.11.rbi +8 -0
  40. data/sorbet/rbi/gems/net-pop@0.1.2.rbi +8 -0
  41. data/sorbet/rbi/gems/net-protocol@0.2.2.rbi +291 -0
  42. data/sorbet/rbi/gems/net-smtp@0.5.0.rbi +8 -0
  43. data/sorbet/rbi/gems/nio4r@2.7.3.rbi +8 -0
  44. data/sorbet/rbi/gems/nokogiri@1.16.5.rbi +7310 -0
  45. data/sorbet/rbi/gems/psych@5.1.2.rbi +1768 -0
  46. data/sorbet/rbi/gems/rack-session@2.0.0.rbi +729 -0
  47. data/sorbet/rbi/gems/rack-test@2.1.0.rbi +749 -0
  48. data/sorbet/rbi/gems/rack@3.0.11.rbi +5195 -0
  49. data/sorbet/rbi/gems/rackup@2.1.0.rbi +406 -0
  50. data/sorbet/rbi/gems/rails-dom-testing@2.2.0.rbi +691 -0
  51. data/sorbet/rbi/gems/rails-html-sanitizer@1.6.0.rbi +721 -0
  52. data/sorbet/rbi/gems/rails@7.1.3.3.rbi +8 -0
  53. data/sorbet/rbi/gems/railties@7.1.3.3.rbi +2167 -0
  54. data/sorbet/rbi/gems/rdoc@6.6.3.1.rbi +12715 -0
  55. data/sorbet/rbi/gems/reline@0.5.7.rbi +8 -0
  56. data/sorbet/rbi/gems/stringio@3.1.0.rbi +8 -0
  57. data/sorbet/rbi/gems/timeout@0.4.1.rbi +148 -0
  58. data/sorbet/rbi/gems/webrick@1.8.1.rbi +2606 -0
  59. data/sorbet/rbi/gems/websocket-driver@0.7.6.rbi +8 -0
  60. data/sorbet/rbi/gems/websocket-extensions@0.1.5.rbi +8 -0
  61. data/sorbet/rbi/gems/zeitwerk@2.6.13.rbi +1003 -0
  62. data/vigiles.gemspec +1 -1
  63. metadata +54 -7
  64. data/sorbet/rbi/gems/activesupport@7.0.5.rbi +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc7d3519a6e858e96fb583784e5fc6b79943ec60bf20e97437eb40552bb9583b
4
- data.tar.gz: d17b829ca3369c0324f8696943b53949be682bdfb0695fe19631f5fc9d299f34
3
+ metadata.gz: 1ebe4f039d4bb2b69d55ecc09714ad8ca498da080c1d29837b9c6ad4f4f455df
4
+ data.tar.gz: ca4c6d6221b06437e3a099282a6d70ab1ddacde85446ecfd78940a3b94de4ea6
5
5
  SHA512:
6
- metadata.gz: 4915409f03686c6181d3dfc54e1cc2a965a2808f0901f67e2a72836665ced0b13de3bfcab06cfff1227aac48b0aa0ff96e1c6ce4b24cff6c6210136e79d15c97
7
- data.tar.gz: f6ae4066b0195444ade50c2c60e21f5fdfbb1251d6050669e981ee5c7c2f7decd2dd22bbdbf6764c1404e78ac61ab4531f435b877b400527634a4569863bebfe
6
+ metadata.gz: 9c3e3a3057cfef634b85c2e91b004a43b0308d3c46015231166b2badaea0ca6a460d14584d5391bc35817c94ba3674cc16ada0bb7ccefd876547450d3ae37f7b
7
+ data.tar.gz: fd01e8c1ce72e058286c85d7c9eebeaeb3f14c81a25bb9c94b9b9aacc43dc84ddf166927bd0802222146cb21a24e816c3ddb82d00d79cc90bf7414b44bca1cfa
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@ require:
4
4
  - rubocop-sorbet
5
5
 
6
6
  AllCops:
7
- TargetRubyVersion: 2.7
7
+ TargetRubyVersion: 3.0
8
8
  Exclude:
9
9
  - "**/generators/**/*"
10
10
  - "**/sorbet/**/*"
@@ -22,5 +22,14 @@ Style/AccessModifierDeclarations:
22
22
  Enabled: true
23
23
  EnforcedStyle: inline
24
24
 
25
+ Style/Documentation:
26
+ Enabled: false
27
+
25
28
  Layout/LineLength:
26
29
  Max: 120
30
+
31
+ Metrics/AbcSize:
32
+ Enabled: false
33
+
34
+ Metrics/MethodLength:
35
+ Enabled: false
@@ -3,11 +3,12 @@
3
3
 
4
4
  module Vigiles
5
5
  module Archive
6
- class Extras < T::Struct;
7
- const :request_env, T.untyped
6
+ class Extras < T::Struct
7
+ const :request_env, T::Hash[T.untyped, T.untyped]
8
8
 
9
+ sig { params(request_env: T::Hash[T.untyped, T.untyped]).returns(Extras) }
9
10
  def self.from(request_env)
10
- Extras.new(request_env:)
11
+ Extras.new(request_env: request_env)
11
12
  end
12
13
  end
13
14
  end
@@ -4,10 +4,11 @@
4
4
  module Vigiles
5
5
  module Archive
6
6
  class Metadata < T::Struct
7
- const :request_env, T.untyped
7
+ const :request_env, T::Hash[T.untyped, T.untyped]
8
8
 
9
+ sig { params(request_env: T::Hash[T.untyped, T.untyped]).returns(Metadata) }
9
10
  def self.from(request_env)
10
- Metadata.new(request_env:)
11
+ Metadata.new(request_env: request_env)
11
12
  end
12
13
  end
13
14
  end
@@ -8,6 +8,20 @@ module Vigiles
8
8
  extend T::Sig
9
9
 
10
10
  class Request < T::Struct
11
+ # raised when some request parameters are either bad/invalid
12
+ # or absent. for example, it is required the request url always
13
+ # be present, and have either http or https scheme.
14
+ class InvalidParameterError < StandardError
15
+ sig { returns(String) }
16
+ attr_reader :parameter
17
+
18
+ sig { params(parameter: String).void }
19
+ def initialize(parameter)
20
+ @parameter = parameter
21
+ super
22
+ end
23
+ end
24
+
11
25
  const :content_type, String
12
26
  const :http_method, Types::HttpMethod
13
27
  const :user_agent, String
@@ -24,17 +38,17 @@ module Vigiles
24
38
  sig { params(request: ActionDispatch::Request).returns(Request) }
25
39
  def self.from(request)
26
40
  Request.new(
27
- content_type: request.content_type,
28
- user_agent: request.user_agent,
41
+ content_type: request.content_type || (raise InvalidParameterError, "content_type"),
42
+ user_agent: request.user_agent || "unknown_user_agent",
29
43
  timestamp: DateTime.now,
30
44
  remote_ip: IPAddr.new(request.remote_ip),
31
45
  protocol: request.protocol,
32
46
  headers: {},
33
- origin: request.origin || "n/a",
47
+ origin: request.origin || "unknown_origin_url",
34
48
  payload: request.body.read,
35
49
  http_method: Types::HttpMethod.deserialize(request.method),
36
50
  path: request.path,
37
- url: URI.parse(request.url),
51
+ url: Utilities::URI.parse_into_http_or_https(request.url),
38
52
  id: request.request_id
39
53
  )
40
54
  end
@@ -1,8 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "action_dispatch"
5
-
6
4
  module Vigiles
7
5
  module Archive
8
6
  extend T::Sig
@@ -10,6 +8,14 @@ module Vigiles
10
8
  Types = Vigiles::Types
11
9
  ContentType = Types::ContentType
12
10
 
11
+ class UnrecordableRequestError < StandardError
12
+ sig { params(reason: String).void }
13
+ def initialize(reason)
14
+ @reason = reason
15
+ super
16
+ end
17
+ end
18
+
13
19
  sig { params(ad_response: ActionDispatch::Response).returns(T.nilable(Conversation)) }
14
20
  def self.record_conversation(ad_response)
15
21
  # preferring to call `response.request` instead of preparing a new
@@ -26,8 +32,10 @@ module Vigiles
26
32
  case (content_type = request.content_type)
27
33
  when ContentType::ApplicationJson.serialize then record_json_conversation(request:, response:, metadata:, extras:)
28
34
  when ContentType::TextHtml.serialize then record_html_conversation(request:, response:, metadata:, extras:)
29
- else record_conversation_with_unknown_content_type(request:)
35
+ else record_conversation_with_unknown_content_type(request:, response:, metadata:, extras:)
30
36
  end
37
+ rescue Request::InvalidParameterError => e
38
+ raise UnrecordableRequestError, "#{e.parameter} considered invalid"
31
39
  end
32
40
 
33
41
  sig do
@@ -60,7 +68,11 @@ module Vigiles
60
68
  )
61
69
  rescue => e
62
70
  end
71
+
72
+ sig { params(request: Request, response: Response, metadata: Metadata, extras: Extras).returns(T.nilable(Conversation)) }
63
73
  private_class_method def self.record_html_conversation(request:, response:, metadata:, extras:); end
74
+
75
+ sig { params(request: Request, response: Response, metadata: Metadata, extras: Extras).returns(T.nilable(Conversation)) }
64
76
  private_class_method def self.record_conversation_with_unknown_content_type(
65
77
  request:,
66
78
  response:,
@@ -0,0 +1,7 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vigiles
5
+ module Constants
6
+ end
7
+ end
@@ -1,26 +1,13 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "rack"
5
-
4
+ require "logger"
6
5
  module Vigiles
7
6
  module Middleware
8
7
  class RecordConversation
9
- class Options < T::Struct
10
- const :logger, T.untyped
11
-
12
- sig { returns(Options) }
13
- def self.defaults
14
- Options.new(
15
- logger: Rails.logger
16
- )
17
- end
18
- end
19
-
20
- sig { params(app: T.untyped, options: Options).void }
21
- def initialize(app, options = Options.defaults)
22
- @app = app
23
- @logger = options.logger
8
+ sig { params(app: T.untyped).void }
9
+ def initialize(app)
10
+ @app = app
24
11
  end
25
12
 
26
13
  sig { params(env: T.untyped).returns(T.untyped) }
@@ -30,15 +17,12 @@ module Vigiles
30
17
  end
31
18
  end
32
19
 
20
+ sig { params(blk: T.proc.returns(T.untyped)).returns(T.untyped) }
33
21
  private def record_conversation(&blk)
34
22
  rack_response = blk.call
35
23
  _, _, body = rack_response
36
24
  response = body.instance_variable_get(:@response)
37
- unless response.nil?
38
- convo = Vigiles.maybe_record_conversation(response)
39
- @logger.info "conversation recorded: conversation_id=#{convo&.id}" if convo
40
- end
41
-
25
+ Vigiles.maybe_record_conversation(response) unless response.nil?
42
26
  rack_response
43
27
  ensure
44
28
  rack_response
data/lib/vigiles/spec.rb CHANGED
@@ -4,6 +4,6 @@
4
4
  module Vigiles
5
5
  class Spec < T::Struct
6
6
  sig { returns(Spec) }
7
- def self.make_default_spec; end
7
+ def self.make_default_spec = Spec.new
8
8
  end
9
9
  end
@@ -0,0 +1,18 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vigiles
5
+ module Utilities
6
+ module URI
7
+ extend T::Sig
8
+
9
+ sig { params(url: String).returns(T.any(::URI::HTTP, ::URI::HTTPS)) }
10
+ def self.parse_into_http_or_https(url)
11
+ parsed_uri = ::URI.parse(url)
12
+ raise unless parsed_uri.is_a?(::URI::HTTP) || parsed_uri.is_a?(::URI::HTTPS)
13
+
14
+ parsed_uri
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Vigiles
5
- VERSION = "0.1.0-beta3"
5
+ VERSION = "0.1.0-beta4"
6
6
  end
data/lib/vigiles.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  require "zeitwerk"
5
5
  require "sorbet-runtime"
6
6
  require_relative "core_ext"
7
+ require "action_dispatch"
7
8
 
8
9
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
9
10
  loader.ignore("#{__dir__}/generators")
@@ -19,11 +20,13 @@ module Vigiles
19
20
  return unless should_record?(response)
20
21
 
21
22
  Archive.record_conversation(response)
23
+ rescue Archive::UnrecordableRequestError
24
+ nil
22
25
  end
23
26
 
24
27
  sig { params(blk: T.untyped).void }
25
28
  def self.configure(&blk)
26
- default_spec = Vigiles::Spec.default_specification
29
+ default_spec = Vigiles::Spec.make_default_spec
27
30
  blk.call(default_spec)
28
31
  end
29
32
 
@@ -1,8 +1,8 @@
1
1
  # typed: true
2
2
 
3
3
  # DO NOT EDIT MANUALLY
4
- # This is an autogenerated file for types exported from the `activemodel` gem.
5
- # Please instead update this file by running `bin/tapioca gem activemodel`.
4
+ # This is an autogenerated file for types exported from the `actioncable` gem.
5
+ # Please instead update this file by running `bin/tapioca gem actioncable`.
6
6
 
7
7
  # THIS IS AN EMPTY RBI FILE.
8
8
  # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
@@ -0,0 +1,8 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `actionmailbox` gem.
5
+ # Please instead update this file by running `bin/tapioca gem actionmailbox`.
6
+
7
+ # THIS IS AN EMPTY RBI FILE.
8
+ # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
@@ -1,8 +1,8 @@
1
1
  # typed: true
2
2
 
3
3
  # DO NOT EDIT MANUALLY
4
- # This is an autogenerated file for types exported from the `activerecord` gem.
5
- # Please instead update this file by running `bin/tapioca gem activerecord`.
4
+ # This is an autogenerated file for types exported from the `actionmailer` gem.
5
+ # Please instead update this file by running `bin/tapioca gem actionmailer`.
6
6
 
7
7
  # THIS IS AN EMPTY RBI FILE.
8
8
  # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem