hyperdrive 0.0.3 → 0.0.4
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 +4 -4
- data/.coveralls.yml +1 -0
- data/.gitignore +3 -0
- data/Gemfile +2 -1
- data/README.md +75 -2
- data/bin/console +14 -0
- data/bin/hyperdrive +42 -0
- data/hyperdrive.gemspec +6 -5
- data/lib/hyperdrive/docs.rb +76 -0
- data/lib/hyperdrive/dsl/main.rb +19 -0
- data/lib/hyperdrive/dsl/resource.rb +42 -0
- data/lib/hyperdrive/dsl.rb +9 -0
- data/lib/hyperdrive/errors/bad_request.rb +13 -0
- data/lib/hyperdrive/errors/dsl/unknown_argument.rb +21 -0
- data/lib/hyperdrive/errors/http_error.rb +11 -0
- data/lib/hyperdrive/errors/internal_server_error.rb +13 -0
- data/lib/hyperdrive/errors/method_not_allowed.rb +17 -0
- data/lib/hyperdrive/errors/not_found.rb +13 -0
- data/lib/hyperdrive/errors/not_implemented.rb +17 -0
- data/lib/hyperdrive/errors/unauthorized.rb +13 -0
- data/lib/hyperdrive/errors.rb +10 -0
- data/lib/hyperdrive/resource.rb +29 -3
- data/lib/hyperdrive/response.rb +41 -0
- data/lib/hyperdrive/server.rb +30 -0
- data/lib/hyperdrive/values.rb +31 -0
- data/lib/hyperdrive/version.rb +1 -1
- data/lib/hyperdrive.rb +12 -4
- data/spec/hyperdrive/docs_spec.rb +56 -0
- data/spec/hyperdrive/dsl/main_spec.rb +16 -0
- data/spec/hyperdrive/dsl/resource_spec.rb +58 -0
- data/spec/hyperdrive/resource_spec.rb +29 -5
- data/spec/hyperdrive/response_spec.rb +23 -0
- data/spec/hyperdrive/server_spec.rb +11 -0
- data/spec/spec_helper.rb +21 -2
- metadata +77 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 04f0142457c2c2727dc798316907630f2d53c828
|
|
4
|
+
data.tar.gz: b1742f5f51b354d1ada859f1b04603e1703396b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 165eb035a20d31e3c33c29e82dc71cd856661aa91d58f0b542e5e90bfe700f185dd1262ea6714e203cbc5db1f047b0d5f80e929ac8da491bbca6fb7fa74dd7eb
|
|
7
|
+
data.tar.gz: f2b83b37947c9b2bd3ed27c6c7db5b5deb15729714b324c68a6c28dc0520ddb13b28f5ac3f40ae9d1a98e117705b15a1aefa344b72c1fec360d856a5c279bc2d
|
data/.coveralls.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
|
@@ -3,6 +3,7 @@ gemspec
|
|
|
3
3
|
|
|
4
4
|
group :development do
|
|
5
5
|
gem 'gem-release', require: false
|
|
6
|
+
gem 'pry', require: false
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
group :test, :rake do
|
|
@@ -17,5 +18,5 @@ group :test do
|
|
|
17
18
|
gem 'minitest', require: false
|
|
18
19
|
gem 'minitest-spec-context', require: false
|
|
19
20
|
gem 'minitest-reporters', require: false
|
|
20
|
-
|
|
21
|
+
gem 'rack-test', require: false
|
|
21
22
|
end
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Hyperdrive
|
|
2
2
|
|
|
3
|
-
Ruby DSL for defining self-documenting,
|
|
3
|
+
Ruby DSL for defining self-documenting, HATEOAS™ complaint, Hypermedia endpoints.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -21,6 +21,7 @@ Or install it yourself as:
|
|
|
21
21
|
Proposed Syntax (WIP):
|
|
22
22
|
|
|
23
23
|
```ruby
|
|
24
|
+
# api.rb
|
|
24
25
|
hyperdrive do
|
|
25
26
|
resource(:thing) do
|
|
26
27
|
name 'Thing Resource'
|
|
@@ -40,13 +41,85 @@ hyperdrive do
|
|
|
40
41
|
# applied). Unlike allowed params, filters are not required by default.
|
|
41
42
|
filter :start_date, 'Format: YYYY-MM-DD'
|
|
42
43
|
filter :end_date, 'Format: YYYY-MM-DD'
|
|
43
|
-
filter :parent_id, 'Parent ID of Thing
|
|
44
|
+
filter :parent_id, 'Parent ID of Thing', required: true
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Handle API Requests
|
|
48
|
+
#
|
|
49
|
+
# - Simply return a string to be used as the body of the response. How you generate
|
|
50
|
+
# that string is completely up to you.
|
|
51
|
+
# - Status Codes and Headers will be handled automatically.
|
|
52
|
+
# - Any unhandled requests will return a 405 "Method Not Supported" error
|
|
53
|
+
|
|
54
|
+
request(:get) do
|
|
55
|
+
# retrieve 1-N objects...
|
|
56
|
+
'{ ... }'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Options and Head requests will be handled automatically and
|
|
60
|
+
# will use info from the GET request block you define, as needed.
|
|
61
|
+
|
|
62
|
+
# POST Requests should return the full object that was created during the request.
|
|
63
|
+
request(:post) do
|
|
64
|
+
# create the object...
|
|
65
|
+
'{ ... }'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# PUT Requests should return the full object that was updated during the request.
|
|
69
|
+
request(:put) do
|
|
70
|
+
# 'upsert' the object...
|
|
71
|
+
'{ ... }'
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# PATCH requests should return the full object that was updated during the request.
|
|
75
|
+
request(:patch) do
|
|
76
|
+
# update the object...
|
|
77
|
+
'{ ... }'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# DELETE requests should return a simple response indicating success.
|
|
81
|
+
request(:delete) do
|
|
82
|
+
# delete the object...
|
|
83
|
+
'{"deleted":true}'
|
|
84
|
+
end
|
|
44
85
|
end
|
|
45
86
|
end
|
|
87
|
+
|
|
88
|
+
# config.ru
|
|
89
|
+
run Hyperdrive::Server
|
|
46
90
|
```
|
|
47
91
|
|
|
92
|
+
## CLI
|
|
93
|
+
|
|
94
|
+
### Generating Documentation
|
|
95
|
+
|
|
96
|
+
`$ hyperdrive docs <option> <parameter>`
|
|
97
|
+
|
|
98
|
+
__`--input` Option__
|
|
99
|
+
|
|
100
|
+
Use the `--input` option and specify a file or directory as a parameter to generate documentation for your API resources.
|
|
101
|
+
|
|
102
|
+
- `$ hyperdrive docs --input api.rb`
|
|
103
|
+
|
|
104
|
+
or
|
|
105
|
+
|
|
106
|
+
- `$ hyperdrive docs --input api`
|
|
107
|
+
|
|
108
|
+
`-in` can be used as an alias for `--input`
|
|
109
|
+
|
|
110
|
+
__`--output` Option__
|
|
111
|
+
|
|
112
|
+
You can also provide a `--output` option and specify a destination for your documentation to be created.
|
|
113
|
+
|
|
114
|
+
- `$ hyperdrive docs --input api.rb --output docs/docs.md`
|
|
115
|
+
|
|
116
|
+
`-out` can be used as an alias for `--output`
|
|
117
|
+
|
|
118
|
+
If the `--output` option is not provided the generated documentation will be written to `docs/doc.md` by default.
|
|
119
|
+
|
|
48
120
|
## Project Status
|
|
49
121
|
|
|
122
|
+
- Version: [](http://badge.fury.io/rb/hyperdrive)
|
|
50
123
|
- Build: [](https://travis-ci.org/styleseek/hyperdrive)
|
|
51
124
|
- Code Quality: [](https://codeclimate.com/github/styleseek/hyperdrive)
|
|
52
125
|
- Dependencies: [](https://gemnasium.com/styleseek/hyperdrive)
|
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
ENV['RACK_ENV'] ||= 'development'
|
|
3
|
+
# load path
|
|
4
|
+
lib_path = File.expand_path('../../lib', __FILE__)
|
|
5
|
+
($:.unshift lib_path) unless ($:.include? lib_path)
|
|
6
|
+
|
|
7
|
+
# require farm
|
|
8
|
+
require 'bundler'
|
|
9
|
+
Bundler.require(:default, ENV['RACK_ENV'])
|
|
10
|
+
require 'pry'
|
|
11
|
+
require 'hyperdrive'
|
|
12
|
+
|
|
13
|
+
# fire up the ftl drive
|
|
14
|
+
Pry.start
|
data/bin/hyperdrive
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
ENV['RACK_ENV'] ||= 'development'
|
|
3
|
+
# load path
|
|
4
|
+
lib_path = File.expand_path('../../lib', __FILE__)
|
|
5
|
+
($:.unshift lib_path) unless ($:.include? lib_path)
|
|
6
|
+
|
|
7
|
+
require 'thor'
|
|
8
|
+
require 'hyperdrive'
|
|
9
|
+
|
|
10
|
+
module Hyperdrive
|
|
11
|
+
class CLI < Thor
|
|
12
|
+
include Thor::Actions
|
|
13
|
+
|
|
14
|
+
desc "docs", "Generate docs in markdown based on your resources."
|
|
15
|
+
method_option :input, aliases: "\--in", desc: "Specify the directory or file to generate docs for."
|
|
16
|
+
method_option :output, aliases: "\--out", desc: "Specify the destination of the docs.", default: "docs/api.md"
|
|
17
|
+
def docs
|
|
18
|
+
input = File.expand_path(options[:input])
|
|
19
|
+
|
|
20
|
+
if File.file?(input)
|
|
21
|
+
require input
|
|
22
|
+
elsif File.directory?(input)
|
|
23
|
+
Dir.glob("#{input}/*.rb").each do |file|
|
|
24
|
+
require file
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
raise ArgumentError, "Input is neither a file nor a directory"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if hyperdrive.resources.empty?
|
|
31
|
+
say "This API doesn't have any resources to document", :red
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
data = Hyperdrive::Docs.new(hyperdrive.resources).output
|
|
36
|
+
create_file(options[:output], data)
|
|
37
|
+
say "Done!"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Hyperdrive::CLI.start
|
data/hyperdrive.gemspec
CHANGED
|
@@ -9,15 +9,16 @@ Gem::Specification.new do |gem|
|
|
|
9
9
|
gem.authors = ['StyleSeek Engineering']
|
|
10
10
|
gem.email = ['engineering@styleseek.com']
|
|
11
11
|
gem.summary = %q{Hypermedia State Machine}
|
|
12
|
-
gem.description = %q{Ruby DSL for defining self-documenting,
|
|
12
|
+
gem.description = %q{Ruby DSL for defining self-documenting, HATEOAS™ complaint, Hypermedia API endpoints.}
|
|
13
13
|
gem.homepage = "https://github.com/styleseek/hyperdrive"
|
|
14
14
|
gem.license = "MIT"
|
|
15
15
|
|
|
16
16
|
gem.files = `git ls-files -z`.split("\x0")
|
|
17
|
-
gem.executables =
|
|
17
|
+
gem.executables = ['hyperdrive']
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
gem.require_paths = ["lib"]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
gem.add_dependency 'rack'
|
|
22
|
+
gem.add_dependency 'linguistics'
|
|
23
|
+
gem.add_dependency 'thor'
|
|
23
24
|
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Hyperdrive
|
|
4
|
+
class Docs
|
|
5
|
+
attr_reader :resources
|
|
6
|
+
|
|
7
|
+
def initialize(resources)
|
|
8
|
+
@resources = resources
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def output
|
|
12
|
+
out = ""
|
|
13
|
+
resources.each_value do |resource|
|
|
14
|
+
out += header(resource.name)
|
|
15
|
+
out += paragraph(resource.desc)
|
|
16
|
+
out += header("Endpoint URL", 2)
|
|
17
|
+
out += paragraph(bullet(code(resource.endpoint), 1))
|
|
18
|
+
out += header("Params", 2)
|
|
19
|
+
out += list(resource.allowed_params)
|
|
20
|
+
out += header("Filters", 2)
|
|
21
|
+
out += list(resource.filters)
|
|
22
|
+
end
|
|
23
|
+
out
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def header(string, level = 1)
|
|
27
|
+
raise ArgumentError, "Header level must be between 1 and 6." unless (1..6).cover?(level)
|
|
28
|
+
header = "#" * level
|
|
29
|
+
"\n\n#{header} #{string}\n\n"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def paragraph(string)
|
|
33
|
+
"#{string}\n\n"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def bold(string)
|
|
37
|
+
"__#{string}__"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def italics(string)
|
|
41
|
+
"_#{string}_"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def code(string)
|
|
45
|
+
"`#{string}`"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def bullet(string, nest = 1)
|
|
49
|
+
raise ArgumentError, "Nest level must be between 1 and 3." unless (1..3).cover?(nest)
|
|
50
|
+
nest = " " * nest
|
|
51
|
+
"#{nest}- #{string}\n"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def list(items)
|
|
55
|
+
list = ""
|
|
56
|
+
items.each do |key, value|
|
|
57
|
+
list += bullet(bold(key), 1)
|
|
58
|
+
|
|
59
|
+
value.each do |subkey, subvalue|
|
|
60
|
+
list += bullet(italics(subkey), 2)
|
|
61
|
+
|
|
62
|
+
if subvalue.kind_of? Array
|
|
63
|
+
list += bullet(code_options(subvalue), 3)
|
|
64
|
+
else
|
|
65
|
+
list += bullet(subvalue, 3)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
list
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def code_options(options)
|
|
73
|
+
options.map { |option| code(option) }.join(", ")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'singleton'
|
|
3
|
+
|
|
4
|
+
module Hyperdrive
|
|
5
|
+
module DSL
|
|
6
|
+
class Main
|
|
7
|
+
include Singleton
|
|
8
|
+
attr_reader :resources
|
|
9
|
+
|
|
10
|
+
def initialize(&block)
|
|
11
|
+
@resources = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def resource(name, &block)
|
|
15
|
+
@resources[name] = Resource.new(name, &block).resource
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Hyperdrive
|
|
4
|
+
module DSL
|
|
5
|
+
class Resource
|
|
6
|
+
attr_reader :resource
|
|
7
|
+
def initialize(key, &block)
|
|
8
|
+
@resource = ::Hyperdrive::Resource.new(key)
|
|
9
|
+
instance_eval(&block) if block_given?
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def name(name)
|
|
13
|
+
resource.name = name
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def desc(description)
|
|
17
|
+
resource.desc = description
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def param(*args)
|
|
21
|
+
resource.register_param(*args)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def filter(*args)
|
|
25
|
+
resource.register_filter(*args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def request(method, &block)
|
|
29
|
+
unless definable_request_methods.include? method
|
|
30
|
+
raise Errors::DSL::UnknownArgument.new(method, 'request')
|
|
31
|
+
end
|
|
32
|
+
resource.define_request_handler(method, block)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def definable_request_methods
|
|
38
|
+
[:get, :post, :put, :patch, :delete].freeze
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Hyperdrive
|
|
2
|
+
module Errors
|
|
3
|
+
module DSL
|
|
4
|
+
class UnknownArgument < RuntimeError
|
|
5
|
+
def initialize(argument, method_name)
|
|
6
|
+
@argument = case argument
|
|
7
|
+
when Symbol
|
|
8
|
+
":#{argument}"
|
|
9
|
+
else
|
|
10
|
+
argument.to_s
|
|
11
|
+
end
|
|
12
|
+
@method_name = method_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def message
|
|
16
|
+
"#{@argument} is not supported by `#{@method_name}'."
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Hyperdrive
|
|
2
|
+
module Errors
|
|
3
|
+
class MethodNotAllowed < HTTPError
|
|
4
|
+
def initialize(request_method)
|
|
5
|
+
@request_method = request_method
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def message
|
|
9
|
+
"A request was made using a request method (#{@request_method}) not supported by this resource."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def http_status_code
|
|
13
|
+
405
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Hyperdrive
|
|
2
|
+
module Errors
|
|
3
|
+
class NotImplemented < HTTPError
|
|
4
|
+
def initialize(request_method)
|
|
5
|
+
@request_method = request_method
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def message
|
|
9
|
+
"The server either does not recognise the request method (#{@request_method}), or it lacks the ability to fulfill the request."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def http_status_code
|
|
13
|
+
501
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'hyperdrive/errors/http_error'
|
|
4
|
+
require 'hyperdrive/errors/bad_request'
|
|
5
|
+
require 'hyperdrive/errors/internal_server_error'
|
|
6
|
+
require 'hyperdrive/errors/method_not_allowed'
|
|
7
|
+
require 'hyperdrive/errors/not_found'
|
|
8
|
+
require 'hyperdrive/errors/not_implemented'
|
|
9
|
+
require 'hyperdrive/errors/unauthorized'
|
|
10
|
+
require 'hyperdrive/errors/dsl/unknown_argument'
|
data/lib/hyperdrive/resource.rb
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module Hyperdrive
|
|
4
4
|
class Resource
|
|
5
|
-
attr_reader :
|
|
5
|
+
attr_reader :endpoint, :allowed_params, :filters, :request_handlers
|
|
6
6
|
attr_accessor :name, :desc
|
|
7
7
|
|
|
8
|
-
def initialize(
|
|
9
|
-
@
|
|
8
|
+
def initialize(key)
|
|
9
|
+
@key = key
|
|
10
|
+
@endpoint = "/#{@key.to_s.en.plural}"
|
|
10
11
|
@allowed_params = default_allowed_params
|
|
11
12
|
@filters = default_filters
|
|
13
|
+
@request_handlers = default_request_handlers
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def register_param(key, description, options = {})
|
|
@@ -21,6 +23,26 @@ module Hyperdrive
|
|
|
21
23
|
@filters[key] = { desc: description }.merge(options)
|
|
22
24
|
end
|
|
23
25
|
|
|
26
|
+
def define_request_handler(request_method, block)
|
|
27
|
+
@request_handlers[request_method] = block
|
|
28
|
+
if request_method == :get
|
|
29
|
+
@request_handlers[:head] = block
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def request_handler(http_request_method)
|
|
34
|
+
request_method = Hyperdrive::Values.request_methods_string_map[http_request_method]
|
|
35
|
+
request_handlers[request_method]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def request_method_allowed?(http_request_method)
|
|
39
|
+
allowed_methods.include?(http_request_method)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def allowed_methods
|
|
43
|
+
Hyperdrive::Values.request_methods_symbol_map.values_at(*request_handlers.keys)
|
|
44
|
+
end
|
|
45
|
+
|
|
24
46
|
private
|
|
25
47
|
|
|
26
48
|
def default_allowed_params
|
|
@@ -42,5 +64,9 @@ module Hyperdrive
|
|
|
42
64
|
def default_filter_options
|
|
43
65
|
{ required: false }.freeze
|
|
44
66
|
end
|
|
67
|
+
|
|
68
|
+
def default_request_handlers
|
|
69
|
+
{ options: proc { '' } }
|
|
70
|
+
end
|
|
45
71
|
end
|
|
46
72
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Hyperdrive
|
|
4
|
+
class Response
|
|
5
|
+
attr_reader :resource, :env, :http_request_method, :headers
|
|
6
|
+
|
|
7
|
+
def initialize(env, resource)
|
|
8
|
+
@resource = resource
|
|
9
|
+
@env = env
|
|
10
|
+
@http_request_method = env['REQUEST_METHOD']
|
|
11
|
+
|
|
12
|
+
unless request_method_supported?
|
|
13
|
+
raise Errors::NotImplemented.new(http_request_method)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
unless resource.request_method_allowed?(http_request_method)
|
|
17
|
+
raise Errors::MethodNotAllowed.new(http_request_method)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@headers = default_headers
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def response
|
|
24
|
+
@headers.merge({ 'Content-Type' => 'text/plain' })
|
|
25
|
+
status = (http_request_method == 'POST') ? 201 : 200
|
|
26
|
+
::Rack::Response.new(resource.request_handler(http_request_method).call(env), status, headers).finish
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def default_headers
|
|
32
|
+
{
|
|
33
|
+
'Allow' => resource.allowed_methods
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def request_method_supported?
|
|
38
|
+
Hyperdrive::Values.request_methods_string_map.key?(http_request_method)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Hyperdrive
|
|
4
|
+
class Server
|
|
5
|
+
def self.call(env)
|
|
6
|
+
server.call(env)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def self.server
|
|
12
|
+
Rack::Builder.new do
|
|
13
|
+
hyperdrive.resources.each do |key, resource|
|
|
14
|
+
map resource.endpoint do
|
|
15
|
+
use Rack::Runtime
|
|
16
|
+
use Rack::Lint
|
|
17
|
+
use Rack::Head
|
|
18
|
+
run ->(env) {
|
|
19
|
+
begin
|
|
20
|
+
Hyperdrive::Response.new(env, resource).response
|
|
21
|
+
rescue Hyperdrive::Errors::HTTPError => error
|
|
22
|
+
[error.http_status_code, { 'Allow' => resource.allowed_methods.join(',') }, [error.message]]
|
|
23
|
+
end
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end.to_app
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Hyperdrive
|
|
2
|
+
module Values
|
|
3
|
+
def self.request_methods
|
|
4
|
+
%w(GET HEAD OPTIONS POST PUT PATCH DELETE).freeze
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.request_methods_symbol_map
|
|
8
|
+
{
|
|
9
|
+
get: 'GET',
|
|
10
|
+
head: 'HEAD',
|
|
11
|
+
options: 'OPTIONS',
|
|
12
|
+
post: 'POST',
|
|
13
|
+
put: 'PUT',
|
|
14
|
+
patch: 'PATCH',
|
|
15
|
+
delete: 'DELETE'
|
|
16
|
+
}.freeze
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.request_methods_string_map
|
|
20
|
+
{
|
|
21
|
+
'GET' => :get,
|
|
22
|
+
'HEAD' => :head,
|
|
23
|
+
'OPTIONS' => :options,
|
|
24
|
+
'POST' => :post,
|
|
25
|
+
'PUT' => :put,
|
|
26
|
+
'PATCH' => :patch,
|
|
27
|
+
'DELETE' => :delete
|
|
28
|
+
}.freeze
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/hyperdrive/version.rb
CHANGED
data/lib/hyperdrive.rb
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
+
# stdlib
|
|
4
|
+
require 'rack'
|
|
5
|
+
require 'linguistics'
|
|
6
|
+
Linguistics.use(:en)
|
|
7
|
+
|
|
8
|
+
# prepare for hyperspace!
|
|
9
|
+
require 'hyperdrive/docs'
|
|
10
|
+
require 'hyperdrive/dsl'
|
|
11
|
+
require 'hyperdrive/errors'
|
|
3
12
|
require 'hyperdrive/resource'
|
|
13
|
+
require 'hyperdrive/response'
|
|
14
|
+
require 'hyperdrive/server'
|
|
15
|
+
require 'hyperdrive/values'
|
|
4
16
|
require 'hyperdrive/version'
|
|
5
|
-
|
|
6
|
-
module Hyperdrive
|
|
7
|
-
# spinning up the FTL drive
|
|
8
|
-
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Hyperdrive::Docs do
|
|
6
|
+
before do
|
|
7
|
+
sample_api
|
|
8
|
+
@docs = Hyperdrive::Docs.new(hyperdrive.resources)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'generates a header with size 1 as default' do
|
|
12
|
+
@docs.header('Thing Resource').must_equal "\n\n# Thing Resource\n\n"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'generates a header only between size 1 and 6' do
|
|
16
|
+
proc {@docs.header('Thing Resource', 0)}.must_raise ArgumentError
|
|
17
|
+
proc {@docs.header('Thing Resource', 8)}.must_raise ArgumentError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'generates a paragraph' do
|
|
21
|
+
@docs.paragraph('Description of Thing Resource').must_equal "Description of Thing Resource\n\n"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'generates bold text' do
|
|
25
|
+
@docs.bold('name').must_equal '__name__'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'generates code formatted text' do
|
|
29
|
+
@docs.code('/things').must_equal '`/things`'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'generates a bullet with nest level of 1 as default' do
|
|
33
|
+
@docs.bullet('test').must_equal " - test\n"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'generates a bullet with nest level between 1 and 3' do
|
|
37
|
+
proc {@docs.bullet('test', 4)}.must_raise ArgumentError
|
|
38
|
+
proc {@docs.bullet('test', 0)}.must_raise ArgumentError
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'generates a nested bulleted list' do
|
|
42
|
+
@docs.bullet('test', 2).must_equal " - test\n"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'generates a nested bullet code span' do
|
|
46
|
+
@docs.bullet('`/things`', 2).must_equal " - `/things`\n"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'generates nested bulleted bold text' do
|
|
50
|
+
@docs.bullet('__id__', 3).must_equal " - __id__\n"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'outputs a string of the completed doc' do
|
|
54
|
+
@docs.output.must_be_kind_of String
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Hyperdrive::DSL::Main do
|
|
6
|
+
it "creates a singleton instance of hyperdrive" do
|
|
7
|
+
hyperdrive do
|
|
8
|
+
end.must_be_instance_of ::Hyperdrive::DSL::Main
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "registers a resource" do
|
|
12
|
+
hyperdrive do
|
|
13
|
+
resource(:thing) {}
|
|
14
|
+
end.resources[:thing].must_be_instance_of ::Hyperdrive::Resource
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Hyperdrive::DSL::Resource do
|
|
6
|
+
|
|
7
|
+
it "sets the name of the endpoint" do
|
|
8
|
+
hyperdrive do
|
|
9
|
+
resource(:thing) do
|
|
10
|
+
name "Thing Resource"
|
|
11
|
+
end
|
|
12
|
+
end.resources[:thing].name.must_equal 'Thing Resource'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "describes the endpoint" do
|
|
16
|
+
hyperdrive do
|
|
17
|
+
resource(:thing) do
|
|
18
|
+
desc "Thing Description"
|
|
19
|
+
end
|
|
20
|
+
end.resources[:thing].desc.must_equal 'Thing Description'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "registers an allowed param on a resource" do
|
|
24
|
+
hyperdrive do
|
|
25
|
+
resource(:thing) do
|
|
26
|
+
param :name, "Thing's Name"
|
|
27
|
+
end
|
|
28
|
+
end.resources[:thing].allowed_params[:name][:desc].must_equal "Thing's Name"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "registers an allowed param on a resource" do
|
|
32
|
+
hyperdrive do
|
|
33
|
+
resource(:thing) do
|
|
34
|
+
filter :parent_id, "Thing's Parent ID"
|
|
35
|
+
end
|
|
36
|
+
end.resources[:thing].filters[:parent_id][:desc].must_equal "Thing's Parent ID"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "defines how requests are handled" do
|
|
40
|
+
hyperdrive do
|
|
41
|
+
resource(:thing) do
|
|
42
|
+
request(:get) do
|
|
43
|
+
'ok'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end.resources[:thing].request_handlers[:get].call.must_equal 'ok'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "raises an exception if request method argument is unknown" do
|
|
50
|
+
proc do
|
|
51
|
+
hyperdrive do
|
|
52
|
+
resource(:thing) do
|
|
53
|
+
request(:verb)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end.must_raise Hyperdrive::Errors::DSL::UnknownArgument
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -5,10 +5,6 @@ describe Hyperdrive::Resource do
|
|
|
5
5
|
@resource = Hyperdrive::Resource.new(:thing)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
it "creates a new resource" do
|
|
9
|
-
@resource.resource.must_equal :thing
|
|
10
|
-
end
|
|
11
|
-
|
|
12
8
|
it "has a name" do
|
|
13
9
|
@resource.name = 'Thing'
|
|
14
10
|
@resource.name.must_equal 'Thing'
|
|
@@ -19,6 +15,10 @@ describe Hyperdrive::Resource do
|
|
|
19
15
|
@resource.desc.must_equal 'Description of Thing Resource'
|
|
20
16
|
end
|
|
21
17
|
|
|
18
|
+
it "has an endpoint" do
|
|
19
|
+
@resource.endpoint.must_equal '/things'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
22
|
it "auto-registers the :id param" do
|
|
23
23
|
@resource.allowed_params[:id][:desc].must_equal 'Resource Identifier'
|
|
24
24
|
@resource.allowed_params[:id][:required].must_equal %w(PUT PATCH DELETE)
|
|
@@ -32,7 +32,7 @@ describe Hyperdrive::Resource do
|
|
|
32
32
|
|
|
33
33
|
it "auto-registers the :id filter" do
|
|
34
34
|
@resource.filters[:id][:desc].must_equal 'Resource Identifier'
|
|
35
|
-
@resource.filters[:id][:required].must_equal false
|
|
35
|
+
@resource.filters[:id][:required].must_equal false
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
it "registers a filter" do
|
|
@@ -40,4 +40,28 @@ describe Hyperdrive::Resource do
|
|
|
40
40
|
@resource.filters[:parent_id][:desc].must_equal 'Parent ID of Thing'
|
|
41
41
|
@resource.filters[:parent_id][:required].must_equal true
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
it "defines a request handler" do
|
|
45
|
+
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
|
46
|
+
@resource.request_handlers[:get].call.must_equal 'ok'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "returns the specified request handler" do
|
|
50
|
+
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
|
51
|
+
@resource.request_handler('GET').call.must_equal 'ok'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "returns true if the request can be handled" do
|
|
55
|
+
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
|
56
|
+
@resource.request_method_allowed?('GET').must_equal true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "returns false if the request can not be handled" do
|
|
60
|
+
@resource.request_method_allowed?('GET').must_equal false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "returns the request methods that can handled" do
|
|
64
|
+
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
|
65
|
+
@resource.allowed_methods.must_equal ['OPTIONS','GET','HEAD']
|
|
66
|
+
end
|
|
43
67
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Hyperdrive::Response do
|
|
6
|
+
before do
|
|
7
|
+
@resource = Hyperdrive::Resource.new(:things)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "throws an error when the request method is unspported by hyperdrive" do
|
|
11
|
+
proc { Hyperdrive::Response.new({ 'REQUEST_METHOD' => 'TRACE' }, @resource) }.must_raise Hyperdrive::Errors::NotImplemented
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "throws an error when the request method is not allowed" do
|
|
15
|
+
proc { Hyperdrive::Response.new({ 'REQUEST_METHOD' => 'GET' }, @resource) }.must_raise Hyperdrive::Errors::MethodNotAllowed
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "responds to requests" do
|
|
19
|
+
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
|
20
|
+
response = Hyperdrive::Response.new({ 'REQUEST_METHOD' => 'GET' }, @resource)
|
|
21
|
+
response.response.must_equal 'ok'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
describe Hyperdrive::Server do
|
|
4
|
+
it "handles GET requests successfully"
|
|
5
|
+
it "handles HEAD requests successfully"
|
|
6
|
+
it "handles OPTIONS requests successfully"
|
|
7
|
+
it "handles POST requests successfully"
|
|
8
|
+
it "handles PUT requests successfully"
|
|
9
|
+
it "handles PATCH requests successfully"
|
|
10
|
+
it "handles DELETE requests successfully"
|
|
11
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
ENV['RACK_ENV'] = 'test'
|
|
5
5
|
lib_path = File.expand_path('../lib', __FILE__)
|
|
6
6
|
($:.unshift lib_path) unless ($:.include? lib_path)
|
|
7
|
+
|
|
8
|
+
# require dependencies
|
|
7
9
|
require 'bundler'
|
|
8
10
|
Bundler.setup(:default, ENV['RACK_ENV'])
|
|
9
11
|
|
|
10
|
-
# test subject
|
|
12
|
+
# our humble test subject
|
|
11
13
|
require 'hyperdrive'
|
|
12
14
|
|
|
13
|
-
# BDD Stack
|
|
15
|
+
# Fire up the BDD Stack
|
|
14
16
|
require 'minitest/autorun'
|
|
15
17
|
require "minitest-spec-context"
|
|
16
18
|
require 'minitest/reporters'
|
|
@@ -18,3 +20,20 @@ require 'minitest/reporters'
|
|
|
18
20
|
# all systems go
|
|
19
21
|
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
|
20
22
|
#include Rack::Test::Methods
|
|
23
|
+
|
|
24
|
+
def sample_api
|
|
25
|
+
hyperdrive do
|
|
26
|
+
resource(:thing) do
|
|
27
|
+
name 'Thing Resource'
|
|
28
|
+
desc 'Description of Thing Resource'
|
|
29
|
+
|
|
30
|
+
param :name, '50 Chars or less'
|
|
31
|
+
param :start_date, 'Format: YYYY-MM-DD', required: false
|
|
32
|
+
param :end_date, 'Format: YYYY-MM-DD', required: false
|
|
33
|
+
|
|
34
|
+
filter :start_date, 'Format: YYYY-MM-DD'
|
|
35
|
+
filter :end_date, 'Format: YYYY-MM-DD'
|
|
36
|
+
filter :parent_id, 'Parent ID of Thing', required: true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
metadata
CHANGED
|
@@ -1,34 +1,101 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hyperdrive
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- StyleSeek Engineering
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-04-
|
|
12
|
-
dependencies:
|
|
13
|
-
|
|
11
|
+
date: 2014-04-22 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rack
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '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'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: linguistics
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: thor
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
description: Ruby DSL for defining self-documenting, HATEOAS™ complaint, Hypermedia
|
|
14
56
|
API endpoints.
|
|
15
57
|
email:
|
|
16
58
|
- engineering@styleseek.com
|
|
17
|
-
executables:
|
|
59
|
+
executables:
|
|
60
|
+
- hyperdrive
|
|
18
61
|
extensions: []
|
|
19
62
|
extra_rdoc_files: []
|
|
20
63
|
files:
|
|
64
|
+
- ".coveralls.yml"
|
|
21
65
|
- ".gitignore"
|
|
22
66
|
- ".travis.yml"
|
|
23
67
|
- Gemfile
|
|
24
68
|
- LICENSE.txt
|
|
25
69
|
- README.md
|
|
26
70
|
- Rakefile
|
|
71
|
+
- bin/console
|
|
72
|
+
- bin/hyperdrive
|
|
27
73
|
- hyperdrive.gemspec
|
|
28
74
|
- lib/hyperdrive.rb
|
|
75
|
+
- lib/hyperdrive/docs.rb
|
|
76
|
+
- lib/hyperdrive/dsl.rb
|
|
77
|
+
- lib/hyperdrive/dsl/main.rb
|
|
78
|
+
- lib/hyperdrive/dsl/resource.rb
|
|
79
|
+
- lib/hyperdrive/errors.rb
|
|
80
|
+
- lib/hyperdrive/errors/bad_request.rb
|
|
81
|
+
- lib/hyperdrive/errors/dsl/unknown_argument.rb
|
|
82
|
+
- lib/hyperdrive/errors/http_error.rb
|
|
83
|
+
- lib/hyperdrive/errors/internal_server_error.rb
|
|
84
|
+
- lib/hyperdrive/errors/method_not_allowed.rb
|
|
85
|
+
- lib/hyperdrive/errors/not_found.rb
|
|
86
|
+
- lib/hyperdrive/errors/not_implemented.rb
|
|
87
|
+
- lib/hyperdrive/errors/unauthorized.rb
|
|
29
88
|
- lib/hyperdrive/resource.rb
|
|
89
|
+
- lib/hyperdrive/response.rb
|
|
90
|
+
- lib/hyperdrive/server.rb
|
|
91
|
+
- lib/hyperdrive/values.rb
|
|
30
92
|
- lib/hyperdrive/version.rb
|
|
93
|
+
- spec/hyperdrive/docs_spec.rb
|
|
94
|
+
- spec/hyperdrive/dsl/main_spec.rb
|
|
95
|
+
- spec/hyperdrive/dsl/resource_spec.rb
|
|
31
96
|
- spec/hyperdrive/resource_spec.rb
|
|
97
|
+
- spec/hyperdrive/response_spec.rb
|
|
98
|
+
- spec/hyperdrive/server_spec.rb
|
|
32
99
|
- spec/spec_helper.rb
|
|
33
100
|
homepage: https://github.com/styleseek/hyperdrive
|
|
34
101
|
licenses:
|
|
@@ -55,5 +122,10 @@ signing_key:
|
|
|
55
122
|
specification_version: 4
|
|
56
123
|
summary: Hypermedia State Machine
|
|
57
124
|
test_files:
|
|
125
|
+
- spec/hyperdrive/docs_spec.rb
|
|
126
|
+
- spec/hyperdrive/dsl/main_spec.rb
|
|
127
|
+
- spec/hyperdrive/dsl/resource_spec.rb
|
|
58
128
|
- spec/hyperdrive/resource_spec.rb
|
|
129
|
+
- spec/hyperdrive/response_spec.rb
|
|
130
|
+
- spec/hyperdrive/server_spec.rb
|
|
59
131
|
- spec/spec_helper.rb
|