turbo-train 0.2.0 → 0.4.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: 848a9382896a69a3cb1d57a569c0fd2fc3908a3599dc5338cd26acf732ee9992
4
- data.tar.gz: 1672959f0bbae5254a6f97904db3322607080ffa7da940f1553732b883d96fcb
3
+ metadata.gz: 4ad7e01b88eb8b09c2eecdffee7a4ede7b383c35573a194eec411a24674ae44e
4
+ data.tar.gz: 26289d3f1a518cc8208f7b0b1db5ad8b06b00f8489d2bfffe3fd89d90ad10a93
5
5
  SHA512:
6
- metadata.gz: 245d52890779c61021ac9b5e3877b164e93535dae1211e351dc883c1c024bd429b1ed4f48d09401d204de16cdf971ccaba1b9daea403c43ff38e47dc874039f9
7
- data.tar.gz: a66cebab47ba27702446128492dfceac83bc6ae2382bf072547681de7989f9a98c81e2e20482d3d9fa9509c4c5d01a421b443b7349afc734b326bdfe5099327a
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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uscreentv/turbo-train",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "",
5
5
  "main": "turbo-train.js",
6
6
  "type": "module",
@@ -2,7 +2,7 @@ import { Turbo } from "@hotwired/turbo-rails"
2
2
 
3
3
  export default class TurboTrain extends HTMLElement {
4
4
  static get observedAttributes() {
5
- return [ 'href', 'session', 'name' ];
5
+ return [ 'href' ];
6
6
  }
7
7
 
8
8
  constructor() {
@@ -10,7 +10,7 @@ export default class TurboTrain extends HTMLElement {
10
10
  }
11
11
 
12
12
  connectedCallback() {
13
- this.eventSource = new EventSource(`${this.href}/mercure?topic=${this.name}&authorization=${this.session}`);
13
+ this.eventSource = new EventSource(this.href);
14
14
  Turbo.connectStreamSource(this.eventSource);
15
15
  }
16
16
 
@@ -21,14 +21,6 @@ export default class TurboTrain extends HTMLElement {
21
21
  get href() {
22
22
  return this.getAttribute('href');
23
23
  }
24
-
25
- get session() {
26
- return this.getAttribute('session');
27
- }
28
-
29
- get name() {
30
- return this.getAttribute('name');
31
- }
32
24
  }
33
25
 
34
26
  if (
@@ -1 +1 @@
1
- import{Turbo as e}from"@hotwired/turbo-rails";export default class t extends HTMLElement{static get observedAttributes(){return["href","session","name"]}constructor(){super()}connectedCallback(){this.eventSource=new EventSource(`${this.href}/mercure?topic=${this.name}&authorization=${this.session}`),e.connectStreamSource(this.eventSource)}disconnectedCallback(){e.disconnectStreamSource(this.eventSource)}get href(){return this.getAttribute("href")}get session(){return this.getAttribute("session")}get name(){return this.getAttribute("name")}};"undefined"==typeof window||window.customElements.get("turbo-train-stream-source")||window.customElements.define("turbo-train-stream-source",t);
1
+ import{Turbo as e}from"@hotwired/turbo-rails";export default class t extends HTMLElement{static get observedAttributes(){return["href"]}constructor(){super()}connectedCallback(){this.eventSource=new EventSource(this.href),e.connectStreamSource(this.eventSource)}disconnectedCallback(){e.disconnectStreamSource(this.eventSource)}get href(){return this.getAttribute("href")}};"undefined"==typeof window||window.customElements.get("turbo-train-stream-source")||window.customElements.define("turbo-train-stream-source",t);
@@ -1,8 +1,6 @@
1
1
  module Turbo::Train::StreamsHelper
2
2
  def turbo_train_from(*streamables, **attributes)
3
- attributes[:name] = Turbo::Train.signed_stream_name(streamables)
4
- attributes[:session] = Turbo::Train.encode({ platform: "web" })
5
- attributes[:href] = Turbo::Train.configuration.url
3
+ attributes[:href] = Turbo::Train.server(attributes[:server]&.to_sym).listen_url(streamables, platform: "web")
6
4
  tag.turbo_train_stream_source(**attributes)
7
5
  end
8
6
  end
@@ -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
@@ -0,0 +1,27 @@
1
+ module Turbo
2
+ module Train
3
+ class BaseServer
4
+ attr_reader :configuration
5
+
6
+ def initialize(configuration)
7
+ @configuration = configuration
8
+ end
9
+
10
+ def publish(topics:, data:)
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def server_config
15
+ raise NotImplementedError
16
+ end
17
+
18
+ def publish_url
19
+ server_config.publish_url
20
+ end
21
+
22
+ def listen_url(topic, **options)
23
+ server_config.listen_url(topic, **options)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  module Turbo::Train::Broadcasts
2
- def broadcast(streamables, content:)
2
+ def broadcast(streamables, content:, server: nil)
3
3
  topics = if streamables.is_a?(Array)
4
4
  streamables.map { |s| signed_stream_name(s) }
5
5
  else
@@ -11,13 +11,13 @@ module Turbo::Train::Broadcasts
11
11
  data: content
12
12
  }
13
13
 
14
- Turbo::Train.server.publish(topics: topics, data: data)
14
+ Turbo::Train.server(server).publish(topics: topics, data: data)
15
15
  end
16
16
 
17
17
  def broadcast_action_to(*streamables, action:, target: nil, targets: nil, **rendering)
18
18
  broadcast(streamables, content: turbo_stream_action_tag(action, target: target, targets: targets, template:
19
19
  rendering.delete(:content) || rendering.delete(:html) || (rendering.any? ? render_format(:html, **rendering) : nil)
20
- ))
20
+ ), server: rendering.delete(:server))
21
21
  end
22
22
 
23
23
  def broadcast_render_to(*streamables, **rendering)
@@ -1,18 +1,96 @@
1
1
  module Turbo
2
2
  module Train
3
- class Configuration
4
- attr_accessor :mercure_domain, :publisher_key, :subscriber_key, :skip_ssl_verification
3
+ class MercureConfiguration
4
+ attr_accessor :mercure_domain, :publisher_key, :subscriber_key
5
5
 
6
6
  def initialize
7
+ super
7
8
  @mercure_domain = 'localhost'
8
9
  @publisher_key = 'test'
9
10
  @subscriber_key = 'testing'
10
- @skip_ssl_verification = Rails.env.development? || Rails.env.test?
11
11
  end
12
12
 
13
13
  def url
14
14
  "https://#{mercure_domain}/.well-known"
15
15
  end
16
+
17
+ def publish_url
18
+ "#{url}/mercure"
19
+ end
20
+
21
+ def listen_url(topic, platform: 'web')
22
+ "#{url}/mercure?topic=#{Turbo::Train.signed_stream_name(topic)}&authorization=#{jwt_auth_token({ platform: platform })}"
23
+ end
24
+
25
+ def jwt_auth_token(payload)
26
+ structured_payload = { mercure: { payload: payload } }
27
+ JWT.encode structured_payload, subscriber_key, ALGORITHM
28
+ end
29
+ end
30
+
31
+ class FanoutConfiguration
32
+ attr_accessor :fastly_api_url, :service_url, :fastly_key, :service_id
33
+
34
+ def initialize
35
+ super
36
+ @fastly_api_url = 'https://api.fastly.com'
37
+ @service_url = 'https://johnny-cage-fake-url.edgecompute.app'
38
+ @fastly_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
39
+ end
40
+
41
+ def publish_url
42
+ "#{@fastly_api_url}/service/#{@service_id}/publish/"
43
+ end
44
+
45
+ def listen_url(topic, **)
46
+ "#{service_url}/stream/sse?topic=#{Turbo::Train.signed_stream_name(topic)}"
47
+ end
48
+ end
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
+
68
+ class Configuration
69
+ attr_accessor :skip_ssl_verification, :mercure, :fanout, :anycable, :default_server
70
+
71
+ def initialize
72
+ @skip_ssl_verification = Rails.env.development? || Rails.env.test?
73
+ @mercure = nil
74
+ @fanout = nil
75
+ @anycable = nil
76
+ @default_server = :mercure
77
+ end
78
+
79
+ def server(server_name)
80
+ case server_name
81
+ when :mercure
82
+ @mercure ||= MercureConfiguration.new
83
+ yield(@mercure)
84
+ when :fanout
85
+ @fanout ||= FanoutConfiguration.new
86
+ yield(@fanout)
87
+ when :anycable
88
+ @anycable ||= AnycableConfiguration.new
89
+ yield(@anycable)
90
+ else
91
+ raise ArgumentError, "Unknown server name: #{server_name}"
92
+ end
93
+ end
16
94
  end
17
95
 
18
96
  class << self
@@ -0,0 +1,36 @@
1
+ module Turbo
2
+ module Train
3
+ class FanoutServer < BaseServer
4
+ def publish(topics:, data:)
5
+ uri = URI(server_config.publish_url)
6
+ req = Net::HTTP::Post.new(uri)
7
+ req['Fastly-Key'] = server_config.fastly_key
8
+
9
+ message = data[:data].gsub("\n", "")
10
+ payload = {items: []}
11
+
12
+ Array(topics).each do |topic|
13
+ payload[:items] << {channel: topic, formats: { 'http-stream': { content: "event: message\ndata: #{message}\n\n" } } }
14
+ end
15
+
16
+ req.body = payload.to_json
17
+
18
+ opts = {
19
+ use_ssl: uri.scheme == 'https'
20
+ }
21
+
22
+ if configuration.skip_ssl_verification
23
+ opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
24
+ end
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.fanout
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,17 +1,11 @@
1
1
  module Turbo
2
2
  module Train
3
- class Server
4
- attr_reader :configuration
5
-
6
- def initialize(configuration)
7
- @configuration = configuration
8
- end
9
-
3
+ class MercureServer < BaseServer
10
4
  def publish(topics:, data:)
11
5
  payload = { mercure: { publish: topics } }
12
- token = JWT.encode payload, configuration.publisher_key, ALGORITHM
6
+ token = JWT.encode payload, server_config.publisher_key, ALGORITHM
13
7
 
14
- uri = URI("#{configuration.url}/mercure")
8
+ uri = URI(publish_url)
15
9
 
16
10
  req = Net::HTTP::Post.new(uri)
17
11
  req['Content-Type'] = 'application/x-www-form-urlencoded'
@@ -30,6 +24,10 @@ module Turbo
30
24
  http.request(req)
31
25
  end
32
26
  end
27
+
28
+ def server_config
29
+ configuration.mercure
30
+ end
33
31
  end
34
32
  end
35
33
  end
@@ -3,13 +3,35 @@ module Turbo
3
3
  module Train
4
4
  module TestHelper
5
5
  def before_setup
6
- Turbo::Train.instance_variable_set(:@server, Turbo::Train::TestServer.new(Turbo::Train.configuration))
6
+ test_server = case ENV.fetch('TURBO_TRAIN_TEST_SERVER', 'mercure').to_sym
7
+ when :mercure
8
+ Turbo::Train::TestServer.new(Turbo::Train.mercure_server, Turbo::Train.configuration)
9
+ when :fanout
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)
13
+ else
14
+ raise "Unknown test server: #{ENV['TURBO_TRAIN_TEST_SERVER']}"
15
+ end
16
+
17
+ Turbo::Train.instance_variable_set(:@server, test_server)
7
18
  super
8
19
  end
9
20
 
10
21
  def after_teardown
22
+ test_server = case ENV.fetch('TURBO_TRAIN_TEST_SERVER', 'mercure').to_sym
23
+ when :mercure
24
+ Turbo::Train.mercure_server
25
+ when :fanout
26
+ Turbo::Train.fanout_server
27
+ when :anycable
28
+ Turbo::Train.anycable_server
29
+ else
30
+ raise "Unknown test server: #{ENV['TURBO_TRAIN_TEST_SERVER']}"
31
+ end
32
+
11
33
  super
12
- Turbo::Train.instance_variable_set(:@server, Turbo::Train::Server.new(Turbo::Train.configuration))
34
+ Turbo::Train.instance_variable_set(:@server, test_server)
13
35
  end
14
36
 
15
37
  def assert_broadcast_on(stream, data, &block)
@@ -36,6 +58,40 @@ module Turbo
36
58
 
37
59
  assert message, "No messages sent with #{data} to #{Turbo::Train.stream_name_from(stream)}"
38
60
  end
61
+
62
+ def assert_body_match(r)
63
+ if Turbo::Train.server.real_server.is_a?(Turbo::Train::FanoutServer)
64
+ assert_match "Published\n", r.body
65
+ elsif Turbo::Train.server.real_server.is_a?(Turbo::Train::MercureServer)
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'
81
+ else
82
+ raise "Unknown server type"
83
+ end
84
+ end
85
+
86
+ def assert_response_from_mercure_server(r)
87
+ assert_equal r.code, '200'
88
+ assert_match /urn:uuid:.*/, r.body
89
+ end
90
+
91
+ def assert_response_from_fanout_server(r)
92
+ assert_equal r.code, '200'
93
+ assert_match "Published\n", r.body
94
+ end
39
95
  end
40
96
  end
41
97
  end
@@ -1,11 +1,12 @@
1
1
  module Turbo
2
2
  module Train
3
- class TestServer < Server
4
- attr_reader :configuration, :channels_data
3
+ class TestServer < BaseServer
4
+ attr_reader :configuration, :channels_data, :real_server
5
5
 
6
- def initialize(configuration)
6
+ def initialize(real_server, configuration)
7
7
  @configuration = configuration
8
8
  @channels_data = {}
9
+ @real_server = real_server
9
10
  end
10
11
 
11
12
  def publish(topics:, data:)
@@ -14,7 +15,7 @@ module Turbo
14
15
  @channels_data[topic] << data[:data]
15
16
  end
16
17
 
17
- super
18
+ real_server.publish(topics: topics, data: data) if real_server
18
19
  end
19
20
 
20
21
  def broadcasts(channel)
@@ -18,8 +18,35 @@ module Turbo
18
18
  Turbo.signed_stream_verifier.generate stream_name_from(streamables)
19
19
  end
20
20
 
21
- def server
22
- @server ||= Server.new(configuration)
21
+ def server(server = nil)
22
+ @server ||= case server || configuration.default_server
23
+ when :mercure
24
+ mercure_server
25
+ when :fanout
26
+ fanout_server
27
+ when :anycable
28
+ anycable_server
29
+ else
30
+ raise ArgumentError, "Unknown server: #{server}"
31
+ end
32
+ end
33
+
34
+ def mercure_server
35
+ raise ArgumentError, "Mercure configuration is missing" unless configuration.mercure
36
+
37
+ @mercure_server ||= MercureServer.new(configuration)
38
+ end
39
+
40
+ def fanout_server
41
+ raise ArgumentError, "Fanout configuration is missing" unless configuration.fanout
42
+
43
+ @fanout_server ||= FanoutServer.new(configuration)
44
+ end
45
+
46
+ def anycable_server
47
+ raise ArgumentError, "Anycable configuration is missing" unless configuration.anycable
48
+
49
+ @anycable_server ||= AnycableServer.new(configuration)
23
50
  end
24
51
 
25
52
  def stream_name_from(streamables)
@@ -30,10 +57,6 @@ module Turbo
30
57
  end
31
58
  end
32
59
 
33
- def url
34
- configuration.url
35
- end
36
-
37
60
  private
38
61
 
39
62
  def render_format(format, **rendering)
@@ -1,5 +1,5 @@
1
1
  module Turbo
2
2
  module Train
3
- VERSION = "0.2.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
data/lib/turbo/train.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require "turbo/train/version"
2
2
  require "turbo/train/config"
3
3
  require 'turbo/train/broadcasts'
4
- require 'turbo/train/server'
4
+ require 'turbo/train/base_server'
5
+ require 'turbo/train/mercure_server'
6
+ require 'turbo/train/fanout_server'
7
+ require 'turbo/train/anycable_server'
5
8
  require 'turbo/train/test_server'
6
9
  require 'turbo/train/test_helper'
7
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.2.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-15 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,10 +84,13 @@ 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
88
+ - lib/turbo/train/base_server.rb
87
89
  - lib/turbo/train/broadcasts.rb
88
90
  - lib/turbo/train/config.rb
89
91
  - lib/turbo/train/engine.rb
90
- - lib/turbo/train/server.rb
92
+ - lib/turbo/train/fanout_server.rb
93
+ - lib/turbo/train/mercure_server.rb
91
94
  - lib/turbo/train/test_helper.rb
92
95
  - lib/turbo/train/test_server.rb
93
96
  - lib/turbo/train/train.rb