hyper-operation 0.5.11 → 0.5.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/DOCS-POLICIES.md +489 -0
- data/DOCS.md +869 -0
- data/README.md +48 -82
- data/hyper-operation.gemspec +4 -2
- data/lib/hyper-operation/api.rb +10 -0
- data/lib/hyper-operation/railway/params_wrapper.rb +13 -1
- data/lib/hyper-operation/server_op.rb +1 -1
- data/lib/hyper-operation/transport/client_drivers.rb +6 -2
- data/lib/hyper-operation/transport/connection.rb +2 -1
- data/lib/hyper-operation/transport/hyperloop.rb +2 -0
- data/lib/hyper-operation/transport/hyperloop_controller.rb +14 -6
- data/lib/hyper-operation/transport/policy.rb +2 -5
- data/lib/hyper-operation/version.rb +1 -1
- metadata +61 -31
data/README.md
CHANGED
@@ -1,110 +1,76 @@
|
|
1
|
-
|
1
|
+
<div class="githubhyperloopheader">
|
2
2
|
|
3
|
-
|
3
|
+
<p align="center">
|
4
4
|
|
5
|
-
|
5
|
+
<a href="http://ruby-hyperloop.io/" alt="Hyperloop" title="Hyperloop">
|
6
|
+
<img width="350px" src="http://ruby-hyperloop.io/images/hyperloop-github-logo.png">
|
7
|
+
</a>
|
6
8
|
|
7
|
-
|
8
|
-
+ An Operation orchestrates the updating of the state of your system.
|
9
|
-
+ Operations also wrap asynchronous operations such as HTTP API requests.
|
10
|
-
+ Operations serve the role of both Action Creators and Dispatchers described in the Flux architecture.
|
11
|
-
+ Operations also serve as the bridge between client and server. An operation can run on the client or the server, and can be invoked remotely.
|
9
|
+
</p>
|
12
10
|
|
13
|
-
|
11
|
+
<h2 align="center">The Complete Isomorphic Ruby Framework</h2>
|
14
12
|
|
15
|
-
|
16
|
-
+ Join the Hyperloop [gitter.io](https://gitter.im/ruby-hyperloop/chat) chat for help and support.
|
13
|
+
<br>
|
17
14
|
|
18
|
-
|
15
|
+
<a href="http://ruby-hyperloop.io/" alt="Hyperloop" title="Hyperloop">
|
16
|
+
<img src="http://ruby-hyperloop.io/images/githubhyperloopbadge.png">
|
17
|
+
</a>
|
19
18
|
|
20
|
-
|
19
|
+
<a href="https://gitter.im/ruby-hyperloop/chat" alt="Gitter chat" title="Gitter chat">
|
20
|
+
<img src="http://ruby-hyperloop.io/images/githubgitterbadge.png">
|
21
|
+
</a>
|
21
22
|
|
22
|
-
|
23
|
+
[![Gem Version](https://badge.fury.io/rb/hyper-operation.svg)](https://badge.fury.io/rb/hyper-operation)
|
23
24
|
|
24
|
-
|
25
|
+
<p align="center">
|
26
|
+
<img src="http://ruby-hyperloop.io/images/HyperOperations.png" width="100" alt="Hyper-operation">
|
27
|
+
</p>
|
25
28
|
|
26
|
-
|
27
|
-
2. Install the Gem: `bundle install`
|
28
|
-
3. Run the generator: `bundle exec rails g hyperloop:install --all`
|
29
|
-
4. Update the bundle: `bundle update`
|
29
|
+
</div>
|
30
30
|
|
31
|
-
|
31
|
+
## Hyper-Operation GEM is part of Hyperloop GEMS family
|
32
32
|
|
33
|
-
|
34
|
-
Add `//= require hyperloop-loader` to your application.rb
|
33
|
+
Build interactive Web applications quickly. Hyperloop encourages rapid development with clean, pragmatic design. With developer productivity as our highest goal, Hyperloop takes care of much of the hassle of Web development, so you can focus on innovation and delivering end-user value.
|
35
34
|
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
# initializers/hyperloop.rb
|
39
|
-
Hyperloop.configuration do |config|
|
40
|
-
|
41
|
-
# to use Action Cable
|
42
|
-
config.transport = :action_cable # for rails 5+
|
43
|
-
|
44
|
-
# to use Pusher (see www.pusher.com)
|
45
|
-
config.transport = :pusher
|
46
|
-
config.opts = {
|
47
|
-
app_id: "pusher application id",
|
48
|
-
key: "pusher public key",
|
49
|
-
secret: "pusher secret key"
|
50
|
-
}
|
51
|
-
|
52
|
-
# to use Pusher Fake (creates a fake pusher service)
|
53
|
-
# Its a bit weird: You have to define require pusher and
|
54
|
-
# define some FAKE pusher keys first, then bring in pusher-fake
|
55
|
-
# the actual key values don't matter just the order!!!
|
56
|
-
require 'pusher'
|
57
|
-
require 'pusher-fake'
|
58
|
-
Pusher.app_id = "MY_TEST_ID" # don't bother changing these strings
|
59
|
-
Pusher.key = "MY_TEST_KEY"
|
60
|
-
Pusher.secret = "MY_TEST_SECRET"
|
61
|
-
require 'pusher-fake/support/base'
|
62
|
-
# then setup your config like pusher but merge in the pusher fake
|
63
|
-
# options
|
64
|
-
config.transport = :pusher
|
65
|
-
config.opts = {
|
66
|
-
app_id: Pusher.app_id,
|
67
|
-
key: Pusher.key,
|
68
|
-
secret: Pusher.secret
|
69
|
-
}.merge(PusherFake.configuration.web_options)
|
70
|
-
|
71
|
-
# For down and dirty simplicity use polling:
|
72
|
-
config.transport = :simple_poller
|
73
|
-
# change this to slow down polling, default is much faster
|
74
|
-
# and hard to debug
|
75
|
-
config.opts = { seconds_between_poll: 2 }
|
76
|
-
end
|
77
|
-
```
|
35
|
+
One language. One model. One set of tests. The same business logic and domain models running on the clients and the server. Hyperloop is fully integrated with Rails and also gives you unfettered access to the complete universe of JavaScript libraries (including React) from within your Ruby code. Hyperloop lets you build beautiful interactive user interfaces in Ruby.
|
78
36
|
|
79
|
-
|
37
|
+
Everything has a place in our architecture. Components deliver interactive user experiences, Operations encapsulate business logic, Models magically synchronize data between clients and servers, Policies govern authorization and Stores hold local state.
|
80
38
|
|
81
|
-
|
82
|
-
# app/policies/application_policy.rb
|
83
|
-
class Hyperloop::ApplicationPolicy
|
84
|
-
# allow any client too attach to the Hyperloop::Application for example
|
85
|
-
always_allow_connection
|
86
|
-
end
|
87
|
-
```
|
39
|
+
**Hyper-Operation** brings Operations which encapsulate business logic. In a traditional MVC architecture, Operations end up either in Controllers, Models or some other secondary construct such as service objects, helpers, or concerns. Here they are first class objects. Their job is to mutate state in the Stores and Models.
|
88
40
|
|
89
|
-
|
41
|
+
## Getting Started
|
90
42
|
|
91
|
-
|
43
|
+
1. Update your Gemfile:
|
92
44
|
|
93
45
|
```ruby
|
94
|
-
#
|
95
|
-
|
46
|
+
#Gemfile
|
47
|
+
|
48
|
+
gem 'hyperloop'
|
96
49
|
```
|
97
50
|
|
98
|
-
|
51
|
+
2. At the command prompt, update your bundle :
|
52
|
+
|
53
|
+
$ bundle update
|
54
|
+
|
55
|
+
3. Run the hyperloop install generator:
|
56
|
+
|
57
|
+
$ rails g hyperloop:install
|
99
58
|
|
100
|
-
|
59
|
+
4. Follow the guidelines to start developing your application. You may find
|
60
|
+
the following resources handy:
|
61
|
+
* [Getting Started with Hyperloop](http://ruby-hyperloop.io/start/components/)
|
62
|
+
* [Hyperloop Guides](http://ruby-hyperloop.io/docs/architecture)
|
63
|
+
* [Hyperloop Tutorial](http://ruby-hyperloop.io/tutorials)
|
101
64
|
|
102
|
-
|
65
|
+
## Community
|
103
66
|
|
104
|
-
|
67
|
+
#### Getting Help
|
68
|
+
Please **do not post** usage questions to GitHub Issues. For these types of questions use our [Gitter chatroom](https://gitter.im/ruby-hyperloop/chat) or [StackOverflow](http://stackoverflow.com/questions/tagged/hyperloop).
|
105
69
|
|
106
|
-
|
70
|
+
#### Submitting Bugs and Enhancements
|
71
|
+
[GitHub Issues](https://github.com/ruby-hyperloop/hyperloop/issues) is for suggesting enhancements and reporting bugs. Before submiting a bug make sure you do the following:
|
72
|
+
* Check out our [contributing guide](https://github.com/ruby-hyperloop/hyperloop/blob/master/CONTRIBUTING.md) for info on our release cycle.
|
107
73
|
|
108
74
|
## License
|
109
75
|
|
110
|
-
|
76
|
+
Hyperloop is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/hyper-operation.gemspec
CHANGED
@@ -23,8 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency 'hyperloop-config', '>= 0.9.7'
|
24
24
|
spec.add_dependency 'opal-activesupport'
|
25
25
|
spec.add_dependency 'activerecord', '>= 0.3.0'
|
26
|
-
spec.add_dependency 'pusher'
|
27
|
-
spec.add_dependency 'pusher-fake'
|
28
26
|
|
29
27
|
spec.add_development_dependency "bundler", "~> 1.8"
|
30
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -35,10 +33,14 @@ Gem::Specification.new do |spec|
|
|
35
33
|
spec.add_development_dependency 'hyper-react'
|
36
34
|
spec.add_development_dependency 'opal-browser'
|
37
35
|
spec.add_development_dependency 'sqlite3', '1.3.10'
|
36
|
+
spec.add_development_dependency 'mysql2'
|
38
37
|
spec.add_development_dependency 'database_cleaner'
|
39
38
|
spec.add_development_dependency 'pry'
|
40
39
|
spec.add_development_dependency 'rspec-wait'
|
41
40
|
spec.add_development_dependency 'puma'
|
42
41
|
spec.add_development_dependency 'rspec-steps'
|
42
|
+
spec.add_development_dependency 'pusher'
|
43
|
+
spec.add_development_dependency 'pusher-fake'
|
44
|
+
spec.add_development_dependency 'timecop', '~>0.8.1'
|
43
45
|
|
44
46
|
end
|
data/lib/hyper-operation/api.rb
CHANGED
@@ -63,6 +63,11 @@ module Hyperloop
|
|
63
63
|
_Railway.add_param(*args, &block)
|
64
64
|
end
|
65
65
|
|
66
|
+
def inbound(*args, &block)
|
67
|
+
name, opts = ParamsWrapper.get_name_and_opts(*args)
|
68
|
+
_Railway.add_param(name, opts.merge(inbound: :true), &block)
|
69
|
+
end
|
70
|
+
|
66
71
|
def outbound(*keys)
|
67
72
|
keys.each { |key| _Railway.add_param(key => nil, :type => :outbound) }
|
68
73
|
#singleton_class.outbound(*keys)
|
@@ -102,6 +107,11 @@ module Hyperloop
|
|
102
107
|
_Railway.add_param(*args, &block)
|
103
108
|
end
|
104
109
|
|
110
|
+
child.singleton_class.define_singleton_method(:inbound) do |*args, &block|
|
111
|
+
name, opts = ParamsWrapper.get_name_and_opts(*args)
|
112
|
+
_Railway.add_param(name, opts.merge(inbound: :true), &block)
|
113
|
+
end
|
114
|
+
|
105
115
|
child.singleton_class.define_singleton_method(:outbound) do |*keys|
|
106
116
|
keys.each { |key| _Railway.add_param(key => nil, :type => :outbound) }
|
107
117
|
end
|
@@ -12,7 +12,12 @@ module Hyperloop
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def to_h
|
15
|
-
@inputs
|
15
|
+
inputs = @inputs
|
16
|
+
if @locked
|
17
|
+
inputs = inputs.dup
|
18
|
+
self.class.inbound_params.each { |name| inputs.delete :"#{name}" }
|
19
|
+
end
|
20
|
+
inputs.with_indifferent_access
|
16
21
|
end
|
17
22
|
|
18
23
|
def to_s
|
@@ -39,6 +44,7 @@ module Hyperloop
|
|
39
44
|
|
40
45
|
def add_param(*args, &block)
|
41
46
|
type_method, name, opts, block = translate_args(*args, &block)
|
47
|
+
inbound_params << :"#{name}" if opts.delete(:inbound)
|
42
48
|
if opts.key? :default
|
43
49
|
hash_filter.optional { send(type_method, name, opts, &block) }
|
44
50
|
else
|
@@ -65,6 +71,10 @@ module Hyperloop
|
|
65
71
|
@hash_filter ||= Mutations::HashFilter.new
|
66
72
|
end
|
67
73
|
|
74
|
+
def inbound_params
|
75
|
+
@inbound_params ||= Set.new
|
76
|
+
end
|
77
|
+
|
68
78
|
def translate_args(*args, &block)
|
69
79
|
name, opts = get_name_and_opts(*args)
|
70
80
|
if opts.key?(:type)
|
@@ -115,6 +125,8 @@ module Hyperloop
|
|
115
125
|
Class.new(superclass.params_wrapper).tap do |wrapper|
|
116
126
|
hash_filter = superclass.params_wrapper.hash_filter
|
117
127
|
wrapper.instance_variable_set('@hash_filter', hash_filter && hash_filter.dup)
|
128
|
+
inbound_params = superclass.params_wrapper.inbound_params
|
129
|
+
wrapper.instance_variable_set('@inbound_params', inbound_params && inbound_params.dup)
|
118
130
|
end
|
119
131
|
end
|
120
132
|
end
|
@@ -101,7 +101,7 @@ module Hyperloop
|
|
101
101
|
end
|
102
102
|
|
103
103
|
class ControllerOp < ServerOp
|
104
|
-
|
104
|
+
inbound :controller
|
105
105
|
alias pre_controller_op_method_missing method_missing
|
106
106
|
def method_missing(name, *args, &block)
|
107
107
|
if params.controller.respond_to? name
|
@@ -28,6 +28,10 @@ module Hyperloop
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def self.connect_session
|
32
|
+
connect(['Hyperloop::Session', ClientDrivers.opts[:id].split('-').last])
|
33
|
+
end
|
34
|
+
|
31
35
|
def self.action_cable_consumer
|
32
36
|
ClientDrivers.opts[:action_cable_consumer]
|
33
37
|
end
|
@@ -114,6 +118,7 @@ module Hyperloop
|
|
114
118
|
end
|
115
119
|
controller.session.delete 'hyperloop-dummy-init' unless controller.session.id
|
116
120
|
id = "#{SecureRandom.uuid}-#{controller.session.id}"
|
121
|
+
auto_connections = Hyperloop::AutoConnect.channels(id, controller.acting_user)
|
117
122
|
config_hash = {
|
118
123
|
transport: Hyperloop.transport,
|
119
124
|
id: id,
|
@@ -126,7 +131,7 @@ module Hyperloop
|
|
126
131
|
channel: Hyperloop.channel,
|
127
132
|
form_authenticity_token: controller.send(:form_authenticity_token),
|
128
133
|
seconds_between_poll: Hyperloop.seconds_between_poll,
|
129
|
-
auto_connect:
|
134
|
+
auto_connect: auto_connections
|
130
135
|
}
|
131
136
|
path = ::Rails.application.routes.routes.detect do |route|
|
132
137
|
# not sure why the second check is needed. It happens in the test app
|
@@ -171,7 +176,6 @@ module Hyperloop
|
|
171
176
|
end
|
172
177
|
|
173
178
|
if on_opal_client?
|
174
|
-
|
175
179
|
if opts[:transport] == :pusher
|
176
180
|
|
177
181
|
opts[:dispatch] = lambda do |data|
|
@@ -2,7 +2,8 @@ module Hyperloop
|
|
2
2
|
module AutoCreate
|
3
3
|
def needs_init?
|
4
4
|
return false if Hyperloop.transport == :none
|
5
|
-
return true
|
5
|
+
return true if connection.respond_to?(:data_sources) && !connection.data_sources.include?(table_name)
|
6
|
+
return true if !connection.respond_to?(:data_sources) && !connection.tables.include?(table_name)
|
6
7
|
return false unless Hyperloop.on_server?
|
7
8
|
return true if defined?(Rails::Server)
|
8
9
|
return true unless Connection.root_path
|
@@ -19,6 +19,7 @@ module Hyperloop
|
|
19
19
|
config.after_initialize { Connection.build_tables }
|
20
20
|
end
|
21
21
|
Object.send(:remove_const, :Application) if @fake_application_defined
|
22
|
+
@fake_application_defined = false
|
22
23
|
policy = begin
|
23
24
|
Object.const_get 'ApplicationPolicy'
|
24
25
|
rescue LoadError
|
@@ -61,6 +62,7 @@ module Hyperloop
|
|
61
62
|
define_setting :opts, {}
|
62
63
|
define_setting :channel_prefix, 'synchromesh'
|
63
64
|
define_setting :client_logging, true
|
65
|
+
define_setting :connect_session, true
|
64
66
|
|
65
67
|
def self.app_id
|
66
68
|
opts[:app_id] || Pusher.app_id if transport == :pusher
|
@@ -42,6 +42,17 @@ module Hyperloop
|
|
42
42
|
session.delete 'hyperloop-dummy-init' unless session.id
|
43
43
|
end
|
44
44
|
|
45
|
+
def session_channel
|
46
|
+
"Hyperloop::Session-#{session.id}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def regulate(channel)
|
50
|
+
unless channel == session_channel # "Hyperloop::Session-#{client_id.split('-').last}"
|
51
|
+
Hyperloop::InternalPolicy.regulate_connection(try(:acting_user), channel)
|
52
|
+
end
|
53
|
+
channel
|
54
|
+
end
|
55
|
+
|
45
56
|
def channels(user = acting_user, session_id = session.id)
|
46
57
|
Hyperloop::AutoConnect.channels(session_id, user)
|
47
58
|
end
|
@@ -89,8 +100,7 @@ module Hyperloop
|
|
89
100
|
end
|
90
101
|
|
91
102
|
def subscribe
|
92
|
-
channel = params[:channel].gsub('==', '::')
|
93
|
-
Hyperloop::InternalPolicy.regulate_connection(try(:acting_user), channel)
|
103
|
+
channel = regulate params[:channel].gsub('==', '::')
|
94
104
|
root_path = request.original_url.gsub(/hyperloop-subscribe.*$/, '')
|
95
105
|
Hyperloop::Connection.open(channel, client_id, root_path)
|
96
106
|
head :ok
|
@@ -105,8 +115,7 @@ module Hyperloop
|
|
105
115
|
end
|
106
116
|
|
107
117
|
def pusher_auth
|
108
|
-
channel = params[:channel_name].gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/,'').gsub('==', '::')
|
109
|
-
Hyperloop::InternalPolicy.regulate_connection(acting_user, channel)
|
118
|
+
channel = regulate params[:channel_name].gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/,'').gsub('==', '::')
|
110
119
|
response = Hyperloop.pusher.authenticate(params[:channel_name], params[:socket_id])
|
111
120
|
render json: response
|
112
121
|
rescue Exception => e
|
@@ -114,8 +123,7 @@ module Hyperloop
|
|
114
123
|
end
|
115
124
|
|
116
125
|
def action_cable_auth
|
117
|
-
channel = params[:channel_name].gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/,'')
|
118
|
-
Hyperloop::InternalPolicy.regulate_connection(acting_user, channel)
|
126
|
+
channel = regulate params[:channel_name].gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/,'')
|
119
127
|
salt = SecureRandom.hex
|
120
128
|
authorization = Hyperloop.authorization(salt, channel, client_id)
|
121
129
|
render json: {authorization: authorization, salt: salt}
|
@@ -296,11 +296,8 @@ module Hyperloop
|
|
296
296
|
def self.channels(session, acting_user)
|
297
297
|
channels = ClassConnectionRegulation.connections_for(acting_user, true) +
|
298
298
|
InstanceConnectionRegulation.connections_for(acting_user, true)
|
299
|
-
channels
|
300
|
-
channels.each
|
301
|
-
Connection.open(channel, session)
|
302
|
-
end
|
303
|
-
channels
|
299
|
+
channels << "Hyperloop::Session-#{session.split('-').last}" if Hyperloop.connect_session && session
|
300
|
+
channels.uniq.each { |channel| Connection.open(channel, session) }
|
304
301
|
end
|
305
302
|
end
|
306
303
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyper-operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- catmando
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mutations
|
@@ -80,34 +80,6 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.3.0
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: pusher
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pusher-fake
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :runtime
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
83
|
- !ruby/object:Gem::Dependency
|
112
84
|
name: bundler
|
113
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,6 +206,20 @@ dependencies:
|
|
234
206
|
- - '='
|
235
207
|
- !ruby/object:Gem::Version
|
236
208
|
version: 1.3.10
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: mysql2
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
237
223
|
- !ruby/object:Gem::Dependency
|
238
224
|
name: database_cleaner
|
239
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -304,6 +290,48 @@ dependencies:
|
|
304
290
|
- - ">="
|
305
291
|
- !ruby/object:Gem::Version
|
306
292
|
version: '0'
|
293
|
+
- !ruby/object:Gem::Dependency
|
294
|
+
name: pusher
|
295
|
+
requirement: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
type: :development
|
301
|
+
prerelease: false
|
302
|
+
version_requirements: !ruby/object:Gem::Requirement
|
303
|
+
requirements:
|
304
|
+
- - ">="
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '0'
|
307
|
+
- !ruby/object:Gem::Dependency
|
308
|
+
name: pusher-fake
|
309
|
+
requirement: !ruby/object:Gem::Requirement
|
310
|
+
requirements:
|
311
|
+
- - ">="
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: '0'
|
314
|
+
type: :development
|
315
|
+
prerelease: false
|
316
|
+
version_requirements: !ruby/object:Gem::Requirement
|
317
|
+
requirements:
|
318
|
+
- - ">="
|
319
|
+
- !ruby/object:Gem::Version
|
320
|
+
version: '0'
|
321
|
+
- !ruby/object:Gem::Dependency
|
322
|
+
name: timecop
|
323
|
+
requirement: !ruby/object:Gem::Requirement
|
324
|
+
requirements:
|
325
|
+
- - "~>"
|
326
|
+
- !ruby/object:Gem::Version
|
327
|
+
version: 0.8.1
|
328
|
+
type: :development
|
329
|
+
prerelease: false
|
330
|
+
version_requirements: !ruby/object:Gem::Requirement
|
331
|
+
requirements:
|
332
|
+
- - "~>"
|
333
|
+
- !ruby/object:Gem::Version
|
334
|
+
version: 0.8.1
|
307
335
|
description:
|
308
336
|
email:
|
309
337
|
- mitch@catprint.com
|
@@ -313,6 +341,8 @@ extra_rdoc_files: []
|
|
313
341
|
files:
|
314
342
|
- ".gitignore"
|
315
343
|
- CODE_OF_CONDUCT.md
|
344
|
+
- DOCS-POLICIES.md
|
345
|
+
- DOCS.md
|
316
346
|
- Gemfile
|
317
347
|
- LICENSE.txt
|
318
348
|
- README.md
|
@@ -619,7 +649,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
619
649
|
version: '0'
|
620
650
|
requirements: []
|
621
651
|
rubyforge_project:
|
622
|
-
rubygems_version: 2.
|
652
|
+
rubygems_version: 2.6.12
|
623
653
|
signing_key:
|
624
654
|
specification_version: 4
|
625
655
|
summary: Compose your business logic into isomorphic commands that sanitize and validate
|