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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5db442aede360ce867a790d610a1fd52ca99149fae66d7122d18061cb2ac389
4
- data.tar.gz: 30d3c64645a15f11b6e2d96326e987f31b0623e500a56c49194e80589e7303d1
3
+ metadata.gz: b329db4c1e00be2afbb4160dff2feb3e3be2dfb0feab05b2b6f591045fe953b4
4
+ data.tar.gz: 3eff127300b99d73b3a15d86c0edba9bdb30f404500e35890aec1498a5f73337
5
5
  SHA512:
6
- metadata.gz: 70b9295d1b016210832c30b2d233683efa045797c5113e80bd959dfa6a6888c414f3a60e01ded946f63d50d51cd79cdae58514c2d8b483bfec29be71a89b83bd
7
- data.tar.gz: af2fa9e9322ed357a2074336a2e536d8ebb3c955692bd1b6a85812fe788fc4d5f19b0b1ecc57ce99c82b118fb7b5024a276d54edbb3560ab594b718c80e88ccd
6
+ metadata.gz: 1d2af39e3de24f4ee4f3dbefa8206dde25648274793bcecfdca183faedfd7d6622bb60552ae7134b9abda3ccb667f285884957cc542f045ecc71b6f2da4b6138
7
+ data.tar.gz: ad96bf7677bf7d8c1d8b438f79f9c3d743f4184c9351c82eceeea5e5bc7d7dd97d039cba51eca4e0c8bd013bc6be96c8558aa61de41d87de2faacb008d3fe31e
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.0
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?
@@ -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
 
@@ -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
@@ -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
 
@@ -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(: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) }
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
@@ -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/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]
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.0
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: 2022-05-20 00:00:00.000000000 Z
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.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.