sinatra-swagger-exposer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.asciidoc +75 -0
- data/Rakefile +9 -0
- data/example/Gemfile +4 -0
- data/example/Gemfile.lock +19 -0
- data/example/config.ru +2 -0
- data/example/petstore.rb +102 -0
- data/lib/sinatra/swagger-exposer/swagger-content-creator.rb +58 -0
- data/lib/sinatra/swagger-exposer/swagger-endpoint-parameter.rb +105 -0
- data/lib/sinatra/swagger-exposer/swagger-endpoint-response.rb +61 -0
- data/lib/sinatra/swagger-exposer/swagger-endpoint.rb +75 -0
- data/lib/sinatra/swagger-exposer/swagger-exposer.rb +182 -0
- data/lib/sinatra/swagger-exposer/swagger-info.rb +67 -0
- data/lib/sinatra/swagger-exposer/swagger-invalid-exception.rb +16 -0
- data/lib/sinatra/swagger-exposer/swagger-type-property.rb +72 -0
- data/lib/sinatra/swagger-exposer/swagger-type.rb +101 -0
- data/lib/sinatra/swagger-exposer/swagger-utilities.rb +85 -0
- data/lib/sinatra/swagger-exposer/version.rb +5 -0
- data/sinatra-swagger-exposer.gemspec +27 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b55ef98d692d8d3d3b6d27a92b7a30657d5729bb
|
4
|
+
data.tar.gz: a34f58471cf590358e549b51ac348829b269b1ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fe4a2405064efbde281a34810dc78680a3a4ba484cc281f3045ef12211cf8470baadb171db8bb6fdfd53faa11bbb178a3cd3d60a3deb21283bcac17cff3af910
|
7
|
+
data.tar.gz: 86f6a2d376446ed4a59e5d1049955f1cacc2eb0334895d116ab42fcdd891618863a30b5264ec81983d7ff3c453ad4e446dc9de4bb3c5bdb8cef4773c39d7eaca
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Julien Kirch
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.asciidoc
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Sinatra::SwaggerExposer
|
2
|
+
|
3
|
+
image:https://codeclimate.com/github/archiloque/sinatra-swagger-exposer/badges/gpa.svg["Code status", link=https://codeclimate.com/github/archiloque/sinatra-swagger-exposer]
|
4
|
+
image:https://travis-ci.org/archiloque/sinatra-swagger-exposer.svg?branch=master["Build Status", link="https://travis-ci.org/archiloque/sinatra-swagger-exposer"]
|
5
|
+
image:https://coveralls.io/repos/archiloque/sinatra-swagger-exposer/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/r/archiloque/sinatra-swagger-exposer?branch=master"]
|
6
|
+
|
7
|
+
Create Swagger endpoint for your Sinatra application.
|
8
|
+
|
9
|
+
This Sinatra extension enable you to add metadata to your code and to expose your API as a Swagger endpoint.
|
10
|
+
|
11
|
+
I'm adding features as I need them and it currently doesn't use all the Swagger options, so if you need one that is missing please open an issue or contribute.
|
12
|
+
|
13
|
+
## Design choices
|
14
|
+
|
15
|
+
- All the declarations are validated when the server is started
|
16
|
+
- The declarations are defined to look as ruby-ish as possible
|
17
|
+
|
18
|
+
To use it in your app :
|
19
|
+
|
20
|
+
[source,ruby]
|
21
|
+
----
|
22
|
+
require 'sinatra/swagger-exposer/swagger-exposer'
|
23
|
+
|
24
|
+
class MyApp < Sinatra::Base
|
25
|
+
|
26
|
+
register Sinatra::SwaggerExposer
|
27
|
+
|
28
|
+
general_info(
|
29
|
+
{
|
30
|
+
version: '0.0.1',
|
31
|
+
title: 'May app',
|
32
|
+
description: 'My wonderful app',
|
33
|
+
license: {
|
34
|
+
name: 'MIT',
|
35
|
+
url: 'http://opensource.org/licenses/MIT'
|
36
|
+
}
|
37
|
+
}
|
38
|
+
)
|
39
|
+
|
40
|
+
type 'Status',
|
41
|
+
{
|
42
|
+
:properties => {
|
43
|
+
:status => {
|
44
|
+
:type => String,
|
45
|
+
:example => 'OK,
|
46
|
+
},
|
47
|
+
},
|
48
|
+
:required => [:status]
|
49
|
+
}
|
50
|
+
|
51
|
+
endpoint_description 'Base method to ping'
|
52
|
+
endpoint_response 200, 'Standard response', 'Status'
|
53
|
+
endpoint_tags 'Ping'
|
54
|
+
get '/' do
|
55
|
+
json({'status' => 'OK'})
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
----
|
60
|
+
|
61
|
+
The swagger json endpoint will be exposed at `/swagger_doc.json`.
|
62
|
+
|
63
|
+
## Detailed example
|
64
|
+
|
65
|
+
A more complete example is available link:https://github.com/archiloque/sinatra-swagger-exposer/tree/master/example[here].
|
66
|
+
|
67
|
+
## Resources
|
68
|
+
|
69
|
+
- link:https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md[Swagger RESTful API Documentation Specification].
|
70
|
+
- link:https://github.com/swagger-api/swagger-spec/tree/master/examples/v2.0/json[Swagger json examples].
|
71
|
+
- link:https://raw.githubusercontent.com/swagger-api/swagger-spec/master/schemas/v2.0/schema.json[The swagger json schema].
|
72
|
+
|
73
|
+
## License
|
74
|
+
|
75
|
+
This software is released under the MIT license.
|
data/Rakefile
ADDED
data/example/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
rack (1.6.0)
|
5
|
+
rack-protection (1.5.3)
|
6
|
+
rack
|
7
|
+
sinatra (1.4.6)
|
8
|
+
rack (~> 1.4)
|
9
|
+
rack-protection (~> 1.4)
|
10
|
+
tilt (>= 1.3, < 3)
|
11
|
+
sinatra-cross_origin (0.3.2)
|
12
|
+
tilt (2.0.1)
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
ruby
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
sinatra (~> 1.4.5)
|
19
|
+
sinatra-cross_origin (~> 0.3.2)
|
data/example/config.ru
ADDED
data/example/petstore.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'json'
|
3
|
+
require 'sinatra/cross_origin'
|
4
|
+
|
5
|
+
require_relative '../lib/sinatra/swagger-exposer/swagger-exposer'
|
6
|
+
|
7
|
+
class Petstore < Sinatra::Base
|
8
|
+
|
9
|
+
set :logging, true
|
10
|
+
|
11
|
+
register Sinatra::CrossOrigin
|
12
|
+
set :allow_origin, :any
|
13
|
+
enable :cross_origin
|
14
|
+
|
15
|
+
register Sinatra::SwaggerExposer
|
16
|
+
|
17
|
+
general_info(
|
18
|
+
{
|
19
|
+
:version => '1.0.0',
|
20
|
+
:title => 'Swagger Petstore',
|
21
|
+
:description => 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification',
|
22
|
+
:termsOfService => 'http://swagger.io/terms/',
|
23
|
+
:contact => {:name => 'Swagger API Team',
|
24
|
+
:email => 'apiteam@swagger.io',
|
25
|
+
:url => 'http://swagger.io'
|
26
|
+
},
|
27
|
+
:license => {
|
28
|
+
:name => 'Apache 2.0',
|
29
|
+
:url => 'http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT'
|
30
|
+
}
|
31
|
+
}
|
32
|
+
)
|
33
|
+
|
34
|
+
type 'Error', {
|
35
|
+
:required => [:code, :message],
|
36
|
+
:properties => {
|
37
|
+
:code => {
|
38
|
+
:type => Integer,
|
39
|
+
:example => 404,
|
40
|
+
:description => 'The error code',
|
41
|
+
},
|
42
|
+
:message => {
|
43
|
+
:type => String,
|
44
|
+
:example => 'Pet not found',
|
45
|
+
:description => 'The error message',
|
46
|
+
},
|
47
|
+
},
|
48
|
+
}
|
49
|
+
|
50
|
+
|
51
|
+
type 'Pet', {
|
52
|
+
:required => [:id, :name],
|
53
|
+
:properties => {
|
54
|
+
:id => {
|
55
|
+
:type => Integer,
|
56
|
+
:format => 'int64',
|
57
|
+
},
|
58
|
+
:name => {
|
59
|
+
:type => String,
|
60
|
+
:example => 'doggie',
|
61
|
+
:description => 'The pet name',
|
62
|
+
},
|
63
|
+
:photoUrls => {
|
64
|
+
:type => [String],
|
65
|
+
},
|
66
|
+
:tags => {
|
67
|
+
:type => [String],
|
68
|
+
:description => 'The pet\'s tags',
|
69
|
+
},
|
70
|
+
:status => {
|
71
|
+
:type => String,
|
72
|
+
:description => 'pet status in the store',
|
73
|
+
:example => 'sleepy',
|
74
|
+
},
|
75
|
+
},
|
76
|
+
}
|
77
|
+
|
78
|
+
endpoint_summary 'Finds all the pets'
|
79
|
+
endpoint_description 'Returns all pets from the system that the user has access to'
|
80
|
+
endpoint_tags 'Pets'
|
81
|
+
endpoint_response 200, ['Pet'], 'Standard response'
|
82
|
+
get '/pets' do
|
83
|
+
content_type :json
|
84
|
+
[].to_json
|
85
|
+
end
|
86
|
+
|
87
|
+
endpoint_summary 'Finds a pet by its id'
|
88
|
+
endpoint_description 'Finds a pet by its id, or 404 if the user does not have access to the pet'
|
89
|
+
endpoint_tags 'Pets'
|
90
|
+
endpoint_response 200, 'Pet', 'Standard response'
|
91
|
+
endpoint_response 404, 'Error', 'Pet not found'
|
92
|
+
endpoint_parameter :id, 'The pet id', :path, true, String
|
93
|
+
{
|
94
|
+
:example => 'AMZ',
|
95
|
+
}
|
96
|
+
get '/pets/:id' do
|
97
|
+
content_type :json
|
98
|
+
[404, {:code => 404, :message => 'Pet not found'}]
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative 'swagger-utilities'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
|
5
|
+
module SwaggerExposer
|
6
|
+
|
7
|
+
# Create the swagger content
|
8
|
+
class SwaggerContentCreator
|
9
|
+
|
10
|
+
include SwaggerUtilities
|
11
|
+
|
12
|
+
def initialize(swagger_info, swagger_types, swagger_endpoints)
|
13
|
+
@swagger_info = swagger_info
|
14
|
+
@swagger_types = swagger_types
|
15
|
+
@swagger_endpoints = swagger_endpoints
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_swagger
|
19
|
+
result = {
|
20
|
+
swagger: '2.0',
|
21
|
+
consumes: ['application/json'],
|
22
|
+
produces: ['application/json'],
|
23
|
+
}
|
24
|
+
if @swagger_info
|
25
|
+
result[:info] = @swagger_info.to_swagger
|
26
|
+
end
|
27
|
+
|
28
|
+
unless @swagger_types.empty?
|
29
|
+
result[:definitions] = hash_to_swagger(@swagger_types)
|
30
|
+
end
|
31
|
+
|
32
|
+
unless @swagger_endpoints.empty?
|
33
|
+
result_endpoints = {}
|
34
|
+
|
35
|
+
# swagger need the endpoints to be grouped by path
|
36
|
+
endpoints_by_path = @swagger_endpoints.group_by { |endpoint| endpoint.path }
|
37
|
+
endpoints_by_path.keys.sort.each do |path|
|
38
|
+
endpoints = endpoints_by_path[path]
|
39
|
+
|
40
|
+
result_endpoints_for_path = {}
|
41
|
+
endpoints.each do |endpoint|
|
42
|
+
result_endpoints_for_path[endpoint.type] = endpoint.to_swagger
|
43
|
+
end
|
44
|
+
|
45
|
+
result_endpoints[path] = result_endpoints_for_path
|
46
|
+
|
47
|
+
end
|
48
|
+
result[:paths] = result_endpoints
|
49
|
+
end
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require_relative 'swagger-invalid-exception'
|
2
|
+
require_relative 'swagger-utilities'
|
3
|
+
|
4
|
+
module Sinatra
|
5
|
+
|
6
|
+
module SwaggerExposer
|
7
|
+
|
8
|
+
class SwaggerEndpointParameter
|
9
|
+
|
10
|
+
include SwaggerUtilities
|
11
|
+
|
12
|
+
HOW_TO_PASS_BODY = 'body'
|
13
|
+
HOW_TO_PASS= ['path', 'query', 'header', 'formData'] + [HOW_TO_PASS_BODY]
|
14
|
+
PRIMITIVE_TYPES_FOR_NON_BODY = ['string', 'number', 'integer', 'boolean']
|
15
|
+
|
16
|
+
def initialize(name, description, how_to_pass, required, type, params, known_types)
|
17
|
+
unless name.is_a?(String) || name.is_a?(Symbol)
|
18
|
+
raise SwaggerInvalidException.new("Name [#{name}] should be a string or a symbol")
|
19
|
+
end
|
20
|
+
name = name.to_s
|
21
|
+
if name.empty?
|
22
|
+
raise SwaggerInvalidException.new('Name should not be empty')
|
23
|
+
end
|
24
|
+
@name = name
|
25
|
+
|
26
|
+
if description
|
27
|
+
@description = description
|
28
|
+
end
|
29
|
+
|
30
|
+
how_to_pass = how_to_pass.to_s
|
31
|
+
unless HOW_TO_PASS.include? how_to_pass
|
32
|
+
raise SwaggerInvalidException.new("Unknown how to pass value [#{how_to_pass}], registered types are #{HOW_TO_PASS.join(', ')}")
|
33
|
+
end
|
34
|
+
@how_to_pass = how_to_pass
|
35
|
+
|
36
|
+
if @how_to_pass == HOW_TO_PASS_BODY
|
37
|
+
get_type(type, PRIMITIVE_TYPES + known_types)
|
38
|
+
else
|
39
|
+
get_type(type, PRIMITIVE_TYPES_FOR_NON_BODY)
|
40
|
+
end
|
41
|
+
|
42
|
+
unless [true, false].include? required
|
43
|
+
raise SwaggerInvalidException.new("Required should be a boolean instead of [#{required}]")
|
44
|
+
end
|
45
|
+
@required = required
|
46
|
+
|
47
|
+
if params
|
48
|
+
white_list_params(params, [:format])
|
49
|
+
end
|
50
|
+
@params = params
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_swagger
|
55
|
+
result = {
|
56
|
+
:name => @name,
|
57
|
+
:in => @how_to_pass,
|
58
|
+
:required => @required
|
59
|
+
}
|
60
|
+
|
61
|
+
if @type
|
62
|
+
if @type == 'array'
|
63
|
+
result[:type] = 'array'
|
64
|
+
if @items
|
65
|
+
if PRIMITIVE_TYPES.include? @items
|
66
|
+
result[:items] = {:type => @items}
|
67
|
+
else
|
68
|
+
result[:schema] = {'$ref' => "#/definitions/#{@items}"}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
else
|
72
|
+
if PRIMITIVE_TYPES.include? @type
|
73
|
+
result[:type] = @type
|
74
|
+
else
|
75
|
+
result[:schema] = {'$ref' => "#/definitions/#{@type}"}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
if @description
|
81
|
+
result[:description] = @description
|
82
|
+
end
|
83
|
+
if @params
|
84
|
+
result.merge!(@params)
|
85
|
+
end
|
86
|
+
|
87
|
+
result
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
{
|
92
|
+
:name => @name,
|
93
|
+
:in => @how_to_pass,
|
94
|
+
:required => @required,
|
95
|
+
:type => @type,
|
96
|
+
:items => @items,
|
97
|
+
:params => @params,
|
98
|
+
:description => @description,
|
99
|
+
}.to_json
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative 'swagger-utilities'
|
2
|
+
require_relative 'swagger-invalid-exception'
|
3
|
+
|
4
|
+
module Sinatra
|
5
|
+
|
6
|
+
module SwaggerExposer
|
7
|
+
|
8
|
+
class SwaggerEndpointResponse
|
9
|
+
|
10
|
+
include SwaggerUtilities
|
11
|
+
|
12
|
+
def initialize(type, description, known_types)
|
13
|
+
get_type(type, known_types + PRIMITIVE_TYPES)
|
14
|
+
if description
|
15
|
+
@description = description
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_swagger
|
20
|
+
result = {}
|
21
|
+
|
22
|
+
if @type
|
23
|
+
if @type == 'array'
|
24
|
+
schema = {:type => 'array'}
|
25
|
+
if @items
|
26
|
+
if PRIMITIVE_TYPES.include? @items
|
27
|
+
schema[:items] = {:type => @items}
|
28
|
+
else
|
29
|
+
schema[:items] = {'$ref' => "#/definitions/#{@items}"}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
result[:schema] = schema
|
33
|
+
else
|
34
|
+
if PRIMITIVE_TYPES.include? @type
|
35
|
+
result[:schema] = {:type => @type}
|
36
|
+
else
|
37
|
+
result[:schema] = {'$ref' => "#/definitions/#{@type}"}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if @description
|
43
|
+
result[:description] = @description
|
44
|
+
end
|
45
|
+
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
{
|
51
|
+
:type => @type,
|
52
|
+
:items => @items,
|
53
|
+
:description => @description,
|
54
|
+
}.to_json
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative 'swagger-utilities'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
|
5
|
+
module SwaggerExposer
|
6
|
+
|
7
|
+
# An endpoint
|
8
|
+
class SwaggerEndpoint
|
9
|
+
|
10
|
+
include SwaggerUtilities
|
11
|
+
|
12
|
+
attr_reader :path, :type
|
13
|
+
|
14
|
+
def initialize(type, path, parameters, responses, summary, description, tags)
|
15
|
+
@type = type
|
16
|
+
@path = sinatra_path_to_swagger_path(path)
|
17
|
+
|
18
|
+
@parameters = parameters
|
19
|
+
@responses = responses
|
20
|
+
|
21
|
+
@attributes = {}
|
22
|
+
if summary
|
23
|
+
@attributes[:summary] = summary
|
24
|
+
end
|
25
|
+
if description
|
26
|
+
@attributes[:description] = description
|
27
|
+
end
|
28
|
+
if tags
|
29
|
+
@attributes[:tags] = tags
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_swagger
|
34
|
+
result = {
|
35
|
+
produces: ['application/json'],
|
36
|
+
}.merge(@attributes)
|
37
|
+
|
38
|
+
unless @parameters.empty?
|
39
|
+
result[:parameters] = @parameters.collect { |parameter| parameter.to_swagger }
|
40
|
+
end
|
41
|
+
|
42
|
+
unless @responses.empty?
|
43
|
+
result[:responses] = hash_to_swagger(@responses)
|
44
|
+
end
|
45
|
+
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
REGEX_PATH_PARAM_MIDDLE = /\A(.*\/)\:([a-z]+)\/(.+)\z/
|
50
|
+
REGEX_PATH_PARAM_END = /\A(.*)\/:([a-z]+)\z/
|
51
|
+
|
52
|
+
def sinatra_path_to_swagger_path(path)
|
53
|
+
while (m = REGEX_PATH_PARAM_MIDDLE.match(path))
|
54
|
+
path = "#{m[1]}{#{m[2]}}/#{m[3]}"
|
55
|
+
end
|
56
|
+
if (m = REGEX_PATH_PARAM_END.match(path))
|
57
|
+
path = "#{m[1]}/{#{m[2]}}"
|
58
|
+
end
|
59
|
+
path
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
{
|
64
|
+
:type => @type,
|
65
|
+
:path => @path,
|
66
|
+
:attributes => @attributes,
|
67
|
+
:parameters => @parameters,
|
68
|
+
:responses => @responses,
|
69
|
+
}.to_json
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require_relative 'swagger-endpoint'
|
5
|
+
require_relative 'swagger-endpoint-parameter'
|
6
|
+
require_relative 'swagger-endpoint-response'
|
7
|
+
require_relative 'swagger-info'
|
8
|
+
require_relative 'swagger-invalid-exception'
|
9
|
+
require_relative 'swagger-type'
|
10
|
+
|
11
|
+
require_relative 'swagger-content-creator'
|
12
|
+
|
13
|
+
module Sinatra
|
14
|
+
|
15
|
+
# Expose swagger API from your Sinatra app
|
16
|
+
module SwaggerExposer
|
17
|
+
|
18
|
+
def self.registered(app)
|
19
|
+
app.set :swagger_endpoints, []
|
20
|
+
app.set :swagger_current_endpoint_info, {}
|
21
|
+
app.set :swagger_current_endpoint_parameters, {}
|
22
|
+
app.set :swagger_current_endpoint_responses, {}
|
23
|
+
app.set :swagger_types, {}
|
24
|
+
|
25
|
+
# Declare the swagger endpoints
|
26
|
+
app.endpoint_summary 'The swagger endpoint'
|
27
|
+
app.endpoint_tags 'swagger'
|
28
|
+
app.get '/swagger_doc.json' do
|
29
|
+
swagger_content = ::Sinatra::SwaggerExposer::SwaggerContentCreator.new(
|
30
|
+
settings.respond_to?(:swagger_info) ? settings.swagger_info : nil ,
|
31
|
+
settings.swagger_types,
|
32
|
+
settings.swagger_endpoints
|
33
|
+
).to_swagger
|
34
|
+
content_type :json
|
35
|
+
swagger_content.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
app.endpoint_summary 'Option method for the swagger endpoint, useful for some CORS stuff'
|
39
|
+
app.endpoint_tags 'swagger'
|
40
|
+
app.options '/swagger_doc.json' do
|
41
|
+
200
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# Provide a summary for the endpoint
|
47
|
+
def endpoint_summary(summary)
|
48
|
+
set_if_type_and_not_exist(summary, 'summary', String)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Provide a description for the endpoint
|
52
|
+
def endpoint_description(description)
|
53
|
+
set_if_type_and_not_exist(description, 'description', String)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Provide tags for the endpoint
|
57
|
+
def endpoint_tags(*tags)
|
58
|
+
set_if_type_and_not_exist(tags, 'tags', nil)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Define parameter for the endpoint
|
62
|
+
def endpoint_parameter(name, description, how_to_pass, required, type, params = nil)
|
63
|
+
parameters = settings.swagger_current_endpoint_parameters
|
64
|
+
check_if_not_duplicate(name, parameters, 'Parameter')
|
65
|
+
parameters[name] = SwaggerEndpointParameter.new(
|
66
|
+
name,
|
67
|
+
description,
|
68
|
+
how_to_pass,
|
69
|
+
required,
|
70
|
+
type,
|
71
|
+
params,
|
72
|
+
settings.swagger_types.keys)
|
73
|
+
end
|
74
|
+
|
75
|
+
# General information
|
76
|
+
def general_info(params)
|
77
|
+
set :swagger_info, SwaggerInfo.new(params)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Declare a type
|
81
|
+
def type(name, params)
|
82
|
+
types = settings.swagger_types
|
83
|
+
if types.key? name
|
84
|
+
raise SwaggerInvalidException.new("Type [#{name}] already exist with value #{types[name]}")
|
85
|
+
end
|
86
|
+
types[name] = SwaggerType.new(name, params, settings.swagger_types.keys)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Declare a response
|
90
|
+
def endpoint_response(code, type = nil, description = nil)
|
91
|
+
responses = settings.swagger_current_endpoint_responses
|
92
|
+
check_if_not_duplicate(code, responses, 'Response')
|
93
|
+
responses[code] = SwaggerEndpointResponse.new(type, description, settings.swagger_types.keys)
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete(*args, &block)
|
97
|
+
process_endpoint('delete', args)
|
98
|
+
super(*args, &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def get(*args, &block)
|
102
|
+
process_endpoint('get', args)
|
103
|
+
super(*args, &block)
|
104
|
+
end
|
105
|
+
|
106
|
+
def head(*args, &block)
|
107
|
+
process_endpoint('head', args)
|
108
|
+
super(*args, &block)
|
109
|
+
end
|
110
|
+
|
111
|
+
def link(*args, &block)
|
112
|
+
process_endpoint('link', args)
|
113
|
+
super(*args, &block)
|
114
|
+
end
|
115
|
+
|
116
|
+
def options(*args, &block)
|
117
|
+
process_endpoint('options', args)
|
118
|
+
super(*args, &block)
|
119
|
+
end
|
120
|
+
|
121
|
+
def patch(*args, &block)
|
122
|
+
process_endpoint('patch', args)
|
123
|
+
super(*args, &block)
|
124
|
+
end
|
125
|
+
|
126
|
+
def post(*args, &block)
|
127
|
+
process_endpoint('post', args)
|
128
|
+
super(*args, &block)
|
129
|
+
end
|
130
|
+
|
131
|
+
def put(*args, &block)
|
132
|
+
process_endpoint('put', args)
|
133
|
+
super(*args, &block)
|
134
|
+
end
|
135
|
+
|
136
|
+
def unlink(*args, &block)
|
137
|
+
process_endpoint('unlink', args)
|
138
|
+
super(*args, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# Call for each endpoint declaration
|
144
|
+
def process_endpoint(type, args)
|
145
|
+
current_endpoint_info = settings.swagger_current_endpoint_info
|
146
|
+
current_endpoint_parameters = settings.swagger_current_endpoint_parameters
|
147
|
+
current_endpoint_responses = settings.swagger_current_endpoint_responses
|
148
|
+
endpoint_path = args[0]
|
149
|
+
settings.swagger_endpoints << SwaggerEndpoint.new(
|
150
|
+
type,
|
151
|
+
endpoint_path,
|
152
|
+
current_endpoint_parameters.values,
|
153
|
+
current_endpoint_responses.clone,
|
154
|
+
current_endpoint_info[:summary],
|
155
|
+
current_endpoint_info[:description],
|
156
|
+
current_endpoint_info[:tags])
|
157
|
+
current_endpoint_info.clear
|
158
|
+
current_endpoint_parameters.clear
|
159
|
+
current_endpoint_responses.clear
|
160
|
+
end
|
161
|
+
|
162
|
+
def set_if_type_and_not_exist(value, name, type)
|
163
|
+
if type
|
164
|
+
unless value.is_a? type
|
165
|
+
raise SwaggerInvalidException.new("#{name} [#{value}] should be a #{type.to_s.downcase}")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
if settings.swagger_current_endpoint_info.key? name
|
169
|
+
raise SwaggerInvalidException.new("#{name} with value [#{value}] already defined: #{settings.swagger_current_endpoint_info[name]}")
|
170
|
+
end
|
171
|
+
settings.swagger_current_endpoint_info[name] = value
|
172
|
+
end
|
173
|
+
|
174
|
+
def check_if_not_duplicate(key, values, name)
|
175
|
+
if values.key? key
|
176
|
+
raise SwaggerInvalidException.new("#{name} already exist for #{key} with value #{values[key]}")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'swagger-invalid-exception'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
|
5
|
+
module SwaggerExposer
|
6
|
+
|
7
|
+
# The info declaration
|
8
|
+
class SwaggerInfo
|
9
|
+
|
10
|
+
def initialize(values)
|
11
|
+
@values = process(values, 'info', INFO_FIELDS, values)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Known fields for the info field
|
15
|
+
INFO_FIELDS = {
|
16
|
+
:version => String,
|
17
|
+
:title => String,
|
18
|
+
:description => String,
|
19
|
+
:termsOfService => String,
|
20
|
+
:contact => {:name => String, :email => String, :url => String},
|
21
|
+
:license => {:name => String, :url => String},
|
22
|
+
}
|
23
|
+
|
24
|
+
# Recursive function
|
25
|
+
def process(current_hash, current_field_name, current_fields, top_level_hash)
|
26
|
+
result = {}
|
27
|
+
|
28
|
+
current_hash.each_pair do |current_key, current_value|
|
29
|
+
key_sym = current_key.to_sym
|
30
|
+
if current_fields.key? key_sym
|
31
|
+
|
32
|
+
field_content = current_fields[key_sym]
|
33
|
+
if field_content == String
|
34
|
+
if current_value.is_a? String
|
35
|
+
result[key_sym] = current_value
|
36
|
+
else
|
37
|
+
raise SwaggerInvalidException.new("Property [#{current_key}] value [#{current_value}] should be a String for #{current_field_name}: #{top_level_hash}")
|
38
|
+
end
|
39
|
+
else
|
40
|
+
if current_value.is_a? Hash
|
41
|
+
sub_params = process(current_value, current_field_name, field_content, top_level_hash)
|
42
|
+
if sub_params
|
43
|
+
result[key_sym] = sub_params
|
44
|
+
end
|
45
|
+
else
|
46
|
+
raise SwaggerInvalidException.new("Property [#{current_key}] value [#{current_value}] should be a Hash for #{current_field_name}: #{top_level_hash}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
raise SwaggerInvalidException.new("Unknown property [#{current_key}] for #{current_field_name}, possible keys are: #{current_fields.keys.join(', ')}: #{top_level_hash}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
result.empty? ? nil : result
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_swagger
|
57
|
+
@values
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
@values.to_json
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require_relative 'swagger-utilities'
|
2
|
+
require_relative 'swagger-invalid-exception'
|
3
|
+
|
4
|
+
module Sinatra
|
5
|
+
|
6
|
+
module SwaggerExposer
|
7
|
+
|
8
|
+
# A property of a type
|
9
|
+
class SwaggerTypeProperty
|
10
|
+
|
11
|
+
include SwaggerUtilities
|
12
|
+
|
13
|
+
OTHER_PROPERTIES = [:example, :description, :format]
|
14
|
+
PROPERTIES = [:type] + OTHER_PROPERTIES
|
15
|
+
|
16
|
+
def initialize(type_name, property_name, property_properties, known_types)
|
17
|
+
@name = property_name
|
18
|
+
|
19
|
+
unless property_properties.is_a? Hash
|
20
|
+
raise SwaggerInvalidException.new("Property [#{property_name}] value [#{property_properties}] of [#{type_name}] should be a hash")
|
21
|
+
end
|
22
|
+
|
23
|
+
if property_properties.key? :type
|
24
|
+
get_type(property_properties[:type], PRIMITIVE_TYPES + known_types)
|
25
|
+
end
|
26
|
+
|
27
|
+
white_list_params(property_properties, PROPERTIES)
|
28
|
+
|
29
|
+
@other_properties = property_properties.select do |key, value|
|
30
|
+
OTHER_PROPERTIES.include? key
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_swagger
|
36
|
+
result = @other_properties.clone
|
37
|
+
|
38
|
+
if @type
|
39
|
+
if @type == 'array'
|
40
|
+
result[:type] = 'array'
|
41
|
+
if @items
|
42
|
+
if PRIMITIVE_TYPES.include? @items
|
43
|
+
result[:items] = {:type => @items}
|
44
|
+
else
|
45
|
+
result[:items] = {'$ref' => "#/definitions/#{@items}"}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
else
|
49
|
+
if PRIMITIVE_TYPES.include? @type
|
50
|
+
result[:type] = @type
|
51
|
+
else
|
52
|
+
result['$ref'] = "#/definitions/#{@type}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
{
|
62
|
+
:name => @name,
|
63
|
+
:type => @type,
|
64
|
+
:items => @items,
|
65
|
+
:other_properties => @other_properties,
|
66
|
+
}.to_json
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative 'swagger-invalid-exception'
|
2
|
+
require_relative 'swagger-type-property'
|
3
|
+
require_relative 'swagger-utilities'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
|
7
|
+
module SwaggerExposer
|
8
|
+
|
9
|
+
# A type
|
10
|
+
class SwaggerType
|
11
|
+
|
12
|
+
include SwaggerUtilities
|
13
|
+
|
14
|
+
def initialize(type_name, type_content, known_types)
|
15
|
+
@properties = process_properties(type_name, type_content, known_types)
|
16
|
+
@required = process_required(type_name, type_content, @properties.keys)
|
17
|
+
@example = process_example(type_name, type_content, @properties.keys)
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_properties(type_name, type_content, known_types)
|
21
|
+
possible_value = check_attribute_empty_or_bad(type_name, type_content, :properties, Hash)
|
22
|
+
if possible_value
|
23
|
+
possible_value
|
24
|
+
else
|
25
|
+
result = {}
|
26
|
+
type_content[:properties].each_pair do |property_name, property_properties|
|
27
|
+
result[property_name.to_s] = SwaggerTypeProperty.new(type_name, property_name, property_properties, known_types)
|
28
|
+
end
|
29
|
+
result
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_required(type_name, type_content, properties_names)
|
34
|
+
possible_value = check_attribute_empty_or_bad(type_name, type_content, :required, Array)
|
35
|
+
if possible_value
|
36
|
+
possible_value
|
37
|
+
else
|
38
|
+
type_content[:required].each do |property_name|
|
39
|
+
property_name = property_name.to_s
|
40
|
+
unless properties_names.include? property_name
|
41
|
+
raise SwaggerInvalidException.new("Required property [#{property_name}] of [#{type_name}] is unknown, known properties: #{properties_names.join(', ')}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
type_content[:required]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def process_example(type_name, type_content, properties_names)
|
49
|
+
possible_value = check_attribute_empty_or_bad(type_name, type_content, :example, Hash)
|
50
|
+
if possible_value
|
51
|
+
possible_value
|
52
|
+
else
|
53
|
+
type_content[:example].each_pair do |property_name, property_value|
|
54
|
+
property_name = property_name.to_s
|
55
|
+
unless properties_names.include? property_name
|
56
|
+
raise SwaggerInvalidException.new("Example property [#{property_name}] with value [#{property_value}] of [#{type_name}] is unknown, known properties: #{properties_names.join(', ')}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
type_content[:example]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_attribute_empty_or_bad(type_name, type_content, attribute_name, attribute_class)
|
64
|
+
if !type_content.key?(attribute_name)
|
65
|
+
attribute_class.new
|
66
|
+
elsif !type_content[attribute_name].is_a? attribute_class
|
67
|
+
raise SwaggerInvalidException.new("Attribute [#{attribute_name}] of #{type_name} is not an hash: #{type_content[attribute_name]}")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_swagger
|
72
|
+
result = {}
|
73
|
+
|
74
|
+
unless @properties.empty?
|
75
|
+
result[:properties] = hash_to_swagger(@properties)
|
76
|
+
end
|
77
|
+
|
78
|
+
unless @required.empty?
|
79
|
+
result[:required] = @required
|
80
|
+
end
|
81
|
+
|
82
|
+
unless @example.empty?
|
83
|
+
result[:example] = @example
|
84
|
+
end
|
85
|
+
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
{
|
91
|
+
:properties => @properties,
|
92
|
+
:required => @required,
|
93
|
+
:example => @example,
|
94
|
+
}.to_json
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'swagger-invalid-exception'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
|
5
|
+
module SwaggerExposer
|
6
|
+
|
7
|
+
module SwaggerUtilities
|
8
|
+
|
9
|
+
PRIMITIVE_TYPES = [
|
10
|
+
'integer',
|
11
|
+
'long',
|
12
|
+
'float',
|
13
|
+
'double',
|
14
|
+
'string',
|
15
|
+
'byte',
|
16
|
+
'boolean',
|
17
|
+
'date',
|
18
|
+
'dateTime',
|
19
|
+
'password'
|
20
|
+
]
|
21
|
+
|
22
|
+
def hash_to_swagger(hash)
|
23
|
+
result = {}
|
24
|
+
hash.each_pair do |key, value|
|
25
|
+
result[key] = value.to_swagger
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def type_to_s(value)
|
31
|
+
if value.is_a? Class
|
32
|
+
value.to_s.downcase
|
33
|
+
else
|
34
|
+
value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_type(type, possible_values)
|
39
|
+
@type = type
|
40
|
+
if type.nil?
|
41
|
+
raise SwaggerInvalidException.new('Type is nil')
|
42
|
+
elsif type.is_a?(String) || @type.is_a?(Class)
|
43
|
+
@type = type_to_s(@type)
|
44
|
+
check_type(@type, possible_values)
|
45
|
+
elsif @type.is_a? Array
|
46
|
+
@items = type_to_s(get_array_type(@type))
|
47
|
+
check_type(@items, possible_values)
|
48
|
+
@type = 'array'
|
49
|
+
else
|
50
|
+
raise SwaggerInvalidException.new("Type [#{@type}] of has an unknown type, should be a class, a string or an array")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def white_list_params(params, allowed_params)
|
55
|
+
params.each_pair do |key, value|
|
56
|
+
unless allowed_params.include? key
|
57
|
+
raise SwaggerInvalidException.new("Unknown property [#{key}] for with value [#{value}], known properties are #{allowed_params.join(', ')}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def get_array_type(array)
|
65
|
+
if array.empty?
|
66
|
+
raise SwaggerInvalidException.new('Type is an empty array, you should specify a type as the array content')
|
67
|
+
elsif array.length > 1
|
68
|
+
raise SwaggerInvalidException.new("Type [#{array}] has more than one entry, it should only have one")
|
69
|
+
else
|
70
|
+
type_to_s(array[0])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def check_type(type, possible_values)
|
75
|
+
unless possible_values.include? type
|
76
|
+
raise SwaggerInvalidException.new("Unknown type [#{type}], possible types are #{possible_values.join(', ')}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sinatra/swagger-exposer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'sinatra-swagger-exposer'
|
8
|
+
spec.version = Sinatra::SwaggerExposer::VERSION
|
9
|
+
spec.authors = ['Julien Kirch']
|
10
|
+
|
11
|
+
spec.summary = %q{Expose swagger API from your Sinatra app}
|
12
|
+
spec.description = %q{This Sinatra extension enable you to add metadata to your code and to expose your API as a Swagger endpoint}
|
13
|
+
spec.homepage = 'https://github.com/archiloque/sinatra-swagger-exposer'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.require_paths = ['lib']
|
18
|
+
|
19
|
+
spec.add_dependency 'sinatra', '~> 1.4'
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'minitest', '~> 5.5'
|
24
|
+
spec.add_development_dependency 'rack-test', '~> 0.6.3'
|
25
|
+
spec.add_development_dependency 'simplecov'
|
26
|
+
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-swagger-exposer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Julien Kirch
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sinatra
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack-test
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.6.3
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.6.3
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: This Sinatra extension enable you to add metadata to your code and to
|
98
|
+
expose your API as a Swagger endpoint
|
99
|
+
email:
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".travis.yml"
|
106
|
+
- CODE_OF_CONDUCT.md
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.asciidoc
|
110
|
+
- Rakefile
|
111
|
+
- example/Gemfile
|
112
|
+
- example/Gemfile.lock
|
113
|
+
- example/config.ru
|
114
|
+
- example/petstore.rb
|
115
|
+
- lib/sinatra/swagger-exposer/swagger-content-creator.rb
|
116
|
+
- lib/sinatra/swagger-exposer/swagger-endpoint-parameter.rb
|
117
|
+
- lib/sinatra/swagger-exposer/swagger-endpoint-response.rb
|
118
|
+
- lib/sinatra/swagger-exposer/swagger-endpoint.rb
|
119
|
+
- lib/sinatra/swagger-exposer/swagger-exposer.rb
|
120
|
+
- lib/sinatra/swagger-exposer/swagger-info.rb
|
121
|
+
- lib/sinatra/swagger-exposer/swagger-invalid-exception.rb
|
122
|
+
- lib/sinatra/swagger-exposer/swagger-type-property.rb
|
123
|
+
- lib/sinatra/swagger-exposer/swagger-type.rb
|
124
|
+
- lib/sinatra/swagger-exposer/swagger-utilities.rb
|
125
|
+
- lib/sinatra/swagger-exposer/version.rb
|
126
|
+
- sinatra-swagger-exposer.gemspec
|
127
|
+
homepage: https://github.com/archiloque/sinatra-swagger-exposer
|
128
|
+
licenses:
|
129
|
+
- MIT
|
130
|
+
metadata: {}
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubyforge_project:
|
147
|
+
rubygems_version: 2.4.5
|
148
|
+
signing_key:
|
149
|
+
specification_version: 4
|
150
|
+
summary: Expose swagger API from your Sinatra app
|
151
|
+
test_files: []
|