openfeature-sdk-sorbet 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -8
  3. data/CHANGELOG.md +16 -10
  4. data/Gemfile.lock +1 -1
  5. data/README.md +20 -18
  6. data/lib/{open_feature → open_feature_sorbet}/client.rb +47 -47
  7. data/lib/{open_feature → open_feature_sorbet}/client_metadata.rb +1 -1
  8. data/lib/{open_feature → open_feature_sorbet}/configuration.rb +2 -2
  9. data/lib/{open_feature → open_feature_sorbet}/error_code.rb +1 -1
  10. data/lib/{open_feature → open_feature_sorbet}/evaluation_context.rb +2 -2
  11. data/lib/{open_feature → open_feature_sorbet}/evaluation_context_builder.rb +1 -1
  12. data/lib/{open_feature → open_feature_sorbet}/evaluation_details.rb +3 -3
  13. data/lib/{open_feature → open_feature_sorbet}/evaluation_options.rb +1 -1
  14. data/lib/{open_feature → open_feature_sorbet}/flag_metadata.rb +1 -1
  15. data/lib/{open_feature → open_feature_sorbet}/hook.rb +7 -7
  16. data/lib/{open_feature → open_feature_sorbet}/hook_context.rb +4 -4
  17. data/lib/{open_feature → open_feature_sorbet}/hooks.rb +1 -1
  18. data/lib/{open_feature → open_feature_sorbet}/multiple_source_provider.rb +10 -10
  19. data/lib/{open_feature → open_feature_sorbet}/no_op_provider.rb +1 -1
  20. data/lib/{open_feature → open_feature_sorbet}/provider.rb +1 -1
  21. data/lib/{open_feature → open_feature_sorbet}/provider_metadata.rb +1 -1
  22. data/lib/{open_feature → open_feature_sorbet}/provider_status.rb +1 -1
  23. data/lib/{open_feature → open_feature_sorbet}/resolution_details.rb +1 -1
  24. data/lib/{open_feature → open_feature_sorbet}/structure.rb +1 -1
  25. data/lib/{open_feature.rb → open_feature_sorbet.rb} +3 -3
  26. metadata +23 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b35975b45d85edc14dd6d1250a6e43c2e8e5bf0f16bfa76c46e230fb1e075bd8
4
- data.tar.gz: 63813db644b864365e7631d6b804082bfe460810dbd7f5ce1bbd8e1f5e0bbdd3
3
+ metadata.gz: d4c602dee15992f209891df9bfcfa7dac28a786bbef9d3943538f1de80e21496
4
+ data.tar.gz: edb41a3936933b08581683adb6e2020e92ebee2f92f4cf11e3af84ffb1e2ed21
5
5
  SHA512:
6
- metadata.gz: 21e85e1fac1387b02841759807c13ce5b36bd505148c4eb3e4cc1bcf8240720fee801534f6013353b57d377e26332063381f36da337aefc7b36db8511e38ed2f
7
- data.tar.gz: 5aa40c6064570f50c405fa4b3b9879535240802e5cdf7a384807dbd2961466313cd9242d2b6b13c0ee17f0b4a17f1d06440ac5d882f1c7bb5f1daafa8d4ff2ef
6
+ metadata.gz: c4034f39bd39dd8f31802c426088f7c65597814888bf463c06bb3586321e4d8e08beae0eb5716bab5c0b0d753344fd6bc097487336386edad33d7f1e0dd3205f
7
+ data.tar.gz: 7c52323bfecad7627afdbeee236b5ca8d0be775adea5c57eec2b61b803d3167c28cfb5a4d919309d4ca65088edb8a9cd8b5c55dee6c45d611921d7d6005b21a8
data/.rubocop.yml CHANGED
@@ -10,24 +10,24 @@ require:
10
10
 
11
11
  AllCops:
12
12
  NewCops: enable
13
- TargetRubyVersion: 3.1
13
+ TargetRubyVersion: 3.0
14
14
  Exclude:
15
15
  - sorbet/**/*.rbi
16
16
 
17
17
  Layout/LineLength:
18
- Max: 120
18
+ Max: 130
19
19
 
20
20
  Lint/UnusedMethodArgument:
21
21
  Exclude:
22
- - lib/open_feature/multiple_source_provider.rb
23
- - lib/open_feature/no_op_provider.rb
22
+ - lib/open_feature_sorbet/multiple_source_provider.rb
23
+ - lib/open_feature_sorbet/no_op_provider.rb
24
24
 
25
25
  Metrics/ClassLength:
26
26
  Exclude:
27
- - lib/open_feature/client.rb
28
- - lib/open_feature/multiple_source_provider.rb
29
- - test/open_feature/client_test.rb
30
- - test/open_feature/multiple_source_provider_test.rb
27
+ - lib/open_feature_sorbet/client.rb
28
+ - lib/open_feature_sorbet/multiple_source_provider.rb
29
+ - test/open_feature_sorbet/client_test.rb
30
+ - test/open_feature_sorbet/multiple_source_provider_test.rb
31
31
 
32
32
  Metrics/MethodLength:
33
33
  Exclude:
data/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.0] - 2024-02-21
10
+
11
+ ### Changed
12
+
13
+ - Set minimum Ruby version back to 3.0.
14
+
9
15
  ## [0.3.1] - 2024-01-26
10
16
 
11
17
  ### Changed
@@ -20,25 +26,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
20
26
 
21
27
  ### Added
22
28
 
23
- - Added `OpenFeature::Provider#status` reader that returns an `OpenFeature::ProviderStatus`.
24
- - Added `OpenFeature::Provider#init` as an overridable method on `Provider`s that can perform any initialization work for the given provider. This method accepts the global `EvaluationContext` and has a `void` return type. The default implementation is a no-op.
25
- - Added `OpenFeature::Provider#shutdown` as an overridable method on `Provider`s that can perform any cleanup work for the given provider. This method has a `void` return type and the default implementation is a no-op.
29
+ - Added `OpenFeatureSorbet::Provider#status` reader that returns an `OpenFeatureSorbet::ProviderStatus`.
30
+ - Added `OpenFeatureSorbet::Provider#init` as an overridable method on `Provider`s that can perform any initialization work for the given provider. This method accepts the global `EvaluationContext` and has a `void` return type. The default implementation is a no-op.
31
+ - Added `OpenFeatureSorbet::Provider#shutdown` as an overridable method on `Provider`s that can perform any cleanup work for the given provider. This method has a `void` return type and the default implementation is a no-op.
26
32
  - Added `OpenFeature.shutdown` to invoke the current provider's `shutdown` method.
27
33
 
28
34
  ### Changed
29
35
 
30
36
  - *Breaking* Changed minimum supported Ruby version to 3.1.
31
- - *Breaking* `OpenFeature::Provider` changed from a module interface to an abstract class to support default method implementations.
32
- - *Breaking* `OpenFeature::Provider.initialize` now must accept an `OpenFeature::ProviderStatus`. Any providers may pass this in during initialization. If you need to do additional setup in `Provider.init`, we recommend you pass `OpenFeature::ProviderStatus::NotReady` here.
37
+ - *Breaking* `OpenFeatureSorbet::Provider` changed from a module interface to an abstract class to support default method implementations.
38
+ - *Breaking* `OpenFeatureSorbet::Provider.initialize` now must accept an `OpenFeatureSorbet::ProviderStatus`. Any providers may pass this in during initialization. If you need to do additional setup in `Provider.init`, we recommend you pass `OpenFeatureSorbet::ProviderStatus::NotReady` here.
33
39
 
34
40
  ## [0.2.0] - 2023-05-17
35
41
 
36
42
  ### Added
37
43
 
38
- - Added ability to set evaluation context globally on the `Configuration` singleton, i.e. `OpenFeature::Configuration.instance.evaluation_context = OpenFeature::EvaluationContext.new(fields: { "globally" => "available" })`.
39
- - Added ability to set evaluation context globally on the `OpenFeature` module, i.e. `OpenFeature.set_evaluation_context(OpenFeature::EvaluationContext.new(fields: { "globally" => "available" }))`.
40
- - Added ability to set evaluation context on a `Client` instance, i.e. `client.evaluation_context = OpenFeature::EvaluationContext.new(fields: { "client" => "available" })`.
41
- - Added ability to set hooks and evaluation context on `Client` initialization, i.e. `OpenFeature.create_client(name: "my_client", evaluation_context: OpenFeature::EvaluationContext.new(fields: { "client" => "available" }), hooks: OpenFeature::Hook.new)`
44
+ - Added ability to set evaluation context globally on the `Configuration` singleton, i.e. `OpenFeatureSorbet::Configuration.instance.evaluation_context = OpenFeatureSorbet::EvaluationContext.new(fields: { "globally" => "available" })`.
45
+ - Added ability to set evaluation context globally on the `OpenFeature` module, i.e. `OpenFeature.set_evaluation_context(OpenFeatureSorbet::EvaluationContext.new(fields: { "globally" => "available" }))`.
46
+ - Added ability to set evaluation context on a `Client` instance, i.e. `client.evaluation_context = OpenFeatureSorbet::EvaluationContext.new(fields: { "client" => "available" })`.
47
+ - Added ability to set hooks and evaluation context on `Client` initialization, i.e. `OpenFeature.create_client(name: "my_client", evaluation_context: OpenFeatureSorbet::EvaluationContext.new(fields: { "client" => "available" }), hooks: OpenFeatureSorbet::Hook.new)`
42
48
  - Added `Configuration#reset!` to reset global configuration to the default state.
43
49
 
44
50
  ### Changed
@@ -55,7 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
55
61
 
56
62
  ### Added
57
63
 
58
- - Introduced `OpenFeature::MultipleSourceProvider` to allow fetching flags from multiple sources.
64
+ - Introduced `OpenFeatureSorbet::MultipleSourceProvider` to allow fetching flags from multiple sources.
59
65
 
60
66
  ## [0.1.1] - 2023-05-15
61
67
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openfeature-sdk-sorbet (0.3.1)
4
+ openfeature-sdk-sorbet (0.5.0)
5
5
  sorbet-runtime (~> 0.5)
6
6
  sorbet-struct-comparable (~> 1.3)
7
7
  zeitwerk (~> 2.6)
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Sorbet-aware OpenFeature Ruby Implementation
2
2
 
3
+ **NOTE** This implementation has been deprecated in favor of the [official Ruby SDK](https://github.com/open-feature/ruby-sdk). We recommend switching to that. In the future, we hope to add RBS and Tapioca DSL generation support to the official library.
4
+
3
5
  [OpenFeature](https://openfeature.dev) is an open standard for vendor-agnostic feature flagging. [Sorbet](https://sorbet.org) is a type-checker for Ruby, built by Stripe. Sorbet provides powerful runtime utilities to achieve things traditionally not possible with Ruby, such as interfaces, immutable structures and enums. This makes it a very good option when defining specifications.
4
6
 
5
7
  If an organization is not already using Sorbet, you probably don't want to introduce a dependency on `sorbet-runtime`, which this gem does. As such, this will always be a distinct implementation, separate from the official [Ruby SDK](https://github.com/open-feature/ruby-sdk).
@@ -21,15 +23,15 @@ If bundler is not being used to manage dependencies, install the gem by executin
21
23
  ## Usage
22
24
 
23
25
  ```ruby
24
- require "open_feature"
26
+ require "open_feature_sorbet"
25
27
 
26
28
  # Configure global API properties
27
29
 
28
- OpenFeature.set_provider(OpenFeature::NoOpProvider.new)
29
- OpenFeature.set_evaluation_context(OpenFeature::EvaluationContext.new(fields: { "globally" => "available" }))
30
- OpenFeature.add_hooks([OpenFeature::Hook.new]) # experimental, not fully supported
30
+ OpenFeature.set_provider(OpenFeatureSorbet::NoOpProvider.new)
31
+ OpenFeature.set_evaluation_context(OpenFeatureSorbet::EvaluationContext.new(fields: { "globally" => "available" }))
32
+ OpenFeature.add_hooks([OpenFeatureSorbet::Hook.new]) # experimental, not fully supported
31
33
 
32
- client = OpenFeature.create_client(evaluation_context: OpenFeature::EvaluationContext.new(fields: { "client" => "available" }))
34
+ client = OpenFeature.create_client(evaluation_context: OpenFeatureSorbet::EvaluationContext.new(fields: { "client" => "available" }))
33
35
 
34
36
  # Fetch boolean value
35
37
  # Also methods available for String, Number, Integer, Float and Structure (Hash)
@@ -39,7 +41,7 @@ bool_value = client.fetch_boolean_value(flag_key: "my_toggle", default_value: fa
39
41
  bool_value = client.fetch_boolean_value(flag_key: "my_toggle", default_value: "bad!") # => raises TypeError from Sorbet, invalid default value
40
42
 
41
43
  # Additional evaluation context can be provided during invocation
42
- number_value = client.fetch_number_value(flag_key: "my_toggle", default_value: 1, context: OpenFeature::EvaluationContext.new(fields: { "only_this_call_site" => 10 })) # => merges client and global context
44
+ number_value = client.fetch_number_value(flag_key: "my_toggle", default_value: 1, context: OpenFeatureSorbet::EvaluationContext.new(fields: { "only_this_call_site" => 10 })) # => merges client and global context
43
45
 
44
46
  # Fetch structure evaluation details
45
47
  structure_evaluation_details = client.fetch_structure_details(flag_key: "my_structure", default_value: { "a" => "fallback" }) # => EvaluationDetails(value: Hash, flag_key: "my_structure", ...)
@@ -55,15 +57,15 @@ We support global evaluation context (set on the `OpenFeature` module), client e
55
57
 
56
58
  ### Provider Abstract Class
57
59
 
58
- By default, this implementation sets the provider to the `OpenFeature::NoOpProvider` which always returns the default value. It's up to the individual teams to define their own providers based on their flag source (in the future, I'll release open-source providers based on various, common vendors).
60
+ By default, this implementation sets the provider to the `OpenFeatureSorbet::NoOpProvider` which always returns the default value. It's up to the individual teams to define their own providers based on their flag source (in the future, I'll release open-source providers based on various, common vendors).
59
61
 
60
- This gem also provides `OpenFeature::MultipleSourceProvider` to allow fetching flags from multiple sources. This is especially useful if your existing application has flags spread across bespoke and vendor solutions and you want to unify the evaluation sites. It can be instantiated and configured like so:
62
+ This gem also provides `OpenFeatureSorbet::MultipleSourceProvider` to allow fetching flags from multiple sources. This is especially useful if your existing application has flags spread across bespoke and vendor solutions and you want to unify the evaluation sites. It can be instantiated and configured like so:
61
63
 
62
64
  ```ruby
63
- provider = OpenFeature::MultipleSourceProvider.new(
65
+ provider = OpenFeatureSorbet::MultipleSourceProvider.new(
64
66
  providers: [
65
67
  CustomProvider.new,
66
- OpenFeature::NoOpProvider.new
68
+ OpenFeatureSorbet::NoOpProvider.new
67
69
  ]
68
70
  )
69
71
 
@@ -75,17 +77,17 @@ OpenFeature.set_provider(provider)
75
77
  Thanks to Sorbet abstract classes, it's fairly straightforward to implement a new provider. Here is an example for a JSON-based flag format on disk:
76
78
 
77
79
  ```ruby
78
- class JsonFileFlagProvider < OpenFeature::Provider
80
+ class JsonFileFlagProvider < OpenFeatureSorbet::Provider
79
81
  extend T::Sig
80
82
 
81
83
  sig { void }
82
84
  def initialize
83
- super(OpenFeature::ProviderStatus::NotReady)
85
+ super(OpenFeatureSorbet::ProviderStatus::NotReady)
84
86
  end
85
87
 
86
88
  def init(context)
87
89
  @file = File.open(context.file || "flags.json")
88
- @status = OpenFeature::ProviderStatus::Ready
90
+ @status = OpenFeatureSorbet::ProviderStatus::Ready
89
91
  end
90
92
 
91
93
  sig { overridable.void }
@@ -93,9 +95,9 @@ class JsonFileFlagProvider < OpenFeature::Provider
93
95
  @file.close
94
96
  end
95
97
 
96
- sig { override.returns(OpenFeature::ProviderMetadata) }
98
+ sig { override.returns(OpenFeatureSorbet::ProviderMetadata) }
97
99
  def metadata
98
- OpenFeature::ProviderMetadata.new(name: "Json File Flag Provider")
100
+ OpenFeatureSorbet::ProviderMetadata.new(name: "Json File Flag Provider")
99
101
  end
100
102
 
101
103
  sig { override.returns(T::Array[Hook]) }
@@ -110,13 +112,13 @@ class JsonFileFlagProvider < OpenFeature::Provider
110
112
  default_value: T::Boolean,
111
113
  context: T.nilable(EvaluationContext)
112
114
  )
113
- .returns(OpenFeature::ResolutionDetails[T::Boolean])
115
+ .returns(OpenFeatureSorbet::ResolutionDetails[T::Boolean])
114
116
  end
115
117
  def resolve_boolean_value(flag_key:, default_value:, context: nil)
116
118
  file_input = JSON.parse(File.read("flags.rb"))
117
119
  value = file_input.fetch("flag_key", default_value)
118
120
 
119
- OpenFeature::ResolutionDetails.new(
121
+ OpenFeatureSorbet::ResolutionDetails.new(
120
122
  value: value,
121
123
  # ... other optional fields
122
124
  )
@@ -126,7 +128,7 @@ class JsonFileFlagProvider < OpenFeature::Provider
126
128
  end
127
129
  ```
128
130
 
129
- By inheriting from the `OpenFeature::Provider` class, Sorbet will indicate what methods it's expecting and what their type signatures should be.
131
+ By inheriting from the `OpenFeatureSorbet::Provider` class, Sorbet will indicate what methods it's expecting and what their type signatures should be.
130
132
 
131
133
  ##### A note on `initialize` versus `init`
132
134
 
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Used during runtime for evaluating features.
6
6
  class Client
7
7
  extend T::Sig
@@ -25,7 +25,7 @@ module OpenFeature
25
25
  end
26
26
  def initialize(provider:, name: nil, evaluation_context: nil, hooks: [])
27
27
  @provider = provider
28
- @client_metadata = T.let(ClientMetadata.new(name:), ClientMetadata)
28
+ @client_metadata = T.let(ClientMetadata.new(name: name), ClientMetadata)
29
29
  @evaluation_context = evaluation_context
30
30
  @hooks = hooks
31
31
  end
@@ -44,10 +44,10 @@ module OpenFeature
44
44
  ).returns(T::Boolean)
45
45
  end
46
46
  def fetch_boolean_value(flag_key:, default_value:, context: nil, options: nil)
47
- evaluated_context = build_context_with_before_hooks(flag_key:, default_value:,
48
- invocation_context: context, options:,
47
+ evaluated_context = build_context_with_before_hooks(flag_key: flag_key, default_value: default_value,
48
+ invocation_context: context, options: options,
49
49
  flag_type: "Boolean")
50
- provider.resolve_boolean_value(flag_key:, default_value:, context: evaluated_context)
50
+ provider.resolve_boolean_value(flag_key: flag_key, default_value: default_value, context: evaluated_context)
51
51
  .value
52
52
  rescue StandardError
53
53
  default_value
@@ -63,14 +63,14 @@ module OpenFeature
63
63
  end
64
64
  def fetch_boolean_details(flag_key:, default_value:, context: nil, options: nil) # rubocop:disable Lint/UnusedMethodArgument
65
65
  details = provider.resolve_boolean_value(
66
- flag_key:,
67
- default_value:,
66
+ flag_key: flag_key,
67
+ default_value: default_value,
68
68
  context: build_context(context)
69
69
  )
70
70
 
71
- EvaluationDetails.from_resolution_details(details, flag_key:)
71
+ EvaluationDetails.from_resolution_details(details, flag_key: flag_key)
72
72
  rescue StandardError => e
73
- EvaluationDetails.from_error(e.message, flag_key:, default_value:)
73
+ EvaluationDetails.from_error(e.message, flag_key: flag_key, default_value: default_value)
74
74
  end
75
75
 
76
76
  sig do
@@ -82,11 +82,11 @@ module OpenFeature
82
82
  ).returns(String)
83
83
  end
84
84
  def fetch_string_value(flag_key:, default_value:, context: nil, options: nil)
85
- evaluated_context = build_context_with_before_hooks(flag_key:, default_value:,
86
- invocation_context: context, options:,
85
+ evaluated_context = build_context_with_before_hooks(flag_key: flag_key, default_value: default_value,
86
+ invocation_context: context, options: options,
87
87
  flag_type: "String")
88
88
  provider
89
- .resolve_string_value(flag_key:, default_value:, context: evaluated_context)
89
+ .resolve_string_value(flag_key: flag_key, default_value: default_value, context: evaluated_context)
90
90
  .value
91
91
  rescue StandardError
92
92
  default_value
@@ -102,14 +102,14 @@ module OpenFeature
102
102
  end
103
103
  def fetch_string_details(flag_key:, default_value:, context: nil, options: nil) # rubocop:disable Lint/UnusedMethodArgument
104
104
  details = provider.resolve_string_value(
105
- flag_key:,
106
- default_value:,
105
+ flag_key: flag_key,
106
+ default_value: default_value,
107
107
  context: build_context(context)
108
108
  )
109
109
 
110
- EvaluationDetails.from_resolution_details(details, flag_key:)
110
+ EvaluationDetails.from_resolution_details(details, flag_key: flag_key)
111
111
  rescue StandardError => e
112
- EvaluationDetails.from_error(e.message, flag_key:, default_value:)
112
+ EvaluationDetails.from_error(e.message, flag_key: flag_key, default_value: default_value)
113
113
  end
114
114
 
115
115
  sig do
@@ -121,11 +121,11 @@ module OpenFeature
121
121
  ).returns(Numeric)
122
122
  end
123
123
  def fetch_number_value(flag_key:, default_value:, context: nil, options: nil)
124
- evaluated_context = build_context_with_before_hooks(flag_key:, default_value:,
125
- invocation_context: context, options:,
124
+ evaluated_context = build_context_with_before_hooks(flag_key: flag_key, default_value: default_value,
125
+ invocation_context: context, options: options,
126
126
  flag_type: "Number")
127
127
  provider
128
- .resolve_number_value(flag_key:, default_value:, context: evaluated_context)
128
+ .resolve_number_value(flag_key: flag_key, default_value: default_value, context: evaluated_context)
129
129
  .value
130
130
  rescue StandardError
131
131
  default_value
@@ -141,14 +141,14 @@ module OpenFeature
141
141
  end
142
142
  def fetch_number_details(flag_key:, default_value:, context: nil, options: nil) # rubocop:disable Lint/UnusedMethodArgument
143
143
  details = provider.resolve_number_value(
144
- flag_key:,
145
- default_value:,
144
+ flag_key: flag_key,
145
+ default_value: default_value,
146
146
  context: build_context(context)
147
147
  )
148
148
 
149
- EvaluationDetails.from_resolution_details(details, flag_key:)
149
+ EvaluationDetails.from_resolution_details(details, flag_key: flag_key)
150
150
  rescue StandardError => e
151
- EvaluationDetails.from_error(e.message, flag_key:, default_value:)
151
+ EvaluationDetails.from_error(e.message, flag_key: flag_key, default_value: default_value)
152
152
  end
153
153
 
154
154
  sig do
@@ -160,11 +160,11 @@ module OpenFeature
160
160
  ).returns(Integer)
161
161
  end
162
162
  def fetch_integer_value(flag_key:, default_value:, context: nil, options: nil)
163
- evaluated_context = build_context_with_before_hooks(flag_key:, default_value:,
164
- invocation_context: context, options:,
163
+ evaluated_context = build_context_with_before_hooks(flag_key: flag_key, default_value: default_value,
164
+ invocation_context: context, options: options,
165
165
  flag_type: "Integer")
166
166
  provider
167
- .resolve_number_value(flag_key:, default_value:, context: evaluated_context)
167
+ .resolve_number_value(flag_key: flag_key, default_value: default_value, context: evaluated_context)
168
168
  .value
169
169
  .to_i
170
170
  rescue StandardError
@@ -180,11 +180,11 @@ module OpenFeature
180
180
  ).returns(Float)
181
181
  end
182
182
  def fetch_float_value(flag_key:, default_value:, context: nil, options: nil)
183
- evaluated_context = build_context_with_before_hooks(flag_key:, default_value:,
184
- invocation_context: context, options:,
183
+ evaluated_context = build_context_with_before_hooks(flag_key: flag_key, default_value: default_value,
184
+ invocation_context: context, options: options,
185
185
  flag_type: "Float")
186
186
  provider
187
- .resolve_number_value(flag_key:, default_value:, context: evaluated_context)
187
+ .resolve_number_value(flag_key: flag_key, default_value: default_value, context: evaluated_context)
188
188
  .value
189
189
  .to_f
190
190
  rescue StandardError
@@ -200,11 +200,11 @@ module OpenFeature
200
200
  ).returns(Structure)
201
201
  end
202
202
  def fetch_structure_value(flag_key:, default_value:, context: nil, options: nil)
203
- evaluated_context = build_context_with_before_hooks(flag_key:, default_value:,
204
- invocation_context: context, options:,
203
+ evaluated_context = build_context_with_before_hooks(flag_key: flag_key, default_value: default_value,
204
+ invocation_context: context, options: options,
205
205
  flag_type: "Structure")
206
206
  provider
207
- .resolve_structure_value(flag_key:, default_value:, context: evaluated_context)
207
+ .resolve_structure_value(flag_key: flag_key, default_value: default_value, context: evaluated_context)
208
208
  .value
209
209
  rescue StandardError
210
210
  default_value
@@ -220,14 +220,14 @@ module OpenFeature
220
220
  end
221
221
  def fetch_structure_details(flag_key:, default_value:, context: nil, options: nil) # rubocop:disable Lint/UnusedMethodArgument
222
222
  details = provider.resolve_structure_value(
223
- flag_key:,
224
- default_value:,
223
+ flag_key: flag_key,
224
+ default_value: default_value,
225
225
  context: build_context(context)
226
226
  )
227
227
 
228
- EvaluationDetails.from_resolution_details(details, flag_key:)
228
+ EvaluationDetails.from_resolution_details(details, flag_key: flag_key)
229
229
  rescue StandardError => e
230
- EvaluationDetails.from_error(e.message, flag_key:, default_value:)
230
+ EvaluationDetails.from_error(e.message, flag_key: flag_key, default_value: default_value)
231
231
  end
232
232
 
233
233
  private
@@ -245,16 +245,16 @@ module OpenFeature
245
245
  ).returns(EvaluationContext)
246
246
  end
247
247
  def build_context_with_before_hooks(flag_key:, default_value:, invocation_context:, options:, flag_type:)
248
- hook_context = build_hook_context(flag_key:, default_value:,
249
- invocation_context:, flag_type:)
250
- OpenFeature::Hook::BeforeHook.call(hooks: build_hooks(options), context: hook_context,
251
- hints: {})
248
+ hook_context = build_hook_context(flag_key: flag_key, default_value: default_value,
249
+ invocation_context: invocation_context, flag_type: flag_type)
250
+ OpenFeatureSorbet::Hook::BeforeHook.call(hooks: build_hooks(options), context: hook_context,
251
+ hints: {})
252
252
  end
253
253
 
254
254
  sig { params(options: T.nilable(EvaluationOptions)).returns(Hooks) }
255
255
  def build_hooks(options)
256
256
  Hooks.new(
257
- global: OpenFeature.configuration.hooks,
257
+ global: OpenFeatureSorbet.configuration.hooks,
258
258
  client: hooks,
259
259
  invocation: (options ? options.hooks : []),
260
260
  provider: provider.hooks
@@ -270,18 +270,18 @@ module OpenFeature
270
270
  ).returns(HookContext[T.type_parameter(:U)])
271
271
  end
272
272
  def build_hook_context(flag_key:, default_value:, invocation_context:, flag_type:)
273
- evaluation_context = build_context(invocation_context) || OpenFeature::EvaluationContext.new
274
- HookContext.new(flag_key:, default_value:,
275
- evaluation_context:, flag_type:,
276
- client_metadata:, provider_metadata: provider.metadata)
273
+ evaluation_context = build_context(invocation_context) || OpenFeatureSorbet::EvaluationContext.new
274
+ HookContext.new(flag_key: flag_key, default_value: default_value,
275
+ evaluation_context: evaluation_context, flag_type: flag_type,
276
+ client_metadata: client_metadata, provider_metadata: provider.metadata)
277
277
  end
278
278
 
279
279
  sig { params(invocation_context: T.nilable(EvaluationContext)).returns(T.nilable(EvaluationContext)) }
280
280
  def build_context(invocation_context)
281
281
  EvaluationContextBuilder.new.call(
282
- global_context: OpenFeature.configuration.evaluation_context,
282
+ global_context: OpenFeatureSorbet.configuration.evaluation_context,
283
283
  client_context: evaluation_context,
284
- invocation_context:
284
+ invocation_context: invocation_context
285
285
  )
286
286
  end
287
287
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Defines information about a Client.
6
6
  class ClientMetadata < T::Struct
7
7
  include T::Struct::ActsAsComparable
@@ -3,7 +3,7 @@
3
3
 
4
4
  require "singleton"
5
5
 
6
- module OpenFeature
6
+ module OpenFeatureSorbet
7
7
  # Singleton class that supports global configuration for OpenFeature.
8
8
  # Should not be interacted with directly; rather, favor interacting
9
9
  # with methods defined on the `OpenFeature` module.
@@ -35,7 +35,7 @@ module OpenFeature
35
35
 
36
36
  sig { void }
37
37
  def reset!
38
- @provider = OpenFeature::NoOpProvider.new
38
+ @provider = OpenFeatureSorbet::NoOpProvider.new
39
39
  @hooks = []
40
40
  @evaluation_context = nil
41
41
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Possible error codes
6
6
  class ErrorCode < T::Enum
7
7
  enums do
@@ -3,7 +3,7 @@
3
3
 
4
4
  require "date"
5
5
 
6
- module OpenFeature
6
+ module OpenFeatureSorbet
7
7
  # Provides ambient information for the purposes of flag evaluation.
8
8
  # Currently does not meet specification!
9
9
  class EvaluationContext < T::Struct
@@ -27,7 +27,7 @@ module OpenFeature
27
27
  sig { params(key: String, value: T.untyped).returns(EvaluationContext) }
28
28
  def add_field(key, value)
29
29
  EvaluationContext.new(
30
- targeting_key:,
30
+ targeting_key: targeting_key,
31
31
  fields: fields.merge({ key => value })
32
32
  )
33
33
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Used to combine evaluation contexts from different sources
6
6
  class EvaluationContextBuilder
7
7
  extend T::Sig
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Information about resolved value, created by a Provider.
6
6
  class EvaluationDetails < T::Struct
7
7
  extend T::Generic
@@ -25,7 +25,7 @@ module OpenFeature
25
25
  sig { params(details: ResolutionDetails[SelfValue], flag_key: String).returns(EvaluationDetails[SelfValue]) }
26
26
  def from_resolution_details(details, flag_key:)
27
27
  EvaluationDetails.new(
28
- flag_key:,
28
+ flag_key: flag_key,
29
29
  value: details.value,
30
30
  error_code: details.error_code,
31
31
  error_message: details.error_message,
@@ -44,7 +44,7 @@ module OpenFeature
44
44
  end
45
45
  def from_error(error_message, flag_key:, default_value:)
46
46
  EvaluationDetails.new(
47
- flag_key:,
47
+ flag_key: flag_key,
48
48
  value: default_value,
49
49
  error_code: ErrorCode::General,
50
50
  error_message: "Provider raised error: #{error_message}",
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Additional options to be supplied to client during flag evaluation.
6
6
  class EvaluationOptions < T::Struct
7
7
  const :hooks, T::Array[Hook], default: []
@@ -1,6 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  FlagMetadata = T.type_alias { T::Hash[String, T.any(T::Boolean, String, Numeric)] }
6
6
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # See https://openfeature.dev/specification/sections/hooks
6
6
  # We model Hooks as a simple ADT
7
7
  module Hook
@@ -15,11 +15,11 @@ module OpenFeature
15
15
  include Hook
16
16
  extend T::Sig
17
17
  extend T::Helpers
18
- include OpenFeature::Hook
18
+ include OpenFeatureSorbet::Hook
19
19
  abstract!
20
20
  sig do
21
- abstract.params(context: OpenFeature::HookContext[T.untyped],
22
- hints: T::Hash[String, T.untyped]).returns(OpenFeature::EvaluationContext)
21
+ abstract.params(context: OpenFeatureSorbet::HookContext[T.untyped],
22
+ hints: T::Hash[String, T.untyped]).returns(OpenFeatureSorbet::EvaluationContext)
23
23
  end
24
24
  def call(context:, hints:); end
25
25
 
@@ -27,15 +27,15 @@ module OpenFeature
27
27
  extend T::Sig
28
28
 
29
29
  sig do
30
- params(hooks: Hooks, context: OpenFeature::HookContext[T.untyped],
31
- hints: T::Hash[String, T.untyped]).returns(OpenFeature::EvaluationContext)
30
+ params(hooks: Hooks, context: OpenFeatureSorbet::HookContext[T.untyped],
31
+ hints: T::Hash[String, T.untyped]).returns(OpenFeatureSorbet::EvaluationContext)
32
32
  end
33
33
  def call(hooks:, context:, hints:)
34
34
  context.evaluation_context.merge(
35
35
  hooks.before.reduce(context.evaluation_context) do |evaluation_context, hook|
36
36
  hook.call(
37
37
  context: context.with_new_evaluation_context(evaluation_context),
38
- hints:
38
+ hints: hints
39
39
  )
40
40
  end
41
41
  )
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # See https://openfeature.dev/specification/sections/hooks#41-hook-context
6
6
  # See Requirement 4.1.1, 4.1.3, 4.1.4
7
7
  # TODO: Requirement 4.1.2
@@ -22,9 +22,9 @@ module OpenFeature
22
22
  # Needed as opposed to .with due to https://sorbet.org/docs/tstruct#from_hash-gotchas
23
23
  sig { params(new_context: EvaluationContext).returns(HookContext[Value]) }
24
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:)
25
+ OpenFeatureSorbet::HookContext.new(flag_key: flag_key, flag_type: flag_type, default_value: default_value,
26
+ evaluation_context: new_context, client_metadata: client_metadata,
27
+ provider_metadata: provider_metadata)
28
28
  end
29
29
  end
30
30
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Represents full set of hooks with helper methods for filtering and sequencing each subtype
6
6
  class Hooks < T::Struct
7
7
  extend T::Generic
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Used to pull from multiple providers.
6
6
  # Order of the providers given to initialize matters.
7
7
  # The providers will be evaluated in that order and the first
@@ -28,7 +28,7 @@ module OpenFeature
28
28
 
29
29
  sig { override.params(context: EvaluationContext).void }
30
30
  def init(context:)
31
- providers.each { |provider| provider.init(context:) }
31
+ providers.each { |provider| provider.init(context: context) }
32
32
  @status = if providers.all? { |provider| provider.status == ProviderStatus::Ready }
33
33
  ProviderStatus::Ready
34
34
  else
@@ -53,8 +53,8 @@ module OpenFeature
53
53
  .returns(ResolutionDetails[T::Boolean])
54
54
  end
55
55
  def resolve_boolean_value(flag_key:, default_value:, context: nil)
56
- resolve_from_sources(default_value:) do |provider|
57
- provider.resolve_boolean_value(flag_key:, default_value:, context:)
56
+ resolve_from_sources(default_value: default_value) do |provider|
57
+ provider.resolve_boolean_value(flag_key: flag_key, default_value: default_value, context: context)
58
58
  end
59
59
  end
60
60
 
@@ -68,8 +68,8 @@ module OpenFeature
68
68
  .returns(ResolutionDetails[Numeric])
69
69
  end
70
70
  def resolve_number_value(flag_key:, default_value:, context: nil)
71
- resolve_from_sources(default_value:) do |provider|
72
- provider.resolve_number_value(flag_key:, default_value:, context:)
71
+ resolve_from_sources(default_value: default_value) do |provider|
72
+ provider.resolve_number_value(flag_key: flag_key, default_value: default_value, context: context)
73
73
  end
74
74
  end
75
75
 
@@ -83,8 +83,8 @@ module OpenFeature
83
83
  .returns(ResolutionDetails[Structure])
84
84
  end
85
85
  def resolve_structure_value(flag_key:, default_value:, context: nil)
86
- resolve_from_sources(default_value:) do |provider|
87
- provider.resolve_structure_value(flag_key:, default_value:, context:)
86
+ resolve_from_sources(default_value: default_value) do |provider|
87
+ provider.resolve_structure_value(flag_key: flag_key, default_value: default_value, context: context)
88
88
  end
89
89
  end
90
90
 
@@ -98,8 +98,8 @@ module OpenFeature
98
98
  .returns(ResolutionDetails[String])
99
99
  end
100
100
  def resolve_string_value(flag_key:, default_value:, context: nil)
101
- resolve_from_sources(default_value:) do |provider|
102
- provider.resolve_string_value(flag_key:, default_value:, context:)
101
+ resolve_from_sources(default_value: default_value) do |provider|
102
+ provider.resolve_string_value(flag_key: flag_key, default_value: default_value, context: context)
103
103
  end
104
104
  end
105
105
 
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
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.
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Interface that providers must implement.
6
6
  class Provider
7
7
  extend T::Sig
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Defines information about a Provider.
6
6
  class ProviderMetadata < T::Struct
7
7
  include T::Struct::ActsAsComparable
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Indicates what state a provider is in
6
6
  class ProviderStatus < T::Enum
7
7
  enums do
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  # Information about resolved value, created by a Provider.
6
6
  class ResolutionDetails < T::Struct
7
7
  extend T::Generic
@@ -1,6 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module OpenFeature
4
+ module OpenFeatureSorbet
5
5
  Structure = T.type_alias { T.any(T::Array[T.untyped], T::Hash[T.untyped, T.untyped]) }
6
6
  end
@@ -8,7 +8,7 @@ loader = Zeitwerk::Loader.for_gem
8
8
  loader.setup
9
9
 
10
10
  # Sorbet-aware implementation of the OpenFeature specification
11
- module OpenFeature
11
+ module OpenFeatureSorbet
12
12
  class << self
13
13
  extend T::Sig
14
14
 
@@ -44,8 +44,8 @@ module OpenFeature
44
44
  def create_client(name: nil, evaluation_context: nil, hooks: nil)
45
45
  Client.new(
46
46
  provider: configuration.provider,
47
- name:,
48
- evaluation_context:,
47
+ name: name,
48
+ evaluation_context: evaluation_context,
49
49
  hooks: Array(hooks)
50
50
  )
51
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openfeature-sdk-sorbet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max VelDink
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-26 00:00:00.000000000 Z
11
+ date: 2024-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -70,26 +70,26 @@ files:
70
70
  - LICENSE.txt
71
71
  - README.md
72
72
  - Rakefile
73
- - lib/open_feature.rb
74
- - lib/open_feature/client.rb
75
- - lib/open_feature/client_metadata.rb
76
- - lib/open_feature/configuration.rb
77
- - lib/open_feature/error_code.rb
78
- - lib/open_feature/evaluation_context.rb
79
- - lib/open_feature/evaluation_context_builder.rb
80
- - lib/open_feature/evaluation_details.rb
81
- - lib/open_feature/evaluation_options.rb
82
- - lib/open_feature/flag_metadata.rb
83
- - lib/open_feature/hook.rb
84
- - lib/open_feature/hook_context.rb
85
- - lib/open_feature/hooks.rb
86
- - lib/open_feature/multiple_source_provider.rb
87
- - lib/open_feature/no_op_provider.rb
88
- - lib/open_feature/provider.rb
89
- - lib/open_feature/provider_metadata.rb
90
- - lib/open_feature/provider_status.rb
91
- - lib/open_feature/resolution_details.rb
92
- - lib/open_feature/structure.rb
73
+ - lib/open_feature_sorbet.rb
74
+ - lib/open_feature_sorbet/client.rb
75
+ - lib/open_feature_sorbet/client_metadata.rb
76
+ - lib/open_feature_sorbet/configuration.rb
77
+ - lib/open_feature_sorbet/error_code.rb
78
+ - lib/open_feature_sorbet/evaluation_context.rb
79
+ - lib/open_feature_sorbet/evaluation_context_builder.rb
80
+ - lib/open_feature_sorbet/evaluation_details.rb
81
+ - lib/open_feature_sorbet/evaluation_options.rb
82
+ - lib/open_feature_sorbet/flag_metadata.rb
83
+ - lib/open_feature_sorbet/hook.rb
84
+ - lib/open_feature_sorbet/hook_context.rb
85
+ - lib/open_feature_sorbet/hooks.rb
86
+ - lib/open_feature_sorbet/multiple_source_provider.rb
87
+ - lib/open_feature_sorbet/no_op_provider.rb
88
+ - lib/open_feature_sorbet/provider.rb
89
+ - lib/open_feature_sorbet/provider_metadata.rb
90
+ - lib/open_feature_sorbet/provider_status.rb
91
+ - lib/open_feature_sorbet/resolution_details.rb
92
+ - lib/open_feature_sorbet/structure.rb
93
93
  - sorbet/config
94
94
  - sorbet/rbi/annotations/rainbow.rbi
95
95
  - sorbet/rbi/gems/.gitattributes
@@ -145,7 +145,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
145
  requirements:
146
146
  - - ">="
147
147
  - !ruby/object:Gem::Version
148
- version: '3.1'
148
+ version: '3.0'
149
149
  required_rubygems_version: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - ">="