openfeature-sdk 0.5.0 → 0.5.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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +7 -0
- data/CLAUDE.md +72 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -2
- data/lib/open_feature/sdk/api.rb +1 -0
- data/lib/open_feature/sdk/client.rb +49 -9
- data/lib/open_feature/sdk/hooks/hints.rb +2 -0
- data/lib/open_feature/sdk/hooks/hook.rb +34 -0
- data/lib/open_feature/sdk/hooks/hook_context.rb +29 -0
- data/lib/open_feature/sdk/hooks/hook_executor.rb +102 -0
- data/lib/open_feature/sdk/hooks.rb +6 -0
- data/lib/open_feature/sdk/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36540a362c2f482ce84d2aa8ba3a6efd9b5d68fe7881ed4037f1422ad85f5525
|
|
4
|
+
data.tar.gz: 4f7e6a764074d50467949e056b0d50be794df0a67323bb80c5e34a724236314b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b77f6731c17b537069bbf72cf4760e88293bc59c9ae147079ff3b24ac6ac7f1b18b42b49e29fd1a04a85a6054d0a43834289561c06d6b342ba579ec23d510ef8
|
|
7
|
+
data.tar.gz: 077d8a3f20c396c82413dad70b9a93cff0cd27a76ff8034f67c50bfa0d08235e3424755a4cd33b81c39fed962d7a62e40d1f257d3bbc4e87bac787d0e315b3fb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.1](https://github.com/open-feature/ruby-sdk/compare/v0.5.0...v0.5.1) (2026-03-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* implement hooks lifecycle (spec section 4) ([#214](https://github.com/open-feature/ruby-sdk/issues/214)) ([41c3b9e](https://github.com/open-feature/ruby-sdk/commit/41c3b9e2b73b34f50d8135122fb4592f8ec44e49))
|
|
9
|
+
|
|
3
10
|
## [0.5.0](https://github.com/open-feature/ruby-sdk/compare/v0.4.1...v0.5.0) (2026-01-16)
|
|
4
11
|
|
|
5
12
|
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
OpenFeature Ruby SDK — implements the [OpenFeature specification](https://openfeature.dev) (v0.8.0) for vendor-agnostic feature flag management. Published as the `openfeature-sdk` gem. Pure Ruby, no runtime dependencies. Requires Ruby >= 3.1.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Install dependencies
|
|
13
|
+
bundle install
|
|
14
|
+
|
|
15
|
+
# Run full test suite + linting (default rake task)
|
|
16
|
+
bundle exec rake
|
|
17
|
+
|
|
18
|
+
# Run tests only
|
|
19
|
+
bundle exec rspec
|
|
20
|
+
|
|
21
|
+
# Run a single test file
|
|
22
|
+
bundle exec rspec spec/open_feature/sdk/client_spec.rb
|
|
23
|
+
|
|
24
|
+
# Run a specific test by line number
|
|
25
|
+
bundle exec rspec spec/open_feature/sdk/client_spec.rb:40
|
|
26
|
+
|
|
27
|
+
# Lint (StandardRB with performance plugin)
|
|
28
|
+
bundle exec rake standard
|
|
29
|
+
|
|
30
|
+
# Auto-fix lint issues
|
|
31
|
+
bundle exec standardrb --fix
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
Entry point: `require 'open_feature/sdk'` — the `OpenFeature::SDK` module delegates all method calls to `API.instance` (Singleton) via `method_missing`.
|
|
37
|
+
|
|
38
|
+
### Core Components
|
|
39
|
+
|
|
40
|
+
- **API** (`lib/open_feature/sdk/api.rb`) — Singleton orchestrator. Manages providers (global or domain-scoped), builds clients, stores API-level evaluation context, and registers event handlers.
|
|
41
|
+
- **Configuration** (`lib/open_feature/sdk/configuration.rb`) — Thread-safe provider storage. Handles provider lifecycle (init/shutdown), domain-scoped provider mapping, and event dispatching. Uses Mutex for all shared state.
|
|
42
|
+
- **Client** (`lib/open_feature/sdk/client.rb`) — Flag evaluation interface. Uses `class_eval` metaprogramming to generate 12 typed methods: `fetch_{boolean,string,number,integer,float,object}_value` and `fetch_*_details` variants. Merges evaluation contexts (API + client + invocation).
|
|
43
|
+
- **EvaluationContext** (`lib/open_feature/sdk/evaluation_context.rb`) — Key-value targeting data with a special `targeting_key`. Supports merging with precedence: invocation > client > API.
|
|
44
|
+
|
|
45
|
+
### Provider System
|
|
46
|
+
|
|
47
|
+
- **Provider interface** — Must implement 6 `fetch_*_value` methods, optional `init(evaluation_context)` and `shutdown`. Returns `ResolutionDetails`.
|
|
48
|
+
- **EventEmitter** (`lib/open_feature/sdk/provider/event_emitter.rb`) — Mixin that providers include to emit lifecycle events.
|
|
49
|
+
- **Built-in providers**: `NoOpProvider` (default), `InMemoryProvider` (testing/examples).
|
|
50
|
+
- **Provider states**: `NOT_READY → READY`, with `ERROR`, `FATAL`, `STALE` transitions. Tracked per-instance via `ProviderStateRegistry` using `object_id`.
|
|
51
|
+
- **Initialization modes**: `set_provider` (async, background thread) or `set_provider_and_wait` (sync, raises `ProviderInitializationError` on failure).
|
|
52
|
+
|
|
53
|
+
### Event System
|
|
54
|
+
|
|
55
|
+
- **EventDispatcher** (`lib/open_feature/sdk/event_dispatcher.rb`) — Thread-safe pub-sub. Handlers called outside mutex to prevent deadlocks. Supports API-level and client-level handlers.
|
|
56
|
+
- **ProviderEvent** constants: `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_STALE`, `PROVIDER_CONFIGURATION_CHANGED`.
|
|
57
|
+
|
|
58
|
+
## Test Structure
|
|
59
|
+
|
|
60
|
+
Tests in `spec/` split into two categories:
|
|
61
|
+
- `spec/specification/` — OpenFeature spec compliance tests, organized by requirement number (e.g., "Requirement 1.1.1")
|
|
62
|
+
- `spec/open_feature/` — Unit tests for individual components
|
|
63
|
+
|
|
64
|
+
Uses Timecop for time-sensitive tests (auto-reset after each test), SimpleCov for coverage.
|
|
65
|
+
|
|
66
|
+
## Conventions
|
|
67
|
+
|
|
68
|
+
- **Linter**: StandardRB (Ruby Standard Style) with `standard-performance` plugin, targeting Ruby 3.1
|
|
69
|
+
- **Commits**: Conventional Commits required for PR titles (enforced by CI)
|
|
70
|
+
- **Releases**: Automated via release-please; changelog auto-generated
|
|
71
|
+
- **Threading**: All shared mutable state must be Mutex-protected. Provider storage uses immutable reassignment (`@providers = @providers.dup.merge(...)`)
|
|
72
|
+
- **Structs for DTOs**: `EvaluationDetails`, `ResolutionDetails`, `ClientMetadata`, `ProviderMetadata` are `Struct`-based
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
</a>
|
|
18
18
|
<!-- x-release-please-start-version -->
|
|
19
19
|
|
|
20
|
-
<a href="https://github.com/open-feature/ruby-sdk/releases/tag/v0.5.
|
|
21
|
-
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.5.
|
|
20
|
+
<a href="https://github.com/open-feature/ruby-sdk/releases/tag/v0.5.1">
|
|
21
|
+
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.5.1&color=blue&style=for-the-badge" />
|
|
22
22
|
</a>
|
|
23
23
|
|
|
24
24
|
<!-- x-release-please-end -->
|
data/lib/open_feature/sdk/api.rb
CHANGED
|
@@ -15,6 +15,7 @@ module OpenFeature
|
|
|
15
15
|
}.freeze
|
|
16
16
|
RESULT_TYPE = TYPE_CLASS_MAP.keys.freeze
|
|
17
17
|
SUFFIXES = %i[value details].freeze
|
|
18
|
+
EMPTY_HINTS = Hooks::Hints.new.freeze
|
|
18
19
|
|
|
19
20
|
attr_reader :metadata, :evaluation_context
|
|
20
21
|
|
|
@@ -40,11 +41,8 @@ module OpenFeature
|
|
|
40
41
|
RESULT_TYPE.each do |result_type|
|
|
41
42
|
SUFFIXES.each do |suffix|
|
|
42
43
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# end
|
|
46
|
-
def fetch_#{result_type}_#{suffix}(flag_key:, default_value:, evaluation_context: nil)
|
|
47
|
-
evaluation_details = fetch_details(type: :#{result_type}, flag_key:, default_value:, evaluation_context:)
|
|
44
|
+
def fetch_#{result_type}_#{suffix}(flag_key:, default_value:, evaluation_context: nil, hooks: [], hook_hints: nil)
|
|
45
|
+
evaluation_details = fetch_details(type: :#{result_type}, flag_key:, default_value:, evaluation_context:, invocation_hooks: hooks, hook_hints: hook_hints)
|
|
48
46
|
#{"evaluation_details.value" if suffix == :value}
|
|
49
47
|
end
|
|
50
48
|
RUBY
|
|
@@ -53,12 +51,54 @@ module OpenFeature
|
|
|
53
51
|
|
|
54
52
|
private
|
|
55
53
|
|
|
56
|
-
def fetch_details(type:, flag_key:, default_value:, evaluation_context: nil)
|
|
54
|
+
def fetch_details(type:, flag_key:, default_value:, evaluation_context: nil, invocation_hooks: [], hook_hints: nil)
|
|
57
55
|
validate_default_value_type(type, default_value)
|
|
58
56
|
|
|
59
|
-
built_context = EvaluationContextBuilder.new.call(
|
|
57
|
+
built_context = EvaluationContextBuilder.new.call(
|
|
58
|
+
api_context: OpenFeature::SDK.evaluation_context,
|
|
59
|
+
client_context: self.evaluation_context,
|
|
60
|
+
invocation_context: evaluation_context
|
|
61
|
+
)
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
# Assemble ordered hooks: API → Client → Invocation → Provider (spec 4.4.2)
|
|
64
|
+
provider_hooks = @provider.respond_to?(:hooks) ? Array(@provider.hooks) : []
|
|
65
|
+
ordered_hooks = [*OpenFeature::SDK.hooks, *@hooks, *invocation_hooks, *provider_hooks]
|
|
66
|
+
|
|
67
|
+
# Fast path: skip hook ceremony when no hooks are registered
|
|
68
|
+
if ordered_hooks.empty?
|
|
69
|
+
return evaluate_flag(type: type, flag_key: flag_key, default_value: default_value, evaluation_context: built_context)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
hook_context = Hooks::HookContext.new(
|
|
73
|
+
flag_key: flag_key,
|
|
74
|
+
flag_value_type: type,
|
|
75
|
+
default_value: default_value,
|
|
76
|
+
evaluation_context: built_context,
|
|
77
|
+
client_metadata: @metadata,
|
|
78
|
+
provider_metadata: @provider.respond_to?(:metadata) ? @provider.metadata : nil
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
hints = if hook_hints.is_a?(Hooks::Hints)
|
|
82
|
+
hook_hints
|
|
83
|
+
elsif hook_hints
|
|
84
|
+
Hooks::Hints.new(hook_hints)
|
|
85
|
+
else
|
|
86
|
+
EMPTY_HINTS
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
executor = Hooks::HookExecutor.new(logger: OpenFeature::SDK.configuration.logger)
|
|
90
|
+
executor.execute(ordered_hooks: ordered_hooks, hook_context: hook_context, hints: hints) do |hctx|
|
|
91
|
+
evaluate_flag(type: type, flag_key: flag_key, default_value: default_value, evaluation_context: hctx.evaluation_context)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def evaluate_flag(type:, flag_key:, default_value:, evaluation_context:)
|
|
96
|
+
resolution_details = @provider.send(
|
|
97
|
+
:"fetch_#{type}_value",
|
|
98
|
+
flag_key: flag_key,
|
|
99
|
+
default_value: default_value,
|
|
100
|
+
evaluation_context: evaluation_context
|
|
101
|
+
)
|
|
62
102
|
|
|
63
103
|
if TYPE_CLASS_MAP[type].none? { |klass| resolution_details.value.is_a?(klass) }
|
|
64
104
|
resolution_details.value = default_value
|
|
@@ -66,7 +106,7 @@ module OpenFeature
|
|
|
66
106
|
resolution_details.reason = Provider::Reason::ERROR
|
|
67
107
|
end
|
|
68
108
|
|
|
69
|
-
EvaluationDetails.new(flag_key
|
|
109
|
+
EvaluationDetails.new(flag_key: flag_key, resolution_details: resolution_details)
|
|
70
110
|
end
|
|
71
111
|
|
|
72
112
|
def validate_default_value_type(type, default_value)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenFeature
|
|
4
|
+
module SDK
|
|
5
|
+
module Hooks
|
|
6
|
+
# Module that hooks include. Provides default no-op implementations
|
|
7
|
+
# for all four lifecycle stages. A hook overrides the stages it cares about.
|
|
8
|
+
#
|
|
9
|
+
# Spec 4.3.1: Hooks MUST specify at least one stage.
|
|
10
|
+
module Hook
|
|
11
|
+
# Called before flag evaluation. May return an EvaluationContext
|
|
12
|
+
# that gets merged into the existing context (spec 4.3.2.1, 4.3.4, 4.3.5).
|
|
13
|
+
def before(hook_context:, hints:)
|
|
14
|
+
nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Called after successful flag evaluation (spec 4.3.3).
|
|
18
|
+
def after(hook_context:, evaluation_details:, hints:)
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Called when an error occurs during flag evaluation (spec 4.3.6).
|
|
23
|
+
def error(hook_context:, exception:, hints:)
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Called unconditionally after flag evaluation (spec 4.3.7).
|
|
28
|
+
def finally(hook_context:, evaluation_details:, hints:)
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenFeature
|
|
4
|
+
module SDK
|
|
5
|
+
module Hooks
|
|
6
|
+
# Provides context to hook stages during flag evaluation.
|
|
7
|
+
#
|
|
8
|
+
# Per spec 4.1.1-4.1.5:
|
|
9
|
+
# - flag_key, flag_value_type, default_value are immutable (4.1.3)
|
|
10
|
+
# - client_metadata, provider_metadata are optional (4.1.2)
|
|
11
|
+
# - evaluation_context is mutable (for before hooks to modify, 4.1.4.1)
|
|
12
|
+
class HookContext
|
|
13
|
+
attr_reader :flag_key, :flag_value_type, :default_value,
|
|
14
|
+
:client_metadata, :provider_metadata
|
|
15
|
+
attr_accessor :evaluation_context
|
|
16
|
+
|
|
17
|
+
def initialize(flag_key:, flag_value_type:, default_value:, evaluation_context:,
|
|
18
|
+
client_metadata: nil, provider_metadata: nil)
|
|
19
|
+
@flag_key = flag_key.freeze
|
|
20
|
+
@flag_value_type = flag_value_type.freeze
|
|
21
|
+
@default_value = default_value.freeze
|
|
22
|
+
@evaluation_context = evaluation_context
|
|
23
|
+
@client_metadata = client_metadata
|
|
24
|
+
@provider_metadata = provider_metadata
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenFeature
|
|
4
|
+
module SDK
|
|
5
|
+
module Hooks
|
|
6
|
+
# Orchestrates the full hook lifecycle for flag evaluation.
|
|
7
|
+
#
|
|
8
|
+
# Hook execution order (spec 4.4.2):
|
|
9
|
+
# Before: API → Client → Invocation → Provider
|
|
10
|
+
# After/Error/Finally: Provider → Invocation → Client → API (reverse)
|
|
11
|
+
#
|
|
12
|
+
# Error handling (spec 4.4.3-4.4.7):
|
|
13
|
+
# - Before/after hook error → stop remaining hooks, run error hooks, return default
|
|
14
|
+
# - Error hook error → log, continue remaining error hooks
|
|
15
|
+
# - Finally hook error → log, continue remaining finally hooks
|
|
16
|
+
class HookExecutor
|
|
17
|
+
def initialize(logger: nil)
|
|
18
|
+
@logger = logger
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Executes the full hook lifecycle around the flag evaluation block.
|
|
22
|
+
#
|
|
23
|
+
# @param ordered_hooks [Array] hooks in before-order (API, Client, Invocation, Provider)
|
|
24
|
+
# @param hook_context [HookContext] the hook context
|
|
25
|
+
# @param hints [Hints] hook hints
|
|
26
|
+
# @param evaluate_block [Proc] the flag evaluation to wrap
|
|
27
|
+
# @return [EvaluationDetails] the evaluation result
|
|
28
|
+
def execute(ordered_hooks:, hook_context:, hints:, &evaluate_block)
|
|
29
|
+
evaluation_details = nil
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
run_before_hooks(ordered_hooks, hook_context, hints)
|
|
33
|
+
evaluation_details = evaluate_block.call(hook_context)
|
|
34
|
+
run_after_hooks(ordered_hooks, hook_context, evaluation_details, hints)
|
|
35
|
+
rescue => e
|
|
36
|
+
run_error_hooks(ordered_hooks, hook_context, e, hints)
|
|
37
|
+
|
|
38
|
+
evaluation_details = EvaluationDetails.new(
|
|
39
|
+
flag_key: hook_context.flag_key,
|
|
40
|
+
resolution_details: Provider::ResolutionDetails.new(
|
|
41
|
+
value: hook_context.default_value,
|
|
42
|
+
error_code: Provider::ErrorCode::GENERAL,
|
|
43
|
+
reason: Provider::Reason::ERROR,
|
|
44
|
+
error_message: e.message
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
ensure
|
|
48
|
+
run_finally_hooks(ordered_hooks, hook_context, evaluation_details, hints)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
evaluation_details
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# Spec 4.4.2: Before hooks run in order: API → Client → Invocation → Provider
|
|
57
|
+
# Spec 4.3.4/4.3.5: If a before hook returns an EvaluationContext, it is merged
|
|
58
|
+
# into the existing context for subsequent hooks and evaluation.
|
|
59
|
+
def run_before_hooks(hooks, hook_context, hints)
|
|
60
|
+
hooks.each do |hook|
|
|
61
|
+
next unless hook.respond_to?(:before)
|
|
62
|
+
result = hook.before(hook_context: hook_context, hints: hints)
|
|
63
|
+
if result.is_a?(EvaluationContext)
|
|
64
|
+
existing = hook_context.evaluation_context
|
|
65
|
+
hook_context.evaluation_context = existing ? existing.merge(result) : result
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Spec 4.4.2: After hooks run in reverse order: Provider → Invocation → Client → API
|
|
71
|
+
def run_after_hooks(hooks, hook_context, evaluation_details, hints)
|
|
72
|
+
hooks.reverse_each do |hook|
|
|
73
|
+
next unless hook.respond_to?(:after)
|
|
74
|
+
hook.after(hook_context: hook_context, evaluation_details: evaluation_details, hints: hints)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Spec 4.4.4: Error hooks run in reverse order.
|
|
79
|
+
# If an error hook itself errors, log and continue remaining error hooks.
|
|
80
|
+
def run_error_hooks(hooks, hook_context, exception, hints)
|
|
81
|
+
hooks.reverse_each do |hook|
|
|
82
|
+
next unless hook.respond_to?(:error)
|
|
83
|
+
hook.error(hook_context: hook_context, exception: exception, hints: hints)
|
|
84
|
+
rescue => e
|
|
85
|
+
@logger&.error("Error hook #{hook.class.name} failed: #{e.message}")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Spec 4.4.3: Finally hooks run in reverse order unconditionally.
|
|
90
|
+
# If a finally hook errors, log and continue remaining finally hooks.
|
|
91
|
+
def run_finally_hooks(hooks, hook_context, evaluation_details, hints)
|
|
92
|
+
hooks.reverse_each do |hook|
|
|
93
|
+
next unless hook.respond_to?(:finally)
|
|
94
|
+
hook.finally(hook_context: hook_context, evaluation_details: evaluation_details, hints: hints)
|
|
95
|
+
rescue => e
|
|
96
|
+
@logger&.error("Finally hook #{hook.class.name} failed: #{e.message}")
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openfeature-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenFeature Authors
|
|
@@ -150,6 +150,7 @@ files:
|
|
|
150
150
|
- ".standard.yml"
|
|
151
151
|
- ".tool-versions"
|
|
152
152
|
- CHANGELOG.md
|
|
153
|
+
- CLAUDE.md
|
|
153
154
|
- CODEOWNERS
|
|
154
155
|
- CODE_OF_CONDUCT.md
|
|
155
156
|
- CONTRIBUTING.md
|
|
@@ -167,7 +168,11 @@ files:
|
|
|
167
168
|
- lib/open_feature/sdk/evaluation_context_builder.rb
|
|
168
169
|
- lib/open_feature/sdk/evaluation_details.rb
|
|
169
170
|
- lib/open_feature/sdk/event_dispatcher.rb
|
|
171
|
+
- lib/open_feature/sdk/hooks.rb
|
|
170
172
|
- lib/open_feature/sdk/hooks/hints.rb
|
|
173
|
+
- lib/open_feature/sdk/hooks/hook.rb
|
|
174
|
+
- lib/open_feature/sdk/hooks/hook_context.rb
|
|
175
|
+
- lib/open_feature/sdk/hooks/hook_executor.rb
|
|
171
176
|
- lib/open_feature/sdk/provider.rb
|
|
172
177
|
- lib/open_feature/sdk/provider/error_code.rb
|
|
173
178
|
- lib/open_feature/sdk/provider/event_emitter.rb
|