featurehub-sdk 1.2.3 → 2.0.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.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/CLAUDE.md +85 -0
  3. data/.rubocop.yml +4 -2
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +17 -0
  6. data/Gemfile +3 -3
  7. data/Gemfile.lock +136 -63
  8. data/LICENSE +21 -0
  9. data/README.md +422 -0
  10. data/examples/rails_example/.env.example +13 -0
  11. data/examples/rails_example/.gitattributes +7 -0
  12. data/examples/rails_example/.gitignore +103 -0
  13. data/examples/rails_example/.ruby-version +1 -0
  14. data/examples/rails_example/Dockerfile +12 -0
  15. data/examples/rails_example/Gemfile +80 -0
  16. data/examples/rails_example/Gemfile.lock +283 -0
  17. data/examples/rails_example/README.md +36 -0
  18. data/examples/rails_example/Rakefile +8 -0
  19. data/examples/rails_example/app/assets/config/manifest.js +4 -0
  20. data/examples/rails_example/app/assets/images/.keep +0 -0
  21. data/examples/rails_example/app/assets/stylesheets/application.css +15 -0
  22. data/examples/rails_example/app/channels/application_cable/channel.rb +6 -0
  23. data/examples/rails_example/app/channels/application_cable/connection.rb +6 -0
  24. data/examples/rails_example/app/controllers/application_controller.rb +4 -0
  25. data/examples/rails_example/app/controllers/concerns/.keep +0 -0
  26. data/examples/rails_example/app/controllers/home_controller.rb +12 -0
  27. data/examples/rails_example/app/helpers/application_helper.rb +4 -0
  28. data/examples/rails_example/app/helpers/home_helper.rb +4 -0
  29. data/examples/rails_example/app/javascript/application.js +3 -0
  30. data/examples/rails_example/app/javascript/controllers/application.js +9 -0
  31. data/examples/rails_example/app/javascript/controllers/hello_controller.js +7 -0
  32. data/examples/rails_example/app/javascript/controllers/index.js +11 -0
  33. data/examples/rails_example/app/jobs/application_job.rb +9 -0
  34. data/examples/rails_example/app/mailers/application_mailer.rb +6 -0
  35. data/examples/rails_example/app/models/application_record.rb +5 -0
  36. data/examples/rails_example/app/models/concerns/.keep +0 -0
  37. data/examples/rails_example/app/views/home/index.html.erb +6 -0
  38. data/examples/rails_example/app/views/layouts/application.html.erb +16 -0
  39. data/examples/rails_example/app/views/layouts/mailer.html.erb +13 -0
  40. data/examples/rails_example/app/views/layouts/mailer.text.erb +1 -0
  41. data/examples/rails_example/bin/bundle +118 -0
  42. data/examples/rails_example/bin/importmap +5 -0
  43. data/examples/rails_example/bin/rails +6 -0
  44. data/examples/rails_example/bin/rake +6 -0
  45. data/examples/rails_example/bin/setup +35 -0
  46. data/examples/rails_example/config/application.rb +24 -0
  47. data/examples/rails_example/config/boot.rb +6 -0
  48. data/examples/rails_example/config/cable.yml +10 -0
  49. data/examples/rails_example/config/credentials.yml.enc +1 -0
  50. data/examples/rails_example/config/database.yml +25 -0
  51. data/examples/rails_example/config/environment.rb +7 -0
  52. data/examples/rails_example/config/environments/development.rb +72 -0
  53. data/examples/rails_example/config/environments/production.rb +95 -0
  54. data/examples/rails_example/config/environments/test.rb +62 -0
  55. data/examples/rails_example/config/importmap.rb +9 -0
  56. data/examples/rails_example/config/initializers/assets.rb +14 -0
  57. data/examples/rails_example/config/initializers/content_security_policy.rb +27 -0
  58. data/examples/rails_example/config/initializers/featurehub.rb +8 -0
  59. data/examples/rails_example/config/initializers/filter_parameter_logging.rb +10 -0
  60. data/examples/rails_example/config/initializers/inflections.rb +18 -0
  61. data/examples/rails_example/config/initializers/permissions_policy.rb +13 -0
  62. data/examples/rails_example/config/locales/en.yml +33 -0
  63. data/examples/rails_example/config/puma.rb +57 -0
  64. data/examples/rails_example/config/routes.rb +8 -0
  65. data/examples/rails_example/config/storage.yml +34 -0
  66. data/examples/rails_example/config.ru +8 -0
  67. data/examples/rails_example/db/seeds.rb +9 -0
  68. data/examples/rails_example/lib/assets/.keep +0 -0
  69. data/examples/rails_example/lib/tasks/.keep +0 -0
  70. data/examples/rails_example/log/.keep +0 -0
  71. data/examples/rails_example/public/404.html +67 -0
  72. data/examples/rails_example/public/422.html +67 -0
  73. data/examples/rails_example/public/500.html +66 -0
  74. data/examples/rails_example/public/apple-touch-icon-precomposed.png +0 -0
  75. data/examples/rails_example/public/apple-touch-icon.png +0 -0
  76. data/examples/rails_example/public/favicon.ico +0 -0
  77. data/examples/rails_example/public/robots.txt +1 -0
  78. data/examples/rails_example/storage/.keep +0 -0
  79. data/examples/rails_example/test/application_system_test_case.rb +7 -0
  80. data/examples/rails_example/test/channels/application_cable/connection_test.rb +15 -0
  81. data/examples/rails_example/test/controllers/.keep +0 -0
  82. data/examples/rails_example/test/controllers/home_controller_test.rb +9 -0
  83. data/examples/rails_example/test/fixtures/files/.keep +0 -0
  84. data/examples/rails_example/test/helpers/.keep +0 -0
  85. data/examples/rails_example/test/integration/.keep +0 -0
  86. data/examples/rails_example/test/mailers/.keep +0 -0
  87. data/examples/rails_example/test/models/.keep +0 -0
  88. data/examples/rails_example/test/system/.keep +0 -0
  89. data/examples/rails_example/test/test_helper.rb +17 -0
  90. data/examples/rails_example/tmp/.keep +0 -0
  91. data/examples/rails_example/tmp/pids/.keep +0 -0
  92. data/examples/rails_example/tmp/storage/.keep +0 -0
  93. data/examples/rails_example/vendor/.keep +0 -0
  94. data/examples/rails_example/vendor/javascript/.keep +0 -0
  95. data/examples/sinatra/.dockerignore +7 -0
  96. data/examples/sinatra/.gitignore +3 -0
  97. data/examples/sinatra/.ruby-version +1 -0
  98. data/examples/sinatra/Dockerfile +31 -0
  99. data/examples/sinatra/Gemfile +17 -0
  100. data/examples/sinatra/Gemfile.lock +94 -0
  101. data/examples/sinatra/README.adoc +10 -0
  102. data/examples/sinatra/app/application.rb +153 -0
  103. data/examples/sinatra/build.sh +2 -0
  104. data/examples/sinatra/conf/nginx.conf +57 -0
  105. data/examples/sinatra/conf/nsswitch.conf +21 -0
  106. data/examples/sinatra/config.ru +17 -0
  107. data/examples/sinatra/docker-compose.yaml +24 -0
  108. data/examples/sinatra/docker_start.sh +3 -0
  109. data/examples/sinatra/feature-flags.yaml +6 -0
  110. data/examples/sinatra/sinatra.iml +43 -0
  111. data/examples/sinatra/start.sh +5 -0
  112. data/examples/sinatra/thin.ru +9 -0
  113. data/featurehub-ruby-sdk.iml +9 -0
  114. data/featurehub-sdk.gemspec +45 -0
  115. data/lib/feature_hub/sdk/context.rb +28 -7
  116. data/lib/feature_hub/sdk/feature_hub_config.rb +68 -14
  117. data/lib/feature_hub/sdk/feature_repository.rb +52 -13
  118. data/lib/feature_hub/sdk/{feature_state.rb → feature_state_holder.rb} +13 -9
  119. data/lib/feature_hub/sdk/impl/rollout_holders.rb +3 -3
  120. data/lib/feature_hub/sdk/interceptors.rb +10 -6
  121. data/lib/feature_hub/sdk/internal_feature_repository.rb +7 -3
  122. data/lib/feature_hub/sdk/local_yaml_interceptor.rb +99 -0
  123. data/lib/feature_hub/sdk/local_yaml_store.rb +71 -0
  124. data/lib/feature_hub/sdk/poll_edge_service.rb +6 -11
  125. data/lib/feature_hub/sdk/raw_update_feature_listener.rb +19 -0
  126. data/lib/feature_hub/sdk/redis_session_store.rb +130 -0
  127. data/lib/feature_hub/sdk/strategy_attributes.rb +7 -0
  128. data/lib/feature_hub/sdk/streaming_edge_service.rb +5 -7
  129. data/lib/feature_hub/sdk/version.rb +2 -2
  130. data/lib/featurehub-sdk.rb +5 -1
  131. data/sig/feature_hub/featurehub.rbs +127 -28
  132. metadata +137 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f51f3ee6ae46d203b9a0654254cf76249ad1a52efb1a0b7c509c135ecd778603
4
- data.tar.gz: 255368f461db8af544c667c9d167a47fb580eaa0875111462fd00fd6cec1649e
3
+ metadata.gz: c3c5127a58f5d1a4c63242919d593399ee0e097dcbd54239584d3620eb00f5a9
4
+ data.tar.gz: 4de3a2a249d35c6dfd52249a6b42171cd27e9aac8ed4c95f2c0efdaa9947663b
5
5
  SHA512:
6
- metadata.gz: 7d1ed64f709b26486f98a700fb47f7fb5f3e122487ad0bd94953f809564b8b917e3bde29103e743d7356a2329b33a5da6a9e3b3affba77d0d04f50b90c3bad51
7
- data.tar.gz: c095eaa5e9674fc1187944384a74527d19624c1429531ac5162234306542c95fbca7a75988d83bb068fcb10f366ef718ee52dac48dbc2a275b1e3287ce2f7a9c
6
+ metadata.gz: 9a41c73c154804782a9795337e33de707a482f2fedb41337783222f561ce1eccae41dfca59ad393a36d9fa8d214f8f54778b016092de3c04e4c9d83c9da44a95
7
+ data.tar.gz: aac1dfb0a3d61d77f4046b9710f146ce0f2d0562a7c324e8e03c43c7276c5eb555322f9b3e49543aeb9958b1b4328b15dc003c29da682160a3b29ac782c830af
data/.claude/CLAUDE.md ADDED
@@ -0,0 +1,85 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ bundle install # Install dependencies
9
+ bundle exec rake # Run tests + linting (default)
10
+ bundle exec rspec # Run tests only
11
+ bundle exec rubocop # Lint only
12
+
13
+ # Run a single test file
14
+ bundle exec rspec spec/feature_hub/sdk/feature_hub_config_spec.rb
15
+
16
+ # Run a specific test by line number
17
+ bundle exec rspec spec/feature_hub/sdk/feature_hub_config_spec.rb:42
18
+ ```
19
+
20
+ ## Architecture
21
+
22
+ This is the FeatureHub Ruby SDK (gem: `featurehub-sdk`, version 2.0.0), targeting Ruby >= 3.2. All code lives under `lib/feature_hub/sdk/` and is namespaced as `FeatureHub::Sdk`.
23
+
24
+ ### Core Data Flow
25
+
26
+ ```
27
+ FeatureHubConfig.init(url, api_key)
28
+ → creates EdgeService (streaming SSE or polling HTTP)
29
+ → edge service receives feature JSON from FeatureHub server
30
+ → FeatureHubRepository stores feature states
31
+
32
+ config.new_context().user_key("id").build()
33
+ → ClientEvalContext: polls edge, evaluates strategies locally
34
+ → ServerEvalContext: sends context as HTTP header, server evaluates
35
+
36
+ context.feature("MY_FLAG").boolean
37
+ → FeatureStateHolder checks interceptors, then calls repository.apply(strategies, ctx)
38
+ → ApplyFeature matches rollout strategies, returns Applied(value)
39
+ ```
40
+
41
+ ### Key Classes
42
+
43
+ - **FeatureHubConfig** ([feature_hub_config.rb](lib/feature_hub/sdk/feature_hub_config.rb)): Entry point. Detects client vs server evaluation by checking for `*` in the API key. Manages edge service lifecycle. Call `new_context()` to get a context builder.
44
+
45
+ - **FeatureHubRepository** ([feature_repository.rb](lib/feature_hub/sdk/feature_repository.rb)): Stores features as a hash (symbol keys → `FeatureStateHolder`). Notifies listeners on changes (`:features`, `:feature`, `:delete_feature`, `:failed`). Checks interceptors before applying strategies. Tracks readiness via `@ready`.
46
+
47
+ - **FeatureStateHolder** ([feature_state_holder.rb](lib/feature_hub/sdk/feature_state_holder.rb)): Wraps feature JSON (`key`, `id`, `type`, `value`, `version`, `l` (locked), `strategies`). Provides typed accessors: `.flag`, `.string`, `.number`, `.raw_json`, `.boolean`. Supports `with_context(ctx)` for strategy evaluation.
48
+
49
+ - **Context classes** ([context.rb](lib/feature_hub/sdk/context.rb)): Fluent builder pattern — `context.user_key("x").platform("ios").country("gb").build()`. Attributes stored as `symbol → [array]`. Two subclasses: `ClientEvalFeatureContext` (local strategy eval) and `ServerEvalFeatureContext` (server-side eval, sends `x-featurehub` header).
50
+
51
+ - **Edge services**: `StreamingEdgeService` ([streaming_edge_service.rb](lib/feature_hub/sdk/streaming_edge_service.rb)) uses SSE via `ld-eventsource`. `PollingEdgeService` ([poll_edge_service.rb](lib/feature_hub/sdk/poll_edge_service.rb)) uses Faraday with `Concurrent::TimerTask`, supports ETags. Call `force_new_edge_service()` after process fork (Puma/Passenger/Unicorn).
52
+
53
+ - **ApplyFeature** ([impl/apply_features.rb](lib/feature_hub/sdk/impl/apply_features.rb)): Client-side strategy evaluator. Iterates rollout strategies, calculates percentage allocation via Murmur3 hash of `percentage_key + feature_id`, matches attribute conditions via `MatcherRegistry`. Returns `Applied(matched:, value:)`.
54
+
55
+ - **EnvironmentInterceptor** ([interceptors.rb](lib/feature_hub/sdk/interceptors.rb)): Override features at runtime via `FEATUREHUB_OVERRIDE_FEATURES=true` + `FEATUREHUB_<FEATURE_NAME>=<value>` env vars.
56
+
57
+ ### Client vs Server Evaluation
58
+
59
+ - **Client-evaluated** API key contains `*` (e.g., `abc*def`): full strategy data sent to SDK, evaluated locally by `ApplyFeature`.
60
+ - **Server-evaluated** API key has no `*`: context attributes sent as `x-featurehub` HTTP header, server evaluates and returns resolved values.
61
+
62
+ ### Strategy Attribute Matchers
63
+
64
+ `MatcherRegistry` dispatches to typed matchers based on `field_type`: `BOOLEAN`, `STRING`/`DATE`/`DATE_TIME` (via `StringMatcher`), `NUMBER`, `SEMANTIC_VERSION` (uses `sem_version` gem), `IP_ADDRESS` (CIDR support). All conditions in a strategy must match for the strategy to apply.
65
+
66
+ ## RBS Type Signatures
67
+
68
+ Type definitions live in [sig/feature_hub/featurehub.rbs](sig/feature_hub/featurehub.rbs). Key signatures to be aware of:
69
+
70
+ - **Feature value type**: `[bool? | String? | Float?]` — the union type used throughout for feature values (`Applied#value`, `FeatureStateHolder#value`, `RolloutStrategy#value`, `InterceptorValue`)
71
+ - **`FeatureStateHolder#initialize`** takes `key:`, `repo:`, `feature_state:`, `parent_state:`, and `ctx:` — the `parent_state` and `ctx` support the `with_context` pattern for context-scoped evaluation
72
+ - **`InternalFeatureRepository`** is the abstract interface that `FeatureHubRepository` implements; `FeatureStateHolder` and context classes depend on this interface, not the concrete class
73
+ - **`ClientContext#build`** returns `ClientContext` (async); **`build_sync`** also returns `ClientContext` (blocking)
74
+ - **`FeatureHubConfig#repository`** takes an optional `InternalFeatureRepository?` and returns one — it acts as both getter and setter
75
+ - **`RolloutStrategyAttribute`**: `values` is `Array[[bool? | String? | Float?]]`; use `float_values` / `str_values` for typed access
76
+ - **`RolloutStrategyCondition`**: predicate methods only (e.g., `equals?`, `regex?`, `includes?`) — no raw string comparison against condition type strings
77
+
78
+ ## Conventions
79
+
80
+ - `# frozen_string_literal: true` on every file
81
+ - Double-quoted strings (RuboCop enforced)
82
+ - Feature keys stored/looked up as symbols internally
83
+ - RuboCop: max line length 120, metrics cops disabled, documentation disabled
84
+ - Tests mirror lib structure: `spec/feature_hub/sdk/**/*_spec.rb`
85
+ - Use `instance_double` for mocking, `aggregate_failures` for multiple assertions
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.7
2
+ TargetRubyVersion: 3.2
3
3
 
4
4
  Style/StringLiterals:
5
5
  Enabled: true
@@ -35,7 +35,7 @@ Metrics/CyclomaticComplexity:
35
35
  Naming/FileName:
36
36
  Enabled: false
37
37
 
38
- Gemspec/DateAssignment: # new in 1.10
38
+ Gemspec/DeprecatedAttributeAssignment:
39
39
  Enabled: true
40
40
  Gemspec/DeprecatedAttributeAssignment: # new in 1.30
41
41
  Enabled: true
@@ -101,6 +101,8 @@ Style/ArgumentsForwarding: # new in 1.1
101
101
  Enabled: true
102
102
  Style/CollectionCompact: # new in 1.2
103
103
  Enabled: true
104
+ Style/Documentation:
105
+ Enabled: false
104
106
  Style/DocumentDynamicEvalDefinition: # new in 1.1
105
107
  Enabled: true
106
108
  Style/EndlessMethod: # new in 1.8
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0.6
1
+ 3.3.10
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## [2.0.0] - 2026-03-22
2
+
3
+ - Refactor FeatureState to FeatureStateHolder to be consistent with other SDKs
4
+ - Add FeatureValueType to reduce duplication
5
+ - Add local YAML file interceptor with an optional timer to watch for changes
6
+ - Add `RawUpdateFeatureListener` base class so custom listeners can react to raw edge updates (including update source tracking)
7
+ - Add `LocalYamlStore`: load features from a local YAML file without an Edge server, as an alternative to the value interceptor
8
+ - Add `RedisSessionStore`: persist features in Redis so they survive process restarts and are shared across processes (client-evaluated only)
9
+ - Support punch-through context evaluation for external stores so per-request context attributes are applied even when features come from Redis or YAML
10
+ - Add `value` accessor to `FeatureStateHolder` as a convenience shortcut alongside the typed accessors
11
+ - Edge services now explicitly close the repository on shutdown
12
+
13
+ ## [1.3.0] - 2026-01-11
14
+
15
+ - update gem dependencies
16
+ - bump minimum ruby version to 3.2
17
+
1
18
  ## [1.2.3] - 2024-01-12
2
19
 
3
20
  - fix for Interceptor contributed by Lukas
data/Gemfile CHANGED
@@ -13,12 +13,12 @@ gem "rubocop", "~> 1.21"
13
13
 
14
14
  gem "simplecov", "~> 0.21"
15
15
 
16
- gem "concurrent-ruby", "~> 1.1"
16
+ gem "concurrent-ruby", "~> 1.3"
17
17
 
18
18
  gem "faraday", "~> 2"
19
19
 
20
- gem "murmurhash3", "~> 0.1.6"
20
+ gem "murmurhash3", "~> 0.1.7"
21
21
 
22
22
  gem "sem_version", "~> 2.0.0"
23
23
 
24
- gem "ld-eventsource", "~> 2.2.0"
24
+ gem "ld-eventsource", "~> 2.5.1"
data/Gemfile.lock CHANGED
@@ -1,107 +1,180 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- featurehub-sdk (1.2.3)
5
- concurrent-ruby (~> 1.1)
4
+ featurehub-sdk (2.0.0)
5
+ concurrent-ruby (~> 1.3)
6
6
  faraday (~> 2)
7
- ld-eventsource (~> 2.2.0)
8
- murmurhash3 (~> 0.1.6)
7
+ ld-eventsource (~> 2.5.1)
8
+ murmurhash3 (~> 0.1.7)
9
9
  sem_version (~> 2.0.0)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- addressable (2.8.0)
15
- public_suffix (>= 2.0.2, < 5.0)
16
- ast (2.4.2)
17
- concurrent-ruby (1.1.10)
18
- diff-lcs (1.5.0)
19
- docile (1.4.0)
20
- domain_name (0.5.20190701)
21
- unf (>= 0.0.5, < 1.0.0)
22
- faraday (2.3.0)
23
- faraday-net_http (~> 2.0)
24
- ruby2_keywords (>= 0.0.4)
25
- faraday-net_http (2.0.3)
26
- ffi (1.15.5)
27
- ffi-compiler (1.0.1)
28
- ffi (>= 1.0.0)
14
+ addressable (2.8.8)
15
+ public_suffix (>= 2.0.2, < 8.0)
16
+ ast (2.4.3)
17
+ concurrent-ruby (1.3.6)
18
+ connection_pool (3.0.2)
19
+ diff-lcs (1.6.2)
20
+ docile (1.4.1)
21
+ domain_name (0.6.20240107)
22
+ faraday (2.14.0)
23
+ faraday-net_http (>= 2.0, < 3.5)
24
+ json
25
+ logger
26
+ faraday-net_http (3.4.2)
27
+ net-http (~> 0.5)
28
+ ffi (1.17.3-arm64-darwin)
29
+ ffi (1.17.3-x86_64-darwin)
30
+ ffi (1.17.3-x86_64-linux-gnu)
31
+ ffi-compiler (1.3.2)
32
+ ffi (>= 1.15.5)
29
33
  rake
30
- http (5.0.4)
34
+ http (5.3.1)
31
35
  addressable (~> 2.8)
32
36
  http-cookie (~> 1.0)
33
37
  http-form_data (~> 2.2)
34
- llhttp-ffi (~> 0.4.0)
35
- http-cookie (1.0.5)
38
+ llhttp-ffi (~> 0.5.0)
39
+ http-cookie (1.1.0)
36
40
  domain_name (~> 0.5)
37
41
  http-form_data (2.3.0)
38
- ld-eventsource (2.2.0)
42
+ json (2.19.2)
43
+ language_server-protocol (3.17.0.5)
44
+ ld-eventsource (2.5.1)
39
45
  concurrent-ruby (~> 1.0)
40
46
  http (>= 4.4.1, < 6.0.0)
41
- llhttp-ffi (0.4.0)
47
+ lint_roller (1.1.0)
48
+ llhttp-ffi (0.5.1)
42
49
  ffi-compiler (~> 1.0)
43
50
  rake (~> 13.0)
44
- murmurhash3 (0.1.6)
45
- parallel (1.22.1)
46
- parser (3.1.2.0)
51
+ logger (1.7.0)
52
+ murmurhash3 (0.1.7)
53
+ net-http (0.9.1)
54
+ uri (>= 0.11.1)
55
+ parallel (1.27.0)
56
+ parser (3.3.10.0)
47
57
  ast (~> 2.4.1)
48
- public_suffix (4.0.7)
58
+ racc
59
+ prism (1.6.0)
60
+ public_suffix (6.0.2)
61
+ racc (1.8.1)
49
62
  rainbow (3.1.1)
50
- rake (13.0.6)
51
- regexp_parser (2.5.0)
52
- rexml (3.2.5)
53
- rspec (3.11.0)
54
- rspec-core (~> 3.11.0)
55
- rspec-expectations (~> 3.11.0)
56
- rspec-mocks (~> 3.11.0)
57
- rspec-core (3.11.0)
58
- rspec-support (~> 3.11.0)
59
- rspec-expectations (3.11.0)
63
+ rake (13.3.1)
64
+ redis (5.4.1)
65
+ redis-client (>= 0.22.0)
66
+ redis-client (0.28.0)
67
+ connection_pool
68
+ regexp_parser (2.11.3)
69
+ rspec (3.13.2)
70
+ rspec-core (~> 3.13.0)
71
+ rspec-expectations (~> 3.13.0)
72
+ rspec-mocks (~> 3.13.0)
73
+ rspec-core (3.13.6)
74
+ rspec-support (~> 3.13.0)
75
+ rspec-expectations (3.13.5)
60
76
  diff-lcs (>= 1.2.0, < 2.0)
61
- rspec-support (~> 3.11.0)
62
- rspec-mocks (3.11.1)
77
+ rspec-support (~> 3.13.0)
78
+ rspec-mocks (3.13.7)
63
79
  diff-lcs (>= 1.2.0, < 2.0)
64
- rspec-support (~> 3.11.0)
65
- rspec-support (3.11.0)
66
- rubocop (1.30.1)
80
+ rspec-support (~> 3.13.0)
81
+ rspec-support (3.13.6)
82
+ rubocop (1.82.0)
83
+ json (~> 2.3)
84
+ language_server-protocol (~> 3.17.0.2)
85
+ lint_roller (~> 1.1.0)
67
86
  parallel (~> 1.10)
68
- parser (>= 3.1.0.0)
87
+ parser (>= 3.3.0.2)
69
88
  rainbow (>= 2.2.2, < 4.0)
70
- regexp_parser (>= 1.8, < 3.0)
71
- rexml (>= 3.2.5, < 4.0)
72
- rubocop-ast (>= 1.18.0, < 2.0)
89
+ regexp_parser (>= 2.9.3, < 3.0)
90
+ rubocop-ast (>= 1.48.0, < 2.0)
73
91
  ruby-progressbar (~> 1.7)
74
- unicode-display_width (>= 1.4.0, < 3.0)
75
- rubocop-ast (1.18.0)
76
- parser (>= 3.1.1.0)
77
- ruby-progressbar (1.11.0)
78
- ruby2_keywords (0.0.5)
92
+ unicode-display_width (>= 2.4.0, < 4.0)
93
+ rubocop-ast (1.48.0)
94
+ parser (>= 3.3.7.2)
95
+ prism (~> 1.4)
96
+ ruby-progressbar (1.13.0)
79
97
  sem_version (2.0.1)
80
- simplecov (0.21.2)
98
+ simplecov (0.22.0)
81
99
  docile (~> 1.1)
82
100
  simplecov-html (~> 0.11)
83
101
  simplecov_json_formatter (~> 0.1)
84
- simplecov-html (0.12.3)
102
+ simplecov-html (0.13.2)
85
103
  simplecov_json_formatter (0.1.4)
86
- unf (0.1.4)
87
- unf_ext
88
- unf_ext (0.0.8.2)
89
- unicode-display_width (2.1.0)
104
+ unicode-display_width (3.2.0)
105
+ unicode-emoji (~> 4.1)
106
+ unicode-emoji (4.2.0)
107
+ uri (1.1.1)
90
108
 
91
109
  PLATFORMS
92
- ruby
110
+ arm64-darwin
111
+ x86_64-darwin-24
112
+ x86_64-linux
93
113
 
94
114
  DEPENDENCIES
95
- concurrent-ruby (~> 1.1)
115
+ concurrent-ruby (~> 1.3)
96
116
  faraday (~> 2)
97
117
  featurehub-sdk!
98
- ld-eventsource (~> 2.2.0)
99
- murmurhash3 (~> 0.1.6)
118
+ ld-eventsource (~> 2.5.1)
119
+ murmurhash3 (~> 0.1.7)
100
120
  rake (~> 13.0)
121
+ redis (~> 5)
101
122
  rspec (~> 3.0)
102
123
  rubocop (~> 1.21)
103
124
  sem_version (~> 2.0.0)
104
125
  simplecov (~> 0.21)
105
126
 
127
+ CHECKSUMS
128
+ addressable (2.8.8) sha256=7c13b8f9536cf6364c03b9d417c19986019e28f7c00ac8132da4eb0fe393b057
129
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
130
+ concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
131
+ connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
132
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
133
+ docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
134
+ domain_name (0.6.20240107) sha256=5f693b2215708476517479bf2b3802e49068ad82167bcd2286f899536a17d933
135
+ faraday (2.14.0) sha256=8699cfe5d97e55268f2596f9a9d5a43736808a943714e3d9a53e6110593941cd
136
+ faraday-net_http (3.4.2) sha256=f147758260d3526939bf57ecf911682f94926a3666502e24c69992765875906c
137
+ featurehub-sdk (2.0.0)
138
+ ffi (1.17.3-arm64-darwin) sha256=0c690555d4cee17a7f07c04d59df39b2fba74ec440b19da1f685c6579bb0717f
139
+ ffi (1.17.3-x86_64-darwin) sha256=1f211811eb5cfaa25998322cdd92ab104bfbd26d1c4c08471599c511f2c00bb5
140
+ ffi (1.17.3-x86_64-linux-gnu) sha256=3746b01f677aae7b16dc1acb7cb3cc17b3e35bdae7676a3f568153fb0e2c887f
141
+ ffi-compiler (1.3.2) sha256=a94f3d81d12caf5c5d4ecf13980a70d0aeaa72268f3b9cc13358bcc6509184a0
142
+ http (5.3.1) sha256=c50802d8e9be3926cb84ac3b36d1a31fbbac383bc4cbecdce9053cb604231d7d
143
+ http-cookie (1.1.0) sha256=38a5e60d1527eebc396831b8c4b9455440509881219273a6c99943d29eadbb19
144
+ http-form_data (2.3.0) sha256=cc4eeb1361d9876821e31d7b1cf0b68f1cf874b201d27903480479d86448a5f3
145
+ json (2.19.2) sha256=e7e1bd318b2c37c4ceee2444841c86539bc462e81f40d134cf97826cb14e83cf
146
+ language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
147
+ ld-eventsource (2.5.1) sha256=19cb44b7d3f91f76b7401a1b74293b32c723389b2d6f9d81ecb803c628ac1b25
148
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
149
+ llhttp-ffi (0.5.1) sha256=9a25a7fc19311f691a78c9c0ac0fbf4675adbd0cca74310228fdf841018fa7bc
150
+ logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
151
+ murmurhash3 (0.1.7) sha256=370a2ce2e9ab0711e51554e530b5f63956927a6554a296855f42a1a4a5ed0936
152
+ net-http (0.9.1) sha256=25ba0b67c63e89df626ed8fac771d0ad24ad151a858af2cc8e6a716ca4336996
153
+ parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
154
+ parser (3.3.10.0) sha256=ce3587fa5cc55a88c4ba5b2b37621b3329aadf5728f9eafa36bbd121462aabd6
155
+ prism (1.6.0) sha256=bfc0281a81718c4872346bc858dc84abd3a60cae78336c65ad35c8fbff641c6b
156
+ public_suffix (6.0.2) sha256=bfa7cd5108066f8c9602e0d6d4114999a5df5839a63149d3e8b0f9c1d3558394
157
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
158
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
159
+ rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
160
+ redis (5.4.1) sha256=b5e675b57ad22b15c9bcc765d5ac26f60b675408af916d31527af9bd5a81faae
161
+ redis-client (0.28.0) sha256=888892f9cd8787a41c0ece00bdf5f556dfff7770326ce40bb2bc11f1bfec824b
162
+ regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
163
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
164
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
165
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
166
+ rspec-mocks (3.13.7) sha256=0979034e64b1d7a838aaaddf12bf065ea4dc40ef3d4c39f01f93ae2c66c62b1c
167
+ rspec-support (3.13.6) sha256=2e8de3702427eab064c9352fe74488cc12a1bfae887ad8b91cba480ec9f8afb2
168
+ rubocop (1.82.0) sha256=237b7dc24952d7ec469a9593c7a5283315515e2e7dc24ac91532819c254fc4ec
169
+ rubocop-ast (1.48.0) sha256=22df9bbf3f7a6eccde0fad54e68547ae1e2a704bf8719e7c83813a99c05d2e76
170
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
171
+ sem_version (2.0.1) sha256=6d97d4f67e28546ba90b3c290f901d6c8031ddb8e08bce962139739c4d40b183
172
+ simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
173
+ simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
174
+ simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
175
+ unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
176
+ unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
177
+ uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
178
+
106
179
  BUNDLED WITH
107
- 2.5.4
180
+ 4.0.3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 FeatureHub
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.