isomorfeus-transport 1.0.0.zeta23 → 2.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -21
  3. data/README.md +27 -36
  4. data/lib/isomorfeus/transport/client_processor.rb +35 -30
  5. data/lib/isomorfeus/transport/config.rb +182 -158
  6. data/lib/isomorfeus/transport/hamster_session_store.rb +96 -0
  7. data/lib/isomorfeus/transport/handler/authentication_handler.rb +70 -70
  8. data/lib/isomorfeus/transport/imports.rb +9 -0
  9. data/lib/isomorfeus/transport/middlewares.rb +13 -13
  10. data/lib/isomorfeus/transport/rack_middleware.rb +59 -55
  11. data/lib/isomorfeus/transport/request_agent.rb +34 -34
  12. data/lib/isomorfeus/transport/response_agent.rb +23 -23
  13. data/lib/isomorfeus/transport/server_processor.rb +129 -101
  14. data/lib/isomorfeus/transport/server_socket_processor.rb +54 -54
  15. data/lib/isomorfeus/transport/ssr_login.rb +28 -28
  16. data/lib/isomorfeus/transport/version.rb +5 -5
  17. data/lib/isomorfeus/transport/{websocket.rb → websocket_client.rb} +123 -123
  18. data/lib/isomorfeus/transport.rb +200 -213
  19. data/lib/isomorfeus-transport.rb +70 -62
  20. data/lib/lucid_authentication/mixin.rb +122 -124
  21. data/lib/lucid_channel/base.rb +8 -11
  22. data/lib/lucid_channel/mixin.rb +105 -50
  23. data/lib/lucid_handler/base.rb +8 -9
  24. data/lib/lucid_handler/mixin.rb +27 -27
  25. data/node_modules/.package-lock.json +27 -0
  26. data/node_modules/ws/LICENSE +19 -0
  27. data/node_modules/ws/README.md +496 -0
  28. data/node_modules/ws/browser.js +8 -0
  29. data/node_modules/ws/index.js +13 -0
  30. data/node_modules/ws/lib/buffer-util.js +126 -0
  31. data/node_modules/ws/lib/constants.js +12 -0
  32. data/node_modules/ws/lib/event-target.js +266 -0
  33. data/node_modules/ws/lib/extension.js +203 -0
  34. data/node_modules/ws/lib/limiter.js +55 -0
  35. data/node_modules/ws/lib/permessage-deflate.js +511 -0
  36. data/node_modules/ws/lib/receiver.js +612 -0
  37. data/node_modules/ws/lib/sender.js +414 -0
  38. data/node_modules/ws/lib/stream.js +180 -0
  39. data/node_modules/ws/lib/subprotocol.js +62 -0
  40. data/node_modules/ws/lib/validation.js +124 -0
  41. data/node_modules/ws/lib/websocket-server.js +485 -0
  42. data/node_modules/ws/lib/websocket.js +1144 -0
  43. data/node_modules/ws/package.json +61 -0
  44. data/node_modules/ws/wrapper.mjs +8 -0
  45. data/package.json +6 -0
  46. metadata +76 -54
  47. data/lib/isomorfeus/transport/dbm_session_store.rb +0 -51
@@ -1,213 +1,200 @@
1
- module Isomorfeus
2
- module Transport
3
- class << self
4
- if RUBY_ENGINE == 'opal'
5
- attr_accessor :socket
6
-
7
- def delay(ms = 1000, &block)
8
- `setTimeout(#{block.to_n}, #{ms})`
9
- end
10
-
11
- def init
12
- @requests_in_progress = { requests: {}, agent_ids: {} }
13
- @socket = nil
14
- @initialized = false
15
- promise_connect if Isomorfeus.on_browser?
16
- true
17
- end
18
-
19
- def promise_connect
20
- promise = Promise.new
21
- if @socket && @socket.ready_state < 2
22
- promise.resolve(true)
23
- return promise
24
- end
25
- if Isomorfeus.on_browser?
26
- window_protocol = `window.location.protocol`
27
- ws_protocol = window_protocol == 'https:' ? 'wss:' : 'ws:'
28
- ws_url = "#{ws_protocol}//#{`window.location.host`}#{Isomorfeus.api_websocket_path}"
29
- else
30
- ws_url = Isomorfeus::TopLevel.transport_ws_url
31
- end
32
- @socket = Isomorfeus::Transport::Websocket.new(ws_url)
33
- @socket.on_error do
34
- @socket.close
35
- delay 1000 do
36
- Isomorfeus::Transport.promise_connect
37
- end
38
- end
39
- @socket.on_message do |event|
40
- json_hash = `Opal.Hash.$new(JSON.parse(event.data))`
41
- Isomorfeus::Transport::ClientProcessor.process(json_hash)
42
- end
43
- @socket.on_open do |event|
44
- if @initialized
45
- requests_in_progress[:requests].each_key do |request|
46
- agent = get_agent_for_request_in_progress(request)
47
- promise_send_request(request) if agent && !agent.sent
48
- end
49
- promise.resolve(true)
50
- else
51
- @initialized = true
52
- init_promises = []
53
- Isomorfeus.transport_init_class_names.each do |constant|
54
- result = constant.constantize.send(:init)
55
- init_promises << result if result.class == Promise
56
- end
57
- if init_promises.size > 0
58
- Promise.when(*init_promises).then { promise.resolve(true) }
59
- end
60
- end
61
- end
62
- promise
63
- end
64
-
65
- def disconnect
66
- @socket.close if @socket
67
- @socket = nil
68
- end
69
-
70
- def promise_send_path(*path, &block)
71
- request = {}
72
- inject_path = path[0...-1]
73
- last_inject_path_el = inject_path.last
74
- last_path_el = path.last
75
- inject_path.inject(request) do |memo, key|
76
- if key == last_inject_path_el
77
- memo[key] = last_path_el
78
- else
79
- memo[key] = {}
80
- end
81
- end
82
- Isomorfeus::Transport.promise_send_request(request, &block)
83
- end
84
-
85
- def promise_send_request(request, &block)
86
- agent = if request_in_progress?(request)
87
- get_agent_for_request_in_progress(request)
88
- else
89
- Isomorfeus::Transport::RequestAgent.new(request)
90
- end
91
- unless agent.sent
92
- if block_given?
93
- agent.promise.then do |response|
94
- block.call(response)
95
- end
96
- end
97
- register_request_in_progress(request, agent.id)
98
- Isomorfeus.raise_error(message: 'No socket!') unless @socket
99
- begin
100
- @socket.send(`JSON.stringify(#{{request: { agent_ids: { agent.id => request }}}.to_n})`)
101
- agent.sent = true
102
- delay(Isomorfeus.on_ssr? ? 8000 : 20000) do
103
- unless agent.promise.realized?
104
- agent.promise.reject({agent_response: { error: 'Request timeout!' }, full_response: {}})
105
- end
106
- end
107
- rescue
108
- @socket.close
109
- delay 5000 do
110
- Isomorfeus::Transport.promise_connect
111
- end
112
- end
113
- end
114
- agent.promise
115
- end
116
-
117
- def send_notification(channel_class, channel, message)
118
- Isomorfeus.raise_error(message: 'No socket!') unless @socket
119
- @socket.send(`JSON.stringify(#{{notification: { class: channel_class.name, channel: channel, message: message}}.to_n})`)
120
- true
121
- end
122
-
123
- def subscribe(channel_class, channel, &block)
124
- request = { subscribe: true, class: channel_class.name, channel: channel }
125
- if request_in_progress?(request)
126
- agent = get_agent_for_request_in_progress(request)
127
- else
128
- agent = Isomorfeus::Transport::RequestAgent.new(request)
129
- register_request_in_progress(request, agent.id)
130
- Isomorfeus.raise_error(message: 'No socket!') unless @socket
131
- @socket.send(`JSON.stringify(#{{subscribe: { agent_ids: { agent.id => request }}}.to_n})`)
132
- end
133
- result_promise = agent.promise.then do |agent|
134
- agent.response
135
- end
136
- if block_given?
137
- result_promise = result_promise.then do |response|
138
- block.call(response)
139
- end
140
- end
141
- result_promise
142
- end
143
-
144
- def unsubscribe(channel_class, channel, &block)
145
- request = { unsubscribe: true, class: channel_class.name, channel: channel }
146
- if request_in_progress?(request)
147
- agent = get_agent_for_request_in_progress(request)
148
- else
149
- agent = Isomorfeus::Transport::RequestAgent.new(request)
150
- register_request_in_progress(request, agent.id)
151
- Isomorfeus.raise_error(message: 'No socket!') unless @socket
152
- @socket.send(`JSON.stringify(#{{unsubscribe: { agent_ids: { agent.id => request }}}.to_n})`)
153
- end
154
- result_promise = agent.promise.then do |agent|
155
- agent.response
156
- end
157
- if block_given?
158
- result_promise = result_promise.then do |response|
159
- block.call(response)
160
- end
161
- end
162
- result_promise
163
- end
164
-
165
- def busy?
166
- @requests_in_progress[:requests].size != 0
167
- end
168
-
169
- def requests_in_progress
170
- @requests_in_progress
171
- end
172
-
173
- def request_in_progress?(request)
174
- @requests_in_progress[:requests].key?(request)
175
- end
176
-
177
- def get_agent_for_request_in_progress(request)
178
- agent_id = @requests_in_progress[:requests][request]
179
- Isomorfeus::Transport::RequestAgent.get(agent_id)
180
- end
181
-
182
- def register_request_in_progress(request, agent_id)
183
- @requests_in_progress[:requests][request] = agent_id
184
- @requests_in_progress[:agent_ids][agent_id] = request
185
- end
186
-
187
- def unregister_request_in_progress(agent_id)
188
- request = @requests_in_progress[:agent_ids].delete(agent_id)
189
- @requests_in_progress[:requests].delete(request)
190
- end
191
- else # RUBY_ENGINE
192
- def send_notification(channel_class, channel, message)
193
- Thread.current[:isomorfeus_pub_sub_client].publish(Oj.dump({notification: { class: channel_class.name, channel: channel, message: message}}, mode: :strict))
194
- true
195
- end
196
-
197
- def subscribe(channel_class, channel, &block)
198
- Thread.current[:isomorfeus_pub_sub_client].subscribe(channel)
199
- result_promise = Promise.new
200
- result_promise.resolve({ success: channel })
201
- result_promise
202
- end
203
-
204
- def unsubscribe(channel_class, channel, &block)
205
- Thread.current[:isomorfeus_pub_sub_client].unsubscribe(channel)
206
- result_promise = Promise.new
207
- result_promise.resolve({ success: channel })
208
- result_promise
209
- end
210
- end # RUBY_ENGINE
211
- end
212
- end
213
- end
1
+ module Isomorfeus
2
+ module Transport
3
+ class << self
4
+ if RUBY_ENGINE == 'opal'
5
+ attr_accessor :socket
6
+
7
+ def init
8
+ @socket = nil
9
+ @initialized = false
10
+ promise_connect if Isomorfeus.on_browser? || Isomorfeus.on_mobile?
11
+ true
12
+ end
13
+
14
+ def promise_connect
15
+ promise = Promise.new
16
+ if @socket && @socket.ready_state < 2
17
+ promise.resolve(true)
18
+ return promise
19
+ end
20
+ if Isomorfeus.on_browser?
21
+ window_protocol = `window.location.protocol`
22
+ ws_protocol = window_protocol == 'https:' ? 'wss:' : 'ws:'
23
+ ws_url = "#{ws_protocol}//#{`window.location.host`}#{Isomorfeus.api_websocket_path}"
24
+ else
25
+ ws_url = "#{Isomorfeus::TopLevel.transport_ws_url}"
26
+ end
27
+ @socket = Isomorfeus::Transport::WebsocketClient.new(ws_url)
28
+ @socket.on_error do |error|
29
+ if Isomorfeus.on_browser?
30
+ `console.warn('Isomorfeus::Transport: Will try again, but so far error connecting:', error)`
31
+ @socket.close
32
+ after 1000 do
33
+ Isomorfeus::Transport.promise_connect
34
+ end
35
+ else
36
+ Isomorfeus.raise_error(message: error.JS[:message], stack: error.JS[:stack])
37
+ end
38
+ end
39
+ @socket.on_message do |event|
40
+ json_hash = `Opal.Hash.$new(JSON.parse(event.data))`
41
+ Isomorfeus::Transport::ClientProcessor.process(json_hash)
42
+ end
43
+ @socket.on_open do |event|
44
+ if @initialized
45
+ requests_in_progress[:requests].each_key do |request|
46
+ agent = get_agent_for_request_in_progress(request)
47
+ promise_send_request(request) if agent && !agent.sent
48
+ end
49
+ promise.resolve(true)
50
+ else
51
+ @initialized = true
52
+ init_promises = []
53
+ Isomorfeus.transport_init_class_names.each do |constant|
54
+ result = constant.constantize.send(:init)
55
+ init_promises << result if result.class == Promise
56
+ end
57
+ if init_promises.size > 0
58
+ Promise.when(*init_promises).then { promise.resolve(true) }
59
+ end
60
+ end
61
+ end
62
+ promise
63
+ end
64
+
65
+ def disconnect
66
+ @socket.close if @socket
67
+ @socket = nil
68
+ end
69
+
70
+ def promise_send_path(*path, &block)
71
+ request = {}
72
+ inject_path = path[0...-1]
73
+ last_inject_path_el = inject_path.last
74
+ last_path_el = path.last
75
+ inject_path.inject(request) do |memo, key|
76
+ if key == last_inject_path_el
77
+ memo[key] = last_path_el
78
+ else
79
+ memo[key] = {}
80
+ end
81
+ end
82
+ Isomorfeus::Transport.promise_send_request(request, &block)
83
+ end
84
+
85
+ def promise_send_request(request, &block)
86
+ agent = if request_in_progress?(request)
87
+ get_agent_for_request_in_progress(request)
88
+ else
89
+ Isomorfeus::Transport::RequestAgent.new(request)
90
+ end
91
+ unless agent.sent
92
+ if block_given?
93
+ agent.promise.then do |response|
94
+ block.call(response)
95
+ end
96
+ end
97
+ register_request_in_progress(request, agent.id)
98
+ Isomorfeus.raise_error(message: 'No socket!') unless @socket
99
+ begin
100
+ @socket.send(`JSON.stringify(#{{request: { agent_ids: { agent.id => request }}}.to_n})`)
101
+ agent.sent = true
102
+ after(Isomorfeus.on_ssr? ? 8000 : 20000) do
103
+ unless agent.promise.realized?
104
+ agent.promise.reject({agent_response: { error: 'Request timeout!' }, full_response: {}})
105
+ end
106
+ end
107
+ rescue
108
+ @socket.close
109
+ after 5000 do
110
+ Isomorfeus::Transport.promise_connect
111
+ end
112
+ end
113
+ end
114
+ agent.promise
115
+ end
116
+
117
+ def send_message(channel_class, channel, message)
118
+ Isomorfeus.raise_error(message: 'No socket!') unless @socket
119
+ @socket.send(`JSON.stringify(#{{ notification: { class: channel_class.name, channel: channel, message: message }}.to_n})`)
120
+ true
121
+ end
122
+
123
+ def promise_subscribe(channel_class_name, channel)
124
+ request = { subscribe: true, class: channel_class_name, channel: channel }
125
+ if request_in_progress?(request)
126
+ agent = get_agent_for_request_in_progress(request)
127
+ else
128
+ agent = Isomorfeus::Transport::RequestAgent.new(request)
129
+ register_request_in_progress(request, agent.id)
130
+ Isomorfeus.raise_error(message: 'No socket!') unless @socket
131
+ @socket.send(`JSON.stringify(#{{ subscribe: { agent_ids: { agent.id => request }}}.to_n})`)
132
+ end
133
+ result_promise = agent.promise.then do |agent|
134
+ agent.response
135
+ end
136
+ result_promise
137
+ end
138
+
139
+ def promise_unsubscribe(channel_class_name, channel)
140
+ request = { unsubscribe: true, class: channel_class_name, channel: channel }
141
+ if request_in_progress?(request)
142
+ agent = get_agent_for_request_in_progress(request)
143
+ else
144
+ agent = Isomorfeus::Transport::RequestAgent.new(request)
145
+ register_request_in_progress(request, agent.id)
146
+ Isomorfeus.raise_error(message: 'No socket!') unless @socket
147
+ @socket.send(`JSON.stringify(#{{ unsubscribe: { agent_ids: { agent.id => request }}}.to_n})`)
148
+ end
149
+ result_promise = agent.promise.then do |agent|
150
+ agent.response
151
+ end
152
+ result_promise
153
+ end
154
+
155
+ def busy?
156
+ requests_in_progress[:requests].size != 0
157
+ end
158
+
159
+ def requests_in_progress
160
+ @requests_in_progress ||= { requests: {}, agent_ids: {} }
161
+ end
162
+
163
+ def request_in_progress?(request)
164
+ requests_in_progress[:requests].key?(request)
165
+ end
166
+
167
+ def get_agent_for_request_in_progress(request)
168
+ agent_id = requests_in_progress[:requests][request]
169
+ Isomorfeus::Transport::RequestAgent.get(agent_id)
170
+ end
171
+
172
+ def register_request_in_progress(request, agent_id)
173
+ requests_in_progress[:requests][request] = agent_id
174
+ requests_in_progress[:agent_ids][agent_id] = request
175
+ end
176
+
177
+ def unregister_request_in_progress(agent_id)
178
+ request = requests_in_progress[:agent_ids].delete(agent_id)
179
+ requests_in_progress[:requests].delete(request)
180
+ end
181
+ else # RUBY_ENGINE
182
+ def send_message(channel_class, channel, message)
183
+ channel_class_name = channel_class.name
184
+ Isomorfeus.pub_sub_client.publish("#{channel_class_name}_#{channel}", Oj.dump({notification: { class: channel_class_name, channel: channel, message: message}}, mode: :strict))
185
+ true
186
+ end
187
+
188
+ def promise_subscribe(channel_class, channel, &block)
189
+ Isomorfeus.pub_sub_client.subscribe(channel)
190
+ Promise.new.resolve({ success: channel })
191
+ end
192
+
193
+ def promise_unsubscribe(channel_class, channel, &block)
194
+ Isomorfeus.pub_sub_client.unsubscribe(channel)
195
+ Promise.new.resolve({ success: channel })
196
+ end
197
+ end # RUBY_ENGINE
198
+ end
199
+ end
200
+ end
@@ -1,62 +1,70 @@
1
- require 'isomorfeus-policy'
2
- require 'lucid_authentication/mixin'
3
- if RUBY_ENGINE == 'opal'
4
- require 'json'
5
- require 'isomorfeus/execution_environment'
6
- require 'isomorfeus/transport/version'
7
- require 'isomorfeus/transport/config'
8
- require 'isomorfeus/transport/request_agent'
9
- require 'isomorfeus/transport/client_processor'
10
- require 'isomorfeus/transport/websocket'
11
- require 'isomorfeus/transport'
12
- require 'isomorfeus/transport/ssr_login'
13
- require 'lucid_channel/mixin'
14
- require 'lucid_channel/base'
15
- Isomorfeus.zeitwerk.push_dir('channels')
16
- Isomorfeus.add_client_init_class_name('Isomorfeus::Transport')
17
- Isomorfeus.add_transport_init_class_name('Isomorfeus::Transport::SsrLogin') if Isomorfeus.on_ssr?
18
- else
19
- require 'base64'
20
- require 'digest'
21
- require 'bcrypt'
22
- require 'ostruct'
23
- require 'socket'
24
- require 'oj'
25
- require 'websocket/driver'
26
- require 'active_support'
27
- require 'iodine'
28
- require 'dbm'
29
- require 'isomorfeus/transport/dbm_session_store'
30
- opal_path = Gem::Specification.find_by_name('opal').full_gem_path
31
- promise_path = File.join(opal_path, 'stdlib', 'promise.rb')
32
- require promise_path
33
- require 'isomorfeus/transport/version'
34
- require 'isomorfeus/transport/response_agent'
35
- require 'isomorfeus/transport/config'
36
- require 'isomorfeus/transport/middlewares'
37
- require 'isomorfeus/transport/request_agent'
38
- require 'isomorfeus/transport/server_processor'
39
- require 'isomorfeus/transport/server_socket_processor'
40
- require 'isomorfeus/transport/websocket'
41
-
42
- require 'isomorfeus/transport/rack_middleware'
43
- require 'isomorfeus/transport/middlewares'
44
-
45
- Isomorfeus.add_middleware(Isomorfeus::Transport::RackMiddleware)
46
-
47
- require 'lucid_handler/mixin'
48
- require 'lucid_handler/base'
49
- require 'lucid_channel/mixin'
50
- require 'lucid_channel/base'
51
-
52
- require 'isomorfeus/transport/handler/authentication_handler'
53
-
54
- Opal.append_path(__dir__.untaint) unless Opal.paths.include?(__dir__.untaint)
55
-
56
- %w[channels handlers server].each do |dir|
57
- path = File.expand_path(File.join('app', dir))
58
- if Dir.exist?(path)
59
- Isomorfeus.zeitwerk.push_dir(path)
60
- end
61
- end
62
- end
1
+ require 'isomorfeus-policy'
2
+ require 'lucid_authentication/mixin'
3
+ if RUBY_ENGINE == 'opal'
4
+ require 'json'
5
+ require 'isomorfeus/transport/version'
6
+ require 'isomorfeus/transport/config'
7
+ require 'isomorfeus/transport/request_agent'
8
+ require 'isomorfeus/transport/client_processor'
9
+ require 'isomorfeus/transport/websocket_client'
10
+ require 'isomorfeus/transport'
11
+ require 'isomorfeus/transport/ssr_login'
12
+ require 'lucid_channel/mixin'
13
+ require 'lucid_channel/base'
14
+ Isomorfeus.zeitwerk.push_dir('channels')
15
+ Isomorfeus.add_client_init_class_name('Isomorfeus::Transport')
16
+ Isomorfeus.add_transport_init_class_name('Isomorfeus::Transport::SsrLogin') if Isomorfeus.on_ssr?
17
+ else
18
+ require 'base64'
19
+ require 'digest'
20
+ require 'bcrypt'
21
+ require 'securerandom'
22
+ require 'fileutils'
23
+ require 'ostruct'
24
+ require 'socket'
25
+ require 'sorted_set'
26
+ require 'oj'
27
+ require 'active_support'
28
+ require 'isomorfeus-asset-manager'
29
+ require 'isomorfeus/transport/hamster_session_store'
30
+ opal_path = Gem::Specification.find_by_name('opal').full_gem_path
31
+ promise_path = File.join(opal_path, 'stdlib', 'promise.rb')
32
+ require promise_path
33
+ require 'isomorfeus/transport/version'
34
+ require 'isomorfeus/transport/response_agent'
35
+ require 'isomorfeus/transport/config'
36
+ require 'isomorfeus/transport/middlewares'
37
+ require 'isomorfeus/transport/request_agent'
38
+ require 'isomorfeus/transport/server_processor'
39
+ require 'isomorfeus/transport/server_socket_processor'
40
+ require 'isomorfeus/transport/websocket_client'
41
+ require 'isomorfeus/transport'
42
+ require 'isomorfeus/transport/rack_middleware'
43
+ require 'isomorfeus/transport/middlewares'
44
+
45
+ Isomorfeus.add_middleware(Isomorfeus::Transport::RackMiddleware)
46
+ Isomorfeus.add_middleware(Isomorfeus::AssetManager::RackMiddleware)
47
+
48
+ require 'lucid_handler/mixin'
49
+ require 'lucid_handler/base'
50
+ require 'lucid_channel/mixin'
51
+ require 'lucid_channel/base'
52
+
53
+ require 'isomorfeus/transport/handler/authentication_handler'
54
+
55
+ require 'iso_opal'
56
+ Opal.append_path(__dir__.untaint) unless IsoOpal.paths_include?(__dir__.untaint)
57
+
58
+ %w[channels handlers server].each do |dir|
59
+ path = File.expand_path(File.join('app', dir))
60
+ if Dir.exist?(path)
61
+ Isomorfeus.zeitwerk.push_dir(path)
62
+ end
63
+ end
64
+
65
+ require 'isomorfeus-speednode'
66
+ Isomorfeus.node_paths << File.expand_path(File.join(File.dirname(__FILE__), '..', 'node_modules'))
67
+
68
+ require 'isomorfeus/transport/imports'
69
+ Isomorfeus::Transport::Imports.add
70
+ end