turbo-train 0.2.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: 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