datastar 1.0.2 → 1.0.4

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: 885e73382637f598ee1feeea492556e30f4dea1dcdd9eae1627649a8dbadc0bc
4
- data.tar.gz: 2945bedd152787c39ae3843f2cf2c937bdba3d7d8a0ea0f6b9a4d0ac2bf34a18
3
+ metadata.gz: eccb35f1a82b7afa5eb234e7232be3cbe4c217ff69a9a1893df9ae2e320e2e67
4
+ data.tar.gz: 5195f98a824736ed1e8a8de5f712b15f55747ea72562032db566579039eca8a4
5
5
  SHA512:
6
- metadata.gz: bc0bb40586da1e305aa87b6c4b830baeaacd671e259aa7105a043ceaebab8659c23df8b12665d1a1bf1b9ca09aa518e275cdc30b5978627da6d818e818cc14f8
7
- data.tar.gz: 5ae556f5ce37d9805fe920c68ab5164464ec6fabbd2f4355d9d17139dbf381bd0dde65b5c33bf8f0e4de6eda431ece4cc7b20a41080f3362fea9f7daedad580d
6
+ metadata.gz: 9c653351bfa89796728e63a6e2e3d3e6aaa28c856632673503174a12436f9043dfb6ade50cd18cea5994f772021cc2fc29e08764fca0600fa0043b9c84213bea
7
+ data.tar.gz: e632142778821a5134c74456a9d704e8d5585eba648c4919d0a15a03f64329c1a2c135757bff6382d4407863a2afb0f0aa66e6a50123ce5ec4ad076020ba5727
data/README.md CHANGED
@@ -245,6 +245,21 @@ You can also set it to a different number (in seconds)
245
245
  heartbeat: 0.5
246
246
  ```
247
247
 
248
+ #### Per-stream override
249
+
250
+ The `#stream` method also accepts a `heartbeat:` keyword that overrides the constructor-level setting for a single call. This is useful when a dispatcher is generally configured with a heartbeat but a particular response doesn't need one (e.g. a one-shot update). The previous value is restored once the call returns.
251
+
252
+ ```ruby
253
+ datastar = Datastar.new(request:, response:) # default heartbeat
254
+
255
+ # Disable heartbeat for this single response
256
+ datastar.stream(heartbeat: false) do |sse|
257
+ sse.patch_elements(html)
258
+ end
259
+ ```
260
+
261
+ The one-shot helpers (`#patch_elements`, `#remove_elements`, `#patch_signals`, `#remove_signals`, `#execute_script`, `#redirect`) use this internally to avoid spawning a heartbeat thread for a single message.
262
+
248
263
  #### Manual connection check
249
264
 
250
265
  If you want to check connection status on your own, you can disable the heartbeat and use `sse.check_connection!`, which will close the connection and trigger callbacks if the client is disconnected.
@@ -28,7 +28,7 @@ module Datastar
28
28
  HTTP_ACCEPT = 'HTTP_ACCEPT'
29
29
  HTTP1 = 'HTTP/1.1'
30
30
 
31
- attr_reader :request, :response
31
+ attr_reader :request, :response, :heartbeat
32
32
 
33
33
  # @option request [Rack::Request] the request object
34
34
  # @option response [Rack::Response, nil] the response object
@@ -56,7 +56,10 @@ module Datastar
56
56
  @queue = nil
57
57
  @executor = executor
58
58
  @view_context = view_context
59
- @request = request
59
+ # Dup the env so that Rack middleware restores (e.g. Rack::URLMap's
60
+ # ensure block resetting SCRIPT_NAME/PATH_INFO after app.call returns)
61
+ # don't affect async stream fibers that run after the handler returns.
62
+ @request = Rack::Request.new(request.env.dup)
60
63
  @response = Rack::Response.new(BLANK_BODY, 200, response&.headers || {})
61
64
  @response.content_type = SSE_CONTENT_TYPE
62
65
  @response.headers['Cache-Control'] = 'no-cache'
@@ -137,7 +140,7 @@ module Datastar
137
140
  # @param elements [String, #call(view_context: Object) => Object] the HTML elements or object
138
141
  # @param options [Hash] the options to send with the message
139
142
  def patch_elements(elements, options = BLANK_OPTIONS)
140
- stream_no_heartbeat do |sse|
143
+ stream(heartbeat: false) do |sse|
141
144
  sse.patch_elements(elements, options)
142
145
  end
143
146
  end
@@ -152,7 +155,7 @@ module Datastar
152
155
  # @param selector [String] a CSS selector for the fragment to remove
153
156
  # @param options [Hash] the options to send with the message
154
157
  def remove_elements(selector, options = BLANK_OPTIONS)
155
- stream_no_heartbeat do |sse|
158
+ stream(heartbeat: false) do |sse|
156
159
  sse.remove_elements(selector, options)
157
160
  end
158
161
  end
@@ -166,7 +169,7 @@ module Datastar
166
169
  # @param signals [Hash, String] signals to merge
167
170
  # @param options [Hash] the options to send with the message
168
171
  def patch_signals(signals, options = BLANK_OPTIONS)
169
- stream_no_heartbeat do |sse|
172
+ stream(heartbeat: false) do |sse|
170
173
  sse.patch_signals(signals, options)
171
174
  end
172
175
  end
@@ -180,7 +183,7 @@ module Datastar
180
183
  # @param paths [Array<String>] object paths to the signals to remove
181
184
  # @param options [Hash] the options to send with the message
182
185
  def remove_signals(paths, options = BLANK_OPTIONS)
183
- stream_no_heartbeat do |sse|
186
+ stream(heartbeat: false) do |sse|
184
187
  sse.remove_signals(paths, options)
185
188
  end
186
189
  end
@@ -194,7 +197,7 @@ module Datastar
194
197
  # @param script [String] the script to execute
195
198
  # @param options [Hash] the options to send with the message
196
199
  def execute_script(script, options = BLANK_OPTIONS)
197
- stream_no_heartbeat do |sse|
200
+ stream(heartbeat: false) do |sse|
198
201
  sse.execute_script(script, options)
199
202
  end
200
203
  end
@@ -204,7 +207,7 @@ module Datastar
204
207
  #
205
208
  # @param url [String] the URL or path to redirect to
206
209
  def redirect(url)
207
- stream_no_heartbeat do |sse|
210
+ stream(heartbeat: false) do |sse|
208
211
  sse.redirect(url)
209
212
  end
210
213
  end
@@ -245,10 +248,24 @@ module Datastar
245
248
  # By default, the built-in Rack finalzer just returns the resposne Array which can be used by any Rack handler.
246
249
  # On Rails, the Rails controller response is set to this objects streaming response.
247
250
  #
251
+ # A per-call +heartbeat:+ keyword overrides the constructor-level heartbeat
252
+ # for the duration of this call. Pass +false+ to disable heartbeat for a
253
+ # one-shot message (e.g. a single +patch_elements+), or a Numeric interval
254
+ # to enable it. The previous value is restored once the call returns.
255
+ # @example Disable heartbeat for a single response
256
+ #
257
+ # datastar.stream(heartbeat: false) do |sse|
258
+ # sse.patch_elements(html)
259
+ # end
260
+ #
248
261
  # @param streamer [#call(ServerSentEventGenerator), nil] a callable to call with the generator
262
+ # @param heartbeat [Numeric, false] override the heartbeat interval for this call, or +false+ to disable
249
263
  # @yieldparam sse [ServerSentEventGenerator] the generator object
250
264
  # @return [Object] depends on the finalize callback
251
- def stream(streamer = nil, &block)
265
+ def stream(streamer = nil, heartbeat: @heartbeat, &block)
266
+ heartbeat_was = @heartbeat
267
+ @heartbeat = heartbeat
268
+
252
269
  streamer ||= block
253
270
  @streamers << streamer
254
271
  if @heartbeat && !@heartbeat_on
@@ -269,18 +286,12 @@ module Datastar
269
286
 
270
287
  @response.body = body
271
288
  @finalize.call(@view_context, @response)
289
+ ensure
290
+ @heartbeat = heartbeat_was
272
291
  end
273
292
 
274
293
  private
275
294
 
276
- def stream_no_heartbeat(&block)
277
- was = @heartbeat
278
- @heartbeat = false
279
- stream(&block).tap do
280
- @heartbeat = was
281
- end
282
- end
283
-
284
295
  # Produce a response body for a single stream
285
296
  # In this case, the SSE generator can write directly to the socket
286
297
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Datastar
4
- VERSION = '1.0.2'
4
+ VERSION = '1.0.4'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datastar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis