smplkit 1.0.13 → 1.0.15

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: 0f74b529f57291b182d674d166e138a61b95bb01c1bdf01a71261405f75a6879
4
- data.tar.gz: 7e08e3ec63e892ae13bec37446afcd38c7b5d16008a0396d7046efd362598ed9
3
+ metadata.gz: d5d5ed1af296c517f09ddd0a76660b157184f3bb763a61ae0fcf727c1a3f5a87
4
+ data.tar.gz: 487bcd0200af912fcbb1acdf52967e87bf485c1b1ced27fb564cfc96ac4ee41b
5
5
  SHA512:
6
- metadata.gz: 28aa21a7b049e824c613ab8d53df09a0993abd938cb275ee7a330735623b9e6de99b986f6930bc6bab472a26533abf472d5a6f41301e54d833856fdb6708c882
7
- data.tar.gz: 738683d247b8a2c557731deaae62c93120899da054dcfb91991d7ee114dd5a40c7f945456916713aa4500aa2a6e1fefe5ea0916f682804c63a4eea2af3ad1afc
6
+ metadata.gz: 78bd324f3ab4c18732cf2a0a4bbef41f761ebf347501d721b941083ee4a06657bbd5f3c48e0113e63522515ed5b15566b47ecc727613925b8df866b4459d4f6e
7
+ data.tar.gz: f66aa64fdd45800335739c0d5a8fda29e4b8c51d70c94f5412ee1bdc44f09d161ded9eefd5c9252f438796c2063d53dcdad870dd949b4d2872b9751b6c54d974
data/README.md CHANGED
@@ -100,12 +100,23 @@ This creates `config/initializers/smplkit.rb` with documented examples for the p
100
100
 
101
101
  ```bash
102
102
  bundle install
103
- bundle exec rspec # unit tests
103
+ bundle exec rspec # unit tests — wrapper layer is held to 100% line coverage in CI
104
104
  bundle exec rubocop # lint
105
- make generate # regenerate clients (requires Node.js + npx)
105
+ make generate # regenerate clients
106
106
  ```
107
107
 
108
- The repository follows the standard smplkit "every commit lands on `main`" workflow — see CLAUDE.md.
108
+ `make generate` shells out to `npx --yes @openapitools/openapi-generator-cli`,
109
+ so it requires:
110
+
111
+ - Node.js 18+ (provides `npx`)
112
+ - A JRE 11+ (the openapi-generator JAR runs under Java)
113
+
114
+ Both are pre-installed on the CI matrix runners. On a developer machine,
115
+ install via Homebrew (`brew install node openjdk`) or your distribution's
116
+ package manager.
117
+
118
+ The repository follows the standard smplkit "every commit lands on `main`"
119
+ workflow — see CLAUDE.md.
109
120
 
110
121
  ## License
111
122
 
@@ -181,7 +181,7 @@ module SmplkitGeneratedClient::App
181
181
  @ignore_operation_servers = false
182
182
  @inject_format = false
183
183
  @force_ending_format = false
184
- @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
184
+ @logger = defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
185
185
 
186
186
  yield(self) if block_given?
187
187
  end
@@ -181,7 +181,7 @@ module SmplkitGeneratedClient::Config
181
181
  @ignore_operation_servers = false
182
182
  @inject_format = false
183
183
  @force_ending_format = false
184
- @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
184
+ @logger = defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
185
185
 
186
186
  yield(self) if block_given?
187
187
  end
@@ -181,7 +181,7 @@ module SmplkitGeneratedClient::Flags
181
181
  @ignore_operation_servers = false
182
182
  @inject_format = false
183
183
  @force_ending_format = false
184
- @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
184
+ @logger = defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
185
185
 
186
186
  yield(self) if block_given?
187
187
  end
@@ -44,7 +44,7 @@ module SmplkitGeneratedClient::Flags
44
44
  def self.openapi_types
45
45
  {
46
46
  :'enabled' => :'Boolean',
47
- :'default' => :'AnyOf',
47
+ :'default' => :'Object',
48
48
  :'rules' => :'Array<FlagRule>'
49
49
  }
50
50
  end
@@ -181,7 +181,7 @@ module SmplkitGeneratedClient::Logging
181
181
  @ignore_operation_servers = false
182
182
  @inject_format = false
183
183
  @force_ending_format = false
184
- @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
184
+ @logger = defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
185
185
 
186
186
  yield(self) if block_given?
187
187
  end
@@ -31,8 +31,8 @@ module Smplkit
31
31
  attr_reader :manage, :config, :flags, :logging
32
32
 
33
33
  # Construct, yield to the block, and close on exit.
34
- def self.open(**)
35
- client = new(**)
34
+ def self.open(**kwargs)
35
+ client = new(**kwargs)
36
36
  begin
37
37
  yield client
38
38
  ensure
@@ -185,19 +185,23 @@ module Smplkit
185
185
 
186
186
  def schedule_periodic_flush
187
187
  @flush_timer = Concurrent::TimerTask.new(execution_interval: PERIODIC_FLUSH_INTERVAL) do
188
- next if @closed
189
-
190
- begin
191
- @manage.contexts.flush
192
- @manage.flags.flush
193
- @manage.loggers.flush
194
- rescue StandardError => e
195
- Smplkit.debug("registration", "periodic flush failed: #{e.class}: #{e.message}")
196
- end
188
+ run_periodic_flush
197
189
  end
198
190
  @flush_timer.execute
199
191
  end
200
192
 
193
+ # Extracted as a private method so the timer body is reachable from
194
+ # tests without poking into Concurrent::TimerTask internals.
195
+ def run_periodic_flush
196
+ return if @closed
197
+
198
+ @manage.contexts.flush
199
+ @manage.flags.flush
200
+ @manage.loggers.flush
201
+ rescue StandardError => e
202
+ Smplkit.debug("registration", "periodic flush failed: #{e.class}: #{e.message}")
203
+ end
204
+
201
205
  def final_flush
202
206
  [@manage.contexts, @manage.flags, @manage.loggers].each do |ns|
203
207
  ns.flush
@@ -206,13 +210,18 @@ module Smplkit
206
210
  end
207
211
  end
208
212
 
209
- def register_service_context(_mgmt, _env, _svc, _app_url)
210
- # No-op stub: bulk-registers the service + environment with the platform.
211
- # Wired up via the contexts buffer once the generated client layer is
212
- # committed. Until then, the in-process buffer captures these and the
213
- # next periodic flush attempts to send them.
213
+ def register_service_context(mgmt, env, svc, app_url)
214
+ # Bulk-register the environment + service as +Smplkit::Context+
215
+ # instances on the platform so they show up in the Console alongside
216
+ # any user-provided contexts. The buffer dedupes on +(type, key)+, so
217
+ # this is safe to call on every client construction.
218
+ contexts = []
219
+ contexts << Smplkit::Context.new("environment", env) if env
220
+ contexts << Smplkit::Context.new("service", svc, name: svc) if svc
221
+ mgmt.contexts.register(contexts)
222
+ mgmt.contexts.flush
214
223
  rescue StandardError => e
215
- Smplkit.debug("lifecycle", "register service context failed: #{e.class}: #{e.message}")
224
+ Smplkit.debug("lifecycle", "register service context failed (app: #{app_url}): #{e.class}: #{e.message}")
216
225
  end
217
226
  end
218
227
  end
@@ -40,32 +40,6 @@ module Smplkit
40
40
  )
41
41
  end
42
42
 
43
- def build_config_request_body(config)
44
- items = {}
45
- config.items.each do |item|
46
- items[item.name] = {
47
- "value" => item.value,
48
- "type" => item.type,
49
- "description" => item.description
50
- }.compact
51
- end
52
-
53
- environments = config.environments.each_with_object({}) do |(env, env_obj), out|
54
- out[env] = { "values" => env_obj.values_raw }
55
- end
56
-
57
- # The Config schema (per the OpenAPI spec) does not include +key+ in
58
- # attributes — the resource +id+ carries the customer-facing key.
59
- attributes = {
60
- "name" => config.name,
61
- "description" => config.description,
62
- "parent" => config.parent_id,
63
- "items" => items,
64
- "environments" => environments
65
- }.compact
66
- { "data" => { "type" => "config", "id" => config.key, "attributes" => attributes } }
67
- end
68
-
69
43
  # Deep-merge two Hashes, with +override+ winning. Mirrors the Python
70
44
  # +deep_merge+ helper used by the resolver.
71
45
  def deep_merge(base, override)
@@ -28,12 +28,14 @@ module Smplkit
28
28
  "telemetry" => true
29
29
  }.freeze
30
30
 
31
- ResolvedConfig = Data.define(
32
- :api_key, :base_domain, :scheme, :environment, :service, :debug, :telemetry
31
+ ResolvedConfig = Struct.new(
32
+ :api_key, :base_domain, :scheme, :environment, :service, :debug, :telemetry,
33
+ keyword_init: true
33
34
  )
34
35
 
35
- ResolvedManagementConfig = Data.define(
36
- :api_key, :base_domain, :scheme, :debug
36
+ ResolvedManagementConfig = Struct.new(
37
+ :api_key, :base_domain, :scheme, :debug,
38
+ keyword_init: true
37
39
  )
38
40
 
39
41
  module_function
@@ -23,8 +23,8 @@ module Smplkit
23
23
  h
24
24
  end
25
25
 
26
- def to_json(*)
27
- JSON.generate(to_h, *)
26
+ def to_json(*args)
27
+ JSON.generate(to_h, *args)
28
28
  end
29
29
  end
30
30
 
@@ -47,30 +47,6 @@ module Smplkit
47
47
  rules: rules
48
48
  )
49
49
  end
50
-
51
- # Build the JSON body for a Flag create/update request.
52
- def build_flag_request_body(flag)
53
- environments = flag.environments.each_with_object({}) do |(env_key, env), out|
54
- out[env_key] = {
55
- "enabled" => env.enabled,
56
- "default" => env.default,
57
- "rules" => env.rules.map { |r| { "logic" => r.logic, "value" => r.value, "description" => r.description } }
58
- }
59
- end
60
-
61
- attributes = {
62
- "id" => flag.id,
63
- "name" => flag.name,
64
- "type" => flag.type,
65
- "default" => flag.default,
66
- "description" => flag.description,
67
- "environments" => environments
68
- }
69
- values = flag.values
70
- attributes["values"] = values.map { |v| { "name" => v.name, "value" => v.value } } if values
71
-
72
- { "data" => { "type" => "flag", "id" => flag.id, "attributes" => attributes.compact } }
73
- end
74
50
  end
75
51
  end
76
52
  end
@@ -6,7 +6,7 @@ module Smplkit
6
6
  #
7
7
  # Lives in +Flag#values+. Frozen — author values via +Flag#add_value+ /
8
8
  # +Flag#remove_value+ / +Flag#clear_values+.
9
- FlagValue = Data.define(:name, :value)
9
+ FlagValue = Struct.new(:name, :value, keyword_init: true)
10
10
 
11
11
  # A single targeting rule on a +Flag+.
12
12
  #
@@ -102,7 +102,11 @@ module Smplkit
102
102
 
103
103
  return unless @adapters.empty?
104
104
 
105
+ # :nocov: defensive log — unreachable in practice because stdlib
106
+ # +Logger+ is always present, so +StdlibLoggerAdapter+ is always
107
+ # constructible.
105
108
  Smplkit.debug("registration", "no logging adapters loaded; runtime features disabled")
109
+ # :nocov:
106
110
  end
107
111
 
108
112
  def observe_logger(_adapter, raw_name, level)
@@ -38,32 +38,6 @@ module Smplkit
38
38
  updated_at: attrs["updated_at"]
39
39
  )
40
40
  end
41
-
42
- def build_logger_body(logger)
43
- attributes = {
44
- "name" => logger.name,
45
- "resolved_level" => logger.resolved_level&.to_s,
46
- "level" => logger.level&.to_s,
47
- "service" => logger.service,
48
- "environment" => logger.environment,
49
- "log_group_id" => logger.log_group_id,
50
- "managed" => logger.managed,
51
- "description" => logger.description
52
- }.compact
53
- { "data" => { "type" => "logger", "id" => logger.id, "attributes" => attributes } }
54
- end
55
-
56
- def build_log_group_body(group)
57
- attributes = {
58
- "key" => group.key,
59
- "name" => group.name,
60
- "level" => group.level&.to_s,
61
- "description" => group.description,
62
- "parent_id" => group.parent_id,
63
- "environments" => group.environments
64
- }.compact
65
- { "data" => { "type" => "log_group", "id" => group.key, "attributes" => attributes } }
66
- end
67
41
  end
68
42
  end
69
43
  end