openfeature-sdk 0.0.3 → 0.1.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: fa5a6e99d67eb65e8880d796b8785091679e353eabe7f619282d0aa30a14541d
4
- data.tar.gz: 1e56499af1beac4c98245c40fcd840aad5a6327dc010320b76320f5f29065026
3
+ metadata.gz: 6286e12fce6a89a9b310e838fd456bfb6dd0fa35ea7d1bd99745beca5781fbd8
4
+ data.tar.gz: ed73a6433ca51fa55403f0893097f102e8816ca93c3b4ec5a21c26b019055461
5
5
  SHA512:
6
- metadata.gz: 7e93027418e168d45dfdb874e9eafd9e8d94c479d0e31f4db09fad10ce6b454b0beb01e5fd42217d4f68ab0ecfb1be2402f673b02bc0399ff0469258a4b82558
7
- data.tar.gz: 4ee653114169ef9ee3af004b65ca6fca4df1674f07cdb1493e28737667fa4d30f2ab1e7245de0b11627c9ae43fcfe175b4e24d6b5b40e0534b38a6bfabb0878a
6
+ metadata.gz: d81f9a31e72afb82edae5cb499d7cec3955199f9b5c795b7f477be314b1de5e5bc26cf9db292b1333b4da5a41ed3f068cab55494a10c1d355a3b641aa3560e4e
7
+ data.tar.gz: 7aff559376dd006308d92806521731aa0b95ddc098f2455bfdb8aa5d7ca4bb8dc57ac7f8ae5939bef9c66672c032d65548c09d704a74df51f2fdd5cad0aa6c28
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.0.3"
2
+ ".": "0.1.0"
3
3
  }
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
+ -I lib
1
2
  --format documentation
2
3
  --color
3
4
  --require spec_helper
data/.rubocop.yml CHANGED
@@ -12,6 +12,17 @@ Style/StringLiteralsInInterpolation:
12
12
 
13
13
  Layout/LineLength:
14
14
  Max: 120
15
+ Exclude:
16
+ - 'spec/**/*.rb'
17
+
18
+ Metrics/BlockLength:
19
+ Exclude:
20
+ - 'spec/**/*.rb'
21
+ - 'openfeature-sdk.gemspec'
15
22
 
16
23
  Gemspec/RequireMFA:
17
24
  Enabled: false
25
+
26
+ Style/DocumentDynamicEvalDefinition:
27
+ # TODO re-enable after figuring out what it actually wants
28
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.1.2
1
+ 3.1.3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.0](https://github.com/open-feature/ruby-sdk/compare/v0.0.3...v0.1.0) (2022-12-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * Add client object ([#34](https://github.com/open-feature/ruby-sdk/issues/34)) ([92f8d0d](https://github.com/open-feature/ruby-sdk/commit/92f8d0d4bf693bf74d0f076621f3453f11d4ca65))
9
+ * OpenFeature::SDK.configure ([#41](https://github.com/open-feature/ruby-sdk/issues/41)) ([7587799](https://github.com/open-feature/ruby-sdk/commit/75877997dcb49aeb38a4969734df87b2845e1e6a))
10
+ * **spec:** Add API implementation ([#32](https://github.com/open-feature/ruby-sdk/issues/32)) ([d6b0922](https://github.com/open-feature/ruby-sdk/commit/d6b0922a54e9cb714c44dfe58ddab01356f6916b))
11
+
3
12
  ## [0.0.3](https://github.com/open-feature/ruby-sdk/compare/v0.0.2...v0.0.3) (2022-11-11)
4
13
 
5
14
 
data/Gemfile CHANGED
@@ -4,3 +4,5 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in openfeature-sdk.gemspec
6
6
  gemspec
7
+
8
+ gem "concurrent-ruby", require: "concurrent"
data/Gemfile.lock CHANGED
@@ -1,12 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openfeature-sdk (0.0.3)
4
+ openfeature-sdk (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ concurrent-ruby (1.1.10)
10
11
  diff-lcs (1.5.0)
11
12
  json (2.6.2)
12
13
  parallel (1.22.1)
@@ -55,6 +56,7 @@ PLATFORMS
55
56
  x86_64-linux
56
57
 
57
58
  DEPENDENCIES
59
+ concurrent-ruby
58
60
  openfeature-sdk!
59
61
  rake (~> 13.0)
60
62
  rspec (~> 3.12.0)
data/README.md CHANGED
@@ -50,17 +50,17 @@ end
50
50
  client = OpenFeature::SDK.build_client(name: "my-app")
51
51
 
52
52
  # fetching boolean value feature flag
53
- bool_value = client.fetch_boolean_value(flag_key: 'boolean_flag', default_value: false);
53
+ bool_value = client.fetch_boolean_value(flag_key: 'boolean_flag', default_value: false)
54
54
 
55
55
  # fetching string value feature flag
56
- string_value = client.fetch_string_value(flag_key: 'string_flag', default_value: false);
56
+ string_value = client.fetch_string_value(flag_key: 'string_flag', default_value: false)
57
57
 
58
58
  # fetching number value feature flag
59
- float_value = client.fetch_number_value(flag_key: 'number_value', default_value: 1.0);
60
- integer_value = client.fetch_number_value(flag_key: 'number_value', default_value: 1);
59
+ float_value = client.fetch_number_value(flag_key: 'number_value', default_value: 1.0)
60
+ integer_value = client.fetch_number_value(flag_key: 'number_value', default_value: 1)
61
61
 
62
62
  # get an object value
63
- object = client.fetch_object_value('object_value', JSON.dump({ name: 'object'}));
63
+ object = client.fetch_object_value(flag_key: 'object_value', default_value: JSON.dump({ name: 'object'}))
64
64
  ```
65
65
 
66
66
  For complete documentation, visit: https://docs.openfeature.dev/docs/category/concepts
data/Rakefile CHANGED
@@ -7,6 +7,9 @@ RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  require "rubocop/rake_task"
9
9
 
10
- RuboCop::RakeTask.new
10
+ RuboCop::RakeTask.new do |task|
11
+ task.options = ["--parallel"]
12
+ task.options << "--color" if ENV["CI"] == "true"
13
+ end
11
14
 
12
15
  task default: %i[spec rubocop]
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "singleton"
5
+
6
+ require_relative "configuration"
7
+ require_relative "client"
8
+ require_relative "metadata"
9
+ require_relative "provider/no_op_provider"
10
+
11
+ module OpenFeature
12
+ module SDK
13
+ # API Initialization and Configuration
14
+ #
15
+ # Represents the entry point to the API, including configuration of <tt>Provider</tt>,<tt>Hook</tt>,
16
+ # and building the <tt>Client</tt>
17
+ #
18
+ # To use the SDK, you can optionally configure a <tt>Provider</tt>, with <tt>Hook</tt>
19
+ #
20
+ # OpenFeature::SDK::API.instance.configure do |config|
21
+ # config.provider = NoOpProvider.new
22
+ # end
23
+ #
24
+ # If no provider is specified, the <tt>NoOpProvider</tt> is set as the default <tt>Provider</tt>.
25
+ # Once the SDK has been configured, a client can be built
26
+ #
27
+ # client = OpenFeature::SDK::API.instance.build_client(name: 'my-open-feature-client')
28
+ class API
29
+ include Singleton
30
+ extend Forwardable
31
+
32
+ def_delegator :@configuration, :provider
33
+ def_delegator :@configuration, :hooks
34
+ def_delegator :@configuration, :context
35
+
36
+ def configuration
37
+ @configuration ||= Configuration.new
38
+ end
39
+
40
+ def configure(&block)
41
+ return unless block_given?
42
+
43
+ block.call(configuration)
44
+ end
45
+
46
+ def build_client(name: nil, version: nil)
47
+ client_options = Metadata.new(name: name, version: version).freeze
48
+ provider = Provider::NoOpProvider.new if provider.nil?
49
+ Client.new(provider: provider, client_options: client_options, context: context)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenFeature
4
+ module SDK
5
+ # TODO: Write documentation
6
+ #
7
+ class Client
8
+ RESULT_TYPE = %i[boolean string number object].freeze
9
+ SUFFIXES = %i[value details].freeze
10
+
11
+ attr_reader :metadata
12
+
13
+ attr_accessor :hooks
14
+
15
+ def initialize(provider:, client_options: nil, context: nil)
16
+ @provider = provider
17
+ @metadata = client_options
18
+ @context = context
19
+ @hooks = []
20
+ end
21
+
22
+ RESULT_TYPE.each do |result_type|
23
+ SUFFIXES.each do |suffix|
24
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
25
+ # def fetch_boolean_details(flag_key:, default_value:, evaluation_context: nil)
26
+ # result = @provider.fetch_boolean_value(flag_key: flag_key, default_value: default_value, evaluation_context: evaluation_context)
27
+ # end
28
+ def fetch_#{result_type}_#{suffix}(flag_key:, default_value:, evaluation_context: nil)
29
+ result = @provider.fetch_#{result_type}_value(flag_key: flag_key, default_value: default_value, evaluation_context: evaluation_context)
30
+ #{"result.value" if suffix == :value}
31
+ end
32
+ RUBY
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent"
4
+
5
+ require_relative "api"
6
+
7
+ module OpenFeature
8
+ module SDK
9
+ # Represents the configuration object for the global API where <tt>Provider</tt>, <tt>Hook</tt>,
10
+ # and <tt>Context</tt> are configured.
11
+ # This class is not meant to be interacted with directly but instead through the <tt>OpenFeature::SDK.configure</tt>
12
+ # method
13
+ class Configuration
14
+ extend Forwardable
15
+
16
+ attr_accessor :context, :provider, :hooks
17
+
18
+ def_delegator :@provider, :metadata
19
+
20
+ def initialize
21
+ @hooks = Concurrent::Array.new([])
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenFeature
4
+ module SDK
5
+ # Metadata structure that defines general metadata relating to a <tt>Provider</tt> or <tt>Client</tt>
6
+ #
7
+ # Within the Metadata structure, the following attribute readers are available:
8
+ #
9
+ # * <tt>name</tt> - Defines the name of the structure
10
+ #
11
+ # * <tt>version</tt> - Allows you to specify version of the Metadata structure
12
+ #
13
+ # Usage:
14
+ #
15
+ # metadata = Metadata.new(name: 'name-for-metadata', version: 'v1.1.3')
16
+ # metadata.name # 'name-for-metadata'
17
+ # metadata.version # version
18
+ # metadata_two = Metadata.new(name: 'name-for-metadata')
19
+ # metadata_two == metadata # true - equality based on values
20
+ class Metadata
21
+ attr_reader :name, :version
22
+
23
+ def initialize(name:, version: nil)
24
+ @name = name
25
+ @version = version
26
+ end
27
+
28
+ def ==(other)
29
+ raise ArgumentError("Expected comparison to be between Metadata object") unless other.is_a?(Metadata)
30
+
31
+ @name == other.name && @version == other.version
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../metadata"
4
+
5
+ # rubocop:disable Lint/UnusedMethodArgument
6
+ module OpenFeature
7
+ module SDK
8
+ module Provider
9
+ # Defines the default provider that is set if no provider is specified.
10
+ #
11
+ # To use <tt>NoOpProvider</tt>, it can be set during the configuration of the SDK
12
+ #
13
+ # OpenFeature::SDK.configure do |config|
14
+ # config.provider = NoOpProvider.new
15
+ # end
16
+ #
17
+ # Within the <tt>NoOpProvider</tt>, the following methods exist
18
+ #
19
+ # * <tt>fetch_boolean_value</tt> - Retrieve feature flag boolean value
20
+ #
21
+ # * <tt>fetch_string_value</tt> - Retrieve feature flag string value
22
+ #
23
+ # * <tt>fetch_number_value</tt> - Retrieve feature flag number value
24
+ #
25
+ # * <tt>fetch_object_value</tt> - Retrieve feature flag object value
26
+ #
27
+ class NoOpProvider
28
+ REASON_NO_OP = "No-op"
29
+ NAME = "No-op Provider"
30
+
31
+ attr_reader :metadata
32
+
33
+ ResolutionDetails = Struct.new(:value, :reason, :variant, :error_code, :error_message)
34
+
35
+ def initialize
36
+ @metadata = Metadata.new(name: NAME).freeze
37
+ end
38
+
39
+ def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
40
+ no_op(default_value)
41
+ end
42
+
43
+ def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
44
+ no_op(default_value)
45
+ end
46
+
47
+ def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
48
+ no_op(default_value)
49
+ end
50
+
51
+ def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
52
+ no_op(default_value)
53
+ end
54
+
55
+ private
56
+
57
+ def no_op(default_value)
58
+ ResolutionDetails.new(value: default_value, reason: REASON_NO_OP)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ # rubocop:enable Lint/UnusedMethodArgument
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OpenFeature
4
4
  module SDK
5
- VERSION = "0.0.3"
5
+ VERSION = "0.1.0"
6
6
  end
7
7
  end
@@ -1,10 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "sdk/version"
4
+ require_relative "sdk/api"
4
5
 
5
6
  module OpenFeature
7
+ # TODO: Add documentation
8
+ #
6
9
  module SDK
7
- class Error < StandardError; end
8
- # Your code goes here...
10
+ class << self
11
+ def method_missing(method_name, *args, **kwargs, &block)
12
+ if API.instance.respond_to?(method_name)
13
+ API.instance.send(method_name, *args, **kwargs, &block)
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ def respond_to_missing?(method_name, include_private = false)
20
+ API.instance.respond_to?(method_name, include_private) || super
21
+ end
22
+ end
9
23
  end
10
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openfeature-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenFeature Authors
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-11 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -72,6 +72,11 @@ files:
72
72
  - README.md
73
73
  - Rakefile
74
74
  - lib/openfeature/sdk.rb
75
+ - lib/openfeature/sdk/api.rb
76
+ - lib/openfeature/sdk/client.rb
77
+ - lib/openfeature/sdk/configuration.rb
78
+ - lib/openfeature/sdk/metadata.rb
79
+ - lib/openfeature/sdk/provider/no_op_provider.rb
75
80
  - lib/openfeature/sdk/version.rb
76
81
  - release-please-config.json
77
82
  - renovate.json
@@ -100,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
105
  - !ruby/object:Gem::Version
101
106
  version: '0'
102
107
  requirements: []
103
- rubygems_version: 3.3.7
108
+ rubygems_version: 3.3.26
104
109
  signing_key:
105
110
  specification_version: 4
106
111
  summary: OpenFeature SDK for Ruby