hyper-operation 1.0.alpha1.5 → 1.0.0.lap28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -7
- data/.travis.yml +9 -20
- data/CODE_OF_CONDUCT.md +49 -0
- data/DOCS-POLICIES.md +582 -0
- data/DOCS.md +869 -0
- data/Gemfile +1 -5
- data/LICENSE.txt +21 -0
- data/README.md +77 -0
- data/Rakefile +2 -1
- data/dciy.toml +3 -0
- data/hyper-operation.gemspec +13 -16
- data/lib/hyper-operation.rb +5 -8
- data/lib/hyper-operation/api.rb +2 -2
- data/lib/hyper-operation/boot.rb +2 -3
- data/lib/hyper-operation/engine.rb +2 -2
- data/lib/hyper-operation/exception.rb +4 -30
- data/lib/hyper-operation/filters/acting_user.rb +1 -1
- data/lib/hyper-operation/http.rb +2 -2
- data/lib/hyper-operation/promise.rb +2 -28
- data/lib/hyper-operation/railway.rb +1 -1
- data/lib/hyper-operation/railway/dispatcher.rb +4 -8
- data/lib/hyper-operation/railway/params_wrapper.rb +2 -2
- data/lib/hyper-operation/railway/run.rb +49 -52
- data/lib/hyper-operation/railway/validations.rb +3 -10
- data/lib/hyper-operation/server_op.rb +19 -45
- data/lib/hyper-operation/transport/action_cable.rb +8 -8
- data/lib/hyper-operation/transport/client_drivers.rb +53 -94
- data/lib/hyper-operation/transport/connection.rb +10 -10
- data/lib/hyper-operation/transport/{hyperstack.rb → hyperloop.rb} +14 -19
- data/lib/hyper-operation/transport/{hyperstack_controller.rb → hyperloop_controller.rb} +52 -54
- data/lib/hyper-operation/transport/policy.rb +45 -41
- data/lib/hyper-operation/version.rb +2 -2
- data/lib/sources/{hyperstack → hyperloop}/pusher.js +0 -0
- metadata +51 -50
- data/lib/hyper-operation/transport/policy_diagnostics.rb +0 -106
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Hyperloop
|
2
2
|
class Operation
|
3
3
|
class Railway
|
4
4
|
|
@@ -28,8 +28,6 @@ module Hyperstack
|
|
28
28
|
rescue Exit => e
|
29
29
|
raise e unless e.state == :failed
|
30
30
|
add_error(param, symbol, message)
|
31
|
-
# use a bogus exit state which will skip adding
|
32
|
-
# a validation error (see catch block in process_validations method)
|
33
31
|
raise Exit.new(:abort_from_add_error, e.result)
|
34
32
|
end
|
35
33
|
end
|
@@ -49,22 +47,17 @@ module Hyperstack
|
|
49
47
|
when :failed
|
50
48
|
add_validation_error(i, "param validation #{i+1} aborted")
|
51
49
|
end
|
52
|
-
@state = :
|
50
|
+
@state = :failed
|
53
51
|
return # break does not work in Opal
|
54
52
|
rescue AccessViolation => e
|
55
53
|
add_validation_error(i, e)
|
56
|
-
@state = :
|
54
|
+
@state = :failed
|
57
55
|
@last_result = e
|
58
56
|
return # break does not work in Opal
|
59
57
|
rescue Exception => e
|
60
58
|
add_validation_error(i, e)
|
61
59
|
end
|
62
60
|
end
|
63
|
-
ensure
|
64
|
-
if @operation.has_errors?
|
65
|
-
@last_result ||= ValidationException.new(@operation.instance_variable_get('@errors'))
|
66
|
-
@state ||= :failed
|
67
|
-
end
|
68
61
|
end
|
69
62
|
end
|
70
63
|
end
|
@@ -1,30 +1,26 @@
|
|
1
1
|
require 'net/http' unless RUBY_ENGINE == 'opal'
|
2
2
|
|
3
|
-
module
|
3
|
+
module Hyperloop
|
4
4
|
class ServerOp < Operation
|
5
5
|
|
6
6
|
class << self
|
7
|
-
include
|
7
|
+
include React::IsomorphicHelpers
|
8
8
|
|
9
9
|
if RUBY_ENGINE == 'opal'
|
10
10
|
if on_opal_client?
|
11
11
|
def run(*args)
|
12
12
|
hash = _Railway.params_wrapper.combine_arg_array(args)
|
13
13
|
hash = serialize_params(hash)
|
14
|
-
|
15
|
-
"#{`window.
|
14
|
+
Hyperloop::HTTP.post(
|
15
|
+
"#{`window.HyperloopEnginePath`}/execute_remote",
|
16
16
|
payload: {json: {operation: name, params: hash}.to_json},
|
17
|
-
headers:
|
17
|
+
headers: {'X-CSRF-Token' => Hyperloop::ClientDrivers.opts[:form_authenticity_token] }
|
18
18
|
)
|
19
19
|
.then do |response|
|
20
20
|
deserialize_response response.json[:response]
|
21
21
|
end
|
22
22
|
.fail do |response|
|
23
|
-
|
24
|
-
const_get(response.json[:error_class]).new(response.json[:error])
|
25
|
-
rescue
|
26
|
-
Exception.new response.json[:error]
|
27
|
-
end
|
23
|
+
Exception.new response.json[:error]
|
28
24
|
end
|
29
25
|
end
|
30
26
|
elsif on_opal_server?
|
@@ -44,21 +40,19 @@ module Hyperstack
|
|
44
40
|
isomorphic_method(:internal_iso_run) do |f, klass_name, op_params|
|
45
41
|
f.send_to_server(klass_name, op_params)
|
46
42
|
f.when_on_server {
|
47
|
-
|
43
|
+
Hyperloop::ServerOp.run_from_client(:acting_user, controller, klass_name, *op_params)
|
48
44
|
}
|
49
45
|
end
|
50
46
|
|
51
47
|
def descendants_map_cache
|
52
48
|
# calling descendants alone may take 10ms in a complex app, so better cache it
|
53
|
-
@cached_descendants ||=
|
49
|
+
@cached_descendants ||= Hyperloop::ServerOp.descendants.map(&:to_s)
|
54
50
|
end
|
55
51
|
|
56
52
|
def run_from_client(security_param, controller, operation, params)
|
57
53
|
if Rails.env.production?
|
58
54
|
# in production everything is eager loaded so ServerOp.descendants is filled and can be used to guard the .constantize
|
59
|
-
unless
|
60
|
-
Hyperstack::InternalPolicy.raise_operation_access_violation(:illegal_remote_op_call, "Operation: #{operation} (in production)")
|
61
|
-
end
|
55
|
+
Hyperloop::InternalPolicy.raise_operation_access_violation unless Hyperloop::ServerOp.descendants_map_cache.include?(operation)
|
62
56
|
# however ...
|
63
57
|
else
|
64
58
|
# ... in development things are autoloaded on demand, thus ServerOp.descendants can be empty or partially filled and above guard
|
@@ -68,17 +62,15 @@ module Hyperstack
|
|
68
62
|
begin
|
69
63
|
const = Object.const_get(operation)
|
70
64
|
rescue NameError
|
71
|
-
|
72
|
-
end
|
73
|
-
unless const < Hyperstack::ServerOp
|
74
|
-
Hyperstack::InternalPolicy.raise_operation_access_violation(:illegal_remote_op_call, "Operation: #{operation} (not a ServerOp subclass)")
|
65
|
+
Hyperloop::InternalPolicy.raise_operation_access_violation
|
75
66
|
end
|
67
|
+
Hyperloop::InternalPolicy.raise_operation_access_violation unless const < Hyperloop::ServerOp
|
76
68
|
end
|
77
69
|
operation.constantize.class_eval do
|
78
70
|
if _Railway.params_wrapper.method_defined?(:controller)
|
79
71
|
params[:controller] = controller
|
80
72
|
elsif !_Railway.params_wrapper.method_defined?(security_param)
|
81
|
-
raise AccessViolation
|
73
|
+
raise AccessViolation
|
82
74
|
end
|
83
75
|
run(deserialize_params(params))
|
84
76
|
.then { |r| return { json: { response: serialize_response(r) } } }
|
@@ -88,27 +80,13 @@ module Hyperstack
|
|
88
80
|
handle_exception(e, operation, params)
|
89
81
|
end
|
90
82
|
|
91
|
-
def status(e)
|
92
|
-
if e.is_a? AccessViolation
|
93
|
-
403
|
94
|
-
elsif e.is_a? Operation::ValidationException
|
95
|
-
400
|
96
|
-
else
|
97
|
-
500
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
83
|
def handle_exception(e, operation, params)
|
102
|
-
if
|
103
|
-
params
|
104
|
-
|
105
|
-
|
106
|
-
params.each { |param, value| message << " #{param} => #{value.inspect.truncate(120, separator: '...')}" }
|
107
|
-
message << "\n#{e.details}" if e.respond_to? :details
|
108
|
-
e.__hyperstack_on_error(operation, params, message.join("\n"))
|
84
|
+
if defined? ::Rails
|
85
|
+
params.delete(:controller)
|
86
|
+
::Rails.logger.debug "\033[0;31;1mERROR: Hyperloop::ServerOp exception caught when running "\
|
87
|
+
"#{operation} with params \"#{params}\": #{e}\033[0;30;21m"
|
109
88
|
end
|
110
|
-
|
111
|
-
{ json: { error_class: e.class.to_s, error: e}, status: status(e) }
|
89
|
+
{ json: { error: e }, status: 500 }
|
112
90
|
end
|
113
91
|
|
114
92
|
|
@@ -122,17 +100,13 @@ module Hyperstack
|
|
122
100
|
end
|
123
101
|
request.body = {
|
124
102
|
operation: name,
|
125
|
-
params:
|
103
|
+
params: Hyperloop::Operation::ParamsWrapper.combine_arg_array(args)
|
126
104
|
}.to_json
|
127
105
|
promise.resolve http.request(request)
|
128
106
|
rescue Exception => e
|
129
107
|
promise.reject e
|
130
108
|
end
|
131
109
|
|
132
|
-
def headers
|
133
|
-
{}
|
134
|
-
end
|
135
|
-
|
136
110
|
def serialize_params(hash)
|
137
111
|
hash
|
138
112
|
end
|
@@ -174,7 +148,7 @@ module Hyperstack
|
|
174
148
|
[operation.instance_exec(*context, ®ulation)].flatten.compact.uniq.each do |channel|
|
175
149
|
unless operation.instance_variable_get(:@_dispatched_channels).include?(channel)
|
176
150
|
operation.instance_variable_set(:@_dispatched_channels, operation.instance_variable_get(:@_dispatched_channels) << channel)
|
177
|
-
|
151
|
+
Hyperloop.dispatch(channel: Hyperloop::InternalPolicy.channel_to_string(channel), operation: operation.class.name, params: serialized_params)
|
178
152
|
end
|
179
153
|
end
|
180
154
|
end
|
@@ -3,7 +3,7 @@ module ApplicationCable
|
|
3
3
|
class Connection < ActionCable::Connection::Base; end
|
4
4
|
end
|
5
5
|
|
6
|
-
module
|
6
|
+
module Hyperloop
|
7
7
|
class ActionCableChannel < ApplicationCable::Channel
|
8
8
|
class << self
|
9
9
|
def subscriptions
|
@@ -12,28 +12,28 @@ module Hyperstack
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def inc_subscription
|
15
|
-
self.class.subscriptions[params[:
|
16
|
-
self.class.subscriptions[params[:
|
15
|
+
self.class.subscriptions[params[:hyperloop_channel]] =
|
16
|
+
self.class.subscriptions[params[:hyperloop_channel]] + 1
|
17
17
|
end
|
18
18
|
|
19
19
|
def dec_subscription
|
20
|
-
self.class.subscriptions[params[:
|
21
|
-
self.class.subscriptions[params[:
|
20
|
+
self.class.subscriptions[params[:hyperloop_channel]] =
|
21
|
+
self.class.subscriptions[params[:hyperloop_channel]] - 1
|
22
22
|
end
|
23
23
|
|
24
24
|
def subscribed
|
25
25
|
session_id = params["client_id"]
|
26
|
-
authorization =
|
26
|
+
authorization = Hyperloop.authorization(params["salt"], params["hyperloop_channel"], session_id)
|
27
27
|
if params["authorization"] == authorization
|
28
28
|
inc_subscription
|
29
|
-
stream_from "
|
29
|
+
stream_from "hyperloop-#{params[:hyperloop_channel]}"
|
30
30
|
else
|
31
31
|
reject
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
def unsubscribed
|
36
|
-
|
36
|
+
Hyperloop::Connection.disconnect(params[:hyperloop_channel]) if dec_subscription == 0
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -1,18 +1,14 @@
|
|
1
1
|
#### this is going to need some refactoring so that HyperMesh can add its methods in here...
|
2
2
|
|
3
|
-
module
|
3
|
+
module Hyperloop
|
4
4
|
# Client side handling of synchronization messages
|
5
5
|
# When a synchronization message comes in, the client will sync_dispatch
|
6
6
|
# We use ERB to determine the configuration and implement the appropriate
|
7
7
|
# client interface to sync_change or sync_destroy
|
8
8
|
|
9
|
-
def self.anti_csrf_token
|
10
|
-
ClientDrivers.opts[:form_authenticity_token]
|
11
|
-
end
|
12
|
-
|
13
9
|
class Application
|
14
|
-
extend
|
15
|
-
|
10
|
+
extend React::IsomorphicHelpers::ClassMethods
|
11
|
+
|
16
12
|
if on_opal_client?
|
17
13
|
def self.acting_user_id
|
18
14
|
ClientDrivers.opts[:acting_user_id]
|
@@ -35,41 +31,22 @@ module Hyperstack
|
|
35
31
|
|
36
32
|
|
37
33
|
if RUBY_ENGINE == 'opal'
|
38
|
-
# Patch in a dummy copy of Model.load in case we are not using models
|
39
|
-
# this will be defined properly by hyper-model
|
40
|
-
module Model
|
41
|
-
def self.load
|
42
|
-
Promise.new.tap { |promise| promise.resolve(yield) }
|
43
|
-
end unless respond_to?(:load)
|
44
|
-
end
|
45
|
-
|
46
34
|
def self.connect(*channels)
|
47
35
|
channels.each do |channel|
|
48
36
|
if channel.is_a? Class
|
49
37
|
IncomingBroadcast.connect_to(channel.name)
|
50
38
|
elsif channel.is_a?(String) || channel.is_a?(Array)
|
51
39
|
IncomingBroadcast.connect_to(*channel)
|
52
|
-
elsif channel.
|
53
|
-
|
54
|
-
channel.id
|
55
|
-
end.then do |id|
|
56
|
-
raise "Hyperstack.connect cannot connect to #{channel.inspect}. "\
|
57
|
-
"The id is nil. This can be caused by connecting to a model "\
|
58
|
-
"that is not saved, or that does not exist." unless id
|
59
|
-
IncomingBroadcast.connect_to(channel.class.name, id)
|
60
|
-
end
|
40
|
+
elsif channel.id
|
41
|
+
IncomingBroadcast.connect_to(channel.class.name, channel.id)
|
61
42
|
else
|
62
|
-
raise "
|
63
|
-
"Channels must be either a class, or a class name,\n"\
|
64
|
-
"a string in the form 'ClassName-id',\n"\
|
65
|
-
"an array in the form [class, id] or [class-name, id],\n"\
|
66
|
-
"or an object that responds to the id method with a non-nil value"
|
43
|
+
raise "cannot connect to model before it has been saved"
|
67
44
|
end
|
68
45
|
end
|
69
46
|
end
|
70
47
|
|
71
48
|
def self.connect_session
|
72
|
-
connect(['
|
49
|
+
connect(['Hyperloop::Session', ClientDrivers.opts[:id].split('-').last])
|
73
50
|
end
|
74
51
|
|
75
52
|
def self.action_cable_consumer
|
@@ -84,14 +61,12 @@ module Hyperstack
|
|
84
61
|
|
85
62
|
def self.add_connection(channel_name, id = nil)
|
86
63
|
channel_string = "#{channel_name}#{'-'+id.to_s if id}"
|
87
|
-
return if open_channels.include? channel_string
|
88
64
|
open_channels << channel_string
|
89
65
|
channel_string
|
90
66
|
end
|
91
67
|
|
92
68
|
def self.connect_to(channel_name, id = nil)
|
93
69
|
channel_string = add_connection(channel_name, id)
|
94
|
-
return unless channel_string # already connected!
|
95
70
|
if ClientDrivers.opts[:transport] == :pusher
|
96
71
|
channel = "#{ClientDrivers.opts[:channel]}-#{channel_string}"
|
97
72
|
%x{
|
@@ -99,24 +74,23 @@ module Hyperstack
|
|
99
74
|
channel.bind('dispatch', #{ClientDrivers.opts[:dispatch]})
|
100
75
|
channel.bind('pusher:subscription_succeeded', #{lambda {ClientDrivers.get_queued_data("connect-to-transport", channel_string)}})
|
101
76
|
}
|
102
|
-
@pusher_dispatcher_registered = true
|
103
77
|
elsif ClientDrivers.opts[:transport] == :action_cable
|
104
78
|
channel = "#{ClientDrivers.opts[:channel]}-#{channel_string}"
|
105
|
-
|
79
|
+
Hyperloop::HTTP.post(ClientDrivers.polling_path('action-cable-auth', channel), headers: { 'X-CSRF-Token' => ClientDrivers.opts[:form_authenticity_token] }).then do |response|
|
106
80
|
%x{
|
107
81
|
var fix_opal_0110 = 'return';
|
108
|
-
#{
|
82
|
+
#{Hyperloop.action_cable_consumer}.subscriptions.create(
|
109
83
|
{
|
110
|
-
channel: "
|
84
|
+
channel: "Hyperloop::ActionCableChannel",
|
111
85
|
client_id: #{ClientDrivers.opts[:id]},
|
112
|
-
|
86
|
+
hyperloop_channel: #{channel_string},
|
113
87
|
authorization: #{response.json[:authorization]},
|
114
88
|
salt: #{response.json[:salt]}
|
115
89
|
},
|
116
90
|
{
|
117
91
|
connected: function() {
|
118
92
|
if (#{ClientDrivers.env == 'development'}) { console.log("ActionCable connected to: ", channel_string); }
|
119
|
-
#{ClientDrivers.
|
93
|
+
#{ClientDrivers.get_queued_data("connect-to-transport", channel_string)}
|
120
94
|
},
|
121
95
|
received: function(data) {
|
122
96
|
if (#{ClientDrivers.env == 'development'}) { console.log("ActionCable received: ", data); }
|
@@ -127,14 +101,14 @@ module Hyperstack
|
|
127
101
|
}
|
128
102
|
end
|
129
103
|
else
|
130
|
-
|
104
|
+
Hyperloop::HTTP.get(ClientDrivers.polling_path(:subscribe, channel_string))
|
131
105
|
end
|
132
106
|
end
|
133
107
|
end
|
134
108
|
end
|
135
109
|
|
136
110
|
class ClientDrivers
|
137
|
-
include
|
111
|
+
include React::IsomorphicHelpers
|
138
112
|
|
139
113
|
def self.sync_dispatch(data)
|
140
114
|
# TODO old synchromesh double checked at this point to make sure that this client
|
@@ -142,7 +116,7 @@ module Hyperstack
|
|
142
116
|
data[:operation].constantize.dispatch_from_server(data[:params])
|
143
117
|
end
|
144
118
|
|
145
|
-
# save the configuration info needed in window.
|
119
|
+
# save the configuration info needed in window.HyperloopOpts
|
146
120
|
|
147
121
|
# we keep a list of all channels by session with connections in progress
|
148
122
|
# for each broadcast we check the list, and add the message to a queue for that
|
@@ -151,51 +125,45 @@ module Hyperstack
|
|
151
125
|
# will remove the session from the list.
|
152
126
|
|
153
127
|
prerender_footer do |controller|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
165
|
-
controller.session.delete 'hyperstack-dummy-init' unless controller.session.id
|
166
|
-
id = "#{SecureRandom.uuid}-#{controller.session.id}"
|
167
|
-
auto_connections = Hyperstack::AutoConnect.channels(id, controller.acting_user) rescue []
|
128
|
+
next if Hyperloop.transport == :none
|
129
|
+
if defined?(PusherFake)
|
130
|
+
path = ::Rails.application.routes.routes.detect do |route|
|
131
|
+
route.app == Hyperloop::Engine ||
|
132
|
+
(route.app.respond_to?(:app) && route.app.app == Hyperloop::Engine)
|
133
|
+
end.path.spec
|
134
|
+
pusher_fake_js = PusherFake.javascript(
|
135
|
+
auth: { headers: { 'X-CSRF-Token' => controller.send(:form_authenticity_token) } },
|
136
|
+
authEndpoint: "#{path}/hyperloop-pusher-auth"
|
137
|
+
)
|
168
138
|
end
|
139
|
+
controller.session.delete 'hyperloop-dummy-init' unless controller.session.id
|
140
|
+
id = "#{SecureRandom.uuid}-#{controller.session.id}"
|
141
|
+
auto_connections = Hyperloop::AutoConnect.channels(id, controller.acting_user)
|
169
142
|
config_hash = {
|
170
|
-
transport:
|
143
|
+
transport: Hyperloop.transport,
|
171
144
|
id: id,
|
172
145
|
acting_user_id: (controller.acting_user && controller.acting_user.id),
|
173
146
|
env: ::Rails.env,
|
174
|
-
client_logging:
|
147
|
+
client_logging: Hyperloop.client_logging,
|
175
148
|
pusher_fake_js: pusher_fake_js,
|
176
|
-
key:
|
177
|
-
cluster:
|
178
|
-
encrypted:
|
179
|
-
channel:
|
149
|
+
key: Hyperloop.key,
|
150
|
+
cluster: Hyperloop.cluster,
|
151
|
+
encrypted: Hyperloop.encrypted,
|
152
|
+
channel: Hyperloop.channel,
|
180
153
|
form_authenticity_token: controller.send(:form_authenticity_token),
|
181
|
-
seconds_between_poll:
|
154
|
+
seconds_between_poll: Hyperloop.seconds_between_poll,
|
182
155
|
auto_connect: auto_connections
|
183
156
|
}
|
184
157
|
path = ::Rails.application.routes.routes.detect do |route|
|
185
158
|
# not sure why the second check is needed. It happens in the test app
|
186
|
-
route.app ==
|
187
|
-
end
|
188
|
-
if path
|
189
|
-
path = path.path.spec
|
190
|
-
"<script type='text/javascript'>\n"\
|
191
|
-
"window.HyperstackEnginePath = '#{path}';\n"\
|
192
|
-
"window.HyperstackOpts = #{config_hash.to_json}\n"\
|
193
|
-
"</script>\n"
|
194
|
-
else
|
195
|
-
"<script type='text/javascript'>\n"\
|
196
|
-
"window.HyperstackOpts = #{config_hash.to_json}\n"\
|
197
|
-
"</script>\n"
|
159
|
+
route.app == Hyperloop::Engine or (route.app.respond_to?(:app) and route.app.app == Hyperloop::Engine)
|
198
160
|
end
|
161
|
+
raise 'Hyperloop::Engine mount point not found. Check your config/routes.rb file' unless path
|
162
|
+
path = path.path.spec
|
163
|
+
"<script type='text/javascript'>\n"\
|
164
|
+
"window.HyperloopEnginePath = '#{path}';\n"\
|
165
|
+
"window.HyperloopOpts = #{config_hash.to_json}\n"\
|
166
|
+
"</script>\n"
|
199
167
|
end if RUBY_ENGINE != 'opal'
|
200
168
|
|
201
169
|
class << self
|
@@ -213,14 +181,8 @@ module Hyperstack
|
|
213
181
|
f.when_on_server { ::Rails.env }
|
214
182
|
end
|
215
183
|
|
216
|
-
def self.complete_connection(channel, retries = 10)
|
217
|
-
get_queued_data('connect-to-transport', channel).fail do
|
218
|
-
after(0.25) { complete_connection(channel, retries - 1) } unless retries.zero?
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
184
|
def self.get_queued_data(operation, channel = nil, opts = {})
|
223
|
-
|
185
|
+
Hyperloop::HTTP.get(polling_path(operation, channel), opts).then do |response|
|
224
186
|
response.json.each do |data|
|
225
187
|
`console.log("simple_poller received: ", data)` if ClientDrivers.env == 'development'
|
226
188
|
sync_dispatch(data[1])
|
@@ -232,11 +194,11 @@ module Hyperstack
|
|
232
194
|
|
233
195
|
if @initialized
|
234
196
|
# 1) skip initialization if already initialized
|
235
|
-
if on_opal_client? &&
|
197
|
+
if on_opal_client? && Hyperloop.action_cable_consumer
|
236
198
|
# 2) if running action_cable make sure connection is up after pinging the server_up
|
237
199
|
# action cable closes the connection if files change on the server
|
238
|
-
|
239
|
-
`#{
|
200
|
+
Hyperloop::HTTP.get("#{`window.HyperloopEnginePath`}/server_up") do
|
201
|
+
`#{Hyperloop.action_cable_consumer}.connection.open()` if `#{Hyperloop.action_cable_consumer}.connection.disconnected`
|
240
202
|
end
|
241
203
|
end
|
242
204
|
return
|
@@ -246,12 +208,9 @@ module Hyperstack
|
|
246
208
|
@opts = {}
|
247
209
|
|
248
210
|
if on_opal_client?
|
249
|
-
|
250
|
-
@opts = Hash.new(`window.
|
251
|
-
|
252
|
-
if opts[:transport] != :none && `typeof(window.HyperstackEnginePath) == 'undefined'`
|
253
|
-
raise "No hyperstack mount point found!\nCheck your Rails routes.rb file";
|
254
|
-
end
|
211
|
+
|
212
|
+
@opts = Hash.new(`window.HyperloopOpts`)
|
213
|
+
|
255
214
|
|
256
215
|
if opts[:transport] == :pusher
|
257
216
|
|
@@ -271,18 +230,18 @@ module Hyperstack
|
|
271
230
|
h = {
|
272
231
|
encrypted: #{opts[:encrypted]},
|
273
232
|
cluster: #{opts[:cluster]},
|
274
|
-
authEndpoint: window.
|
233
|
+
authEndpoint: window.HyperloopEnginePath+'/hyperloop-pusher-auth',
|
275
234
|
auth: {headers: {'X-CSRF-Token': #{opts[:form_authenticity_token]}}}
|
276
235
|
};
|
277
236
|
pusher_api = new Pusher(#{opts[:key]}, h)
|
278
237
|
}
|
279
238
|
opts[:pusher_api] = pusher_api
|
280
239
|
end
|
281
|
-
|
240
|
+
Hyperloop.connect(*opts[:auto_connect])
|
282
241
|
elsif opts[:transport] == :action_cable
|
283
242
|
opts[:action_cable_consumer] =
|
284
243
|
`ActionCable.createConsumer.apply(ActionCable, #{[*opts[:action_cable_consumer_url]]})`
|
285
|
-
|
244
|
+
Hyperloop.connect(*opts[:auto_connect])
|
286
245
|
elsif opts[:transport] == :simple_poller
|
287
246
|
opts[:auto_connect].each { |channel| IncomingBroadcast.add_connection(*channel) }
|
288
247
|
every(opts[:seconds_between_poll]) do
|
@@ -293,7 +252,7 @@ module Hyperstack
|
|
293
252
|
end
|
294
253
|
|
295
254
|
def self.polling_path(to, id = nil)
|
296
|
-
s = "#{`window.
|
255
|
+
s = "#{`window.HyperloopEnginePath`}/hyperloop-#{to}/#{opts[:id]}"
|
297
256
|
s = "#{s}/#{id}" if id
|
298
257
|
s
|
299
258
|
end
|