hyper-operation 0.5.0

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.
Files changed (291) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +49 -0
  3. data/CODE_OF_CONDUCT.md +49 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +324 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +708 -0
  8. data/Rakefile +4 -0
  9. data/examples/chat-app/.gitignore +21 -0
  10. data/examples/chat-app/Gemfile +57 -0
  11. data/examples/chat-app/Gemfile.lock +282 -0
  12. data/examples/chat-app/README.md +3 -0
  13. data/examples/chat-app/Rakefile +6 -0
  14. data/examples/chat-app/app/assets/config/manifest.js +3 -0
  15. data/examples/chat-app/app/assets/images/.keep +0 -0
  16. data/examples/chat-app/app/assets/javascripts/application.js +3 -0
  17. data/examples/chat-app/app/assets/javascripts/cable.js +13 -0
  18. data/examples/chat-app/app/assets/javascripts/channels/.keep +0 -0
  19. data/examples/chat-app/app/assets/stylesheets/application.css +15 -0
  20. data/examples/chat-app/app/channels/application_cable/channel.rb +4 -0
  21. data/examples/chat-app/app/channels/application_cable/connection.rb +4 -0
  22. data/examples/chat-app/app/controllers/application_controller.rb +3 -0
  23. data/examples/chat-app/app/controllers/concerns/.keep +0 -0
  24. data/examples/chat-app/app/controllers/home_controller.rb +5 -0
  25. data/examples/chat-app/app/helpers/application_helper.rb +2 -0
  26. data/examples/chat-app/app/hyperloop/components/app.rb +11 -0
  27. data/examples/chat-app/app/hyperloop/components/formatted_div.rb +13 -0
  28. data/examples/chat-app/app/hyperloop/components/input_box.rb +29 -0
  29. data/examples/chat-app/app/hyperloop/components/message.rb +29 -0
  30. data/examples/chat-app/app/hyperloop/components/messages.rb +9 -0
  31. data/examples/chat-app/app/hyperloop/components/nav.rb +30 -0
  32. data/examples/chat-app/app/hyperloop/operations/operations.rb +56 -0
  33. data/examples/chat-app/app/hyperloop/stores/message_store.rb +23 -0
  34. data/examples/chat-app/app/models/application_record.rb +3 -0
  35. data/examples/chat-app/app/models/concerns/.keep +0 -0
  36. data/examples/chat-app/app/models/models.rb +2 -0
  37. data/examples/chat-app/app/models/public/.keep +0 -0
  38. data/examples/chat-app/app/models/public/announcement.rb +8 -0
  39. data/examples/chat-app/app/policies/application_policy.rb +5 -0
  40. data/examples/chat-app/app/views/layouts/application.html.erb +51 -0
  41. data/examples/chat-app/bin/bundle +3 -0
  42. data/examples/chat-app/bin/rails +9 -0
  43. data/examples/chat-app/bin/rake +9 -0
  44. data/examples/chat-app/bin/setup +34 -0
  45. data/examples/chat-app/bin/spring +17 -0
  46. data/examples/chat-app/bin/update +29 -0
  47. data/examples/chat-app/config.ru +5 -0
  48. data/examples/chat-app/config/application.rb +13 -0
  49. data/examples/chat-app/config/boot.rb +3 -0
  50. data/examples/chat-app/config/cable.yml +9 -0
  51. data/examples/chat-app/config/database.yml +25 -0
  52. data/examples/chat-app/config/environment.rb +5 -0
  53. data/examples/chat-app/config/environments/development.rb +56 -0
  54. data/examples/chat-app/config/environments/production.rb +86 -0
  55. data/examples/chat-app/config/environments/test.rb +42 -0
  56. data/examples/chat-app/config/initializers/application_controller_renderer.rb +6 -0
  57. data/examples/chat-app/config/initializers/assets.rb +11 -0
  58. data/examples/chat-app/config/initializers/backtrace_silencers.rb +7 -0
  59. data/examples/chat-app/config/initializers/cookies_serializer.rb +5 -0
  60. data/examples/chat-app/config/initializers/filter_parameter_logging.rb +4 -0
  61. data/examples/chat-app/config/initializers/hyperloop.rb +4 -0
  62. data/examples/chat-app/config/initializers/inflections.rb +16 -0
  63. data/examples/chat-app/config/initializers/mime_types.rb +4 -0
  64. data/examples/chat-app/config/initializers/new_framework_defaults.rb +24 -0
  65. data/examples/chat-app/config/initializers/session_store.rb +3 -0
  66. data/examples/chat-app/config/initializers/wrap_parameters.rb +14 -0
  67. data/examples/chat-app/config/locales/en.yml +23 -0
  68. data/examples/chat-app/config/puma.rb +47 -0
  69. data/examples/chat-app/config/routes.rb +5 -0
  70. data/examples/chat-app/config/secrets.yml +22 -0
  71. data/examples/chat-app/config/spring.rb +6 -0
  72. data/examples/chat-app/db/seeds.rb +7 -0
  73. data/examples/chat-app/lib/assets/.keep +0 -0
  74. data/examples/chat-app/lib/tasks/.keep +0 -0
  75. data/examples/chat-app/log/.keep +0 -0
  76. data/examples/chat-app/public/404.html +67 -0
  77. data/examples/chat-app/public/422.html +67 -0
  78. data/examples/chat-app/public/500.html +66 -0
  79. data/examples/chat-app/public/apple-touch-icon-precomposed.png +0 -0
  80. data/examples/chat-app/public/apple-touch-icon.png +0 -0
  81. data/examples/chat-app/public/favicon.ico +0 -0
  82. data/examples/chat-app/public/robots.txt +5 -0
  83. data/examples/chat-app/test/controllers/.keep +0 -0
  84. data/examples/chat-app/test/fixtures/.keep +0 -0
  85. data/examples/chat-app/test/fixtures/files/.keep +0 -0
  86. data/examples/chat-app/test/helpers/.keep +0 -0
  87. data/examples/chat-app/test/integration/.keep +0 -0
  88. data/examples/chat-app/test/mailers/.keep +0 -0
  89. data/examples/chat-app/test/models/.keep +0 -0
  90. data/examples/chat-app/test/test_helper.rb +10 -0
  91. data/examples/chat-app/tmp/.keep +0 -0
  92. data/examples/chat-app/vendor/assets/javascripts/.keep +0 -0
  93. data/examples/chat-app/vendor/assets/stylesheets/.keep +0 -0
  94. data/examples/five-letter-word-game/.gitignore +21 -0
  95. data/examples/five-letter-word-game/Gemfile +57 -0
  96. data/examples/five-letter-word-game/Gemfile.lock +282 -0
  97. data/examples/five-letter-word-game/README.md +24 -0
  98. data/examples/five-letter-word-game/Rakefile +6 -0
  99. data/examples/five-letter-word-game/app/assets/config/manifest.js +3 -0
  100. data/examples/five-letter-word-game/app/assets/images/.keep +0 -0
  101. data/examples/five-letter-word-game/app/assets/javascripts/application.js +3 -0
  102. data/examples/five-letter-word-game/app/assets/javascripts/cable.js +13 -0
  103. data/examples/five-letter-word-game/app/assets/javascripts/channels/.keep +0 -0
  104. data/examples/five-letter-word-game/app/assets/stylesheets/application.css +15 -0
  105. data/examples/five-letter-word-game/app/channels/application_cable/channel.rb +4 -0
  106. data/examples/five-letter-word-game/app/channels/application_cable/connection.rb +4 -0
  107. data/examples/five-letter-word-game/app/controllers/application_controller.rb +14 -0
  108. data/examples/five-letter-word-game/app/controllers/concerns/.keep +0 -0
  109. data/examples/five-letter-word-game/app/controllers/home_controller.rb +5 -0
  110. data/examples/five-letter-word-game/app/helpers/application_helper.rb +2 -0
  111. data/examples/five-letter-word-game/app/hyperloop/components/app.rb +65 -0
  112. data/examples/five-letter-word-game/app/hyperloop/components/guesses.rb +8 -0
  113. data/examples/five-letter-word-game/app/hyperloop/components/input_word.rb +13 -0
  114. data/examples/five-letter-word-game/app/hyperloop/models/user.rb +27 -0
  115. data/examples/five-letter-word-game/app/hyperloop/operations/ops.rb +115 -0
  116. data/examples/five-letter-word-game/app/hyperloop/stores/store.rb +120 -0
  117. data/examples/five-letter-word-game/app/jobs/application_job.rb +2 -0
  118. data/examples/five-letter-word-game/app/mailers/application_mailer.rb +4 -0
  119. data/examples/five-letter-word-game/app/models/application_record.rb +3 -0
  120. data/examples/five-letter-word-game/app/models/concerns/.keep +0 -0
  121. data/examples/five-letter-word-game/app/policies/user_policy.rb +4 -0
  122. data/examples/five-letter-word-game/app/views/layouts/application.html.erb +14 -0
  123. data/examples/five-letter-word-game/app/views/layouts/mailer.html.erb +13 -0
  124. data/examples/five-letter-word-game/app/views/layouts/mailer.text.erb +1 -0
  125. data/examples/five-letter-word-game/bin/bundle +3 -0
  126. data/examples/five-letter-word-game/bin/rails +9 -0
  127. data/examples/five-letter-word-game/bin/rake +9 -0
  128. data/examples/five-letter-word-game/bin/setup +34 -0
  129. data/examples/five-letter-word-game/bin/spring +17 -0
  130. data/examples/five-letter-word-game/bin/update +29 -0
  131. data/examples/five-letter-word-game/config.ru +5 -0
  132. data/examples/five-letter-word-game/config/application.rb +12 -0
  133. data/examples/five-letter-word-game/config/boot.rb +3 -0
  134. data/examples/five-letter-word-game/config/cable.yml +9 -0
  135. data/examples/five-letter-word-game/config/database.yml +25 -0
  136. data/examples/five-letter-word-game/config/environment.rb +5 -0
  137. data/examples/five-letter-word-game/config/environments/development.rb +56 -0
  138. data/examples/five-letter-word-game/config/environments/production.rb +86 -0
  139. data/examples/five-letter-word-game/config/environments/test.rb +42 -0
  140. data/examples/five-letter-word-game/config/initializers/application_controller_renderer.rb +6 -0
  141. data/examples/five-letter-word-game/config/initializers/assets.rb +11 -0
  142. data/examples/five-letter-word-game/config/initializers/backtrace_silencers.rb +7 -0
  143. data/examples/five-letter-word-game/config/initializers/cookies_serializer.rb +5 -0
  144. data/examples/five-letter-word-game/config/initializers/filter_parameter_logging.rb +4 -0
  145. data/examples/five-letter-word-game/config/initializers/hyperloop.rb +3 -0
  146. data/examples/five-letter-word-game/config/initializers/inflections.rb +16 -0
  147. data/examples/five-letter-word-game/config/initializers/mime_types.rb +4 -0
  148. data/examples/five-letter-word-game/config/initializers/new_framework_defaults.rb +24 -0
  149. data/examples/five-letter-word-game/config/initializers/session_store.rb +3 -0
  150. data/examples/five-letter-word-game/config/initializers/wrap_parameters.rb +14 -0
  151. data/examples/five-letter-word-game/config/locales/en.yml +23 -0
  152. data/examples/five-letter-word-game/config/puma.rb +47 -0
  153. data/examples/five-letter-word-game/config/routes.rb +5 -0
  154. data/examples/five-letter-word-game/config/secrets.yml +22 -0
  155. data/examples/five-letter-word-game/config/spring.rb +6 -0
  156. data/examples/five-letter-word-game/db/schema.rb +28 -0
  157. data/examples/five-letter-word-game/db/seeds.rb +7 -0
  158. data/examples/five-letter-word-game/lib/assets/.keep +0 -0
  159. data/examples/five-letter-word-game/lib/tasks/.keep +0 -0
  160. data/examples/five-letter-word-game/log/.keep +0 -0
  161. data/examples/five-letter-word-game/public/404.html +67 -0
  162. data/examples/five-letter-word-game/public/422.html +67 -0
  163. data/examples/five-letter-word-game/public/500.html +66 -0
  164. data/examples/five-letter-word-game/public/apple-touch-icon-precomposed.png +0 -0
  165. data/examples/five-letter-word-game/public/apple-touch-icon.png +0 -0
  166. data/examples/five-letter-word-game/public/favicon.ico +0 -0
  167. data/examples/five-letter-word-game/public/robots.txt +5 -0
  168. data/examples/five-letter-word-game/test/controllers/.keep +0 -0
  169. data/examples/five-letter-word-game/test/fixtures/.keep +0 -0
  170. data/examples/five-letter-word-game/test/fixtures/files/.keep +0 -0
  171. data/examples/five-letter-word-game/test/helpers/.keep +0 -0
  172. data/examples/five-letter-word-game/test/integration/.keep +0 -0
  173. data/examples/five-letter-word-game/test/mailers/.keep +0 -0
  174. data/examples/five-letter-word-game/test/models/.keep +0 -0
  175. data/examples/five-letter-word-game/test/test_helper.rb +10 -0
  176. data/examples/five-letter-word-game/tmp/.keep +0 -0
  177. data/examples/five-letter-word-game/vendor/assets/javascripts/.keep +0 -0
  178. data/examples/five-letter-word-game/vendor/assets/stylesheets/.keep +0 -0
  179. data/examples/smoke_test/.gitignore +21 -0
  180. data/examples/smoke_test/Gemfile +59 -0
  181. data/examples/smoke_test/Gemfile.lock +289 -0
  182. data/examples/smoke_test/README.md +24 -0
  183. data/examples/smoke_test/Rakefile +6 -0
  184. data/examples/smoke_test/app/assets/config/manifest.js +3 -0
  185. data/examples/smoke_test/app/assets/images/.keep +0 -0
  186. data/examples/smoke_test/app/assets/javascripts/application.js +15 -0
  187. data/examples/smoke_test/app/assets/javascripts/cable.js +13 -0
  188. data/examples/smoke_test/app/assets/javascripts/channels/.keep +0 -0
  189. data/examples/smoke_test/app/assets/stylesheets/application.css +15 -0
  190. data/examples/smoke_test/app/channels/application_cable/channel.rb +4 -0
  191. data/examples/smoke_test/app/channels/application_cable/connection.rb +4 -0
  192. data/examples/smoke_test/app/controllers/app_controller.rb +5 -0
  193. data/examples/smoke_test/app/controllers/application_controller.rb +3 -0
  194. data/examples/smoke_test/app/helpers/application_helper.rb +2 -0
  195. data/examples/smoke_test/app/hyperloop/components/hello.rb +25 -0
  196. data/examples/smoke_test/app/hyperloop/operations/operations/nested_send_to_all.rb +7 -0
  197. data/examples/smoke_test/app/hyperloop/operations/send_to_all.rb +6 -0
  198. data/examples/smoke_test/app/hyperloop/stores/messages.rb +4 -0
  199. data/examples/smoke_test/app/jobs/application_job.rb +2 -0
  200. data/examples/smoke_test/app/mailers/application_mailer.rb +4 -0
  201. data/examples/smoke_test/app/models/application_record.rb +3 -0
  202. data/examples/smoke_test/app/models/concerns/.keep +0 -0
  203. data/examples/smoke_test/app/policies/application_policy.rb +8 -0
  204. data/examples/smoke_test/app/views/layouts/application.html.erb +14 -0
  205. data/examples/smoke_test/app/views/layouts/mailer.html.erb +13 -0
  206. data/examples/smoke_test/app/views/layouts/mailer.text.erb +1 -0
  207. data/examples/smoke_test/bin/bundle +3 -0
  208. data/examples/smoke_test/bin/rails +9 -0
  209. data/examples/smoke_test/bin/rake +9 -0
  210. data/examples/smoke_test/bin/setup +34 -0
  211. data/examples/smoke_test/bin/spring +17 -0
  212. data/examples/smoke_test/bin/update +29 -0
  213. data/examples/smoke_test/config.ru +5 -0
  214. data/examples/smoke_test/config/application.rb +15 -0
  215. data/examples/smoke_test/config/boot.rb +3 -0
  216. data/examples/smoke_test/config/cable.yml +9 -0
  217. data/examples/smoke_test/config/database.yml +25 -0
  218. data/examples/smoke_test/config/environment.rb +5 -0
  219. data/examples/smoke_test/config/environments/development.rb +54 -0
  220. data/examples/smoke_test/config/environments/production.rb +86 -0
  221. data/examples/smoke_test/config/environments/test.rb +42 -0
  222. data/examples/smoke_test/config/initializers/application_controller_renderer.rb +6 -0
  223. data/examples/smoke_test/config/initializers/assets.rb +11 -0
  224. data/examples/smoke_test/config/initializers/backtrace_silencers.rb +7 -0
  225. data/examples/smoke_test/config/initializers/cookies_serializer.rb +5 -0
  226. data/examples/smoke_test/config/initializers/filter_parameter_logging.rb +4 -0
  227. data/examples/smoke_test/config/initializers/hyperloop.rb +32 -0
  228. data/examples/smoke_test/config/initializers/inflections.rb +16 -0
  229. data/examples/smoke_test/config/initializers/mime_types.rb +4 -0
  230. data/examples/smoke_test/config/initializers/new_framework_defaults.rb +24 -0
  231. data/examples/smoke_test/config/initializers/session_store.rb +3 -0
  232. data/examples/smoke_test/config/initializers/wrap_parameters.rb +14 -0
  233. data/examples/smoke_test/config/locales/en.yml +23 -0
  234. data/examples/smoke_test/config/puma.rb +47 -0
  235. data/examples/smoke_test/config/routes.rb +5 -0
  236. data/examples/smoke_test/config/secrets.yml +22 -0
  237. data/examples/smoke_test/config/spring.rb +6 -0
  238. data/examples/smoke_test/db/seeds.rb +7 -0
  239. data/examples/smoke_test/lib/assets/.keep +0 -0
  240. data/examples/smoke_test/lib/tasks/.keep +0 -0
  241. data/examples/smoke_test/log/.keep +0 -0
  242. data/examples/smoke_test/public/404.html +67 -0
  243. data/examples/smoke_test/public/422.html +67 -0
  244. data/examples/smoke_test/public/500.html +66 -0
  245. data/examples/smoke_test/public/apple-touch-icon-precomposed.png +0 -0
  246. data/examples/smoke_test/public/apple-touch-icon.png +0 -0
  247. data/examples/smoke_test/public/favicon.ico +0 -0
  248. data/examples/smoke_test/public/robots.txt +5 -0
  249. data/examples/smoke_test/test/controllers/.keep +0 -0
  250. data/examples/smoke_test/test/fixtures/.keep +0 -0
  251. data/examples/smoke_test/test/fixtures/files/.keep +0 -0
  252. data/examples/smoke_test/test/helpers/.keep +0 -0
  253. data/examples/smoke_test/test/integration/.keep +0 -0
  254. data/examples/smoke_test/test/mailers/.keep +0 -0
  255. data/examples/smoke_test/test/models/.keep +0 -0
  256. data/examples/smoke_test/test/test_helper.rb +10 -0
  257. data/examples/smoke_test/tmp/.keep +0 -0
  258. data/examples/smoke_test/vendor/assets/javascripts/.keep +0 -0
  259. data/examples/smoke_test/vendor/assets/stylesheets/.keep +0 -0
  260. data/hyper-operation.gemspec +44 -0
  261. data/lib/hyper-operation.rb +59 -0
  262. data/lib/hyper-operation/api.rb +154 -0
  263. data/lib/hyper-operation/boot.rb +24 -0
  264. data/lib/hyper-operation/call_by_class_name.rb +60 -0
  265. data/lib/hyper-operation/delay_and_interval.rb +9 -0
  266. data/lib/hyper-operation/engine.rb +11 -0
  267. data/lib/hyper-operation/exception.rb +13 -0
  268. data/lib/hyper-operation/filters/acting_user.rb +19 -0
  269. data/lib/hyper-operation/filters/outbound_filter.rb +9 -0
  270. data/lib/hyper-operation/filters/simple_hash.rb +22 -0
  271. data/lib/hyper-operation/opal_patches.rb +39 -0
  272. data/lib/hyper-operation/promise.rb +347 -0
  273. data/lib/hyper-operation/railway.rb +5 -0
  274. data/lib/hyper-operation/railway/dispatcher.rb +31 -0
  275. data/lib/hyper-operation/railway/operation_wrapper.rb +106 -0
  276. data/lib/hyper-operation/railway/params_wrapper.rb +124 -0
  277. data/lib/hyper-operation/railway/run.rb +140 -0
  278. data/lib/hyper-operation/railway/validations.rb +63 -0
  279. data/lib/hyper-operation/server_op.rb +98 -0
  280. data/lib/hyper-operation/transport/acting_user.rb +6 -0
  281. data/lib/hyper-operation/transport/action_cable.rb +39 -0
  282. data/lib/hyper-operation/transport/active_record.rb +15 -0
  283. data/lib/hyper-operation/transport/client_drivers.rb +210 -0
  284. data/lib/hyper-operation/transport/connection.rb +170 -0
  285. data/lib/hyper-operation/transport/hyperloop.rb +165 -0
  286. data/lib/hyper-operation/transport/hyperloop_controller.rb +184 -0
  287. data/lib/hyper-operation/transport/pluck.rb +6 -0
  288. data/lib/hyper-operation/transport/policy.rb +535 -0
  289. data/lib/hyper-operation/version.rb +5 -0
  290. data/lib/sources/hyperloop/pusher.js +98 -0
  291. metadata +628 -0
@@ -0,0 +1,5 @@
1
+ module Hyperloop
2
+ class Operation
3
+
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ module Hyperloop
2
+ class Operation
3
+ class Railway
4
+
5
+ def receivers
6
+ self.class.receivers
7
+ end
8
+
9
+ class << self
10
+ def receivers
11
+ @receivers ||= []
12
+ end
13
+
14
+ def add_receiver(&block)
15
+ receivers << block
16
+ end
17
+ end
18
+
19
+ def dispatch
20
+ result.then do
21
+ receivers.each do |receiver|
22
+ receiver.call(
23
+ self.class.params_wrapper.dispatch_params(@operation.params),
24
+ @operation
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,106 @@
1
+ # module Hyperloop
2
+ # class Operation
3
+ # class Railway
4
+ #
5
+ # class Exit < StandardError
6
+ # attr_reader :state
7
+ # attr_reader :result
8
+ # def initialize(state, result)
9
+ # @state = state
10
+ # @result = result
11
+ # end
12
+ # end
13
+ #
14
+ # class << self
15
+ # def add_param(*args, &block)
16
+ # Hyperloop::Operation::ParamsWrapper.add_param(hash_filter, *args, &block)
17
+ # end
18
+ #
19
+ # def add_validation(*args, &block)
20
+ # validations << [args, block]
21
+ # end
22
+ #
23
+ # def add_error(param, symbol, message, *args, &block)
24
+ # add_validation do
25
+ # add_error(param, symbol, message) if call_block_with_context(args, block)
26
+ # end
27
+ # end
28
+ #
29
+ # def add_step(*args, &block)
30
+ # railway << [:step, args, block]
31
+ # end
32
+ #
33
+ # def add_failed(*args, &block)
34
+ # railway << [:failed, args, block]
35
+ # end
36
+ #
37
+ # def add_async(*args, &block)
38
+ # railway << [:async, args, block]
39
+ # end
40
+ #
41
+ # def apply(op, state, result, args, block)
42
+ # if block.arity == 0
43
+ # [state, op.instance_eval &block]
44
+ # elsif result.is_a? Array && block.arity == result.count
45
+ # [state, op.instance_exec(*result, &block)]
46
+ # else
47
+ # [state, op.instance_exec(result, block)]
48
+ # end
49
+ # rescue Exception => e
50
+ # [:failed, e]
51
+ # end
52
+ #
53
+ # def run(op)
54
+ # state = :success # or :failed if @errors
55
+ # result = nil
56
+ # railway.each do |tie|
57
+ # case tie[0]
58
+ # when :step
59
+ # if result.is_a? Promise
60
+ # result = result.then { |*result| apply(op, :success, result, *tie[1..2]) }
61
+ # elsif state == :success
62
+ # state, result = apply(op, state, result, tie[1], tie[2])
63
+ # end
64
+ # when :failed
65
+ # if result.is_a? Promise
66
+ # result = result.fail { |*result| apply(op, :failed, result, *tie[1..2]) }
67
+ # elsif state == :failed
68
+ # state, result = apply(op, state, result, tie[1], tie[2])
69
+ # end
70
+ # when :async
71
+ # state, result = apply(op, state, result, tie[1], tie[2]) if state != :failed
72
+ # end
73
+ # end
74
+ # rescue Hyperloop::Operation::Wrapper::Exit => e
75
+ # result, state = [e.result, e.state]
76
+ # ensure
77
+ # if result.is_a? Promise
78
+ # result
79
+ # elsif state == :failed
80
+ # Promise.new.reject(result)
81
+ # else
82
+ # Promise.new.resolve(result)
83
+ # end
84
+ # end
85
+ #
86
+ #
87
+ #
88
+ #
89
+ # # THIS SHOULD BE ADDED ONLY IN ServerOps
90
+ # def dispatch_to(*args, &block)
91
+ # dispatches << [args, block]
92
+ # end
93
+ #
94
+ # def hash_filter
95
+ # @hash_filter ||= Mutations::HashFilter.new
96
+ # end
97
+ #
98
+ # def validations
99
+ # @validations ||= []
100
+ # end
101
+ #
102
+ #
103
+ #
104
+ # def dispatches
105
+ # @dispatches ||= []
106
+ # end
@@ -0,0 +1,124 @@
1
+ module Hyperloop
2
+ class Operation
3
+ class ParamsWrapper
4
+
5
+ def initialize(inputs)
6
+ @inputs = inputs
7
+ end
8
+
9
+ def lock
10
+ @locked = true
11
+ self
12
+ end
13
+
14
+ def to_h
15
+ @inputs.with_indifferent_access
16
+ end
17
+
18
+ def to_s
19
+ to_h.to_s
20
+ end
21
+
22
+ class << self
23
+
24
+ def combine_arg_array(args)
25
+ hash = args.inject({}.with_indifferent_access) do |h, arg|
26
+ raise ArgumentError.new("All arguments must be hashes") unless arg.respond_to? :to_h
27
+ h.merge!(arg.to_h)
28
+ end
29
+ end
30
+
31
+ def process_params(operation, args)
32
+ raw_inputs = combine_arg_array(args)
33
+ inputs, errors = hash_filter.filter(raw_inputs)
34
+ params_wrapper = new(inputs)
35
+ operation.instance_eval do
36
+ @raw_inputs, @params, @errors = [raw_inputs, params_wrapper, errors]
37
+ end
38
+ end
39
+
40
+ def add_param(*args, &block)
41
+ type_method, name, opts, block = translate_args(*args, &block)
42
+ if opts.key? :default
43
+ hash_filter.optional { send(type_method, name, opts, &block) }
44
+ else
45
+ hash_filter.required { send(type_method, name, opts, &block) }
46
+ end
47
+
48
+ # don't forget specially handling for procs
49
+ define_method(name) do
50
+ @inputs[name]
51
+ end
52
+ define_method(:"#{name}=") do |x|
53
+ method_missing(:"#{name}=", x) if @locked
54
+ @inputs[name] = x
55
+ end
56
+ end
57
+
58
+ def dispatch_params(params, hashes = {})
59
+ params = params.dup
60
+ hashes.each { |hash| hash.each { |k, v| params.send(:"#{k}=", v) } }
61
+ params.lock
62
+ end
63
+
64
+ def hash_filter
65
+ @hash_filter ||= Mutations::HashFilter.new
66
+ end
67
+
68
+ def translate_args(*args, &block)
69
+ name, opts = get_name_and_opts(*args)
70
+ if opts.key?(:type)
71
+ type_method = opts.delete(:type)
72
+ if type_method.is_a?(Array)
73
+ opts[:class] = type_method.first if type_method.count > 0
74
+ type_method = Array
75
+ elsif type_method.is_a?(Hash) || type_method == Hash
76
+ type_method = Hash
77
+ block ||= proc { duck :* }
78
+ end
79
+ type_method = type_method.to_s.underscore
80
+ else
81
+ type_method = :duck
82
+ end
83
+ [type_method, name, opts, block || proc {}]
84
+ end
85
+
86
+ def get_name_and_opts(*args)
87
+ if args[0].is_a? Hash
88
+ opts = args[0]
89
+ name = opts.first.first
90
+ opts[:default] = opts.first.last
91
+ opts.delete(name)
92
+ else
93
+ name = args[0]
94
+ opts = args[1] || {}
95
+ end
96
+ [name, opts]
97
+ end
98
+ end
99
+ end
100
+
101
+ class Railway
102
+ def process_params(args)
103
+ self.class.params_wrapper.process_params(@operation, args)
104
+ end
105
+
106
+ def self.add_param(*args, &block)
107
+ params_wrapper.add_param(*args, &block)
108
+ end
109
+
110
+ def self.params_wrapper
111
+ @params_wrapper ||= begin
112
+ if Railway == superclass
113
+ Class.new(ParamsWrapper)
114
+ else
115
+ Class.new(superclass.params_wrapper).tap do |wrapper|
116
+ hash_filter = superclass.params_wrapper.hash_filter
117
+ wrapper.instance_variable_set('@hash_filter', hash_filter && hash_filter.dup)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,140 @@
1
+ module Hyperloop
2
+ class Operation
3
+
4
+ class Exit < StandardError
5
+ attr_reader :state
6
+ attr_reader :result
7
+ def initialize(state, result)
8
+ @state = state
9
+ @result = result
10
+ end
11
+ end
12
+
13
+ class Railway
14
+
15
+ def tracks
16
+ self.class.tracks
17
+ end
18
+
19
+ class << self
20
+ def tracks
21
+ @tracks ||= []
22
+ end
23
+
24
+ def to_opts(tie, args, block)
25
+ if args.count.zero?
26
+ { run: block }
27
+ elsif args[0].is_a?(Hash)
28
+ {
29
+ scope: args[0][:class] ? :class : args[0][:scope],
30
+ run: args[0][:class] || args[0][:run] || block
31
+ }
32
+ elsif args[0] == :class && block
33
+ { run: block, scope: :class }
34
+ elsif args[0].is_a?(Class) && args[0] < Operation
35
+ { run: proc { args[0].run(params) } }
36
+ else
37
+ scope = args[1][:scope] if args[1].is_a? Hash
38
+ { run: args[0], scope: scope }
39
+ end.merge(tie: instance_method(tie))
40
+ end
41
+
42
+ [:step, :failed, :async].each do |tie|
43
+ define_method :"add_#{tie}" do |*args, &block|
44
+ tracks << to_opts(tie, args, block)
45
+ end
46
+ end
47
+
48
+ def abort!(arg)
49
+ raise Exit.new(:failed, arg)
50
+ end
51
+
52
+ def succeed!(arg)
53
+ raise Exit.new(:success, arg)
54
+ end
55
+ end
56
+
57
+ def step(opts)
58
+ if @last_result.is_a? Promise
59
+ @last_result = @last_result.then do |*result|
60
+ @last_result = result
61
+ apply(opts, :in_promise)
62
+ end
63
+ elsif @state == :success
64
+ apply(opts)
65
+ end
66
+ end
67
+
68
+ def failed(opts)
69
+ if @last_result.is_a? Promise
70
+ @last_result = @last_result.fail do |e|
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
79
+ end
80
+
81
+ def async(opts)
82
+ apply(opts) if @state != :failed
83
+ end
84
+
85
+ def apply(opts, in_promise = nil)
86
+ if opts[:scope] == :class
87
+ args = [@operation, *@last_result]
88
+ instance = @operation.class
89
+ else
90
+ args = @last_result
91
+ instance = @operation
92
+ end
93
+ block = opts[:run]
94
+ block = instance.method(block) if block.is_a? Symbol
95
+ @last_result =
96
+ if block.arity.zero?
97
+ instance.instance_exec(&block)
98
+ elsif args.is_a?(Array) && block.arity == args.count
99
+ instance.instance_exec(*args, &block)
100
+ else
101
+ instance.instance_exec(args, &block)
102
+ end
103
+ return @last_result unless @last_result.is_a? Promise
104
+ raise @last_result.error if @last_result.rejected?
105
+ @last_result = @last_result.value if @last_result.resolved?
106
+ @last_result
107
+ rescue Exit => e
108
+ @state = e.state
109
+ @last_result = (e.state != :failed || e.result.is_a?(Exception)) ? e.result : e
110
+ raise e
111
+ rescue Exception => e
112
+ @state = :failed
113
+ @last_result = e
114
+ raise e if in_promise
115
+ end
116
+
117
+ def run
118
+ if @operation.has_errors? || @state
119
+ @last_result ||= ValidationException.new(@operation.instance_variable_get('@errors'))
120
+ return if @state # handles abort out of validation
121
+ @state = :failed
122
+ else
123
+ @state = :success
124
+ end
125
+ tracks.each { |opts| opts[:tie].bind(self).call(opts) }
126
+ rescue Exit
127
+ end
128
+
129
+ def result
130
+ return @last_result if @last_result.is_a? Promise
131
+ @last_result =
132
+ if @state == :success
133
+ Promise.new.resolve(@last_result)
134
+ else
135
+ Promise.new.reject(@last_result)
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,63 @@
1
+ module Hyperloop
2
+ class Operation
3
+ class Railway
4
+
5
+ def validations
6
+ self.class.validations
7
+ end
8
+
9
+ def add_validation_error(i, e)
10
+ @operation.add_error("param validation #{i+1}", :validation_error, e.to_s)
11
+ end
12
+
13
+ class << self
14
+ def validations
15
+ @validations ||= []
16
+ end
17
+
18
+ def add_validation(*args, &block)
19
+ block = args[0] if args[0]
20
+ validations << block
21
+ end
22
+
23
+ def add_error(param, symbol, message, *args, &block)
24
+ add_validation do
25
+ begin
26
+ add_error(param, symbol, message) if instance_eval(&block)
27
+ rescue Exit => e
28
+ raise e unless e.state == :failed
29
+ add_error(param, symbol, message)
30
+ raise Exit.new(:abort_from_add_error, e.result)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def process_validations
37
+ validations.each_with_index do |validator, i|
38
+ begin
39
+ validator = @operation.method(validator) if validator.is_a? Symbol
40
+ next if @operation.instance_exec(&validator)
41
+ add_validation_error(i, "param validation #{i+1} failed")
42
+ rescue Exit => e
43
+ case e.state
44
+ when :success
45
+ add_validation_error(i, "illegal use of succeed! in validation")
46
+ when :failed
47
+ add_validation_error(i, "param validation #{i+1} aborted")
48
+ end
49
+ @state = :failed
50
+ return # break does not work in Opal
51
+ rescue AccessViolation => e
52
+ add_validation_error(i, e)
53
+ @state = :failed
54
+ @last_result = e
55
+ return # break does not work in Opal
56
+ rescue Exception => e
57
+ add_validation_error(i, e)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end