apia 3.2.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9eccaade7623f6fc8ecae88bb8c87da23d4a436a2d76801ac6dbd2d57db9efe
4
- data.tar.gz: c77009793790064a1f6219b6a362128359d2e98a0ccc7c8215d184f7afa36b5b
3
+ metadata.gz: f40c9dba04e5b064ced8833f9edb42f96efd59c9d4e9342a4fa6535a1e76c6ee
4
+ data.tar.gz: 2506e79260735d3c2029ac7eaa9733e481b975b177506f03fcdeba21760b8781
5
5
  SHA512:
6
- metadata.gz: 3dc391ac5e8ad44636978220ceeb55bef47b10ba03f5826e371ed4041e428873ed59d351447d3345817e3bbb8b25bfafc6ecd01f4f86745ddc1d0851c2bc19a2
7
- data.tar.gz: 2f92e720ce247b4408c21bc5a4096137ef75433b10c8712c4d2d115f8d4a33def15509bd5a7af05fd1bfffed9e465e57dac6cd4f5422e3aa2278e12aa0727664
6
+ metadata.gz: 7ae74d9f396b7dda8d14513d072f3e7f0902724c5b3e8bd0a430341f8d1e91dd83e4e6aae0b377dc954e3f248c5da7ba3984da354202fa42043c1e5d8d0e5ba7
7
+ data.tar.gz: 7e735b6a11cfc48325cd60ce0d01a36cb9eb776afeb2b74c3efe8de034b02413df3c8cec149b9ffa0883af4c85d4f631d7cc9f67e63c169e3fbcaeb4d0dbe517
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?
@@ -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\-]+\z/i
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
 
@@ -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
 
@@ -60,7 +60,7 @@ module Apia
60
60
 
61
61
  argument :per_page, type: Scalars::Integer, default: 30 do
62
62
  validation(:greater_than_zero) { |o| o.positive? }
63
- validation(:less_than_or_equal_to_100) { |o| o <= (pagination_options[:maximum_per_page]&.to_i || 200) }
63
+ validation(:less_than_or_equal_to_one_hundred) { |o| o <= (pagination_options[:maximum_per_page]&.to_i || 200) }
64
64
  end
65
65
 
66
66
  field :pagination, type: PaginationObject
@@ -5,6 +5,7 @@ require 'apia/scalar'
5
5
  require 'apia/object'
6
6
  require 'apia/enum'
7
7
  require 'apia/field_spec'
8
+ require 'apia/generated_hash'
8
9
 
9
10
  module Apia
10
11
  class FieldSet < Hash
@@ -35,10 +36,12 @@ module Apia
35
36
  #
36
37
  # @param source [Object, Hash]
37
38
  # @param request [Apia::Request]
39
+ # @param object [Apia::Object] the object that this fieldset belongs to
38
40
  # @param only [Array]
39
41
  # @return [Hash]
40
- def generate_hash(source, request: nil, path: [])
41
- each_with_object({}) do |(_, field), hash|
42
+ def generate_hash(source, request: nil, path: [], object: nil)
43
+ new_hash = GeneratedHash.enabled? ? GeneratedHash.new(object, source, path: path) : {}
44
+ each_with_object(new_hash) do |(_, field), hash|
42
45
  next unless field.include?(source, request)
43
46
 
44
47
  field_path = path + [field]
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apia
4
+ class GeneratedHash < Hash
5
+
6
+ attr_reader :object
7
+ attr_reader :source
8
+ attr_reader :path
9
+
10
+ def initialize(object, source, path: nil)
11
+ super()
12
+ @object = object
13
+ @source = source
14
+ @path = path
15
+ end
16
+
17
+ class << self
18
+
19
+ def enabled?
20
+ @enabled == true
21
+ end
22
+
23
+ def enable
24
+ @enabled = true
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -15,8 +15,9 @@ module Apia
15
15
  end
16
16
  end
17
17
 
18
- def add_handler(&block)
19
- handlers.push(block)
18
+ def add_handler(handler = nil, &block)
19
+ handlers.push(block) if block
20
+ handlers.push(handler) if handler
20
21
  end
21
22
 
22
23
  def clear_handlers
data/lib/apia/object.rb CHANGED
@@ -49,7 +49,7 @@ module Apia
49
49
  # @param request [Apia::Request] the associated request
50
50
  # @return [Hash]
51
51
  def hash(request: nil, path: [])
52
- self.class.definition.fields.generate_hash(@value, request: request, path: path)
52
+ self.class.definition.fields.generate_hash(@value, object: self, request: request, path: path)
53
53
  end
54
54
 
55
55
  # Should this type be included in any output?
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
- if env['REQUEST_METHOD'].upcase == 'OPTIONS'
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(env['REQUEST_METHOD'], api_path)
88
+ route = find_route(request_method, api_path)
83
89
  if route.nil?
84
- raise RackError.new(404, 'route_not_found', "No route matches '#{api_path}' for #{env['REQUEST_METHOD']}")
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, { request: request, response: response, time: (end_time - start_time).to_f })
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
- if e.is_a?(RackError) || e.is_a?(Apia::ManifestError)
104
- return e.triplet
105
- end
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
- request_or_nil = defined?(request) ? request : nil
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(e, {
126
+ api.definition.exception_handlers.call(exception, {
110
127
  env: env,
111
128
  api: api,
112
- request: request_or_nil
129
+ request: request
113
130
  })
114
131
 
115
- Apia::Notifications.notify(:request_error, { exception: e, request: request_or_nil, api: api, env: env })
132
+ Apia::Notifications.notify(:request_error, notify_hash)
116
133
 
117
134
  if development?
118
- return triplet_for_exception(e)
135
+ return triplet_for_exception(exception)
119
136
  end
120
137
 
121
138
  self.class.error_triplet('unhandled_exception', status: 500)
@@ -26,7 +26,7 @@ module Apia
26
26
  end
27
27
 
28
28
  def create_from_request(request)
29
- hash = request.each_header.each_with_object({}) do |(key, value), inner_hash|
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.each_with_object({}) do |(part, index), hash|
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]
data/lib/apia/version.rb CHANGED
@@ -2,11 +2,6 @@
2
2
 
3
3
  module Apia
4
4
 
5
- VERSION_FILE_ROOT = File.expand_path('../../VERSION', __dir__)
6
- if File.file?(VERSION_FILE_ROOT)
7
- VERSION = File.read(VERSION_FILE_ROOT).strip.sub(/\Av/, '')
8
- else
9
- VERSION = '0.0.0.dev'
10
- end
5
+ VERSION = '3.4.0'
11
6
 
12
7
  end
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.2.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Cooke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-26 00:00:00.000000000 Z
11
+ date: 2023-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -45,7 +45,6 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - VERSION
49
48
  - lib/apia.rb
50
49
  - lib/apia/api.rb
51
50
  - lib/apia/argument_set.rb
@@ -110,6 +109,7 @@ files:
110
109
  - lib/apia/errors/standard_error.rb
111
110
  - lib/apia/field_set.rb
112
111
  - lib/apia/field_spec.rb
112
+ - lib/apia/generated_hash.rb
113
113
  - lib/apia/helpers.rb
114
114
  - lib/apia/hook_set.rb
115
115
  - lib/apia/lookup_argument_set.rb
@@ -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.1.6
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.
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 3.2.0