hyper-operation 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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,24 @@
1
+ module Hyperloop
2
+ # Tricky business here. Hyperloop::Store will define boot
3
+ # if it is not already defined. It creates a minimal compatible
4
+ # API that includes the run and on_dispatch methods. This way
5
+ # you can use the Boot interface without loading operations.
6
+
7
+ # Here we define Boot, but in case it has already been defined
8
+ # we make sure to run the inherited method, and define the
9
+ # on_dispatch and run methods. Finally we copy any receivers
10
+ # that may have been defined on the existing Boot to the new class.
11
+ class Application
12
+ Operation.inherited(Boot) if defined? Boot
13
+ class Boot < Operation
14
+ def self.on_dispatch(&block)
15
+ _Railway.add_receiver(&block)
16
+ end
17
+ def self.run(*args)
18
+ ClientDrivers.initialize_client_drivers_on_boot
19
+ _run(*args)
20
+ end
21
+ end
22
+ Boot.receivers.each { |r| Boot.on_dispatch &r } if Boot.respond_to? :receivers
23
+ end
24
+ end
@@ -0,0 +1,60 @@
1
+ module Hyperloop
2
+ class Operation
3
+ end
4
+ end
5
+
6
+ # patch so that we recognize Foo(...) as an operation inside a React Component
7
+ module React
8
+ module Component
9
+ module Tags
10
+
11
+ private
12
+
13
+ # redefine find_component so if its a HyperOperation we return nil which will
14
+ # let Object.method_missing (see below) handle the method call to run.
15
+ def find_component(name)
16
+ component = lookup_const(name)
17
+ return nil if component && component < Hyperloop::Operation
18
+ if component && !component.method_defined?(:render)
19
+ raise "#{name} does not appear to be a react component."
20
+ end
21
+ component
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ class Object
28
+ class << self
29
+ alias _hyper_operation_original_method_missing method_missing
30
+
31
+ def method_missing(name, *args, &block)
32
+ if name =~ /^[A-Z]/
33
+ scopes = self.name.to_s.split('::').inject([Module]) do |nesting, next_const|
34
+ nesting + [nesting.last.const_get(next_const)]
35
+ end.reverse
36
+ #cant use const_defined? on server because it wont invoke rails auto loading
37
+ scope = scopes.detect { |s| s.const_get(name) rescue nil }
38
+ const = scope.const_get(name) if scope
39
+ end
40
+ _hyper_operation_original_method_missing(name, *args, &block) unless const.is_a?(Class) && const < Hyperloop::Operation
41
+ const.send(:run, *args)
42
+ end
43
+ end
44
+
45
+ alias _hyper_operation_original_method_missing method_missing
46
+
47
+ def method_missing(name, *args, &block)
48
+ if name =~ /^[A-Z]/
49
+ first = self.is_a?(Module) || self.is_a?(Class) ? self.name : self.class.name
50
+ scopes = first.to_s.split('::').inject([Module]) do |nesting, next_const|
51
+ nesting + [nesting.last.const_get(next_const)]
52
+ end.reverse
53
+ #cant use const_defined? on server because it wont invoke rails auto loading
54
+ scope = scopes.detect { |s| s.const_get(name) rescue nil }
55
+ const = scope.const_get(name) if scope
56
+ end
57
+ _hyper_operation_original_method_missing(name, *args, &block) unless const.is_a?(Class) && const < Hyperloop::Operation
58
+ const.send(:run, *args)
59
+ end
60
+ end
@@ -0,0 +1,9 @@
1
+ module Kernel
2
+ def every(time, &block)
3
+ Thread.new { loop { sleep time; block.call }}
4
+ end
5
+
6
+ def after(time, &block)
7
+ Thread.new { sleep time; block.call }
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Hyperloop
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Hyperloop
4
+ config.generators do |g|
5
+ g.test_framework :rspec, :fixture => false
6
+ g.fixture_replacement :factory_girl, :dir => 'spec/factories'
7
+ g.assets false
8
+ g.helper false
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Hyperloop
2
+ class AccessViolation < StandardError
3
+ def message
4
+ "Hyperloop::Operation::AccessViolation: #{super}"
5
+ end
6
+ end
7
+
8
+ class Operation
9
+ class ValidationException < Mutations::ValidationException
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,19 @@
1
+ module Hyperloop
2
+ class ActingUser
3
+ @default_options = {
4
+ :nils => false # true allows an explicit nil to be valid. Overrides any other options
5
+ }
6
+
7
+ def filter(data)
8
+
9
+ # Handle nil case
10
+ if data.nil?
11
+ return [nil, nil] if options[:nils]
12
+ return [nil, :nils]
13
+ end
14
+
15
+ # otherwise, we win.
16
+ return [data, nil]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ module Mutations
2
+ class OutboundFilter < AdditionalFilter
3
+ @default_options = {}
4
+
5
+ def filter(data)
6
+ return [data, :outbound]
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module Mutations
2
+ class SimpleHashFilter < AdditionalFilter
3
+ @default_options = {
4
+ :nils => false # true allows an explicit nil to be valid. Overrides any other options
5
+ }
6
+
7
+ def filter(data)
8
+
9
+ # Handle nil case
10
+ if data.nil?
11
+ return [nil, nil] if options[:nils]
12
+ return [nil, :nils]
13
+ end
14
+
15
+ # Now check if it's empty:
16
+ return [data, :empty] if data == {}
17
+
18
+ # If data is a hash, we win.
19
+ return [data, nil] if data.is_a? Hash
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ class Date
2
+ alias broken_equals ==
3
+ def ==(other)
4
+ return false unless other.is_a?(Date)
5
+ broken_equals(other)
6
+ end
7
+ end
8
+
9
+ class Time
10
+ alias broken_equals ==
11
+ def ==(other)
12
+ return false unless other.is_a?(Time)
13
+ broken_equals(other)
14
+ end
15
+ end
16
+
17
+ begin
18
+ JSON.parse("test")
19
+ rescue Exception => e
20
+ JSON.class_eval do
21
+ class << self
22
+ alias old_parse parse
23
+ end
24
+ def self.parse(*args, &block)
25
+ old_parse *args, &block
26
+ rescue Exception => e
27
+ raise StandardError.new e.message
28
+ end
29
+ end unless e.is_a? StandardError
30
+ end
31
+
32
+ class Set
33
+ def &(enum)
34
+ n = self.class.new
35
+ enum.each { |o| n.add(o) if include?(o) }
36
+ n
37
+ end
38
+ alias intersection &
39
+ end unless Set.method_defined? :intersection
@@ -0,0 +1,347 @@
1
+ class Promise
2
+ def self.value(value)
3
+ new.resolve(value)
4
+ end
5
+
6
+ def self.error(value)
7
+ new.reject(value)
8
+ end
9
+
10
+ def self.when(*promises)
11
+ When.new(promises)
12
+ end
13
+
14
+ attr_reader :error, :prev, :next
15
+
16
+ def initialize(action = {})
17
+ @action = action
18
+
19
+ @realized = false
20
+ @exception = false
21
+ @value = nil
22
+ @error = nil
23
+ @delayed = false
24
+
25
+ @prev = nil
26
+ @next = []
27
+ end
28
+
29
+ def value
30
+ if Promise === @value
31
+ @value.value
32
+ else
33
+ @value
34
+ end
35
+ end
36
+
37
+ def act?
38
+ @action.has_key?(:success) || @action.has_key?(:always)
39
+ end
40
+
41
+ def action
42
+ @action.keys
43
+ end
44
+
45
+ def exception?
46
+ @exception
47
+ end
48
+
49
+ def realized?
50
+ !!@realized
51
+ end
52
+
53
+ def resolved?
54
+ @realized == :resolve
55
+ end
56
+
57
+ def rejected?
58
+ @realized == :reject
59
+ end
60
+
61
+ def pending?
62
+ !realized?
63
+ end
64
+
65
+ def ^(promise)
66
+ promise << self
67
+ self >> promise
68
+
69
+ promise
70
+ end
71
+
72
+ def <<(promise)
73
+ @prev = promise
74
+
75
+ self
76
+ end
77
+
78
+ def >>(promise)
79
+ @next << promise
80
+
81
+ if exception?
82
+ promise.reject(@delayed[0])
83
+ elsif resolved?
84
+ promise.resolve(@delayed ? @delayed[0] : value)
85
+ elsif rejected?
86
+ if !@action.has_key?(:failure) || Promise === (@delayed ? @delayed[0] : @error)
87
+ promise.reject(@delayed ? @delayed[0] : error)
88
+ elsif promise.action.include?(:always)
89
+ promise.reject(@delayed ? @delayed[0] : error)
90
+ end
91
+ end
92
+
93
+ self
94
+ end
95
+
96
+ def resolve(value = nil)
97
+ if realized?
98
+ raise ArgumentError, 'the promise has already been realized'
99
+ end
100
+
101
+ if Promise === value
102
+ return (value << @prev) ^ self
103
+ end
104
+
105
+ begin
106
+ if block = @action[:success] || @action[:always]
107
+ value = block.call(value)
108
+ end
109
+
110
+ resolve!(value)
111
+ rescue Exception => e
112
+ exception!(e)
113
+ end
114
+
115
+ self
116
+ end
117
+
118
+ def resolve!(value)
119
+ @realized = :resolve
120
+ @value = value
121
+
122
+ if @next.any?
123
+ @next.each { |p| p.resolve(value) }
124
+ else
125
+ @delayed = [value]
126
+ end
127
+ end
128
+
129
+ def reject(value = nil)
130
+ if realized?
131
+ raise ArgumentError, 'the promise has already been realized'
132
+ end
133
+
134
+ if Promise === value
135
+ return (value << @prev) ^ self
136
+ end
137
+
138
+ begin
139
+ if block = @action[:failure] || @action[:always]
140
+ value = block.call(value)
141
+ end
142
+
143
+ if @action.has_key?(:always)
144
+ resolve!(value)
145
+ else
146
+ reject!(value)
147
+ end
148
+ rescue Exception => e
149
+ exception!(e)
150
+ end
151
+
152
+ self
153
+ end
154
+
155
+ def reject!(value)
156
+ @realized = :reject
157
+ @error = value
158
+
159
+ if @next.any?
160
+ @next.each { |p| p.reject(value) }
161
+ else
162
+ @delayed = [value]
163
+ end
164
+ end
165
+
166
+ def exception!(error)
167
+ @exception = true
168
+
169
+ reject!(error)
170
+ end
171
+
172
+ def then(&block)
173
+ self ^ Promise.new(success: block)
174
+ end
175
+
176
+ def then!(&block)
177
+ there_can_be_only_one!
178
+ self.then(&block)
179
+ end
180
+
181
+ alias do then
182
+ alias do! then!
183
+
184
+ def fail(&block)
185
+ self ^ Promise.new(failure: block)
186
+ end
187
+
188
+ def fail!(&block)
189
+ there_can_be_only_one!
190
+ fail(&block)
191
+ end
192
+
193
+ alias rescue fail
194
+ alias catch fail
195
+ alias rescue! fail!
196
+ alias catch! fail!
197
+
198
+ def always(&block)
199
+ self ^ Promise.new(always: block)
200
+ end
201
+
202
+ def always!(&block)
203
+ there_can_be_only_one!
204
+ always(&block)
205
+ end
206
+
207
+ alias finally always
208
+ alias ensure always
209
+ alias finally! always!
210
+ alias ensure! always!
211
+
212
+ def trace(depth = nil, &block)
213
+ self ^ Trace.new(depth, block)
214
+ end
215
+
216
+ def trace!(*args, &block)
217
+ there_can_be_only_one!
218
+ trace(*args, &block)
219
+ end
220
+
221
+ def there_can_be_only_one!
222
+ if @next.any?
223
+ raise ArgumentError, 'a promise has already been chained'
224
+ end
225
+ end
226
+
227
+ def inspect
228
+ result = "#<#{self.class}(#{object_id})"
229
+
230
+ if @next.any?
231
+ result += " >> #{@next.inspect}"
232
+ end
233
+
234
+ if realized?
235
+ result += ": #{(@value || @error).inspect}>"
236
+ else
237
+ result += ">"
238
+ end
239
+
240
+ result
241
+ end
242
+
243
+ class Trace < self
244
+ def self.it(promise)
245
+ current = []
246
+
247
+ if promise.act? || promise.prev.nil?
248
+ current.push(promise.value)
249
+ end
250
+
251
+ if prev = promise.prev
252
+ current.concat(it(prev))
253
+ else
254
+ current
255
+ end
256
+ end
257
+
258
+ def initialize(depth, block)
259
+ @depth = depth
260
+
261
+ super success: proc {
262
+ trace = Trace.it(self).reverse
263
+ trace.pop
264
+
265
+ if depth && depth <= trace.length
266
+ trace.shift(trace.length - depth)
267
+ end
268
+
269
+ block.call(*trace)
270
+ }
271
+ end
272
+ end
273
+
274
+ class When < self
275
+ def initialize(promises = [])
276
+ super()
277
+
278
+ @wait = []
279
+
280
+ promises.each {|promise|
281
+ wait promise
282
+ }
283
+ end
284
+
285
+ def each(&block)
286
+ raise ArgumentError, 'no block given' unless block
287
+
288
+ self.then {|values|
289
+ values.each(&block)
290
+ }
291
+ end
292
+
293
+ def collect(&block)
294
+ raise ArgumentError, 'no block given' unless block
295
+
296
+ self.then {|values|
297
+ When.new(values.map(&block))
298
+ }
299
+ end
300
+
301
+ def inject(*args, &block)
302
+ self.then {|values|
303
+ values.reduce(*args, &block)
304
+ }
305
+ end
306
+
307
+ alias map collect
308
+
309
+ alias reduce inject
310
+
311
+ def wait(promise)
312
+ unless Promise === promise
313
+ promise = Promise.value(promise)
314
+ end
315
+
316
+ if promise.act?
317
+ promise = promise.then
318
+ end
319
+
320
+ @wait << promise
321
+
322
+ promise.always {
323
+ try if @next.any?
324
+ }
325
+
326
+ self
327
+ end
328
+
329
+ alias and wait
330
+
331
+ def >>(*)
332
+ super.tap {
333
+ try
334
+ }
335
+ end
336
+
337
+ def try
338
+ if @wait.all?(&:realized?)
339
+ if promise = @wait.find(&:rejected?)
340
+ reject(promise.error)
341
+ else
342
+ resolve(@wait.map(&:value))
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end