hyper-operation 1.0.alpha1.4 → 1.0.alpha1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/hyper-operation/promise.rb +28 -2
- data/lib/hyper-operation/railway/run.rb +51 -48
- data/lib/hyper-operation/railway/validations.rb +9 -2
- data/lib/hyper-operation/server_op.rb +5 -1
- data/lib/hyper-operation/transport/client_drivers.rb +39 -9
- data/lib/hyper-operation/transport/hyperstack.rb +6 -1
- data/lib/hyper-operation/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 65b352cb39f23e41aa0f4adc29ba892a8d9cf269c7345314851f2a68bccddf86
|
|
4
|
+
data.tar.gz: 71f10e8f1dfc3f38b968b694c0535169211a374dc404fa3da79a864791e075f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba63a89809105c28b96d246a9958d0aab4ea121bcd59d5ee0f7fb1f96d88b1832dcafe35421f8220a13b401acba73d08cf7b27ce798c382336a2c9d844e7533f
|
|
7
|
+
data.tar.gz: afaea58dfe7c97007f3d70cebe53d02258c938e3fa4c863788a259f2478fbf45dcf7bc8472fc46967c60b797b693594d1e2468b45671b58281bcaed2925e7e0f
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# Caution. For now Hyperstack maintains its own copy of the Promise class.
|
|
2
|
+
# Eventually the diff between hyperstacks version and the official Opal version
|
|
3
|
+
# should be put into a PR.
|
|
4
|
+
|
|
5
|
+
# A key feature add is the Fail Exception class which is simply there to allow
|
|
6
|
+
# a `always` block to reject without raising an error. To use this see the run.rb
|
|
7
|
+
# module.
|
|
8
|
+
|
|
9
|
+
# Also see exception! method for the part of the code that detects the Fail exception.
|
|
10
|
+
|
|
11
|
+
# See https://github.com/opal/opal/issues/1967 for details.
|
|
12
|
+
|
|
1
13
|
class Promise
|
|
2
14
|
def self.value(value)
|
|
3
15
|
new.resolve(value)
|
|
@@ -11,6 +23,13 @@ class Promise
|
|
|
11
23
|
When.new(promises)
|
|
12
24
|
end
|
|
13
25
|
|
|
26
|
+
class Fail < StandardError
|
|
27
|
+
attr_reader :result
|
|
28
|
+
def initialize(result)
|
|
29
|
+
@result = result
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
14
33
|
attr_reader :error, :prev, :next
|
|
15
34
|
|
|
16
35
|
def initialize(action = {})
|
|
@@ -164,8 +183,15 @@ class Promise
|
|
|
164
183
|
end
|
|
165
184
|
|
|
166
185
|
def exception!(error)
|
|
167
|
-
|
|
168
|
-
|
|
186
|
+
# If the error is a Promise::Fail, then
|
|
187
|
+
# the error becomes the error.result value
|
|
188
|
+
# this allows code to raise an error on an
|
|
189
|
+
# object that is not an error.
|
|
190
|
+
if error.is_a? Promise::Fail
|
|
191
|
+
error = error.result
|
|
192
|
+
else
|
|
193
|
+
@exception = true
|
|
194
|
+
end
|
|
169
195
|
reject!(error)
|
|
170
196
|
end
|
|
171
197
|
|
|
@@ -21,7 +21,7 @@ module Hyperstack
|
|
|
21
21
|
@tracks ||= []
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def
|
|
24
|
+
def build_tie(tie, args, block)
|
|
25
25
|
if args.count.zero?
|
|
26
26
|
{ run: block }
|
|
27
27
|
elsif args[0].is_a?(Hash)
|
|
@@ -41,7 +41,7 @@ module Hyperstack
|
|
|
41
41
|
|
|
42
42
|
[:step, :failed, :async].each do |tie|
|
|
43
43
|
define_method :"add_#{tie}" do |*args, &block|
|
|
44
|
-
tracks <<
|
|
44
|
+
tracks << build_tie(tie, args, block)
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -55,44 +55,33 @@ module Hyperstack
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def step(opts)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@last_result = result
|
|
61
|
-
apply(opts, :in_promise)
|
|
62
|
-
end
|
|
63
|
-
elsif @state == :success
|
|
64
|
-
apply(opts)
|
|
65
|
-
end
|
|
58
|
+
@promise_chain = @promise_chain
|
|
59
|
+
.then { |result| apply(result, :success, opts) }
|
|
66
60
|
end
|
|
67
61
|
|
|
68
62
|
def failed(opts)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@last_result = e
|
|
72
|
-
apply(opts, :in_promise)
|
|
73
|
-
raise @last_result if @last_result.is_a? Exception
|
|
74
|
-
raise e
|
|
75
|
-
end
|
|
76
|
-
elsif @state == :failed
|
|
77
|
-
apply(opts)
|
|
78
|
-
end
|
|
63
|
+
@promise_chain = @promise_chain
|
|
64
|
+
.always { |result| apply(result, :failed, opts) }
|
|
79
65
|
end
|
|
80
66
|
|
|
81
67
|
def async(opts)
|
|
82
|
-
|
|
68
|
+
@promise_chain = @promise_chain_start = Promise.new
|
|
69
|
+
@promise_chain.resolve(@last_async_result)
|
|
70
|
+
step(opts)
|
|
83
71
|
end
|
|
84
72
|
|
|
85
|
-
def apply(
|
|
73
|
+
def apply(result, state, opts)
|
|
74
|
+
return result unless @state == state
|
|
86
75
|
if opts[:scope] == :class
|
|
87
|
-
args = [@operation,
|
|
76
|
+
args = [@operation, *result]
|
|
88
77
|
instance = @operation.class
|
|
89
78
|
else
|
|
90
|
-
args =
|
|
79
|
+
args = result
|
|
91
80
|
instance = @operation
|
|
92
81
|
end
|
|
93
82
|
block = opts[:run]
|
|
94
83
|
block = instance.method(block) if block.is_a? Symbol
|
|
95
|
-
|
|
84
|
+
last_result =
|
|
96
85
|
if block.arity.zero?
|
|
97
86
|
instance.instance_exec(&block)
|
|
98
87
|
elsif args.is_a?(Array) && block.arity == args.count
|
|
@@ -100,40 +89,54 @@ module Hyperstack
|
|
|
100
89
|
else
|
|
101
90
|
instance.instance_exec(args, &block)
|
|
102
91
|
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
@last_result = @last_result.value if @last_result.resolved?
|
|
106
|
-
@last_result
|
|
92
|
+
@last_async_result = last_result unless last_result.is_a? Promise
|
|
93
|
+
last_result
|
|
107
94
|
rescue Exit => e
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
# the promise chain ends with an always block which will process
|
|
96
|
+
# any immediate exits by checking the value of @state. All other
|
|
97
|
+
# step/failed/async blocks will be skipped because state will not equal
|
|
98
|
+
# :succeed or :failed
|
|
99
|
+
if e.state == :failed
|
|
100
|
+
@state = :abort
|
|
101
|
+
# exit via the final always block with the exception
|
|
102
|
+
raise e.result.is_a?(Exception) ? e.result : e
|
|
103
|
+
else
|
|
104
|
+
@state = :succeed
|
|
105
|
+
# exit via the final then block with the success value
|
|
106
|
+
e.result
|
|
107
|
+
end
|
|
111
108
|
rescue Exception => e
|
|
112
109
|
@state = :failed
|
|
113
|
-
|
|
114
|
-
raise e if in_promise
|
|
110
|
+
raise e
|
|
115
111
|
end
|
|
116
112
|
|
|
117
113
|
def run
|
|
118
|
-
if @operation.has_errors? || @state
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
114
|
+
# if @operation.has_errors? || @state
|
|
115
|
+
# @last_result ||= ValidationException.new(@operation.instance_variable_get('@errors'))
|
|
116
|
+
# # following handles abort out of validation. if state is already set then we are aborting
|
|
117
|
+
# # otherwise if state is not set but we have errors then we are failed
|
|
118
|
+
# @state ||= :failed
|
|
119
|
+
# else
|
|
120
|
+
# @state = :success
|
|
121
|
+
# end
|
|
122
|
+
@state ||= :success
|
|
123
|
+
@promise_chain_start = @promise_chain = Promise.new
|
|
124
|
+
@promise_chain_start.resolve(@last_result)
|
|
125
|
+
tracks.each { |opts| opts[:tie].bind(self).call(opts) } unless @state == :abort
|
|
127
126
|
end
|
|
128
127
|
|
|
129
128
|
def result
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
@result ||= @promise_chain.always do |e|
|
|
130
|
+
if %i[abort failed].include? @state
|
|
131
|
+
if e.is_a? Exception
|
|
132
|
+
raise e
|
|
133
|
+
else
|
|
134
|
+
raise Promise::Fail.new(e)
|
|
135
|
+
end
|
|
134
136
|
else
|
|
135
|
-
|
|
137
|
+
e
|
|
136
138
|
end
|
|
139
|
+
end
|
|
137
140
|
end
|
|
138
141
|
end
|
|
139
142
|
end
|
|
@@ -28,6 +28,8 @@ 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)
|
|
31
33
|
raise Exit.new(:abort_from_add_error, e.result)
|
|
32
34
|
end
|
|
33
35
|
end
|
|
@@ -47,17 +49,22 @@ module Hyperstack
|
|
|
47
49
|
when :failed
|
|
48
50
|
add_validation_error(i, "param validation #{i+1} aborted")
|
|
49
51
|
end
|
|
50
|
-
@state = :
|
|
52
|
+
@state = :abort
|
|
51
53
|
return # break does not work in Opal
|
|
52
54
|
rescue AccessViolation => e
|
|
53
55
|
add_validation_error(i, e)
|
|
54
|
-
@state = :
|
|
56
|
+
@state = :abort
|
|
55
57
|
@last_result = e
|
|
56
58
|
return # break does not work in Opal
|
|
57
59
|
rescue Exception => e
|
|
58
60
|
add_validation_error(i, e)
|
|
59
61
|
end
|
|
60
62
|
end
|
|
63
|
+
ensure
|
|
64
|
+
if @operation.has_errors?
|
|
65
|
+
@last_result ||= ValidationException.new(@operation.instance_variable_get('@errors'))
|
|
66
|
+
@state ||= :failed
|
|
67
|
+
end
|
|
61
68
|
end
|
|
62
69
|
end
|
|
63
70
|
end
|
|
@@ -14,7 +14,7 @@ module Hyperstack
|
|
|
14
14
|
Hyperstack::HTTP.post(
|
|
15
15
|
"#{`window.HyperstackEnginePath`}/execute_remote",
|
|
16
16
|
payload: {json: {operation: name, params: hash}.to_json},
|
|
17
|
-
headers:
|
|
17
|
+
headers: headers.merge('X-CSRF-Token' => Hyperstack::ClientDrivers.opts[:form_authenticity_token])
|
|
18
18
|
)
|
|
19
19
|
.then do |response|
|
|
20
20
|
deserialize_response response.json[:response]
|
|
@@ -129,6 +129,10 @@ module Hyperstack
|
|
|
129
129
|
promise.reject e
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
+
def headers
|
|
133
|
+
{}
|
|
134
|
+
end
|
|
135
|
+
|
|
132
136
|
def serialize_params(hash)
|
|
133
137
|
hash
|
|
134
138
|
end
|
|
@@ -35,16 +35,35 @@ module Hyperstack
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
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
|
+
|
|
38
46
|
def self.connect(*channels)
|
|
39
47
|
channels.each do |channel|
|
|
40
48
|
if channel.is_a? Class
|
|
41
49
|
IncomingBroadcast.connect_to(channel.name)
|
|
42
50
|
elsif channel.is_a?(String) || channel.is_a?(Array)
|
|
43
51
|
IncomingBroadcast.connect_to(*channel)
|
|
44
|
-
elsif channel.id
|
|
45
|
-
|
|
52
|
+
elsif channel.respond_to?(:id)
|
|
53
|
+
Hyperstack::Model.load do
|
|
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
|
|
46
61
|
else
|
|
47
|
-
raise "cannot connect to
|
|
62
|
+
raise "Hyperstack.connect cannot connect to #{channel.inspect}.\n"\
|
|
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"
|
|
48
67
|
end
|
|
49
68
|
end
|
|
50
69
|
end
|
|
@@ -65,12 +84,14 @@ module Hyperstack
|
|
|
65
84
|
|
|
66
85
|
def self.add_connection(channel_name, id = nil)
|
|
67
86
|
channel_string = "#{channel_name}#{'-'+id.to_s if id}"
|
|
87
|
+
return if open_channels.include? channel_string
|
|
68
88
|
open_channels << channel_string
|
|
69
89
|
channel_string
|
|
70
90
|
end
|
|
71
91
|
|
|
72
92
|
def self.connect_to(channel_name, id = nil)
|
|
73
93
|
channel_string = add_connection(channel_name, id)
|
|
94
|
+
return unless channel_string # already connected!
|
|
74
95
|
if ClientDrivers.opts[:transport] == :pusher
|
|
75
96
|
channel = "#{ClientDrivers.opts[:channel]}-#{channel_string}"
|
|
76
97
|
%x{
|
|
@@ -78,6 +99,7 @@ module Hyperstack
|
|
|
78
99
|
channel.bind('dispatch', #{ClientDrivers.opts[:dispatch]})
|
|
79
100
|
channel.bind('pusher:subscription_succeeded', #{lambda {ClientDrivers.get_queued_data("connect-to-transport", channel_string)}})
|
|
80
101
|
}
|
|
102
|
+
@pusher_dispatcher_registered = true
|
|
81
103
|
elsif ClientDrivers.opts[:transport] == :action_cable
|
|
82
104
|
channel = "#{ClientDrivers.opts[:channel]}-#{channel_string}"
|
|
83
105
|
Hyperstack::HTTP.post(ClientDrivers.polling_path('action-cable-auth', channel), headers: { 'X-CSRF-Token' => ClientDrivers.opts[:form_authenticity_token] }).then do |response|
|
|
@@ -163,12 +185,17 @@ module Hyperstack
|
|
|
163
185
|
# not sure why the second check is needed. It happens in the test app
|
|
164
186
|
route.app == Hyperstack::Engine or (route.app.respond_to?(:app) and route.app.app == Hyperstack::Engine)
|
|
165
187
|
end
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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"
|
|
198
|
+
end
|
|
172
199
|
end if RUBY_ENGINE != 'opal'
|
|
173
200
|
|
|
174
201
|
class << self
|
|
@@ -222,6 +249,9 @@ module Hyperstack
|
|
|
222
249
|
|
|
223
250
|
@opts = Hash.new(`window.HyperstackOpts`)
|
|
224
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
|
|
225
255
|
|
|
226
256
|
if opts[:transport] == :pusher
|
|
227
257
|
|
|
@@ -59,6 +59,8 @@ module Hyperstack
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
define_setting(:send_to_server_timeout, 10)
|
|
63
|
+
|
|
62
64
|
define_setting :opts, {}
|
|
63
65
|
define_setting :channel_prefix, 'synchromesh'
|
|
64
66
|
define_setting :client_logging, true
|
|
@@ -163,7 +165,10 @@ module Hyperstack
|
|
|
163
165
|
request.body = {
|
|
164
166
|
channel: channel, data: data, salt: salt, authorization: authorization
|
|
165
167
|
}.to_json
|
|
166
|
-
http.request(request)
|
|
168
|
+
Timeout::timeout(Hyperstack.send_to_server_timeout) { http.request(request) }
|
|
169
|
+
rescue Timeout::Error
|
|
170
|
+
puts "\n********* FAILED TO RECEIVE RESPONSE FROM SERVER WITHIN #{Hyperstack.send_to_server_timeout} SECONDS. CHANGES WILL NOT BE SYNCED ************\n"
|
|
171
|
+
raise 'no server running'
|
|
167
172
|
end
|
|
168
173
|
|
|
169
174
|
def self.dispatch(data)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hyper-operation
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.alpha1.
|
|
4
|
+
version: 1.0.alpha1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mitch VanDuyn
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: exe
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2019-
|
|
12
|
+
date: 2019-06-19 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activerecord
|
|
@@ -31,14 +31,14 @@ dependencies:
|
|
|
31
31
|
requirements:
|
|
32
32
|
- - '='
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 1.0.alpha1.
|
|
34
|
+
version: 1.0.alpha1.5
|
|
35
35
|
type: :runtime
|
|
36
36
|
prerelease: false
|
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
|
38
38
|
requirements:
|
|
39
39
|
- - '='
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: 1.0.alpha1.
|
|
41
|
+
version: 1.0.alpha1.5
|
|
42
42
|
- !ruby/object:Gem::Dependency
|
|
43
43
|
name: mutations
|
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,14 +135,14 @@ dependencies:
|
|
|
135
135
|
requirements:
|
|
136
136
|
- - '='
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 1.0.alpha1.
|
|
138
|
+
version: 1.0.alpha1.5
|
|
139
139
|
type: :development
|
|
140
140
|
prerelease: false
|
|
141
141
|
version_requirements: !ruby/object:Gem::Requirement
|
|
142
142
|
requirements:
|
|
143
143
|
- - '='
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 1.0.alpha1.
|
|
145
|
+
version: 1.0.alpha1.5
|
|
146
146
|
- !ruby/object:Gem::Dependency
|
|
147
147
|
name: mysql2
|
|
148
148
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -441,7 +441,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
441
441
|
- !ruby/object:Gem::Version
|
|
442
442
|
version: 1.3.1
|
|
443
443
|
requirements: []
|
|
444
|
-
rubygems_version: 3.0.
|
|
444
|
+
rubygems_version: 3.0.4
|
|
445
445
|
signing_key:
|
|
446
446
|
specification_version: 4
|
|
447
447
|
summary: HyperOperations are the swiss army knife of the Hyperstack
|