swagger_yard 0.3.6 → 0.3.7

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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9aeaddf2ad2b175e4bfdc57babde3aa86ee99062
4
- data.tar.gz: ff4b60b5e565142fb1fbca9a965df9ac966c1de1
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjdkMTcwZWU5NTNhNjNhNjA0NzhlN2ZjMWZmMzZlMDUxZTI1NWNiOA==
5
+ data.tar.gz: !binary |-
6
+ MjAxYzIwNDYyNzc1MjEyMGU0MzIyNjAyZmU5OTI4YjA4MzFmMzRhOA==
5
7
  SHA512:
6
- metadata.gz: 803a430a06eb91d2b853a9e1eccd45920d7047db36181076e53aec1e64ebc43a2e288cbab11f4541bb43e8d37f11b7f9822d0557065cd0f1ac92389ada974643
7
- data.tar.gz: 19ce8dba724574bc55588c3ee5b913b3416ee18e24b26818e8ed5862637df439d8b83ddb3e54fbd1477594cc29d13d43cbe9d6352b327becf9e4d52aa19b6b49
8
+ metadata.gz: !binary |-
9
+ MDhhNWJkNDJhNWI3ODQyZTI0OGQ3ZmM4ZGE4MzYzMzgwNWU3YmM2N2MyMTAz
10
+ NGM3MDVkOTM1MDMwMDYxYTU1MjE4YTUyZWNlZmM0OWY3NjFhYjI0Mzc4ZDFk
11
+ ODUxODdkZWQ4YWNiY2Q1YTQ0YjMwODRjMzI3ZDQ0NWQwYWQ1Nzc=
12
+ data.tar.gz: !binary |-
13
+ NWFkMDRjMGE1MGYzYzE1ZWQ2NGRiMjRiMmZkOWQ5YjliZGYzYWJlZDFjOWE5
14
+ YzE2YWM0N2E2MzA4MDI4NzhmNTk0YjA3OTI2ODdjODUyZDU5OGNjNmE5NDBj
15
+ OWUyNGEyYTc3OGYyNDhmMTgxOTYzM2YwMzFhOWJmN2JkMTcwNDI=
data/README.md CHANGED
@@ -38,6 +38,8 @@ are indicated inside square-brackets (e.g., `[string]`) as part of a YARD tag.
38
38
  uuid, etc.) should be lowercased.
39
39
  - An array of models or basic types is specified with `[array<...>]`.
40
40
  - An enum of allowed string values is specified with `[enum<one,two,three>]`.
41
+ - An object definition can include the property definitions of its fields, and / or of an additional property for any remaining allowed fields. E.g., `[object<name: string, age: integer, string >]`
42
+ - Structured data like objects, arrays, pairs, etc., definitions can also be nested; E.g., `[object<pairs:array<object<right:integer,left:integer>>>]`
41
43
  - JSON-Schema `format` attributes can be specified for basic types using
42
44
  `<...>`. For example, `[integer<int64>]` produces JSON
43
45
  `{ "type": "integer", "format": "int64" }`.
@@ -156,8 +158,9 @@ end
156
158
  ```
157
159
 
158
160
  ## Authorization ##
161
+ ### API Key auth ###
159
162
 
160
- Currently, SwaggerYard only supports API Key auth descriptions. Start by adding `@authorization` to your `ApplicationController`.
163
+ SwaggerYard supports API Key auth descriptions. Start by adding `@authorization` to your `ApplicationController`.
161
164
 
162
165
  ```ruby
163
166
  #
@@ -177,6 +180,28 @@ class PetController < ApplicationController
177
180
  end
178
181
  ```
179
182
 
183
+ ### Custom security definitions (OAuth2) ###
184
+
185
+ Additionally SwaggerYard also supports custom [security definitions](http://swagger.io/specification/#securityDefinitionsObject). You can define these in your configuration like:
186
+
187
+ ```ruby
188
+ SwaggerYard.configure do |config|
189
+ config.security_definitions['petstore_oauth'] = {
190
+ type: "oauth2",
191
+ authorizationUrl: "http://swagger.io/api/oauth/dialog",
192
+ flow: :implicit
193
+ }
194
+ end
195
+ ```
196
+
197
+ Then you can also use these authorizations from your controller or actions in a controller.
198
+
199
+ ```ruby
200
+ # @authorize_with petstore_oauth
201
+ class PetController < ApplicationController
202
+ end
203
+ ```
204
+
180
205
  ## UI ##
181
206
 
182
207
  We suggest using something like [swagger-ui_rails](https://github.com/3scale/swagger-ui_rails/tree/dev-2.1.3) for your UI needs inside of Rails.
@@ -6,6 +6,7 @@ module SwaggerYard
6
6
  attr_accessor :enable, :reload
7
7
  attr_accessor :controller_path, :model_path
8
8
  attr_accessor :path_discovery_function
9
+ attr_accessor :security_definitions
9
10
 
10
11
  def initialize
11
12
  self.swagger_version = "2.0"
@@ -14,6 +15,7 @@ module SwaggerYard
14
15
  self.reload = true
15
16
  self.title = "Configure title with SwaggerYard.config.title"
16
17
  self.description = "Configure description with SwaggerYard.config.description"
18
+ self.security_definitions = {}
17
19
  end
18
20
 
19
21
  def swagger_spec_base_path=(ignored)
@@ -43,7 +43,10 @@ module SwaggerYard
43
43
  end
44
44
 
45
45
  def security_objects
46
- Hash[authorizations.map {|auth| [auth.name, auth.to_h]}]
46
+ controllers # triggers controller parsing in case it did not happen before
47
+ SwaggerYard.config.security_definitions.merge(
48
+ Hash[authorizations.map {|auth| [auth.name, auth.to_h]}]
49
+ )
47
50
  end
48
51
 
49
52
  private
@@ -1,89 +1,34 @@
1
1
  module SwaggerYard
2
2
  class Type
3
3
  def self.from_type_list(types)
4
- parts = types.first.split(/[<>]/)
5
- name = parts.last
6
- options = {}
7
- if parts.size > 1
8
- case parts.first
9
- when /^array$/i
10
- options[:array] = true
11
- when /^enum$/i
12
- name = nil
13
- options[:enum] = parts.last.split(/[,|]/)
14
- when /^regexp?$/i
15
- name = 'string'
16
- options[:pattern] = parts.last
17
- when /^object$/i
18
- options[:object] = parts[1..-1]
19
- else
20
- name = parts.first
21
- options[:format] = parts.last
22
- end
23
- end
24
- new(name, options)
4
+ new(types.first)
25
5
  end
26
6
 
27
- attr_reader :name, :array, :enum, :object
7
+ attr_reader :name, :source, :schema
28
8
 
29
- def initialize(name, options = {})
30
- @name = Model.mangle(name) if name
31
- @array = options[:array]
32
- @enum = options[:enum]
33
- @format = options[:format]
34
- @pattern = options[:pattern]
35
- @object = options[:object]
9
+ def initialize(string)
10
+ @source = string
11
+ @schema = TypeParser.new.json_schema(string)
12
+ @name = name_for(@schema)
13
+ @name = name_for(@schema['items']) if @name == 'array'
36
14
  end
37
15
 
38
16
  # TODO: have this look at resource listing?
39
17
  def ref?
40
- /[[:upper:]]/.match(name)
18
+ schema["$ref"]
41
19
  end
42
20
 
43
21
  def model_name
44
22
  ref? ? name : nil
45
23
  end
46
24
 
47
- alias :array? :array
48
- alias :enum? :enum
49
- alias :object? :object
50
-
51
- def json_type
52
- type, format = name, @format
53
- case name
54
- when "float", "double"
55
- type = "number"
56
- format = name
57
- when "date-time", "date", "time", "uuid"
58
- type = "string"
59
- format = name
60
- end
61
-
62
- hsh = { "type" => type }
63
- hsh["format"] = format if format
64
- hsh["pattern"] = @pattern if @pattern
65
- hsh
66
- end
67
-
68
25
  def to_h
69
- type = if ref?
70
- { "$ref" => "#/definitions/#{name}"}
71
- elsif enum?
72
- { "type" => "string", "enum" => @enum }
73
- else
74
- json_type
75
- end
26
+ schema
27
+ end
76
28
 
77
- if array?
78
- { "type" => "array", "items" => type }
79
- elsif object?
80
- {
81
- "type" => "object",
82
- "additionalProperties" => Type.from_type_list([object.join("<")]).to_h
83
- }
84
- else
85
- type
86
- end
29
+ private
30
+ def name_for(schema)
31
+ schema["type"] || schema["$ref"][%r'#/definitions/(.*)', 1]
87
32
  end
88
33
  end
89
34
  end
@@ -0,0 +1,129 @@
1
+ require 'parslet'
2
+
3
+ module SwaggerYard
4
+ class TypeParser
5
+ class Parser < Parslet::Parser
6
+ # Allow for whitespace surrounding a string value
7
+ def spaced(arg)
8
+ space >> str(arg) >> space
9
+ end
10
+
11
+ def stri(str)
12
+ key_chars = str.split(//)
13
+ key_chars.collect! { |char| match["#{char.upcase}#{char.downcase}"] }.
14
+ reduce(:>>)
15
+ end
16
+
17
+ rule(:space) { match[" \n"].repeat }
18
+
19
+ rule(:id_char) { match['-a-zA-Z0-9_'].repeat }
20
+
21
+ rule(:id_start) { match('[a-zA-Z_]') }
22
+
23
+ rule(:name) { id_start >> id_char }
24
+
25
+ rule(:identifier) { name >> (str('::') >> name).repeat }
26
+
27
+ rule(:regexp) { stri('regex') >> match['Pp'].maybe >> space >>
28
+ str('<') >> (str('\\\\') | str('\\>') | match['[^>]']).repeat.as(:regexp) >> str('>') }
29
+
30
+ rule(:enum_list) { name.as(:value) >> (spaced(',') >> name.as(:value)).repeat }
31
+
32
+ rule(:enum) { stri('enum') >> spaced('<') >> enum_list >> spaced('>') }
33
+
34
+ rule(:array) { stri('array') >> spaced('<') >> type >> spaced('>') }
35
+
36
+ rule(:pair) { (name.as(:property) >> spaced(':') >> type.as(:type)).as(:pair) }
37
+
38
+ rule(:pairs) { pair >> (spaced(',') >> pair).repeat >> (spaced(',') >> type.as(:additional)).maybe }
39
+
40
+ rule(:object) { stri('object') >> spaced('<') >> (pairs | type.as(:additional)) >> spaced('>') }
41
+
42
+ rule(:formatted) { name.as(:name) >> spaced('<') >> name.as(:format) >> spaced('>') }
43
+
44
+ rule(:type) { enum.as(:enum) |
45
+ array.as(:array) |
46
+ object.as(:object) |
47
+ formatted.as(:formatted) |
48
+ identifier.as(:identifier) |
49
+ regexp }
50
+
51
+ root :type
52
+ end
53
+
54
+ class Transform < Parslet::Transform
55
+ rule(identifier: simple(:id)) do
56
+ v = id.to_s
57
+ case v
58
+ when /array/i
59
+ { 'type' => 'array', 'items' => { 'type' => 'string' } }
60
+ when /object/i
61
+ { 'type' => 'object' }
62
+ when "float", "double"
63
+ { 'type' => 'number', 'format' => v }
64
+ when "date-time", "date", "time", "uuid"
65
+ { 'type' => 'string', 'format' => v }
66
+ else
67
+ name = Model.mangle(v)
68
+ if /[[:upper:]]/.match(name)
69
+ { '$ref' => "#/definitions/#{name}" }
70
+ else
71
+ { 'type' => name }
72
+ end
73
+ end
74
+ end
75
+
76
+ rule(formatted: { name: simple(:name), format: simple(:format) }) do
77
+ { 'type' => name.to_s, 'format' => format.to_s }
78
+ end
79
+
80
+ rule(regexp: simple(:pattern)) do
81
+ { 'type' => 'string', 'pattern' => pattern.to_s.gsub('\\\\', '\\').gsub('\>', '>') }
82
+ end
83
+
84
+ rule(value: simple(:value)) { value.to_s }
85
+
86
+ rule(enum: subtree(:values)) do
87
+ { 'type' => 'string', 'enum' => Array(values) }
88
+ end
89
+
90
+ rule(array: subtree(:type)) do
91
+ { 'type' => 'array', 'items' => type }
92
+ end
93
+
94
+ rule(pair: { property: simple(:prop), type: subtree(:type) }) do
95
+ { 'properties' => { prop.to_s => type } }
96
+ end
97
+
98
+ rule(additional: subtree(:type)) do
99
+ { 'additionalProperties' => type }
100
+ end
101
+
102
+ rule(object: subtree(:properties)) do
103
+ { 'type' => 'object' }.tap do |result|
104
+ all_props = Array === properties ? properties : [properties]
105
+ props, additional = all_props.partition {|pr| pr['properties'] }
106
+ props.each do |pr|
107
+ result['properties'] = (result['properties'] || {}).merge(pr['properties'])
108
+ end
109
+ result.update additional.first unless additional.empty?
110
+ end
111
+ end
112
+ end
113
+
114
+ def initialize
115
+ @parser = Parser.new
116
+ @xform = Transform.new
117
+ end
118
+
119
+ def parse(str)
120
+ @parser.parse(str)
121
+ end
122
+
123
+ def json_schema(str)
124
+ @xform.apply(parse(str))
125
+ rescue Parslet::ParseFailed => e
126
+ raise ArgumentError, "invalid type: #{e.message}"
127
+ end
128
+ end
129
+ end
@@ -1,3 +1,3 @@
1
1
  module SwaggerYard
2
- VERSION = "0.3.6"
2
+ VERSION = "0.3.7"
3
3
  end
data/lib/swagger_yard.rb CHANGED
@@ -2,6 +2,7 @@ require "yard"
2
2
  require "json"
3
3
  require "swagger_yard/configuration"
4
4
  require "swagger_yard/type"
5
+ require "swagger_yard/type_parser"
5
6
  require "swagger_yard/parameter"
6
7
  require "swagger_yard/property"
7
8
  require "swagger_yard/operation"
metadata CHANGED
@@ -1,125 +1,167 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swagger_yard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - chtrinh (Chris Trinh)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-26 00:00:00.000000000 Z
11
+ date: 2016-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: parslet
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
+ - - ! '>='
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - ">="
45
+ - - ! '>='
32
46
  - !ruby/object:Gem::Version
33
47
  version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - ">="
52
+ - - ! '>='
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - ">="
59
+ - - ! '>='
46
60
  - !ruby/object:Gem::Version
47
61
  version: '0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - ">="
66
+ - - ! '>='
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rspec-its
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - ">="
73
+ - - ! '>='
60
74
  - !ruby/object:Gem::Version
61
75
  version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - ">="
80
+ - - ! '>='
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: apivore
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - ">="
87
+ - - ! '>='
74
88
  - !ruby/object:Gem::Version
75
89
  version: '0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - ">="
94
+ - - ! '>='
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: addressable
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - <=
102
+ - !ruby/object:Gem::Version
103
+ version: 2.4.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - <=
109
+ - !ruby/object:Gem::Version
110
+ version: 2.4.0
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: simplecov
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - ">="
115
+ - - ! '>='
88
116
  - !ruby/object:Gem::Version
89
117
  version: '0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - ">="
122
+ - - ! '>='
95
123
  - !ruby/object:Gem::Version
96
124
  version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: mocha
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
- - - ">="
129
+ - - ! '>='
102
130
  - !ruby/object:Gem::Version
103
131
  version: '0'
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
- - - ">="
136
+ - - ! '>='
109
137
  - !ruby/object:Gem::Version
110
138
  version: '0'
111
139
  - !ruby/object:Gem::Dependency
112
140
  name: bourne
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
- - - ">="
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: wwtd
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ! '>='
116
158
  - !ruby/object:Gem::Version
117
159
  version: '0'
118
160
  type: :development
119
161
  prerelease: false
120
162
  version_requirements: !ruby/object:Gem::Requirement
121
163
  requirements:
122
- - - ">="
164
+ - - ! '>='
123
165
  - !ruby/object:Gem::Version
124
166
  version: '0'
125
167
  description: SwaggerYard API doc gem that uses YARD to parse the docs for a REST rails
@@ -145,6 +187,7 @@ files:
145
187
  - lib/swagger_yard/resource_listing.rb
146
188
  - lib/swagger_yard/swagger.rb
147
189
  - lib/swagger_yard/type.rb
190
+ - lib/swagger_yard/type_parser.rb
148
191
  - lib/swagger_yard/version.rb
149
192
  homepage: http://www.synctv.com
150
193
  licenses:
@@ -156,19 +199,18 @@ require_paths:
156
199
  - lib
157
200
  required_ruby_version: !ruby/object:Gem::Requirement
158
201
  requirements:
159
- - - ">="
202
+ - - ! '>='
160
203
  - !ruby/object:Gem::Version
161
204
  version: '0'
162
205
  required_rubygems_version: !ruby/object:Gem::Requirement
163
206
  requirements:
164
- - - ">="
207
+ - - ! '>='
165
208
  - !ruby/object:Gem::Version
166
209
  version: '0'
167
210
  requirements: []
168
211
  rubyforge_project:
169
- rubygems_version: 2.4.5
212
+ rubygems_version: 2.4.8
170
213
  signing_key:
171
214
  specification_version: 4
172
215
  summary: SwaggerYard API doc through YARD
173
216
  test_files: []
174
- has_rdoc: