swagger_yard 0.3.7 → 0.4.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MjdkMTcwZWU5NTNhNjNhNjA0NzhlN2ZjMWZmMzZlMDUxZTI1NWNiOA==
5
- data.tar.gz: !binary |-
6
- MjAxYzIwNDYyNzc1MjEyMGU0MzIyNjAyZmU5OTI4YjA4MzFmMzRhOA==
2
+ SHA1:
3
+ metadata.gz: ef1f9c99cbcdd6a637a1d68079ba1e2a0b1cb718
4
+ data.tar.gz: 17849b615de17e9ec974f9905202a8097daf0eba
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MDhhNWJkNDJhNWI3ODQyZTI0OGQ3ZmM4ZGE4MzYzMzgwNWU3YmM2N2MyMTAz
10
- NGM3MDVkOTM1MDMwMDYxYTU1MjE4YTUyZWNlZmM0OWY3NjFhYjI0Mzc4ZDFk
11
- ODUxODdkZWQ4YWNiY2Q1YTQ0YjMwODRjMzI3ZDQ0NWQwYWQ1Nzc=
12
- data.tar.gz: !binary |-
13
- NWFkMDRjMGE1MGYzYzE1ZWQ2NGRiMjRiMmZkOWQ5YjliZGYzYWJlZDFjOWE5
14
- YzE2YWM0N2E2MzA4MDI4NzhmNTk0YjA3OTI2ODdjODUyZDU5OGNjNmE5NDBj
15
- OWUyNGEyYTc3OGYyNDhmMTgxOTYzM2YwMzFhOWJmN2JkMTcwNDI=
6
+ metadata.gz: e200703aa74c246766ec9dbeb448ab6fd7f8b036376f82bd8ae60d0c7b6abe4d1d1149ec662c45d4ab1d34af0f38ece20e909a501bcdae78ee9b038687aa1f68
7
+ data.tar.gz: 4877499f45c859a0d75ba2518d425a867f2dc072955c38ea49b5cbcaa13f8bd2322989a15f10cb39de1f8a6191057dfdb25333cdb6eef96bdf9aa339d54032e3
data/README.md CHANGED
@@ -47,6 +47,31 @@ are indicated inside square-brackets (e.g., `[string]`) as part of a YARD tag.
47
47
  `[regex<PATTERN>]`. For example, `[regex<^.{3}$>]` produces JSON
48
48
  `{ "type": "string", "pattern": "^.{3}$" }`.
49
49
 
50
+ ### External Schema ###
51
+
52
+ Types can be specified that refer to external JSON schema documents for their definition. External schema documents are expected to also define their models under a `definitions` top-level key like so:
53
+ ```
54
+ {
55
+ "definitions": {
56
+ "MyStandardModel": {
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ To register an external schema so that it can be referenced in places where you specify a type, configure SwaggerYard as follows:
63
+ ```ruby
64
+ SwaggerYard.configure do |config|
65
+ config.external_schema mymodels: 'https://example.com/mymodels/v1.0'
66
+ end
67
+ ```
68
+
69
+ Then refer to models in the schema using the syntax `[mymodels#MyStandardModel]` where types are specified. This causes SwaggerYard to emit the following schema for the type:
70
+
71
+ ```
72
+ { "$ref": "https://example.com/mymodels/v1.0#/definitions/MyStandardModel" }
73
+ ```
74
+
50
75
  ### Options ###
51
76
 
52
77
  Parameter or property _options_ are expressed inside parenthesis immediately
@@ -11,7 +11,7 @@ module SwaggerYard
11
11
  yard_object.add_tag YARD::Tags::Tag.new("path", path, [method]) if path
12
12
  path
13
13
  rescue => e
14
- YARD::Logger.instance.warn e.message
14
+ SwaggerYard.log.warn e.message
15
15
  nil
16
16
  end
17
17
  end
@@ -41,7 +41,7 @@ module SwaggerYard
41
41
  end
42
42
 
43
43
  if tag = yard_object.tags.detect {|t| t.tag_name == "resource_path"}
44
- log.warn "DEPRECATED: @resource_path tag is obsolete."
44
+ SwaggerYard.log.warn "DEPRECATED: @resource_path tag is obsolete."
45
45
  end
46
46
 
47
47
  # we only have api_key auth, the value for now is always empty array
@@ -9,13 +9,21 @@ module SwaggerYard
9
9
  attr_accessor :security_definitions
10
10
 
11
11
  def initialize
12
- self.swagger_version = "2.0"
13
- self.api_version = "0.1"
14
- self.enable = false
15
- self.reload = true
16
- self.title = "Configure title with SwaggerYard.config.title"
17
- self.description = "Configure description with SwaggerYard.config.description"
18
- self.security_definitions = {}
12
+ @swagger_version = "2.0"
13
+ @api_version = "0.1"
14
+ @enable = false
15
+ @reload = true
16
+ @title = "Configure title with SwaggerYard.config.title"
17
+ @description = "Configure description with SwaggerYard.config.description"
18
+ @security_definitions = {}
19
+ @external_schema = {}
20
+ end
21
+
22
+ def external_schema(mappings = nil)
23
+ mappings.each do |prefix, url|
24
+ @external_schema[prefix.to_s] = url
25
+ end if mappings
26
+ @external_schema
19
27
  end
20
28
 
21
29
  def swagger_spec_base_path=(ignored)
@@ -90,6 +90,12 @@ module SwaggerYard
90
90
  # Example: [GET] /api/v2/ownerships
91
91
  # Example: [PUT] /api/v1/accounts/{account_id}
92
92
  def add_path_params_and_method(tag)
93
+ if @path && @http_method
94
+ SwaggerYard.log.warn 'multiple path tags not supported: ' \
95
+ "ignored [#{tag.types.first}] #{tag.text}"
96
+ return
97
+ end
98
+
93
99
  @path = tag.text
94
100
  @http_method = tag.types.first
95
101
 
@@ -113,6 +119,9 @@ module SwaggerYard
113
119
  existing.param_type = parameter.param_type if parameter.from_path?
114
120
  existing.required ||= parameter.required
115
121
  existing.allow_multiple = parameter.allow_multiple
122
+ elsif parameter.param_type == 'body' && @parameters.detect {|param| param.param_type == 'body'}
123
+ SwaggerYard.log.warn 'multiple body parameters invalid: ' \
124
+ "ignored #{parameter.name} for #{@api.api_declaration.class_name}##{ruby_method}"
116
125
  else
117
126
  @parameters << parameter
118
127
  end
@@ -1,10 +1,11 @@
1
1
  module SwaggerYard
2
2
  class Parameter
3
- attr_accessor :name, :description, :param_type, :required, :allow_multiple
3
+ attr_accessor :name, :type, :description, :param_type, :required, :allow_multiple
4
4
 
5
5
  def self.from_yard_tag(tag, operation)
6
- description = tag.text
7
6
  name, options_string = tag.name.split(/[\(\)]/)
7
+ description = tag.text
8
+ description = name if description.strip.empty?
8
9
  type = Type.from_type_list(tag.types)
9
10
 
10
11
  options = {}
@@ -26,11 +26,13 @@ module SwaggerYard
26
26
 
27
27
  def to_h
28
28
  @type.to_h.tap do |h|
29
- h["description"] = description if description
30
- if @nullable
31
- h["x-nullable"] = true
32
- if h["type"]
33
- h["type"] = [h["type"], "null"]
29
+ unless h['$ref']
30
+ h["description"] = description if description
31
+ if @nullable
32
+ h["x-nullable"] = true
33
+ if h["type"]
34
+ h["type"] = [h["type"], "null"]
35
+ end
34
36
  end
35
37
  end
36
38
  end
@@ -30,12 +30,14 @@ module SwaggerYard
30
30
  end
31
31
 
32
32
  def path_objects
33
- controllers.map(&:apis_hash).reduce({}, :merge)
33
+ controllers.map(&:apis_hash).reduce({}, :merge).tap do |paths|
34
+ warn_duplicate_operations(paths)
35
+ end
34
36
  end
35
37
 
36
38
  # Resources
37
39
  def tag_objects
38
- controllers.map(&:to_tag)
40
+ controllers.sort {|a,b| a.resource.upcase <=> b.resource.upcase}.map(&:to_tag)
39
41
  end
40
42
 
41
43
  def model_objects
@@ -73,5 +75,18 @@ module SwaggerYard
73
75
  end
74
76
  end.flatten.select(&:valid?)
75
77
  end
78
+
79
+ def warn_duplicate_operations(paths)
80
+ operation_ids = []
81
+ paths.each do |path,ops|
82
+ ops.each do |method,op|
83
+ if operation_ids.include?(op['operationId'])
84
+ SwaggerYard.log.warn("duplicate operation #{op['operationId']}")
85
+ next
86
+ end
87
+ operation_ids << op['operationId']
88
+ end
89
+ end
90
+ end
76
91
  end
77
92
  end
@@ -24,6 +24,8 @@ module SwaggerYard
24
24
 
25
25
  rule(:identifier) { name >> (str('::') >> name).repeat }
26
26
 
27
+ rule(:external_identifier) { name.as(:namespace) >> str('#') >> identifier.as(:identifier) }
28
+
27
29
  rule(:regexp) { stri('regex') >> match['Pp'].maybe >> space >>
28
30
  str('<') >> (str('\\\\') | str('\\>') | match['[^>]']).repeat.as(:regexp) >> str('>') }
29
31
 
@@ -45,6 +47,7 @@ module SwaggerYard
45
47
  array.as(:array) |
46
48
  object.as(:object) |
47
49
  formatted.as(:formatted) |
50
+ external_identifier.as(:external_identifier) |
48
51
  identifier.as(:identifier) |
49
52
  regexp }
50
53
 
@@ -73,6 +76,14 @@ module SwaggerYard
73
76
  end
74
77
  end
75
78
 
79
+ rule(external_identifier: { namespace: simple(:namespace), identifier: simple(:identifier) }) do
80
+ prefix, name = namespace.to_s, identifier.to_s
81
+ unless url = SwaggerYard.config.external_schema[prefix]
82
+ raise UndefinedSchemaError, "unknown prefix #{prefix} for #{name}"
83
+ end
84
+ { '$ref' => "#{url}#/definitions/#{Model.mangle(name)}"}
85
+ end
86
+
76
87
  rule(formatted: { name: simple(:name), format: simple(:format) }) do
77
88
  { 'type' => name.to_s, 'format' => format.to_s }
78
89
  end
@@ -123,7 +134,7 @@ module SwaggerYard
123
134
  def json_schema(str)
124
135
  @xform.apply(parse(str))
125
136
  rescue Parslet::ParseFailed => e
126
- raise ArgumentError, "invalid type: #{e.message}"
137
+ raise InvalidTypeError, "'#{str}': #{e.message}"
127
138
  end
128
139
  end
129
140
  end
@@ -1,3 +1,3 @@
1
1
  module SwaggerYard
2
- VERSION = "0.3.7"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/swagger_yard.rb CHANGED
@@ -14,6 +14,10 @@ require "swagger_yard/api"
14
14
  require "swagger_yard/swagger"
15
15
 
16
16
  module SwaggerYard
17
+ class Error < StandardError; end
18
+ class InvalidTypeError < Error; end
19
+ class UndefinedSchemaError < Error; end
20
+
17
21
  class << self
18
22
  ##
19
23
  # Configuration for Swagger Yard, use like:
@@ -33,6 +37,10 @@ module SwaggerYard
33
37
  @configuration ||= Configuration.new
34
38
  end
35
39
 
40
+ def log
41
+ YARD::Logger.instance
42
+ end
43
+
36
44
  #
37
45
  # Use YARD to parse object tags from a file
38
46
  #
metadata CHANGED
@@ -1,167 +1,181 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swagger_yard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.4.0
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-11-29 00:00:00.000000000 Z
11
+ date: 2018-04-05 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
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: parslet
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - "<"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '12'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - "<"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '12'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec-its
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ! '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ! '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: apivore
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - "<"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '1.6'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - "<"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '1.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: nokogiri
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "<"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.8'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "<"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.8'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: addressable
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - <=
115
+ - - "<="
102
116
  - !ruby/object:Gem::Version
103
117
  version: 2.4.0
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - <=
122
+ - - "<="
109
123
  - !ruby/object:Gem::Version
110
124
  version: 2.4.0
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
- - - ! '>='
129
+ - - ">="
116
130
  - !ruby/object:Gem::Version
117
131
  version: '0'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
- - - ! '>='
136
+ - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: mocha
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
- - - ! '>='
143
+ - - ">="
130
144
  - !ruby/object:Gem::Version
131
145
  version: '0'
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
- - - ! '>='
150
+ - - ">="
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: bourne
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
- - - ! '>='
157
+ - - ">="
144
158
  - !ruby/object:Gem::Version
145
159
  version: '0'
146
160
  type: :development
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
- - - ! '>='
164
+ - - ">="
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: wwtd
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
- - - ! '>='
171
+ - - ">="
158
172
  - !ruby/object:Gem::Version
159
173
  version: '0'
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
- - - ! '>='
178
+ - - ">="
165
179
  - !ruby/object:Gem::Version
166
180
  version: '0'
167
181
  description: SwaggerYard API doc gem that uses YARD to parse the docs for a REST rails
@@ -199,17 +213,17 @@ require_paths:
199
213
  - lib
200
214
  required_ruby_version: !ruby/object:Gem::Requirement
201
215
  requirements:
202
- - - ! '>='
216
+ - - ">="
203
217
  - !ruby/object:Gem::Version
204
218
  version: '0'
205
219
  required_rubygems_version: !ruby/object:Gem::Requirement
206
220
  requirements:
207
- - - ! '>='
221
+ - - ">="
208
222
  - !ruby/object:Gem::Version
209
223
  version: '0'
210
224
  requirements: []
211
225
  rubyforge_project:
212
- rubygems_version: 2.4.8
226
+ rubygems_version: 2.6.12
213
227
  signing_key:
214
228
  specification_version: 4
215
229
  summary: SwaggerYard API doc through YARD