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,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