elaios 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +263 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/elaios.gemspec +26 -0
- data/lib/elaios.rb +12 -0
- data/lib/elaios/client.rb +65 -0
- data/lib/elaios/server.rb +93 -0
- data/lib/elaios/version.rb +3 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 20887b1b251d6324dc684b0e87a99339dea9e37a
|
4
|
+
data.tar.gz: 64dfcd192b76ce0c41370943e780b51dc0db21e3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dda0d362a80747fda46f2f37639e5e06ac0c88523eb866b8820c615ad6dcf952efedda4527d92b151ed118c51efaa86e68a7417ba6ba901cff857a2064503370
|
7
|
+
data.tar.gz: 8601b34a70f2bb4523073e22fc847b60ae0bb58a92ecd74ac08badb14b7074f3466d2b078560053f110854a543c4c1346caab462f0e9af52e999351a47a34320
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
# Elaios
|
2
|
+
|
3
|
+
Elaios is a protocol-agnostic library for writing JSON-RPC clients and servers.
|
4
|
+
It can be used over TCP, HTTP, STOMP, and other protocols, and can be used with
|
5
|
+
threaded-, evented-, or fiber-based code.
|
6
|
+
|
7
|
+
Furthermore, it is thread-safe, has a very simple API, and well-tested.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'elaios'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install elaios
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Look in the `spec/integation` directory for more usage examples.
|
28
|
+
|
29
|
+
### Including Elaios in your code
|
30
|
+
|
31
|
+
From your Ruby code:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'elaios'
|
35
|
+
```
|
36
|
+
|
37
|
+
### Basic client usage
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
elaios_client = Elaios::Client.new
|
41
|
+
|
42
|
+
# Call a JSON-RPC method and don't expect a response.
|
43
|
+
elaios_client.foo(['some', 'args'])
|
44
|
+
|
45
|
+
# Call a JSON-RPC method and expect a response.
|
46
|
+
elaios_client.bar(['some', 'other', 'args']) do |data|
|
47
|
+
# Do something with the response from the server...
|
48
|
+
end
|
49
|
+
|
50
|
+
request_1 = elaios_client.pop
|
51
|
+
request_2 = elaios_client.pop
|
52
|
+
# Send the requests to the server somehow (they will be JSON strings)...
|
53
|
+
|
54
|
+
# Get a response from the server somehow (it will be a JSON string). This will
|
55
|
+
# trigger the callback above to be called.
|
56
|
+
elaios_client << response
|
57
|
+
```
|
58
|
+
|
59
|
+
### Basic server usage
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
elaios_server = Elaios::Server.new
|
63
|
+
|
64
|
+
elaios_server.foo do |data|
|
65
|
+
# Do some processing here...
|
66
|
+
end
|
67
|
+
|
68
|
+
elaios_server.bar do |data|
|
69
|
+
# To send a success response...
|
70
|
+
res(data['method'], data['id'], ['some', 'response'])
|
71
|
+
|
72
|
+
# Or, to send an error response...
|
73
|
+
err(data['method'], data['id'], 'Sorry, an error occurred.')
|
74
|
+
end
|
75
|
+
|
76
|
+
# Get JSON string requests from the client somehow. These will trigger the above
|
77
|
+
# callbacks to be called.
|
78
|
+
elaios_server << request_1
|
79
|
+
elaios_server << request_2
|
80
|
+
|
81
|
+
response = elaios_server.pop
|
82
|
+
# Send the response to the client somehow (it will be a JSON string).
|
83
|
+
```
|
84
|
+
|
85
|
+
### API
|
86
|
+
|
87
|
+
```
|
88
|
+
# --------------
|
89
|
+
# Elaios::Server
|
90
|
+
# --------------
|
91
|
+
|
92
|
+
# Create a new Elaios server object.
|
93
|
+
Elaios::Server#new(options={})
|
94
|
+
|
95
|
+
`options` may consist of:
|
96
|
+
|
97
|
+
* `:name` - An optional name for a server.
|
98
|
+
* `:logger` - An optional logger object.
|
99
|
+
|
100
|
+
# Push an object onto the server for processing.
|
101
|
+
Elaios::Server#push(obj)
|
102
|
+
Elaios::Server#<<(obj)
|
103
|
+
Elaios::Server#enq(obj)
|
104
|
+
|
105
|
+
# Pop a response off of the server.
|
106
|
+
Elaios::Server#pop
|
107
|
+
Elaios::Server#deq
|
108
|
+
Elaios::Server#shift
|
109
|
+
|
110
|
+
# Push an object onto the server, update, and then pop a response off.
|
111
|
+
Elaios::Server#process(obj)
|
112
|
+
Elaios::Server#pushpop(obj)
|
113
|
+
Elaios::Server#push_pop(obj)
|
114
|
+
|
115
|
+
# Register a handler.
|
116
|
+
Elaios::Server#method_missing(name, &block)
|
117
|
+
|
118
|
+
# Generate a success response for sending to the client.
|
119
|
+
Elaios::Server#res(method, id, data)
|
120
|
+
Elaios::Server#response(method, id, data)
|
121
|
+
|
122
|
+
# Generate an error response for sending to the client.
|
123
|
+
Elaios::Server#err(method, id, data)
|
124
|
+
Elaios::Server#error(method, id, data)
|
125
|
+
|
126
|
+
# --------------
|
127
|
+
# Elaios::Client
|
128
|
+
# --------------
|
129
|
+
|
130
|
+
# Create a new Elaios client object.
|
131
|
+
Elaios::Client.new(options={})
|
132
|
+
|
133
|
+
`options` may consist of:
|
134
|
+
|
135
|
+
* `:name` - An optional name for a server.
|
136
|
+
* `:logger` - An optional logger object.
|
137
|
+
|
138
|
+
# Push an object onto the client for processing.
|
139
|
+
Elaios::Client.push(obj)
|
140
|
+
Elaios::Client.<<(obj)
|
141
|
+
Elaios::Client.enq(obj)
|
142
|
+
|
143
|
+
# Pop a response off of the client.
|
144
|
+
Elaios::Client#pop
|
145
|
+
Elaios::Client#deq
|
146
|
+
Elaios::Client#shift
|
147
|
+
|
148
|
+
# Call a JSON-RPC method.
|
149
|
+
Elaios::Client#method_missing(name, args=nil, &block)
|
150
|
+
```
|
151
|
+
|
152
|
+
### Threaded TCP client usage
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
# TCP client.
|
156
|
+
socket = TCPSocket.open('0.0.0.0', 5000)
|
157
|
+
elaios_client = Elaios::Client.new
|
158
|
+
|
159
|
+
# Incoming socket data.
|
160
|
+
Thread.new do
|
161
|
+
loop do
|
162
|
+
elaios_client << socket.gets.chomp
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Outgoing socket data.
|
167
|
+
Thread.new do
|
168
|
+
loop do
|
169
|
+
result = elaios_client.pop
|
170
|
+
socket.puts(result) if result
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Make a service call and expect no response.
|
175
|
+
elaios_client.ping('foo')
|
176
|
+
|
177
|
+
# Make a service call and expect a response.
|
178
|
+
elaios_client.ping('foo') do |response|
|
179
|
+
# Do something with the response...
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
### Threaded TCP server usage
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
# TCP server.
|
187
|
+
server = TCPServer.open(5000)
|
188
|
+
loop do
|
189
|
+
# New incoming socket connection.
|
190
|
+
Thread.fork(server.accept) do |socket|
|
191
|
+
# We need a new Elaios instance for every incoming connection.
|
192
|
+
elaios_server = Elaios::Server.new
|
193
|
+
|
194
|
+
# Create a server handler.
|
195
|
+
elaios_server.ping do |data|
|
196
|
+
# Generate some sort of response. Note that we grab the method name and id
|
197
|
+
# from the `data` hash.
|
198
|
+
#
|
199
|
+
# Also note that within this block, `self` is the `elaios_server` object.
|
200
|
+
#
|
201
|
+
res(data['method'], data['id'], { foo: 'bar' })
|
202
|
+
end
|
203
|
+
|
204
|
+
# Incoming socket data.
|
205
|
+
Thread.new do
|
206
|
+
loop do
|
207
|
+
elaios_server << socket.gets.chomp
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Outgoing socket data.
|
212
|
+
Thread.new do
|
213
|
+
loop do
|
214
|
+
result = elaios_server.pop
|
215
|
+
socket.puts(result) if result
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
222
|
+
### Evented TCP client usage
|
223
|
+
|
224
|
+
**TODO:** Fill this in.
|
225
|
+
|
226
|
+
### Evented TCP server usage
|
227
|
+
|
228
|
+
**TODO:** Fill this in.
|
229
|
+
|
230
|
+
### HTTP client usage
|
231
|
+
|
232
|
+
**NOTE:** This is only one way to use Elaios with an HTTP client. You can use
|
233
|
+
any HTTP client library with Elaios.
|
234
|
+
|
235
|
+
**TODO:** Fill this in.
|
236
|
+
|
237
|
+
### HTTP server usage
|
238
|
+
|
239
|
+
**NOTE:** This is only one way to use Elaios with an HTTP server. You can use
|
240
|
+
any HTTP server library with Elaios.
|
241
|
+
|
242
|
+
**TODO:** Fill this in.
|
243
|
+
|
244
|
+
### STOMP usage
|
245
|
+
|
246
|
+
**TODO:** Fill this in.
|
247
|
+
|
248
|
+
## Development
|
249
|
+
|
250
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
251
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
252
|
+
prompt that will allow you to experiment.
|
253
|
+
|
254
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
255
|
+
release a new version, update the version number in `version.rb`, and then run
|
256
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
257
|
+
git commits and tags, and push the `.gem` file to
|
258
|
+
[rubygems.org](https://rubygems.org).
|
259
|
+
|
260
|
+
## Contributing
|
261
|
+
|
262
|
+
Bug reports and pull requests are welcome on GitHub at
|
263
|
+
https://github.com/rjungemann/elaios.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "elaios"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/elaios.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'elaios/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'elaios'
|
8
|
+
spec.version = Elaios::VERSION
|
9
|
+
spec.authors = ['Roger Jungemann']
|
10
|
+
spec.email = ['roger@thefifthcircuit.com']
|
11
|
+
|
12
|
+
spec.summary = %q{A protocol-agnostic JSON-RPC client-server library.}
|
13
|
+
spec.homepage = 'https://github.com/rjungemann/elaios'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = 'exe'
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_dependency 'simple-queue', '~> 0.1.0'
|
21
|
+
spec.add_dependency 'eventmachine', '1.2.0.1'
|
22
|
+
spec.add_dependency 'sinatra', '1.4.7'
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
|
+
end
|
data/lib/elaios.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
class Elaios::Client
|
2
|
+
attr_reader :logger
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
@name = options[:name] || 'elaios_client'
|
6
|
+
@logger = options[:logger] || Logger.new(STDOUT).tap { |l|
|
7
|
+
l.progname = @name
|
8
|
+
l.level = ENV['LOG_LEVEL'] || 'info'
|
9
|
+
}
|
10
|
+
@blocks = {}
|
11
|
+
@in = Simple::Queue.new
|
12
|
+
@out = Simple::Queue.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def push(obj)
|
16
|
+
@in.push(obj)
|
17
|
+
update
|
18
|
+
end
|
19
|
+
alias_method :<<, :push
|
20
|
+
alias_method :enq, :push
|
21
|
+
|
22
|
+
def pop
|
23
|
+
@out.pop
|
24
|
+
end
|
25
|
+
alias_method :deq, :pop
|
26
|
+
alias_method :shift, :pop
|
27
|
+
|
28
|
+
# Call a remote JSON-RPC method. If a block is provided, then we expect a
|
29
|
+
# response from the server.
|
30
|
+
def method_missing(name, args=nil, &block)
|
31
|
+
id = SecureRandom.uuid
|
32
|
+
data = {
|
33
|
+
'jsonrpc' => '2.0',
|
34
|
+
'method' => name,
|
35
|
+
'params' => args
|
36
|
+
}
|
37
|
+
# Only set the id if the client expects a response.
|
38
|
+
data['id'] = id if block
|
39
|
+
payload = JSON.dump(data)
|
40
|
+
@logger.debug(%(method_missing payload: #{payload.inspect}))
|
41
|
+
@out << payload
|
42
|
+
return unless block
|
43
|
+
@logger.debug(%(registered block for id #{id}: #{block.inspect}))
|
44
|
+
@blocks[id] = block if block
|
45
|
+
end
|
46
|
+
|
47
|
+
# Called internally by `push`. Exposed for testing.
|
48
|
+
def update
|
49
|
+
results = @in.pop
|
50
|
+
return unless results
|
51
|
+
results.split("\n").each do |result|
|
52
|
+
@logger.debug(%(result given: #{result}))
|
53
|
+
payload = JSON.load(result) rescue nil
|
54
|
+
next unless payload
|
55
|
+
@logger.debug(%(payload parsed: #{payload.inspect}))
|
56
|
+
block = @blocks[payload['id']]
|
57
|
+
@logger.debug(%(block found: #{block.inspect}))
|
58
|
+
next unless block
|
59
|
+
self.instance_exec(payload, &block)
|
60
|
+
@logger.debug(%(block called: #{block.inspect}))
|
61
|
+
@blocks.delete(payload['id'])
|
62
|
+
@logger.debug(%(block unregistered: #{block.inspect}))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
class Elaios::Server
|
2
|
+
attr_reader :logger
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
@name = options[:name] || 'elaios_server'
|
6
|
+
@logger = options[:logger] || Logger.new(STDOUT).tap { |l|
|
7
|
+
l.progname = @name
|
8
|
+
l.level = ENV['LOG_LEVEL'] || 'info'
|
9
|
+
}
|
10
|
+
@blocks = {}
|
11
|
+
@in = Simple::Queue.new
|
12
|
+
@out = Simple::Queue.new
|
13
|
+
@mutex = Mutex.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def push(obj)
|
17
|
+
@mutex.synchronize { unsafe_push(obj) }
|
18
|
+
end
|
19
|
+
alias_method :<<, :push
|
20
|
+
alias_method :enq, :push
|
21
|
+
|
22
|
+
def pop
|
23
|
+
@mutex.synchronize { unsafe_pop }
|
24
|
+
end
|
25
|
+
alias_method :deq, :pop
|
26
|
+
alias_method :shift, :pop
|
27
|
+
|
28
|
+
def process(obj)
|
29
|
+
@mutex.synchronize { unsafe_push(obj); unsafe_pop }
|
30
|
+
end
|
31
|
+
alias_method :pushpop, :process
|
32
|
+
alias_method :push_pop, :process
|
33
|
+
|
34
|
+
# Set up a handler.
|
35
|
+
def method_missing(name, &block)
|
36
|
+
@blocks[name] = block
|
37
|
+
@logger.debug(%(registered handler for #{name}: #{block.inspect}))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Send a success response to the client.
|
41
|
+
def res(method, id, data)
|
42
|
+
payload = JSON.dump({
|
43
|
+
'jsonrpc' => '2.0',
|
44
|
+
'method' => method,
|
45
|
+
'result' => data,
|
46
|
+
'id' => id
|
47
|
+
})
|
48
|
+
@logger.debug(%(enqueueing success payload for sending: #{payload.inspect}))
|
49
|
+
@out << payload
|
50
|
+
end
|
51
|
+
alias_method :response, :res
|
52
|
+
|
53
|
+
# Send an error response to the client.
|
54
|
+
def err(method, id, data)
|
55
|
+
payload = JSON.dump({
|
56
|
+
'jsonrpc' => '2.0',
|
57
|
+
'method' => method,
|
58
|
+
'error' => data,
|
59
|
+
'id' => id
|
60
|
+
})
|
61
|
+
@logger.debug(%(enqueueing error payload for sending: #{payload.inspect}))
|
62
|
+
@out << payload
|
63
|
+
end
|
64
|
+
alias_method :error, :err
|
65
|
+
|
66
|
+
# Called internally by `push`. Exposed for testing.
|
67
|
+
def update
|
68
|
+
results = @in.pop
|
69
|
+
return unless results
|
70
|
+
results.split("\n").each do |result|
|
71
|
+
@logger.debug(%(result given: #{result}))
|
72
|
+
payload = JSON.load(result) rescue nil
|
73
|
+
next unless payload
|
74
|
+
@logger.debug(%(payload parsed: #{payload.inspect}))
|
75
|
+
block = @blocks[payload['method'].to_sym]
|
76
|
+
@logger.debug(%(block found: #{block.inspect}))
|
77
|
+
next unless block
|
78
|
+
self.instance_exec(payload, &block)
|
79
|
+
@logger.debug(%(block called: #{block.inspect}))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Called internally by `push` and `process`. Exposed for testing.
|
84
|
+
def unsafe_push(obj)
|
85
|
+
@in.push(obj)
|
86
|
+
update
|
87
|
+
end
|
88
|
+
|
89
|
+
# Called internally by `pop` and `process`. Exposed for testing.
|
90
|
+
def unsafe_pop
|
91
|
+
@out.pop
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: elaios
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roger Jungemann
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: simple-queue
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: eventmachine
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.0.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.2.0.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sinatra
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.4.7
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.4.7
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.12'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.12'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- roger@thefifthcircuit.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".travis.yml"
|
107
|
+
- Gemfile
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- bin/console
|
111
|
+
- bin/setup
|
112
|
+
- elaios.gemspec
|
113
|
+
- lib/elaios.rb
|
114
|
+
- lib/elaios/client.rb
|
115
|
+
- lib/elaios/server.rb
|
116
|
+
- lib/elaios/version.rb
|
117
|
+
homepage: https://github.com/rjungemann/elaios
|
118
|
+
licenses: []
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.5.1
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: A protocol-agnostic JSON-RPC client-server library.
|
140
|
+
test_files: []
|