openapi_first 0.21.0 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rack'
4
-
5
- module OpenapiFirst
6
- class App
7
- def initialize( # rubocop:disable Metrics/ParameterLists
8
- parent_app,
9
- spec,
10
- namespace:,
11
- router_raise_error: false,
12
- request_validation_raise_error: false,
13
- response_validation: false,
14
- resolver: nil
15
- )
16
- @stack = Rack::Builder.app do
17
- freeze_app
18
- use OpenapiFirst::Router, spec: spec, raise_error: router_raise_error, parent_app: parent_app
19
- use OpenapiFirst::RequestValidation, raise_error: request_validation_raise_error
20
- use OpenapiFirst::ResponseValidation if response_validation
21
- run OpenapiFirst::Responder.new(namespace: namespace, resolver: resolver)
22
- end
23
- end
24
-
25
- def call(env)
26
- @stack.call(env)
27
- end
28
- end
29
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenapiFirst
4
- class Coverage
5
- attr_reader :to_be_called
6
-
7
- def initialize(app, spec)
8
- @app = app
9
- @spec = spec
10
- @to_be_called = spec.operations.map do |operation|
11
- endpoint_id(operation)
12
- end
13
- end
14
-
15
- def call(env)
16
- response = @app.call(env)
17
- operation = env[OPERATION]
18
- @to_be_called.delete(endpoint_id(operation)) if operation
19
- response
20
- end
21
-
22
- private
23
-
24
- def endpoint_id(operation)
25
- "#{operation.path}##{operation.method}"
26
- end
27
- end
28
- end
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'utils'
4
-
5
- module OpenapiFirst
6
- class DefaultOperationResolver
7
- def initialize(namespace)
8
- @namespace = namespace
9
- @handlers = {}
10
- end
11
-
12
- def call(operation)
13
- @handlers[operation.name] ||= begin
14
- id = handler_id(operation)
15
- find_handler(id) if id
16
- end
17
- end
18
-
19
- def find_handler(id)
20
- name = id.match(/:*(.*)/)&.to_a&.at(1)
21
- return if name.nil?
22
-
23
- catch :halt do
24
- return find_class_method_handler(name) if name.include?('.')
25
- return find_instance_method_handler(name) if name.include?('#')
26
- end
27
- method_name = Utils.underscore(name)
28
- return unless @namespace.respond_to?(method_name)
29
-
30
- @namespace.method(method_name)
31
- end
32
-
33
- def handler_id(operation)
34
- id = operation['x-handler'] || operation['operationId']
35
- if id.nil?
36
- raise HandlerNotFoundError,
37
- "operationId or x-handler is missing in '#{operation.method} #{operation.path}' so I cannot find a handler for this operation." # rubocop:disable Layout/LineLength
38
- end
39
-
40
- id
41
- end
42
-
43
- def find_class_method_handler(name)
44
- module_name, method_name = name.split('.')
45
- klass = find_const(@namespace, module_name)
46
- klass.method(Utils.underscore(method_name))
47
- end
48
-
49
- def find_instance_method_handler(name)
50
- module_name, klass_name = name.split('#')
51
- const = find_const(@namespace, module_name)
52
- klass = find_const(const, klass_name)
53
- klass.new
54
- end
55
-
56
- def find_const(parent, name)
57
- name = Utils.classify(name)
58
- throw :halt unless parent.const_defined?(name, false)
59
-
60
- parent.const_get(name, false)
61
- end
62
- end
63
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenapiFirst
4
- # An instance of this gets passed to handler functions in the Responder.
5
- class Inbox < Hash
6
- attr_reader :env
7
-
8
- def initialize(env)
9
- @env = env
10
- super()
11
- end
12
- end
13
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'responder'
4
-
5
- module OpenapiFirst
6
- class RackResponder < Responder
7
- def call(env)
8
- operation = env[OpenapiFirst::OPERATION]
9
- find_handler(operation)&.call(env)
10
- end
11
- end
12
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rack'
4
- require 'multi_json'
5
- require_relative 'inbox'
6
- require_relative 'default_operation_resolver'
7
-
8
- module OpenapiFirst
9
- class Responder
10
- def initialize(namespace: nil, resolver: nil)
11
- @resolver = resolver || DefaultOperationResolver.new(namespace)
12
- @namespace = namespace
13
- end
14
-
15
- def call(env)
16
- operation = env[OpenapiFirst::OPERATION]
17
- res = Rack::Response.new
18
- handler = find_handler(operation)
19
- result = handler.call(inbox(env), res)
20
- res.write serialize(result) if result && res.body.empty?
21
- res[Rack::CONTENT_TYPE] ||= operation.content_types_for(res.status)&.first
22
- res.finish
23
- end
24
-
25
- private
26
-
27
- def inbox(env)
28
- Inbox.new(env).tap { |i| i.merge!(env[INBOX]) if env[INBOX] }
29
- end
30
-
31
- def find_handler(operation)
32
- handler = @resolver.call(operation)
33
- raise NotImplementedError, "Could not find handler for #{operation.name}" unless handler
34
-
35
- handler
36
- end
37
-
38
- def serialize(result)
39
- return result if result.is_a?(String)
40
-
41
- MultiJson.dump(result)
42
- end
43
- end
44
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'forwardable'
4
-
5
- module OpenapiFirst
6
- # Represents an OpenAPI Response Object
7
- class ResponseObject
8
- extend Forwardable
9
- def_delegators :@parsed,
10
- :content
11
-
12
- def_delegators :@raw,
13
- :[]
14
-
15
- def initialize(parsed)
16
- @parsed = parsed
17
- @raw = parsed.raw
18
- end
19
- end
20
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenapiFirst
4
- class Validation
5
- attr_reader :errors
6
-
7
- def initialize(errors)
8
- @errors = errors
9
- end
10
-
11
- def errors?
12
- !errors.empty?
13
- end
14
- end
15
- end