shipeasy-sdk 3.6.0 → 3.7.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: ad9abca98f87069daf53c2e2347e9f2975595b437576738aef381fbc2a4a9a10
4
- data.tar.gz: 300a69f50db74da6279666d9d6d8698dbb22d08365e846f20403609e001ea638
3
+ metadata.gz: c492371b226e15657ecdbdafdab11e79cd512d4f46ae412af3b000a203c0f3ec
4
+ data.tar.gz: a10503e08343510e5b12ebb3c23e9cdc19f05cb5781edb5fac381d7c98f8bc78
5
5
  SHA512:
6
- metadata.gz: cfb4185054243325d9130de44d40fff6d28af91ee2100150a7f594c2a9925c8ab20f931a2d1ccb433b830521ac07b7ff2381ff2325cf3b1ada0591d674f30c0d
7
- data.tar.gz: 5b89a4b38c9f6b9eebc9946e50ebd74bbfb5336c0354cee43321b7ea94652fff7da669deebf74317a7aee6492db6760e471ea29b0c375885474e5ab2e37fbdab
6
+ metadata.gz: 8df684d6629ee574b6e20bbac97c1409b56c00892c739357b980f298203cc7dc7fe1b34bce3f5758e983354c19124a648f1078f4e27bdcc9e383cef5aba5706c
7
+ data.tar.gz: ca4ff0fcfceca63eaad68696f5e19168b07ca559530adb42747ec9f1138d12750e694b40025094ec0b97952b73bb6dd1d784dc94a3f0669b538693260ed9cf97
data/docs/skill/SKILL.md CHANGED
@@ -145,8 +145,9 @@ into every see() report later in the same (fiber-local, per-request) scope.
145
145
  <h1><%= i18n_t("hero.title", name: current_user.name) %></h1>
146
146
  ```
147
147
 
148
- Outside Rails: `Shipeasy.i18n_script_tag(client_key, profile: "en:prod")` emits
149
- the loader tag (public client key).
148
+ Anywhere (Rails or not): `<%= Shipeasy.i18n_script_tag %>` emits the loader tag
149
+ (public client key). Every argument is optional — key, profile and CDN base come
150
+ from `configure`; pass one only to override it for that tag.
150
151
 
151
152
  → More: `pages/i18n.md` · snippets `snippets/i18n/{setup,render}.md`.
152
153
 
@@ -157,7 +158,10 @@ the loader tag (public client key).
157
158
  - `c.private_attributes = ["email"]` strips keys from outbound events.
158
159
  - `c.clean_backtrace` (default on) filters `see()` stacks to app frames via `Rails.backtrace_cleaner`; set `false` for raw backtraces.
159
160
  - `c.sticky_store = Shipeasy::SDK::InMemoryStickyStore.new` pins experiment assignment.
160
- - SSR: `Shipeasy.bootstrap_script_tag(user)` + `Shipeasy.i18n_script_tag(client_key, "en:prod")`.
161
+ - SSR tags — all arguments optional (defaults from `configure`), html_safe under Rails:
162
+ `Shipeasy.bootstrap_script_tag(user)`, `Shipeasy.i18n_script_tag`,
163
+ `Shipeasy.devtools_script_tag` (overlay; needs `c.project_id` + `c.public_key`;
164
+ opens with Shift+Alt+S or `?se=1`).
161
165
  - `Shipeasy.on_change { ... }` (requires `c.poll = true`) fires after a poll fetches new data.
162
166
 
163
167
  → More: `pages/advanced.md`.
@@ -55,7 +55,7 @@ module Shipeasy
55
55
  say " Shipeasy installed → config/initializers/shipeasy.rb", :green
56
56
  say ""
57
57
  say " Next steps:"
58
- say " 1. Mint your keys: https://app.shipeasy.ai → Settings → SDK keys"
58
+ say " 1. Mint your keys: https://shipeasy.ai → Connect → SDK Keys"
59
59
  say " 2. Provide them (pick one):"
60
60
  say " • ENV — set SHIPEASY_SERVER_KEY#{options[:i18n] ? " and SHIPEASY_CLIENT_KEY" : ""}"
61
61
  say " • Rails credentials — bin/rails credentials:edit, then read"
@@ -86,9 +86,15 @@ module Shipeasy
86
86
  attr_accessor :attributes
87
87
 
88
88
  # ---- i18n / string manager ----
89
- attr_accessor :public_key, :profile, :default_chunk,
89
+ attr_accessor :public_key, :profile,
90
90
  :cdn_base_url, :loader_url,
91
- :manifest_cache_ttl, :label_file_cache_ttl, :http_timeout
91
+ :label_file_cache_ttl, :http_timeout
92
+
93
+ # Your Shipeasy project id (`proj_…`). Read by the SSR tag helpers — the
94
+ # devtools overlay tag needs it to know which project it is wired to — so
95
+ # setting it here is what makes `Shipeasy.devtools_script_tag` an
96
+ # argument-free call.
97
+ attr_accessor :project_id
92
98
 
93
99
  # When true, `i18n_t` renders the translation KEY verbatim instead of
94
100
  # resolving its value, so tests/snapshots assert against stable data instead
@@ -114,11 +120,12 @@ module Shipeasy
114
120
  @sticky_store = nil
115
121
  @log_level = :warn
116
122
 
123
+ @project_id = nil
117
124
  @profile = "default"
118
- @default_chunk = "index"
119
- @cdn_base_url = "https://cdn.i18n.shipeasy.ai"
120
- @loader_url = "https://cdn.i18n.shipeasy.ai/loader.js"
121
- @manifest_cache_ttl = 60
125
+ # The single CDN host the worker actually serves i18n from. The historical
126
+ # `cdn.i18n.shipeasy.ai` manifest host was never wired up.
127
+ @cdn_base_url = "https://cdn.shipeasy.ai"
128
+ @loader_url = "https://cdn.shipeasy.ai/sdk/i18n/loader.js"
122
129
  @label_file_cache_ttl = 3600
123
130
  @http_timeout = 1
124
131
  # nil ⇒ env-derived (on under RAILS_ENV/…=="test"); true/false overrides.
@@ -306,18 +313,33 @@ module Shipeasy
306
313
  end
307
314
 
308
315
  # SSR tag helpers — delegate to the configured global engine, so you never
309
- # touch it. i18n_script_tag carries the PUBLIC client key (not the server
310
- # key); bootstrap_script_tag embeds no key.
311
- def i18n_script_tag(client_key, profile: "en:prod", base_url: nil)
316
+ # touch it. i18n_script_tag and devtools_script_tag carry the PUBLIC client
317
+ # key (never the server key); bootstrap_script_tag embeds no key.
318
+ #
319
+ # EVERY argument is optional: each falls back to what `Shipeasy.configure`
320
+ # already set (public_key / project_id / profile / cdn_base_url), so the
321
+ # normal call is the bare helper — `<%= Shipeasy.i18n_script_tag %>`. Pass an
322
+ # argument only to override the configured value for one tag. The returned
323
+ # tag is html_safe under Rails, so no `.html_safe` at the callsite.
324
+ def i18n_script_tag(client_key = nil, profile: nil, base_url: nil)
312
325
  require_engine("i18n_script_tag").i18n_script_tag(client_key, profile: profile, base_url: base_url)
313
326
  end
314
327
 
315
- def bootstrap_script_tag(user, anon_id: nil, i18n_profile: "en:prod", base_url: nil)
328
+ def bootstrap_script_tag(user = nil, anon_id: nil, i18n_profile: nil, base_url: nil)
316
329
  require_engine("bootstrap_script_tag").bootstrap_script_tag(
317
330
  user, anon_id: anon_id, i18n_profile: i18n_profile, base_url: base_url
318
331
  )
319
332
  end
320
333
 
334
+ # The devtools overlay tag (hosted se-devtools.js; opens with Shift+Alt+S or
335
+ # `?se=1`). Needs the project id + public client key, both taken from
336
+ # configure unless passed.
337
+ def devtools_script_tag(project_id = nil, client_key: nil, base_url: nil, defer: true)
338
+ require_engine("devtools_script_tag").devtools_script_tag(
339
+ project_id, client_key: client_key, base_url: base_url, defer: defer
340
+ )
341
+ end
342
+
321
343
  # see() structured error reporting — package-level, dispatched through the
322
344
  # last-constructed default client (the engine configure built). Never raises
323
345
  # into caller code; a call before any client exists warns and no-ops.
@@ -472,31 +472,64 @@ module Shipeasy
472
472
  # Return the cross-platform SSR bootstrap <script> tag for a request:
473
473
  # se-bootstrap.js reads its data-* attributes and hydrates
474
474
  # window.__SE_BOOTSTRAP (and writes the anon cookie). No key is embedded.
475
- def bootstrap_script_tag(user, anon_id: nil, i18n_profile: "en:prod", base_url: nil)
475
+ #
476
+ # Every argument is OPTIONAL and falls back to `Shipeasy.configure`:
477
+ # `user` to an anonymous request, `i18n_profile:` to `config.profile`,
478
+ # `base_url:` to `config.cdn_base_url` — so `bootstrap_script_tag` alone
479
+ # is a valid call for a logged-out page.
480
+ def bootstrap_script_tag(user = nil, anon_id: nil, i18n_profile: nil, base_url: nil)
481
+ user ||= {}
476
482
  payload = evaluate(user)
477
- base = cdn_base(base_url)
483
+ base = cdn_base(base_url || Shipeasy.config.cdn_base_url)
478
484
  attrs = [
479
485
  "data-se-bootstrap",
480
486
  attr("data-flags", JSON.generate(payload["flags"])),
481
487
  attr("data-configs", JSON.generate(payload["configs"])),
482
488
  attr("data-experiments", JSON.generate(payload["experiments"])),
483
489
  attr("data-killswitches", JSON.generate(payload["killswitches"])),
484
- attr("data-i18n-profile", i18n_profile || "en:prod"),
490
+ attr("data-i18n-profile", resolved_profile(i18n_profile)),
485
491
  attr("data-api-url", base),
486
492
  ]
487
493
  attrs << attr("data-anon-id", anon_id) if anon_id && !anon_id.empty?
488
494
  data_user = identity_attrs(user)
489
495
  attrs << attr("data-user", data_user) if data_user
490
- %(<script src="#{CGI.escapeHTML("#{base}/sdk/bootstrap.js")}" #{attrs.join(' ')}></script>)
496
+ html %(<script src="#{CGI.escapeHTML("#{base}/sdk/bootstrap.js")}" #{attrs.join(' ')}></script>)
491
497
  end
492
498
 
493
499
  # Return the i18n loader <script> tag (framework-agnostic; the Rails view
494
500
  # helper Shipeasy::I18n::ViewHelpers#i18n_script_tag is separate). The
495
501
  # loader fetches translations for the profile using the PUBLIC client key.
496
- def i18n_script_tag(client_key, profile: "en:prod", base_url: nil)
497
- base = cdn_base(base_url)
498
- %(<script src="#{CGI.escapeHTML("#{base}/sdk/i18n/loader.js")}" ) +
499
- %(#{attr('data-key', client_key)} #{attr('data-profile', profile || 'en:prod')}></script>)
502
+ #
503
+ # Every argument is OPTIONAL and falls back to `Shipeasy.configure`:
504
+ # `client_key` to `config.public_key`, `profile:` to `config.profile`,
505
+ # `base_url:` to `config.cdn_base_url`.
506
+ def i18n_script_tag(client_key = nil, profile: nil, base_url: nil)
507
+ base = cdn_base(base_url || Shipeasy.config.cdn_base_url)
508
+ key = client_key || Shipeasy.config.public_key
509
+ warn_missing("i18n_script_tag", "public_key", key)
510
+ html %(<script src="#{CGI.escapeHTML("#{base}/sdk/i18n/loader.js")}" ) +
511
+ %(#{attr('data-key', key)} #{attr('data-profile', resolved_profile(profile))}></script>)
512
+ end
513
+
514
+ # Return the devtools overlay <script> tag. se-devtools.js is a hosted,
515
+ # self-executing bundle — nothing to install — that reads its project and
516
+ # public client key off the tag. The overlay opens with Shift+Alt+S or on
517
+ # any page loaded with `?se=1`.
518
+ #
519
+ # Every argument is OPTIONAL and falls back to `Shipeasy.configure`:
520
+ # `project_id` to `config.project_id`, `client_key:` to
521
+ # `config.public_key`, `base_url:` to `config.cdn_base_url`. `defer:`
522
+ # (default true) keeps the overlay off the critical rendering path — the
523
+ # overlay is a developer tool, never needed for first paint.
524
+ def devtools_script_tag(project_id = nil, client_key: nil, base_url: nil, defer: true)
525
+ base = cdn_base(base_url || Shipeasy.config.cdn_base_url)
526
+ pid = project_id || Shipeasy.config.project_id
527
+ key = client_key || Shipeasy.config.public_key
528
+ warn_missing("devtools_script_tag", "project_id", pid)
529
+ warn_missing("devtools_script_tag", "public_key", key)
530
+ attrs = [attr("data-project-id", pid), attr("data-client-api-key", key)]
531
+ attrs << "defer" if defer
532
+ html %(<script src="#{CGI.escapeHTML("#{base}/se-devtools.js")}" #{attrs.join(' ')}></script>)
500
533
  end
501
534
 
502
535
  def track(user_id, event_name, props = {})
@@ -747,6 +780,37 @@ module Shipeasy
747
780
  %(#{name}="#{CGI.escapeHTML(value.to_s)}")
748
781
  end
749
782
 
783
+ # Mark a tag we built ourselves (every interpolated value is already
784
+ # HTML-escaped) as safe, so `<%= Shipeasy.i18n_script_tag %>` renders the
785
+ # markup instead of escaping it — no `.html_safe` at the callsite. Plain
786
+ # String outside Rails, where nothing defines html_safe.
787
+ def html(tag)
788
+ tag.respond_to?(:html_safe) ? tag.html_safe : tag
789
+ end
790
+
791
+ # The i18n profile a tag should carry: an explicit argument wins, then the
792
+ # configured profile, then the platform default.
793
+ def resolved_profile(profile)
794
+ p = profile || Shipeasy.config.profile
795
+ p.nil? || p.to_s.empty? ? "en:prod" : p
796
+ end
797
+
798
+ # A tag built with no key/id is not an error — it renders, and the browser
799
+ # bundle reports what it needs — but it is never what the caller wanted.
800
+ # Logged once per (helper, setting): a tag helper runs on every render, and
801
+ # one misconfiguration must not fill the log with a line per request.
802
+ def warn_missing(fn_name, setting, value)
803
+ return unless value.nil? || value.to_s.empty?
804
+
805
+ @warned_missing ||= {}
806
+ return if @warned_missing["#{fn_name}.#{setting}"]
807
+
808
+ @warned_missing["#{fn_name}.#{setting}"] = true
809
+ Shipeasy::Logging.warn "[shipeasy] #{fn_name}: no #{setting} — set c.#{setting} " \
810
+ "in Shipeasy.configure (or pass it explicitly); the tag " \
811
+ "will render without it"
812
+ end
813
+
750
814
  # Serialize the server-identified user's traits for the SSR bootstrap tag's
751
815
  # data-user attribute: the request user minus `anonymous_id`, dropping
752
816
  # nil values only (empty strings and other present values are kept, to
@@ -1,26 +1,34 @@
1
1
  require "net/http"
2
2
  require "uri"
3
3
  require "json"
4
- require "digest"
5
4
 
6
5
  module Shipeasy
7
6
  module I18n
8
7
  class LabelFetcher
9
- MANIFEST_KEY_PREFIX = "i18n:manifest:"
10
- LABEL_KEY_PREFIX = "i18n:label:"
8
+ LABEL_KEY_PREFIX = "i18n:strings:"
11
9
 
12
10
  def initialize(config = Shipeasy.config)
13
11
  @config = config
14
12
  end
15
13
 
16
- def fetch(profile: @config.profile, chunk: @config.default_chunk)
17
- manifest = fetch_manifest(profile)
18
- return nil unless manifest
19
-
20
- file_url = manifest[chunk]
21
- return nil unless file_url
22
-
23
- fetch_label_file(file_url)
14
+ # Fetch a profile's published strings.
15
+ #
16
+ # Publishing is PROFILE-WIDE: the whole profile is snapshotted into one
17
+ # blob and served from a single endpoint, so there is no sub-profile unit
18
+ # to select. This used to fetch a `manifest.json` and index it by "chunk"
19
+ # an endpoint the worker never served, so SSR i18n always came back
20
+ # empty and pages rendered raw `{{var}}` templates and key fallbacks.
21
+ # (sdk-ts hit the same bug and moved to this endpoint; see its
22
+ # `fetchLabelsForSSR`.)
23
+ #
24
+ # Returns the `{ "locale" => ..., "strings" => { key => value } }` blob,
25
+ # or nil when it cannot be fetched.
26
+ def fetch(profile: @config.profile)
27
+ cache_key = "#{LABEL_KEY_PREFIX}#{@config.public_key}:#{profile}"
28
+ cache_fetch(cache_key, @config.label_file_cache_ttl) do
29
+ url = "#{@config.cdn_base_url}/sdk/i18n/strings?profile=#{URI.encode_www_form_component(profile)}"
30
+ http_get_json(url, { "X-SDK-Key" => @config.public_key.to_s })
31
+ end
24
32
  rescue => e
25
33
  ::Rails.logger.warn("[Shipeasy::I18n] Failed to fetch labels: #{e.message}") if defined?(::Rails)
26
34
  nil
@@ -28,21 +36,6 @@ module Shipeasy
28
36
 
29
37
  private
30
38
 
31
- def fetch_manifest(profile)
32
- cache_key = "#{MANIFEST_KEY_PREFIX}#{@config.public_key}:#{profile}"
33
- cache_fetch(cache_key, @config.manifest_cache_ttl) do
34
- url = "#{@config.cdn_base_url}/labels/#{@config.public_key}/#{profile}/manifest.json"
35
- http_get_json(url)
36
- end
37
- end
38
-
39
- def fetch_label_file(url)
40
- cache_key = "#{LABEL_KEY_PREFIX}#{Digest::MD5.hexdigest(url)}"
41
- cache_fetch(cache_key, @config.label_file_cache_ttl) do
42
- http_get_json(url)
43
- end
44
- end
45
-
46
39
  def cache_fetch(key, ttl, &block)
47
40
  if defined?(::Rails) && ::Rails.cache
48
41
  ::Rails.cache.fetch(key, expires_in: ttl.seconds, &block)
@@ -51,13 +44,13 @@ module Shipeasy
51
44
  end
52
45
  end
53
46
 
54
- def http_get_json(url)
47
+ def http_get_json(url, headers = {})
55
48
  uri = URI.parse(url)
56
49
  http = Net::HTTP.new(uri.host, uri.port)
57
50
  http.use_ssl = (uri.scheme == "https")
58
51
  http.open_timeout = @config.http_timeout
59
52
  http.read_timeout = @config.http_timeout
60
- res = http.get(uri.request_uri, { "Accept" => "application/json" })
53
+ res = http.get(uri.request_uri, { "Accept" => "application/json" }.merge(headers))
61
54
  raise "HTTP #{res.code} fetching #{url}" unless res.is_a?(Net::HTTPSuccess)
62
55
  JSON.parse(res.body)
63
56
  end
@@ -1,18 +1,17 @@
1
1
  module Shipeasy
2
2
  module I18n
3
3
  module ViewHelpers
4
- def i18n_head_tags(profile: nil, chunk: nil)
4
+ def i18n_head_tags(profile: nil)
5
5
  safe_join([
6
- i18n_inline_data(profile: profile, chunk: chunk),
6
+ i18n_inline_data(profile: profile),
7
7
  i18n_script_tag,
8
8
  ], "\n")
9
9
  end
10
10
 
11
- def i18n_inline_data(profile: nil, chunk: nil)
11
+ def i18n_inline_data(profile: nil)
12
12
  config = Shipeasy.config
13
13
  label_file = Shipeasy::I18n::LabelFetcher.new.fetch(
14
14
  profile: profile || config.profile,
15
- chunk: chunk || config.default_chunk,
16
15
  )
17
16
  return "".html_safe unless label_file
18
17
 
@@ -29,10 +28,15 @@ module Shipeasy
29
28
  async: true,
30
29
  }
31
30
  attrs[:"data-hide-until-ready"] = "true" if hide_until_ready
32
- tag(:script, attrs)
31
+ # `content_tag`, NOT `tag` — the latter renders a self-closing
32
+ # `<script … />`, which HTML has no such thing as: the parser treats
33
+ # everything up to the next `</script>` as this script's body, silently
34
+ # swallowing whatever the layout puts after us in the <head> (the
35
+ # bootstrap tag, most often). An explicit close tag is required.
36
+ content_tag(:script, "", attrs)
33
37
  end
34
38
 
35
- def i18n_t(key, variables = {}, profile: nil, chunk: nil)
39
+ def i18n_t(key, variables = {}, profile: nil)
36
40
  config = Shipeasy.config
37
41
  # render_keys_only (default: env==test): return the key verbatim,
38
42
  # skipping value resolution + interpolation so tests assert stable data.
@@ -40,7 +44,6 @@ module Shipeasy
40
44
 
41
45
  label_file = Shipeasy::I18n::LabelFetcher.new.fetch(
42
46
  profile: profile || config.profile,
43
- chunk: chunk || config.default_chunk,
44
47
  )
45
48
  return key unless label_file && label_file["strings"]
46
49
 
@@ -1,5 +1,5 @@
1
1
  module Shipeasy
2
2
  module SDK
3
- VERSION = "3.6.0"
3
+ VERSION = "3.7.0"
4
4
  end
5
5
  end
@@ -91,7 +91,7 @@ module Shipeasy::Admin::Generated
91
91
  end
92
92
 
93
93
  # List i18n profiles
94
- # Returns every locale profile in the project (e.g. `en:prod`, `fr:prod`). **Use case:** Discover which locale profiles exist before pushing keys or publishing a chunk.
94
+ # Returns every locale profile in the project (e.g. `en:prod`, `fr:prod`). **Use case:** Discover which locale profiles exist before pushing keys or publishing.
95
95
  # @param [Hash] opts the optional parameters
96
96
  # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
97
97
  # @return [Array<ListI18nProfilesResponseInner>]
@@ -101,7 +101,7 @@ module Shipeasy::Admin::Generated
101
101
  end
102
102
 
103
103
  # List i18n profiles
104
- # Returns every locale profile in the project (e.g. &#x60;en:prod&#x60;, &#x60;fr:prod&#x60;). **Use case:** Discover which locale profiles exist before pushing keys or publishing a chunk.
104
+ # Returns every locale profile in the project (e.g. &#x60;en:prod&#x60;, &#x60;fr:prod&#x60;). **Use case:** Discover which locale profiles exist before pushing keys or publishing.
105
105
  # @param [Hash] opts the optional parameters
106
106
  # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
107
107
  # @return [Array<(Array<ListI18nProfilesResponseInner>, Integer, Hash)>] Array<ListI18nProfilesResponseInner> data, response status code and response headers
@@ -151,32 +151,28 @@ module Shipeasy::Admin::Generated
151
151
  end
152
152
 
153
153
  # Publish a profile live
154
- # Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the optional `chunk` in the body is an audit label only (it does not scope what ships). **Use case:** Ship the latest translations live after pushing/updating keys.
154
+ # Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the body takes no options. **Use case:** Ship the latest translations live after pushing/updating keys.
155
155
  # @param profile_id [String] The profile id to publish.
156
- # @param publish_i18n_profile_request [PublishI18nProfileRequest]
157
156
  # @param [Hash] opts the optional parameters
158
157
  # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
158
+ # @option opts [Object] :body
159
159
  # @return [PublishI18nProfileResponse]
160
- def publish_i18n_profile(profile_id, publish_i18n_profile_request, opts = {})
161
- data, _status_code, _headers = publish_i18n_profile_with_http_info(profile_id, publish_i18n_profile_request, opts)
160
+ def publish_i18n_profile(profile_id, opts = {})
161
+ data, _status_code, _headers = publish_i18n_profile_with_http_info(profile_id, opts)
162
162
  data
163
163
  end
164
164
 
165
165
  # Publish a profile live
166
- # Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the optional &#x60;chunk&#x60; in the body is an audit label only (it does not scope what ships). **Use case:** Ship the latest translations live after pushing/updating keys.
166
+ # Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the body takes no options. **Use case:** Ship the latest translations live after pushing/updating keys.
167
167
  # @param profile_id [String] The profile id to publish.
168
- # @param publish_i18n_profile_request [PublishI18nProfileRequest]
169
168
  # @param [Hash] opts the optional parameters
170
169
  # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
170
+ # @option opts [Object] :body
171
171
  # @return [Array<(PublishI18nProfileResponse, Integer, Hash)>] PublishI18nProfileResponse data, response status code and response headers
172
- def publish_i18n_profile_with_http_info(profile_id, publish_i18n_profile_request, opts = {})
172
+ def publish_i18n_profile_with_http_info(profile_id, opts = {})
173
173
  if @api_client.config.debugging
174
174
  @api_client.config.logger.debug 'Calling API: ProfilesApi.publish_i18n_profile ...'
175
175
  end
176
- # verify the required parameter 'publish_i18n_profile_request' is set
177
- if @api_client.config.client_side_validation && publish_i18n_profile_request.nil?
178
- fail ArgumentError, "Missing the required parameter 'publish_i18n_profile_request' when calling ProfilesApi.publish_i18n_profile"
179
- end
180
176
  # resource path
181
177
  local_var_path = '/api/admin/i18n/profiles/{profileId}/publish'.sub('{profileId}', CGI.escape(profile_id.to_s))
182
178
 
@@ -198,7 +194,7 @@ module Shipeasy::Admin::Generated
198
194
  form_params = opts[:form_params] || {}
199
195
 
200
196
  # http body (model)
201
- post_body = opts[:debug_body] || @api_client.object_to_http_body(publish_i18n_profile_request)
197
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(opts[:'body'])
202
198
 
203
199
  # return_type
204
200
  return_type = opts[:debug_return_type] || 'PublishI18nProfileResponse'
@@ -34,9 +34,6 @@ module Shipeasy::Admin::Generated
34
34
  # Owning profile id.
35
35
  attr_accessor :profile_id
36
36
 
37
- # Owning chunk (authoring grouping) id.
38
- attr_accessor :chunk_id
39
-
40
37
  # ISO-8601 timestamp of the last edit.
41
38
  attr_accessor :updated_at
42
39
 
@@ -52,7 +49,6 @@ module Shipeasy::Admin::Generated
52
49
  :'description' => :'description',
53
50
  :'variables' => :'variables',
54
51
  :'profile_id' => :'profileId',
55
- :'chunk_id' => :'chunkId',
56
52
  :'updated_at' => :'updatedAt',
57
53
  :'updated_by' => :'updatedBy'
58
54
  }
@@ -77,7 +73,6 @@ module Shipeasy::Admin::Generated
77
73
  :'description' => :'String',
78
74
  :'variables' => :'Array<String>',
79
75
  :'profile_id' => :'String',
80
- :'chunk_id' => :'String',
81
76
  :'updated_at' => :'String',
82
77
  :'updated_by' => :'String'
83
78
  }
@@ -139,10 +134,6 @@ module Shipeasy::Admin::Generated
139
134
  self.profile_id = attributes[:'profile_id']
140
135
  end
141
136
 
142
- if attributes.key?(:'chunk_id')
143
- self.chunk_id = attributes[:'chunk_id']
144
- end
145
-
146
137
  if attributes.key?(:'updated_at')
147
138
  self.updated_at = attributes[:'updated_at']
148
139
  end
@@ -223,7 +214,6 @@ module Shipeasy::Admin::Generated
223
214
  description == o.description &&
224
215
  variables == o.variables &&
225
216
  profile_id == o.profile_id &&
226
- chunk_id == o.chunk_id &&
227
217
  updated_at == o.updated_at &&
228
218
  updated_by == o.updated_by
229
219
  end
@@ -237,7 +227,7 @@ module Shipeasy::Admin::Generated
237
227
  # Calculates hash code according to all attributes.
238
228
  # @return [Integer] Hash code
239
229
  def hash
240
- [id, key, value, description, variables, profile_id, chunk_id, updated_at, updated_by].hash
230
+ [id, key, value, description, variables, profile_id, updated_at, updated_by].hash
241
231
  end
242
232
 
243
233
  # Builds the object from hash
@@ -22,9 +22,6 @@ module Shipeasy::Admin::Generated
22
22
  # Profile that was published.
23
23
  attr_accessor :profile_id
24
24
 
25
- # Audit chunk label, or `null` when none was given.
26
- attr_accessor :chunk
27
-
28
25
  # ISO-8601 timestamp of the publish.
29
26
  attr_accessor :published_at
30
27
 
@@ -73,7 +70,6 @@ module Shipeasy::Admin::Generated
73
70
  {
74
71
  :'ok' => :'ok',
75
72
  :'profile_id' => :'profile_id',
76
- :'chunk' => :'chunk',
77
73
  :'published_at' => :'published_at',
78
74
  :'version' => :'version',
79
75
  :'key_count' => :'key_count',
@@ -99,7 +95,6 @@ module Shipeasy::Admin::Generated
99
95
  {
100
96
  :'ok' => :'Boolean',
101
97
  :'profile_id' => :'String',
102
- :'chunk' => :'String',
103
98
  :'published_at' => :'String',
104
99
  :'version' => :'String',
105
100
  :'key_count' => :'Float',
@@ -113,7 +108,6 @@ module Shipeasy::Admin::Generated
113
108
  # List of attributes with nullable: true
114
109
  def self.openapi_nullable
115
110
  Set.new([
116
- :'chunk',
117
111
  ])
118
112
  end
119
113
 
@@ -145,12 +139,6 @@ module Shipeasy::Admin::Generated
145
139
  self.profile_id = nil
146
140
  end
147
141
 
148
- if attributes.key?(:'chunk')
149
- self.chunk = attributes[:'chunk']
150
- else
151
- self.chunk = nil
152
- end
153
-
154
142
  if attributes.key?(:'published_at')
155
143
  self.published_at = attributes[:'published_at']
156
144
  else
@@ -338,7 +326,6 @@ module Shipeasy::Admin::Generated
338
326
  self.class == o.class &&
339
327
  ok == o.ok &&
340
328
  profile_id == o.profile_id &&
341
- chunk == o.chunk &&
342
329
  published_at == o.published_at &&
343
330
  version == o.version &&
344
331
  key_count == o.key_count &&
@@ -357,7 +344,7 @@ module Shipeasy::Admin::Generated
357
344
  # Calculates hash code according to all attributes.
358
345
  # @return [Integer] Hash code
359
346
  def hash
360
- [ok, profile_id, chunk, published_at, version, key_count, changed, purged, kv_verified, warning].hash
347
+ [ok, profile_id, published_at, version, key_count, changed, purged, kv_verified, warning].hash
361
348
  end
362
349
 
363
350
  # Builds the object from hash
@@ -19,9 +19,6 @@ module Shipeasy::Admin::Generated
19
19
  # Target profile id to add keys to.
20
20
  attr_accessor :profile_id
21
21
 
22
- # Logical grouping the new keys are filed under. Defaults to `default`.
23
- attr_accessor :chunk
24
-
25
22
  # Keys to add. Insert-only — existing keys are reported back as `skipped`.
26
23
  attr_accessor :keys
27
24
 
@@ -29,7 +26,6 @@ module Shipeasy::Admin::Generated
29
26
  def self.attribute_map
30
27
  {
31
28
  :'profile_id' => :'profile_id',
32
- :'chunk' => :'chunk',
33
29
  :'keys' => :'keys'
34
30
  }
35
31
  end
@@ -48,7 +44,6 @@ module Shipeasy::Admin::Generated
48
44
  def self.openapi_types
49
45
  {
50
46
  :'profile_id' => :'String',
51
- :'chunk' => :'String',
52
47
  :'keys' => :'Array<PushI18nKeysRequestKeysInner>'
53
48
  }
54
49
  end
@@ -81,10 +76,6 @@ module Shipeasy::Admin::Generated
81
76
  self.profile_id = nil
82
77
  end
83
78
 
84
- if attributes.key?(:'chunk')
85
- self.chunk = attributes[:'chunk']
86
- end
87
-
88
79
  if attributes.key?(:'keys')
89
80
  if (value = attributes[:'keys']).is_a?(Array)
90
81
  self.keys = value
@@ -145,7 +136,6 @@ module Shipeasy::Admin::Generated
145
136
  return true if self.equal?(o)
146
137
  self.class == o.class &&
147
138
  profile_id == o.profile_id &&
148
- chunk == o.chunk &&
149
139
  keys == o.keys
150
140
  end
151
141
 
@@ -158,7 +148,7 @@ module Shipeasy::Admin::Generated
158
148
  # Calculates hash code according to all attributes.
159
149
  # @return [Integer] Hash code
160
150
  def hash
161
- [profile_id, chunk, keys].hash
151
+ [profile_id, keys].hash
162
152
  end
163
153
 
164
154
  # Builds the object from hash
@@ -28,17 +28,13 @@ module Shipeasy::Admin::Generated
28
28
  # Number of keys skipped (== `skipped.length`).
29
29
  attr_accessor :skipped_count
30
30
 
31
- # The chunk the keys were filed under.
32
- attr_accessor :chunk
33
-
34
31
  # Attribute mapping from ruby-style variable name to JSON key.
35
32
  def self.attribute_map
36
33
  {
37
34
  :'added' => :'added',
38
35
  :'skipped' => :'skipped',
39
36
  :'pushed_count' => :'pushed_count',
40
- :'skipped_count' => :'skipped_count',
41
- :'chunk' => :'chunk'
37
+ :'skipped_count' => :'skipped_count'
42
38
  }
43
39
  end
44
40
 
@@ -58,8 +54,7 @@ module Shipeasy::Admin::Generated
58
54
  :'added' => :'Array<String>',
59
55
  :'skipped' => :'Array<String>',
60
56
  :'pushed_count' => :'Float',
61
- :'skipped_count' => :'Float',
62
- :'chunk' => :'String'
57
+ :'skipped_count' => :'Float'
63
58
  }
64
59
  end
65
60
 
@@ -112,10 +107,6 @@ module Shipeasy::Admin::Generated
112
107
  else
113
108
  self.skipped_count = nil
114
109
  end
115
-
116
- if attributes.key?(:'chunk')
117
- self.chunk = attributes[:'chunk']
118
- end
119
110
  end
120
111
 
121
112
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -201,8 +192,7 @@ module Shipeasy::Admin::Generated
201
192
  added == o.added &&
202
193
  skipped == o.skipped &&
203
194
  pushed_count == o.pushed_count &&
204
- skipped_count == o.skipped_count &&
205
- chunk == o.chunk
195
+ skipped_count == o.skipped_count
206
196
  end
207
197
 
208
198
  # @see the `==` method
@@ -214,7 +204,7 @@ module Shipeasy::Admin::Generated
214
204
  # Calculates hash code according to all attributes.
215
205
  # @return [Integer] Hash code
216
206
  def hash
217
- [added, skipped, pushed_count, skipped_count, chunk].hash
207
+ [added, skipped, pushed_count, skipped_count].hash
218
208
  end
219
209
 
220
210
  # Builds the object from hash
@@ -153,7 +153,6 @@ require 'shipeasy_admin/models/notify_ops_request'
153
153
  require 'shipeasy_admin/models/notify_ops_response'
154
154
  require 'shipeasy_admin/models/publish_config_draft_request'
155
155
  require 'shipeasy_admin/models/publish_config_draft_response'
156
- require 'shipeasy_admin/models/publish_i18n_profile_request'
157
156
  require 'shipeasy_admin/models/publish_i18n_profile_response'
158
157
  require 'shipeasy_admin/models/push_i18n_keys_request'
159
158
  require 'shipeasy_admin/models/push_i18n_keys_request_keys_inner'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shipeasy-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shipeasy, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-20 00:00:00.000000000 Z
11
+ date: 2026-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -311,7 +311,6 @@ files:
311
311
  - lib/shipeasy_admin/models/notify_ops_response.rb
312
312
  - lib/shipeasy_admin/models/publish_config_draft_request.rb
313
313
  - lib/shipeasy_admin/models/publish_config_draft_response.rb
314
- - lib/shipeasy_admin/models/publish_i18n_profile_request.rb
315
314
  - lib/shipeasy_admin/models/publish_i18n_profile_response.rb
316
315
  - lib/shipeasy_admin/models/push_i18n_keys_request.rb
317
316
  - lib/shipeasy_admin/models/push_i18n_keys_request_keys_inner.rb
@@ -1,149 +0,0 @@
1
- =begin
2
- #Shipeasy Admin API
3
-
4
- #REST API for managing feature gates, experiments, configs, universes, and killswitches in a Shipeasy project. Authenticate with an admin SDK key (`Authorization: Bearer sdk_admin_…`) and scope every request to a project via the `X-Project-Id` header. Mint admin keys via `POST /api/admin/keys` with `type: \"admin\"`. Keys expire after 90 days; rotate with the `revoke` action.
5
-
6
- The version of the OpenAPI document: 2.0.0
7
-
8
- Generated by: https://openapi-generator.tech
9
- Generator version: 7.23.0
10
-
11
- =end
12
-
13
- require 'date'
14
- require 'time'
15
-
16
- module Shipeasy::Admin::Generated
17
- # Body for `POST /api/admin/i18n/profiles/{profileId}/publish`. The `chunk` is an audit label only.
18
- class PublishI18nProfileRequest < ApiModelBase
19
- # Optional chunk label to stamp on the audit log. Publishing is profile-wide regardless — the whole profile is snapshotted into one KV blob.
20
- attr_accessor :chunk
21
-
22
- # Attribute mapping from ruby-style variable name to JSON key.
23
- def self.attribute_map
24
- {
25
- :'chunk' => :'chunk'
26
- }
27
- end
28
-
29
- # Returns attribute mapping this model knows about
30
- def self.acceptable_attribute_map
31
- attribute_map
32
- end
33
-
34
- # Returns all the JSON keys this model knows about
35
- def self.acceptable_attributes
36
- acceptable_attribute_map.values
37
- end
38
-
39
- # Attribute type mapping.
40
- def self.openapi_types
41
- {
42
- :'chunk' => :'String'
43
- }
44
- end
45
-
46
- # List of attributes with nullable: true
47
- def self.openapi_nullable
48
- Set.new([
49
- ])
50
- end
51
-
52
- # Initializes the object
53
- # @param [Hash] attributes Model attributes in the form of hash
54
- def initialize(attributes = {})
55
- if (!attributes.is_a?(Hash))
56
- fail ArgumentError, "The input argument (attributes) must be a hash in `Shipeasy::Admin::Generated::PublishI18nProfileRequest` initialize method"
57
- end
58
-
59
- # check to see if the attribute exists and convert string to symbol for hash key
60
- acceptable_attribute_map = self.class.acceptable_attribute_map
61
- attributes = attributes.each_with_object({}) { |(k, v), h|
62
- if (!acceptable_attribute_map.key?(k.to_sym))
63
- fail ArgumentError, "`#{k}` is not a valid attribute in `Shipeasy::Admin::Generated::PublishI18nProfileRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
64
- end
65
- h[k.to_sym] = v
66
- }
67
-
68
- if attributes.key?(:'chunk')
69
- self.chunk = attributes[:'chunk']
70
- end
71
- end
72
-
73
- # Show invalid properties with the reasons. Usually used together with valid?
74
- # @return Array for valid properties with the reasons
75
- def list_invalid_properties
76
- warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
77
- invalid_properties = Array.new
78
- invalid_properties
79
- end
80
-
81
- # Check to see if the all the properties in the model are valid
82
- # @return true if the model is valid
83
- def valid?
84
- warn '[DEPRECATED] the `valid?` method is obsolete'
85
- true
86
- end
87
-
88
- # Checks equality by comparing each attribute.
89
- # @param [Object] Object to be compared
90
- def ==(o)
91
- return true if self.equal?(o)
92
- self.class == o.class &&
93
- chunk == o.chunk
94
- end
95
-
96
- # @see the `==` method
97
- # @param [Object] Object to be compared
98
- def eql?(o)
99
- self == o
100
- end
101
-
102
- # Calculates hash code according to all attributes.
103
- # @return [Integer] Hash code
104
- def hash
105
- [chunk].hash
106
- end
107
-
108
- # Builds the object from hash
109
- # @param [Hash] attributes Model attributes in the form of hash
110
- # @return [Object] Returns the model itself
111
- def self.build_from_hash(attributes)
112
- return nil unless attributes.is_a?(Hash)
113
- attributes = attributes.transform_keys(&:to_sym)
114
- transformed_hash = {}
115
- openapi_types.each_pair do |key, type|
116
- if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
117
- transformed_hash["#{key}"] = nil
118
- elsif type =~ /\AArray<(.*)>/i
119
- # check to ensure the input is an array given that the attribute
120
- # is documented as an array but the input is not
121
- if attributes[attribute_map[key]].is_a?(Array)
122
- transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
123
- end
124
- elsif !attributes[attribute_map[key]].nil?
125
- transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
126
- end
127
- end
128
- new(transformed_hash)
129
- end
130
-
131
- # Returns the object in the form of hash
132
- # @return [Hash] Returns the object in the form of hash
133
- def to_hash
134
- hash = {}
135
- self.class.attribute_map.each_pair do |attr, param|
136
- value = self.send(attr)
137
- if value.nil?
138
- is_nullable = self.class.openapi_nullable.include?(attr)
139
- next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
140
- end
141
-
142
- hash[param] = _to_hash(value)
143
- end
144
- hash
145
- end
146
-
147
- end
148
-
149
- end