userplex 0.1.0 → 0.3.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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +1 -1
  4. data/lib/userplex/client.rb +1 -1
  5. data/lib/userplex/internal/transport/base_client.rb +7 -1
  6. data/lib/userplex/internal/transport/pooled_net_requester.rb +36 -26
  7. data/lib/userplex/internal/util.rb +5 -5
  8. data/lib/userplex/models/{event_track_params.rb → event_new_params.rb} +9 -10
  9. data/lib/userplex/models/event_new_response.rb +17 -0
  10. data/lib/userplex/models/user_identify_response.rb +4 -4
  11. data/lib/userplex/models.rb +1 -1
  12. data/lib/userplex/resources/events.rb +8 -8
  13. data/lib/userplex/version.rb +1 -1
  14. data/lib/userplex.rb +4 -2
  15. data/manifest.yaml +2 -0
  16. data/rbi/userplex/internal/transport/base_client.rbi +5 -0
  17. data/rbi/userplex/internal/transport/pooled_net_requester.rbi +6 -2
  18. data/rbi/userplex/internal/type/base_model.rbi +8 -4
  19. data/rbi/userplex/models/{event_track_params.rbi → event_new_params.rbi} +8 -10
  20. data/rbi/userplex/models/event_new_response.rbi +27 -0
  21. data/rbi/userplex/models/user_identify_response.rbi +4 -4
  22. data/rbi/userplex/models.rbi +1 -1
  23. data/rbi/userplex/resources/events.rbi +5 -6
  24. data/sig/userplex/internal/transport/base_client.rbs +2 -0
  25. data/sig/userplex/internal/transport/pooled_net_requester.rbs +4 -1
  26. data/sig/userplex/models/{event_track_params.rbs → event_new_params.rbs} +6 -6
  27. data/sig/userplex/models/event_new_response.rbs +13 -0
  28. data/sig/userplex/models.rbs +1 -1
  29. data/sig/userplex/resources/events.rbs +3 -3
  30. metadata +8 -8
  31. data/lib/userplex/models/event_track_response.rb +0 -33
  32. data/rbi/userplex/models/event_track_response.rbi +0 -52
  33. data/sig/userplex/models/event_track_response.rbs +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d3a6006aa1726e9643a159149a388583ecf3156b91fda10064397685af1d2af
4
- data.tar.gz: 6437cd93059ca4464b9a92f1e7462e200aa01ca868b6a7c513e54cbc2ad27a1c
3
+ metadata.gz: eb929982a0ce676c345b56bdf26ee45481f1ed280f6f5ec68d0ac77ed4291c60
4
+ data.tar.gz: 715c8a66b30f78347c26e2261d7c6bb2cee016c40d8b4550b07909c6af3c627f
5
5
  SHA512:
6
- metadata.gz: b103a06762433ab9a0e2a0aa77e320a5802cda16d577e9bfc6c6aa12f006aeb3b1f8e6aa9e5fa75f4f6d4c0f26fe2c18282efaef70d433aeacb18e99d4351559
7
- data.tar.gz: 1e160957f5c7562471bd43b08c5bed17126665083cfcdbf979da0a4787856477ee2a37dddf846e524539b922f15f6071f4a9cf8add46eeb7a4585db7ffaf8563
6
+ metadata.gz: 7dcb63ec75676af6c8466329acf9527b883db4d408f2839f67ae4f246fe228487caa9a3c38a933bbb0abde5e7b9cb8dacfc81d974030154359e912241922bd2e
7
+ data.tar.gz: 6099840a9b712dbb93faf7a0b24e818d79dae1062a96c6a1263a490f966c81ec95f9b0af3dee81fc763a3a1e296d07780b4fb1e625b390d6b317587ac076a09a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 (2025-12-13)
4
+
5
+ Full Changelog: [v0.2.0...v0.3.0](https://github.com/dqnamo/userplex-ruby/compare/v0.2.0...v0.3.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** manual updates ([1bc8505](https://github.com/dqnamo/userplex-ruby/commit/1bc8505bd8eb427c5e6af270da8c70af8d7a2c75))
10
+
11
+ ## 0.2.0 (2025-12-13)
12
+
13
+ Full Changelog: [v0.1.0...v0.2.0](https://github.com/dqnamo/userplex-ruby/compare/v0.1.0...v0.2.0)
14
+
15
+ ### Features
16
+
17
+ * **api:** api update ([38d5fdf](https://github.com/dqnamo/userplex-ruby/commit/38d5fdf26b03f9047a693fa55de2d89a07a74517))
18
+ * **api:** api update ([f2a58a2](https://github.com/dqnamo/userplex-ruby/commit/f2a58a206f7423ef43adcc556ca5aeedf49c22d2))
19
+ * **api:** manual updates ([f265a76](https://github.com/dqnamo/userplex-ruby/commit/f265a763bf483a0c580c674f9e14a46bda46580a))
20
+ * handle thread interrupts in the core HTTP client ([56666de](https://github.com/dqnamo/userplex-ruby/commit/56666de917a9f0da6563ea9f01d40a5bf8887e5a))
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * absolutely qualified uris should always override the default ([2af0223](https://github.com/dqnamo/userplex-ruby/commit/2af02232fad02217c0b405ff0b14248ce6e38d6d))
26
+ * better thread safety via early initializing SSL store during HTTP client creation ([e7b8153](https://github.com/dqnamo/userplex-ruby/commit/e7b81536d6e788820a3b4ff29c951a647cc8af32))
27
+ * should not reuse buffers for `IO.copy_stream` interop ([5aec1c1](https://github.com/dqnamo/userplex-ruby/commit/5aec1c1aa21eb4ef9c2f7b8bf7e373d1baeea196))
28
+
29
+
30
+ ### Chores
31
+
32
+ * bump dependency version and update sorbet types ([f77dcad](https://github.com/dqnamo/userplex-ruby/commit/f77dcad1e0e2b74aa37e142472174425388eb81f))
33
+ * explicitly require "base64" gem ([47c50c3](https://github.com/dqnamo/userplex-ruby/commit/47c50c3fac9126f56a525153edeebfc727e1898d))
34
+ * ignore linter error for tests having large collections ([792c73c](https://github.com/dqnamo/userplex-ruby/commit/792c73c12aa1183d50b7e67c09a11d8f8997b524))
35
+
3
36
  ## 0.1.0 (2025-10-02)
4
37
 
5
38
  Full Changelog: [v0.0.1...v0.1.0](https://github.com/dqnamo/userplex-ruby/compare/v0.0.1...v0.1.0)
data/README.md CHANGED
@@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
15
15
  <!-- x-release-please-start-version -->
16
16
 
17
17
  ```ruby
18
- gem "userplex", "~> 0.1.0"
18
+ gem "userplex", "~> 0.3.0"
19
19
  ```
20
20
 
21
21
  <!-- x-release-please-end -->
@@ -57,7 +57,7 @@ module Userplex
57
57
  initial_retry_delay: self.class::DEFAULT_INITIAL_RETRY_DELAY,
58
58
  max_retry_delay: self.class::DEFAULT_MAX_RETRY_DELAY
59
59
  )
60
- base_url ||= "http://localhost:3000"
60
+ base_url ||= "https://userplex.app"
61
61
 
62
62
  if api_key.nil?
63
63
  raise ArgumentError.new("api_key is required, and can be set via environ: \"USERPLEX_API_KEY\"")
@@ -201,7 +201,8 @@ module Userplex
201
201
  self.class::PLATFORM_HEADERS,
202
202
  {
203
203
  "accept" => "application/json",
204
- "content-type" => "application/json"
204
+ "content-type" => "application/json",
205
+ "user-agent" => user_agent
205
206
  },
206
207
  headers
207
208
  )
@@ -219,6 +220,11 @@ module Userplex
219
220
  # @return [Hash{String=>String}]
220
221
  private def auth_headers = {}
221
222
 
223
+ # @api private
224
+ #
225
+ # @return [String]
226
+ private def user_agent = "#{self.class.name}/Ruby #{Userplex::VERSION}"
227
+
222
228
  # @api private
223
229
  #
224
230
  # @return [String]
@@ -16,10 +16,11 @@ module Userplex
16
16
  class << self
17
17
  # @api private
18
18
  #
19
+ # @param cert_store [OpenSSL::X509::Store]
19
20
  # @param url [URI::Generic]
20
21
  #
21
22
  # @return [Net::HTTP]
22
- def connect(url)
23
+ def connect(cert_store:, url:)
23
24
  port =
24
25
  case [url.port, url.scheme]
25
26
  in [Integer, _]
@@ -33,6 +34,8 @@ module Userplex
33
34
  Net::HTTP.new(url.host, port).tap do
34
35
  _1.use_ssl = %w[https wss].include?(url.scheme)
35
36
  _1.max_retries = 0
37
+
38
+ (_1.cert_store = cert_store) if _1.use_ssl?
36
39
  end
37
40
  end
38
41
 
@@ -102,7 +105,7 @@ module Userplex
102
105
  pool =
103
106
  @mutex.synchronize do
104
107
  @pools[origin] ||= ConnectionPool.new(size: @size) do
105
- self.class.connect(url)
108
+ self.class.connect(cert_store: @cert_store, url: url)
106
109
  end
107
110
  end
108
111
 
@@ -128,40 +131,48 @@ module Userplex
128
131
  url, deadline = request.fetch_values(:url, :deadline)
129
132
 
130
133
  req = nil
131
- eof = false
132
134
  finished = false
133
- closing = nil
134
135
 
135
136
  # rubocop:disable Metrics/BlockLength
136
137
  enum = Enumerator.new do |y|
137
138
  next if finished
138
139
 
139
140
  with_pool(url, deadline: deadline) do |conn|
140
- req, closing = self.class.build_request(request) do
141
- self.class.calibrate_socket_timeout(conn, deadline)
142
- end
143
-
144
- self.class.calibrate_socket_timeout(conn, deadline)
145
- unless conn.started?
146
- conn.keep_alive_timeout = self.class::KEEP_ALIVE_TIMEOUT
147
- conn.start
148
- end
141
+ eof = false
142
+ closing = nil
143
+ ::Thread.handle_interrupt(Object => :never) do
144
+ ::Thread.handle_interrupt(Object => :immediate) do
145
+ req, closing = self.class.build_request(request) do
146
+ self.class.calibrate_socket_timeout(conn, deadline)
147
+ end
149
148
 
150
- self.class.calibrate_socket_timeout(conn, deadline)
151
- conn.request(req) do |rsp|
152
- y << [req, rsp]
153
- break if finished
154
-
155
- rsp.read_body do |bytes|
156
- y << bytes.force_encoding(Encoding::BINARY)
157
- break if finished
149
+ self.class.calibrate_socket_timeout(conn, deadline)
150
+ unless conn.started?
151
+ conn.keep_alive_timeout = self.class::KEEP_ALIVE_TIMEOUT
152
+ conn.start
153
+ end
158
154
 
159
155
  self.class.calibrate_socket_timeout(conn, deadline)
156
+ conn.request(req) do |rsp|
157
+ y << [req, rsp]
158
+ break if finished
159
+
160
+ rsp.read_body do |bytes|
161
+ y << bytes.force_encoding(Encoding::BINARY)
162
+ break if finished
163
+
164
+ self.class.calibrate_socket_timeout(conn, deadline)
165
+ end
166
+ eof = true
167
+ end
168
+ end
169
+ ensure
170
+ begin
171
+ conn.finish if !eof && conn&.started?
172
+ ensure
173
+ closing&.call
160
174
  end
161
- eof = true
162
175
  end
163
- ensure
164
- conn.finish if !eof && conn&.started?
165
176
  end
166
177
  rescue Timeout::Error
167
178
  raise Userplex::Errors::APITimeoutError.new(url: url, request: req)
@@ -174,8 +185,6 @@ module Userplex
174
185
  body = Userplex::Internal::Util.fused_enum(enum, external: true) do
175
186
  finished = true
176
187
  loop { enum.next }
177
- ensure
178
- closing&.call
179
188
  end
180
189
  [Integer(response.code), response, body]
181
190
  end
@@ -186,6 +195,7 @@ module Userplex
186
195
  def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS)
187
196
  @mutex = Mutex.new
188
197
  @size = size
198
+ @cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths)
189
199
  @pools = {}
190
200
  end
191
201
 
@@ -346,8 +346,9 @@ module Userplex
346
346
  base_path, base_query = lhs.fetch_values(:path, :query)
347
347
  slashed = base_path.end_with?("/") ? base_path : "#{base_path}/"
348
348
 
349
- parsed_path, parsed_query = parse_uri(rhs.fetch(:path)).fetch_values(:path, :query)
350
- override = URI::Generic.build(**rhs.slice(:scheme, :host, :port), path: parsed_path)
349
+ merged = {**parse_uri(rhs.fetch(:path)), **rhs.except(:path, :query)}
350
+ parsed_path, parsed_query = merged.fetch_values(:path, :query)
351
+ override = URI::Generic.build(**merged.slice(:scheme, :host, :port), path: parsed_path)
351
352
 
352
353
  joined = URI.join(URI::Generic.build(lhs.except(:path, :query)), slashed, override)
353
354
  query = deep_merge(
@@ -473,10 +474,9 @@ module Userplex
473
474
  # @return [Enumerable<String>]
474
475
  def writable_enum(&blk)
475
476
  Enumerator.new do |y|
476
- buf = String.new
477
477
  y.define_singleton_method(:write) do
478
- self << buf.replace(_1)
479
- buf.bytesize
478
+ self << _1.dup
479
+ _1.bytesize
480
480
  end
481
481
 
482
482
  blk.call(y)
@@ -2,25 +2,24 @@
2
2
 
3
3
  module Userplex
4
4
  module Models
5
- # @see Userplex::Resources::Events#track
6
- class EventTrackParams < Userplex::Internal::Type::BaseModel
5
+ # @see Userplex::Resources::Events#new
6
+ class EventNewParams < Userplex::Internal::Type::BaseModel
7
7
  extend Userplex::Internal::Type::RequestParameters::Converter
8
8
  include Userplex::Internal::Type::RequestParameters
9
9
 
10
- # @!attribute event
11
- # Event name
10
+ # @!attribute name
12
11
  #
13
12
  # @return [String]
14
- required :event, String
13
+ required :name, String
15
14
 
16
15
  # @!attribute user_id
17
16
  # External user ID
18
17
  #
19
18
  # @return [String]
20
- required :user_id, String, api_name: :userId
19
+ required :user_id, String
21
20
 
22
21
  # @!attribute properties
23
- # Event metadata
22
+ # Additional event properties
24
23
  #
25
24
  # @return [Hash{Symbol=>Object, nil}, nil]
26
25
  optional :properties, Userplex::Internal::Type::HashOf[Userplex::Internal::Type::Unknown, nil?: true]
@@ -31,12 +30,12 @@ module Userplex
31
30
  # @return [Time, nil]
32
31
  optional :timestamp, Time
33
32
 
34
- # @!method initialize(event:, user_id:, properties: nil, timestamp: nil, request_options: {})
35
- # @param event [String] Event name
33
+ # @!method initialize(name:, user_id:, properties: nil, timestamp: nil, request_options: {})
34
+ # @param name [String]
36
35
  #
37
36
  # @param user_id [String] External user ID
38
37
  #
39
- # @param properties [Hash{Symbol=>Object, nil}] Event metadata
38
+ # @param properties [Hash{Symbol=>Object, nil}] Additional event properties
40
39
  #
41
40
  # @param timestamp [Time] Event timestamp (ISO 8601)
42
41
  #
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Userplex
4
+ module Models
5
+ # @see Userplex::Resources::Events#new
6
+ class EventNewResponse < Userplex::Internal::Type::BaseModel
7
+ # @!attribute success
8
+ # Operation success status
9
+ #
10
+ # @return [Boolean]
11
+ required :success, Userplex::Internal::Type::Boolean
12
+
13
+ # @!method initialize(success:)
14
+ # @param success [Boolean] Operation success status
15
+ end
16
+ end
17
+ end
@@ -5,21 +5,21 @@ module Userplex
5
5
  # @see Userplex::Resources::Users#identify
6
6
  class UserIdentifyResponse < Userplex::Internal::Type::BaseModel
7
7
  # @!attribute success
8
- # Whether the operation was successful
8
+ # Operation success status
9
9
  #
10
10
  # @return [Boolean]
11
11
  required :success, Userplex::Internal::Type::Boolean
12
12
 
13
13
  # @!attribute user_id
14
- # The identified user ID
14
+ # The ID of the identified user
15
15
  #
16
16
  # @return [String]
17
17
  required :user_id, String, api_name: :userId
18
18
 
19
19
  # @!method initialize(success:, user_id:)
20
- # @param success [Boolean] Whether the operation was successful
20
+ # @param success [Boolean] Operation success status
21
21
  #
22
- # @param user_id [String] The identified user ID
22
+ # @param user_id [String] The ID of the identified user
23
23
  end
24
24
  end
25
25
  end
@@ -39,7 +39,7 @@ module Userplex
39
39
  mod.define_sorbet_constant!(const) { T.type_alias { mod.to_sorbet_type } }
40
40
  end
41
41
 
42
- EventTrackParams = Userplex::Models::EventTrackParams
42
+ EventNewParams = Userplex::Models::EventNewParams
43
43
 
44
44
  UserIdentifyParams = Userplex::Models::UserIdentifyParams
45
45
  end
@@ -6,28 +6,28 @@ module Userplex
6
6
  # Creates or uses an existing event and records an event occurrence for an end
7
7
  # user. Requires a valid API key for authentication.
8
8
  #
9
- # @overload track(event:, user_id:, properties: nil, timestamp: nil, request_options: {})
9
+ # @overload new(name:, user_id:, properties: nil, timestamp: nil, request_options: {})
10
10
  #
11
- # @param event [String] Event name
11
+ # @param name [String]
12
12
  #
13
13
  # @param user_id [String] External user ID
14
14
  #
15
- # @param properties [Hash{Symbol=>Object, nil}] Event metadata
15
+ # @param properties [Hash{Symbol=>Object, nil}] Additional event properties
16
16
  #
17
17
  # @param timestamp [Time] Event timestamp (ISO 8601)
18
18
  #
19
19
  # @param request_options [Userplex::RequestOptions, Hash{Symbol=>Object}, nil]
20
20
  #
21
- # @return [Userplex::Models::EventTrackResponse]
21
+ # @return [Userplex::Models::EventNewResponse]
22
22
  #
23
- # @see Userplex::Models::EventTrackParams
24
- def track(params)
25
- parsed, options = Userplex::EventTrackParams.dump_request(params)
23
+ # @see Userplex::Models::EventNewParams
24
+ def new(params)
25
+ parsed, options = Userplex::EventNewParams.dump_request(params)
26
26
  @client.request(
27
27
  method: :post,
28
28
  path: "api/event",
29
29
  body: parsed,
30
- model: Userplex::Models::EventTrackResponse,
30
+ model: Userplex::Models::EventNewResponse,
31
31
  options: options
32
32
  )
33
33
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Userplex
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/userplex.rb CHANGED
@@ -3,12 +3,14 @@
3
3
  # Standard libraries.
4
4
  # rubocop:disable Lint/RedundantRequireStatement
5
5
  require "English"
6
+ require "base64"
6
7
  require "cgi"
7
8
  require "date"
8
9
  require "erb"
9
10
  require "etc"
10
11
  require "json"
11
12
  require "net/http"
13
+ require "openssl"
12
14
  require "pathname"
13
15
  require "rbconfig"
14
16
  require "securerandom"
@@ -50,8 +52,8 @@ require_relative "userplex/errors"
50
52
  require_relative "userplex/internal/transport/base_client"
51
53
  require_relative "userplex/internal/transport/pooled_net_requester"
52
54
  require_relative "userplex/client"
53
- require_relative "userplex/models/event_track_params"
54
- require_relative "userplex/models/event_track_response"
55
+ require_relative "userplex/models/event_new_params"
56
+ require_relative "userplex/models/event_new_response"
55
57
  require_relative "userplex/models/user_identify_params"
56
58
  require_relative "userplex/models/user_identify_response"
57
59
  require_relative "userplex/models"
data/manifest.yaml CHANGED
@@ -1,11 +1,13 @@
1
1
  dependencies:
2
2
  - English
3
+ - base64
3
4
  - cgi
4
5
  - date
5
6
  - erb
6
7
  - etc
7
8
  - json
8
9
  - net/http
10
+ - openssl
9
11
  - pathname
10
12
  - rbconfig
11
13
  - securerandom
@@ -176,6 +176,11 @@ module Userplex
176
176
  private def auth_headers
177
177
  end
178
178
 
179
+ # @api private
180
+ sig { returns(String) }
181
+ private def user_agent
182
+ end
183
+
179
184
  # @api private
180
185
  sig { returns(String) }
181
186
  private def generate_idempotency_key
@@ -26,8 +26,12 @@ module Userplex
26
26
 
27
27
  class << self
28
28
  # @api private
29
- sig { params(url: URI::Generic).returns(Net::HTTP) }
30
- def connect(url)
29
+ sig do
30
+ params(cert_store: OpenSSL::X509::Store, url: URI::Generic).returns(
31
+ Net::HTTP
32
+ )
33
+ end
34
+ def connect(cert_store:, url:)
31
35
  end
32
36
 
33
37
  # @api private
@@ -31,7 +31,7 @@ module Userplex
31
31
  #
32
32
  # Assumes superclass fields are totally defined before fields are accessed /
33
33
  # defined on subclasses.
34
- sig { params(child: T.self_type).void }
34
+ sig { params(child: Userplex::Internal::Type::BaseModel).void }
35
35
  def inherited(child)
36
36
  end
37
37
 
@@ -274,9 +274,13 @@ module Userplex
274
274
 
275
275
  # Create a new instance of a model.
276
276
  sig do
277
- params(data: T.any(T::Hash[Symbol, T.anything], T.self_type)).returns(
278
- T.attached_class
279
- )
277
+ params(
278
+ data:
279
+ T.any(
280
+ T::Hash[Symbol, T.anything],
281
+ Userplex::Internal::Type::BaseModel
282
+ )
283
+ ).returns(T.attached_class)
280
284
  end
281
285
  def self.new(data = {})
282
286
  end
@@ -2,24 +2,23 @@
2
2
 
3
3
  module Userplex
4
4
  module Models
5
- class EventTrackParams < Userplex::Internal::Type::BaseModel
5
+ class EventNewParams < Userplex::Internal::Type::BaseModel
6
6
  extend Userplex::Internal::Type::RequestParameters::Converter
7
7
  include Userplex::Internal::Type::RequestParameters
8
8
 
9
9
  OrHash =
10
10
  T.type_alias do
11
- T.any(Userplex::EventTrackParams, Userplex::Internal::AnyHash)
11
+ T.any(Userplex::EventNewParams, Userplex::Internal::AnyHash)
12
12
  end
13
13
 
14
- # Event name
15
14
  sig { returns(String) }
16
- attr_accessor :event
15
+ attr_accessor :name
17
16
 
18
17
  # External user ID
19
18
  sig { returns(String) }
20
19
  attr_accessor :user_id
21
20
 
22
- # Event metadata
21
+ # Additional event properties
23
22
  sig { returns(T.nilable(T::Hash[Symbol, T.nilable(T.anything)])) }
24
23
  attr_reader :properties
25
24
 
@@ -35,7 +34,7 @@ module Userplex
35
34
 
36
35
  sig do
37
36
  params(
38
- event: String,
37
+ name: String,
39
38
  user_id: String,
40
39
  properties: T::Hash[Symbol, T.nilable(T.anything)],
41
40
  timestamp: Time,
@@ -43,11 +42,10 @@ module Userplex
43
42
  ).returns(T.attached_class)
44
43
  end
45
44
  def self.new(
46
- # Event name
47
- event:,
45
+ name:,
48
46
  # External user ID
49
47
  user_id:,
50
- # Event metadata
48
+ # Additional event properties
51
49
  properties: nil,
52
50
  # Event timestamp (ISO 8601)
53
51
  timestamp: nil,
@@ -58,7 +56,7 @@ module Userplex
58
56
  sig do
59
57
  override.returns(
60
58
  {
61
- event: String,
59
+ name: String,
62
60
  user_id: String,
63
61
  properties: T::Hash[Symbol, T.nilable(T.anything)],
64
62
  timestamp: Time,
@@ -0,0 +1,27 @@
1
+ # typed: strong
2
+
3
+ module Userplex
4
+ module Models
5
+ class EventNewResponse < Userplex::Internal::Type::BaseModel
6
+ OrHash =
7
+ T.type_alias do
8
+ T.any(Userplex::Models::EventNewResponse, Userplex::Internal::AnyHash)
9
+ end
10
+
11
+ # Operation success status
12
+ sig { returns(T::Boolean) }
13
+ attr_accessor :success
14
+
15
+ sig { params(success: T::Boolean).returns(T.attached_class) }
16
+ def self.new(
17
+ # Operation success status
18
+ success:
19
+ )
20
+ end
21
+
22
+ sig { override.returns({ success: T::Boolean }) }
23
+ def to_hash
24
+ end
25
+ end
26
+ end
27
+ end
@@ -11,11 +11,11 @@ module Userplex
11
11
  )
12
12
  end
13
13
 
14
- # Whether the operation was successful
14
+ # Operation success status
15
15
  sig { returns(T::Boolean) }
16
16
  attr_accessor :success
17
17
 
18
- # The identified user ID
18
+ # The ID of the identified user
19
19
  sig { returns(String) }
20
20
  attr_accessor :user_id
21
21
 
@@ -23,9 +23,9 @@ module Userplex
23
23
  params(success: T::Boolean, user_id: String).returns(T.attached_class)
24
24
  end
25
25
  def self.new(
26
- # Whether the operation was successful
26
+ # Operation success status
27
27
  success:,
28
- # The identified user ID
28
+ # The ID of the identified user
29
29
  user_id:
30
30
  )
31
31
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strong
2
2
 
3
3
  module Userplex
4
- EventTrackParams = Userplex::Models::EventTrackParams
4
+ EventNewParams = Userplex::Models::EventNewParams
5
5
 
6
6
  UserIdentifyParams = Userplex::Models::UserIdentifyParams
7
7
  end
@@ -7,19 +7,18 @@ module Userplex
7
7
  # user. Requires a valid API key for authentication.
8
8
  sig do
9
9
  params(
10
- event: String,
10
+ name: String,
11
11
  user_id: String,
12
12
  properties: T::Hash[Symbol, T.nilable(T.anything)],
13
13
  timestamp: Time,
14
14
  request_options: Userplex::RequestOptions::OrHash
15
- ).returns(Userplex::Models::EventTrackResponse)
15
+ ).returns(Userplex::Models::EventNewResponse)
16
16
  end
17
- def track(
18
- # Event name
19
- event:,
17
+ def new(
18
+ name:,
20
19
  # External user ID
21
20
  user_id:,
22
- # Event metadata
21
+ # Additional event properties
23
22
  properties: nil,
24
23
  # Event timestamp (ISO 8601)
25
24
  timestamp: nil,
@@ -87,6 +87,8 @@ module Userplex
87
87
 
88
88
  private def auth_headers: -> ::Hash[String, String]
89
89
 
90
+ private def user_agent: -> String
91
+
90
92
  private def generate_idempotency_key: -> String
91
93
 
92
94
  private def build_request: (
@@ -17,7 +17,10 @@ module Userplex
17
17
 
18
18
  DEFAULT_MAX_CONNECTIONS: Integer
19
19
 
20
- def self.connect: (URI::Generic url) -> top
20
+ def self.connect: (
21
+ cert_store: OpenSSL::X509::Store,
22
+ url: URI::Generic
23
+ ) -> top
21
24
 
22
25
  def self.calibrate_socket_timeout: (top conn, Float deadline) -> void
23
26
 
@@ -1,19 +1,19 @@
1
1
  module Userplex
2
2
  module Models
3
- type event_track_params =
3
+ type event_new_params =
4
4
  {
5
- event: String,
5
+ name: String,
6
6
  user_id: String,
7
7
  properties: ::Hash[Symbol, top?],
8
8
  timestamp: Time
9
9
  }
10
10
  & Userplex::Internal::Type::request_parameters
11
11
 
12
- class EventTrackParams < Userplex::Internal::Type::BaseModel
12
+ class EventNewParams < Userplex::Internal::Type::BaseModel
13
13
  extend Userplex::Internal::Type::RequestParameters::Converter
14
14
  include Userplex::Internal::Type::RequestParameters
15
15
 
16
- attr_accessor event: String
16
+ attr_accessor name: String
17
17
 
18
18
  attr_accessor user_id: String
19
19
 
@@ -26,7 +26,7 @@ module Userplex
26
26
  def timestamp=: (Time) -> Time
27
27
 
28
28
  def initialize: (
29
- event: String,
29
+ name: String,
30
30
  user_id: String,
31
31
  ?properties: ::Hash[Symbol, top?],
32
32
  ?timestamp: Time,
@@ -34,7 +34,7 @@ module Userplex
34
34
  ) -> void
35
35
 
36
36
  def to_hash: -> {
37
- event: String,
37
+ name: String,
38
38
  user_id: String,
39
39
  properties: ::Hash[Symbol, top?],
40
40
  timestamp: Time,
@@ -0,0 +1,13 @@
1
+ module Userplex
2
+ module Models
3
+ type event_new_response = { success: bool }
4
+
5
+ class EventNewResponse < Userplex::Internal::Type::BaseModel
6
+ attr_accessor success: bool
7
+
8
+ def initialize: (success: bool) -> void
9
+
10
+ def to_hash: -> { success: bool }
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Userplex
2
- class EventTrackParams = Userplex::Models::EventTrackParams
2
+ class EventNewParams = Userplex::Models::EventNewParams
3
3
 
4
4
  class UserIdentifyParams = Userplex::Models::UserIdentifyParams
5
5
  end
@@ -1,13 +1,13 @@
1
1
  module Userplex
2
2
  module Resources
3
3
  class Events
4
- def track: (
5
- event: String,
4
+ def new: (
5
+ name: String,
6
6
  user_id: String,
7
7
  ?properties: ::Hash[Symbol, top?],
8
8
  ?timestamp: Time,
9
9
  ?request_options: Userplex::request_opts
10
- ) -> Userplex::Models::EventTrackResponse
10
+ ) -> Userplex::Models::EventNewResponse
11
11
 
12
12
  def initialize: (client: Userplex::Client) -> void
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: userplex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Userplex
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-02 00:00:00.000000000 Z
11
+ date: 2025-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool
@@ -55,8 +55,8 @@ files:
55
55
  - lib/userplex/internal/type/unknown.rb
56
56
  - lib/userplex/internal/util.rb
57
57
  - lib/userplex/models.rb
58
- - lib/userplex/models/event_track_params.rb
59
- - lib/userplex/models/event_track_response.rb
58
+ - lib/userplex/models/event_new_params.rb
59
+ - lib/userplex/models/event_new_response.rb
60
60
  - lib/userplex/models/user_identify_params.rb
61
61
  - lib/userplex/models/user_identify_response.rb
62
62
  - lib/userplex/request_options.rb
@@ -83,8 +83,8 @@ files:
83
83
  - rbi/userplex/internal/type/unknown.rbi
84
84
  - rbi/userplex/internal/util.rbi
85
85
  - rbi/userplex/models.rbi
86
- - rbi/userplex/models/event_track_params.rbi
87
- - rbi/userplex/models/event_track_response.rbi
86
+ - rbi/userplex/models/event_new_params.rbi
87
+ - rbi/userplex/models/event_new_response.rbi
88
88
  - rbi/userplex/models/user_identify_params.rbi
89
89
  - rbi/userplex/models/user_identify_response.rbi
90
90
  - rbi/userplex/request_options.rbi
@@ -110,8 +110,8 @@ files:
110
110
  - sig/userplex/internal/type/unknown.rbs
111
111
  - sig/userplex/internal/util.rbs
112
112
  - sig/userplex/models.rbs
113
- - sig/userplex/models/event_track_params.rbs
114
- - sig/userplex/models/event_track_response.rbs
113
+ - sig/userplex/models/event_new_params.rbs
114
+ - sig/userplex/models/event_new_response.rbs
115
115
  - sig/userplex/models/user_identify_params.rbs
116
116
  - sig/userplex/models/user_identify_response.rbs
117
117
  - sig/userplex/request_options.rbs
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Userplex
4
- module Models
5
- # @see Userplex::Resources::Events#track
6
- class EventTrackResponse < Userplex::Internal::Type::BaseModel
7
- # @!attribute event_id
8
- # The event ID
9
- #
10
- # @return [String]
11
- required :event_id, String, api_name: :eventId
12
-
13
- # @!attribute occurrence_id
14
- # The event occurrence ID
15
- #
16
- # @return [String]
17
- required :occurrence_id, String, api_name: :occurrenceId
18
-
19
- # @!attribute success
20
- # Whether the operation was successful
21
- #
22
- # @return [Boolean]
23
- required :success, Userplex::Internal::Type::Boolean
24
-
25
- # @!method initialize(event_id:, occurrence_id:, success:)
26
- # @param event_id [String] The event ID
27
- #
28
- # @param occurrence_id [String] The event occurrence ID
29
- #
30
- # @param success [Boolean] Whether the operation was successful
31
- end
32
- end
33
- end
@@ -1,52 +0,0 @@
1
- # typed: strong
2
-
3
- module Userplex
4
- module Models
5
- class EventTrackResponse < Userplex::Internal::Type::BaseModel
6
- OrHash =
7
- T.type_alias do
8
- T.any(
9
- Userplex::Models::EventTrackResponse,
10
- Userplex::Internal::AnyHash
11
- )
12
- end
13
-
14
- # The event ID
15
- sig { returns(String) }
16
- attr_accessor :event_id
17
-
18
- # The event occurrence ID
19
- sig { returns(String) }
20
- attr_accessor :occurrence_id
21
-
22
- # Whether the operation was successful
23
- sig { returns(T::Boolean) }
24
- attr_accessor :success
25
-
26
- sig do
27
- params(
28
- event_id: String,
29
- occurrence_id: String,
30
- success: T::Boolean
31
- ).returns(T.attached_class)
32
- end
33
- def self.new(
34
- # The event ID
35
- event_id:,
36
- # The event occurrence ID
37
- occurrence_id:,
38
- # Whether the operation was successful
39
- success:
40
- )
41
- end
42
-
43
- sig do
44
- override.returns(
45
- { event_id: String, occurrence_id: String, success: T::Boolean }
46
- )
47
- end
48
- def to_hash
49
- end
50
- end
51
- end
52
- end
@@ -1,22 +0,0 @@
1
- module Userplex
2
- module Models
3
- type event_track_response =
4
- { event_id: String, occurrence_id: String, success: bool }
5
-
6
- class EventTrackResponse < Userplex::Internal::Type::BaseModel
7
- attr_accessor event_id: String
8
-
9
- attr_accessor occurrence_id: String
10
-
11
- attr_accessor success: bool
12
-
13
- def initialize: (
14
- event_id: String,
15
- occurrence_id: String,
16
- success: bool
17
- ) -> void
18
-
19
- def to_hash: -> { event_id: String, occurrence_id: String, success: bool }
20
- end
21
- end
22
- end