openfeature-sdk-sorbet 0.2.0.2 → 0.3.0

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -1
  3. data/.ruby-version +1 -1
  4. data/.tool-versions +1 -1
  5. data/CHANGELOG.md +9 -6
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +55 -49
  8. data/README.md +23 -6
  9. data/lib/open_feature/client.rb +90 -32
  10. data/lib/open_feature/client_metadata.rb +1 -0
  11. data/lib/open_feature/evaluation_context.rb +7 -5
  12. data/lib/open_feature/evaluation_details.rb +2 -2
  13. data/lib/open_feature/hook.rb +41 -1
  14. data/lib/open_feature/hook_context.rb +30 -0
  15. data/lib/open_feature/hooks.rb +22 -0
  16. data/lib/open_feature/multiple_source_provider.rb +28 -12
  17. data/lib/open_feature/no_op_provider.rb +2 -3
  18. data/lib/open_feature/provider.rb +16 -2
  19. data/lib/open_feature/provider_status.rb +13 -0
  20. data/lib/open_feature.rb +9 -2
  21. data/sorbet/rbi/gems/.gitattributes +1 -0
  22. data/sorbet/rbi/gems/{json@2.6.3.rbi → json@2.7.1.rbi} +80 -60
  23. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14237 -0
  24. data/sorbet/rbi/gems/{minitest@5.18.0.rbi → minitest@5.21.2.rbi} +299 -258
  25. data/sorbet/rbi/gems/{parallel@1.23.0.rbi → parallel@1.24.0.rbi} +8 -1
  26. data/sorbet/rbi/gems/{parser@3.2.2.1.rbi → parser@3.3.0.5.rbi} +438 -2219
  27. data/sorbet/rbi/gems/prism@0.19.0.rbi +25199 -0
  28. data/sorbet/rbi/gems/psych@5.1.2.rbi +1731 -0
  29. data/sorbet/rbi/gems/racc@1.7.3.rbi +157 -0
  30. data/sorbet/rbi/gems/{rake@13.0.6.rbi → rake@13.1.0.rbi} +68 -65
  31. data/sorbet/rbi/gems/{rbi@0.0.16.rbi → rbi@0.1.6.rbi} +628 -755
  32. data/sorbet/rbi/gems/{regexp_parser@2.8.0.rbi → regexp_parser@2.9.0.rbi} +203 -180
  33. data/sorbet/rbi/gems/{rexml@3.2.5.rbi → rexml@3.2.6.rbi} +116 -52
  34. data/sorbet/rbi/gems/{rubocop-ast@1.28.1.rbi → rubocop-ast@1.30.0.rbi} +178 -84
  35. data/sorbet/rbi/gems/{rubocop-minitest@0.31.0.rbi → rubocop-minitest@0.34.5.rbi} +280 -232
  36. data/sorbet/rbi/gems/{rubocop-performance@1.17.1.rbi → rubocop-performance@1.20.2.rbi} +397 -172
  37. data/sorbet/rbi/gems/{rubocop-sorbet@0.7.0.rbi → rubocop-sorbet@0.7.6.rbi} +728 -261
  38. data/sorbet/rbi/gems/{rubocop@1.51.0.rbi → rubocop@1.60.2.rbi} +4006 -1936
  39. data/sorbet/rbi/gems/spoom@1.2.1.rbi +17 -56
  40. data/sorbet/rbi/gems/stringio@3.1.0.rbi +8 -0
  41. data/sorbet/rbi/gems/{tapioca@0.11.6.rbi → tapioca@0.11.17.rbi} +778 -576
  42. data/sorbet/rbi/gems/{thor@1.2.2.rbi → thor@1.3.0.rbi} +775 -395
  43. data/sorbet/rbi/gems/yard-sorbet@0.8.1.rbi +1 -1
  44. data/sorbet/rbi/gems/yard@0.9.34.rbi +2 -2
  45. data/sorbet/rbi/gems/{zeitwerk@2.6.8.rbi → zeitwerk@2.6.12.rbi} +78 -67
  46. data/sorbet/tapioca/config.yml +2 -2
  47. data/sorbet/tapioca/require.rb +3 -1
  48. metadata +36 -31
  49. data/openfeature-sdk-sorbet.gemspec +0 -35
  50. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +0 -1083
  51. data/sorbet/rbi/gems/irb@1.6.4.rbi +0 -342
  52. data/sorbet/rbi/gems/unparser@0.6.7.rbi +0 -4524
  53. /data/sorbet/rbi/gems/{io-console@0.6.0.rbi → io-console@0.7.2.rbi} +0 -0
  54. /data/sorbet/rbi/gems/{reline@0.3.3.rbi → reline@0.4.2.rbi} +0 -0
  55. /data/sorbet/rbi/gems/{unicode-display_width@2.4.2.rbi → unicode-display_width@2.5.0.rbi} +0 -0
@@ -0,0 +1,30 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module OpenFeature
5
+ # See https://openfeature.dev/specification/sections/hooks#41-hook-context
6
+ # See Requirement 4.1.1, 4.1.3, 4.1.4
7
+ # TODO: Requirement 4.1.2
8
+ class HookContext < T::Struct
9
+ extend T::Generic
10
+ extend T::Sig
11
+
12
+ include T::Struct::ActsAsComparable
13
+
14
+ Value = type_member
15
+ const :flag_key, String
16
+ const :flag_type, String
17
+ const :evaluation_context, EvaluationContext
18
+ const :default_value, Value
19
+ const :client_metadata, ClientMetadata
20
+ const :provider_metadata, ProviderMetadata
21
+
22
+ # Needed as opposed to .with due to https://sorbet.org/docs/tstruct#from_hash-gotchas
23
+ sig { params(new_context: EvaluationContext).returns(HookContext[Value]) }
24
+ def with_new_evaluation_context(new_context)
25
+ OpenFeature::HookContext.new(flag_key:, flag_type:, default_value:,
26
+ evaluation_context: new_context, client_metadata:,
27
+ provider_metadata:)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module OpenFeature
5
+ # Represents full set of hooks with helper methods for filtering and sequencing each subtype
6
+ class Hooks < T::Struct
7
+ extend T::Generic
8
+ extend T::Sig
9
+ const :global, T::Array[Hook], default: []
10
+ const :provider, T::Array[Hook], default: []
11
+ const :client, T::Array[Hook], default: []
12
+ const :invocation, T::Array[Hook], default: []
13
+
14
+ # See Requirement 4.4.2
15
+ # TODO: when there is >1 subtype of hook will need to filter and not simply re-cast
16
+ # ACHTUNG! T.cast is safe for now but will need to be updated after ^
17
+ sig { returns(T::Array[Hook::BeforeHook]) }
18
+ def before
19
+ T.cast(global + client + invocation + provider, T::Array[Hook::BeforeHook])
20
+ end
21
+ end
22
+ end
@@ -7,19 +7,18 @@ module OpenFeature
7
7
  # The providers will be evaluated in that order and the first
8
8
  # non-error result will be used. If all sources return an error
9
9
  # then the default value is used.
10
- class MultipleSourceProvider
10
+ class MultipleSourceProvider < Provider
11
11
  extend T::Sig
12
12
 
13
- include Provider
14
-
15
13
  sig { params(providers: T::Array[Provider]).void }
16
14
  def initialize(providers:)
17
15
  @providers = providers
16
+ super(ProviderStatus::NotReady)
18
17
  end
19
18
 
20
19
  sig { override.returns(ProviderMetadata) }
21
20
  def metadata
22
- ProviderMetadata.new(name: "Multiple Sources: #{providers.map(&:metadata).map(&:name).join(", ")}")
21
+ ProviderMetadata.new(name: "Multiple Sources: #{providers.map { |provider| provider.metadata.name }.join(", ")}")
23
22
  end
24
23
 
25
24
  sig { override.returns(T::Array[Hook]) }
@@ -27,6 +26,23 @@ module OpenFeature
27
26
  providers.flat_map(&:hooks)
28
27
  end
29
28
 
29
+ sig { override.params(context: EvaluationContext).void }
30
+ def init(context:)
31
+ providers.each { |provider| provider.init(context:) }
32
+ @status = if providers.all? { |provider| provider.status == ProviderStatus::Ready }
33
+ ProviderStatus::Ready
34
+ else
35
+ ProviderStatus::Error
36
+ end
37
+ rescue StandardError
38
+ @status = ProviderStatus::Error
39
+ end
40
+
41
+ sig { override.void }
42
+ def shutdown
43
+ providers.each(&:shutdown)
44
+ end
45
+
30
46
  sig do
31
47
  override
32
48
  .params(
@@ -37,8 +53,8 @@ module OpenFeature
37
53
  .returns(ResolutionDetails[T::Boolean])
38
54
  end
39
55
  def resolve_boolean_value(flag_key:, default_value:, context: nil)
40
- resolve_from_sources(default_value: default_value) do |provider|
41
- provider.resolve_boolean_value(flag_key: flag_key, default_value: default_value, context: context)
56
+ resolve_from_sources(default_value:) do |provider|
57
+ provider.resolve_boolean_value(flag_key:, default_value:)
42
58
  end
43
59
  end
44
60
 
@@ -52,8 +68,8 @@ module OpenFeature
52
68
  .returns(ResolutionDetails[Numeric])
53
69
  end
54
70
  def resolve_number_value(flag_key:, default_value:, context: nil)
55
- resolve_from_sources(default_value: default_value) do |provider|
56
- provider.resolve_number_value(flag_key: flag_key, default_value: default_value, context: context)
71
+ resolve_from_sources(default_value:) do |provider|
72
+ provider.resolve_number_value(flag_key:, default_value:)
57
73
  end
58
74
  end
59
75
 
@@ -67,8 +83,8 @@ module OpenFeature
67
83
  .returns(ResolutionDetails[Structure])
68
84
  end
69
85
  def resolve_structure_value(flag_key:, default_value:, context: nil)
70
- resolve_from_sources(default_value: default_value) do |provider|
71
- provider.resolve_structure_value(flag_key: flag_key, default_value: default_value, context: context)
86
+ resolve_from_sources(default_value:) do |provider|
87
+ provider.resolve_structure_value(flag_key:, default_value:)
72
88
  end
73
89
  end
74
90
 
@@ -82,8 +98,8 @@ module OpenFeature
82
98
  .returns(ResolutionDetails[String])
83
99
  end
84
100
  def resolve_string_value(flag_key:, default_value:, context: nil)
85
- resolve_from_sources(default_value: default_value) do |provider|
86
- provider.resolve_string_value(flag_key: flag_key, default_value: default_value, context: context)
101
+ resolve_from_sources(default_value:) do |provider|
102
+ provider.resolve_string_value(flag_key:, default_value:)
87
103
  end
88
104
  end
89
105
 
@@ -5,11 +5,9 @@ module OpenFeature
5
5
  # Default provider when initializing OpenFeature.
6
6
  # Always returns the default value given.
7
7
  # This will result in a TypeError if the given default value does not have the correct type.
8
- class NoOpProvider
8
+ class NoOpProvider < Provider
9
9
  extend T::Sig
10
10
 
11
- include Provider
12
-
13
11
  sig { override.returns(ProviderMetadata) }
14
12
  attr_reader :metadata
15
13
 
@@ -20,6 +18,7 @@ module OpenFeature
20
18
  def initialize
21
19
  @metadata = T.let(ProviderMetadata.new(name: "No Op Provider"), ProviderMetadata)
22
20
  @hooks = T.let([], T::Array[Hook])
21
+ super()
23
22
  end
24
23
 
25
24
  sig do
@@ -3,10 +3,21 @@
3
3
 
4
4
  module OpenFeature
5
5
  # Interface that providers must implement.
6
- module Provider
6
+ class Provider
7
7
  extend T::Sig
8
8
  extend T::Helpers
9
- interface!
9
+ abstract!
10
+
11
+ sig { returns(ProviderStatus) }
12
+ attr_reader :status
13
+
14
+ sig { params(status: ProviderStatus).void }
15
+ def initialize(status = ProviderStatus::Ready)
16
+ @status = status
17
+ end
18
+
19
+ sig { overridable.params(context: EvaluationContext).void }
20
+ def init(context:); end
10
21
 
11
22
  sig { abstract.returns(ProviderMetadata) }
12
23
  def metadata; end
@@ -14,6 +25,9 @@ module OpenFeature
14
25
  sig { abstract.returns(T::Array[Hook]) }
15
26
  def hooks; end
16
27
 
28
+ sig { overridable.void }
29
+ def shutdown; end
30
+
17
31
  sig do
18
32
  abstract
19
33
  .params(
@@ -0,0 +1,13 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module OpenFeature
5
+ # Indicates what state a provider is in
6
+ class ProviderStatus < T::Enum
7
+ enums do
8
+ NotReady = new
9
+ Ready = new
10
+ Error = new
11
+ end
12
+ end
13
+ end
data/lib/open_feature.rb CHANGED
@@ -19,6 +19,8 @@ module OpenFeature
19
19
 
20
20
  sig { params(provider: Provider).void }
21
21
  def set_provider(provider) # rubocop:disable Naming/AccessorMethodName
22
+ configuration.provider.shutdown
23
+ provider.init(context: configuration.evaluation_context || EvaluationContext.new)
22
24
  configuration.provider = provider
23
25
  end
24
26
 
@@ -42,12 +44,17 @@ module OpenFeature
42
44
  def create_client(name: nil, evaluation_context: nil, hooks: nil)
43
45
  Client.new(
44
46
  provider: configuration.provider,
45
- name: name,
46
- evaluation_context: evaluation_context,
47
+ name:,
48
+ evaluation_context:,
47
49
  hooks: Array(hooks)
48
50
  )
49
51
  end
50
52
 
53
+ sig { void }
54
+ def shutdown
55
+ configuration.provider.shutdown
56
+ end
57
+
51
58
  sig { returns(Configuration) }
52
59
  def configuration
53
60
  Configuration.instance
@@ -0,0 +1 @@
1
+ **/*.rbi linguist-generated=true