post-for-me 0.1.0.pre.alpha.9 → 0.1.0.pre.alpha.10

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: 01ccb7d44dae77373838e7b5fe9d286727f29d5b0cb28c147c4d5f2db24f8755
4
- data.tar.gz: 80cf5a0f6c198eb315344dfeec272c8987552d5ec63ac8054b10b6c99787d577
3
+ metadata.gz: f08a4f8e227f322ee7b0d29a30c415f41d249ab7522893a827f436897b1d618c
4
+ data.tar.gz: 58515896f263b04c98c2251a662b52a283c3d7a67b677361a4375391c080987b
5
5
  SHA512:
6
- metadata.gz: 3040c94c71317b8e81ec5b45fd1b06ed7214b291b158d9ae292d229ce1ad7404b359c6424294702923d4d2edec71dbe5c14542e4c5ae101f189ef07f2dd730ef
7
- data.tar.gz: a294fa51eff7716dd53392b2defcc295b559c5fddbc3d857f4274d6bcfd52189b105c8d0e247c25820e601670f76ef5c8ab319c423ce777eebf74e1dc69aa14a
6
+ metadata.gz: 7fb396a4a563b2dc101a3226c6cae480249ce4eabfc32320d2c70fdad267c27078636da74a1d4fd5716533c6873e6b3d3effb0f8fdc36d1959cc8114f39bbdd2
7
+ data.tar.gz: 1f15d35794ada3b12e1839818c8ef5d1f6cf885f170f480a341eb9a95d3ad247da2efaa22b4c5b111ff8f56e620852d4a824382db6d8cce0b7da6b199008d303
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.10 (2025-11-05)
4
+
5
+ Full Changelog: [v0.1.0-alpha.9...v0.1.0-alpha.10](https://github.com/DayMoonDevelopment/post-for-me-ruby/compare/v0.1.0-alpha.9...v0.1.0-alpha.10)
6
+
7
+ ### Features
8
+
9
+ * **api:** api update ([129bf08](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/129bf0849de95a151f9fb756f8ae18feee7ca85b))
10
+ * handle thread interrupts in the core HTTP client ([67a9096](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/67a9096a8cdf6200f708a3f58063405bceb7f7ca))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * absolutely qualified uris should always override the default ([2f8e594](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/2f8e594d99b3c79d12b6e6dcb50d1928df5af7c0))
16
+ * better thread safety via early initializing SSL store during HTTP client creation ([b9e0151](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/b9e01515a5ff7e201462dded310b312800a0276d))
17
+ * should not reuse buffers for `IO.copy_stream` interop ([4a8bedd](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/4a8bedda953dabf110a699a183b62d338713b44f))
18
+
19
+
20
+ ### Chores
21
+
22
+ * bump dependency version and update sorbet types ([936adc6](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/936adc671f5a30e84245daa790743dd9183b0a17))
23
+ * ignore linter error for tests having large collections ([8b60378](https://github.com/DayMoonDevelopment/post-for-me-ruby/commit/8b60378131cc5ff32c7dc2e96aa3d7db84280d6b))
24
+
3
25
  ## 0.1.0-alpha.9 (2025-10-03)
4
26
 
5
27
  Full Changelog: [v0.1.0-alpha.8...v0.1.0-alpha.9](https://github.com/DayMoonDevelopment/post-for-me-ruby/compare/v0.1.0-alpha.8...v0.1.0-alpha.9)
data/README.md CHANGED
@@ -17,7 +17,7 @@ To use this gem, install via Bundler by adding the following to your application
17
17
  <!-- x-release-please-start-version -->
18
18
 
19
19
  ```ruby
20
- gem "post-for-me", "~> 0.1.0.pre.alpha.9"
20
+ gem "post-for-me", "~> 0.1.0.pre.alpha.10"
21
21
  ```
22
22
 
23
23
  <!-- x-release-please-end -->
@@ -201,7 +201,8 @@ module PostForMe
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 PostForMe
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 #{PostForMe::VERSION}"
227
+
222
228
  # @api private
223
229
  #
224
230
  # @return [String]
@@ -16,10 +16,11 @@ module PostForMe
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 PostForMe
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 PostForMe
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 PostForMe
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 PostForMe::Errors::APITimeoutError.new(url: url, request: req)
@@ -174,8 +185,6 @@ module PostForMe
174
185
  body = PostForMe::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 PostForMe
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 PostForMe
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 PostForMe
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)
@@ -40,6 +40,12 @@ module PostForMe
40
40
  # @return [String]
41
41
  required :platform, String
42
42
 
43
+ # @!attribute profile_photo_url
44
+ # The platform's profile photo of the social account
45
+ #
46
+ # @return [String, nil]
47
+ required :profile_photo_url, String, nil?: true
48
+
43
49
  # @!attribute refresh_token
44
50
  # The refresh token of the social account
45
51
  #
@@ -70,7 +76,7 @@ module PostForMe
70
76
  # @return [String, nil]
71
77
  required :username, String, nil?: true
72
78
 
73
- # @!method initialize(id:, access_token:, access_token_expires_at:, external_id:, metadata:, platform:, refresh_token:, refresh_token_expires_at:, status:, user_id:, username:)
79
+ # @!method initialize(id:, access_token:, access_token_expires_at:, external_id:, metadata:, platform:, profile_photo_url:, refresh_token:, refresh_token_expires_at:, status:, user_id:, username:)
74
80
  # @param id [String] The unique identifier of the social account
75
81
  #
76
82
  # @param access_token [String] The access token of the social account
@@ -83,6 +89,8 @@ module PostForMe
83
89
  #
84
90
  # @param platform [String] The platform of the social account
85
91
  #
92
+ # @param profile_photo_url [String, nil] The platform's profile photo of the social account
93
+ #
86
94
  # @param refresh_token [String, nil] The refresh token of the social account
87
95
  #
88
96
  # @param refresh_token_expires_at [Time, nil] The refresh token expiration date of the social account
@@ -40,6 +40,12 @@ module PostForMe
40
40
  # @return [String]
41
41
  required :platform, String
42
42
 
43
+ # @!attribute profile_photo_url
44
+ # The platform's profile photo of the social account
45
+ #
46
+ # @return [String, nil]
47
+ required :profile_photo_url, String, nil?: true
48
+
43
49
  # @!attribute refresh_token
44
50
  # The refresh token of the social account
45
51
  #
@@ -70,7 +76,7 @@ module PostForMe
70
76
  # @return [String, nil]
71
77
  required :username, String, nil?: true
72
78
 
73
- # @!method initialize(id:, access_token:, access_token_expires_at:, external_id:, metadata:, platform:, refresh_token:, refresh_token_expires_at:, status:, user_id:, username:)
79
+ # @!method initialize(id:, access_token:, access_token_expires_at:, external_id:, metadata:, platform:, profile_photo_url:, refresh_token:, refresh_token_expires_at:, status:, user_id:, username:)
74
80
  # @param id [String] The unique identifier of the social account
75
81
  #
76
82
  # @param access_token [String] The access token of the social account
@@ -83,6 +89,8 @@ module PostForMe
83
89
  #
84
90
  # @param platform [String] The platform of the social account
85
91
  #
92
+ # @param profile_photo_url [String, nil] The platform's profile photo of the social account
93
+ #
86
94
  # @param refresh_token [String, nil] The refresh token of the social account
87
95
  #
88
96
  # @param refresh_token_expires_at [Time, nil] The refresh token expiration date of the social account
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PostForMe
4
- VERSION = "0.1.0.pre.alpha.9"
4
+ VERSION = "0.1.0.pre.alpha.10"
5
5
  end
data/lib/post_for_me.rb CHANGED
@@ -9,6 +9,7 @@ require "erb"
9
9
  require "etc"
10
10
  require "json"
11
11
  require "net/http"
12
+ require "openssl"
12
13
  require "pathname"
13
14
  require "rbconfig"
14
15
  require "securerandom"
data/manifest.yaml CHANGED
@@ -6,6 +6,7 @@ dependencies:
6
6
  - etc
7
7
  - json
8
8
  - net/http
9
+ - openssl
9
10
  - pathname
10
11
  - rbconfig
11
12
  - securerandom
@@ -176,6 +176,11 @@ module PostForMe
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 PostForMe
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 PostForMe
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: PostForMe::Internal::Type::BaseModel).void }
35
35
  def inherited(child)
36
36
  end
37
37
 
@@ -276,9 +276,13 @@ module PostForMe
276
276
 
277
277
  # Create a new instance of a model.
278
278
  sig do
279
- params(data: T.any(T::Hash[Symbol, T.anything], T.self_type)).returns(
280
- T.attached_class
281
- )
279
+ params(
280
+ data:
281
+ T.any(
282
+ T::Hash[Symbol, T.anything],
283
+ PostForMe::Internal::Type::BaseModel
284
+ )
285
+ ).returns(T.attached_class)
282
286
  end
283
287
  def self.new(data = {})
284
288
  end
@@ -32,6 +32,10 @@ module PostForMe
32
32
  sig { returns(String) }
33
33
  attr_accessor :platform
34
34
 
35
+ # The platform's profile photo of the social account
36
+ sig { returns(T.nilable(String)) }
37
+ attr_accessor :profile_photo_url
38
+
35
39
  # The refresh token of the social account
36
40
  sig { returns(T.nilable(String)) }
37
41
  attr_accessor :refresh_token
@@ -60,6 +64,7 @@ module PostForMe
60
64
  external_id: T.nilable(String),
61
65
  metadata: T.nilable(T.anything),
62
66
  platform: String,
67
+ profile_photo_url: T.nilable(String),
63
68
  refresh_token: T.nilable(String),
64
69
  refresh_token_expires_at: T.nilable(Time),
65
70
  status: PostForMe::SocialAccount::Status::OrSymbol,
@@ -80,6 +85,8 @@ module PostForMe
80
85
  metadata:,
81
86
  # The platform of the social account
82
87
  platform:,
88
+ # The platform's profile photo of the social account
89
+ profile_photo_url:,
83
90
  # The refresh token of the social account
84
91
  refresh_token:,
85
92
  # The refresh token expiration date of the social account
@@ -102,6 +109,7 @@ module PostForMe
102
109
  external_id: T.nilable(String),
103
110
  metadata: T.nilable(T.anything),
104
111
  platform: String,
112
+ profile_photo_url: T.nilable(String),
105
113
  refresh_token: T.nilable(String),
106
114
  refresh_token_expires_at: T.nilable(Time),
107
115
  status: PostForMe::SocialAccount::Status::TaggedSymbol,
@@ -35,6 +35,10 @@ module PostForMe
35
35
  sig { returns(String) }
36
36
  attr_accessor :platform
37
37
 
38
+ # The platform's profile photo of the social account
39
+ sig { returns(T.nilable(String)) }
40
+ attr_accessor :profile_photo_url
41
+
38
42
  # The refresh token of the social account
39
43
  sig { returns(T.nilable(String)) }
40
44
  attr_accessor :refresh_token
@@ -67,6 +71,7 @@ module PostForMe
67
71
  external_id: T.nilable(String),
68
72
  metadata: T.nilable(T.anything),
69
73
  platform: String,
74
+ profile_photo_url: T.nilable(String),
70
75
  refresh_token: T.nilable(String),
71
76
  refresh_token_expires_at: T.nilable(Time),
72
77
  status:
@@ -88,6 +93,8 @@ module PostForMe
88
93
  metadata:,
89
94
  # The platform of the social account
90
95
  platform:,
96
+ # The platform's profile photo of the social account
97
+ profile_photo_url:,
91
98
  # The refresh token of the social account
92
99
  refresh_token:,
93
100
  # The refresh token expiration date of the social account
@@ -110,6 +117,7 @@ module PostForMe
110
117
  external_id: T.nilable(String),
111
118
  metadata: T.nilable(T.anything),
112
119
  platform: String,
120
+ profile_photo_url: T.nilable(String),
113
121
  refresh_token: T.nilable(String),
114
122
  refresh_token_expires_at: T.nilable(Time),
115
123
  status:
@@ -87,6 +87,8 @@ module PostForMe
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 PostForMe
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
 
@@ -8,6 +8,7 @@ module PostForMe
8
8
  external_id: String?,
9
9
  metadata: top?,
10
10
  platform: String,
11
+ profile_photo_url: String?,
11
12
  refresh_token: String?,
12
13
  refresh_token_expires_at: Time?,
13
14
  status: PostForMe::Models::SocialAccount::status,
@@ -28,6 +29,8 @@ module PostForMe
28
29
 
29
30
  attr_accessor platform: String
30
31
 
32
+ attr_accessor profile_photo_url: String?
33
+
31
34
  attr_accessor refresh_token: String?
32
35
 
33
36
  attr_accessor refresh_token_expires_at: Time?
@@ -45,6 +48,7 @@ module PostForMe
45
48
  external_id: String?,
46
49
  metadata: top?,
47
50
  platform: String,
51
+ profile_photo_url: String?,
48
52
  refresh_token: String?,
49
53
  refresh_token_expires_at: Time?,
50
54
  status: PostForMe::Models::SocialAccount::status,
@@ -59,6 +63,7 @@ module PostForMe
59
63
  external_id: String?,
60
64
  metadata: top?,
61
65
  platform: String,
66
+ profile_photo_url: String?,
62
67
  refresh_token: String?,
63
68
  refresh_token_expires_at: Time?,
64
69
  status: PostForMe::Models::SocialAccount::status,
@@ -8,6 +8,7 @@ module PostForMe
8
8
  external_id: String?,
9
9
  metadata: top?,
10
10
  platform: String,
11
+ profile_photo_url: String?,
11
12
  refresh_token: String?,
12
13
  refresh_token_expires_at: Time?,
13
14
  status: PostForMe::Models::SocialAccountDisconnectResponse::status,
@@ -28,6 +29,8 @@ module PostForMe
28
29
 
29
30
  attr_accessor platform: String
30
31
 
32
+ attr_accessor profile_photo_url: String?
33
+
31
34
  attr_accessor refresh_token: String?
32
35
 
33
36
  attr_accessor refresh_token_expires_at: Time?
@@ -45,6 +48,7 @@ module PostForMe
45
48
  external_id: String?,
46
49
  metadata: top?,
47
50
  platform: String,
51
+ profile_photo_url: String?,
48
52
  refresh_token: String?,
49
53
  refresh_token_expires_at: Time?,
50
54
  status: PostForMe::Models::SocialAccountDisconnectResponse::status,
@@ -59,6 +63,7 @@ module PostForMe
59
63
  external_id: String?,
60
64
  metadata: top?,
61
65
  platform: String,
66
+ profile_photo_url: String?,
62
67
  refresh_token: String?,
63
68
  refresh_token_expires_at: Time?,
64
69
  status: PostForMe::Models::SocialAccountDisconnectResponse::status,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: post-for-me
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.alpha.9
4
+ version: 0.1.0.pre.alpha.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Post For Me
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-03 00:00:00.000000000 Z
11
+ date: 2025-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool