devcycle-ruby-server-sdk 3.3.0 → 3.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf57528da3b098cb3809b3263fa7d1c09c86b6d6c7659b18d8e4329b41f5db17
4
- data.tar.gz: cf875a30fb7df01907cc855a6191cfb20026070211de1df85852039e5cf46578
3
+ metadata.gz: a7c2ca8abeadbfc07bc034899330813d7167dbd9f863432fd34c968ff7597f00
4
+ data.tar.gz: 8fbdbd190921633b72bbb32abbd918dd83dbacc4bf4306864fbb95c587c92677
5
5
  SHA512:
6
- metadata.gz: 77453f3ef07274af1ab5eea8cb6d3f8daa139dcc32636888e27df9a0bbdd14e37b7318b25b7b941fb709ddcafc8d63fadf608f707ee5f943540b22ceae8373c1
7
- data.tar.gz: d00d7bf1751382362d5eb57046744924fecd7ceb99eedba5765a1b3172dd9e6a06dd8300c4e87bb46a2333c24f2d66e26d7d7dd0e274ccdfdb3c5da64768129b
6
+ metadata.gz: 84184a82c8d20bc21cdddc0142b08d915e6c3f4f29f562659e2be56cbd3cba5aca1f76bc98f613b1f9a3f00b157a82052dd05b49bbea5317583fbfe85bcf6b7c
7
+ data.tar.gz: a5ef7dec4c798f9efdaaed7b7c414159ccad957be178dc0becc2e4f852067146f6ee3ae1233659910fcd5e793611d99d038727474062dfd25a59023539912906
data/Gemfile CHANGED
@@ -15,3 +15,5 @@ group :development, :test do
15
15
  gem 'pry-byebug'
16
16
  gem 'rubocop', '~> 1.57.1'
17
17
  end
18
+
19
+ gem "openfeature-sdk", "~> 0.4.0"
@@ -3,6 +3,7 @@ require 'logger'
3
3
 
4
4
  module DevCycle
5
5
  class Client
6
+ attr_reader :open_feature_provider
6
7
  def initialize(sdkKey, dvc_options = Options.new, wait_for_init = false)
7
8
  if sdkKey.nil?
8
9
  raise ArgumentError.new('Missing SDK key!')
@@ -23,6 +24,7 @@ module DevCycle
23
24
  @local_bucketing = LocalBucketing.new(@sdkKey, dvc_options, wait_for_init)
24
25
  @event_queue = EventQueue.new(@sdkKey, dvc_options.event_queue_options, @local_bucketing)
25
26
  end
27
+ @open_feature_provider = Provider.new(self)
26
28
  end
27
29
 
28
30
  def close
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevCycle
4
+ class Provider
5
+ attr_reader :client
6
+ def initialize(client)
7
+ unless client.is_a?(DevCycle::Client)
8
+ fail ArgumentError('Client must be an instance of DevCycleClient')
9
+ end
10
+ @client = client
11
+ end
12
+
13
+ def init
14
+ # We handle all initialization on the DVC Client itself
15
+ end
16
+
17
+ def shutdown
18
+ @client.close
19
+ end
20
+
21
+ def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
22
+ # Retrieve a boolean value from provider source
23
+ @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
24
+ end
25
+
26
+ def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
27
+ @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
28
+ end
29
+
30
+ def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
31
+ @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
32
+ end
33
+
34
+ def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
35
+ @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
36
+ end
37
+
38
+ def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
39
+ @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
40
+ end
41
+
42
+ def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
43
+ @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
44
+ end
45
+
46
+ def self.user_from_openfeature_context(context)
47
+ unless context.is_a?(OpenFeature::SDK::EvaluationContext)
48
+ raise ArgumentError, "Invalid context type, expected OpenFeature::SDK::EvaluationContext but got #{context.class}"
49
+ end
50
+ args = {}
51
+ if context.field('user_id')
52
+ args.merge!(user_id: context.field('user_id'))
53
+ elsif context.field('targeting_key')
54
+ args.merge!(user_id: context.field('targeting_key'))
55
+ end
56
+ customData = {}
57
+ privateCustomData = {}
58
+ context.fields.each do |field, value|
59
+ if field === 'user_id' || field === 'targeting_key'
60
+ next
61
+ end
62
+ case field
63
+ when 'email'
64
+ args.merge!(email: value)
65
+ when 'name'
66
+ args.merge!(name: value)
67
+ when 'language'
68
+ args.merge!(language: value)
69
+ when 'country'
70
+ args.merge!(country: value)
71
+ when 'appVersion'
72
+ if value.is_a?(String)
73
+ args.merge!(appVersion: value)
74
+ end
75
+ next
76
+ when 'appBuild'
77
+ if value.is_a?(Numeric)
78
+ args.merge!(appBuild: value)
79
+ end
80
+ when 'customData'
81
+ if value.is_a?(Hash)
82
+ customData.merge!(value)
83
+ end
84
+ next
85
+ when 'privateCustomData'
86
+ if value.is_a?(Hash)
87
+ privateCustomData.merge!(value)
88
+ end
89
+ else
90
+ customData.merge!(field => value)
91
+ end
92
+ end
93
+ args.merge!(customData: customData)
94
+ args.merge!(privateCustomData: privateCustomData)
95
+ User.new(**args)
96
+ end
97
+ end
98
+ end
@@ -1,15 +1,3 @@
1
- =begin
2
- #DevCycle Bucketing API
3
-
4
- #Documents the DevCycle Bucketing API which provides and API interface to User Bucketing and for generated SDKs.
5
-
6
- The version of the OpenAPI document: 1.0.0
7
-
8
- Generated by: https://openapi-generator.tech
9
- OpenAPI Generator version: 5.3.0
10
-
11
- =end
12
-
13
1
  require 'date'
14
2
  require 'time'
15
3
  require 'oj'
@@ -11,5 +11,5 @@ OpenAPI Generator version: 5.3.0
11
11
  =end
12
12
 
13
13
  module DevCycle
14
- VERSION = '3.3.0'
14
+ VERSION = '3.4.0'
15
15
  end
@@ -27,6 +27,7 @@ require 'devcycle-ruby-server-sdk/models/variable'
27
27
 
28
28
  # APIs
29
29
  require 'devcycle-ruby-server-sdk/api/client'
30
+ require 'devcycle-ruby-server-sdk/api/dev_cycle_provider'
30
31
 
31
32
  require 'devcycle-ruby-server-sdk/localbucketing/options'
32
33
  require 'devcycle-ruby-server-sdk/localbucketing/local_bucketing'
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'open_feature/sdk'
5
+
6
+ context 'user_from_openfeature_context' do
7
+ context 'user_id' do
8
+
9
+ it 'returns a user with the user_id from the context' do
10
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id')
11
+ user = DevCycle::Provider.user_from_openfeature_context(context)
12
+ expect(user.user_id).to eq('user_id')
13
+ end
14
+
15
+ it 'returns a user with the targeting_key from the context' do
16
+ context = OpenFeature::SDK::EvaluationContext.new(targeting_key: 'targeting_key')
17
+ user = DevCycle::Provider.user_from_openfeature_context(context)
18
+ expect(user.user_id).to eq('targeting_key')
19
+ end
20
+ end
21
+ context 'email' do
22
+ it 'returns a user with a valid user_id and email' do
23
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id', email: 'email')
24
+ user = DevCycle::Provider.user_from_openfeature_context(context)
25
+ expect(user.user_id).to eq('user_id')
26
+ expect(user.email).to eq('email')
27
+ end
28
+ it 'returns a user with a valid targeting_key and email' do
29
+ context = OpenFeature::SDK::EvaluationContext.new(targeting_key: 'targeting_key', email: 'email')
30
+ user = DevCycle::Provider.user_from_openfeature_context(context)
31
+ expect(user.user_id).to eq('targeting_key')
32
+ expect(user.email).to eq('email')
33
+ end
34
+ end
35
+
36
+ context 'customData' do
37
+ it 'returns a user with customData' do
38
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id', customData: { 'key' => 'value' })
39
+ user = DevCycle::Provider.user_from_openfeature_context(context)
40
+ expect(user.user_id).to eq('user_id')
41
+ expect(user.customData).to eq({ 'key' => 'value' })
42
+ end
43
+ end
44
+
45
+ context 'privateCustomData' do
46
+ it 'returns a user with privateCustomData' do
47
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id', privateCustomData: { 'key' => 'value' })
48
+ user = DevCycle::Provider.user_from_openfeature_context(context)
49
+ expect(user.user_id).to eq('user_id')
50
+ expect(user.privateCustomData).to eq({ 'key' => 'value' })
51
+ end
52
+ end
53
+
54
+ context 'appVersion' do
55
+ it 'returns a user with appVersion' do
56
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id', appVersion: '1.0.0')
57
+ user = DevCycle::Provider.user_from_openfeature_context(context)
58
+ expect(user.user_id).to eq('user_id')
59
+ expect(user.appVersion).to eq('1.0.0')
60
+ end
61
+
62
+ it 'returns a user with appBuild' do
63
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id', appBuild: 1)
64
+ user = DevCycle::Provider.user_from_openfeature_context(context)
65
+ expect(user.user_id).to eq('user_id')
66
+ expect(user.appBuild).to eq(1)
67
+ end
68
+ end
69
+ context 'randomFields' do
70
+ it 'returns a user with customData fields mapped to any non-standard fields' do
71
+ context = OpenFeature::SDK::EvaluationContext.new(user_id: 'user_id', randomField: 'value')
72
+ user = DevCycle::Provider.user_from_openfeature_context(context)
73
+ expect(user.user_id).to eq('user_id')
74
+ expect(user.customData).to eq({ 'randomField' => 'value' })
75
+ end
76
+ end
77
+
78
+ context 'provider' do
79
+ before(:all) do
80
+ @dvc = DevCycle::Client.new('dvc_server_token_hash')
81
+ OpenFeature::SDK.configure do |config|
82
+ config.set_provider(@dvc.open_feature_provider)
83
+ end
84
+ @client = OpenFeature::SDK.build_client
85
+ sleep(3)
86
+ end
87
+ it 'returns a provider with a valid client' do
88
+ provider = @dvc.open_feature_provider
89
+ expect(provider).to be_instance_of(DevCycle::Provider)
90
+ end
91
+ it 'responds properly to fetch_boolean_value' do
92
+ expect(@client.fetch_boolean_value(flag_key: 'flag_key', default_value: false, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'user_id'))).to be(false)
93
+ end
94
+ it 'responds properly to fetch_string_value' do
95
+ expect(@client.fetch_string_value(flag_key: 'flag_key', default_value: 'default', evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'user_id'))).to eq('default')
96
+ end
97
+ it 'responds properly to fetch_number_value' do
98
+ expect(@client.fetch_number_value(flag_key: 'flag_key', default_value: 1, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'user_id'))).to eq(1)
99
+ end
100
+ it 'responds properly to fetch_integer_value' do
101
+ expect(@client.fetch_integer_value(flag_key: 'flag_key', default_value: 1, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'user_id'))).to eq(1)
102
+ end
103
+ it 'responds properly to fetch_float_value' do
104
+ expect(@client.fetch_float_value(flag_key: 'flag_key', default_value: 1.0, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'user_id'))).to eq(1.0)
105
+ end
106
+ it 'responds properly to fetch_object_value' do
107
+ expect(@client.fetch_object_value(flag_key: 'flag_key', default_value: { 'key' => 'value' }, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'user_id'))).to eq({ 'key' => 'value' })
108
+ end
109
+ it 'returns a provider with a valid client' do
110
+ provider = @dvc.open_feature_provider
111
+ expect(provider).to be_instance_of(DevCycle::Provider)
112
+ end
113
+ it 'responds properly to fetch_boolean_value' do
114
+ expect(@client.fetch_boolean_value(flag_key: 'test', default_value: false, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'test'))).to be(true)
115
+ end
116
+ it 'responds properly to fetch_string_value' do
117
+ expect(@client.fetch_string_value(flag_key: 'test-string-variable', default_value: 'default', evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'test'))).not_to eq('default')
118
+ end
119
+ it 'responds properly to fetch_number_value' do
120
+ expect(@client.fetch_number_value(flag_key: 'test-number-variable', default_value: 1, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'test'))).not_to eq(1)
121
+ end
122
+ it 'responds properly to fetch_integer_value' do
123
+ expect(@client.fetch_integer_value(flag_key: 'test-number-variable', default_value: 1, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'test'))).not_to eq(1)
124
+ end
125
+ it 'responds properly to fetch_float_value' do
126
+ expect(@client.fetch_float_value(flag_key: 'test-float-variable', default_value: 1.0, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'test'))).not_to eq(1.0)
127
+ end
128
+ it 'responds properly to fetch_object_value' do
129
+ expect(@client.fetch_object_value(flag_key: 'test-json-variable', default_value: { 'key' => 'value' }, evaluation_context: OpenFeature::SDK::EvaluationContext.new(user_id:'test'))).not_to eq({ 'key' => 'value' })
130
+ end
131
+ end
132
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devcycle-ruby-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DevCycleHQ
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-20 00:00:00.000000000 Z
11
+ date: 2025-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: typhoeus
@@ -148,6 +148,7 @@ files:
148
148
  - devcycle-ruby-server-sdk.gemspec
149
149
  - lib/devcycle-ruby-server-sdk.rb
150
150
  - lib/devcycle-ruby-server-sdk/api/client.rb
151
+ - lib/devcycle-ruby-server-sdk/api/dev_cycle_provider.rb
151
152
  - lib/devcycle-ruby-server-sdk/api_client.rb
152
153
  - lib/devcycle-ruby-server-sdk/api_error.rb
153
154
  - lib/devcycle-ruby-server-sdk/configuration.rb
@@ -175,6 +176,7 @@ files:
175
176
  - spec/api/devcycle_api_spec.rb
176
177
  - spec/api_client_spec.rb
177
178
  - spec/configuration_spec.rb
179
+ - spec/devcycle_provider_spec.rb
178
180
  - spec/spec_helper.rb
179
181
  homepage: https://devcycle.com
180
182
  licenses:
@@ -203,4 +205,5 @@ test_files:
203
205
  - spec/api/devcycle_api_spec.rb
204
206
  - spec/api_client_spec.rb
205
207
  - spec/configuration_spec.rb
208
+ - spec/devcycle_provider_spec.rb
206
209
  - spec/spec_helper.rb