anycable-rails-core 1.4.4 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/lib/action_cable/subscription_adapter/any_cable.rb +1 -1
- data/lib/anycable/rails/action_cable_ext/broadcast_options.rb +5 -0
- data/lib/anycable/rails/action_cable_ext/channel.rb +9 -1
- data/lib/anycable/rails/action_cable_ext/signed_streams.rb +31 -0
- data/lib/anycable/rails/channel_state.rb +12 -4
- data/lib/anycable/rails/compatibility.rb +1 -1
- data/lib/anycable/rails/config.rb +6 -2
- data/lib/anycable/rails/connections/serializable_identification.rb +2 -2
- data/lib/anycable/rails/ext/jwt.rb +35 -0
- data/lib/anycable/rails/ext.rb +10 -0
- data/lib/anycable/rails/helper.rb +36 -0
- data/lib/anycable/rails/object_serializer.rb +19 -0
- data/lib/anycable/rails/pubsub_channel.rb +22 -0
- data/lib/anycable/rails/railtie.rb +25 -0
- data/lib/anycable/rails/version.rb +1 -1
- data/lib/anycable/rails.rb +12 -20
- data/lib/generators/anycable/bin/USAGE +10 -0
- data/lib/generators/anycable/bin/bin_generator.rb +52 -0
- data/lib/generators/anycable/bin/templates/bin/anycable-go.tt +22 -0
- data/lib/generators/anycable/download/USAGE +2 -2
- data/lib/generators/anycable/download/download_generator.rb +3 -3
- data/lib/generators/anycable/setup/USAGE +0 -6
- data/lib/generators/anycable/setup/setup_generator.rb +165 -149
- data/lib/generators/anycable/setup/templates/bin/anycable-go.tt +3 -3
- data/lib/generators/anycable/setup/templates/config/anycable.yml.tt +11 -4
- metadata +13 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e23407a3fe0b10d54fdb4c0b368f23df917dc5f901b821312c9464c37099c23d
|
4
|
+
data.tar.gz: ce1ea7b919210c7ea6a2d0098a5bf90141ce3910d57f17f9cbb116b96d93753f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 658fffc579a1ddea3001a6ed05f6b59dbe1f05f48ce27c70924cd0ae18b0d8c2bd4c3151b0ea82b52ea78f37e9217f2b80769683dadeba21b2f9f50b6588a566
|
7
|
+
data.tar.gz: c8982b7cae01bfdefa4c0bef71581b7de2b579a0471bf2ff32619c043e84710822026e9814682474e84c386880808d79a651db0d42ff68d0d7ae646630050522
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,36 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 1.5.0 (2024-04-01)
|
6
|
+
|
7
|
+
- Allow specifying the _whispering_ stream via `#stream_from(..., whisper: true)`. ([@palkan][])
|
8
|
+
|
9
|
+
You can use specify the stream to use for _whispering_ (client-initiated broadcasts) by adding `whisper: true` to the `#stream_from` (or `#stream_for`) method call.
|
10
|
+
|
11
|
+
NOTE: This feature is only supported when using AnyCable server and ignored otherwise.
|
12
|
+
|
13
|
+
- Support passing objects to `ActionCable.server.broadcast`. ([@palkan][])
|
14
|
+
|
15
|
+
Make it possible to call `ActionCable.server.broadcast(user, data)` or `ActionCable.server.broadcast([user, :context], data)`. This is a companion functionality for `#signed_stream_name`.
|
16
|
+
|
17
|
+
- Added `websocket_url` configuration option to specify the URL of AnyCable server. ([@palkan][])
|
18
|
+
|
19
|
+
It's used to configure `config.action_cable.url` if AnyCable is activated. No need to set up it manually.
|
20
|
+
|
21
|
+
- Added `rails g anycable:bin` to create a binstub to run AnyCable server. ([@palkan][])
|
22
|
+
|
23
|
+
- Added signed streams helpers. ([@palkan][])
|
24
|
+
|
25
|
+
You can use `#signed_stream_name(streamable)` to generate a signed stream name.
|
26
|
+
|
27
|
+
- Added JWT authentication helpers. ([@palkan][])
|
28
|
+
|
29
|
+
No more need in a separate `anycable-rails-jwt` gem.
|
30
|
+
|
31
|
+
## 1.4.5
|
32
|
+
|
33
|
+
- Restrict `anycable` gem version.
|
34
|
+
|
5
35
|
## 1.4.4 (2024-03-08) 🌷
|
6
36
|
|
7
37
|
- Minor fixes
|
@@ -8,7 +8,7 @@ module ActionCable
|
|
8
8
|
# to AnyCable
|
9
9
|
class AnyCable < Base
|
10
10
|
ACTION_CABLE_SERVER_ERROR_MESSAGE = <<~STR
|
11
|
-
Looks like you
|
11
|
+
Looks like you are trying to connect to Rails Action Cable server, not an AnyCable one.
|
12
12
|
|
13
13
|
Please make sure your client is configured to connect to AnyCable server.
|
14
14
|
|
@@ -10,6 +10,11 @@ ActionCable::Server::Base.prepend(Module.new do
|
|
10
10
|
super(channel, payload)
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
def broadcaster_for(broadcasting, **options)
|
15
|
+
broadcasting = AnyCable::Rails.stream_name_from(broadcasting)
|
16
|
+
super(broadcasting, **options)
|
17
|
+
end
|
13
18
|
end)
|
14
19
|
|
15
20
|
ActionCable::Channel::Base.singleton_class.prepend(Module.new do
|
@@ -22,12 +22,20 @@ ActionCable::Channel::Base.prepend(Module.new do
|
|
22
22
|
super unless anycabled?
|
23
23
|
end
|
24
24
|
|
25
|
-
def stream_from(broadcasting, _callback = nil, **)
|
25
|
+
def stream_from(broadcasting, _callback = nil, **opts)
|
26
|
+
whispering = opts.delete(:whisper)
|
26
27
|
return super unless anycabled?
|
27
28
|
|
28
29
|
broadcasting = String(broadcasting)
|
29
30
|
|
30
31
|
connection.anycable_socket.subscribe identifier, broadcasting
|
32
|
+
if whispering
|
33
|
+
connection.anycable_socket.whisper identifier, broadcasting
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def stream_for(model, callback = nil, **opts, &block)
|
38
|
+
stream_from(broadcasting_for(model), callback || block, **opts)
|
31
39
|
end
|
32
40
|
|
33
41
|
def stop_stream_from(broadcasting)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_cable"
|
4
|
+
|
5
|
+
ActionCable::Connection::Base.include(Module.new do
|
6
|
+
# This method is assumed to be overriden in the connection class to enable public
|
7
|
+
# streams
|
8
|
+
def allow_public_streams?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
end)
|
12
|
+
|
13
|
+
# Handle $pubsub channel in Subscriptions
|
14
|
+
ActionCable::Connection::Subscriptions.prepend(Module.new do
|
15
|
+
# The contents are mostly copied from the original,
|
16
|
+
# there is no good way to configure channels mapping due to #safe_constantize
|
17
|
+
# and the layers of JSON
|
18
|
+
# https://github.com/rails/rails/blob/main/actioncable/lib/action_cable/connection/subscriptions.rb
|
19
|
+
def add(data)
|
20
|
+
id_key = data["identifier"]
|
21
|
+
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
22
|
+
|
23
|
+
return if subscriptions.key?(id_key)
|
24
|
+
|
25
|
+
return super unless id_options[:channel] == "$pubsub"
|
26
|
+
|
27
|
+
subscription = AnyCable::Rails::PubSubChannel.new(connection, id_key, id_options)
|
28
|
+
subscriptions[id_key] = subscription
|
29
|
+
subscription.subscribe_to_channel
|
30
|
+
end
|
31
|
+
end)
|
@@ -10,11 +10,16 @@ module AnyCable
|
|
10
10
|
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
11
11
|
def #{name}
|
12
12
|
return @#{name} if instance_variable_defined?(:@#{name})
|
13
|
-
|
13
|
+
return unless anycabled?
|
14
|
+
|
15
|
+
raw_val = __istate__["#{name}"]
|
16
|
+
val = raw_val.present? ? AnyCable::Serializer.deserialize(JSON.parse(raw_val)) : nil
|
17
|
+
|
18
|
+
@#{name} = val.try(:with_indifferent_access) || val
|
14
19
|
end
|
15
20
|
|
16
21
|
def #{name}=(val)
|
17
|
-
__istate__["#{name}"] = AnyCable::
|
22
|
+
__istate__["#{name}"] = AnyCable::Serializer.serialize(val).to_json if anycabled?
|
18
23
|
instance_variable_set(:@#{name}, val)
|
19
24
|
end
|
20
25
|
RUBY
|
@@ -53,11 +58,14 @@ module AnyCable
|
|
53
58
|
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
54
59
|
def #{name}
|
55
60
|
return @#{name} if instance_variable_defined?(:@#{name})
|
56
|
-
|
61
|
+
return unless anycabled?
|
62
|
+
|
63
|
+
val = __cstate__["#{name}"]
|
64
|
+
@#{name} = val.present? ? AnyCable::Serializer.deserialize(JSON.parse(val)) : nil
|
57
65
|
end
|
58
66
|
|
59
67
|
def #{name}=(val)
|
60
|
-
__cstate__["#{name}"] = AnyCable::
|
68
|
+
__cstate__["#{name}"] = AnyCable::Serializer.serialize(val).to_json if anycabled?
|
61
69
|
instance_variable_set(:@#{name}, val)
|
62
70
|
end
|
63
71
|
RUBY
|
@@ -11,7 +11,7 @@ module AnyCable
|
|
11
11
|
]
|
12
12
|
|
13
13
|
ActionCable::Channel::Base.prepend(Module.new do
|
14
|
-
def stream_from(broadcasting, callback = nil, coder: nil)
|
14
|
+
def stream_from(broadcasting, callback = nil, coder: nil, **)
|
15
15
|
if coder.present? && coder != ActiveSupport::JSON
|
16
16
|
raise AnyCable::CompatibilityError, "Custom coders are not supported by AnyCable"
|
17
17
|
end
|
@@ -9,15 +9,19 @@ require "anyway/rails"
|
|
9
9
|
# - `access_logs_disabled` (defaults to true) — whether to print Started/Finished logs
|
10
10
|
# - `persistent_session_enabled` (defaults to false) — whether to store session changes in the connection state
|
11
11
|
# - `embedded` (defaults to false) — whether to run RPC server inside a Rails server process
|
12
|
-
# - `http_rpc_mount_path` (
|
12
|
+
# - `http_rpc_mount_path` (defaults to nil) — path to mount HTTP RPC server
|
13
13
|
# - `batch_broadcasts` (defaults to false) — whether to batch broadcasts automatically for code wrapped with Rails executor
|
14
|
+
# - `jwt_param` (defaults to 'jid') — the name of the JWT authentication query paramter or header
|
15
|
+
# - `websocket_url` (defaults to nil) — the URL of AnyCable server WebSocket endpoint
|
14
16
|
AnyCable::Config.attr_config(
|
15
17
|
access_logs_disabled: true,
|
16
18
|
persistent_session_enabled: false,
|
17
19
|
embedded: false,
|
20
|
+
jwt_param: "jid",
|
18
21
|
http_rpc_mount_path: nil,
|
19
22
|
batch_broadcasts: false,
|
20
23
|
socket_id_header: "X-Socket-ID",
|
21
|
-
disable_rpc_pool_size_warning: false
|
24
|
+
disable_rpc_pool_size_warning: false,
|
25
|
+
websocket_url: nil
|
22
26
|
)
|
23
27
|
AnyCable::Config.ignore_options :access_logs_disabled, :persistent_session_enabled
|
@@ -24,7 +24,7 @@ module AnyCable
|
|
24
24
|
obj = instance_variable_get("@#{id}")
|
25
25
|
next unless obj
|
26
26
|
|
27
|
-
acc[id] = AnyCable::
|
27
|
+
acc[id] = AnyCable::Serializer.serialize(obj)
|
28
28
|
end.compact
|
29
29
|
end
|
30
30
|
|
@@ -37,7 +37,7 @@ module AnyCable
|
|
37
37
|
return unless @cached_ids
|
38
38
|
|
39
39
|
@cached_ids[name] ||= @cached_ids.fetch(name) do
|
40
|
-
AnyCable::
|
40
|
+
AnyCable::Serializer.deserialize(@serialized_ids[name.to_s])
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCable
|
4
|
+
module Rails
|
5
|
+
module Ext
|
6
|
+
# This module adds AnyCable JWT helpers to Action Cable
|
7
|
+
module JWT
|
8
|
+
# Handle expired tokens here to respond with a different disconnect reason
|
9
|
+
def handle_open
|
10
|
+
super
|
11
|
+
rescue AnyCable::JWT::ExpiredSignature
|
12
|
+
logger.error "An expired JWT token was rejected"
|
13
|
+
close(reason: "token_expired", reconnect: false) if websocket&.alive?
|
14
|
+
end
|
15
|
+
|
16
|
+
def anycable_jwt_present?
|
17
|
+
request.params[AnyCable.config.jwt_param].present? ||
|
18
|
+
request.headers["x-#{AnyCable.config.jwt_param}"].present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def identify_from_anycable_jwt!
|
22
|
+
token = request.params[AnyCable.config.jwt_param].presence ||
|
23
|
+
request.headers["x-#{AnyCable.config.jwt_param}"].presence
|
24
|
+
|
25
|
+
identifiers = AnyCable::JWT.decode(token)
|
26
|
+
identifiers.each do |k, v|
|
27
|
+
public_send("#{k}=", v)
|
28
|
+
end
|
29
|
+
rescue AnyCable::JWT::VerificationError
|
30
|
+
reject_unauthorized_connection
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module AnyCable
|
6
|
+
module Rails
|
7
|
+
module Helper
|
8
|
+
def action_cable_with_jwt_meta_tag(**identifiers)
|
9
|
+
# From: https://github.com/rails/rails/blob/main/actioncable/lib/action_cable/helpers/action_cable_helper.rb
|
10
|
+
base_url = ActionCable.server.config.url ||
|
11
|
+
ActionCable.server.config.mount_path ||
|
12
|
+
raise("No Action Cable URL configured -- please configure this at config.action_cable.url")
|
13
|
+
|
14
|
+
token = JWT.encode(identifiers)
|
15
|
+
|
16
|
+
parts = [base_url, "#{AnyCable.config.jwt_param}=#{token}"]
|
17
|
+
|
18
|
+
uri = URI.parse(base_url)
|
19
|
+
|
20
|
+
url = parts.join(uri.query ? "&" : "?")
|
21
|
+
|
22
|
+
tag "meta", name: "action-cable-url", content: url
|
23
|
+
end
|
24
|
+
|
25
|
+
def any_cable_jwt_meta_tag(**identifiers)
|
26
|
+
token = JWT.encode(identifiers)
|
27
|
+
|
28
|
+
tag "meta", name: "any-cable-jwt", content: token
|
29
|
+
end
|
30
|
+
|
31
|
+
def signed_stream_name(streamables)
|
32
|
+
Rails.signed_stream_name(streamables)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCable
|
4
|
+
module Rails
|
5
|
+
module ObjectSerializer
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Serialize via GlobalID if available
|
9
|
+
def serialize(obj)
|
10
|
+
obj.try(:to_gid_param)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Deserialize from GlobalID
|
14
|
+
def deserialize(str)
|
15
|
+
GlobalID::Locator.locate(str)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCable
|
4
|
+
module Rails
|
5
|
+
class PubSubChannel < ActionCable::Channel::Base
|
6
|
+
def subscribed
|
7
|
+
stream_name =
|
8
|
+
if params[:stream_name] && connection.allow_public_streams?
|
9
|
+
params[:stream_name]
|
10
|
+
elsif params[:signed_stream_name]
|
11
|
+
AnyCable::Streams.verified(params[:signed_stream_name])
|
12
|
+
end
|
13
|
+
|
14
|
+
if stream_name
|
15
|
+
stream_from stream_name
|
16
|
+
else
|
17
|
+
reject
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -4,6 +4,7 @@ require "anycable/rails/action_cable_ext/connection"
|
|
4
4
|
require "anycable/rails/action_cable_ext/channel"
|
5
5
|
require "anycable/rails/action_cable_ext/remote_connections"
|
6
6
|
require "anycable/rails/action_cable_ext/broadcast_options"
|
7
|
+
require "anycable/rails/action_cable_ext/signed_streams"
|
7
8
|
|
8
9
|
require "anycable/rails/channel_state"
|
9
10
|
require "anycable/rails/connection_factory"
|
@@ -17,6 +18,19 @@ module AnyCable
|
|
17
18
|
app.config.action_cable.mount_path = nil
|
18
19
|
end
|
19
20
|
|
21
|
+
initializer "anycable.websocket_url", after: "action_cable.set_configs" do |app|
|
22
|
+
next unless AnyCable::Rails.enabled?
|
23
|
+
|
24
|
+
websocket_url = AnyCable.config.websocket_url.presence
|
25
|
+
next unless websocket_url
|
26
|
+
|
27
|
+
app.config.action_cable.url = websocket_url
|
28
|
+
|
29
|
+
ActiveSupport.on_load(:action_cable) do
|
30
|
+
::ActionCable.server.config.url = websocket_url
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
20
34
|
initializer "anycable.logger", after: "action_cable.logger" do |_app|
|
21
35
|
AnyCable.logger = ::ActionCable.server.config.logger
|
22
36
|
|
@@ -51,6 +65,11 @@ module AnyCable
|
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
68
|
+
initializer "anycable.object_serializer" do |_app|
|
69
|
+
require "anycable/rails/object_serializer"
|
70
|
+
AnyCable::Serializer.object_serializer = AnyCable::Rails::ObjectSerializer
|
71
|
+
end
|
72
|
+
|
54
73
|
initializer "anycable.executor" do |app|
|
55
74
|
require "anycable/rails/middlewares/executor"
|
56
75
|
# see https://github.com/rails/rails/pull/33469/files
|
@@ -131,6 +150,12 @@ module AnyCable
|
|
131
150
|
end
|
132
151
|
end
|
133
152
|
|
153
|
+
initializer "anycable.helpers" do
|
154
|
+
ActiveSupport.on_load(:action_view) do
|
155
|
+
include AnyCable::Rails::Helper
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
134
159
|
# Since Rails 6.1
|
135
160
|
if respond_to?(:server)
|
136
161
|
server do
|
data/lib/anycable/rails.rb
CHANGED
@@ -8,9 +8,14 @@ require "anycable/rails/rack"
|
|
8
8
|
require "globalid"
|
9
9
|
require "active_support/core_ext/module/attribute_accessors_per_thread"
|
10
10
|
|
11
|
+
require "anycable/rails/ext"
|
12
|
+
|
11
13
|
module AnyCable
|
12
14
|
# Rails handler for AnyCable
|
13
15
|
module Rails
|
16
|
+
autoload :Helper, "anycable/rails/helper"
|
17
|
+
autoload :PubSubChannel, "anycable/rails/pubsub_channel"
|
18
|
+
|
14
19
|
require "anycable/rails/railtie"
|
15
20
|
|
16
21
|
ADAPTER_ALIASES = %w[any_cable anycable].freeze
|
@@ -51,28 +56,15 @@ module AnyCable
|
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
def serialize(obj, json: false)
|
57
|
-
obj.try(:to_gid_param) || (json ? obj.to_json : obj)
|
59
|
+
def signed_stream_name(streamables)
|
60
|
+
Streams.signed(stream_name_from(streamables))
|
58
61
|
end
|
59
62
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
next val unless val.is_a?(String)
|
66
|
-
|
67
|
-
gval = GlobalID::Locator.locate(val)
|
68
|
-
return gval if gval
|
69
|
-
|
70
|
-
next val unless json
|
71
|
-
|
72
|
-
JSON.parse(val)
|
73
|
-
end.yield_self do |val|
|
74
|
-
next val.with_indifferent_access if val.is_a?(Hash)
|
75
|
-
val
|
63
|
+
def stream_name_from(streamables)
|
64
|
+
if streamables.is_a?(Array)
|
65
|
+
streamables.map { |streamable| stream_name_from(streamable) }.join(":")
|
66
|
+
else
|
67
|
+
streamables.then { |streamable| streamable.try(:to_gid_param) || streamable.to_param }
|
76
68
|
end
|
77
69
|
end
|
78
70
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "generators/anycable/with_os_helpers"
|
4
|
+
|
5
|
+
module AnyCableRailsGenerators
|
6
|
+
# Generates bin/anycable-go binstub
|
7
|
+
class BinGenerator < ::Rails::Generators::Base
|
8
|
+
namespace "anycable:bin"
|
9
|
+
|
10
|
+
source_root File.expand_path("templates", __dir__)
|
11
|
+
|
12
|
+
class_option :version,
|
13
|
+
type: :string,
|
14
|
+
desc: "Specify AnyCable server version (defaults to latest release)",
|
15
|
+
version: "latest"
|
16
|
+
|
17
|
+
def generate_bin
|
18
|
+
inside("bin") do
|
19
|
+
template "anycable-go"
|
20
|
+
chmod "anycable-go", 0755, verbose: false # rubocop:disable Style/NumericLiteralPrefix
|
21
|
+
end
|
22
|
+
|
23
|
+
in_root do
|
24
|
+
next unless File.file?(".gitignore")
|
25
|
+
|
26
|
+
ignores = File.read(".gitignore").lines
|
27
|
+
|
28
|
+
if ignores.none? { |line| line.match?(/^bin\/dist$/) }
|
29
|
+
append_file ".gitignore", "bin/dist\n"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def anycable_go_version
|
39
|
+
@anycable_go_version ||= normalize_version(options[:version]) || "latest"
|
40
|
+
end
|
41
|
+
|
42
|
+
def normalize_version(version)
|
43
|
+
return unless version
|
44
|
+
return if version.chomp == "latest"
|
45
|
+
|
46
|
+
# We need a full version for bin/anycable-go script
|
47
|
+
segments = Gem::Version.new(version).segments
|
48
|
+
segments << 0 until segments.size >= 3
|
49
|
+
segments.join(".")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
cd $(dirname $0)/..
|
4
|
+
|
5
|
+
# It's recommended to use the exact version of AnyCable here
|
6
|
+
version="<%= anycable_go_version %>"
|
7
|
+
|
8
|
+
if [ ! -f ./bin/dist/anycable-go ]; then
|
9
|
+
echo "AnyCable server is not installed, downloading..."
|
10
|
+
./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
|
11
|
+
fi
|
12
|
+
|
13
|
+
curVersion=$(./bin/dist/anycable-go -v)
|
14
|
+
|
15
|
+
if [[ "$version" != "latest" ]]; then
|
16
|
+
if [[ "$curVersion" != "$version"* ]]; then
|
17
|
+
echo "AnyCable server version is not $version, downloading a new one..."
|
18
|
+
./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
|
19
|
+
fi
|
20
|
+
fi
|
21
|
+
|
22
|
+
./bin/dist/anycable-go $@
|
@@ -1,5 +1,5 @@
|
|
1
1
|
Description:
|
2
|
-
Install AnyCable-
|
2
|
+
Install AnyCable real-time server locally (the latest version by default).
|
3
3
|
|
4
4
|
Example:
|
5
5
|
rails generate anycable:download
|
@@ -11,4 +11,4 @@ Example:
|
|
11
11
|
|
12
12
|
rails generate anycable:download --bin-path=/usr/local/bin
|
13
13
|
|
14
|
-
rails generate anycable:download --version=1.
|
14
|
+
rails generate anycable:download --version=1.4.0
|
@@ -13,10 +13,10 @@ module AnyCableRailsGenerators
|
|
13
13
|
|
14
14
|
class_option :bin_path,
|
15
15
|
type: :string,
|
16
|
-
desc: "Where to download AnyCable
|
16
|
+
desc: "Where to download AnyCable server binary (default: #{DEFAULT_BIN_PATH})"
|
17
17
|
class_option :version,
|
18
18
|
type: :string,
|
19
|
-
desc: "Specify the AnyCable
|
19
|
+
desc: "Specify the AnyCable version (defaults to latest release)"
|
20
20
|
|
21
21
|
def download_bin
|
22
22
|
out = options[:bin_path] || DEFAULT_BIN_PATH
|
@@ -74,7 +74,7 @@ module AnyCableRailsGenerators
|
|
74
74
|
if yes? "Path is not writable 😕. Do you have sudo privileges?"
|
75
75
|
sudo = "sudo "
|
76
76
|
else
|
77
|
-
say_status :error, "❌ Failed to install AnyCable-
|
77
|
+
say_status :error, "❌ Failed to install AnyCable real-time server", :red
|
78
78
|
raise StandardError, "Path #{path} is not writable!"
|
79
79
|
end
|
80
80
|
end
|
@@ -10,105 +10,63 @@ module AnyCableRailsGenerators
|
|
10
10
|
|
11
11
|
DOCS_ROOT = "https://docs.anycable.io"
|
12
12
|
DEVELOPMENT_METHODS = %w[skip local docker].freeze
|
13
|
-
|
13
|
+
DEPLOYMENT_METHODS = %w[other fly heroku anycable_plus].freeze
|
14
|
+
RPC_IMPL = %w[none grpc http].freeze
|
14
15
|
|
15
16
|
class_option :devenv,
|
16
17
|
type: :string,
|
17
|
-
desc: "Select your development environment (options: #{DEVELOPMENT_METHODS.join(", ")})"
|
18
|
+
desc: "Select your development environment (options: #{DEVELOPMENT_METHODS.reverse.join(", ")})"
|
18
19
|
class_option :rpc,
|
19
20
|
type: :string,
|
20
|
-
desc: "Select RPC implementation (options: #{RPC_IMPL.join(", ")})"
|
21
|
-
|
22
|
-
class_option :skip_heroku,
|
21
|
+
desc: "Select RPC implementation (options: #{RPC_IMPL.reverse.join(", ")})"
|
22
|
+
class_option :skip_procfile,
|
23
23
|
type: :boolean,
|
24
|
-
desc: "Do not
|
25
|
-
class_option :skip_procfile_dev,
|
26
|
-
type: :boolean,
|
27
|
-
desc: "Do not create Procfile.dev"
|
28
|
-
class_option :skip_jwt,
|
29
|
-
type: :boolean,
|
30
|
-
desc: "Do not install anycable-rails-jwt"
|
31
|
-
class_option :skip_install,
|
32
|
-
type: :boolean,
|
33
|
-
desc: "Do not run bundle install when adding new gems"
|
24
|
+
desc: "Do not create/update Procfile.dev"
|
34
25
|
class_option :version,
|
35
26
|
type: :string,
|
36
|
-
desc: "Specify
|
27
|
+
desc: "Specify AnyCable server version (defaults to latest release)",
|
28
|
+
default: "latest"
|
37
29
|
|
38
30
|
def welcome
|
39
|
-
say "
|
31
|
+
say ""
|
32
|
+
say "👋 Welcome to AnyCable interactive installer. We'll guide you through the process of installing AnyCable for your Rails application. Buckle up!"
|
33
|
+
say ""
|
40
34
|
end
|
41
35
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
template "anycable.yml"
|
46
|
-
end
|
47
|
-
end
|
36
|
+
def rpc_implementation
|
37
|
+
say "AnyCable connects to your Rails server to communicate with Action Cable channels (via RPC API). Learn more from the docs 👉 #{DOCS_ROOT}/anycable-go/rpc"
|
38
|
+
say ""
|
48
39
|
|
49
|
-
|
50
|
-
environment(nil, env: :development) do
|
51
|
-
<<~SNIPPET
|
52
|
-
# Specify AnyCable WebSocket server URL to use by JS client
|
53
|
-
config.after_initialize do
|
54
|
-
config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
|
55
|
-
end
|
56
|
-
SNIPPET
|
57
|
-
end
|
40
|
+
answer = RPC_IMPL.index(options[:rpc]) || 99
|
58
41
|
|
59
|
-
|
60
|
-
|
61
|
-
# Specify AnyCable WebSocket server URL to use by JS client
|
62
|
-
config.after_initialize do
|
63
|
-
config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL", "/cable") if AnyCable::Rails.enabled?
|
64
|
-
end
|
65
|
-
SNIPPET
|
42
|
+
until RPC_IMPL[answer.to_i]
|
43
|
+
answer = ask "Do you want to use gRPC or HTTP for AnyCable RPC? (1) gRPC, (2) HTTP, (0) None"
|
66
44
|
end
|
67
45
|
|
68
|
-
|
69
|
-
say_status :help, "⚠️ If you're using JS client make sure you have " \
|
70
|
-
"`action_cable_meta_tag` included before any <script> tag in your application.html"
|
46
|
+
@rpc_impl = RPC_IMPL[answer.to_i]
|
71
47
|
end
|
72
48
|
|
73
49
|
def development_method
|
74
50
|
answer = DEVELOPMENT_METHODS.index(options[:devenv]) || 99
|
75
51
|
|
52
|
+
say ""
|
53
|
+
|
76
54
|
until DEVELOPMENT_METHODS[answer.to_i]
|
77
|
-
answer = ask "Do you want to run anycable-go locally or as a Docker container? (1) Local, (2) Docker, (0) Skip"
|
55
|
+
answer = ask "Do you want to run AnyCable server (anycable-go) locally or as a Docker container? (1) Local, (2) Docker, (0) Skip"
|
78
56
|
end
|
79
57
|
|
80
|
-
|
58
|
+
@devenv = DEVELOPMENT_METHODS[answer.to_i]
|
59
|
+
|
60
|
+
case @devenv
|
81
61
|
when "skip"
|
82
|
-
say_status :help, "⚠️ Please, read this guide on how to install AnyCable
|
62
|
+
say_status :help, "⚠️ Please, read this guide on how to install AnyCable server 👉 #{DOCS_ROOT}/anycable-go/getting_started", :yellow
|
83
63
|
else
|
84
|
-
send "install_for_#{
|
64
|
+
send "install_for_#{@devenv}"
|
85
65
|
end
|
86
66
|
end
|
87
67
|
|
88
|
-
def heroku
|
89
|
-
if options[:skip_heroku].nil?
|
90
|
-
return unless yes? "Do you use Heroku for deployment? [Yn]"
|
91
|
-
elsif options[:skip_heroku]
|
92
|
-
return
|
93
|
-
end
|
94
|
-
|
95
|
-
in_root do
|
96
|
-
next unless File.file?("Procfile")
|
97
|
-
next if http_rpc?
|
98
|
-
|
99
|
-
contents = File.read("Procfile")
|
100
|
-
contents.sub!(/^web: (.*)$/, %q(web: [[ "$ANYCABLE_DEPLOYMENT" == "true" ]] && bundle exec anycable --server-command="anycable-go" || \1))
|
101
|
-
File.write("Procfile", contents)
|
102
|
-
say_status :info, "✅ Procfile updated"
|
103
|
-
end
|
104
|
-
|
105
|
-
say_status :help, "️️⚠️ Please, read the required steps to configure Heroku applications 👉 #{DOCS_ROOT}/deployment/heroku", :yellow
|
106
|
-
end
|
107
|
-
|
108
68
|
def devise
|
109
|
-
|
110
|
-
return unless File.file?("config/initializers/devise.rb")
|
111
|
-
end
|
69
|
+
return unless devise?
|
112
70
|
|
113
71
|
inside("config/initializers") do
|
114
72
|
template "anycable.rb"
|
@@ -117,10 +75,12 @@ module AnyCableRailsGenerators
|
|
117
75
|
say_status :info, "✅ config/initializers/anycable.rb with Devise configuration has been added"
|
118
76
|
end
|
119
77
|
|
120
|
-
def
|
121
|
-
|
78
|
+
def configs
|
79
|
+
inside("config") do
|
80
|
+
template "anycable.yml"
|
81
|
+
end
|
122
82
|
|
123
|
-
|
83
|
+
update_cable_yml
|
124
84
|
end
|
125
85
|
|
126
86
|
def rubocop_compatibility
|
@@ -131,14 +91,15 @@ module AnyCableRailsGenerators
|
|
131
91
|
say_status :help, "⚠️ Please, take a look at the icompatibilities above and fix them. See #{DOCS_ROOT}/rails/compatibility" unless res
|
132
92
|
end
|
133
93
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
|
94
|
+
def cable_url_info
|
95
|
+
say_status :help, "⚠️ If you're using JS client make sure you have " \
|
96
|
+
"`action_cable_meta_tag` or `action_cable_with_jwt_meta_tag` included in your HTML layout"
|
97
|
+
end
|
138
98
|
|
139
|
-
|
99
|
+
def deployment_method
|
100
|
+
say_status :info, "🚢 See our deployment guide to learn how to run AnyCable in production 👉 #{DOCS_ROOT}/deployment"
|
140
101
|
|
141
|
-
|
102
|
+
say_status :info, "Check out AnyCable+, our hosted AnyCable solution: https://plus.anycable.io"
|
142
103
|
end
|
143
104
|
|
144
105
|
def finish
|
@@ -147,10 +108,6 @@ module AnyCableRailsGenerators
|
|
147
108
|
|
148
109
|
private
|
149
110
|
|
150
|
-
def stimulus_reflex?
|
151
|
-
!!gemfile_lock&.match?(/^\s+stimulus_reflex\b/)
|
152
|
-
end
|
153
|
-
|
154
111
|
def redis?
|
155
112
|
!!gemfile_lock&.match?(/^\s+redis\b/)
|
156
113
|
end
|
@@ -167,8 +124,20 @@ module AnyCableRailsGenerators
|
|
167
124
|
!!gemfile_lock&.match?(/^\s+rubocop\b/)
|
168
125
|
end
|
169
126
|
|
127
|
+
def devise?
|
128
|
+
!!gemfile_lock&.match?(/^\s+devise\b/)
|
129
|
+
end
|
130
|
+
|
131
|
+
def local?
|
132
|
+
@devenv == "local"
|
133
|
+
end
|
134
|
+
|
135
|
+
def grpc?
|
136
|
+
@rpc_impl == "grpc"
|
137
|
+
end
|
138
|
+
|
170
139
|
def http_rpc?
|
171
|
-
|
140
|
+
@rpc_impl == "http"
|
172
141
|
end
|
173
142
|
|
174
143
|
def gemfile_lock
|
@@ -183,83 +152,143 @@ module AnyCableRailsGenerators
|
|
183
152
|
end
|
184
153
|
|
185
154
|
def install_for_docker
|
186
|
-
# Remove localhost from configuraiton
|
187
|
-
gsub_file "config/anycable.yml", /^.*redis_url:.*localhost[^\n]+\n/, ""
|
188
|
-
|
189
155
|
say_status :help, "️️⚠️ Docker development configuration could vary", :yellow
|
190
156
|
|
191
|
-
say "Here is an example snippet for
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
157
|
+
say "Here is an example snippet for Docker Compose:"
|
158
|
+
|
159
|
+
if @rpc_impl == "grpc"
|
160
|
+
say <<~YML
|
161
|
+
─────────────────────────────────────────
|
162
|
+
# your Rails application service
|
163
|
+
rails: &rails
|
164
|
+
# ...
|
165
|
+
ports:
|
166
|
+
- '3000:3000'
|
167
|
+
environment: &rails_environment
|
168
|
+
# ...
|
169
|
+
ANYCABLE_HTTP_BROADCAST_URL: http://ws:8090/_broadcast
|
170
|
+
depends_on: &rails_depends_on
|
171
|
+
#...
|
172
|
+
anycable:
|
173
|
+
condition: service_started
|
174
|
+
|
175
|
+
ws:
|
176
|
+
image: anycable/anycable-go:1.5
|
177
|
+
ports:
|
178
|
+
- '8080:8080'
|
179
|
+
- '8090'
|
180
|
+
environment:
|
181
|
+
ANYCABLE_HOST: "0.0.0.0"
|
182
|
+
ANYCABLE_BROADCAST_ADAPTER: http
|
183
|
+
ANYCABLE_RPC_HOST: anycable:50051
|
184
|
+
ANYCABLE_DEBUG: ${ANYCABLE_DEBUG:-true}
|
185
|
+
|
186
|
+
anycable:
|
187
|
+
<<: *rails
|
188
|
+
command: bundle exec anycable
|
189
|
+
environment:
|
190
|
+
<<: *rails_environment
|
191
|
+
ANYCABLE_RPC_HOST: 0.0.0.0:50051
|
192
|
+
ports:
|
193
|
+
- '50051'
|
194
|
+
depends_on:
|
195
|
+
<<: *rails_depends_on
|
196
|
+
ws:
|
197
|
+
condition: service_started
|
198
|
+
─────────────────────────────────────────
|
199
|
+
YML
|
200
|
+
else
|
201
|
+
say <<~YML
|
202
|
+
─────────────────────────────────────────
|
203
|
+
# Your Rails application service
|
204
|
+
rails: &rails
|
205
|
+
# ...
|
206
|
+
ports:
|
207
|
+
- '3000:3000'
|
208
|
+
environment: &rails_environment
|
209
|
+
# ...
|
210
|
+
ANYCABLE_HTTP_BROADCAST_URL: http://ws:8090/_broadcast
|
211
|
+
depends_on: &rails_depends_on
|
212
|
+
#...
|
213
|
+
anycable:
|
214
|
+
condition: service_started
|
215
|
+
|
216
|
+
ws:
|
217
|
+
image: anycable/anycable-go:1.5
|
218
|
+
ports:
|
219
|
+
- '8080:8080'
|
220
|
+
environment:
|
221
|
+
ANYCABLE_HOST: "0.0.0.0"
|
222
|
+
ANYCABLE_BROADCAST_ADAPTER: http
|
223
|
+
ANYCABLE_RPC_HOST: http://rails:3000/_anycable
|
224
|
+
ANYCABLE_DEBUG: ${ANYCABLE_DEBUG:-true}
|
225
|
+
─────────────────────────────────────────
|
226
|
+
YML
|
227
|
+
end
|
223
228
|
end
|
224
229
|
|
225
230
|
def install_for_local
|
226
|
-
|
227
|
-
|
228
|
-
chmod "anycable-go", 0755, verbose: false # rubocop:disable Style/NumericLiteralPrefix
|
231
|
+
unless file_exists?("bin/anycable-go")
|
232
|
+
generate "anycable:bin", "--version #{options[:version]}"
|
229
233
|
end
|
234
|
+
template_proc_files
|
235
|
+
true
|
236
|
+
end
|
230
237
|
|
231
|
-
|
232
|
-
|
233
|
-
|
238
|
+
def update_cable_yml
|
239
|
+
if file_exists?("config/cable.yml")
|
240
|
+
in_root do
|
241
|
+
contents = File.read("config/cable.yml")
|
242
|
+
# Replace any adapter: x with any_cable unless x == "test"
|
243
|
+
new_contents = contents.gsub(/\sadapter:\s*([^$\n]+)/) do |match|
|
244
|
+
adapter = Regexp.last_match[1]
|
245
|
+
next match if adapter == "test" || adapter.include?("any_cable")
|
234
246
|
|
235
|
-
|
247
|
+
match.sub(adapter, %(<%= ENV.fetch("ACTION_CABLE_ADAPTER", "any_cable") %>))
|
248
|
+
end
|
249
|
+
|
250
|
+
File.write "config/cable.yml", new_contents
|
251
|
+
end
|
252
|
+
else
|
253
|
+
inside("config") do
|
254
|
+
template "cable.yml"
|
255
|
+
end
|
256
|
+
end
|
236
257
|
end
|
237
258
|
|
238
259
|
def template_proc_files
|
239
260
|
file_name = "Procfile.dev"
|
240
261
|
|
241
262
|
if file_exists?(file_name)
|
242
|
-
|
243
|
-
append_file file_name, "anycable: bundle exec anycable\n", force: true
|
244
|
-
end
|
245
|
-
append_file file_name, "ws: bin/anycable-go #{anycable_go_options}", force: true
|
263
|
+
update_procfile(file_name)
|
246
264
|
else
|
247
|
-
say_status :help, "💡 We recommend using
|
265
|
+
say_status :help, "💡 We recommend using Overmind to manage multiple processes in development 👉 https://github.com/DarthSim/overmind", :yellow
|
248
266
|
|
249
|
-
if options[:skip_procfile_dev]
|
250
|
-
return unless yes? "Do you want to create a '#{file_name}' file?"
|
251
|
-
elsif options[:skip_procfile_dev]
|
252
|
-
return
|
253
|
-
end
|
267
|
+
return if options[:skip_procfile_dev]
|
254
268
|
|
255
269
|
template file_name
|
256
270
|
end
|
257
271
|
end
|
258
272
|
|
273
|
+
def update_procfile(file_name)
|
274
|
+
in_root do
|
275
|
+
contents = File.read(file_name)
|
276
|
+
|
277
|
+
unless http_rpc?
|
278
|
+
unless contents.match?(/^anycable:\s/)
|
279
|
+
append_file file_name, "anycable: bundle exec anycable\n", force: true
|
280
|
+
end
|
281
|
+
end
|
282
|
+
unless contents.match?(/^ws:\s/)
|
283
|
+
append_file file_name, "ws: bin/anycable-go #{anycable_go_options}", force: true
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
259
288
|
def anycable_go_options
|
260
289
|
opts = ["--port=8080"]
|
261
290
|
opts << "--broadcast_adapter=http" unless redis?
|
262
|
-
opts << "--
|
291
|
+
opts << "--rpc_host=http://localhost:3000/_anycable" if http_rpc?
|
263
292
|
opts.join(" ")
|
264
293
|
end
|
265
294
|
|
@@ -268,18 +297,5 @@ module AnyCableRailsGenerators
|
|
268
297
|
return File.file?(name)
|
269
298
|
end
|
270
299
|
end
|
271
|
-
|
272
|
-
def anycable_go_version
|
273
|
-
@anycable_go_version ||= normalize_version(options[:version]) || "latest"
|
274
|
-
end
|
275
|
-
|
276
|
-
def normalize_version(version)
|
277
|
-
return unless version
|
278
|
-
|
279
|
-
# We need a full version for bin/anycable-go script
|
280
|
-
segments = Gem::Version.new(version).segments
|
281
|
-
segments << 0 until segments.size >= 3
|
282
|
-
segments.join(".")
|
283
|
-
end
|
284
300
|
end
|
285
301
|
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
cd $(dirname $0)/..
|
4
4
|
|
5
|
-
# It's recommended to use the exact version of AnyCable
|
5
|
+
# It's recommended to use the exact version of AnyCable here
|
6
6
|
version="<%= anycable_go_version %>"
|
7
7
|
|
8
8
|
if [ ! -f ./bin/dist/anycable-go ]; then
|
9
|
-
echo "AnyCable
|
9
|
+
echo "AnyCable server is not installed, downloading..."
|
10
10
|
./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
|
11
11
|
fi
|
12
12
|
|
@@ -14,7 +14,7 @@ curVersion=$(./bin/dist/anycable-go -v)
|
|
14
14
|
|
15
15
|
if [[ "$version" != "latest" ]]; then
|
16
16
|
if [[ "$curVersion" != "$version"* ]]; then
|
17
|
-
echo "AnyCable
|
17
|
+
echo "AnyCable server version is not $version, downloading a new one..."
|
18
18
|
./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
|
19
19
|
fi
|
20
20
|
fi
|
@@ -21,26 +21,33 @@ default: &default
|
|
21
21
|
# Use NATS to broadcast messages to AnyCable server
|
22
22
|
broadcast_adapter: nats
|
23
23
|
<%- else -%>
|
24
|
-
# Use HTTP
|
24
|
+
# Use HTTP broadcaster
|
25
25
|
broadcast_adapter: http
|
26
26
|
<%- end -%>
|
27
|
-
# Use the same channel name for WebSocket server, e.g.:
|
28
|
-
# $ anycable-go --redis_channel="__anycable__"
|
29
|
-
redis_channel: "__anycable__"
|
30
27
|
<%- if redis? -%>
|
31
28
|
# You can use REDIS_URL env var to configure Redis URL.
|
32
29
|
# Localhost is used by default.
|
33
30
|
# redis_url: "redis://localhost:6379/1"
|
31
|
+
# Use the same channel name for WebSocket server, e.g.:
|
32
|
+
# $ anycable-go --redis_channel="__anycable__"
|
33
|
+
# redis_channel: "__anycable__"
|
34
34
|
<%- end -%>
|
35
35
|
<%- if http_rpc? -%>
|
36
|
+
# Use HTTP RPC mounted at the specified path of your web server
|
37
|
+
# Read more about AnyCable RPC: <%= DOCS_ROOT %>/anycable-go/rpc
|
36
38
|
http_rpc_mount_path: "/_anycable"
|
37
39
|
<%- end -%>
|
38
40
|
|
39
41
|
development:
|
40
42
|
<<: *default
|
43
|
+
# WebSocket endpoint of your AnyCable server for clients to connect to
|
44
|
+
# Make sure you have the `action_cable_meta_tag` in your HTML layout
|
45
|
+
# to propogate this value to the client app
|
46
|
+
websocket_url: "ws://localhost:8080/cable"
|
41
47
|
|
42
48
|
test:
|
43
49
|
<<: *default
|
44
50
|
|
45
51
|
production:
|
46
52
|
<<: *default
|
53
|
+
websocket_url: ~
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anycable-rails-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: anycable-core
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.5.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.5.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: actioncable
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/anycable/rails/action_cable_ext/channel.rb
|
71
71
|
- lib/anycable/rails/action_cable_ext/connection.rb
|
72
72
|
- lib/anycable/rails/action_cable_ext/remote_connections.rb
|
73
|
+
- lib/anycable/rails/action_cable_ext/signed_streams.rb
|
73
74
|
- lib/anycable/rails/channel_state.rb
|
74
75
|
- lib/anycable/rails/compatibility.rb
|
75
76
|
- lib/anycable/rails/compatibility/rubocop.rb
|
@@ -83,12 +84,20 @@ files:
|
|
83
84
|
- lib/anycable/rails/connections/persistent_session.rb
|
84
85
|
- lib/anycable/rails/connections/serializable_identification.rb
|
85
86
|
- lib/anycable/rails/connections/session_proxy.rb
|
87
|
+
- lib/anycable/rails/ext.rb
|
88
|
+
- lib/anycable/rails/ext/jwt.rb
|
89
|
+
- lib/anycable/rails/helper.rb
|
86
90
|
- lib/anycable/rails/middlewares/executor.rb
|
87
91
|
- lib/anycable/rails/middlewares/log_tagging.rb
|
92
|
+
- lib/anycable/rails/object_serializer.rb
|
93
|
+
- lib/anycable/rails/pubsub_channel.rb
|
88
94
|
- lib/anycable/rails/rack.rb
|
89
95
|
- lib/anycable/rails/railtie.rb
|
90
96
|
- lib/anycable/rails/socket_id_tracking.rb
|
91
97
|
- lib/anycable/rails/version.rb
|
98
|
+
- lib/generators/anycable/bin/USAGE
|
99
|
+
- lib/generators/anycable/bin/bin_generator.rb
|
100
|
+
- lib/generators/anycable/bin/templates/bin/anycable-go.tt
|
92
101
|
- lib/generators/anycable/download/USAGE
|
93
102
|
- lib/generators/anycable/download/download_generator.rb
|
94
103
|
- lib/generators/anycable/setup/USAGE
|