oas_core 0.5.3 → 1.0.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 +4 -4
- data/README.md +5 -1
- data/lib/oas_core/builders/content_builder.rb +15 -8
- data/lib/oas_core/builders/operation_builder.rb +9 -1
- data/lib/oas_core/builders/parameters_builder.rb +9 -1
- data/lib/oas_core/builders/request_body_builder.rb +1 -1
- data/lib/oas_core/builders/response_builder.rb +2 -2
- data/lib/oas_core/builders/responses_builder.rb +9 -7
- data/lib/oas_core/configuration.rb +1 -4
- data/lib/oas_core/json_schema_generator.rb +4 -2
- data/lib/oas_core/spec/components.rb +14 -15
- data/lib/oas_core/spec/media_type.rb +0 -1
- data/lib/oas_core/spec/response.rb +1 -0
- data/lib/oas_core/spec/responses.rb +5 -5
- data/lib/oas_core/spec/specable.rb +24 -22
- data/lib/oas_core/version.rb +1 -1
- data/lib/oas_core/yard/oas_core_factory.rb +124 -86
- data/lib/oas_core/yard/parameter_reference_tag.rb +8 -0
- data/lib/oas_core/yard/parameter_tag.rb +4 -4
- data/lib/oas_core/yard/reference_tag.rb +14 -0
- data/lib/oas_core/yard/request_body_example_tag.rb +0 -5
- data/lib/oas_core/yard/request_body_reference_tag.rb +8 -0
- data/lib/oas_core/yard/request_body_tag.rb +3 -4
- data/lib/oas_core/yard/response_example_tag.rb +1 -1
- data/lib/oas_core/yard/response_reference_tag.rb +14 -0
- data/lib/oas_core/yard/response_tag.rb +5 -4
- data/lib/oas_core.rb +15 -0
- metadata +27 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc7875de7f736a4c22a97996c6fd5073eb1f7486380da2822079d5698533f838
|
4
|
+
data.tar.gz: 03c6a672ec713bbdfd205f8aab8c50f30fa8bb5e935225a254bab98096cdd810
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d6bf9b134a6b23d98fd49a7e731dc3d5034dfa3208de61805ca91d1a33ee126acef7e963d2865a6ca7c4becf80d2f17d6b5fc063dcf78fc53545862ceb083c7
|
7
|
+
data.tar.gz: cee566dc9b35190ddef8109e836dd4473de56ee27f5c936b3f818157d1edd86d2a9d854e3f2a0a202d39b44d464ce007bf5345a9dc84c6e16197ff8628102d1a
|
data/README.md
CHANGED
@@ -10,7 +10,11 @@ OasCore is a Ruby gem designed to generate Open API Specification (OAS) 3.1 docu
|
|
10
10
|
|
11
11
|
## Framework adapters
|
12
12
|
|
13
|
-
- **[OasRails](https://github.com/a-chacon/oas_rails)
|
13
|
+
- **[OasRails](https://github.com/a-chacon/oas_rails)**: For Ruby on Rails framework.
|
14
|
+
|
15
|
+
- **[OasHanami](https://github.com/a-chacon/oas_hanami)**: For [Hanami](https://github.com/hanami/hanami) framework.
|
16
|
+
|
17
|
+
- **[OasRage](https://github.com/a-chacon/oas_rage)**: For [Rage](https://github.com/rage-rb/rage) framework.
|
14
18
|
|
15
19
|
## Documentation
|
16
20
|
|
@@ -3,15 +3,18 @@
|
|
3
3
|
module OasCore
|
4
4
|
module Builders
|
5
5
|
class ContentBuilder
|
6
|
-
def initialize(specification
|
7
|
-
@context = context || :incoming
|
6
|
+
def initialize(specification)
|
8
7
|
@specification = specification
|
9
8
|
@media_type = Spec::MediaType.new(specification)
|
10
9
|
@content_type = 'application/json'
|
11
10
|
end
|
12
11
|
|
13
12
|
def with_schema(schema)
|
14
|
-
@media_type.schema =
|
13
|
+
@media_type.schema = if schema.is_a? OasCore::Spec::Reference
|
14
|
+
schema
|
15
|
+
else
|
16
|
+
@specification.components.add_schema(schema)
|
17
|
+
end
|
15
18
|
|
16
19
|
self
|
17
20
|
end
|
@@ -31,11 +34,15 @@ module OasCore
|
|
31
34
|
def with_examples_from_tags(tags)
|
32
35
|
@media_type.examples = @media_type.examples.merge(tags.each_with_object({}).with_index(1) do |(example, result), _index|
|
33
36
|
key = example.text.downcase.gsub(' ', '_')
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
if example.content.is_a? OasCore::Spec::Reference
|
38
|
+
result[key] = example.content
|
39
|
+
else
|
40
|
+
value = {
|
41
|
+
'summary' => example.text,
|
42
|
+
'value' => example.content
|
43
|
+
}
|
44
|
+
result[key] = @specification.components.add_example(value)
|
45
|
+
end
|
39
46
|
end)
|
40
47
|
|
41
48
|
self
|
@@ -15,7 +15,7 @@ module OasCore
|
|
15
15
|
@operation.tags = extract_tags(oas_route:)
|
16
16
|
@operation.security = extract_security(oas_route:)
|
17
17
|
@operation.parameters = ParametersBuilder.new(@specification).from_oas_route(oas_route).build
|
18
|
-
@operation.request_body =
|
18
|
+
@operation.request_body = extract_request_body(oas_route)
|
19
19
|
@operation.responses = ResponsesBuilder.new(@specification)
|
20
20
|
.from_oas_route(oas_route)
|
21
21
|
.add_default_responses(oas_route, !@operation.security.empty?).build
|
@@ -82,6 +82,14 @@ module OasCore
|
|
82
82
|
destroy: 'Delete'
|
83
83
|
}.fetch(method.to_sym)
|
84
84
|
end
|
85
|
+
|
86
|
+
def extract_request_body(oas_route)
|
87
|
+
if (ref_tag = oas_route.tags(:request_body_ref).first)
|
88
|
+
ref_tag.reference
|
89
|
+
else
|
90
|
+
RequestBodyBuilder.new(@specification).from_oas_route(oas_route).reference
|
91
|
+
end
|
92
|
+
end
|
85
93
|
end
|
86
94
|
end
|
87
95
|
end
|
@@ -15,6 +15,10 @@ module OasCore
|
|
15
15
|
@parameters << ParameterBuilder.new(@specification).from_path(oas_route.path, p).build unless @parameters.any? { |param| param.name.to_s == p.to_s }
|
16
16
|
end
|
17
17
|
|
18
|
+
oas_route.tags(:parameter_ref)&.each do |ref_tag|
|
19
|
+
@parameters << ref_tag.reference
|
20
|
+
end
|
21
|
+
|
18
22
|
self
|
19
23
|
end
|
20
24
|
|
@@ -34,7 +38,11 @@ module OasCore
|
|
34
38
|
|
35
39
|
def build
|
36
40
|
@parameters.map do |p|
|
37
|
-
|
41
|
+
if p.is_a? OasCore::Spec::Reference
|
42
|
+
p
|
43
|
+
else
|
44
|
+
@specification.components.add_parameter(p)
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
@@ -19,7 +19,7 @@ module OasCore
|
|
19
19
|
|
20
20
|
def from_tags(tag:, examples_tags: [])
|
21
21
|
@request_body.description = tag.text
|
22
|
-
@request_body.content = ContentBuilder.new(@specification
|
22
|
+
@request_body.content = ContentBuilder.new(@specification).with_schema(tag.content).with_examples_from_tags(examples_tags).with_content_type(tag.content_type).build
|
23
23
|
@request_body.required = tag.required
|
24
24
|
|
25
25
|
self
|
@@ -27,9 +27,9 @@ module OasCore
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def from_tag(tag)
|
30
|
-
@response.code = tag.
|
30
|
+
@response.code = tag.code.to_i
|
31
31
|
@response.description = tag.text
|
32
|
-
@response.content = ContentBuilder.new(@specification
|
32
|
+
@response.content = ContentBuilder.new(@specification).with_schema(tag.content).build
|
33
33
|
|
34
34
|
self
|
35
35
|
end
|
@@ -15,15 +15,18 @@ module OasCore
|
|
15
15
|
|
16
16
|
def from_oas_route(oas_route)
|
17
17
|
oas_route.tags(:response).each do |tag|
|
18
|
-
content = @content_builder.new(@specification
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
response = @response_builder.new(@specification).with_code(tag.name.to_i).with_description(tag.text).with_content(content).build
|
18
|
+
content = @content_builder.new(@specification).with_schema(tag.content).with_examples_from_tags(oas_route.tags(:response_example).filter do |re|
|
19
|
+
re.code == tag.code
|
20
|
+
end).build
|
21
|
+
response = @response_builder.new(@specification).with_code(tag.code.to_i).with_description(tag.text).with_content(content).build
|
23
22
|
|
24
23
|
@responses.add_response(response)
|
25
24
|
end
|
26
25
|
|
26
|
+
oas_route.tags(:response_ref)&.each do |ref_tag|
|
27
|
+
@responses.add_reference_response(ref_tag.code, ref_tag.reference)
|
28
|
+
end
|
29
|
+
|
27
30
|
self
|
28
31
|
end
|
29
32
|
|
@@ -63,8 +66,7 @@ module OasCore
|
|
63
66
|
def add_responses_for_errors(errors)
|
64
67
|
errors.each do |error|
|
65
68
|
response_body = resolve_response_body(error)
|
66
|
-
content = @content_builder.new(@specification
|
67
|
-
:outgoing).with_schema(@json_schema_generator.process_string(response_body)[:json_schema]).build
|
69
|
+
content = @content_builder.new(@specification).with_schema(@json_schema_generator.process_string(response_body)[:json_schema]).build
|
68
70
|
code = @utils.status_to_integer(error)
|
69
71
|
response = @response_builder.new(@specification).with_code(code).with_description(@utils.get_definition(code)).with_content(content).build
|
70
72
|
|
@@ -9,8 +9,7 @@ module OasCore
|
|
9
9
|
:authenticate_all_routes_by_default,
|
10
10
|
:set_default_responses,
|
11
11
|
:possible_default_responses,
|
12
|
-
:http_verbs
|
13
|
-
:use_model_names
|
12
|
+
:http_verbs
|
14
13
|
|
15
14
|
attr_reader :servers, :tags, :security_schema, :response_body_of_default
|
16
15
|
|
@@ -29,8 +28,6 @@ module OasCore
|
|
29
28
|
unprocessable_entity]
|
30
29
|
@http_verbs = %i[get post put patch delete]
|
31
30
|
@response_body_of_default = 'Hash{ status: !Integer, error: String }'
|
32
|
-
# TODO: What does this config??
|
33
|
-
@use_model_names = false
|
34
31
|
|
35
32
|
@possible_default_responses.each do |response|
|
36
33
|
method_name = "response_body_of_#{response}="
|
@@ -52,6 +52,7 @@ module OasCore
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
# rubocop:disable Metrics
|
55
56
|
# Parses the properties of an object type from a string.
|
56
57
|
#
|
57
58
|
# @param str [String] The string representation of the object's properties.
|
@@ -97,6 +98,7 @@ module OasCore
|
|
97
98
|
|
98
99
|
properties
|
99
100
|
end
|
101
|
+
# rubocop:enable Metrics
|
100
102
|
|
101
103
|
# Converts a parsed data type into a JSON schema format.
|
102
104
|
#
|
@@ -128,11 +130,11 @@ module OasCore
|
|
128
130
|
end
|
129
131
|
end
|
130
132
|
|
133
|
+
# rubocop:disable Metrics
|
131
134
|
# Converts a Ruby data type into its corresponding JSON schema type.
|
132
135
|
#
|
133
136
|
# @param type [Symbol, String] The Ruby data type.
|
134
137
|
# @return [Hash, String] The JSON schema type or a hash with additional format information.
|
135
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
136
138
|
def self.ruby_type_to_json_schema_type(type)
|
137
139
|
case type.to_s.downcase
|
138
140
|
when 'string' then { type: 'string' }
|
@@ -148,6 +150,6 @@ module OasCore
|
|
148
150
|
else type.to_s.downcase
|
149
151
|
end
|
150
152
|
end
|
151
|
-
# rubocop:enable Metrics
|
153
|
+
# rubocop:enable Metrics
|
152
154
|
end
|
153
155
|
end
|
@@ -21,8 +21,18 @@ module OasCore
|
|
21
21
|
@callbacks = {}
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
|
24
|
+
def to_spec
|
25
|
+
{
|
26
|
+
schemas: @schemas,
|
27
|
+
responses: @responses.transform_values(&:to_spec),
|
28
|
+
parameters: @parameters.transform_values(&:to_spec),
|
29
|
+
requestBodies: @request_bodies.transform_values(&:to_spec),
|
30
|
+
securitySchemes: @security_schemes,
|
31
|
+
headers: @headers.transform_values(&:to_spec),
|
32
|
+
examples: @examples,
|
33
|
+
links: @links.transform_values(&:to_spec),
|
34
|
+
callbacks: @callbacks.transform_values(&:to_spec)
|
35
|
+
}.compact
|
26
36
|
end
|
27
37
|
|
28
38
|
def add_response(response)
|
@@ -47,20 +57,9 @@ module OasCore
|
|
47
57
|
end
|
48
58
|
|
49
59
|
def add_schema(schema)
|
50
|
-
key =
|
51
|
-
if OasCore.config.use_model_names
|
52
|
-
if schema[:type] == 'array'
|
53
|
-
arr_schema = schema[:items]
|
54
|
-
arr_key = arr_schema['title']
|
55
|
-
key = "#{arr_key}List" unless arr_key.nil?
|
56
|
-
else
|
57
|
-
key = schema['title']
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
key = Hashable.generate_hash(schema) if key.nil?
|
62
|
-
|
60
|
+
key = Hashable.generate_hash(schema)
|
63
61
|
@schemas[key] = schema if @schemas[key].nil?
|
62
|
+
|
64
63
|
schema_reference(key)
|
65
64
|
end
|
66
65
|
|
@@ -15,12 +15,12 @@ module OasCore
|
|
15
15
|
@responses[response.code] = @specification.components.add_response(response)
|
16
16
|
end
|
17
17
|
|
18
|
+
def add_reference_response(code, reference)
|
19
|
+
@responses[code] = reference
|
20
|
+
end
|
21
|
+
|
18
22
|
def to_spec
|
19
|
-
|
20
|
-
@responses.each do |key, value|
|
21
|
-
spec[key] = value.to_spec
|
22
|
-
end
|
23
|
-
spec
|
23
|
+
@responses.transform_values(&:to_spec)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -8,30 +8,12 @@ module OasCore
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def to_spec
|
11
|
-
|
12
|
-
|
13
|
-
key = var.to_s
|
14
|
-
|
15
|
-
camel_case_key = key.camelize(:lower).to_sym
|
11
|
+
oas_fields.each_with_object({}) do |var, hash|
|
12
|
+
key = var.to_s.camelize(:lower).to_sym
|
16
13
|
value = send(var)
|
17
|
-
|
18
|
-
|
19
|
-
value.to_spec
|
20
|
-
elsif value.is_a?(Array) && value.all? { |elem| elem.respond_to?(:to_spec) }
|
21
|
-
value.map(&:to_spec)
|
22
|
-
# elsif value.is_a?(Hash)
|
23
|
-
# hash = {}
|
24
|
-
# value.each do |key, object|
|
25
|
-
# hash[key] = object.to_spec
|
26
|
-
# end
|
27
|
-
# hash
|
28
|
-
else
|
29
|
-
value
|
30
|
-
end
|
31
|
-
|
32
|
-
hash[camel_case_key] = processed_value unless valid_processed_value?(processed_value)
|
14
|
+
processed_value = process_value(value)
|
15
|
+
hash[key] = processed_value unless valid_processed_value?(processed_value)
|
33
16
|
end
|
34
|
-
hash
|
35
17
|
end
|
36
18
|
|
37
19
|
# rubocop:disable Lint/UnusedMethodArgument
|
@@ -42,6 +24,26 @@ module OasCore
|
|
42
24
|
|
43
25
|
private
|
44
26
|
|
27
|
+
def process_value(value)
|
28
|
+
if value.respond_to?(:to_spec)
|
29
|
+
value.to_spec
|
30
|
+
elsif value.is_a?(Array)
|
31
|
+
process_array(value)
|
32
|
+
elsif value.is_a?(Hash)
|
33
|
+
process_hash(value)
|
34
|
+
else
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_array(array)
|
40
|
+
array.all? { |elem| elem.respond_to?(:to_spec) } ? array.map(&:to_spec) : array
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_hash(hash)
|
44
|
+
hash.transform_values { |val| val.respond_to?(:to_spec) ? val.to_spec : val }
|
45
|
+
end
|
46
|
+
|
45
47
|
def valid_processed_value?(processed_value)
|
46
48
|
((processed_value.is_a?(Hash) || processed_value.is_a?(Array)) && processed_value.empty?) || processed_value.nil?
|
47
49
|
end
|
data/lib/oas_core/version.rb
CHANGED
@@ -2,14 +2,22 @@
|
|
2
2
|
|
3
3
|
module OasCore
|
4
4
|
module YARD
|
5
|
+
class TagParsingError < StandardError; end
|
6
|
+
|
5
7
|
class OasCoreFactory < ::YARD::Tags::DefaultFactory
|
6
8
|
# Parses a tag that represents a request body.
|
7
9
|
# @param tag_name [String] The name of the tag.
|
8
10
|
# @param text [String] The tag text to parse.
|
9
11
|
# @return [RequestBodyTag] The parsed request body tag object.
|
10
12
|
def parse_tag_with_request_body(tag_name, text)
|
11
|
-
description,
|
12
|
-
|
13
|
+
description, raw_type = split_description_and_type(text.squish)
|
14
|
+
description, content_type = text_and_last_parenthesis_content(description)
|
15
|
+
raw_type, required = text_and_required(raw_type)
|
16
|
+
content = raw_type_to_content(raw_type)
|
17
|
+
|
18
|
+
RequestBodyTag.new(tag_name, description, content:, required:, content_type:)
|
19
|
+
rescue StandardError => e
|
20
|
+
raise TagParsingError, "Failed to parse request body tag: #{e.message}"
|
13
21
|
end
|
14
22
|
|
15
23
|
# Parses a tag that represents a request body example.
|
@@ -17,9 +25,13 @@ module OasCore
|
|
17
25
|
# @param text [String] The tag text to parse.
|
18
26
|
# @return [RequestBodyExampleTag] The parsed request body example tag object.
|
19
27
|
def parse_tag_with_request_body_example(tag_name, text)
|
20
|
-
description,
|
21
|
-
|
22
|
-
|
28
|
+
description, raw_type = split_description_and_type(text.squish)
|
29
|
+
raw_type, = text_and_required(raw_type)
|
30
|
+
content = raw_type_to_content(raw_type)
|
31
|
+
|
32
|
+
RequestBodyExampleTag.new(tag_name, description, content: content)
|
33
|
+
rescue StandardError => e
|
34
|
+
raise TagParsingError, "Failed to parse request body example tag: #{e.message}"
|
23
35
|
end
|
24
36
|
|
25
37
|
# Parses a tag that represents a parameter.
|
@@ -27,9 +39,20 @@ module OasCore
|
|
27
39
|
# @param text [String] The tag text to parse.
|
28
40
|
# @return [ParameterTag] The parsed parameter tag object.
|
29
41
|
def parse_tag_with_parameter(tag_name, text)
|
30
|
-
|
42
|
+
match = text.squish.match(/^(.*?)\s*\[(.*?)\]\s*(.*)$/)
|
43
|
+
if match
|
44
|
+
first = match[1]
|
45
|
+
second = match[2]
|
46
|
+
description = match[3]
|
47
|
+
end
|
48
|
+
name, location = text_and_last_parenthesis_content(first)
|
49
|
+
raw_type, required = text_and_required(second)
|
50
|
+
schema = raw_type_to_content(raw_type)
|
31
51
|
name = "#{name}[]" if location == 'query' && schema[:type] == 'array'
|
32
|
-
|
52
|
+
|
53
|
+
ParameterTag.new(tag_name, name, description.strip, schema, location, required:)
|
54
|
+
rescue StandardError => e
|
55
|
+
raise TagParsingError, "Failed to parse parameter tag: #{e.message}"
|
33
56
|
end
|
34
57
|
|
35
58
|
# Parses a tag that represents a response.
|
@@ -37,8 +60,13 @@ module OasCore
|
|
37
60
|
# @param text [String] The tag text to parse.
|
38
61
|
# @return [ResponseTag] The parsed response tag object.
|
39
62
|
def parse_tag_with_response(tag_name, text)
|
40
|
-
|
41
|
-
|
63
|
+
description, raw_type = split_description_and_type(text.squish)
|
64
|
+
description, code = text_and_last_parenthesis_content(description)
|
65
|
+
content = raw_type_to_content(raw_type)
|
66
|
+
|
67
|
+
ResponseTag.new(tag_name, description, code, content)
|
68
|
+
rescue StandardError => e
|
69
|
+
raise TagParsingError, "Failed to parse response tag: #{e.message}"
|
42
70
|
end
|
43
71
|
|
44
72
|
# Parses a tag that represents a response example.
|
@@ -46,79 +74,67 @@ module OasCore
|
|
46
74
|
# @param text [String] The tag text to parse.
|
47
75
|
# @return [ResponseExampleTag] The parsed response example tag object.
|
48
76
|
def parse_tag_with_response_example(tag_name, text)
|
49
|
-
description,
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
private
|
77
|
+
description, raw_type = split_description_and_type(text.squish)
|
78
|
+
description, code = text_and_last_parenthesis_content(description)
|
79
|
+
content = raw_type_to_content(raw_type)
|
54
80
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# @return [Array] An array containing the description, type, and content or remaining text.
|
59
|
-
def extract_description_type_and_content(text, process_content: false, expresion: /^(.*?)\s*\[(.*)\]\s*(.*)$/)
|
60
|
-
match = text.match(expresion)
|
61
|
-
raise ArgumentError, "Invalid tag format: #{text}" if match.nil?
|
62
|
-
|
63
|
-
description = match[1].strip
|
64
|
-
type = match[2].strip
|
65
|
-
content = process_content ? eval_content(match[3].strip) : match[3].strip
|
66
|
-
|
67
|
-
[description, type, content]
|
81
|
+
ResponseExampleTag.new(tag_name, description, content: content, code:)
|
82
|
+
rescue StandardError => e
|
83
|
+
raise TagParsingError, "Failed to parse response example tag: #{e.message}"
|
68
84
|
end
|
69
85
|
|
70
|
-
#
|
71
|
-
# @param
|
72
|
-
# @
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
86
|
+
# Parses a tag that represents a parameter reference.
|
87
|
+
# @param tag_name [String] The name of the tag.
|
88
|
+
# @param text [String] The tag text to parse.
|
89
|
+
# @return [ParameterReferenceTag] The parsed parameter reference tag object.
|
90
|
+
def parse_tag_with_parameter_reference(tag_name, text)
|
91
|
+
ref = text.strip
|
92
|
+
reference = OasCore::Spec::Reference.new(ref)
|
93
|
+
ParameterReferenceTag.new(tag_name, reference)
|
94
|
+
rescue StandardError => e
|
95
|
+
raise TagParsingError, "Failed to parse parameter reference tag: #{e.message}"
|
79
96
|
end
|
80
97
|
|
81
|
-
#
|
82
|
-
# @param
|
83
|
-
# @
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
98
|
+
# Parses a tag that represents a request body reference.
|
99
|
+
# @param tag_name [String] The name of the tag.
|
100
|
+
# @param text [String] The tag text to parse.
|
101
|
+
# @return [RequestBodyReferenceTag] The parsed request body reference tag object.
|
102
|
+
def parse_tag_with_request_body_reference(tag_name, text)
|
103
|
+
ref = text.strip
|
104
|
+
reference = OasCore::Spec::Reference.new(ref)
|
105
|
+
RequestBodyReferenceTag.new(tag_name, reference)
|
106
|
+
rescue StandardError => e
|
107
|
+
raise TagParsingError, "Failed to parse request body reference tag: #{e.message}"
|
90
108
|
end
|
91
109
|
|
92
|
-
#
|
93
|
-
# @param
|
94
|
-
# @
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
110
|
+
# Parses a tag that represents a response reference.
|
111
|
+
# @param tag_name [String] The name of the tag.
|
112
|
+
# @param text [String] The tag text to parse.
|
113
|
+
# @return [ResponseReferenceTag] The parsed response reference tag object.
|
114
|
+
def parse_tag_with_response_reference(tag_name, text)
|
115
|
+
reference_str, code_text = text_and_first_parenthesis_content(text.strip)
|
116
|
+
reference = OasCore::Spec::Reference.new(reference_str)
|
117
|
+
ResponseReferenceTag.new(tag_name, reference, code: code_text.to_i)
|
118
|
+
rescue StandardError => e
|
119
|
+
raise TagParsingError, "Failed to parse response reference tag: #{e.message}"
|
100
120
|
end
|
101
121
|
|
102
|
-
|
103
|
-
# @param text [String] The text to parse.
|
104
|
-
# @return [Array] An array containing the name, code, and schema.
|
105
|
-
def extract_name_code_and_hash(text)
|
106
|
-
name, code = extract_text_and_parentheses_content(text)
|
107
|
-
_, _, content = extract_description_type_and_content(text, expresion: /^(.*?)\[([^\]]*)\](.*)$/m)
|
108
|
-
hash = eval_content(content)
|
109
|
-
[name, code, hash]
|
110
|
-
end
|
122
|
+
private
|
111
123
|
|
112
|
-
#
|
113
|
-
# @param
|
114
|
-
# @return [Hash] The
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
124
|
+
# Converts raw_type to content based on its format.
|
125
|
+
# @param raw_type [String] The raw type string to process.
|
126
|
+
# @return [Hash] The processed content.
|
127
|
+
def raw_type_to_content(raw_type)
|
128
|
+
if raw_type.start_with?('JSON')
|
129
|
+
json_string = raw_type.sub(/^JSON/, '').gsub(/'/, '"')
|
130
|
+
JSON.parse(json_string)
|
131
|
+
elsif raw_type.start_with?('Reference:')
|
132
|
+
ref = raw_type.sub(/^Reference:/, '').strip
|
133
|
+
OasCore::Spec::Reference.new(ref)
|
134
|
+
else
|
135
|
+
JsonSchemaGenerator.process_string(raw_type)[:json_schema]
|
136
|
+
end
|
120
137
|
end
|
121
|
-
# rubocop:enable Security/Eval
|
122
138
|
|
123
139
|
# Parses the position name and location from input text.
|
124
140
|
# @param input [String] The input text to parse.
|
@@ -142,26 +158,48 @@ module OasCore
|
|
142
158
|
end
|
143
159
|
end
|
144
160
|
|
145
|
-
#
|
161
|
+
# Splits the text into description with detail and type parts.
|
146
162
|
# @param text [String] The text to parse.
|
147
|
-
# @return [
|
148
|
-
def
|
149
|
-
match = text.match(/^(.*?)\s*\[(.*?)\]
|
150
|
-
raise
|
163
|
+
# @return [Array] An array containing the description with detail and the type.
|
164
|
+
def split_description_and_type(text)
|
165
|
+
match = text.match(/^(.*?)\s*\[(.*?)\]$/)
|
166
|
+
raise TagParsingError, "Invalid format: #{text}" if match.nil?
|
151
167
|
|
152
|
-
match
|
168
|
+
[match[1].strip, match[2].strip]
|
153
169
|
end
|
154
170
|
|
155
|
-
#
|
156
|
-
# @param text [String] The
|
157
|
-
# @return [Array] An array containing the
|
158
|
-
def
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
171
|
+
# Extracts the description and the detail (content of the last parentheses) from the text.
|
172
|
+
# @param text [String] The text to parse.
|
173
|
+
# @return [Array] An array containing the description and the detail.
|
174
|
+
def text_and_last_parenthesis_content(text)
|
175
|
+
# Find the last occurrence of parentheses
|
176
|
+
last_open = text.rindex('(')
|
177
|
+
last_close = text.rindex(')')
|
178
|
+
|
179
|
+
if last_open && last_close && last_open < last_close
|
180
|
+
description = text[0...last_open].strip
|
181
|
+
detail = text[(last_open + 1)...last_close].strip
|
182
|
+
[description, detail]
|
183
|
+
else
|
184
|
+
[text.strip, nil]
|
185
|
+
end
|
186
|
+
end
|
163
187
|
|
164
|
-
|
188
|
+
# Extracts the first occurrence of content inside parentheses and the rest of the text.
|
189
|
+
# @param text [String] The text to parse.
|
190
|
+
# @return [Array] An array containing the rest of the text and the first detail in parentheses.
|
191
|
+
def text_and_first_parenthesis_content(text)
|
192
|
+
# Find the first occurrence of parentheses
|
193
|
+
first_open = text.index('(')
|
194
|
+
first_close = text.index(')')
|
195
|
+
|
196
|
+
if first_open && first_close && first_open < first_close
|
197
|
+
detail = text[(first_open + 1)...first_close].strip
|
198
|
+
rest = (text[0...first_open] + text[(first_close + 1)..]).strip
|
199
|
+
[rest, detail]
|
200
|
+
else
|
201
|
+
[text.strip, nil]
|
202
|
+
end
|
165
203
|
end
|
166
204
|
end
|
167
205
|
end
|
@@ -5,11 +5,11 @@ module OasCore
|
|
5
5
|
class ParameterTag < ::YARD::Tags::Tag
|
6
6
|
attr_accessor :schema, :required, :location
|
7
7
|
|
8
|
-
def initialize(tag_name, name, text,
|
8
|
+
def initialize(tag_name, name, text, *args, **kwargs)
|
9
9
|
super(tag_name, text, nil, name)
|
10
|
-
@schema = schema
|
11
|
-
@
|
12
|
-
@
|
10
|
+
@schema = args[0] || kwargs.fetch(:schema, nil)
|
11
|
+
@location = args[1] || kwargs.fetch(:location, nil)
|
12
|
+
@required = kwargs.fetch(:required, false)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OasCore
|
4
|
+
module YARD
|
5
|
+
class ReferenceTag < ::YARD::Tags::Tag
|
6
|
+
attr_accessor :reference
|
7
|
+
|
8
|
+
def initialize(tag_name, reference)
|
9
|
+
super(tag_name, nil, nil, nil)
|
10
|
+
@reference = reference
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -3,13 +3,12 @@
|
|
3
3
|
module OasCore
|
4
4
|
module YARD
|
5
5
|
class RequestBodyTag < ::YARD::Tags::Tag
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :content, :required, :content_type
|
7
7
|
|
8
|
-
def initialize(tag_name, text,
|
8
|
+
def initialize(tag_name, text, content: nil, required: false, content_type: 'application/json')
|
9
9
|
# initialize(tag_name, text, types = nil, name = nil)
|
10
10
|
super(tag_name, text, nil, nil)
|
11
|
-
@
|
12
|
-
@schema = schema
|
11
|
+
@content = content
|
13
12
|
@required = required
|
14
13
|
@content_type = content_type
|
15
14
|
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module OasCore
|
4
4
|
module YARD
|
5
5
|
class ResponseTag < ::YARD::Tags::Tag
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :content, :code
|
7
7
|
|
8
8
|
# TODO: name == code. The name MUST be changed to code for better understanding
|
9
|
-
def initialize(tag_name,
|
10
|
-
super(tag_name,
|
11
|
-
@
|
9
|
+
def initialize(tag_name, description, code, content)
|
10
|
+
super(tag_name, description, nil, nil)
|
11
|
+
@code = code
|
12
|
+
@content = content
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
data/lib/oas_core.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'yard'
|
4
4
|
require 'method_source'
|
5
5
|
require 'active_support/all'
|
6
|
+
require 'deep_merge'
|
6
7
|
|
7
8
|
module OasCore
|
8
9
|
require 'oas_core/version'
|
@@ -49,11 +50,16 @@ module OasCore
|
|
49
50
|
module YARD
|
50
51
|
autoload :RequestBodyTag, 'oas_core/yard/request_body_tag'
|
51
52
|
autoload :ExampleTag, 'oas_core/yard/example_tag'
|
53
|
+
autoload :ReferenceTag, 'oas_core/yard/reference_tag'
|
52
54
|
autoload :RequestBodyExampleTag, 'oas_core/yard/request_body_example_tag'
|
53
55
|
autoload :ParameterTag, 'oas_core/yard/parameter_tag'
|
54
56
|
autoload :ResponseTag, 'oas_core/yard/response_tag'
|
55
57
|
autoload :ResponseExampleTag, 'oas_core/yard/response_example_tag'
|
56
58
|
autoload :OasCoreFactory, 'oas_core/yard/oas_core_factory'
|
59
|
+
|
60
|
+
autoload :ParameterReferenceTag, 'oas_core/yard/parameter_reference_tag'
|
61
|
+
autoload :RequestBodyReferenceTag, 'oas_core/yard/request_body_reference_tag'
|
62
|
+
autoload :ResponseReferenceTag, 'oas_core/yard/response_reference_tag'
|
57
63
|
end
|
58
64
|
|
59
65
|
class << self
|
@@ -71,9 +77,12 @@ module OasCore
|
|
71
77
|
::YARD::Tags::Library.default_factory = YARD::OasCoreFactory
|
72
78
|
yard_tags = {
|
73
79
|
'Request body' => %i[request_body with_request_body],
|
80
|
+
'Request body Reference' => %i[request_body_ref with_request_body_reference],
|
74
81
|
'Request body Example' => %i[request_body_example with_request_body_example],
|
75
82
|
'Parameter' => %i[parameter with_parameter],
|
83
|
+
'Parameter Reference' => %i[parameter_ref with_parameter_reference],
|
76
84
|
'Response' => %i[response with_response],
|
85
|
+
'Response Reference' => %i[response_ref with_response_reference],
|
77
86
|
'Response Example' => %i[response_example with_response_example],
|
78
87
|
'Endpoint Tags' => [:tags],
|
79
88
|
'Summary' => [:summary],
|
@@ -85,5 +94,11 @@ module OasCore
|
|
85
94
|
::YARD::Tags::Library.define_tag(tag_name, method_name, handler)
|
86
95
|
end
|
87
96
|
end
|
97
|
+
|
98
|
+
def build(oas_routes, oas_source: {})
|
99
|
+
oas = Builders::SpecificationBuilder.new.with_oas_routes(oas_routes).build.to_spec
|
100
|
+
|
101
|
+
oas_source.deep_merge(oas, merge_hash_arrays: true, extend_existing_arrays: true)
|
102
|
+
end
|
88
103
|
end
|
89
104
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oas_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- a-chacon
|
@@ -23,6 +23,26 @@ dependencies:
|
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: '7.0'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: deep_merge
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.2'
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.2.2
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.2'
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.2.2
|
26
46
|
- !ruby/object:Gem::Dependency
|
27
47
|
name: method_source
|
28
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,16 +118,22 @@ files:
|
|
98
118
|
- lib/oas_core/version.rb
|
99
119
|
- lib/oas_core/yard/example_tag.rb
|
100
120
|
- lib/oas_core/yard/oas_core_factory.rb
|
121
|
+
- lib/oas_core/yard/parameter_reference_tag.rb
|
101
122
|
- lib/oas_core/yard/parameter_tag.rb
|
123
|
+
- lib/oas_core/yard/reference_tag.rb
|
102
124
|
- lib/oas_core/yard/request_body_example_tag.rb
|
125
|
+
- lib/oas_core/yard/request_body_reference_tag.rb
|
103
126
|
- lib/oas_core/yard/request_body_tag.rb
|
104
127
|
- lib/oas_core/yard/response_example_tag.rb
|
128
|
+
- lib/oas_core/yard/response_reference_tag.rb
|
105
129
|
- lib/oas_core/yard/response_tag.rb
|
106
130
|
homepage: https://github.com/a-chacon/oas_core
|
107
131
|
licenses:
|
108
132
|
- GPL-3.0-only
|
109
133
|
metadata:
|
110
134
|
homepage_uri: https://github.com/a-chacon/oas_core
|
135
|
+
source_code_uri: https://github.com/a-chacon/oas_core
|
136
|
+
changelog_uri: https://github.com/a-chacon/oas_core/blob/main/CHANGELOG.md
|
111
137
|
rubygems_mfa_required: 'true'
|
112
138
|
rdoc_options: []
|
113
139
|
require_paths:
|