openfeature-flagsmith-provider 0.1.1
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.
- checksums.yaml +7 -0
- data/.context.md +316 -0
- data/.gitignore +11 -0
- data/.rspec +4 -0
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +22 -0
- data/FLAGSMITH_PROVIDER_DESIGN.md +393 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +126 -0
- data/README.md +324 -0
- data/Rakefile +6 -0
- data/lib/openfeature/flagsmith/error/errors.rb +78 -0
- data/lib/openfeature/flagsmith/options.rb +82 -0
- data/lib/openfeature/flagsmith/provider.rb +265 -0
- data/lib/openfeature/flagsmith/version.rb +7 -0
- data/openfeature-flagsmith-provider.gemspec +38 -0
- metadata +176 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open_feature/sdk"
|
|
4
|
+
require "flagsmith"
|
|
5
|
+
require "json"
|
|
6
|
+
require_relative "options"
|
|
7
|
+
require_relative "error/errors"
|
|
8
|
+
|
|
9
|
+
module OpenFeature
|
|
10
|
+
module Flagsmith
|
|
11
|
+
# OpenFeature provider for Flagsmith
|
|
12
|
+
class Provider
|
|
13
|
+
PROVIDER_NAME = "Flagsmith Provider"
|
|
14
|
+
attr_reader :metadata, :options
|
|
15
|
+
|
|
16
|
+
def initialize(options:)
|
|
17
|
+
@metadata = SDK::Provider::ProviderMetadata.new(name: PROVIDER_NAME)
|
|
18
|
+
@options = options
|
|
19
|
+
@flagsmith_client = nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def init
|
|
23
|
+
# Initialize Flagsmith client
|
|
24
|
+
@flagsmith_client = create_flagsmith_client
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def shutdown
|
|
28
|
+
# Cleanup Flagsmith client resources
|
|
29
|
+
# Note: Flagsmith Ruby SDK doesn't require explicit cleanup as of version 4.3
|
|
30
|
+
# If future versions add cleanup methods, they should be called here
|
|
31
|
+
@flagsmith_client = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
|
|
35
|
+
evaluate_boolean(flag_key, default_value, evaluation_context)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
|
|
39
|
+
evaluate_value(flag_key, default_value, evaluation_context, [String])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
|
|
43
|
+
evaluate_value(flag_key, default_value, evaluation_context, [Integer, Float, Numeric])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
|
|
47
|
+
evaluate_value(flag_key, default_value, evaluation_context, [Integer])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
|
|
51
|
+
evaluate_value(flag_key, default_value, evaluation_context, [Float])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
|
|
55
|
+
evaluate_value(flag_key, default_value, evaluation_context, [Hash, Array])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def create_flagsmith_client
|
|
61
|
+
::Flagsmith::Client.new(
|
|
62
|
+
environment_key: @options.environment_key,
|
|
63
|
+
api_url: @options.api_url,
|
|
64
|
+
enable_local_evaluation: @options.local_evaluation?,
|
|
65
|
+
request_timeout_seconds: @options.request_timeout_seconds,
|
|
66
|
+
enable_analytics: @options.analytics_enabled?,
|
|
67
|
+
environment_refresh_interval_seconds: @options.environment_refresh_interval_seconds
|
|
68
|
+
)
|
|
69
|
+
rescue => e
|
|
70
|
+
raise ProviderNotReadyError, "Failed to create Flagsmith client: #{e.class}: #{e.message}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def evaluate_boolean(flag_key, default_value, evaluation_context)
|
|
74
|
+
return provider_not_ready_result(default_value) if @flagsmith_client.nil?
|
|
75
|
+
return invalid_flag_key_result(default_value) if flag_key.nil? || flag_key.to_s.empty?
|
|
76
|
+
|
|
77
|
+
flags = get_flags(evaluation_context)
|
|
78
|
+
value = flags.is_feature_enabled(flag_key)
|
|
79
|
+
|
|
80
|
+
success_result(value, evaluation_context)
|
|
81
|
+
rescue FlagsmithError => e
|
|
82
|
+
error_result(default_value, e.error_code, e.error_message)
|
|
83
|
+
rescue => e
|
|
84
|
+
error_result(default_value, SDK::Provider::ErrorCode::GENERAL, "Unexpected error: #{e.class}: #{e.message}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def evaluate_value(flag_key, default_value, evaluation_context, allowed_type_classes)
|
|
88
|
+
return provider_not_ready_result(default_value) if @flagsmith_client.nil?
|
|
89
|
+
return invalid_flag_key_result(default_value) if flag_key.nil? || flag_key.to_s.empty?
|
|
90
|
+
|
|
91
|
+
flags = get_flags(evaluation_context)
|
|
92
|
+
found_flag = flags.all_flags.find { |f| f.feature_name == flag_key }
|
|
93
|
+
|
|
94
|
+
return flag_not_found_result(default_value, flag_key) if found_flag.nil?
|
|
95
|
+
return flag_disabled_result(default_value, flag_key) unless found_flag.enabled
|
|
96
|
+
|
|
97
|
+
raw_value = found_flag.value
|
|
98
|
+
value = if [Hash, Array].any? { |klass| allowed_type_classes.include?(klass) }
|
|
99
|
+
parse_json_value(raw_value)
|
|
100
|
+
elsif [Integer, Float, Numeric].any? { |klass| allowed_type_classes.include?(klass) }
|
|
101
|
+
parse_numeric_value(raw_value, allowed_type_classes)
|
|
102
|
+
else
|
|
103
|
+
raw_value
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
return type_mismatch_result(default_value, value, allowed_type_classes) unless type_matches?(value, allowed_type_classes)
|
|
107
|
+
|
|
108
|
+
success_result(value, evaluation_context)
|
|
109
|
+
rescue FlagsmithError => e
|
|
110
|
+
error_result(default_value, e.error_code, e.error_message)
|
|
111
|
+
rescue => e
|
|
112
|
+
error_result(default_value, SDK::Provider::ErrorCode::GENERAL, "Unexpected error: #{e.class}: #{e.message}")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def provider_not_ready_result(default_value)
|
|
116
|
+
SDK::Provider::ResolutionDetails.new(
|
|
117
|
+
value: default_value,
|
|
118
|
+
reason: SDK::Provider::Reason::ERROR,
|
|
119
|
+
error_code: SDK::Provider::ErrorCode::PROVIDER_NOT_READY,
|
|
120
|
+
error_message: "Provider not initialized. Call init() first."
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def invalid_flag_key_result(default_value)
|
|
125
|
+
SDK::Provider::ResolutionDetails.new(
|
|
126
|
+
value: default_value,
|
|
127
|
+
reason: SDK::Provider::Reason::DEFAULT,
|
|
128
|
+
error_code: SDK::Provider::ErrorCode::FLAG_NOT_FOUND,
|
|
129
|
+
error_message: "Flag key cannot be empty or nil"
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def flag_not_found_result(default_value, flag_key)
|
|
134
|
+
SDK::Provider::ResolutionDetails.new(
|
|
135
|
+
value: default_value,
|
|
136
|
+
reason: SDK::Provider::Reason::DEFAULT,
|
|
137
|
+
error_code: SDK::Provider::ErrorCode::FLAG_NOT_FOUND,
|
|
138
|
+
error_message: "Flag '#{flag_key}' not found"
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def flag_disabled_result(default_value, flag_key)
|
|
143
|
+
SDK::Provider::ResolutionDetails.new(
|
|
144
|
+
value: default_value,
|
|
145
|
+
reason: SDK::Provider::Reason::DISABLED,
|
|
146
|
+
error_message: "Flag '#{flag_key}' is disabled"
|
|
147
|
+
)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def type_mismatch_result(default_value, value, allowed_type_classes)
|
|
151
|
+
SDK::Provider::ResolutionDetails.new(
|
|
152
|
+
value: default_value,
|
|
153
|
+
reason: SDK::Provider::Reason::ERROR,
|
|
154
|
+
error_code: SDK::Provider::ErrorCode::TYPE_MISMATCH,
|
|
155
|
+
error_message: "Expected type #{allowed_type_classes}, got #{value.class}"
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def error_result(default_value, error_code, error_message)
|
|
160
|
+
SDK::Provider::ResolutionDetails.new(
|
|
161
|
+
value: default_value,
|
|
162
|
+
reason: SDK::Provider::Reason::ERROR,
|
|
163
|
+
error_code: error_code,
|
|
164
|
+
error_message: error_message
|
|
165
|
+
)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def success_result(value, evaluation_context)
|
|
169
|
+
SDK::Provider::ResolutionDetails.new(
|
|
170
|
+
value: value,
|
|
171
|
+
reason: determine_reason(evaluation_context),
|
|
172
|
+
variant: nil,
|
|
173
|
+
flag_metadata: {}
|
|
174
|
+
)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def get_flags(evaluation_context)
|
|
178
|
+
raise ProviderNotReadyError, "Flagsmith client not initialized" if @flagsmith_client.nil?
|
|
179
|
+
|
|
180
|
+
if evaluation_context.nil?
|
|
181
|
+
return @flagsmith_client.get_environment_flags
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
targeting_key = evaluation_context.targeting_key
|
|
185
|
+
if targeting_key.nil? || targeting_key.to_s.strip.empty?
|
|
186
|
+
@flagsmith_client.get_environment_flags
|
|
187
|
+
else
|
|
188
|
+
traits = evaluation_context.fields.transform_keys(&:to_sym).reject { |k, _v| k == :targeting_key }
|
|
189
|
+
@flagsmith_client.get_identity_flags(targeting_key.to_s, **traits)
|
|
190
|
+
end
|
|
191
|
+
rescue => e
|
|
192
|
+
raise FlagsmithClientError, "#{e.class}: #{e.message}"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def parse_json_value(value)
|
|
196
|
+
return value if value.is_a?(Hash) || value.is_a?(Array)
|
|
197
|
+
return nil if value.nil?
|
|
198
|
+
|
|
199
|
+
JSON.parse(value.to_s)
|
|
200
|
+
rescue JSON::ParserError => e
|
|
201
|
+
raise ParseError, e.message
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def parse_numeric_value(value, allowed_type_classes)
|
|
205
|
+
# If already the right type, return it
|
|
206
|
+
return value if allowed_type_classes.any? { |klass| value.is_a?(klass) }
|
|
207
|
+
return nil if value.nil?
|
|
208
|
+
|
|
209
|
+
# Try to parse string to numeric
|
|
210
|
+
if value.is_a?(String)
|
|
211
|
+
if allowed_type_classes.include?(Numeric)
|
|
212
|
+
# For Numeric, try Integer first, then Float
|
|
213
|
+
begin
|
|
214
|
+
return Integer(value)
|
|
215
|
+
rescue ArgumentError, TypeError
|
|
216
|
+
return Float(value)
|
|
217
|
+
end
|
|
218
|
+
elsif allowed_type_classes.include?(Integer)
|
|
219
|
+
return Integer(value)
|
|
220
|
+
elsif allowed_type_classes.include?(Float)
|
|
221
|
+
return Float(value)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Safe numeric type conversions (following Flipt provider pattern)
|
|
226
|
+
if value.is_a?(Numeric)
|
|
227
|
+
# Integer → Float: always safe (no precision loss)
|
|
228
|
+
if value.is_a?(Integer) && allowed_type_classes == [Float]
|
|
229
|
+
return value.to_f
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Float → Integer: only if it's a whole number (prevents data loss)
|
|
233
|
+
# Example: 3.0 → 3 (OK), but 3.99 → fails type check (ERROR)
|
|
234
|
+
if value.is_a?(Float) && allowed_type_classes == [Integer]
|
|
235
|
+
return value.to_i if value.to_i == value
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# For generic fetch_number_value (accepts any numeric type), return as-is
|
|
239
|
+
# This handles [Integer, Float, Numeric] case
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
value
|
|
243
|
+
rescue ArgumentError, TypeError => e
|
|
244
|
+
raise ParseError, "Cannot convert '#{value}' to numeric type: #{e.message}"
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def type_matches?(value, allowed_type_classes)
|
|
248
|
+
allowed_type_classes.any? { |klass| value.is_a?(klass) }
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def determine_reason(evaluation_context)
|
|
252
|
+
# Use TARGETING_MATCH if we have targeting_key (identity-specific)
|
|
253
|
+
# Use STATIC for environment-level flags
|
|
254
|
+
return SDK::Provider::Reason::STATIC if evaluation_context.nil?
|
|
255
|
+
|
|
256
|
+
targeting_key = evaluation_context.targeting_key
|
|
257
|
+
if targeting_key.nil? || targeting_key.to_s.strip.empty?
|
|
258
|
+
SDK::Provider::Reason::STATIC
|
|
259
|
+
else
|
|
260
|
+
SDK::Provider::Reason::TARGETING_MATCH
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require_relative "lib/openfeature/flagsmith/version"
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = "openfeature-flagsmith-provider"
|
|
5
|
+
spec.version = OpenFeature::Flagsmith::VERSION
|
|
6
|
+
spec.authors = ["OpenFeature Contributors"]
|
|
7
|
+
spec.email = ["cncf-openfeature-contributors@lists.cncf.io"]
|
|
8
|
+
|
|
9
|
+
spec.summary = "OpenFeature provider for Flagsmith"
|
|
10
|
+
spec.description = "Flagsmith provider for the OpenFeature Ruby SDK"
|
|
11
|
+
spec.homepage = "https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider"
|
|
12
|
+
spec.license = "Apache-2.0"
|
|
13
|
+
spec.required_ruby_version = ">= 3.1"
|
|
14
|
+
|
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
16
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
17
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
18
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/issues"
|
|
19
|
+
spec.metadata["documentation_uri"] = "#{spec.homepage}/README.md"
|
|
20
|
+
|
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
spec.require_paths = ["lib"]
|
|
26
|
+
|
|
27
|
+
# Runtime dependencies
|
|
28
|
+
spec.add_runtime_dependency "openfeature-sdk", "~> 0.3.1"
|
|
29
|
+
spec.add_runtime_dependency "flagsmith", "~> 4.3"
|
|
30
|
+
|
|
31
|
+
# Development dependencies
|
|
32
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.12.0"
|
|
34
|
+
spec.add_development_dependency "webmock", "~> 3.0"
|
|
35
|
+
spec.add_development_dependency "standard", "~> 1.0"
|
|
36
|
+
spec.add_development_dependency "rubocop", "~> 1.0"
|
|
37
|
+
spec.add_development_dependency "simplecov", "~> 0.22"
|
|
38
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: openfeature-flagsmith-provider
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- OpenFeature Contributors
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-12-15 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: openfeature-sdk
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.3.1
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.3.1
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: flagsmith
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '4.3'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '4.3'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '13.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '13.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 3.12.0
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 3.12.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: webmock
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '3.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '3.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: standard
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '1.0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rubocop
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '1.0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '1.0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: simplecov
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.22'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0.22'
|
|
125
|
+
description: Flagsmith provider for the OpenFeature Ruby SDK
|
|
126
|
+
email:
|
|
127
|
+
- cncf-openfeature-contributors@lists.cncf.io
|
|
128
|
+
executables: []
|
|
129
|
+
extensions: []
|
|
130
|
+
extra_rdoc_files: []
|
|
131
|
+
files:
|
|
132
|
+
- ".context.md"
|
|
133
|
+
- ".gitignore"
|
|
134
|
+
- ".rspec"
|
|
135
|
+
- ".rubocop.yml"
|
|
136
|
+
- ".ruby-version"
|
|
137
|
+
- CHANGELOG.md
|
|
138
|
+
- FLAGSMITH_PROVIDER_DESIGN.md
|
|
139
|
+
- Gemfile
|
|
140
|
+
- Gemfile.lock
|
|
141
|
+
- README.md
|
|
142
|
+
- Rakefile
|
|
143
|
+
- lib/openfeature/flagsmith/error/errors.rb
|
|
144
|
+
- lib/openfeature/flagsmith/options.rb
|
|
145
|
+
- lib/openfeature/flagsmith/provider.rb
|
|
146
|
+
- lib/openfeature/flagsmith/version.rb
|
|
147
|
+
- openfeature-flagsmith-provider.gemspec
|
|
148
|
+
homepage: https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider
|
|
149
|
+
licenses:
|
|
150
|
+
- Apache-2.0
|
|
151
|
+
metadata:
|
|
152
|
+
homepage_uri: https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider
|
|
153
|
+
source_code_uri: https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider
|
|
154
|
+
changelog_uri: https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider/blob/main/CHANGELOG.md
|
|
155
|
+
bug_tracker_uri: https://github.com/open-feature/ruby-sdk-contrib/issues
|
|
156
|
+
documentation_uri: https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider/README.md
|
|
157
|
+
post_install_message:
|
|
158
|
+
rdoc_options: []
|
|
159
|
+
require_paths:
|
|
160
|
+
- lib
|
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '3.1'
|
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
|
+
requirements:
|
|
168
|
+
- - ">="
|
|
169
|
+
- !ruby/object:Gem::Version
|
|
170
|
+
version: '0'
|
|
171
|
+
requirements: []
|
|
172
|
+
rubygems_version: 3.5.22
|
|
173
|
+
signing_key:
|
|
174
|
+
specification_version: 4
|
|
175
|
+
summary: OpenFeature provider for Flagsmith
|
|
176
|
+
test_files: []
|