swagger-parser 0.2.5

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +23 -0
  6. data/.travis.yml +6 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +5 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +114 -0
  11. data/Rakefile +11 -0
  12. data/lib/swagger.rb +56 -0
  13. data/lib/swagger/api.rb +26 -0
  14. data/lib/swagger/attachable.rb +39 -0
  15. data/lib/swagger/boolean.rb +13 -0
  16. data/lib/swagger/builder.rb +109 -0
  17. data/lib/swagger/mime_type.rb +46 -0
  18. data/lib/swagger/notes.md +35 -0
  19. data/lib/swagger/parsers.rb +36 -0
  20. data/lib/swagger/schema.rb +63 -0
  21. data/lib/swagger/swagger_object.rb +49 -0
  22. data/lib/swagger/uri.rb +11 -0
  23. data/lib/swagger/uri_template.rb +11 -0
  24. data/lib/swagger/v2/api.rb +90 -0
  25. data/lib/swagger/v2/deterministic_json_schema.rb +130 -0
  26. data/lib/swagger/v2/example.rb +32 -0
  27. data/lib/swagger/v2/header.rb +22 -0
  28. data/lib/swagger/v2/info.rb +33 -0
  29. data/lib/swagger/v2/operation.rb +66 -0
  30. data/lib/swagger/v2/parameter.rb +35 -0
  31. data/lib/swagger/v2/path.rb +47 -0
  32. data/lib/swagger/v2/response.rb +26 -0
  33. data/lib/swagger/v2/security_requirement.rb +12 -0
  34. data/lib/swagger/v2/security_scheme.rb +25 -0
  35. data/lib/swagger/v2/tag.rb +11 -0
  36. data/lib/swagger/version.rb +3 -0
  37. data/resources/schemas/json_schema/draft-04.json +150 -0
  38. data/resources/schemas/swagger/v2.0/schema.json +1483 -0
  39. data/spec/fixtures/custom-properties.yaml +61 -0
  40. data/spec/fixtures/petstore-full.yaml +245 -0
  41. data/spec/fixtures/swagger.yaml +100 -0
  42. data/spec/spec_helper.rb +2 -0
  43. data/spec/swagger/api_spec.rb +87 -0
  44. data/spec/swagger/builder_spec.rb +52 -0
  45. data/spec/swagger/custom_properties_spec.rb +22 -0
  46. data/spec/swagger/info_spec.rb +76 -0
  47. data/spec/swagger/operation_spec.rb +99 -0
  48. data/spec/swagger/swagger_spec.rb +74 -0
  49. data/swagger-parser.gemspec +32 -0
  50. metadata +250 -0
@@ -0,0 +1,46 @@
1
+ require 'mime/types'
2
+
3
+ module Swagger
4
+ # Class representing Media Types (commonly known as MIME Types).
5
+ # @see http://en.wikipedia.org/wiki/Internet_media_type
6
+ class MimeType < String
7
+ extend Forwardable
8
+ def_delegators :@mime_type, :media_type, :sub_type
9
+
10
+ MIME_TYPE_FORMAT = /(\w+)\/(\w+\.)?([\w\.]+)(\+\w+)?\s*(;.*)?/
11
+
12
+ COMMON_ALIASES = {
13
+ txt: 'text/plain',
14
+ text: 'text/plain',
15
+ json: 'application/json',
16
+ xml: 'application/xml',
17
+ binary: 'application/octet-stream'
18
+ }
19
+
20
+ def initialize(mime_type_name)
21
+ @mime_type_name = mime_type_name.to_s
22
+ @mime_type = MIME::Types[@mime_type_name].first || base_type(@mime_type_name)
23
+ #fail ArgumentError, "Unknown mime type or suffix: #{mime_type_name}" if @mime_type.nil?
24
+ @mime_type ||= MIME::Types["text/plain"].first
25
+ super @mime_type_name
26
+ end
27
+
28
+ def self.parser_for(mime_type)
29
+ mime_type = COMMON_ALIASES[mime_type] if COMMON_ALIASES.key? mime_type
30
+ case mime_type
31
+ when 'application/json'
32
+ return JSON
33
+ else
34
+ fail NotImplementedError, "Parser support for #{mime_type} is not implemented"
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def base_type(mime_type_name)
41
+ media_type, _sub_type, _tree, suffix, _parameters = MIME_TYPE_FORMAT.match mime_type_name
42
+ return MIME::Types["#{media_type}/#{suffix}"].first if media_type && suffix
43
+ nil
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ Classes added to Swagger-Core (Java) for 2.0:
2
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/converter/ModelConverters.java
3
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Contact.java
4
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Info.java
5
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/License.java
6
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Model.java
7
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/ModelFactory.java
8
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Operation.java
9
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Path.java
10
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/RefModel.java
11
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Response.java
12
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Scheme.java
13
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Security.java
14
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Swagger.java
15
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/AbstractParameter.java
16
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/BodyParameter.java
17
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/CookieParameter.java
18
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/HeaderParameter.java
19
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/Parameter.java
20
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/PathParameter.java
21
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/QueryParameter.java
22
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/AbstractProperty.java
23
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/ArrayProperty.java
24
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/BooleanProperty.java
25
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/DateProperty.java
26
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/DateTimeProperty.java
27
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/DoubleProperty.java
28
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/IntegerProperty.java
29
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/LongProperty.java
30
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/MapProperty.java
31
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/Property.java
32
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/RefProperty.java
33
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/StringProperty.java
34
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/Xml.java
35
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/util/Json.java
@@ -0,0 +1,36 @@
1
+ autoload :YAML, 'yaml'
2
+ autoload :JSON, 'json'
3
+
4
+ module Swagger
5
+ # Provides classes for loading Swagger from YAML or JSON.
6
+ module Parsers
7
+ def self.parser_for(format)
8
+ case format
9
+ when '.yaml', '.yml', :yaml
10
+ YAMLParser
11
+ when '.json', '.js', :json
12
+ JSONParser
13
+ end
14
+ end
15
+
16
+ # Parses YAML content
17
+ class YAMLParser
18
+ # Parses a YAML document
19
+ # @param content [String] The YAML content to parse
20
+ # @return [Hash] the parsed content
21
+ def self.parse(content)
22
+ YAML.load(content)
23
+ end
24
+ end
25
+
26
+ # Parses JSON content
27
+ class JSONParser
28
+ # Parses a JSON document
29
+ # @param content [String] The JSON content to parse
30
+ # @return [Hash] the parsed content
31
+ def self.parse(content)
32
+ JSON.parse(content)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,63 @@
1
+ module Swagger
2
+ # Represents a Swagger Schema Object, a more deterministic subset of JSON Schema.
3
+ # @see https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md#schema-object- Schema Object
4
+ # @see http://json-schema.org/ JSON Schema
5
+ class Schema < Hashie::Mash
6
+ include Attachable
7
+ include Hashie::Extensions::MergeInitializer
8
+ include Hashie::Extensions::DeepFind
9
+ attr_accessor :parent
10
+
11
+ def initialize(hash, default = nil)
12
+ super
13
+ attach_to_children
14
+ end
15
+
16
+ def parse
17
+ schema = clone
18
+ if schema.key?('$ref')
19
+ key = schema.delete('$ref').split('/').last
20
+ model = root.definitions[key]
21
+ schema.merge!(model)
22
+ end
23
+
24
+ count = 0
25
+ until schema.refs_resolved?
26
+ fail 'Could not resolve non-remote $refs 5 cycles - circular references?' if count >= 5
27
+ schema.resolve_refs
28
+ count += 1
29
+ end
30
+
31
+ schema.to_hash
32
+ end
33
+
34
+ protected
35
+
36
+ def refs
37
+ deep_find_all('$ref')
38
+ end
39
+
40
+ def resolve_refs
41
+ children.each do |child|
42
+ child.resolve_refs if child.is_a?(Swagger::Schema)
43
+ end
44
+ key = self.delete('$ref')
45
+ return if key.nil? || remote_ref?(key)
46
+ key = key.split('/').last
47
+ model = root.definitions[key]
48
+ self.merge!(model)
49
+ end
50
+
51
+ def refs_resolved?
52
+ return true if refs.nil?
53
+
54
+ refs.all? do |ref|
55
+ remote_ref?(ref)
56
+ end
57
+ end
58
+
59
+ def remote_ref?(ref)
60
+ ref.match(%r{\A\w+\://})
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ module Swagger
2
+ # A class that represents an Object defined in the Swagger specification.
3
+ # Provides methods for defining fields in the object.
4
+ class SwaggerObject < Hashie::Dash
5
+ include Hashie::Extensions::Coercion
6
+ include Hashie::Extensions::IndifferentAccess
7
+ include Swagger::Attachable
8
+
9
+ CUSTOM_PROPERTY_PREFIX = /^x\-/
10
+
11
+ # Swagger allows any properties starting with `x-`
12
+ def self.property?(name)
13
+ super(name) || name.to_s =~ CUSTOM_PROPERTY_PREFIX
14
+ end
15
+
16
+ attr_accessor :parent
17
+
18
+ # @api private
19
+ # Initializes a Swagger object, using Hashie::Dash,
20
+ # and attaches to children objects so navigation via +parent+
21
+ # and +root+ is possible.
22
+ def initialize(hash)
23
+ super
24
+ attach_to_children
25
+ end
26
+
27
+ # @api private
28
+ # @!macro [attach] field
29
+ # @!attribute [rw] $1
30
+ # Swagger field $1. $3
31
+ # @return [$2]
32
+ # Defines a Swagger field on a class.
33
+ def self.field(name, type, opts = {})
34
+ property name, opts
35
+ coerce_key name, type
36
+ end
37
+
38
+ # @api private
39
+ # @!macro [attach] required_field
40
+ # @!attribute [rw] $1
41
+ # **Required** Swagger field $1. $3
42
+ # @return [$2]
43
+ # Defines a required Swagger field on a class.
44
+ def self.required_field(name, type, opts = {})
45
+ opts[:required] = true
46
+ field(name, type, opts)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ module Swagger
2
+ # Class representing a URI. Backed by Addressable::URI.
3
+ # @see http://en.wikipedia.org/wiki/Uniform_resource_identifier
4
+ class URI < String
5
+ attr_reader :uri
6
+ def initialize(string)
7
+ @uri = Addressable::URI.heuristic_parse string
8
+ super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Swagger
2
+ # Class representing a URI Template. Backed by Addressable::Template.
3
+ # @see http://tools.ietf.org/html/rfc6570
4
+ class URITemplate < String
5
+ attr_reader :uri_template
6
+ def initialize(string)
7
+ @uri_template = Addressable::Template.new(string)
8
+ super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,90 @@
1
+ require 'swagger/swagger_object'
2
+ require 'swagger/v2/deterministic_json_schema'
3
+ require 'swagger/v2/info'
4
+ require 'swagger/v2/path'
5
+ require 'swagger/v2/tag'
6
+ require 'swagger/v2/security_scheme'
7
+ require 'swagger/v2/security_requirement'
8
+ require 'json-schema'
9
+
10
+ module Swagger
11
+ # Module containing classes that handle version 2 of the Swagger specification.
12
+ # @see https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md Swagger Specification 2.0
13
+ module V2
14
+ SWAGGER_SCHEMA = File.expand_path 'schemas/swagger/v2.0/schema.json', Swagger::RESOURCES_DIR
15
+ JSON_SCHEMA = File.expand_path 'schemas/json_schema/draft-04.json', Swagger::RESOURCES_DIR
16
+
17
+ # Class representing the top level "Swagger Object"
18
+ # @see https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md#swagger-object- Swagger Object
19
+ class API < Swagger::API
20
+ # @group Swagger Fields
21
+ required_field :swagger, String
22
+ required_field :info, Info
23
+ field :host, Swagger::URITemplate
24
+ field :basePath, Swagger::URITemplate
25
+ field :schemes, Array[String]
26
+ field :consumes, Array[String]
27
+ field :produces, Array[String]
28
+ required_field :paths, Hash[String => Path]
29
+ field :definitions, Hash[String => Schema]
30
+ field :parameters, Hash[String => Parameter]
31
+ field :responses, Hash[String => Response]
32
+ field :securityDefinitions, Hash[String => SecurityScheme]
33
+ field :security, Array[SecurityRequirement]
34
+ field :tags, Array[Object] # FIXME: This is actually an array of Tag objects
35
+ field :externalDocs, Object # TODO: ExternalDocs class
36
+ # @endgroup
37
+
38
+ alias_method :base_path, :basePath
39
+
40
+ # All operations under all paths
41
+ # @return [Array<Operation>]
42
+ def operations
43
+ # Perhaps not the best way...
44
+ paths.values.map do |path|
45
+ path.operations.values
46
+ end.flatten
47
+ end
48
+
49
+ # A complete (including host) URI Template for the basePath.
50
+ # @return [Swagger::URITemplate]
51
+ def uri_template
52
+ Swagger::URITemplate.new("#{host}#{basePath}")
53
+ end
54
+
55
+ # Validates this object against the Swagger specification and returns all detected errors.
56
+ # Slower than {#validate}.
57
+ # @return [true] if the object fully complies with the Swagger specification.
58
+ # @raise [Swagger::InvalidDefinition] if any errors are found.
59
+ def fully_validate
60
+ # NOTE: fully_validate is ideal, but very slow with the current schema/validator
61
+ errors = JSON::Validator.fully_validate(swagger_schema, to_json)
62
+ fail Swagger::InvalidDefinition, errors unless errors.empty?
63
+ true
64
+ end
65
+
66
+ # Validates this object against the Swagger specification and returns the first detected error.
67
+ # Faster than {#fully_validate}.
68
+ # @return [true] if the object fully complies with the Swagger specification.
69
+ # @raise [Swagger::InvalidDefinition] if an error is found.
70
+ def validate
71
+ JSON::Validator.validate!(swagger_schema, to_json)
72
+ rescue JSON::Schema::ValidationError => e
73
+ raise Swagger::InvalidDefinition, e.message
74
+ end
75
+
76
+ private
77
+
78
+ def swagger_schema
79
+ @swagger_schema ||= JSON.parse(File.read(SWAGGER_SCHEMA))
80
+
81
+ # FIXME: Swagger should be able to parse offline. Blocked by json-schema.
82
+ # Offline workaround
83
+ # @swagger_schema = JSON.parse(File.read(SWAGGER_SCHEMA)
84
+ # .gsub('http://json-schema.org/draft-04/schema', "file://#{SWAGGER_SCHEMA}"))
85
+ # @swagger_schema['$schema'] = 'http://json-schema.org/draft-04/schema#'
86
+ # @swagger_schema
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,130 @@
1
+ module Swagger
2
+ module V2
3
+ # A Swagger Schema Object, which is subset of JSON-Schema that's constrainted to be more deterministic.
4
+ # @see https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#schema-object- Schema Object
5
+ # @see http://json-schema.org/ JSON-Schema
6
+ module DeterministicJSONSchema
7
+ # FIXME: yard group doesn't seem to work below
8
+
9
+ # @!group Deterministic JSON Schema
10
+ # @!attribute [rw] $ref
11
+ # JSON-Schema field $ref.
12
+ # @return String
13
+ # @!attribute [rw] format
14
+ # JSON-Schema field format.
15
+ # @return String
16
+ # @!attribute [rw] title
17
+ # JSON-Schema field title.
18
+ # @return String
19
+ # @!attribute [rw] description
20
+ # JSON-Schema field description.
21
+ # @return String
22
+ # @!attribute [rw] default
23
+ # JSON-Schema field default.
24
+ # @return Object
25
+ # @!attribute [rw] multipleOf
26
+ # JSON-Schema field multipleOf.
27
+ # @return Object
28
+ # @!attribute [rw] maximum
29
+ # JSON-Schema field maximum.
30
+ # @return Numeric
31
+ # @!attribute [rw] exclusiveMaximum
32
+ # JSON-Schema field exclusiveMaximum.
33
+ # @return boolean
34
+ # @!attribute [rw] minimum
35
+ # JSON-Schema field minimum.
36
+ # @return Numeric
37
+ # @!attribute [rw] exclusiveMinimum
38
+ # JSON-Schema field exclusiveMinimum.
39
+ # @return boolean
40
+ # @!attribute [rw] minLength
41
+ # JSON-Schema field minLength.
42
+ # @return Integer
43
+ # @!attribute [rw] maxLength
44
+ # JSON-Schema field maxLength.
45
+ # @return Integer
46
+ # @!attribute [rw] pattern
47
+ # JSON-Schema field pattern.
48
+ # @return Regexp
49
+ # @!attribute [rw] minItems
50
+ # JSON-Schema field minItems.
51
+ # @return Integer
52
+ # @!attribute [rw] maxItems
53
+ # JSON-Schema field maxItems.
54
+ # @return Integer
55
+ # @!attribute [rw] uniqueItems
56
+ # JSON-Schema field uniqueItems.
57
+ # @return boolean
58
+ # @!attribute [rw] maxProperties
59
+ # JSON-Schema field maxProperties.
60
+ # @return Integer
61
+ # @!attribute [rw] minProperties
62
+ # JSON-Schema field minProperties.
63
+ # @return Integer
64
+ # @!attribute [rw] required
65
+ # JSON-Schema field required.
66
+ # @return boolean
67
+ # @!attribute [rw] enum
68
+ # JSON-Schema field enum.
69
+ # @return Array[Object]
70
+ # @!attribute [rw] type
71
+ # JSON-Schema field type.
72
+ # @return Object
73
+ # @!endgroup
74
+
75
+ # @!group Swagger specific extensions
76
+ # @!attribute [rw] discriminator
77
+ # Swagger Schema field discriminator.
78
+ # @return String
79
+ # @!attribute [rw] readOnly
80
+ # Swagger Schema field readOnly.
81
+ # @return boolean
82
+ # @!attribute [rw] xml
83
+ # Swagger Schema field xml.
84
+ # @return Object
85
+ # @!attribute [rw] externalDocs
86
+ # Swagger Schema field externalDocs.
87
+ # @return ExternalDocumentation
88
+ # @!attribute [rw] example
89
+ # Swagger Schema field example.
90
+ # @return Object
91
+ # @!endgroup
92
+
93
+ def self.included(base) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
94
+ # Subset of standard JSON schema
95
+ base.field :$ref, String
96
+ base.field :format, String
97
+ base.field :title, String
98
+ base.field :description, String
99
+ base.field :default, Object
100
+ base.field :multipleOf, Numeric
101
+ base.field :maximum, Numeric
102
+ base.field :exclusiveMaximum, Swagger::Boolean
103
+ base.send(:alias_method, :exclusiveMaximum?, :exclusiveMaximum)
104
+ base.field :minimum, Numeric
105
+ base.field :exclusiveMinimum, Swagger::Boolean
106
+ base.send(:alias_method, :exclusiveMinimum?, :exclusiveMinimum)
107
+ base.field :maxLength, Integer
108
+ base.field :minLength, Integer
109
+ base.field :pattern, String
110
+ base.field :maxItems, Integer
111
+ base.field :minItems, Integer
112
+ base.field :uniqueItems, Swagger::Boolean
113
+ base.send(:alias_method, :uniqueItems?, :uniqueItems)
114
+ base.field :maxProperties, Integer
115
+ base.field :minProperties, Integer
116
+ base.field :required, Swagger::Boolean
117
+ base.send(:alias_method, :required?, :required)
118
+ base.field :enum, Array[Object]
119
+ base.field :type, Object
120
+
121
+ # Swagger extensions to JSON schema :\
122
+ base.field :discriminator, String
123
+ base.field :readOnly, Swagger::Boolean
124
+ base.field :xml, Object # TODO: Swagger XML object / XML support
125
+ base.field :externalDocs, Object # TODO: ExternalDocumentation class
126
+ base.field :example, Object
127
+ end
128
+ end
129
+ end
130
+ end