apia 3.1.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/apia/api.rb +1 -1
- data/lib/apia/definitions/api.rb +1 -1
- data/lib/apia/definitions/endpoint.rb +13 -0
- data/lib/apia/dsls/controller.rb +1 -1
- data/lib/apia/dsls/endpoint.rb +9 -1
- data/lib/apia/notifications.rb +3 -2
- data/lib/apia/rack.rb +29 -12
- data/lib/apia/request_headers.rb +1 -1
- data/lib/apia/route.rb +1 -1
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b329db4c1e00be2afbb4160dff2feb3e3be2dfb0feab05b2b6f591045fe953b4
         | 
| 4 | 
            +
              data.tar.gz: 3eff127300b99d73b3a15d86c0edba9bdb30f404500e35890aec1498a5f73337
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1d2af39e3de24f4ee4f3dbefa8206dde25648274793bcecfdca183faedfd7d6622bb60552ae7134b9abda3ccb667f285884957cc542f045ecc71b6f2da4b6138
         | 
| 7 | 
            +
              data.tar.gz: ad96bf7677bf7d8c1d8b438f79f9c3d743f4184c9351c82eceeea5e5bc7d7dd97d039cba51eca4e0c8bd013bc6be96c8558aa61de41d87de2faacb008d3fe31e
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            3.1 | 
| 1 | 
            +
            3.3.1
         | 
    
        data/lib/apia/api.rb
    CHANGED
    
    | @@ -79,7 +79,7 @@ module Apia | |
| 79 79 | 
             
                  # @param endpoint_name [Symbol]
         | 
| 80 80 | 
             
                  # @return [Apia::Response]
         | 
| 81 81 | 
             
                  def test_endpoint(endpoint, controller: nil)
         | 
| 82 | 
            -
                    if controller && endpoint.is_a?(Symbol) || endpoint.is_a?(String)
         | 
| 82 | 
            +
                    if controller && (endpoint.is_a?(Symbol) || endpoint.is_a?(String))
         | 
| 83 83 | 
             
                      endpoint_name = endpoint
         | 
| 84 84 | 
             
                      endpoint = controller.definition.endpoints[endpoint.to_sym]
         | 
| 85 85 | 
             
                      if endpoint.nil?
         | 
    
        data/lib/apia/definitions/api.rb
    CHANGED
    
    | @@ -36,7 +36,7 @@ module Apia | |
| 36 36 | 
             
                    end
         | 
| 37 37 |  | 
| 38 38 | 
             
                    @controllers.each do |name, controller|
         | 
| 39 | 
            -
                      unless name.to_s =~ /\A[\w | 
| 39 | 
            +
                      unless name.to_s =~ /\A[\w-]+\z/i
         | 
| 40 40 | 
             
                        errors.add self, 'InvalidControllerName', "The controller name #{name} is invalid. It can only contain letters, numbers, underscores, and hyphens"
         | 
| 41 41 | 
             
                      end
         | 
| 42 42 |  | 
| @@ -36,6 +36,19 @@ module Apia | |
| 36 36 | 
             
                    @potential_errors ||= Apia::ErrorSet.new
         | 
| 37 37 | 
             
                  end
         | 
| 38 38 |  | 
| 39 | 
            +
                  def fields=(fieldset)
         | 
| 40 | 
            +
                    unless @fields.empty?
         | 
| 41 | 
            +
                      raise Apia::StandardError, 'Cannot set the fieldset on an endpoint that already has fields defined'
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    @fields = fieldset
         | 
| 45 | 
            +
                    @fields_overriden = true
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def fields_overriden?
         | 
| 49 | 
            +
                    @fields_overriden == true
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 39 52 | 
             
                  def dsl
         | 
| 40 53 | 
             
                    @dsl ||= DSLs::Endpoint.new(self)
         | 
| 41 54 | 
             
                  end
         | 
    
        data/lib/apia/dsls/controller.rb
    CHANGED
    
    | @@ -18,7 +18,7 @@ module Apia | |
| 18 18 |  | 
| 19 19 | 
             
                  def endpoint(name, klass = nil, &block)
         | 
| 20 20 | 
             
                    if block_given?
         | 
| 21 | 
            -
                      id = "#{@definition.id}/#{klass || Helpers.camelize(name) + 'Endpoint'}"
         | 
| 21 | 
            +
                      id = "#{@definition.id}/#{klass || (Helpers.camelize(name) + 'Endpoint')}"
         | 
| 22 22 | 
             
                      klass = Apia::Endpoint.create(id, &block)
         | 
| 23 23 | 
             
                    end
         | 
| 24 24 |  | 
    
        data/lib/apia/dsls/endpoint.rb
    CHANGED
    
    | @@ -41,6 +41,10 @@ module Apia | |
| 41 41 | 
             
                  end
         | 
| 42 42 |  | 
| 43 43 | 
             
                  def field(name, *args, type: nil, **options, &block)
         | 
| 44 | 
            +
                    if @definition.fields_overriden?
         | 
| 45 | 
            +
                      raise Apia::StandardError, 'Cannot add fields to an endpoint that has a separate fieldset'
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 44 48 | 
             
                    if pagination_options = options.delete(:paginate)
         | 
| 45 49 |  | 
| 46 50 | 
             
                      unless @definition.paginated_field.nil?
         | 
| @@ -56,7 +60,7 @@ module Apia | |
| 56 60 |  | 
| 57 61 | 
             
                      argument :per_page, type: Scalars::Integer, default: 30 do
         | 
| 58 62 | 
             
                        validation(:greater_than_zero) { |o| o.positive? }
         | 
| 59 | 
            -
                        validation(: | 
| 63 | 
            +
                        validation(:less_than_or_equal_to_one_hundred) { |o| o <= (pagination_options[:maximum_per_page]&.to_i || 200) }
         | 
| 60 64 | 
             
                      end
         | 
| 61 65 |  | 
| 62 66 | 
             
                      field :pagination, type: PaginationObject
         | 
| @@ -64,6 +68,10 @@ module Apia | |
| 64 68 | 
             
                    super(name, *args, type: type, **options, &block)
         | 
| 65 69 | 
             
                  end
         | 
| 66 70 |  | 
| 71 | 
            +
                  def fields(fieldset)
         | 
| 72 | 
            +
                    @definition.fields = fieldset
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 67 75 | 
             
                  def scopes(*names)
         | 
| 68 76 | 
             
                    names.each { |name| scope(name) }
         | 
| 69 77 | 
             
                  end
         | 
    
        data/lib/apia/notifications.rb
    CHANGED
    
    
    
        data/lib/apia/rack.rb
    CHANGED
    
    | @@ -73,15 +73,22 @@ module Apia | |
| 73 73 | 
             
                private
         | 
| 74 74 |  | 
| 75 75 | 
             
                def handle_request(env, api_path)
         | 
| 76 | 
            -
                   | 
| 76 | 
            +
                  request = nil
         | 
| 77 | 
            +
                  request_method = env['REQUEST_METHOD'].upcase
         | 
| 78 | 
            +
                  notify_hash = { api: api, env: env, path: api_path, method: request_method }
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  if request_method.upcase == 'OPTIONS'
         | 
| 77 81 | 
             
                    return [204, {}, ['']]
         | 
| 78 82 | 
             
                  end
         | 
| 79 83 |  | 
| 84 | 
            +
                  Apia::Notifications.notify(:request_start, notify_hash)
         | 
| 85 | 
            +
             | 
| 80 86 | 
             
                  validate_api if development?
         | 
| 81 87 |  | 
| 82 | 
            -
                  route = find_route( | 
| 88 | 
            +
                  route = find_route(request_method, api_path)
         | 
| 83 89 | 
             
                  if route.nil?
         | 
| 84 | 
            -
                     | 
| 90 | 
            +
                    Apia::Notifications.notify(:request_route_not_found, notify_hash)
         | 
| 91 | 
            +
                    raise RackError.new(404, 'route_not_found', "No route matches '#{api_path}' for #{request_method}")
         | 
| 85 92 | 
             
                  end
         | 
| 86 93 |  | 
| 87 94 | 
             
                  request = Apia::Request.new(env)
         | 
| @@ -92,30 +99,40 @@ module Apia | |
| 92 99 | 
             
                  request.endpoint = route.endpoint
         | 
| 93 100 | 
             
                  request.route = route
         | 
| 94 101 |  | 
| 102 | 
            +
                  Apia::Notifications.notify(:request_before_execution, notify_hash.merge(request: request))
         | 
| 103 | 
            +
             | 
| 95 104 | 
             
                  start_time = Time.now
         | 
| 96 105 | 
             
                  response = request.endpoint.execute(request)
         | 
| 97 106 | 
             
                  end_time = Time.now
         | 
| 107 | 
            +
                  time = end_time - start_time
         | 
| 98 108 |  | 
| 99 | 
            -
                  Apia::Notifications.notify(:request,  | 
| 109 | 
            +
                  Apia::Notifications.notify(:request, notify_hash.merge(request: request, response: response, time: time))
         | 
| 100 110 |  | 
| 101 111 | 
             
                  response.rack_triplet
         | 
| 102 112 | 
             
                rescue ::StandardError => e
         | 
| 103 | 
            -
                   | 
| 104 | 
            -
             | 
| 105 | 
            -
                   | 
| 113 | 
            +
                  handle_error(e, env, request, request_method)
         | 
| 114 | 
            +
                ensure
         | 
| 115 | 
            +
                  Apia::Notifications.notify(:request_end, notify_hash)
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                def handle_error(exception, env, request, request_method)
         | 
| 119 | 
            +
                  notify_hash = { api: api, env: env, path: request&.api_path, request: request, method: request_method, exception: exception }
         | 
| 106 120 |  | 
| 107 | 
            -
                   | 
| 121 | 
            +
                  if exception.is_a?(RackError) || exception.is_a?(Apia::ManifestError)
         | 
| 122 | 
            +
                    Apia::Notifications.notify(:request_manifest_error, notify_hash)
         | 
| 123 | 
            +
                    return exception.triplet
         | 
| 124 | 
            +
                  end
         | 
| 108 125 |  | 
| 109 | 
            -
                  api.definition.exception_handlers.call( | 
| 126 | 
            +
                  api.definition.exception_handlers.call(exception, {
         | 
| 110 127 | 
             
                    env: env,
         | 
| 111 128 | 
             
                    api: api,
         | 
| 112 | 
            -
                    request:  | 
| 129 | 
            +
                    request: request
         | 
| 113 130 | 
             
                  })
         | 
| 114 131 |  | 
| 115 | 
            -
                  Apia::Notifications.notify(:request_error,  | 
| 132 | 
            +
                  Apia::Notifications.notify(:request_error, notify_hash)
         | 
| 116 133 |  | 
| 117 134 | 
             
                  if development?
         | 
| 118 | 
            -
                    return triplet_for_exception( | 
| 135 | 
            +
                    return triplet_for_exception(exception)
         | 
| 119 136 | 
             
                  end
         | 
| 120 137 |  | 
| 121 138 | 
             
                  self.class.error_triplet('unhandled_exception', status: 500)
         | 
    
        data/lib/apia/request_headers.rb
    CHANGED
    
    | @@ -26,7 +26,7 @@ module Apia | |
| 26 26 | 
             
                  end
         | 
| 27 27 |  | 
| 28 28 | 
             
                  def create_from_request(request)
         | 
| 29 | 
            -
                    hash = request.each_header. | 
| 29 | 
            +
                    hash = request.each_header.with_object({}) do |(key, value), inner_hash|
         | 
| 30 30 | 
             
                      next unless key =~ /\AHTTP_(\w+)\z/
         | 
| 31 31 |  | 
| 32 32 | 
             
                      name = Regexp.last_match[1]
         | 
    
        data/lib/apia/route.rb
    CHANGED
    
    | @@ -49,7 +49,7 @@ module Apia | |
| 49 49 | 
             
                # @return [Hash]
         | 
| 50 50 | 
             
                def extract_arguments(given_path)
         | 
| 51 51 | 
             
                  given_path_parts = RouteSet.split_path(given_path)
         | 
| 52 | 
            -
                  path_parts.each_with_index. | 
| 52 | 
            +
                  path_parts.each_with_index.with_object({}) do |(part, index), hash|
         | 
| 53 53 | 
             
                    next unless part =~ /\A:(\w+)/
         | 
| 54 54 |  | 
| 55 55 | 
             
                    value = given_path_parts[index]
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: apia
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3.1 | 
| 4 | 
            +
              version: 3.3.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Adam Cooke
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2023-03-14 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: json
         | 
| @@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 184 184 | 
             
                - !ruby/object:Gem::Version
         | 
| 185 185 | 
             
                  version: '0'
         | 
| 186 186 | 
             
            requirements: []
         | 
| 187 | 
            -
            rubygems_version: 3. | 
| 187 | 
            +
            rubygems_version: 3.3.26
         | 
| 188 188 | 
             
            signing_key: 
         | 
| 189 189 | 
             
            specification_version: 4
         | 
| 190 190 | 
             
            summary: This gem provides a friendly DSL for constructing HTTP APIs.
         |