diesel-api-dsl 0.0.1 → 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 +5 -13
- data/Rakefile +5 -0
- data/diesel.gemspec +4 -0
- data/lib/diesel.rb +13 -5
- data/lib/diesel/api_base.rb +27 -0
- data/lib/diesel/api_builder.rb +98 -34
- data/lib/diesel/api_error.rb +3 -0
- data/lib/diesel/api_group.rb +27 -0
- data/lib/diesel/data_model.rb +24 -0
- data/lib/diesel/endpoint.rb +15 -33
- data/lib/diesel/middleware/auth/api_key.rb +27 -0
- data/lib/diesel/middleware/debug.rb +20 -0
- data/lib/diesel/middleware/set_body_parameter.rb +11 -0
- data/lib/diesel/middleware/set_header.rb +15 -0
- data/lib/diesel/middleware/set_parameter_base.rb +33 -0
- data/lib/diesel/middleware/set_path_parameter.rb +17 -0
- data/lib/diesel/middleware/set_query_parameter.rb +13 -0
- data/lib/diesel/middleware_builder.rb +15 -0
- data/lib/diesel/middleware_stack.rb +21 -0
- data/lib/diesel/request_context.rb +40 -15
- data/lib/diesel/swagger/data_type_field.rb +25 -0
- data/lib/diesel/swagger/definition.rb +12 -0
- data/lib/diesel/swagger/external_docs.rb +10 -0
- data/lib/diesel/swagger/info.rb +14 -0
- data/lib/diesel/swagger/node.rb +140 -0
- data/lib/diesel/swagger/operation.rb +22 -0
- data/lib/diesel/swagger/parameter.rb +32 -0
- data/lib/diesel/swagger/parser.rb +70 -0
- data/lib/diesel/swagger/path.rb +27 -0
- data/lib/diesel/swagger/property.rb +8 -0
- data/lib/diesel/swagger/security_definition.rb +15 -0
- data/lib/diesel/swagger/specification.rb +30 -0
- data/lib/diesel/utils/inflections.rb +46 -0
- data/lib/diesel/version.rb +1 -1
- data/spec/diesel/api_builder_spec.rb +14 -0
- data/spec/diesel/swagger/parser_spec.rb +80 -0
- data/spec/diesel_spec.rb +43 -0
- data/spec/files/honeybadger.json +80 -0
- data/spec/files/pivotal_tracker.json +94 -0
- data/spec/fixtures/vcr_cassettes/honeybadger.yml +98 -0
- data/spec/fixtures/vcr_cassettes/pivotal_tracker_create_story.yml +61 -0
- data/spec/spec_helper.rb +10 -0
- metadata +110 -25
- data/apis/pivotal_tracker.rb +0 -55
- data/examples/create_pivotal_task.rb +0 -13
- data/lib/diesel/action/http.rb +0 -92
- data/lib/diesel/api.rb +0 -33
- data/lib/diesel/auth/api_key.rb +0 -39
- data/lib/diesel/auth/base.rb +0 -8
- data/lib/diesel/auth/oauth2.rb +0 -13
- data/lib/diesel/authenticator.rb +0 -35
- data/lib/diesel/complex_type_builder.rb +0 -24
- data/lib/diesel/container_builder.rb +0 -6
- data/lib/diesel/dsl.rb +0 -239
- data/lib/diesel/model_builder.rb +0 -9
- data/lib/diesel/profile.rb +0 -112
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ODhkYmQ4ZDFjMTBjZjZiMTUxMDU4NTI4NjhkMzQ5NTUzODg5OGQxNA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4c09f2251953d171164fa4883b9aad83e9a1d7d9
|
4
|
+
data.tar.gz: 7c885dc69abd71c3e3c897e20bfcbf5ca141c166
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OWZlZjExOTA4NjRiN2E0MjZiZmE5N2JiYzJjMjFkMGQ1NWI5ZTQ0OGM0YTZk
|
11
|
-
M2M5MTk3ZWRiYzk1YTIxNTQ3ZDU2NzQ3MjQ2YjNmNDYyYWQ1ZmQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NjhlOGZkZTg2ODhiYmNkYjQ5MmYwZjVjYTRjOWZkNjhhZTI5NjZlMTUyYzhj
|
14
|
-
NjlhMzkyNTljZDQ1Y2IzZWM1YmRmODVlNzdlNDBkMmNjZWYyZmJlNjdhMzU1
|
15
|
-
MDJiYjk2NDFhNThhNTkzZTIwODRkYjE1Nzc4MTJhODgyZjQ4Yzc=
|
6
|
+
metadata.gz: 8347d51bde9ca019c77d813ce453199603736228b00e69294bc4af670959101b978218d39bf18ef1f7b04afdfe2483d7b2fae19eb9bde26f51c528592d442496
|
7
|
+
data.tar.gz: b67551247eab1cde0aa09fb14f34f60e1d6e4824d1d4016eae690d3f34d92662b1d2e738e032a81b33295151a59613e021ba43d5ae0d7135c857093f9d86f1ba
|
data/Rakefile
CHANGED
data/diesel.gemspec
CHANGED
@@ -20,6 +20,10 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.1"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0.0"
|
24
|
+
spec.add_development_dependency "vcr", "~> 2.9.0"
|
25
|
+
spec.add_development_dependency "webmock", "~> 1.20.0"
|
23
26
|
|
24
27
|
spec.add_dependency "httparty", "~> 0.12"
|
28
|
+
spec.add_dependency "multi_json", "~> 1.10.1"
|
25
29
|
end
|
data/lib/diesel.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require 'diesel/
|
1
|
+
require 'diesel/version'
|
2
|
+
require 'diesel/swagger/parser'
|
3
3
|
require 'diesel/api_builder'
|
4
4
|
|
5
|
+
|
5
6
|
module Diesel
|
6
|
-
def self.
|
7
|
-
|
8
|
-
|
7
|
+
def self.parse_specification(path)
|
8
|
+
Diesel::Swagger::Parser.new.parse(File.read(path))
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.build_api(specification)
|
12
|
+
Diesel::APIBuilder.new(specification).build
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.load_api(path)
|
16
|
+
build_api(parse_specification(path))
|
9
17
|
end
|
10
18
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'diesel/api_group'
|
2
|
+
|
3
|
+
module Diesel
|
4
|
+
class APIError < Exception; end
|
5
|
+
end
|
6
|
+
|
7
|
+
module Diesel
|
8
|
+
class APIBase
|
9
|
+
attr_accessor :logger, :options
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def logger=(logger)
|
16
|
+
@logger = logger
|
17
|
+
self.class.api_groups.each { |g| g.logger = logger }
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def api_groups; @api_groups ||= []; end
|
22
|
+
def api_groups=(api_groups)
|
23
|
+
@api_groups = api_groups
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/diesel/api_builder.rb
CHANGED
@@ -1,61 +1,125 @@
|
|
1
|
-
require 'diesel/
|
2
|
-
require 'diesel/
|
3
|
-
require 'diesel/
|
1
|
+
require 'diesel/api_error'
|
2
|
+
require 'diesel/utils/inflections'
|
3
|
+
require 'diesel/api_base'
|
4
|
+
require 'diesel/data_model'
|
5
|
+
|
6
|
+
require 'diesel/middleware/debug'
|
7
|
+
require 'diesel/middleware/set_header'
|
4
8
|
|
5
9
|
module Diesel
|
6
10
|
class APIBuilder
|
7
|
-
|
11
|
+
include Diesel::Utils::Inflections
|
12
|
+
|
13
|
+
attr_reader :specification
|
8
14
|
|
9
|
-
def initialize(
|
10
|
-
@
|
15
|
+
def initialize(specification)
|
16
|
+
@specification = specification
|
11
17
|
end
|
12
18
|
|
13
19
|
def build
|
20
|
+
validate!
|
21
|
+
|
14
22
|
create_api_class.tap do |klass|
|
15
|
-
klass.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
klass.api_groups = [
|
24
|
+
APIGroup.new.tap do |group|
|
25
|
+
group.endpoints = build_endpoints
|
26
|
+
group.endpoints.each do |endpoint|
|
27
|
+
klass.send(:define_method, endpoint.name.to_sym) do |parameters|
|
28
|
+
group.execute(self.options, endpoint, parameters)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
]
|
33
|
+
|
21
34
|
#Diesel.const_set create_class_name(name), klass
|
22
35
|
end
|
23
36
|
end
|
24
37
|
|
25
38
|
protected
|
26
|
-
|
27
|
-
|
39
|
+
|
40
|
+
def validate!
|
41
|
+
api_errors = specification.collect_errors
|
42
|
+
if api_errors.any?
|
43
|
+
raise APIError, "API specification is invalid: \n #{api_errors.join("\n")}"
|
44
|
+
end
|
28
45
|
end
|
29
46
|
|
30
47
|
def create_api_class
|
31
|
-
Class.new(Diesel::
|
48
|
+
Class.new(Diesel::APIBase)
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_endpoint_url(specification, path)
|
52
|
+
base_path = specification.base_path.chomp('/')
|
53
|
+
resource_path = path.sub(/^([^\/])/, '/\1').chomp('/')
|
54
|
+
[
|
55
|
+
specification.schemes.first,
|
56
|
+
'://',
|
57
|
+
specification.host,
|
58
|
+
base_path,
|
59
|
+
resource_path
|
60
|
+
].join('')
|
32
61
|
end
|
33
62
|
|
34
|
-
def build_endpoints
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
63
|
+
def build_endpoints
|
64
|
+
spec = specification
|
65
|
+
data_models = self.data_models
|
66
|
+
|
67
|
+
spec.paths.map do |path, path_model|
|
68
|
+
path_model.operations_map.map do |(method, operation)|
|
69
|
+
endpoint_name = underscore(operation.operation_id)
|
70
|
+
endpoint_url = build_endpoint_url(spec, path)
|
71
|
+
|
72
|
+
Diesel::Endpoint.new(endpoint_name, endpoint_url, method).tap do |endpoint|
|
73
|
+
endpoint.config_middleware do
|
74
|
+
use Diesel::Middleware::Debug
|
75
|
+
|
76
|
+
if spec.produces.any?
|
77
|
+
use Diesel::Middleware::SetHeader, 'Content-Type' => spec.produces.first
|
78
|
+
end
|
79
|
+
|
80
|
+
spec.security_definitions.each_pair do |name, security_def|
|
81
|
+
case security_def.type
|
82
|
+
when 'apiKey'
|
83
|
+
require 'diesel/middleware/auth/api_key'
|
84
|
+
use Diesel::Middleware::Auth::APIKey,
|
85
|
+
id: Diesel::Utils::Inflections.underscore(name).to_sym,
|
86
|
+
in: security_def.in,
|
87
|
+
name: security_def.name
|
88
|
+
else
|
89
|
+
raise APIError, "Unsupported security definition: #{security_def.type}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
operation.parameters.each do |parameter|
|
94
|
+
param_class_path = "diesel/middleware/set_#{parameter.in}_parameter"
|
95
|
+
require param_class_path
|
96
|
+
param_class_name = Diesel::Utils::Inflections.camelize(param_class_path)
|
97
|
+
param_class = Diesel::Utils::Inflections.constantize(param_class_name)
|
98
|
+
middleware_opts = {name: parameter.name}
|
99
|
+
if parameter.schema?
|
100
|
+
unless schema = data_models[parameter.schema]
|
101
|
+
raise APIError, "Unspecified schema: #{parameter.schema}"
|
102
|
+
end
|
103
|
+
middleware_opts[:schema] = schema
|
104
|
+
end
|
105
|
+
use param_class, middleware_opts
|
106
|
+
end
|
107
|
+
|
45
108
|
end
|
46
109
|
end
|
47
110
|
end
|
48
111
|
end.flatten.compact
|
49
112
|
end
|
50
113
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
114
|
+
def data_models
|
115
|
+
@data_models ||= build_data_models
|
116
|
+
end
|
117
|
+
|
118
|
+
def build_data_models
|
119
|
+
specification.definitions.reduce({}) do |m, (name, definition)|
|
120
|
+
m[name] = DataModel.new(definition)
|
121
|
+
m
|
122
|
+
end
|
59
123
|
end
|
60
124
|
|
61
125
|
def create_class_name(name)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'diesel/request_context'
|
2
|
+
require 'diesel/endpoint'
|
3
|
+
|
4
|
+
module Diesel
|
5
|
+
class APIGroup
|
6
|
+
attr_accessor :logger
|
7
|
+
|
8
|
+
def endpoints; @endpoints ||= []; end
|
9
|
+
def endpoints=(endpoints)
|
10
|
+
@endpoints = endpoints
|
11
|
+
end
|
12
|
+
|
13
|
+
def authenticators; @authenticators; end
|
14
|
+
def authenticators=(auth)
|
15
|
+
@authenticators = auth
|
16
|
+
end
|
17
|
+
|
18
|
+
def data_models; @data_models ||= {}; end
|
19
|
+
def data_models=(data_models)
|
20
|
+
@data_models = data_models
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute(options, endpoint, parameters)
|
24
|
+
RequestContext.new(options, self, endpoint, parameters).perform
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Diesel
|
4
|
+
class DataModel
|
5
|
+
attr_reader :definition
|
6
|
+
|
7
|
+
def initialize(definition)
|
8
|
+
@definition = definition
|
9
|
+
end
|
10
|
+
|
11
|
+
def build(parameter_name, env)
|
12
|
+
context = env[:context]
|
13
|
+
h = context.get_attribute(parameter_name)
|
14
|
+
return nil unless h
|
15
|
+
|
16
|
+
json = definition.properties.reduce({}) do |m, (name, property)|
|
17
|
+
name = name.to_sym
|
18
|
+
m[name] = h[name] if h[name]; m
|
19
|
+
end
|
20
|
+
|
21
|
+
MultiJson.dump(json)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/diesel/endpoint.rb
CHANGED
@@ -1,43 +1,25 @@
|
|
1
|
+
require 'diesel/middleware_builder'
|
2
|
+
require 'diesel/middleware_stack'
|
3
|
+
|
1
4
|
module Diesel
|
2
5
|
class Endpoint
|
3
|
-
attr_reader :
|
4
|
-
attr_accessor :action
|
6
|
+
attr_reader :name, :url, :request_method
|
5
7
|
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
+
def initialize(name, url, request_method)
|
9
|
+
@name, @url, @request_method = name, url, request_method
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
assert_attributes(context)
|
14
|
-
|
15
|
-
#unless action.accept? context
|
16
|
-
# raise 'endpoint does not support this context'
|
17
|
-
#end
|
18
|
-
|
19
|
-
action.perform(context)
|
12
|
+
def middlewares
|
13
|
+
@middlewares ||= []
|
20
14
|
end
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# unless context.attributes.empty?
|
26
|
-
# raise ArgumentError, "invalid attributes #{atts.keys.join(', ')}"
|
27
|
-
# end
|
28
|
-
# return
|
29
|
-
#end
|
30
|
-
|
31
|
-
#invalid_atts = context.attributes.keys.map!(&:intern) - attributes.keys
|
32
|
-
#unless invalid_atts.empty?
|
33
|
-
# raise ArgumentError, "invalid attributes #{invalid_atts.join(', ')}"
|
34
|
-
#end
|
16
|
+
def middleware_stack
|
17
|
+
@middleware_stack ||= MiddlewareStack.new(middlewares)
|
18
|
+
end
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#end
|
41
|
-
end
|
20
|
+
def config_middleware(&block)
|
21
|
+
builder = MiddlewareBuilder.new(middlewares)
|
22
|
+
builder.build(&block)
|
23
|
+
end
|
42
24
|
end
|
43
25
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Diesel
|
2
|
+
module Middleware
|
3
|
+
module Auth
|
4
|
+
class APIKey
|
5
|
+
|
6
|
+
def initialize(app, options)
|
7
|
+
@app = app
|
8
|
+
@id = options[:id]
|
9
|
+
@in = options[:in]
|
10
|
+
@name = options[:name]
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
context = env[:context]
|
15
|
+
value = context.options[@id]
|
16
|
+
if @in == :header
|
17
|
+
env[:request_headers][@name] = value
|
18
|
+
elsif @in == :query
|
19
|
+
env[:params][@name] = value
|
20
|
+
end
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Diesel
|
2
|
+
module Middleware
|
3
|
+
class Debug
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
def call(env)
|
8
|
+
@app.call(env)
|
9
|
+
logger = env[:logger]
|
10
|
+
if logger && logger.debug?
|
11
|
+
logger.debug("Request Method: #{env[:method]}")
|
12
|
+
logger.debug("URL: #{env[:url]}")
|
13
|
+
logger.debug("Request Headers: #{env[:request_headers].inspect}")
|
14
|
+
logger.debug("Params: #{env[:params].inspect}")
|
15
|
+
logger.debug("Body: #{env[:body]}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|