sofia 0.1.0 → 0.1.2

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/CLAUDE.md +53 -0
  4. data/README.md +67 -1
  5. data/lib/sofia/adapter/net_http.rb +28 -14
  6. data/lib/sofia/adapter/soren.rb +101 -0
  7. data/lib/sofia/adapter.rb +1 -0
  8. data/lib/sofia/client.rb +9 -4
  9. data/lib/sofia/defaults/timeouts.rb +12 -0
  10. data/lib/sofia/{helper.rb → defaults.rb} +2 -3
  11. data/lib/sofia/error/{invalid_json.rb → parser_error.rb} +1 -1
  12. data/lib/sofia/error.rb +1 -1
  13. data/lib/sofia/options.rb +29 -0
  14. data/lib/sofia/request.rb +18 -14
  15. data/lib/sofia/response.rb +3 -3
  16. data/lib/sofia/types/client/adapter.rb +43 -0
  17. data/lib/sofia/types/client/base_url.rb +35 -0
  18. data/lib/sofia/types/client/body.rb +62 -0
  19. data/lib/sofia/types/client/headers.rb +58 -0
  20. data/lib/sofia/types/client/options.rb +33 -0
  21. data/lib/sofia/types/client/params.rb +57 -0
  22. data/lib/sofia/types/client/path.rb +30 -0
  23. data/lib/sofia/types/client.rb +16 -0
  24. data/lib/sofia/types/options/timeout/base.rb +34 -0
  25. data/lib/sofia/types/options/timeout/connection.rb +12 -0
  26. data/lib/sofia/types/options/timeout/read.rb +12 -0
  27. data/lib/sofia/types/options/timeout/write.rb +12 -0
  28. data/lib/sofia/types/options/timeout.rb +15 -0
  29. data/lib/sofia/types/options.rb +10 -0
  30. data/lib/sofia/types.rb +2 -6
  31. data/lib/sofia/version.rb +1 -1
  32. data/lib/sofia.rb +7 -5
  33. data/sorbet/rbi/gems/soren@0.1.2.rbi +934 -0
  34. metadata +38 -11
  35. data/lib/sofia/types/adapter.rb +0 -39
  36. data/lib/sofia/types/base_url.rb +0 -33
  37. data/lib/sofia/types/body.rb +0 -60
  38. data/lib/sofia/types/headers.rb +0 -56
  39. data/lib/sofia/types/params.rb +0 -56
  40. data/lib/sofia/types/path.rb +0 -28
@@ -0,0 +1,58 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Client
7
+ class Headers
8
+
9
+ #: (?untyped headers) -> void
10
+ def initialize(headers = {})
11
+ defaults = { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
12
+ headers = validate_and_normalize(headers)
13
+ @headers = defaults.merge(headers) #: Hash[String, String]
14
+ end
15
+
16
+ #: (untyped key) -> void
17
+ def [](key)
18
+ @headers[key.to_s]
19
+ end
20
+
21
+ #: (untyped key, untyped value) -> void
22
+ def []=(key, value)
23
+ @headers[key.to_s] = value.to_s
24
+ end
25
+
26
+ #: -> Hash[String, String]
27
+ def to_h
28
+ @headers.dup
29
+ end
30
+
31
+ #: () { ([String, String]) -> untyped } -> Hash[String, String]
32
+ def each(&block) # rubocop:disable Naming/BlockForwarding
33
+ @headers.each(&block) # rubocop:disable Naming/BlockForwarding
34
+ end
35
+
36
+ private
37
+
38
+ #: (untyped) -> Hash[String, String]
39
+ def validate_and_normalize(headers)
40
+ Kernel.raise Sofia::Error::ArgumentError, 'headers must be a Hash' unless headers.is_a?(Hash)
41
+ normalized = {}
42
+
43
+ headers.each do |key, value|
44
+ next if value.nil?
45
+
46
+ if value.is_a?(Hash) || value.is_a?(Array)
47
+ Kernel.raise Sofia::Error::ArgumentError, "invalid header value for #{key}"
48
+ end
49
+
50
+ normalized[key.to_s] = value.to_s
51
+ end
52
+
53
+ normalized
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,33 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Client
7
+ class Options
8
+
9
+ #: Sofia::Options
10
+ attr_reader :value
11
+
12
+ #: (?untyped options) -> void
13
+ def initialize(options = nil)
14
+ @value = build(options) #: Sofia::Options
15
+ end
16
+
17
+ private
18
+
19
+ #: (untyped) -> Sofia::Options
20
+ def build(options)
21
+ case options
22
+ when nil
23
+ Sofia::Options.new
24
+ when Hash
25
+ Sofia::Options.new(**options)
26
+ else
27
+ Kernel.raise Sofia::Error::ArgumentError, "options must be a Hash, got #{options.class}"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,57 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Client
7
+ class Params
8
+ extend T::Sig
9
+
10
+ #: (?untyped params) -> void
11
+ def initialize(params = {}) # rubocop:disable Style/OptionHash
12
+ @params = validate_and_normalize(params || {}) #: Hash[String, String]
13
+ end
14
+
15
+ #: (untyped key) -> void
16
+ def [](key)
17
+ @params[key.to_s]
18
+ end
19
+
20
+ #: (untyped key, untyped value) -> void
21
+ def []=(key, value)
22
+ @params[key.to_s] = value.to_s
23
+ end
24
+
25
+ #: -> Hash[String, String]
26
+ def to_h
27
+ @params.dup
28
+ end
29
+
30
+ #: -> String
31
+ def to_s
32
+ URI.encode_www_form(@params)
33
+ end
34
+
35
+ private
36
+
37
+ #: (untyped) -> Hash[String, String]
38
+ def validate_and_normalize(headers)
39
+ Kernel.raise Sofia::Error::ArgumentError, 'params must be a Hash' unless headers.is_a?(Hash)
40
+ normalized = {}
41
+
42
+ headers.each do |key, value|
43
+ next if value.nil?
44
+
45
+ if value.is_a?(Hash) || value.is_a?(Array)
46
+ Kernel.raise Sofia::Error::ArgumentError, "invalid param value for #{key}"
47
+ end
48
+
49
+ normalized[key.to_s] = value.to_s
50
+ end
51
+
52
+ normalized
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,30 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Client
7
+ class Path
8
+
9
+ #: (?untyped path) -> void
10
+ def initialize(path = '/')
11
+ @path = validate_and_normalize(path).freeze #: String
12
+ end
13
+
14
+ #: -> String
15
+ def to_s
16
+ @path
17
+ end
18
+
19
+ private
20
+
21
+ #: (untyped) -> String
22
+ def validate_and_normalize(path)
23
+ Kernel.raise Sofia::Error::ArgumentError, 'path must be a String' unless path.is_a?(String)
24
+
25
+ path.start_with?('/') ? path : "/#{path}"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Client; end
7
+ end
8
+ end
9
+
10
+ require_relative 'client/adapter'
11
+ require_relative 'client/base_url'
12
+ require_relative 'client/headers'
13
+ require_relative 'client/body'
14
+ require_relative 'client/params'
15
+ require_relative 'client/path'
16
+ require_relative 'client/options'
@@ -0,0 +1,34 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Options
7
+ module Timeout
8
+ class Base
9
+
10
+ #: (untyped value) -> void
11
+ def initialize(value)
12
+ @value = validate_and_normalize(value) #: Float
13
+ end
14
+
15
+ #: -> Float
16
+ def to_f
17
+ @value
18
+ end
19
+
20
+ private
21
+
22
+ #: (untyped) -> Float
23
+ def validate_and_normalize(value)
24
+ unless value.is_a?(Numeric) && value.to_f > 0
25
+ raise Sofia::Error::ArgumentError, "timeout must be a positive number, got #{value.inspect}"
26
+ end
27
+
28
+ value.to_f
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,12 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Options
7
+ module Timeout
8
+ class Connection < Base; end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Options
7
+ module Timeout
8
+ class Read < Base; end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Options
7
+ module Timeout
8
+ class Write < Base; end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Options
7
+ module Timeout; end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative 'timeout/base'
13
+ require_relative 'timeout/read'
14
+ require_relative 'timeout/write'
15
+ require_relative 'timeout/connection'
@@ -0,0 +1,10 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Sofia
5
+ module Types
6
+ module Options; end
7
+ end
8
+ end
9
+
10
+ require_relative 'options/timeout'
data/lib/sofia/types.rb CHANGED
@@ -5,9 +5,5 @@ module Sofia
5
5
  module Types; end
6
6
  end
7
7
 
8
- require_relative 'types/adapter'
9
- require_relative 'types/base_url'
10
- require_relative 'types/headers'
11
- require_relative 'types/body'
12
- require_relative 'types/params'
13
- require_relative 'types/path'
8
+ require_relative 'types/client'
9
+ require_relative 'types/options'
data/lib/sofia/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sofia
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/sofia.rb CHANGED
@@ -8,18 +8,20 @@ require 'sorbet-runtime'
8
8
  require 'byebug'
9
9
 
10
10
  require_relative 'sofia/version'
11
+ require_relative 'sofia/error'
12
+ require_relative 'sofia/defaults'
13
+ require_relative 'sofia/types'
14
+ require_relative 'sofia/options'
11
15
  require_relative 'sofia/request'
12
16
  require_relative 'sofia/response'
13
17
  require_relative 'sofia/adapter'
14
18
  require_relative 'sofia/client'
15
- require_relative 'sofia/error'
16
- require_relative 'sofia/types'
17
19
 
18
20
  module Sofia
19
21
  class << self
20
- #: (base_url: untyped, ?adapter: untyped) -> Sofia::Client
21
- def new(base_url:, adapter: nil)
22
- Client.new(base_url: base_url, adapter: adapter)
22
+ #: (base_url: untyped, ?adapter: untyped, ?options: untyped) -> Sofia::Client
23
+ def new(base_url:, adapter: nil, options: nil)
24
+ Client.new(base_url: base_url, adapter: adapter, options: options)
23
25
  end
24
26
  end
25
27
  end