skeleton 0.3.3 → 0.4.1
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 +4 -4
- data/.gitignore +1 -0
- data/README.md +140 -65
- data/Rakefile +10 -3
- data/lib/skeleton.rb +6 -10
- data/lib/skeleton/contact.rb +1 -13
- data/lib/skeleton/error.rb +4 -0
- data/lib/skeleton/graph.rb +56 -0
- data/lib/skeleton/header.rb +2 -63
- data/lib/skeleton/items.rb +34 -0
- data/lib/skeleton/license.rb +1 -12
- data/lib/skeleton/model.rb +13 -17
- data/lib/skeleton/operation.rb +50 -121
- data/lib/skeleton/parameter.rb +31 -88
- data/lib/skeleton/parameters.rb +40 -0
- data/lib/skeleton/path.rb +42 -80
- data/lib/skeleton/presenter.rb +19 -0
- data/lib/skeleton/property.rb +6 -0
- data/lib/skeleton/response.rb +24 -45
- data/lib/skeleton/schema.rb +80 -63
- data/lib/skeleton/scope.rb +18 -0
- data/lib/skeleton/security_scheme.rb +19 -37
- data/lib/skeleton/serializers/options.rb +215 -0
- data/lib/skeleton/serializers/swagger.rb +197 -0
- data/lib/skeleton/structure.rb +92 -138
- data/lib/skeleton/swagger.rb +9 -0
- data/lib/skeleton/tag.rb +11 -16
- data/lib/skeleton/version.rb +1 -1
- data/skeleton.gemspec +2 -0
- data/test/fixtures/json-schema-draft-04.json +150 -0
- data/test/fixtures/schema.json +1482 -0
- data/test/integrations/validate_complex_schema_spec.rb +42 -0
- data/test/skeleton/graph_test.rb +22 -0
- data/test/skeleton/mapper_test.rb +84 -0
- data/test/skeleton/operation_test.rb +11 -0
- data/test/skeleton/parameter_test.rb +34 -0
- data/test/skeleton/parameters_test.rb +9 -0
- data/test/skeleton/path_test.rb +46 -0
- data/test/skeleton/property_test.rb +8 -0
- data/test/skeleton/serializers/options_test.rb +68 -0
- data/test/skeleton/serializers/swagger_test.rb +30 -0
- data/test/support/factories/structure_factory.rb +86 -0
- data/test/support/fixtures.rb +6 -0
- data/test/support/kissmetrics/core_api.rb +542 -0
- data/{spec/spec_helper.rb → test/test_helper.rb} +7 -1
- metadata +73 -25
- data/lib/skeleton/config.rb +0 -37
- data/lib/skeleton/documentation.rb +0 -17
- data/lib/skeleton/example.rb +0 -31
- data/lib/skeleton/headers.rb +0 -50
- data/lib/skeleton/helpers/controller_helpers.rb +0 -25
- data/lib/skeleton/info.rb +0 -40
- data/lib/skeleton/item.rb +0 -99
- data/lib/skeleton/responses.rb +0 -59
- data/lib/skeleton/scopes.rb +0 -24
- data/lib/skeleton/security_definitions.rb +0 -46
- data/lib/skeleton/security_requirement.rb +0 -29
- data/spec/integrations/use_case_spec.rb +0 -131
- data/spec/skeleton/operation_spec.rb +0 -113
- data/spec/skeleton/serializers/contact_spec.rb +0 -30
- data/spec/skeleton/serializers/documentation_spec.rb +0 -23
- data/spec/skeleton/serializers/header_spec.rb +0 -57
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'skeleton/attributes'
|
2
|
+
module Skeleton
|
3
|
+
class Scope
|
4
|
+
extend Skeleton::Attributes
|
5
|
+
|
6
|
+
attr_accessor :name, :description
|
7
|
+
attr_presence :name, :description
|
8
|
+
|
9
|
+
def initialize(args={})
|
10
|
+
args.each do |k, v|
|
11
|
+
setter = "#{k}="
|
12
|
+
self.send(setter, v) if self.respond_to?(setter)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :describe, :description=
|
17
|
+
end
|
18
|
+
end
|
@@ -1,47 +1,29 @@
|
|
1
|
-
require 'skeleton/
|
2
|
-
require 'skeleton/
|
1
|
+
require 'skeleton/attributes'
|
2
|
+
require 'skeleton/scope'
|
3
3
|
|
4
4
|
module Skeleton
|
5
|
-
class SecurityScheme
|
6
|
-
|
7
|
-
:token_url, :scopes
|
5
|
+
class SecurityScheme
|
6
|
+
extend Skeleton::Attributes
|
8
7
|
|
9
|
-
|
10
|
-
|
8
|
+
attr_accessor :type, :description, :name, :location, :flow,
|
9
|
+
:authorization_url, :token_url
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
when Hash
|
15
|
-
@scopes = Skeleton::Scopes.new(value)
|
16
|
-
else
|
17
|
-
@scopes = value
|
18
|
-
end
|
19
|
-
end
|
11
|
+
attr_presence :type, :description, :name, :location, :flow,
|
12
|
+
:authorization_url, :token_url
|
20
13
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
hash[:authorization_url] = authorization_url if authorization_url?
|
29
|
-
hash[:token_url] = token_url if token_url?
|
30
|
-
hash[:scopes] = scopes.to_h if scopes?
|
31
|
-
hash
|
14
|
+
def initialize(args={})
|
15
|
+
@scopes = {}
|
16
|
+
|
17
|
+
args.each do |k, v|
|
18
|
+
setter = "#{k}="
|
19
|
+
self.send(setter, v) if self.respond_to?(setter)
|
20
|
+
end
|
32
21
|
end
|
33
22
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
hash[:name] = name if name?
|
39
|
-
hash[:location] = location if location?
|
40
|
-
hash[:flow] = flow if flow?
|
41
|
-
hash[:authorizationUrl] = authorization_url if authorization_url?
|
42
|
-
hash[:tokenUrl] = token_url if token_url?
|
43
|
-
hash[:scopes] = scopes.to_swagger_hash if scopes?
|
44
|
-
hash
|
23
|
+
def define_scope(name, &block)
|
24
|
+
@scopes[name] = Skeleton::Scope.new
|
25
|
+
@scopes[name].instance_eval(&block)
|
26
|
+
@scopes[name]
|
45
27
|
end
|
46
28
|
end
|
47
29
|
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'skeleton/error'
|
3
|
+
require 'skeleton/graph'
|
4
|
+
|
5
|
+
module Skeleton
|
6
|
+
module Serializers
|
7
|
+
class Options
|
8
|
+
attr_reader :structure
|
9
|
+
|
10
|
+
def initialize(structure, options={})
|
11
|
+
@structure = structure
|
12
|
+
|
13
|
+
@path = options[:path] || raise(Skeleton::Error, ':path is required')
|
14
|
+
@definition_path = options[:definitions] || '#/definitions'
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(*)
|
19
|
+
MultiJson.dump(to_h)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_h
|
23
|
+
graph = Skeleton::Graph.new
|
24
|
+
structure.models.each do |name, model|
|
25
|
+
graph.register(name, dependencies_for(model))
|
26
|
+
end
|
27
|
+
|
28
|
+
hash = {
|
29
|
+
consumes: structure.consumes.map(&:to_s),
|
30
|
+
produces: structure.produces.map(&:to_s)
|
31
|
+
}
|
32
|
+
|
33
|
+
if structure.parameters?
|
34
|
+
hash[:parameters] = {}
|
35
|
+
structure.parameters.each do |name, parameter|
|
36
|
+
hash[:parameters][name] = parameter_to_h(parameter)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if structure.responses?
|
41
|
+
hash[:responses] = {}
|
42
|
+
structure.responses.each do |name, response|
|
43
|
+
hash[:responses][name] = response_to_h(response)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if structure.secure?
|
48
|
+
hash[:security_definitions] = {},
|
49
|
+
hash[:security] = []
|
50
|
+
end
|
51
|
+
|
52
|
+
hash[:tags] = structure.tags.map do |name, tag|
|
53
|
+
sub = {
|
54
|
+
name: name
|
55
|
+
}
|
56
|
+
sub[:description] = tag.description if tag.description?
|
57
|
+
sub[:external_docs] = tag.external_docs if tag.external_docs?
|
58
|
+
sub
|
59
|
+
end
|
60
|
+
|
61
|
+
path = structure.paths.fetch(@path) { raise(Skeleton::Error, "path '#{@path}' not found in structure") }
|
62
|
+
hash[:operations] ||= {}
|
63
|
+
path.operations.each do |verb, operation|
|
64
|
+
hash[:operations][verb] = operation_to_h(operation)
|
65
|
+
end
|
66
|
+
|
67
|
+
hash[:definitions] ||= {}
|
68
|
+
|
69
|
+
dependencies.to_a.each do |dep|
|
70
|
+
graph.each_dependent_for(dep) do |name|
|
71
|
+
hash[:definitions][name] = schema_to_h(structure.models[name])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
hash
|
76
|
+
end
|
77
|
+
|
78
|
+
def dependencies
|
79
|
+
@definitions ||= Set.new
|
80
|
+
end
|
81
|
+
|
82
|
+
def register_dependent(name)
|
83
|
+
dependencies.add(name)
|
84
|
+
end
|
85
|
+
|
86
|
+
def dependencies_for(schema, set=Set.new)
|
87
|
+
return set if schema.nil?
|
88
|
+
|
89
|
+
if schema.ref?
|
90
|
+
return set if set.include?(schema.ref)
|
91
|
+
set.add(schema.ref)
|
92
|
+
end
|
93
|
+
|
94
|
+
schema.properties.each do |field, property|
|
95
|
+
set.merge(dependencies_for(property))
|
96
|
+
end
|
97
|
+
|
98
|
+
set.merge(dependencies_for(schema.items)) if schema.items?
|
99
|
+
|
100
|
+
set.to_a
|
101
|
+
end
|
102
|
+
|
103
|
+
def definition_reference(name)
|
104
|
+
'%s/%s' % [@definition_path, name]
|
105
|
+
end
|
106
|
+
|
107
|
+
def parameter_to_h(parameter)
|
108
|
+
hash = {
|
109
|
+
name: parameter.name,
|
110
|
+
in: parameter.location,
|
111
|
+
required: parameter.required?
|
112
|
+
}.merge(schema_to_h(parameter))
|
113
|
+
|
114
|
+
hash[:schema] = schema_to_h(parameter.schema) if parameter.schema?
|
115
|
+
hash
|
116
|
+
end
|
117
|
+
|
118
|
+
def items_to_h(items)
|
119
|
+
return nil if items.nil?
|
120
|
+
hash = {
|
121
|
+
type: items.type
|
122
|
+
}
|
123
|
+
hash[:format] = items.format if items.format?
|
124
|
+
if items.array?
|
125
|
+
hash[:items] = items_to_h(items)
|
126
|
+
hash[:collectionFormat] = items.collection_format
|
127
|
+
end
|
128
|
+
hash.merge(schema_to_h(items))
|
129
|
+
hash
|
130
|
+
end
|
131
|
+
|
132
|
+
def schema_to_h(schema)
|
133
|
+
hash = {}
|
134
|
+
|
135
|
+
return hash if schema.nil?
|
136
|
+
|
137
|
+
if schema.ref?
|
138
|
+
hash['$ref'] = definition_reference(schema.ref)
|
139
|
+
dependencies.merge(dependencies_for(schema))
|
140
|
+
dependencies.add(schema.ref)
|
141
|
+
end
|
142
|
+
|
143
|
+
hash[:description] = schema.description if schema.description?
|
144
|
+
hash[:default] = schema.default if schema.default?
|
145
|
+
hash[:maximum] = schema.maximum if schema.maximum?
|
146
|
+
hash[:exclusive_maximum] = !!schema.exclusive_maximum if schema.exclusive_maximum?
|
147
|
+
hash[:minimum] = schema.minimum if schema.minimum?
|
148
|
+
hash[:exclusive_minimum] = !!schema.exclusive_minimum if schema.exclusive_minimum?
|
149
|
+
hash[:max_length] = schema.max_length if schema.max_length?
|
150
|
+
hash[:min_length] = schema.min_length if schema.min_length?
|
151
|
+
hash[:pattern] = schema.pattern if schema.pattern?
|
152
|
+
hash[:max_items] = schema.max_items if schema.max_items?
|
153
|
+
hash[:min_items] = schema.min_items if schema.min_items?
|
154
|
+
hash[:unique_items] = !!schema.unique_items if schema.unique_items?
|
155
|
+
hash[:enum] = schema.enum.map(&:to_s) unless schema.enum.empty?
|
156
|
+
hash[:multiple_of] = schema.multiple_of if schema.multiple_of?
|
157
|
+
hash[:type] = schema.type if schema.type
|
158
|
+
|
159
|
+
if schema.properties?
|
160
|
+
hash[:properties] = {}
|
161
|
+
schema.properties.each do |name, prop|
|
162
|
+
hash[:properties][name] = schema_to_h(prop)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
if schema.items?
|
167
|
+
hash[:items] = schema_to_h(schema.items)
|
168
|
+
end
|
169
|
+
hash
|
170
|
+
end
|
171
|
+
|
172
|
+
def response_to_h(response)
|
173
|
+
hash = {
|
174
|
+
description: response.description
|
175
|
+
}
|
176
|
+
if response.schema?
|
177
|
+
hash[:schema] = schema_to_h(response.schema)
|
178
|
+
end
|
179
|
+
|
180
|
+
hash[:headers] = {}
|
181
|
+
response.headers.each do |field, header|
|
182
|
+
hash[:headers][field] = schema_to_h(header)
|
183
|
+
end
|
184
|
+
hash
|
185
|
+
end
|
186
|
+
|
187
|
+
def operation_to_h(operation)
|
188
|
+
hash = {
|
189
|
+
tags: operation.tags,
|
190
|
+
summary: operation.summary,
|
191
|
+
description: operation.description,
|
192
|
+
responses: {}
|
193
|
+
}
|
194
|
+
|
195
|
+
hash[:deprecated] = true if operation.deprecated?
|
196
|
+
hash[:operation_id] = operation.id if operation.id?
|
197
|
+
hash[:consumes] = operation.consumes if operation.consumes?
|
198
|
+
hash[:produces] = operation.produces if operation.produces?
|
199
|
+
|
200
|
+
operation.responses.each do |status, response|
|
201
|
+
hash[:responses][status] = response_to_h(response)
|
202
|
+
end
|
203
|
+
|
204
|
+
if operation.parameters?
|
205
|
+
hash[:parameters] = operation.parameters.map do |parameter|
|
206
|
+
parameter_to_h(parameter)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
hash
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Skeleton
|
4
|
+
module Serializers
|
5
|
+
class Swagger
|
6
|
+
attr_reader :structure
|
7
|
+
|
8
|
+
def initialize(structure)
|
9
|
+
@structure = structure
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_json(*)
|
13
|
+
MultiJson.dump(to_h)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
hash = {
|
18
|
+
swagger: '2.0',
|
19
|
+
info: {
|
20
|
+
title: structure.title,
|
21
|
+
description: structure.description,
|
22
|
+
version: structure.version,
|
23
|
+
termsOfService: structure.terms,
|
24
|
+
contact: {
|
25
|
+
name: structure.contact.name,
|
26
|
+
email: structure.contact.email,
|
27
|
+
url: structure.contact.url
|
28
|
+
},
|
29
|
+
license: {
|
30
|
+
name: structure.license.name,
|
31
|
+
url: structure.license.url
|
32
|
+
}
|
33
|
+
},
|
34
|
+
basePath: structure.base_path,
|
35
|
+
host: structure.host,
|
36
|
+
schemes: structure.schemes.map(&:to_s),
|
37
|
+
consumes: structure.consumes.map(&:to_s),
|
38
|
+
produces: structure.produces.map(&:to_s)
|
39
|
+
}
|
40
|
+
|
41
|
+
if structure.parameters?
|
42
|
+
hash[:parameters] = {}
|
43
|
+
structure.parameters.each do |name, parameter|
|
44
|
+
hash[:parameters][name] = parameter_to_h(parameter)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if structure.responses?
|
49
|
+
hash[:responses] = {}
|
50
|
+
structure.responses.each do |name, response|
|
51
|
+
hash[:responses][name] = response_to_h(response)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if structure.secure?
|
56
|
+
hash[:securityDefinitions] = {},
|
57
|
+
hash[:security] = []
|
58
|
+
end
|
59
|
+
|
60
|
+
hash[:tags] = structure.tags.map do |name, tag|
|
61
|
+
sub = {
|
62
|
+
name: name
|
63
|
+
}
|
64
|
+
sub[:description] = tag.description if tag.description?
|
65
|
+
sub[:externalDocs] = tag.external_docs if tag.external_docs?
|
66
|
+
sub
|
67
|
+
end
|
68
|
+
|
69
|
+
if structure.external_docs
|
70
|
+
hash[:externalDocs] = structure.external_docs
|
71
|
+
end
|
72
|
+
|
73
|
+
hash[:paths] = {}
|
74
|
+
structure.paths.each do |resource, path|
|
75
|
+
hash[:paths][resource] = {}
|
76
|
+
|
77
|
+
path.operations.each do |verb, operation|
|
78
|
+
hash[:paths][resource][verb] = operation_to_h(operation)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
hash[:definitions] = {}
|
83
|
+
structure.models.each do |name, model|
|
84
|
+
hash[:definitions][name] = schema_to_h(model)
|
85
|
+
end
|
86
|
+
|
87
|
+
hash
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def definition_ref(name)
|
93
|
+
'#/definitions/%s' % [name]
|
94
|
+
end
|
95
|
+
|
96
|
+
def parameter_to_h(parameter)
|
97
|
+
hash = {
|
98
|
+
name: parameter.name,
|
99
|
+
in: parameter.location,
|
100
|
+
required: parameter.required?
|
101
|
+
}.merge(schema_to_h(parameter))
|
102
|
+
hash[:schema] = schema_to_h(parameter.schema) if parameter.schema?
|
103
|
+
hash
|
104
|
+
end
|
105
|
+
|
106
|
+
def items_to_h(items)
|
107
|
+
return nil if items.nil?
|
108
|
+
hash = {
|
109
|
+
type: items.type
|
110
|
+
}
|
111
|
+
hash[:format] = items.format if items.format?
|
112
|
+
if items.array?
|
113
|
+
hash[:items] = items_to_h(items)
|
114
|
+
hash[:collectionFormat] = items.collection_format
|
115
|
+
end
|
116
|
+
hash.merge(schema_to_h(items))
|
117
|
+
hash
|
118
|
+
end
|
119
|
+
|
120
|
+
def schema_to_h(schema)
|
121
|
+
hash = {}
|
122
|
+
return hash if schema.nil?
|
123
|
+
|
124
|
+
hash['$ref'] = definition_ref(schema.ref) if schema.ref?
|
125
|
+
hash[:description] = schema.description if schema.description?
|
126
|
+
hash[:default] = schema.default if schema.default?
|
127
|
+
hash[:maximum] = schema.maximum if schema.maximum?
|
128
|
+
hash[:exclusiveMaximum] = !!schema.exclusive_maximum if schema.exclusive_maximum?
|
129
|
+
hash[:minimum] = schema.minimum if schema.minimum?
|
130
|
+
hash[:exclusiveMinimum] = !!schema.exclusive_minimum if schema.exclusive_minimum?
|
131
|
+
hash[:maxLength] = schema.max_length if schema.max_length?
|
132
|
+
hash[:minLength] = schema.min_length if schema.min_length?
|
133
|
+
hash[:pattern] = schema.pattern if schema.pattern?
|
134
|
+
hash[:maxItems] = schema.max_items if schema.max_items?
|
135
|
+
hash[:minItems] = schema.min_items if schema.min_items?
|
136
|
+
hash[:uniqueItems] = !!schema.unique_items if schema.unique_items?
|
137
|
+
hash[:enum] = schema.enum.map(&:to_s) unless schema.enum.empty?
|
138
|
+
hash[:multipleOf] = schema.multiple_of if schema.multiple_of?
|
139
|
+
hash[:type] = schema.type if schema.type
|
140
|
+
|
141
|
+
if schema.properties?
|
142
|
+
hash[:properties] = {}
|
143
|
+
schema.properties.each do |name, prop|
|
144
|
+
hash[:properties][name] = schema_to_h(prop)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
if schema.items?
|
149
|
+
hash[:items] = schema_to_h(schema.items)
|
150
|
+
end
|
151
|
+
hash
|
152
|
+
end
|
153
|
+
|
154
|
+
def response_to_h(response)
|
155
|
+
hash = {
|
156
|
+
description: response.description
|
157
|
+
}
|
158
|
+
if response.schema?
|
159
|
+
hash[:schema] = schema_to_h(response.schema)
|
160
|
+
end
|
161
|
+
|
162
|
+
hash[:headers] = {}
|
163
|
+
response.headers.each do |field, header|
|
164
|
+
hash[:headers][field] = schema_to_h(header)
|
165
|
+
end
|
166
|
+
hash
|
167
|
+
end
|
168
|
+
|
169
|
+
def operation_to_h(operation)
|
170
|
+
hash = {
|
171
|
+
tags: operation.tags,
|
172
|
+
summary: operation.summary,
|
173
|
+
description: operation.description,
|
174
|
+
responses: {}
|
175
|
+
}
|
176
|
+
|
177
|
+
hash[:deprecated] = true if operation.deprecated?
|
178
|
+
hash[:operationId] = operation.id if operation.id?
|
179
|
+
hash[:consumes] = operation.consumes if operation.consumes?
|
180
|
+
hash[:produces] = operation.produces if operation.produces?
|
181
|
+
|
182
|
+
operation.responses.each do |status, response|
|
183
|
+
hash[:responses][status] = response_to_h(response)
|
184
|
+
end
|
185
|
+
|
186
|
+
if operation.parameters?
|
187
|
+
hash[:parameters] = operation.parameters.map do |parameter|
|
188
|
+
parameter_to_h(parameter)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
hash
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|