rat_pack_swagger 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,52 @@
1
+ class SwaggerObject
2
+ instance_methods.each do |m|
3
+ unless m =~ /^__/ || [:inspect, :instance_eval, :object_id].include?(m)
4
+ undef_method m
5
+ end
6
+ end
7
+
8
+ def initialize(*args, **kwargs, &block)
9
+ if args.count > 0 && (!kwargs.empty? || block_given?)
10
+ raise "Cannot give both unnamed arguments AND named arguments or block to Swagger parameter '#{m}'."
11
+ elsif block_given?
12
+ @obj = kwargs unless kwargs.empty?
13
+ instance_eval &block
14
+ elsif !kwargs.empty?
15
+ @obj = kwargs
16
+ elsif args.count > 0
17
+ @obj = [*args]
18
+ else
19
+ raise "Cannot create SwaggerObject with no arguments."
20
+ end
21
+ end
22
+
23
+ def add(*args, **kwargs)
24
+ @obj ||= []
25
+ if !@obj.is_a?(Array)
26
+ raise "Swagger object must be an array to append data '#{item}'"
27
+ elsif args.count > 0
28
+ @obj << [*args, kwargs]
29
+ else
30
+ @obj << kwargs
31
+ end
32
+ end
33
+
34
+ def method_missing(m, *args, **kwargs, &block)
35
+ @obj ||= {}
36
+ if block_given?
37
+ @obj[m] = SwaggerObject.new(**kwargs, &block).to_h
38
+ elsif !kwargs.empty?
39
+ @obj[m] = SwaggerObject.new(**kwargs).to_h
40
+ elsif args.count > 1
41
+ @obj[m] = [*args]
42
+ elsif args.count == 1
43
+ @obj[m] = args[0]
44
+ else
45
+ raise "Cannot give zero arguments to Swagger key '#{m}'"
46
+ end
47
+ end
48
+
49
+ def to_h
50
+ @obj
51
+ end
52
+ end
@@ -0,0 +1,172 @@
1
+ require 'json'
2
+
3
+ module RatPackSwagger
4
+ module SwaggerType
5
+ def to_h
6
+ h = {}
7
+ getters = methods.select{|m| m =~ /\w+=$/}.map{|m| m.to_s.chop}
8
+ getters.each do |getter|
9
+ val = send(getter)
10
+ next if [nil, [], {}].include?(val)
11
+ val = val.to_h if val.is_a?(SwaggerType)
12
+ h[getter.to_sym] = val
13
+ end
14
+ return h
15
+ end
16
+ end
17
+
18
+ class SwaggerPathItem
19
+ include SwaggerType
20
+ attr_accessor :get, :put, :post, :delete, :options, :head, :patch
21
+ end
22
+
23
+ class SwaggerOperation
24
+ include SwaggerType
25
+ attr_accessor :tags, :summary, :description,
26
+ :externalDocs, :consumes, :produces, :parameters, :responses,
27
+ :schemes, :deprecated, :security
28
+ def initialize
29
+ @tags = []
30
+ @consumes = []
31
+ @parameters = []
32
+ @responses = {}
33
+ @schemes = []
34
+ @security = []
35
+ end
36
+ end
37
+
38
+ class SwaggerSpec
39
+ attr_accessor :swagger_schema, :spec, :this_route
40
+
41
+ def initialize
42
+ @spec = {
43
+ paths: {}
44
+ }
45
+ @spec_cache_invalid = true
46
+ @spec_cache = {
47
+ api_spec: nil, # the data returned byt /v2/swagger.json
48
+ api_spec_json: nil, # api_spec as json string
49
+ resolved_spec: nil, # a hash where all json pointers are resolved
50
+ # for request/response validation, because json-schema sucks at pointers
51
+ }
52
+ @swagger_schema = ::JSON.parse(File.read(File.join(File.dirname(__FILE__), 'swagger_json_schema.json')))
53
+ @this_route = SwaggerOperation.new
54
+ end
55
+
56
+ def route_consumes?(path, verb, mime)
57
+ route = @spec[:paths][path][verb]
58
+ return true if route[:consumes] && route[:consumes].include?(mime)
59
+ return true if @spec[:consumes].include?(mime)
60
+ return false
61
+ end
62
+
63
+ def register_this_route(path, verb)
64
+ verb.downcase!
65
+ paths = @spec[:paths]
66
+ paths[path] ||= {}
67
+ paths[path][verb] = @this_route.to_h
68
+ @this_route = SwaggerOperation.new
69
+ @spec_cache_invalid = true
70
+ end
71
+
72
+ def add_definitions(*constants)
73
+ @spec[:definitions] ||= {}
74
+ constants.each do |constant|
75
+ if constant.is_a?(Module)
76
+ constant.constants.each do |c|
77
+ klass = constant.const_get(c)
78
+ if klass.is_a?(Class) && klass.ancestors.include?(Definition)
79
+ @spec[:definitions][c] = klass.definition
80
+ end
81
+ end
82
+ else
83
+ if constant.is_a?(Class) && constant.ancestors.include?(Definition)
84
+ @@doc[:definitions][constant.to_s.rpartition('::').last] = constant.definition
85
+ end
86
+ end
87
+ end
88
+ @spec_cache_invalid = true
89
+ end
90
+
91
+ def resolved_spec
92
+ update_spec_cache if @spec_cache_invalid
93
+ @spec_cache[:resolved_spec]
94
+ end
95
+ def api_spec
96
+ update_spec_cache if @spec_cache_invalid
97
+ @spec_cache[:api_spec]
98
+ end
99
+ def api_spec_json
100
+ update_spec_cache if @spec_cache_invalid
101
+ @spec_cache[:api_spec_json]
102
+ end
103
+
104
+ private
105
+
106
+ def update_spec_cache
107
+ cache_resolved_spec
108
+ cache_api_spec
109
+ @spec_cache[:api_spec_json] = @spec_cache[:api_spec].to_json
110
+ @spec_cache_invalid = false
111
+ end
112
+
113
+ def cache_resolved_spec
114
+ resolved_spec = make_deep_copy(@spec)
115
+ map_hash_values!(resolved_spec) do |k,v|
116
+ new_v = v
117
+ if v.is_a?(Hash) && v[:$ref]
118
+ if v[:$ref].respond_to?(:to_h)
119
+ new_v = v[:$ref].to_h
120
+ end
121
+ end
122
+ new_v
123
+ end
124
+ @spec_cache[:resolved_spec] = resolved_spec
125
+ end
126
+
127
+ def cache_api_spec
128
+ api_spec = make_deep_copy(@spec)
129
+ map_hash_values!(api_spec) do |k,v|
130
+ new_v = v
131
+ if k.to_s == '$ref'
132
+ if v.is_a?(Class)
133
+ classname = v.to_s.rpartition('::').last
134
+ if v.ancestors.include?(Definition)
135
+ new_v = "#/definitions/#{classname}"
136
+ end
137
+ # TODO: Add other types like Parameters"
138
+ end
139
+ end
140
+ new_v
141
+ end
142
+ @spec_cache[:api_spec] = api_spec
143
+ end
144
+
145
+ def make_deep_copy(arg)
146
+ Marshal.load(Marshal.dump(arg))
147
+ end
148
+
149
+ def map_hash_values!(obj, &block)
150
+ if obj.is_a? Hash
151
+ obj.each do |k,v|
152
+ # perform mapping first, THEN if result is hash/array, go recursive
153
+ obj[k] = yield(k,v)
154
+ if obj[k].is_a?(Hash) || obj[k].is_a?(Array)
155
+ obj[k] = map_hash_values!(obj[k], &block)
156
+ end
157
+ end
158
+ elsif obj.is_a? Array
159
+ obj.each_with_index do |e,i|
160
+ if e.is_a?(Hash) || e.is_a?(Array)
161
+ obj[i] = map_hash_values!(e, &block)
162
+ end
163
+ end
164
+ else
165
+ raise "Argument must be a Hash or an Array."
166
+ end
167
+ return obj
168
+ end
169
+
170
+ end
171
+ end
172
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rat_pack_swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hildebrand
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-15 00:00:00.000000000 Z
12
+ date: 2015-07-20 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json-schema
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '2.5'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '2.5'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: sinatra
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -36,6 +50,10 @@ files:
36
50
  - README.md
37
51
  - lib/rat_pack_swagger.rb
38
52
  - lib/rat_pack_swagger/version.rb
53
+ - lib/request_validators.rb
54
+ - lib/swagger_json_schema.json
55
+ - lib/swagger_object.rb
56
+ - lib/swagger_spec.rb
39
57
  homepage: https://github.com/ckhrysze/rat_pack_swagger
40
58
  licenses:
41
59
  - MIT