quonfig-openfeature 2.1.0 → 2.2.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: cd942b88517b56c8ff6d676684e0f1c27fbd5fd62c96c15964af1239d0ac2fe6
4
- data.tar.gz: bff802046f4d1ec5c0422e93f7c13a28edeb98178f2703354511976dc4c3384e
3
+ metadata.gz: d4a4af7330ac53ebeb637ed61d4c7cd0530bcfe62db92b845e5233d105496a3b
4
+ data.tar.gz: 7761829a3596aace1dad718f622b1156656079fd9ffe15123fcf0114c06e9837
5
5
  SHA512:
6
- metadata.gz: 57db850f4f8384be2cc8b47e690ff363876d9ab51a5c7e80468880b3cf9b4607b7263f9081b965feef1dc6cc3e3c0594180153cb67cf9a5317fb7025562e70a9
7
- data.tar.gz: 56bb8b4420465725dd15303de581c254abae3d5f27a98205463dbed394f9cc9848ae47c61d97f7ac89962d707fa35ae8ed6d8c05fb66c2f9e0a50050c434123f
6
+ metadata.gz: 1de71990148d10403dcc3559f5a2d07d16a73a3c6c920e1fc38bdd282a8ba2fbd2d6e9e10524c1b8f04195c337918757f51d94365ec8368824aaccc52da17e8e
7
+ data.tar.gz: 80802c8ddb10fada30d464bbbaf55a9b45e45d05a819980dd555d601568c01003b2d8de9aa5c3f970727e39a4e0d5bcfe5c370d29b82bd11db4b33de987d5ae0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0 - 2026-10-29
4
+
5
+ `fetch_string_value` on a `duration` config returns its stored ISO 8601 text again (reason
6
+ `STATIC`), as in openfeature-go and the shared OpenFeature cases (qfg-177f). The text comes back
7
+ unchanged: `"PT90S"` stays `"PT90S"`, not `"PT1M30S"`. 2.x returned your default with
8
+ `TYPE_MISMATCH`. Number reads of a duration still return your default. A malformed stored duration
9
+ such as `"30s"` still returns your default with `PARSE_ERROR`, and so does a duration ENV_VAR set
10
+ to a malformed value.
11
+
12
+ Requires quonfig (sdk-ruby) 2.1.0: the text is read with its new public `evaluate_details`, in one
13
+ evaluation, and checked against the shared duration grammar with `Quonfig::Duration.valid?`.
14
+
3
15
  ## 2.1.0 - 2026-10-28
4
16
 
5
17
  A malformed value now resolves with error code `PARSE_ERROR` instead of `TYPE_MISMATCH`
data/README.md CHANGED
@@ -134,9 +134,9 @@ Quonfig features require the native `quonfig` SDK:
134
134
 
135
135
  1. **Log levels** -- `should_log?` and the `semantic_logger_filter` are native-only.
136
136
  2. **`string_list` configs** -- accessed via `fetch_object_value` and used as `Array<String>`.
137
- 3. **`duration` configs** -- native-only: read them with `provider.client.get_duration` (integer
138
- milliseconds). `fetch_float_value` and `fetch_number_value` on a duration config return your
139
- default with `TYPE_MISMATCH`.
137
+ 3. **`duration` configs** -- `fetch_string_value` returns the stored ISO 8601 text unchanged
138
+ (`"PT90S"`). For integer milliseconds use `provider.client.get_duration`. `fetch_float_value`
139
+ and `fetch_number_value` on a duration config return your default with `TYPE_MISMATCH`.
140
140
  4. **`bytes` configs** -- not accessible via OpenFeature (no binary type in OF).
141
141
  5. **`keys` / raw config inspection** -- native-only via `provider.client`.
142
142
  6. **Context keys use dot-notation** -- `"user.email"`, not nested hashes.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.2.0
@@ -148,8 +148,12 @@ module Quonfig
148
148
  end
149
149
  end
150
150
 
151
+ # A +duration+ config reads as its stored ISO 8601 text, unchanged
152
+ # ("PT90S" stays "PT90S"): OpenFeature has no duration type (qfg-177f).
151
153
  def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
152
154
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
155
+ next duration_iso_resolution(client, flag_key, mapped_ctx, default_value) if stored_value_type(client, flag_key) == 'duration'
156
+
153
157
  details = client.get_string_details(flag_key, context: mapped_ctx)
154
158
  to_resolution(details, default_value, parse_error: malformed?(client, flag_key, mapped_ctx, :string, details))
155
159
  end
@@ -247,6 +251,38 @@ module Quonfig
247
251
  native.error_code == ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH
248
252
  end
249
253
 
254
+ # Read a duration config as its ISO 8601 text with one evaluation:
255
+ # sdk-ruby's evaluate_details (quonfig >= 2.1.0) returns the resolved
256
+ # value in stored form, so the text is the stored text, or an ENV_VAR's
257
+ # text for a provided duration. evaluate_details does no type check, so
258
+ # the text is validated here with Quonfig::Duration.valid?, the grammar
259
+ # get_duration uses:
260
+ #
261
+ # * valid text: the text, with the evaluation's reason, variant and
262
+ # flag_metadata.
263
+ # * malformed stored text ("30s"): the default with PARSE_ERROR.
264
+ # * malformed ENV_VAR: evaluate_details reports ERROR / TYPE_MISMATCH,
265
+ # which on a duration config can only mean a value that did not
266
+ # parse, so it is PARSE_ERROR too.
267
+ # * the structured { seconds, nanos } shape has no ISO text: the
268
+ # default with TYPE_MISMATCH.
269
+ def duration_iso_resolution(client, flag_key, mapped_ctx, default_value)
270
+ details = client.evaluate_details(flag_key, context: mapped_ctx)
271
+ if details.reason == ::Quonfig::EvaluationDetails::REASON_ERROR
272
+ parse_error = details.error_code == ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH
273
+ return to_resolution(details, default_value, parse_error: parse_error)
274
+ end
275
+ return to_resolution(details, default_value) if details.reason == ::Quonfig::EvaluationDetails::REASON_DEFAULT
276
+
277
+ value = details.value
278
+ return to_resolution(details, default_value) if value.is_a?(String) && ::Quonfig::Duration.valid?(value)
279
+
280
+ error_code = value.is_a?(String) ? ErrorCode::PARSE_ERROR : ErrorCode::TYPE_MISMATCH
281
+ ResolutionDetails.new(value: default_value, reason: Reason::ERROR, error_code: error_code,
282
+ error_message: "duration #{flag_key.inspect} has no valid ISO 8601 text",
283
+ variant: details.variant, flag_metadata: details.flag_metadata || {})
284
+ end
285
+
250
286
  def stored_value_type(client, flag_key)
251
287
  config = client.store.get(flag_key)
252
288
  return nil unless config.is_a?(Hash)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quonfig-openfeature
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dwyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-28 00:00:00.000000000 Z
11
+ date: 2026-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openfeature-sdk
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.0
33
+ version: 2.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.0
40
+ version: 2.1.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement