cloudkit 0.11.1 → 0.11.2
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.
- data/CHANGES +8 -0
- data/README +1 -1
- data/TODO +1 -3
- data/cloudkit.gemspec +5 -5
- data/doc/curl.html +4 -2
- data/doc/index.html +1 -1
- data/lib/cloudkit.rb +2 -2
- data/lib/cloudkit/oauth_filter.rb +1 -1
- data/lib/cloudkit/openid_filter.rb +9 -0
- data/lib/cloudkit/rack/builder.rb +1 -1
- data/lib/cloudkit/request.rb +5 -0
- data/lib/cloudkit/service.rb +17 -8
- data/lib/cloudkit/store.rb +5 -4
- data/lib/cloudkit/store/resource.rb +3 -3
- data/lib/cloudkit/store/response_helpers.rb +18 -7
- data/lib/cloudkit/uri.rb +2 -2
- data/spec/flash_session_spec.rb +1 -1
- data/spec/openid_filter_spec.rb +2 -0
- data/spec/request_spec.rb +6 -0
- data/spec/service_spec.rb +30 -4
- data/spec/uri_spec.rb +1 -1
- metadata +8 -8
data/CHANGES
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.11.2
|
2
|
+
- Added Location header for 201s
|
3
|
+
- Fixed JSON response for DELETE operations
|
4
|
+
- Updated MD5 dependency for Ruby 1.9 (Andreas Haller)
|
5
|
+
- Updated spec setup for RSpec 1.2 (Andreas Haller)
|
6
|
+
- Updated gem dependencies for Rack, OpenID, and JSON
|
7
|
+
- Other minor fixes
|
8
|
+
|
1
9
|
0.11.1
|
2
10
|
- Added a block option for configuring OpenID bypassed routes (Devlin Daley)
|
3
11
|
- Added write locks for Tokyo Tyrant Tables
|
data/README
CHANGED
@@ -17,7 +17,7 @@ In a rackup file called config.ru:
|
|
17
17
|
require 'cloudkit'
|
18
18
|
expose :notes, :todos
|
19
19
|
|
20
|
-
The above creates a versioned HTTP service using JSON to represent two types of resource collections -- Notes and ToDos.
|
20
|
+
The above creates a versioned HTTP/REST service using JSON to represent two types of resource collections -- Notes and ToDos.
|
21
21
|
|
22
22
|
In a different rackup file:
|
23
23
|
|
data/TODO
CHANGED
@@ -2,18 +2,16 @@
|
|
2
2
|
- openid sreg
|
3
3
|
- oauth token management
|
4
4
|
- oauth consumer registration
|
5
|
-
- acls i.e. allowed methods per user per uri
|
6
|
-
- jsonpath
|
7
5
|
- jsonquery
|
8
6
|
- jsonschema
|
9
7
|
- user lookup via a block for integration with existing stores
|
10
8
|
- custom templates for openid / oauth
|
11
9
|
|
12
10
|
Backlog
|
11
|
+
- acls i.e. allowed methods per user per uri
|
13
12
|
- method filtering on collections
|
14
13
|
- js functions as observers (validation, mapping, etc.)
|
15
14
|
- complete user data export
|
16
|
-
- batch updates (post, put, delete)
|
17
15
|
- expect header/100-continue
|
18
16
|
- deployable gem + admin app
|
19
17
|
- cappuccino adapter
|
data/cloudkit.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
s.name = "cloudkit"
|
5
|
-
s.version = "0.11.
|
6
|
-
s.date = "2008-03
|
5
|
+
s.version = "0.11.2"
|
6
|
+
s.date = "2008-05-03"
|
7
7
|
s.summary = "An Open Web JSON Appliance."
|
8
8
|
s.description = "An Open Web JSON Appliance."
|
9
9
|
s.authors = ["Jon Crosby"]
|
@@ -77,9 +77,9 @@ Gem::Specification.new do |s|
|
|
77
77
|
s.test_files = s.files.select {|path| path =~ /^spec\/.*_spec.rb/}
|
78
78
|
s.rubyforge_project = "cloudkit"
|
79
79
|
s.rubygems_version = "1.1.1"
|
80
|
-
s.add_dependency 'rack', '
|
80
|
+
s.add_dependency 'rack', '>= 1.0'
|
81
81
|
s.add_dependency 'uuid', '= 2.0.1'
|
82
82
|
s.add_dependency 'oauth', '~> 0.3'
|
83
|
-
s.add_dependency 'ruby-openid', '
|
84
|
-
s.add_dependency 'json', '
|
83
|
+
s.add_dependency 'ruby-openid', '~> 2.1'
|
84
|
+
s.add_dependency 'json', '~> 1.1'
|
85
85
|
end
|
data/doc/curl.html
CHANGED
@@ -38,13 +38,13 @@ If you haven't already installed the gem:
|
|
38
38
|
</p>
|
39
39
|
|
40
40
|
<p>
|
41
|
-
If you already have the gem, make sure you're running the latest version (0.11.
|
41
|
+
If you already have the gem, make sure you're running the latest version (0.11.2):
|
42
42
|
<div class="code">
|
43
43
|
$ gem list cloudkit<br/>
|
44
44
|
cloudkit (0.10.0) <-- need to upgrade<br/>
|
45
45
|
$ gem update cloudkit<br/>
|
46
46
|
$ gem list cloudkit<br/>
|
47
|
-
cloudkit (0.11.
|
47
|
+
cloudkit (0.11.2, 0.10.0) <-- 0.11.2 is now in the list
|
48
48
|
</div>
|
49
49
|
</p>
|
50
50
|
|
@@ -120,6 +120,7 @@ Let's move on, creating a note using <a href="http://tools.ietf.org/html/rfc2616
|
|
120
120
|
$ curl -i -XPOST -d'{"title":"projects"}' http://localhost:9292/notes<br/>
|
121
121
|
HTTP/1.1 201 Created<br/>
|
122
122
|
Cache-Control: no-cache<br/>
|
123
|
+
Location: http://localhost:9292/notes/0dda06f0-b134-012b-a2d8-0017f2c62348<br/>
|
123
124
|
Content-Type: application/json<br/>
|
124
125
|
Content-Length: 159<br/><br/>
|
125
126
|
|
@@ -139,6 +140,7 @@ so that we can specify its location:
|
|
139
140
|
$ curl -i -XPUT -d'{"title":"reminders"}' http://localhost:9292/notes/abc<br/>
|
140
141
|
HTTP/1.1 201 Created<br/>
|
141
142
|
Cache-Control: no-cache<br/>
|
143
|
+
Location: http://localhost:9292/notes/abc<br/>
|
142
144
|
Content-Type: application/json<br/>
|
143
145
|
Content-Length: 126<br/><br/>
|
144
146
|
|
data/doc/index.html
CHANGED
@@ -24,7 +24,7 @@
|
|
24
24
|
</div>
|
25
25
|
<div class="meta">
|
26
26
|
<p class="wrapper">
|
27
|
-
Version 0.11.
|
27
|
+
Version 0.11.2 released with Tokyo Cabinet support. Install with <em>gem install cloudkit</em>.
|
28
28
|
</p>
|
29
29
|
</div>
|
30
30
|
<div class="wrapper intro-row">
|
data/lib/cloudkit.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'erb'
|
3
3
|
require 'json'
|
4
|
-
require 'md5'
|
4
|
+
require 'digest/md5'
|
5
5
|
require 'openid'
|
6
6
|
require 'time'
|
7
7
|
require 'uuid'
|
@@ -34,7 +34,7 @@ require 'cloudkit/user_store'
|
|
34
34
|
include CloudKit::Constants
|
35
35
|
|
36
36
|
module CloudKit
|
37
|
-
VERSION = '0.11.
|
37
|
+
VERSION = '0.11.2'
|
38
38
|
|
39
39
|
# Sets up the storage adapter. Defaults to development-time
|
40
40
|
# CloudKit::MemoryTable. Also supports Rufus Tokyo Table instances. See the
|
@@ -6,8 +6,17 @@ module CloudKit
|
|
6
6
|
# The root URI, "/", is always bypassed. More URIs can also be bypassed using
|
7
7
|
# the :allow option:
|
8
8
|
#
|
9
|
+
# use Rack::Session::Pool
|
9
10
|
# use OpenIDFilter, :allow => ['/foo', '/bar']
|
10
11
|
#
|
12
|
+
# In addition to the :allow option, a block can also be used for more complex
|
13
|
+
# decisions:
|
14
|
+
#
|
15
|
+
# use Rack::Session::Pool
|
16
|
+
# use OpenIDFilter, :allow => ['/foo'] do |url|
|
17
|
+
# bar(url) # some method returning true or false
|
18
|
+
# end
|
19
|
+
#
|
11
20
|
# Responds to the following URIs:
|
12
21
|
# /login
|
13
22
|
# /logout
|
@@ -4,7 +4,7 @@ module Rack #:nodoc:
|
|
4
4
|
|
5
5
|
# Extends Rack::Builder's to_app method to detect if the last piece of
|
6
6
|
# middleware in the stack is a CloudKit shortcut (contain or expose), adding
|
7
|
-
#
|
7
|
+
# a default developer page at the root and a 404 everywhere else.
|
8
8
|
def to_app
|
9
9
|
default_app = lambda do |env|
|
10
10
|
if (env['PATH_INFO'] == '/')
|
data/lib/cloudkit/request.rb
CHANGED
data/lib/cloudkit/service.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module CloudKit
|
2
2
|
|
3
3
|
# A CloudKit Service is Rack middleware providing a REST/HTTP 1.1 interface to
|
4
|
-
# a Store. Its primary purpose is initialize and adapt a Store for use in a
|
4
|
+
# a Store. Its primary purpose is to initialize and adapt a Store for use in a
|
5
5
|
# Rack middleware stack.
|
6
6
|
#
|
7
7
|
# ==Examples
|
@@ -68,18 +68,22 @@ module CloudKit
|
|
68
68
|
if tunnel_methods.include?(request['_method'].try(:upcase))
|
69
69
|
return send(request['_method'].downcase, request)
|
70
70
|
end
|
71
|
-
@store.post(
|
71
|
+
response = @store.post(
|
72
72
|
request.uri,
|
73
73
|
{:json => request.json}.filter_merge!(
|
74
|
-
:remote_user => request.current_user))
|
74
|
+
:remote_user => request.current_user))
|
75
|
+
update_location_header(request, response)
|
76
|
+
response.to_rack
|
75
77
|
end
|
76
78
|
|
77
79
|
def put(request)
|
78
|
-
@store.put(
|
80
|
+
response = @store.put(
|
79
81
|
request.uri,
|
80
82
|
{:json => request.json}.filter_merge!(
|
81
83
|
:remote_user => request.current_user,
|
82
|
-
:etag => request.if_match))
|
84
|
+
:etag => request.if_match))
|
85
|
+
update_location_header(request, response)
|
86
|
+
response.to_rack
|
83
87
|
end
|
84
88
|
|
85
89
|
def delete(request)
|
@@ -114,21 +118,26 @@ module CloudKit
|
|
114
118
|
end
|
115
119
|
|
116
120
|
def versions_link_header(request)
|
117
|
-
base_url = "#{request.
|
121
|
+
base_url = "#{request.domain_root}#{request.path_info}"
|
118
122
|
"<#{base_url}/versions>; rel=\"http://joncrosby.me/cloudkit/1.0/rel/versions\""
|
119
123
|
end
|
120
124
|
|
121
125
|
def resolved_link_header(request)
|
122
|
-
base_url = "#{request.
|
126
|
+
base_url = "#{request.domain_root}#{request.path_info}"
|
123
127
|
"<#{base_url}/_resolved>; rel=\"http://joncrosby.me/cloudkit/1.0/rel/resolved\""
|
124
128
|
end
|
125
129
|
|
126
130
|
def index_link_header(request)
|
127
131
|
index_path = request.path_info.sub(/\/_resolved(\/)*$/, '')
|
128
|
-
base_url = "#{request.
|
132
|
+
base_url = "#{request.domain_root}#{index_path}"
|
129
133
|
"<#{base_url}>; rel=\"index\""
|
130
134
|
end
|
131
135
|
|
136
|
+
def update_location_header(request, response)
|
137
|
+
return unless response['Location']
|
138
|
+
response['Location'] = "#{request.domain_root}#{response['Location']}"
|
139
|
+
end
|
140
|
+
|
132
141
|
def auth_missing?(request)
|
133
142
|
request.current_user == nil
|
134
143
|
end
|
data/lib/cloudkit/store.rb
CHANGED
@@ -117,7 +117,8 @@ module CloudKit
|
|
117
117
|
return status_412 if resource.etag != options[:etag]
|
118
118
|
|
119
119
|
resource.delete
|
120
|
-
|
120
|
+
archived_resource = resource.previous_version
|
121
|
+
return json_meta_response(archived_resource.uri.string, archived_resource.etag, resource.last_modified)
|
121
122
|
end
|
122
123
|
|
123
124
|
# Build a response containing the allowed methods for a given URI.
|
@@ -276,7 +277,7 @@ module CloudKit
|
|
276
277
|
def create_resource(uri, options)
|
277
278
|
JSON.parse(options[:json]) rescue (return status_422)
|
278
279
|
resource = CloudKit::Resource.create(uri, options[:json], options[:remote_user])
|
279
|
-
|
280
|
+
json_create_response(resource.uri.string, resource.etag, resource.last_modified)
|
280
281
|
end
|
281
282
|
|
282
283
|
# Update the resource at the specified URI. Requires the :etag option.
|
@@ -288,7 +289,7 @@ module CloudKit
|
|
288
289
|
return etag_required unless options[:etag]
|
289
290
|
return status_412 unless options[:etag] == resource.etag
|
290
291
|
resource.update(options[:json])
|
291
|
-
return json_meta_response(
|
292
|
+
return json_meta_response(uri.string, resource.etag, resource.last_modified)
|
292
293
|
end
|
293
294
|
|
294
295
|
# Bundle a collection of results as a list of URIs for the response.
|
@@ -337,7 +338,7 @@ module CloudKit
|
|
337
338
|
# optimization for GETs. This method is used for collections of resources
|
338
339
|
# where the optimization is not practical.
|
339
340
|
def build_etag(data)
|
340
|
-
MD5
|
341
|
+
Digest::MD5.hexdigest(data.to_s)
|
341
342
|
end
|
342
343
|
|
343
344
|
# Returns true if the collection type is valid for this Store.
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module CloudKit
|
2
2
|
|
3
3
|
# A CloudKit::Resource represents a "resource" in the REST/HTTP sense of the
|
4
|
-
# word. It encapsulates a JSON document and its metadata such as
|
5
|
-
# Last-Modified date, remote user, and
|
4
|
+
# word. It encapsulates a JSON document and its metadata such as its URI, ETag,
|
5
|
+
# Last-Modified date, remote user, and historical versions.
|
6
6
|
class Resource
|
7
7
|
|
8
8
|
attr_reader :uri, :etag, :last_modified, :json, :remote_user
|
@@ -60,7 +60,7 @@ module CloudKit
|
|
60
60
|
end
|
61
61
|
|
62
62
|
# Delete the given resource. This is a soft delete, archiving the previous
|
63
|
-
# resource and
|
63
|
+
# resource and inserting a deleted resource placeholder at the old URI.
|
64
64
|
# Raises HistoricalIntegrityViolation for attempts to delete resources that
|
65
65
|
# are not current.
|
66
66
|
def delete
|
@@ -46,21 +46,32 @@ module CloudKit::ResponseHelpers
|
|
46
46
|
|
47
47
|
def response(status, content='', etag=nil, last_modified=nil, options={})
|
48
48
|
cache_control = options[:cache] == false ? 'no-cache' : 'proxy-revalidate'
|
49
|
-
|
49
|
+
etag = "\"#{etag}\"" if etag
|
50
|
+
headers = {}.filter_merge!(
|
50
51
|
'Content-Type' => 'application/json',
|
51
|
-
'Cache-Control' => cache_control
|
52
|
-
|
53
|
-
|
52
|
+
'Cache-Control' => cache_control,
|
53
|
+
'Last-Modified' => last_modified,
|
54
|
+
'Location' => options[:location],
|
55
|
+
'ETag' => etag)
|
54
56
|
CloudKit::Response.new(status, headers, content)
|
55
57
|
end
|
56
58
|
|
57
|
-
def json_meta_response(
|
58
|
-
json =
|
59
|
+
def json_meta_response(uri, etag, last_modified)
|
60
|
+
json = json_metadata(uri, etag, last_modified)
|
61
|
+
response(200, json, nil, nil, :cache => false)
|
62
|
+
end
|
63
|
+
|
64
|
+
def json_create_response(uri, etag, last_modified)
|
65
|
+
json = json_metadata(uri, etag, last_modified)
|
66
|
+
response(201, json, nil, nil, {:cache => false, :location => uri})
|
67
|
+
end
|
68
|
+
|
69
|
+
def json_metadata(uri, etag, last_modified)
|
70
|
+
JSON.generate(
|
59
71
|
:ok => true,
|
60
72
|
:uri => uri,
|
61
73
|
:etag => etag,
|
62
74
|
:last_modified => last_modified)
|
63
|
-
response(status, json, nil, nil, :cache => false)
|
64
75
|
end
|
65
76
|
|
66
77
|
def json_error(message)
|
data/lib/cloudkit/uri.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module CloudKit
|
2
2
|
|
3
|
-
# A CloudKit::URI wraps a URI string,
|
3
|
+
# A CloudKit::URI wraps a URI string, adding methods useful for routing
|
4
4
|
# in CloudKit as well as caching URI components for future comparisons.
|
5
5
|
class URI
|
6
6
|
|
@@ -42,7 +42,7 @@ module CloudKit
|
|
42
42
|
|
43
43
|
# Returns true if URI matches /{collection}
|
44
44
|
def resource_collection_uri?
|
45
|
-
return components.size == 1
|
45
|
+
return components.size == 1 && components[0] != 'cloudkit-meta'
|
46
46
|
end
|
47
47
|
|
48
48
|
# Returns true if URI matches /{collection}/_resolved
|
data/spec/flash_session_spec.rb
CHANGED
data/spec/openid_filter_spec.rb
CHANGED
@@ -34,6 +34,8 @@ describe "An OpenIDFilter" do
|
|
34
34
|
request = Rack::MockRequest.new(openid_app)
|
35
35
|
response = request.get('/bar')
|
36
36
|
response.status.should == 200
|
37
|
+
response = request.get('/foo')
|
38
|
+
response.status.should == 200
|
37
39
|
end
|
38
40
|
|
39
41
|
it "should redirect to the login page if authorization is required" do
|
data/spec/request_spec.rb
CHANGED
@@ -182,4 +182,10 @@ describe "A Request" do
|
|
182
182
|
request.last_path_element.should == 'def'
|
183
183
|
end
|
184
184
|
|
185
|
+
it "should know its domain root" do
|
186
|
+
request = CloudKit::Request.new(Rack::MockRequest.env_for(
|
187
|
+
'/', 'HTTP_HOST' => 'example.com'))
|
188
|
+
request.domain_root.should == "http://example.com"
|
189
|
+
end
|
190
|
+
|
185
191
|
end
|
data/spec/service_spec.rb
CHANGED
@@ -570,7 +570,7 @@ describe "A CloudKit::Service" do
|
|
570
570
|
before(:each) do
|
571
571
|
json = JSON.generate(:this => 'that')
|
572
572
|
@response = @request.post(
|
573
|
-
'/items', {:input => json}.merge(VALID_TEST_AUTH))
|
573
|
+
'/items', {:input => json, 'HTTP_HOST' => 'example.org'}.merge(VALID_TEST_AUTH))
|
574
574
|
@body = JSON.parse(@response.body)
|
575
575
|
end
|
576
576
|
|
@@ -600,6 +600,10 @@ describe "A CloudKit::Service" do
|
|
600
600
|
@response['Last-Modified'].should be_nil
|
601
601
|
end
|
602
602
|
|
603
|
+
it "should return a Location header" do
|
604
|
+
@response['Location'].should match(/http:\/\/example.org#{@body['uri']}/)
|
605
|
+
end
|
606
|
+
|
603
607
|
it "should return a 422 if parsing fails" do
|
604
608
|
response = @request.post('/items', {:input => 'fail'}.merge(VALID_TEST_AUTH))
|
605
609
|
response.status.should == 422
|
@@ -607,7 +611,7 @@ describe "A CloudKit::Service" do
|
|
607
611
|
|
608
612
|
end
|
609
613
|
|
610
|
-
describe "on PUT /:collection/:id" do
|
614
|
+
describe "on PUT /:collection/:id" do
|
611
615
|
|
612
616
|
before(:each) do
|
613
617
|
json = JSON.generate(:this => 'that')
|
@@ -626,11 +630,15 @@ describe "A CloudKit::Service" do
|
|
626
630
|
it "should create a document if it does not already exist" do
|
627
631
|
json = JSON.generate(:this => 'thing')
|
628
632
|
response = @request.put(
|
629
|
-
'/items/xyz', {
|
633
|
+
'/items/xyz', {
|
634
|
+
:input => json,
|
635
|
+
'HTTP_HOST' => 'example.org'}.merge(VALID_TEST_AUTH))
|
630
636
|
response.status.should == 201
|
631
637
|
result = @request.get('/items/xyz', VALID_TEST_AUTH)
|
632
638
|
result.status.should == 200
|
633
|
-
JSON.parse(result.body)['this']
|
639
|
+
parsed_json = JSON.parse(result.body)['this']
|
640
|
+
parsed_json.should == 'thing'
|
641
|
+
response['Location'].should match(/http:\/\/example.org#{parsed_json['uri']}/)
|
634
642
|
end
|
635
643
|
|
636
644
|
it "should not create new resources using deleted resource URIs" do
|
@@ -782,6 +790,24 @@ describe "A CloudKit::Service" do
|
|
782
790
|
json.keys.sort.should == ['etag', 'last_modified', 'ok', 'uri']
|
783
791
|
end
|
784
792
|
|
793
|
+
it "should use the archived URI in the JSON result" do
|
794
|
+
response = @request.delete(
|
795
|
+
'/items/abc',
|
796
|
+
'HTTP_IF_MATCH' => @etag,
|
797
|
+
CLOUDKIT_AUTH_KEY => TEST_REMOTE_USER)
|
798
|
+
json = JSON.parse(response.body)
|
799
|
+
json['uri'].should match(/\/items\/abc\/versions\/.+/)
|
800
|
+
end
|
801
|
+
|
802
|
+
it "should not change the ETag for the archived version" do
|
803
|
+
response = @request.delete(
|
804
|
+
'/items/abc',
|
805
|
+
'HTTP_IF_MATCH' => @etag,
|
806
|
+
CLOUDKIT_AUTH_KEY => TEST_REMOTE_USER)
|
807
|
+
json = JSON.parse(response.body)
|
808
|
+
json['etag'].should == @etag
|
809
|
+
end
|
810
|
+
|
785
811
|
it "should set the Content-Type header" do
|
786
812
|
response = @request.delete(
|
787
813
|
'/items/abc',
|
data/spec/uri_spec.rb
CHANGED
@@ -36,7 +36,7 @@ describe "A URI" do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should know if it is a resource collection URI" do
|
39
|
-
['/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
39
|
+
['/cloudkit-meta', '/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
40
40
|
CloudKit::URI.new(uri).should_not be_resource_collection_uri
|
41
41
|
}
|
42
42
|
CloudKit::URI.new('/items').should be_resource_collection_uri
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Crosby
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-03
|
12
|
+
date: 2008-05-03 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -18,9 +18,9 @@ dependencies:
|
|
18
18
|
version_requirement:
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
|
-
- -
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: "0
|
23
|
+
version: "1.0"
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: uuid
|
@@ -48,9 +48,9 @@ dependencies:
|
|
48
48
|
version_requirement:
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 2.1
|
53
|
+
version: "2.1"
|
54
54
|
version:
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: json
|
@@ -58,9 +58,9 @@ dependencies:
|
|
58
58
|
version_requirement:
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- -
|
61
|
+
- - ~>
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 1.1
|
63
|
+
version: "1.1"
|
64
64
|
version:
|
65
65
|
description: An Open Web JSON Appliance.
|
66
66
|
email: jon@joncrosby.me
|