convert_sdk 1.0.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16cc235aa36baea77098bf6d47a5d479e840ca95a416b36b87f8f178b95895c1
4
- data.tar.gz: 1354d6d78384ebea2f6b187ae601da34e7090de152fc6ca4fa95480e406c04a0
3
+ metadata.gz: aab5bea865be444282ecd0fdcea5b30b5928204e4fecee1bb8b455c3ad54c550
4
+ data.tar.gz: 2753c4042b733710dde55260479205dcc81bcc637c3d5c473b4c3a2671f6f05e
5
5
  SHA512:
6
- metadata.gz: 5fc43abd0fbf174055ef97a00c3c983f232287f886151990931f2635a733fcd0a626e1b35a7f7ef564b2953bcc3cee32b6fe7cb96a9e9ba7dce40b5dfc2e7ae7
7
- data.tar.gz: 74e704ae66077b55a6e92a008a44933190208f8b3caaacefbea041801b4e9bfe8e8498f082205bfa71b4901834ed9cca2ce5d3e80b5e317848e4fc4a2b925e6e
6
+ metadata.gz: 8be2456929af9052ff3522b4004320056d526e6f5ea768ba1cb2f9c47116f80cffe79b8123a141db54d7afb2d70553393ee03ad6fa1d7abb0b9e11baaae39268
7
+ data.tar.gz: a1273013c76b64bb5598767cf9a3d87273f7fda3a4a8a65f2803473bdd123222b8b0dbe67437547dc8d6d0a28b850387e9be01a887b0d51b0e27a0489147c5d3
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Convert Ruby SDK
2
2
 
3
3
  [![Quality Checks](https://github.com/convertcom/ruby-sdk/actions/workflows/qa.yml/badge.svg)](https://github.com/convertcom/ruby-sdk/actions/workflows/qa.yml)
4
- [![Gem Version](https://badge.fury.io/rb/convert_sdk.svg)](https://rubygems.org/gems/convert_sdk)
4
+ [![Gem Version](https://img.shields.io/gem/v/convert_sdk.svg)](https://rubygems.org/gems/convert_sdk)
5
5
  [![API docs](https://img.shields.io/badge/API_docs-YARD-blue)](https://convertcom.github.io/ruby-sdk)
6
6
 
7
7
  The official Convert Experiences FullStack Ruby SDK — server-side A/B testing,
@@ -18,19 +18,21 @@ module ConvertSdk
18
18
  #
19
19
  # == No raw config hash crosses the boundary
20
20
  #
21
- # The parsed config envelope is wrapped here and exposed ONLY through
22
- # hand-written reader methods (+#experiences+, +#feature_by_key(key)+, …) that
23
- # return frozen sub-hashes / arrays. There is no public accessor for the raw
24
- # snapshot and no OpenAPI codegen — the reader inventory is derived by hand
25
- # from the actual config wire shape (the vendored +test-config.json+ fixture).
21
+ # The parsed config snapshot is exposed ONLY through hand-written reader methods
22
+ # (+#experiences+, +#feature_by_key(key)+, …) that return frozen sub-hashes /
23
+ # arrays. There is no public accessor for the raw snapshot and no OpenAPI codegen
24
+ # — the reader inventory is derived by hand from the actual config wire shape
25
+ # (the vendored +test-config.json+ fixture).
26
26
  #
27
- # == Wire shape
27
+ # == Wire shape (flat/root — JS/PHP/Android parity)
28
28
  #
29
- # The config envelope is +{"environment" => ..., "data" => {...}}+; the entity
30
- # collections (+experiences+, +features+, +goals+, +audiences+, +segments+,
31
- # optional +locations+) plus +account_id+ and the +project+ sub-hash live under
32
- # +"data"+. +#project_id+ is +data.project.id+. Readers tolerate sparse or
33
- # absent keys (return +nil+ / +[]+) so a partial config never crashes a reader.
29
+ # Entities live at the ROOT of the config snapshot: +account_id+, +project+,
30
+ # +experiences+, +features+, +goals+, +audiences+, +segments+,
31
+ # +archived_experiences+, and optional +locations+. +#project_id+ is
32
+ # +root["project"]["id"]+. This matches the live endpoint shape (no +"data"+
33
+ # wrapper), the JS SDK, the PHP SDK, and the Android OpenAPI-generated schema.
34
+ # Readers tolerate sparse or absent keys (return +nil+ / +[]+) so a partial
35
+ # config never crashes a reader.
34
36
  #
35
37
  # == Degrade-gracefully (NFR12)
36
38
  #
@@ -138,8 +140,8 @@ module ConvertSdk
138
140
  # marker, so exactly one install in the manager's lifetime is +:first+ even
139
141
  # under concurrent installs.
140
142
  #
141
- # @param hash [Hash{String=>Object}] the parsed config envelope
142
- # (+{"environment" => ..., "data" => {...}}+).
143
+ # @param hash [Hash{String=>Object}] the parsed flat config snapshot
144
+ # (entities at the root +account_id+, +project+, +experiences+, etc.).
143
145
  # @return [Symbol, false] +:first+ on the first successful install,
144
146
  # +:updated+ on any subsequent install, or +false+ when the argument was
145
147
  # rejected (non-Hash) and no swap happened.
@@ -223,22 +225,31 @@ module ConvertSdk
223
225
  (@clock.call - fetched_at) > effective_ttl
224
226
  end
225
227
 
226
- # @return [Boolean] true once a config snapshot has been installed.
228
+ # @return [Boolean] true once a USABLE config (account_id + project.id both
229
+ # present) is installed. Mirrors JS SDK's +isValidConfigData+ check
230
+ # (+account_id && project.id+). A snapshot that carries a +project+ key but
231
+ # no id (e.g. +project: {}+) or a malformed +project+ value is NOT considered
232
+ # available — avoids silently serving nil reads to decision paths.
227
233
  def config_available?
228
- !@config.nil?
234
+ !account_id.nil? && !project_id.nil?
229
235
  end
230
236
 
231
- # @return [String, nil] the account id (+data.account_id+), or nil pre-config.
237
+ # @return [String, nil] the account id (+account_id+ at the config root), or nil pre-config.
232
238
  def account_id
233
239
  data&.fetch("account_id", nil)
234
240
  end
235
241
 
236
- # @return [String, nil] the project id (+data.project.id+), or nil pre-config.
242
+ # @return [String, nil] the project id (+project.id+ at the config root), or nil pre-config.
243
+ # Type-safe against a non-Hash +project+ value (e.g. a String in a malformed
244
+ # direct-data config): +&.+ guards nil only; a non-nil non-Hash would raise
245
+ # NoMethodError on +#fetch+. Mirrors JS optional-chaining safety
246
+ # (+data?.project?.id+).
237
247
  def project_id
238
- project&.fetch("id", nil)
248
+ p = project
249
+ p.is_a?(Hash) ? p.fetch("id", nil) : nil
239
250
  end
240
251
 
241
- # @return [Hash, nil] the frozen +data.project+ sub-hash, or nil pre-config.
252
+ # @return [Hash, nil] the frozen +project+ sub-hash at the config root, or nil pre-config.
242
253
  def project
243
254
  data&.fetch("project", nil)
244
255
  end
@@ -856,13 +867,14 @@ module ConvertSdk
856
867
  @ttl || ConvertSdk::DEFAULT_CONFIG_TTL
857
868
  end
858
869
 
859
- # The frozen +"data"+ sub-hash of the live snapshot, or nil pre-config.
860
- # Read lock-free: @config is either nil or a fully-frozen graph.
870
+ # The live snapshot root (entities live at the root JS/PHP/Android parity),
871
+ # or nil pre-config. Read lock-free: @config is either nil or a fully-frozen
872
+ # graph.
861
873
  def data
862
- @config&.fetch("data", nil)
874
+ @config
863
875
  end
864
876
 
865
- # Fetch a frozen collection under +"data"+, defaulting to a frozen empty
877
+ # Fetch a frozen collection at the config root, defaulting to a frozen empty
866
878
  # array when the snapshot or the key is absent.
867
879
  def collection(name)
868
880
  found = data&.fetch(name, nil)
@@ -10,5 +10,5 @@ module ConvertSdk
10
10
  # derives its version from this run's git tag, not from this file (FR66).
11
11
  # Mirrors the Android SDK's `0.0.0` placeholder in gradle/libs.versions.toml.
12
12
  # @return [String]
13
- VERSION = "1.0.0"
13
+ VERSION = "1.0.1"
14
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convert_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Convert Insights, Inc.