openfeature-sdk-sorbet 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +9 -9
- data/README.md +15 -0
- data/lib/open_feature/multiple_source_provider.rb +121 -0
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96650d45be9bb86f0349e27d1ad9d56c748659b3d075b6c2cc6c769fff642571
|
4
|
+
data.tar.gz: 370bd63d0ffb1143eec2de19d3b70e5e0b5033b4dcd0f08117dfbaeee7c1f8cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 915afef5bdae8110b53c4e96dc9494955636753c1170349eb25f432760590fc75004ebd6f8c47bd3359da982b81fbae0c08a7053df4b552fe760f939021bdd00
|
7
|
+
data.tar.gz: 799b9745b26bf0eac7cdf5e54b237d63abe8f2af5e238bcaf554bd368105dc880a7cc643e5565529053baa4a7041cbc61a5c95eafcc56331ad25b6c2527883e9
|
data/.rubocop.yml
CHANGED
@@ -19,16 +19,20 @@ Layout/LineLength:
|
|
19
19
|
|
20
20
|
Lint/UnusedMethodArgument:
|
21
21
|
Exclude:
|
22
|
+
- lib/open_feature/multiple_source_provider.rb
|
22
23
|
- lib/open_feature/no_op_provider.rb
|
23
24
|
|
24
25
|
Metrics/ClassLength:
|
25
26
|
Exclude:
|
26
27
|
- lib/open_feature/client.rb
|
27
28
|
- test/open_feature/client_test.rb
|
29
|
+
- test/open_feature/multiple_source_provider_test.rb
|
28
30
|
|
29
31
|
Metrics/MethodLength:
|
30
32
|
Exclude:
|
31
33
|
- test/open_feature/evaluation_details_test.rb
|
34
|
+
- test/open_feature/multiple_source_provider_test.rb
|
35
|
+
- test/support/test_provider.rb
|
32
36
|
|
33
37
|
Style/AccessorGrouping:
|
34
38
|
Enabled: false
|
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.1.2] - 2023-05-16
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Introduced `OpenFeature::MultipleSourceProvider` to allow fetching flags from multiple sources.
|
14
|
+
|
9
15
|
## [0.1.1] - 2023-05-15
|
10
16
|
|
11
17
|
### Changed
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openfeature-sdk-sorbet (0.1.
|
4
|
+
openfeature-sdk-sorbet (0.1.2)
|
5
5
|
sorbet-runtime (~> 0.5)
|
6
6
|
sorbet-struct-comparable (~> 1.3)
|
7
7
|
zeitwerk (~> 2.6)
|
@@ -56,14 +56,14 @@ GEM
|
|
56
56
|
rubocop-sorbet (0.7.0)
|
57
57
|
rubocop (>= 0.90.0)
|
58
58
|
ruby-progressbar (1.13.0)
|
59
|
-
sorbet (0.5.
|
60
|
-
sorbet-static (= 0.5.
|
61
|
-
sorbet-runtime (0.5.
|
62
|
-
sorbet-static (0.5.
|
63
|
-
sorbet-static (0.5.
|
64
|
-
sorbet-static-and-runtime (0.5.
|
65
|
-
sorbet (= 0.5.
|
66
|
-
sorbet-runtime (= 0.5.
|
59
|
+
sorbet (0.5.10827)
|
60
|
+
sorbet-static (= 0.5.10827)
|
61
|
+
sorbet-runtime (0.5.10827)
|
62
|
+
sorbet-static (0.5.10827-universal-darwin-22)
|
63
|
+
sorbet-static (0.5.10827-x86_64-linux)
|
64
|
+
sorbet-static-and-runtime (0.5.10827)
|
65
|
+
sorbet (= 0.5.10827)
|
66
|
+
sorbet-runtime (= 0.5.10827)
|
67
67
|
sorbet-struct-comparable (1.3.0)
|
68
68
|
sorbet-runtime (>= 0.5)
|
69
69
|
spoom (1.2.1)
|
data/README.md
CHANGED
@@ -49,6 +49,21 @@ The OpenFeature specification defines [Structure as a potential return type](htt
|
|
49
49
|
|
50
50
|
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).
|
51
51
|
|
52
|
+
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:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
provider = OpenFeature::MultipleSourceProvider.new(
|
56
|
+
providers: [
|
57
|
+
CustomProvider.new,
|
58
|
+
OpenFeature::NoOpProvider.new
|
59
|
+
]
|
60
|
+
)
|
61
|
+
|
62
|
+
OpenFeature.set_provider(provider)
|
63
|
+
```
|
64
|
+
|
65
|
+
#### Implementing Custom Providers
|
66
|
+
|
52
67
|
Thanks to Sorbet interfaces, it's fairly straightforward to implement a new provider. Here is an example for a JSON-based flag format on disk:
|
53
68
|
|
54
69
|
```ruby
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module OpenFeature
|
5
|
+
# Used to pull from multiple providers.
|
6
|
+
# Order of the providers given to initialize matters.
|
7
|
+
# The providers will be evaluated in that order and the first
|
8
|
+
# non-error result will be used. If all sources return an error
|
9
|
+
# then the default value is used.
|
10
|
+
class MultipleSourceProvider
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
include Provider
|
14
|
+
|
15
|
+
sig { params(providers: T::Array[Provider]).void }
|
16
|
+
def initialize(providers:)
|
17
|
+
@providers = providers
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { override.returns(ProviderMetadata) }
|
21
|
+
def metadata
|
22
|
+
ProviderMetadata.new(name: "Multiple Sources: #{providers.map(&:metadata).map(&:name).join(", ")}")
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { override.returns(T::Array[Hook]) }
|
26
|
+
def hooks
|
27
|
+
providers.flat_map(&:hooks)
|
28
|
+
end
|
29
|
+
|
30
|
+
sig do
|
31
|
+
override
|
32
|
+
.params(
|
33
|
+
flag_key: String,
|
34
|
+
default_value: T::Boolean,
|
35
|
+
context: T.nilable(EvaluationContext)
|
36
|
+
)
|
37
|
+
.returns(ResolutionDetails[T::Boolean])
|
38
|
+
end
|
39
|
+
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)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
sig do
|
46
|
+
override
|
47
|
+
.params(
|
48
|
+
flag_key: String,
|
49
|
+
default_value: Numeric,
|
50
|
+
context: T.nilable(EvaluationContext)
|
51
|
+
)
|
52
|
+
.returns(ResolutionDetails[Numeric])
|
53
|
+
end
|
54
|
+
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)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
sig do
|
61
|
+
override
|
62
|
+
.params(
|
63
|
+
flag_key: String,
|
64
|
+
default_value: Structure,
|
65
|
+
context: T.nilable(EvaluationContext)
|
66
|
+
)
|
67
|
+
.returns(ResolutionDetails[Structure])
|
68
|
+
end
|
69
|
+
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)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
sig do
|
76
|
+
override
|
77
|
+
.params(
|
78
|
+
flag_key: String,
|
79
|
+
default_value: String,
|
80
|
+
context: T.nilable(EvaluationContext)
|
81
|
+
)
|
82
|
+
.returns(ResolutionDetails[String])
|
83
|
+
end
|
84
|
+
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)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
sig { returns(T::Array[Provider]) }
|
93
|
+
attr_reader :providers
|
94
|
+
|
95
|
+
# rubocop:disable Metrics/MethodLength
|
96
|
+
sig do
|
97
|
+
type_parameters(:U)
|
98
|
+
.params(
|
99
|
+
default_value: T.type_parameter(:U),
|
100
|
+
blk: T.proc.params(arg0: Provider).returns(ResolutionDetails[T.type_parameter(:U)])
|
101
|
+
)
|
102
|
+
.returns(ResolutionDetails[T.type_parameter(:U)])
|
103
|
+
end
|
104
|
+
def resolve_from_sources(default_value:, &blk)
|
105
|
+
successful_details = providers.each do |provider|
|
106
|
+
details = yield(provider)
|
107
|
+
|
108
|
+
break details if details.error_code.nil?
|
109
|
+
rescue StandardError
|
110
|
+
next
|
111
|
+
end
|
112
|
+
|
113
|
+
if successful_details.is_a?(ResolutionDetails)
|
114
|
+
successful_details
|
115
|
+
else
|
116
|
+
ResolutionDetails.new(value: default_value, error_code: ErrorCode::General, reason: "ERROR")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
# rubocop:enable Metrics/MethodLength
|
120
|
+
end
|
121
|
+
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.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max VelDink
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sorbet-runtime
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.6'
|
55
|
-
description:
|
55
|
+
description:
|
56
56
|
email:
|
57
57
|
- maxveldink@gmail.com
|
58
58
|
executables: []
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/open_feature/evaluation_options.rb
|
81
81
|
- lib/open_feature/flag_metadata.rb
|
82
82
|
- lib/open_feature/hook.rb
|
83
|
+
- lib/open_feature/multiple_source_provider.rb
|
83
84
|
- lib/open_feature/no_op_provider.rb
|
84
85
|
- lib/open_feature/provider.rb
|
85
86
|
- lib/open_feature/provider_metadata.rb
|
@@ -129,7 +130,7 @@ metadata:
|
|
129
130
|
homepage_uri: https://github.com/maxveldink/openfeature-sdk-sorbet
|
130
131
|
source_code_uri: https://github.com/maxveldink/openfeature-sdk-sorbet
|
131
132
|
changelog_uri: https://github.com/maxveldink/openfeature-sdk-sorbet/blob/main/CHANGELOG.md
|
132
|
-
post_install_message:
|
133
|
+
post_install_message:
|
133
134
|
rdoc_options: []
|
134
135
|
require_paths:
|
135
136
|
- lib
|
@@ -144,8 +145,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
145
|
- !ruby/object:Gem::Version
|
145
146
|
version: '0'
|
146
147
|
requirements: []
|
147
|
-
rubygems_version: 3.4.
|
148
|
-
signing_key:
|
148
|
+
rubygems_version: 3.4.10
|
149
|
+
signing_key:
|
149
150
|
specification_version: 4
|
150
151
|
summary: Sorbet-aware implemention of the OpenFeature specification
|
151
152
|
test_files: []
|