diesel-api-dsl 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +5 -13
  2. data/Rakefile +5 -0
  3. data/diesel.gemspec +4 -0
  4. data/lib/diesel.rb +13 -5
  5. data/lib/diesel/api_base.rb +27 -0
  6. data/lib/diesel/api_builder.rb +98 -34
  7. data/lib/diesel/api_error.rb +3 -0
  8. data/lib/diesel/api_group.rb +27 -0
  9. data/lib/diesel/data_model.rb +24 -0
  10. data/lib/diesel/endpoint.rb +15 -33
  11. data/lib/diesel/middleware/auth/api_key.rb +27 -0
  12. data/lib/diesel/middleware/debug.rb +20 -0
  13. data/lib/diesel/middleware/set_body_parameter.rb +11 -0
  14. data/lib/diesel/middleware/set_header.rb +15 -0
  15. data/lib/diesel/middleware/set_parameter_base.rb +33 -0
  16. data/lib/diesel/middleware/set_path_parameter.rb +17 -0
  17. data/lib/diesel/middleware/set_query_parameter.rb +13 -0
  18. data/lib/diesel/middleware_builder.rb +15 -0
  19. data/lib/diesel/middleware_stack.rb +21 -0
  20. data/lib/diesel/request_context.rb +40 -15
  21. data/lib/diesel/swagger/data_type_field.rb +25 -0
  22. data/lib/diesel/swagger/definition.rb +12 -0
  23. data/lib/diesel/swagger/external_docs.rb +10 -0
  24. data/lib/diesel/swagger/info.rb +14 -0
  25. data/lib/diesel/swagger/node.rb +140 -0
  26. data/lib/diesel/swagger/operation.rb +22 -0
  27. data/lib/diesel/swagger/parameter.rb +32 -0
  28. data/lib/diesel/swagger/parser.rb +70 -0
  29. data/lib/diesel/swagger/path.rb +27 -0
  30. data/lib/diesel/swagger/property.rb +8 -0
  31. data/lib/diesel/swagger/security_definition.rb +15 -0
  32. data/lib/diesel/swagger/specification.rb +30 -0
  33. data/lib/diesel/utils/inflections.rb +46 -0
  34. data/lib/diesel/version.rb +1 -1
  35. data/spec/diesel/api_builder_spec.rb +14 -0
  36. data/spec/diesel/swagger/parser_spec.rb +80 -0
  37. data/spec/diesel_spec.rb +43 -0
  38. data/spec/files/honeybadger.json +80 -0
  39. data/spec/files/pivotal_tracker.json +94 -0
  40. data/spec/fixtures/vcr_cassettes/honeybadger.yml +98 -0
  41. data/spec/fixtures/vcr_cassettes/pivotal_tracker_create_story.yml +61 -0
  42. data/spec/spec_helper.rb +10 -0
  43. metadata +110 -25
  44. data/apis/pivotal_tracker.rb +0 -55
  45. data/examples/create_pivotal_task.rb +0 -13
  46. data/lib/diesel/action/http.rb +0 -92
  47. data/lib/diesel/api.rb +0 -33
  48. data/lib/diesel/auth/api_key.rb +0 -39
  49. data/lib/diesel/auth/base.rb +0 -8
  50. data/lib/diesel/auth/oauth2.rb +0 -13
  51. data/lib/diesel/authenticator.rb +0 -35
  52. data/lib/diesel/complex_type_builder.rb +0 -24
  53. data/lib/diesel/container_builder.rb +0 -6
  54. data/lib/diesel/dsl.rb +0 -239
  55. data/lib/diesel/model_builder.rb +0 -9
  56. data/lib/diesel/profile.rb +0 -112
@@ -0,0 +1,33 @@
1
+ module Diesel
2
+ module Middleware
3
+ class SetParameterBase
4
+
5
+ def initialize(app, options)
6
+ @app = app
7
+ @name = options[:name]
8
+ @schema = options[:schema]
9
+ end
10
+
11
+ def call(env)
12
+ value = find_parameter_value(env)
13
+ apply_parameter_value(env, value)
14
+ @app.call(env)
15
+ end
16
+
17
+ protected
18
+
19
+ def find_parameter_value(env)
20
+ if @schema
21
+ @schema.build(@name, env)
22
+ else
23
+ context = env[:context]
24
+ context.get_attribute(@name)
25
+ end
26
+ end
27
+
28
+ def apply_parameter_value(env, value)
29
+ raise NotImplementedError
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'diesel/middleware/set_parameter_base'
2
+
3
+ module Diesel
4
+ module Middleware
5
+ class SetPathParameter < SetParameterBase
6
+
7
+ def initialize(app, options)
8
+ super
9
+ @regex = Regexp.new(Regexp.quote("{#{@name}}"))
10
+ end
11
+
12
+ def apply_parameter_value(env, value)
13
+ env[:url] = env[:url].gsub(@regex, value.to_s)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ require 'diesel/middleware/set_parameter_base'
2
+
3
+ module Diesel
4
+ module Middleware
5
+ class SetQueryParameter < SetParameterBase
6
+ def apply_parameter_value(env, value)
7
+ unless value.nil?
8
+ env[:params][@name] = value
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Diesel
2
+ class MiddlewareBuilder
3
+ def initialize(middlewares)
4
+ @middlewares = middlewares
5
+ end
6
+
7
+ def build(&block)
8
+ instance_eval(&block)
9
+ end
10
+
11
+ def use(middleware_klass, options = {})
12
+ @middlewares << [middleware_klass, options]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module Diesel
2
+ class MiddlewareStack
3
+
4
+ def initialize(middlewares)
5
+ cur = ->(env){}
6
+ middlewares.reverse.each do |(klass, options)|
7
+ cur = if klass.instance_method(:initialize).arity == 1
8
+ klass.new(cur)
9
+ else
10
+ klass.new(cur, options)
11
+ end
12
+ end
13
+ @first = cur
14
+ end
15
+
16
+ def call(env)
17
+ @first.call(env)
18
+ end
19
+
20
+ end
21
+ end
@@ -1,30 +1,55 @@
1
+ require 'httparty'
2
+ require 'diesel/utils/inflections'
3
+
1
4
  module Diesel
2
5
  class RequestContext
3
- attr_reader :api, :endpoint, :attributes
6
+ include Diesel::Utils::Inflections
7
+
8
+ attr_reader :options, :group, :endpoint, :attributes
4
9
 
5
- def initialize(api, endpoint, attributes)
6
- @api, @endpoint, @attributes = api, endpoint, attributes
10
+ def initialize(options, group, endpoint, attributes)
11
+ @options, @group, @endpoint, @attributes = options, group, endpoint, attributes
7
12
  end
8
13
 
9
- def logger
10
- api.logger
14
+ def perform
15
+ env = {
16
+ method: endpoint.request_method,
17
+ url: endpoint.url,
18
+ params: {},
19
+ request_headers: {},
20
+ logger: logger,
21
+ context: self
22
+ }
23
+ endpoint.middleware_stack.call(env)
24
+ perform_request(env)
11
25
  end
12
26
 
13
- def get_attribute(name)
14
- name = name.to_sym
15
- attributes[name]
27
+ def authenticator
28
+ group.authenticator
16
29
  end
17
30
 
18
31
  def endpoint_url
19
- url = api.class.base_path.dup
20
- url << "/" unless url =~ /\/$/
21
- endpoint_path = endpoint.path
22
- url << (endpoint_path =~ /^\// ? endpoint_path[1..-1] : endpoint_path)
23
- url
32
+ endpoint.url
24
33
  end
25
34
 
26
- def perform
27
- endpoint.perform(self)
35
+ def logger
36
+ group.logger
28
37
  end
38
+
39
+ def get_attribute(name)
40
+ name = name.to_sym
41
+ unless attributes.has_key?(name)
42
+ name = underscore(name).to_sym
43
+ end
44
+ attributes[name]
45
+ end
46
+
47
+ protected
48
+ def perform_request(env)
49
+ HTTParty.send(env[:method], env[:url],
50
+ headers: env[:request_headers],
51
+ query: env[:params],
52
+ body: env[:body])
53
+ end
29
54
  end
30
55
  end
@@ -0,0 +1,25 @@
1
+ require 'diesel/swagger/node'
2
+
3
+ module Diesel
4
+ module Swagger
5
+ class DataTypeField < Node
6
+ attribute :type, symbolize: true
7
+ attribute :format
8
+ attribute :default_value
9
+ attribute :multiple_of
10
+ attribute :maximum
11
+ attribute :exclusive_maximum, type: :boolean
12
+ attribute :minimum
13
+ attribute :exclusive_minimum, type: :boolean
14
+ attribute :max_length
15
+ attribute :min_length
16
+ attribute :pattern
17
+ attribute :max_items
18
+ attribute :min_items
19
+ attribute :unique_items, type: :boolean
20
+
21
+ list :enum
22
+ list :items
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ require 'diesel/swagger/node'
2
+ require 'diesel/swagger/property'
3
+
4
+ module Diesel
5
+ module Swagger
6
+ class Definition < Node
7
+ attribute :required
8
+ attribute :discriminator
9
+ hash :properties
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ require 'diesel/swagger/node'
2
+
3
+ module Diesel
4
+ module Swagger
5
+ class ExternalDocs < Node
6
+ attribute :description
7
+ attribute :url
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ require 'diesel/swagger/node'
2
+
3
+ module Diesel
4
+ module Swagger
5
+ class Info < Node
6
+ attribute :title
7
+ attribute :description
8
+ attribute :terms_of_service
9
+ attribute :contact
10
+ attribute :license
11
+ attribute :version
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,140 @@
1
+ require 'diesel/utils/inflections'
2
+
3
+ module Diesel
4
+ module Swagger
5
+ class Node
6
+ include Diesel::Utils::Inflections
7
+
8
+ class << self
9
+ def inherited(base)
10
+ base.instance_variable_set(:@attribute_names, attribute_names.dup)
11
+ base.instance_variable_set(:@list_names, list_names.dup)
12
+ base.instance_variable_set(:@hash_names, hash_names.dup)
13
+ end
14
+
15
+ def attribute_names
16
+ @attribute_names || []
17
+ end
18
+
19
+ def list_names
20
+ @list_names || []
21
+ end
22
+
23
+ def hash_names
24
+ @hash_names || []
25
+ end
26
+
27
+ def attribute(name, options = {})
28
+ name = name.to_sym
29
+ (@attribute_names ||= []) << name
30
+ attr_accessor name
31
+ if options[:type] == :boolean
32
+ define_method("#{name}?".to_sym) do
33
+ !!send(name)
34
+ end
35
+ elsif options[:symbolize]
36
+ define_method("#{name}=".to_sym) do |value|
37
+ instance_variable_set("@#{name}".to_sym, value.nil? ? nil : value.to_sym)
38
+ end
39
+ end
40
+ (@validates_children ||= []) << name if options[:validate]
41
+ end
42
+
43
+ def list(name, options = {})
44
+ attr_accessor name
45
+ (@list_names ||= []) << name
46
+ (@validates_children ||= []) << name if options[:validate]
47
+ end
48
+
49
+ def hash(name, options = {})
50
+ attr_accessor name
51
+ (@hash_names ||= []) << name
52
+ (@validates_children ||= []) << name if options[:validate]
53
+ end
54
+
55
+ def collect_errors(node, all_errors = [])
56
+ if @validates_children
57
+ @validates_children.each do |name|
58
+ if attr_val = node.send(name)
59
+ if @hash_names && @hash_names.include?(name)
60
+ attr_val.each_pair { |k,v| v.collect_errors(all_errors) }
61
+
62
+ elsif @list_names && @list_names.include?(name)
63
+ attr_val.each { |v| v.collect_errors(all_errors) }
64
+
65
+ else
66
+ unless attr_val.respond_to? :collect_errors
67
+ raise "Expecting #{name} to be a node"
68
+ end
69
+ attr_val.collect_errors(all_errors)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ all_errors
75
+ end
76
+ end
77
+
78
+ attr_reader :errors
79
+
80
+ def initialize
81
+ @errors = []
82
+ end
83
+
84
+ def validate
85
+ end
86
+
87
+ def valid?
88
+ validate
89
+ @errors.any?
90
+ end
91
+
92
+ def collect_errors(all_errors = [])
93
+ validate; all_errors.concat(errors)
94
+ self.class.collect_errors(self, all_errors)
95
+ end
96
+
97
+ def serializable_hash
98
+ h = {}
99
+
100
+ if self.class.attribute_names
101
+ self.class.attribute_names.each do |nm|
102
+ if v = __send__(nm)
103
+ h[camelize(nm, false)] = value_or_serializable_hash(v)
104
+ end
105
+ end
106
+ end
107
+
108
+ if self.class.list_names
109
+ self.class.list_names.each do |nm|
110
+ if arr = __send__(nm)
111
+ result = arr.map do |v|
112
+ value_or_serializable_hash(v)
113
+ end
114
+ h[camelize(nm, false)] = result if result.any?
115
+ end
116
+ end
117
+ end
118
+
119
+ if self.class.hash_names
120
+ self.class.hash_names.each do |nm|
121
+ if value_hash = __send__(nm)
122
+ result = value_hash.reduce({}) do |m,(k,v)|
123
+ m[k] = value_or_serializable_hash(v); m
124
+ end
125
+ h[camelize(nm, false)] = result if result.any?
126
+ end
127
+ end
128
+ end
129
+
130
+ h
131
+ end
132
+
133
+ private
134
+
135
+ def value_or_serializable_hash(v)
136
+ v.respond_to?(:serializable_hash) ? v.serializable_hash : v
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,22 @@
1
+ require 'diesel/swagger/node'
2
+ require 'diesel/swagger/parameter'
3
+
4
+ module Diesel
5
+ module Swagger
6
+ class Operation < Node
7
+ attribute :summary
8
+ attribute :description
9
+ attribute :external_docs, validate: true
10
+ attribute :operation_id
11
+ attribute :deprecated
12
+
13
+ list :tags
14
+ list :consumes
15
+ list :produces
16
+ list :parameters, validate: true
17
+ list :responses, validate: true
18
+ list :schemes
19
+ list :security, validate: true
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ require 'diesel/swagger/data_type_field'
2
+
3
+ module Diesel
4
+ module Swagger
5
+ class Parameter < DataTypeField
6
+ VALID_TYPES = %w(
7
+ string
8
+ number
9
+ integer
10
+ boolean
11
+ array
12
+ file
13
+ )
14
+
15
+ attribute :name
16
+ attribute :in, symbolize: true
17
+ attribute :description
18
+ attribute :required, type: :boolean
19
+ attribute :schema
20
+
21
+ def schema?
22
+ !!schema
23
+ end
24
+
25
+ def validate
26
+ if type == :path && !required?
27
+ errors << "Path parameters must be defined as required"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end