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.
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