turbo-train 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8f44643f00dc3a0c248fd990ffc95631a63bf9df53768ecb8e740a5dda4bc45
4
- data.tar.gz: 92d303ac07e6402c9dc9ce4f71dcb9c56345c78980184c59692b7c7508daaf4d
3
+ metadata.gz: 4ad7e01b88eb8b09c2eecdffee7a4ede7b383c35573a194eec411a24674ae44e
4
+ data.tar.gz: 26289d3f1a518cc8208f7b0b1db5ad8b06b00f8489d2bfffe3fd89d90ad10a93
5
5
  SHA512:
6
- metadata.gz: 229de6bb9a249571e03daddb1b1288aa9138ddee9a1711538961bce90a6bc02e92ba2b83dd4f0062a78c75bb27cf92202126a40034303c10ae127bb9786eb34d
7
- data.tar.gz: f2cd4ebef097ffc2d66fd6ec081537ae57b54c7318c132ed0cf508f26dfe03cdc2b13d3386839c209269062c344f9eb127ff8728593a7b82807db8407cb70dd2
6
+ metadata.gz: 5f000e44026c4e4d675eb5e6fa09ffab8b1f370ffd8f242f8582276542b9f5860b4ee8513a9f9f8350a4f5094b44d032894a10ca044f1d78c710e6a9ce42bad1
7
+ data.tar.gz: 84fd805f8e22ef1f1686cbe50a0cc7e4c3753f9f1f91225fab5c73be392d2a710acf2e9fe563166c1e28af7e9cf56e5b1f06a8c277d89486b7199f876ee951fd
data/README.md CHANGED
@@ -4,19 +4,19 @@
4
4
 
5
5
  <img align="right" width="220" title="Turbo::Train logo"
6
6
  src="https://user-images.githubusercontent.com/3010927/210603861-4b265489-a4a7-4d2a-bceb-40ceccebcd96.jpg">
7
-
8
7
 
9
- Real-time page updates for your Rails app over SSE with [Mercure](https://mercure.rocks) and [Hotwire Turbo](https://turbo.hotwired.dev/handbook/streams#integration-with-server-side-frameworks).
8
+
9
+ Real-time page updates for your Rails app over SSE with [Mercure](https://mercure.rocks), [Fanout Cloud](https://fanout.io/cloud) or [AnyCable](https://anycable.io/) and [Hotwire Turbo](https://turbo.hotwired.dev/handbook/streams#integration-with-server-side-frameworks).
10
10
 
11
11
  * **Uses [SSE](https://html.spec.whatwg.org/multipage/server-sent-events.html)**. No more websockets, client libraries, JS code and handling reconnects. Just an HTTP connection. Let the [browser](https://caniuse.com/eventsource) do the work.
12
12
  * **Seamless Hotwire integration.** Use it exactly like [ActionCable](https://github.com/hotwired/turbo-rails#come-alive-with-turbo-streams). Drop-in replacement for `broadcast_action_to` and usual helpers.
13
- * **Simple.** Get running in minutes, scale easily in production 🚀
13
+ * **Simple.** Get running in minutes, scale easily in production 🚀
14
14
 
15
15
  ## Before your proceed
16
16
 
17
17
  Using this gem requires some knowledge of ActionCable and broadcasting turbo streams. Turbo::Train is designed to mimic those, so it is highly recommended to first try the original to understand the concept.
18
18
 
19
- You can start [here](https://hotwired.dev/) and proceed with the [Turbo Handbook](https://turbo.hotwired.dev/handbook/introduction). One of its chapters will be covering [Turbo Streams](https://turbo.hotwired.dev/handbook/streams). Specifically [this section](https://turbo.hotwired.dev/handbook/streams#integration-with-server-side-frameworks) would be the main prerequisite to understanding what this gem is about: it covers [Broadcastable](https://github.com/hotwired/turbo-rails/blob/main/app/models/concerns/turbo/broadcastable.rb) and the overall idea of working with Mercure.
19
+ You can start [here](https://hotwired.dev/) and proceed with the [Turbo Handbook](https://turbo.hotwired.dev/handbook/introduction). One of its chapters will be covering [Turbo Streams](https://turbo.hotwired.dev/handbook/streams). Specifically [this section](https://turbo.hotwired.dev/handbook/streams#integration-with-server-side-frameworks) would be the main prerequisite to understanding what this gem is about: it covers [Broadcastable](https://github.com/hotwired/turbo-rails/blob/main/app/models/concerns/turbo/broadcastable.rb) and the overall idea of working with Mercure or Fanout Cloud.
20
20
 
21
21
  ## Prerequisites
22
22
 
@@ -40,7 +40,8 @@ Instructions for Rails 6
40
40
  1. Install [turbo-rails](https://github.com/hotwired/turbo-rails#installation)
41
41
  2. Repeat steps for Rails 7 above
42
42
 
43
- ### Step 2. Mercure
43
+ ### Step 2. Server
44
+ #### Mercure
44
45
 
45
46
  Mercure is installed as a plugin to [Caddy](https://github.com/caddyserver/caddy) server. For mac users everything is pretty easy:
46
47
 
@@ -57,6 +58,21 @@ Now you are ready to run 🚀
57
58
  ```
58
59
  caddy run
59
60
  ```
61
+ #### Fanout Cloud
62
+
63
+ We only support the cloud version today. To use [Fanout](https://fanout.io/cloud/) you must purchase a paid account with a contract for Fastly's services.
64
+
65
+ #### Fanout self-hosted (Pushpin)
66
+
67
+ Coming soon.
68
+
69
+ #### AnyCable
70
+
71
+ ```
72
+ anycable-go --host=localhost --port=8080 --sse --broadcast_adapter=http --broadcast_key=test --public_streams --noauth
73
+ ```
74
+
75
+ Coming soon.
60
76
 
61
77
  ## Usage
62
78
 
@@ -98,17 +114,35 @@ You have the same options as original Rails Turbo helpers: rendering partials, p
98
114
 
99
115
  ## Configuration
100
116
 
101
- To specify different Mercure server settings, please adjust the generated `config/initializers/turbo_train.rb` file:
117
+ To specify different Mercure or Fanout server settings, please adjust the generated `config/initializers/turbo_train.rb` file:
102
118
 
103
119
  ```ruby
104
120
  Turbo::Train.configure do |config|
105
- config.mercure_domain = ...
106
- config.publisher_key = ...
107
- config.subscriber_key = ...
121
+ config.skip_ssl_verification = true # Development only; don't do this in production
122
+ config.default_server = :fanout # Default value is :mercure
123
+
124
+ config.server :mercure do |mercure|
125
+ mercure.mercure_domain = ...
126
+ mercure.publisher_key = ...
127
+ mercure.subscriber_key = ...
128
+ end
129
+
130
+ config.server :fanout do |fanout|
131
+ fanout.service_url = ...
132
+ fanout.service_id = ...
133
+ fanout.fastly_key = ...
134
+ end
135
+
136
+ config.server :anycable do |fanout|
137
+ ac.anycable_url = 'http://0.0.0.0:8080'
138
+ ac.broadcast_key = 'test'
139
+ end
108
140
  end
109
141
  ```
110
142
 
111
- * Your SSE will connect to `https://#{configuration.mercure_domain}/.well-known`.
143
+ ### Mercure
144
+
145
+ * Your SSE will connect to `https://#{configuration.mercure_domain}/.well-known`.
112
146
  * The publisher/subscriber key correspond to the [configuration](https://mercure.rocks/docs/hub/config) or your Mercure server.
113
147
 
114
148
  By default, these are set to `localhost`/`test`/`testing` to match the configuration of the local development server from the installation instructions above.
@@ -2,10 +2,20 @@ say "Creating initializer"
2
2
  create_file Rails.root.join("config/initializers/turbo_train.rb") do
3
3
  %{
4
4
  Turbo::Train.configure do |config|
5
- config.mercure_domain = 'localhost'
6
- config.publisher_key = 'testing'
7
- config.subscriber_key = 'test'
8
5
  config.skip_ssl_verification = true # Development only; don't do this in production
6
+ config.default_server = # Default value is :mercure
7
+
8
+ config.server :mercure do |mercure|
9
+ mercure.mercure_domain = 'localhost'
10
+ mercure.publisher_key = 'testing'
11
+ mercure.subscriber_key = 'test'
12
+ end
13
+
14
+ config.server :fanout do |fanout|
15
+ fanout.service_url = ''
16
+ fanout.service_id = ''
17
+ fanout.fastly_key = ''
18
+ end
9
19
  end
10
20
  }
11
21
  end
@@ -0,0 +1,36 @@
1
+ module Turbo
2
+ module Train
3
+ class AnycableServer < BaseServer
4
+ def publish(topics:, data:)
5
+ uri = URI(server_config.publish_url)
6
+ req = Net::HTTP::Post.new(uri)
7
+ req['Content-Type'] = 'application/json'
8
+ req['Authorization'] = "Bearer #{server_config.broadcast_key}"
9
+
10
+ message = data[:data].gsub("\n", '')
11
+
12
+ opts = {
13
+ use_ssl: uri.scheme == 'https'
14
+ }
15
+
16
+ payload = []
17
+
18
+ Array(topics).each do |topic|
19
+ payload << { stream: topic, data: message }
20
+ end
21
+
22
+ req.body = payload.to_json
23
+
24
+ opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if configuration.skip_ssl_verification
25
+
26
+ Net::HTTP.start(uri.host, uri.port, opts) do |http|
27
+ http.request(req)
28
+ end
29
+ end
30
+
31
+ def server_config
32
+ configuration.anycable
33
+ end
34
+ end
35
+ end
36
+ end
@@ -47,13 +47,32 @@ module Turbo
47
47
  end
48
48
  end
49
49
 
50
+ class AnycableConfiguration
51
+ attr_accessor :anycable_url, :broadcast_key
52
+
53
+ def initialize
54
+ super
55
+ @anycable_url = 'http://localhost:8080'
56
+ @broadcast_key = 'test'
57
+ end
58
+
59
+ def publish_url
60
+ "#{@anycable_url}/_broadcast"
61
+ end
62
+
63
+ def listen_url(topic, **)
64
+ "#{@anycable_url}/events?stream=#{Turbo::Train.signed_stream_name(topic)}"
65
+ end
66
+ end
67
+
50
68
  class Configuration
51
- attr_accessor :skip_ssl_verification, :mercure, :fanout, :default_server
69
+ attr_accessor :skip_ssl_verification, :mercure, :fanout, :anycable, :default_server
52
70
 
53
71
  def initialize
54
72
  @skip_ssl_verification = Rails.env.development? || Rails.env.test?
55
73
  @mercure = nil
56
74
  @fanout = nil
75
+ @anycable = nil
57
76
  @default_server = :mercure
58
77
  end
59
78
 
@@ -65,6 +84,9 @@ module Turbo
65
84
  when :fanout
66
85
  @fanout ||= FanoutConfiguration.new
67
86
  yield(@fanout)
87
+ when :anycable
88
+ @anycable ||= AnycableConfiguration.new
89
+ yield(@anycable)
68
90
  else
69
91
  raise ArgumentError, "Unknown server name: #{server_name}"
70
92
  end
@@ -8,6 +8,8 @@ module Turbo
8
8
  Turbo::Train::TestServer.new(Turbo::Train.mercure_server, Turbo::Train.configuration)
9
9
  when :fanout
10
10
  Turbo::Train::TestServer.new(Turbo::Train.fanout_server, Turbo::Train.configuration)
11
+ when :anycable
12
+ Turbo::Train::TestServer.new(Turbo::Train.anycable_server, Turbo::Train.configuration)
11
13
  else
12
14
  raise "Unknown test server: #{ENV['TURBO_TRAIN_TEST_SERVER']}"
13
15
  end
@@ -22,6 +24,8 @@ module Turbo
22
24
  Turbo::Train.mercure_server
23
25
  when :fanout
24
26
  Turbo::Train.fanout_server
27
+ when :anycable
28
+ Turbo::Train.anycable_server
25
29
  else
26
30
  raise "Unknown test server: #{ENV['TURBO_TRAIN_TEST_SERVER']}"
27
31
  end
@@ -60,6 +64,20 @@ module Turbo
60
64
  assert_match "Published\n", r.body
61
65
  elsif Turbo::Train.server.real_server.is_a?(Turbo::Train::MercureServer)
62
66
  assert_match /urn:uuid:.*/, r.body
67
+ elsif Turbo::Train.server.real_server.is_a?(Turbo::Train::AnycableServer)
68
+ assert_match '', r.body
69
+ else
70
+ raise "Unknown server type"
71
+ end
72
+ end
73
+
74
+ def assert_code_ok(r)
75
+ if Turbo::Train.server.real_server.is_a?(Turbo::Train::FanoutServer)
76
+ assert_equal r.code, '200'
77
+ elsif Turbo::Train.server.real_server.is_a?(Turbo::Train::MercureServer)
78
+ assert_equal r.code, '200'
79
+ elsif Turbo::Train.server.real_server.is_a?(Turbo::Train::AnycableServer)
80
+ assert_equal r.code, '201'
63
81
  else
64
82
  raise "Unknown server type"
65
83
  end
@@ -24,6 +24,8 @@ module Turbo
24
24
  mercure_server
25
25
  when :fanout
26
26
  fanout_server
27
+ when :anycable
28
+ anycable_server
27
29
  else
28
30
  raise ArgumentError, "Unknown server: #{server}"
29
31
  end
@@ -41,6 +43,12 @@ module Turbo
41
43
  @fanout_server ||= FanoutServer.new(configuration)
42
44
  end
43
45
 
46
+ def anycable_server
47
+ raise ArgumentError, "Anycable configuration is missing" unless configuration.anycable
48
+
49
+ @anycable_server ||= AnycableServer.new(configuration)
50
+ end
51
+
44
52
  def stream_name_from(streamables)
45
53
  if streamables.is_a?(Array)
46
54
  streamables.map { |streamable| stream_name_from(streamable) }.join(":")
@@ -1,5 +1,5 @@
1
1
  module Turbo
2
2
  module Train
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
data/lib/turbo/train.rb CHANGED
@@ -4,6 +4,7 @@ require 'turbo/train/broadcasts'
4
4
  require 'turbo/train/base_server'
5
5
  require 'turbo/train/mercure_server'
6
6
  require 'turbo/train/fanout_server'
7
+ require 'turbo/train/anycable_server'
7
8
  require 'turbo/train/test_server'
8
9
  require 'turbo/train/test_helper'
9
10
  require "turbo/train/engine"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbo-train
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Savrov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-05-29 00:00:00.000000000 Z
12
+ date: 2024-05-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -84,6 +84,7 @@ files:
84
84
  - lib/install/install_node.rb
85
85
  - lib/tasks/install_tasks.rake
86
86
  - lib/turbo/train.rb
87
+ - lib/turbo/train/anycable_server.rb
87
88
  - lib/turbo/train/base_server.rb
88
89
  - lib/turbo/train/broadcasts.rb
89
90
  - lib/turbo/train/config.rb