jsonapi_errors_handler 0.2.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/gem-push.yml +31 -0
- data/.github/workflows/gem-test.yml +29 -0
- data/.rubocop.yml +11 -0
- data/.ruby-version +1 -1
- data/CONTRIBUTING.md +21 -13
- data/Gemfile.lock +27 -18
- data/README.md +27 -8
- data/jsonapi_errors_handler.gemspec +8 -3
- data/lib/jsonapi_errors_handler/configuration.rb +10 -1
- data/lib/jsonapi_errors_handler/error_mapper.rb +10 -4
- data/lib/jsonapi_errors_handler/error_serializer.rb +2 -0
- data/lib/jsonapi_errors_handler/errors/forbidden.rb +2 -0
- data/lib/jsonapi_errors_handler/errors/invalid.rb +2 -0
- data/lib/jsonapi_errors_handler/errors/not_found.rb +2 -0
- data/lib/jsonapi_errors_handler/errors/standard_error.rb +8 -3
- data/lib/jsonapi_errors_handler/errors/unauthorized.rb +2 -0
- data/lib/jsonapi_errors_handler/errors.rb +2 -0
- data/lib/jsonapi_errors_handler/keys_stringifier.rb +2 -0
- data/lib/jsonapi_errors_handler/version.rb +1 -1
- data/lib/jsonapi_errors_handler.rb +32 -14
- data/package-lock.json +634 -2044
- data/package.json +8 -1
- metadata +50 -20
- data/.circleci/config.yml +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31413f8cbc86bedcb155eb0574b6675ab75133b9ca4fec4721e7fc6b96bce447
|
4
|
+
data.tar.gz: 4d308a155c082df85e91b35d54f0b0c491e7db6905ef756f73493259223fc6b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87a8f68e263dbf1c1c7352ae1c5a9ce3294a4bdf4fe00bf1d60356ace9cea210ebf737047b003c183d22408a44f4e7edfa2bb3183f9df5da3c6d90d18a74f385
|
7
|
+
data.tar.gz: 25e5082f2cceb2f40c50c8ee3d572312b3f6803d3deb0eb7eccf06875451f74a8765e419ac72ce3175a7c95007014919ab47dccd7c399c0d7ead268833c4b2a7
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Test & Release
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ release ]
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
build:
|
9
|
+
name: Build + Publish
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v2
|
14
|
+
- name: Set up Ruby 2.7.2
|
15
|
+
uses: actions/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
ruby-version: 2.7.2
|
18
|
+
- name: Run tests
|
19
|
+
run: |
|
20
|
+
bundle install
|
21
|
+
bundle exec rspec
|
22
|
+
- name: Publish to RubyGems
|
23
|
+
run: |
|
24
|
+
mkdir -p $HOME/.gem
|
25
|
+
touch $HOME/.gem/credentials
|
26
|
+
chmod 0600 $HOME/.gem/credentials
|
27
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
28
|
+
gem build *.gemspec
|
29
|
+
gem push *.gem
|
30
|
+
env:
|
31
|
+
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
name: Run tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches-ignore: [ release ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master release ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
name: Build + Test
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v2
|
16
|
+
- name: Set up Ruby 2.7.2
|
17
|
+
uses: actions/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: 2.7.2
|
20
|
+
- name: Run tests
|
21
|
+
run: |
|
22
|
+
bundle install
|
23
|
+
CI=true bundle exec rspec
|
24
|
+
- name: Upload report
|
25
|
+
run: |
|
26
|
+
mv ./coverage/coverage.xml cobertura.xml
|
27
|
+
bash <(curl -Ls https://coverage.codacy.com/get.sh) report
|
28
|
+
env:
|
29
|
+
CODACY_PROJECT_TOKEN: ${{secrets.CODACY_PROJECT_TOKEN}}
|
data/.rubocop.yml
ADDED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.2
|
data/CONTRIBUTING.md
CHANGED
@@ -1,21 +1,29 @@
|
|
1
1
|
## Contributing
|
2
2
|
|
3
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/driggl/jsonapi_errors_handler
|
3
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/driggl/jsonapi_errors_handler>.
|
4
4
|
|
5
5
|
**How to contribute:**
|
6
6
|
|
7
|
-
1.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
1. Create Issue on Github.
|
8
|
+
|
9
|
+
2. Fork repository
|
10
|
+
|
11
|
+
3. Install [Rubocop](https://github.com/rubocop-hq/rubocop) - make sure you run it before commiting changes
|
12
|
+
|
13
|
+
4. Commit changes
|
14
|
+
* Keep commits small and atomic
|
15
|
+
|
16
|
+
* Start commit message from keywords (Add/Remove/Change/Refactor/Move/Rename/Upgrade/Downgrade)
|
17
|
+
|
18
|
+
* Keep commits imperative style
|
19
|
+
|
20
|
+
* Mention issue number (i.e "Resolves: #3")
|
21
|
+
|
22
|
+
5. Make sure you cover your change with tests.
|
23
|
+
|
24
|
+
6. Create Pull Request
|
17
25
|
|
18
26
|
**Coding Guidelines**
|
19
27
|
|
20
|
-
|
21
|
-
|
28
|
+
* We use [Rubocop](https://github.com/rubocop*hq/rubocop) and Ruby style guides for linting `*.rb` files.
|
29
|
+
* We use [Remark Lint](https://github.com/remarkjs/remark-lint) for linting `*.md` files.
|
data/Gemfile.lock
CHANGED
@@ -1,35 +1,44 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
jsonapi_errors_handler (0.
|
4
|
+
jsonapi_errors_handler (0.5.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
rspec-
|
14
|
-
rspec-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
diff-lcs (1.4.4)
|
10
|
+
docile (1.3.2)
|
11
|
+
rake (13.0.1)
|
12
|
+
rspec (3.9.0)
|
13
|
+
rspec-core (~> 3.9.0)
|
14
|
+
rspec-expectations (~> 3.9.0)
|
15
|
+
rspec-mocks (~> 3.9.0)
|
16
|
+
rspec-core (3.9.2)
|
17
|
+
rspec-support (~> 3.9.3)
|
18
|
+
rspec-expectations (3.9.2)
|
18
19
|
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
-
rspec-support (~> 3.
|
20
|
-
rspec-mocks (3.
|
20
|
+
rspec-support (~> 3.9.0)
|
21
|
+
rspec-mocks (3.9.1)
|
21
22
|
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
-
rspec-support (~> 3.
|
23
|
-
rspec-support (3.
|
23
|
+
rspec-support (~> 3.9.0)
|
24
|
+
rspec-support (3.9.3)
|
25
|
+
simplecov (0.18.5)
|
26
|
+
docile (~> 1.1)
|
27
|
+
simplecov-html (~> 0.11)
|
28
|
+
simplecov-cobertura (1.4.0)
|
29
|
+
simplecov (~> 0.8)
|
30
|
+
simplecov-html (0.12.2)
|
24
31
|
|
25
32
|
PLATFORMS
|
26
33
|
ruby
|
27
34
|
|
28
35
|
DEPENDENCIES
|
29
|
-
bundler
|
36
|
+
bundler
|
30
37
|
jsonapi_errors_handler!
|
31
|
-
rake
|
32
|
-
rspec
|
38
|
+
rake
|
39
|
+
rspec
|
40
|
+
simplecov
|
41
|
+
simplecov-cobertura
|
33
42
|
|
34
43
|
BUNDLED WITH
|
35
|
-
1.
|
44
|
+
2.1.4
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/542259a14a8f4b2894a39850c5031ffa)](https://app.codacy.com/app/swilgosz/jsonapi_errors_handler?utm_source=github.com&utm_medium=referral&utm_content=driggl/jsonapi_errors_handler&utm_campaign=Badge_Grade_Dashboard)
|
2
1
|
[![Gem Version](https://badge.fury.io/rb/jsonapi_errors_handler.svg)](https://badge.fury.io/rb/jsonapi_errors_handler)
|
3
|
-
[![
|
2
|
+
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/6dba6e4556354789809185e0decde4f8)](https://www.codacy.com/gh/driggl/jsonapi_errors_handler?utm_source=github.com&utm_medium=referral&utm_content=driggl/jsonapi_errors_handler&utm_campaign=Badge_Grade)
|
3
|
+
[![Codacy Badge](https://app.codacy.com/project/badge/Coverage/6dba6e4556354789809185e0decde4f8)](https://www.codacy.com/gh/driggl/jsonapi_errors_handler?utm_source=github.com&utm_medium=referral&utm_content=driggl/jsonapi_errors_handler&utm_campaign=Badge_Coverage)
|
4
|
+
![Run tests](https://github.com/driggl/jsonapi_errors_handler/workflows/Run%20tests/badge.svg?branch=master)
|
4
5
|
|
5
6
|
# JsonapiErrorsHandler
|
6
7
|
|
@@ -16,11 +17,15 @@ Add this line to your application's Gemfile:
|
|
16
17
|
|
17
18
|
And then execute:
|
18
19
|
|
19
|
-
|
20
|
+
```shell
|
21
|
+
$ bundle
|
22
|
+
```
|
20
23
|
|
21
24
|
Or install it yourself as:
|
22
25
|
|
23
|
-
|
26
|
+
```shell
|
27
|
+
$ gem install jsonapi_errors_handler
|
28
|
+
```
|
24
29
|
|
25
30
|
## Usage
|
26
31
|
|
@@ -52,6 +57,19 @@ JsonapiErrorsHandler.configure do |config|
|
|
52
57
|
end
|
53
58
|
```
|
54
59
|
|
60
|
+
|
61
|
+
### Response Content-Type
|
62
|
+
|
63
|
+
If you want to change the response content type you can do it through the configuration setting `content_type` by default it is `application/vnd.api+json`
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'jsonapi_errors_handler'
|
67
|
+
|
68
|
+
JsonapiErrorsHandler.configure do |config|
|
69
|
+
config.content_type = 'application/json'
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
55
73
|
### Custom errors mapping
|
56
74
|
|
57
75
|
If you want your custom errors being handled by default, just add them to the mapper
|
@@ -139,16 +157,17 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
139
157
|
|
140
158
|
## Contributing
|
141
159
|
|
142
|
-
Bug reports and pull requests are welcome on GitHub at
|
160
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/driggl/jsonapi_errors_handler>.
|
143
161
|
|
144
162
|
**How to contribute:**
|
145
163
|
|
146
164
|
1. Fork repository
|
147
165
|
2. Install [Rubocop](https://github.com/rubocop-hq/rubocop) - make sure you run it before commiting changes
|
148
166
|
3. Commit changes
|
149
|
-
|
150
|
-
|
151
|
-
|
167
|
+
* Keep commits small and atomic
|
168
|
+
* Start commit message from keywords (Add/Remove/Change/Refactor/Move/Rename/Upgrade/Downgrade)
|
169
|
+
* Keep commits imperative style
|
170
|
+
|
152
171
|
4. Create Pull Request
|
153
172
|
|
154
173
|
## License
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
5
6
|
require 'jsonapi_errors_handler/version'
|
6
7
|
|
7
8
|
Gem::Specification.new do |spec|
|
@@ -31,6 +32,8 @@ Gem::Specification.new do |spec|
|
|
31
32
|
'public gem pushes.'
|
32
33
|
end
|
33
34
|
|
35
|
+
spec.required_ruby_version = '>= 2.4.0'
|
36
|
+
|
34
37
|
# Specify which files should be added to the gem when it is released.
|
35
38
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
36
39
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
@@ -40,7 +43,9 @@ Gem::Specification.new do |spec|
|
|
40
43
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
41
44
|
spec.require_paths = ['lib']
|
42
45
|
|
43
|
-
spec.add_development_dependency 'bundler'
|
44
|
-
spec.add_development_dependency 'rake'
|
45
|
-
spec.add_development_dependency 'rspec'
|
46
|
+
spec.add_development_dependency 'bundler'
|
47
|
+
spec.add_development_dependency 'rake'
|
48
|
+
spec.add_development_dependency 'rspec'
|
49
|
+
spec.add_development_dependency 'simplecov'
|
50
|
+
spec.add_development_dependency 'simplecov-cobertura'
|
46
51
|
end
|
@@ -3,15 +3,23 @@
|
|
3
3
|
require 'singleton'
|
4
4
|
|
5
5
|
module JsonapiErrorsHandler
|
6
|
+
# Configuration class allowing to set up the initial behavior for the gem
|
7
|
+
#
|
6
8
|
class Configuration
|
7
9
|
include Singleton
|
8
10
|
|
9
11
|
attr_writer :handle_unexpected
|
10
|
-
|
12
|
+
attr_accessor :content_type
|
13
|
+
# Allows to override the configuration options
|
14
|
+
# @param [Block] - list of options to be overwritten
|
15
|
+
#
|
11
16
|
def configure
|
12
17
|
yield(self) if block_given?
|
13
18
|
end
|
14
19
|
|
20
|
+
# Checks if unexpected errors should be handled by the gem
|
21
|
+
# @return [Boolean]
|
22
|
+
#
|
15
23
|
def handle_unexpected?
|
16
24
|
@handle_unexpected
|
17
25
|
end
|
@@ -20,6 +28,7 @@ module JsonapiErrorsHandler
|
|
20
28
|
|
21
29
|
def initialize
|
22
30
|
@handle_unexpected = false
|
31
|
+
@content_type = 'application/vnd.api+json'
|
23
32
|
end
|
24
33
|
end
|
25
34
|
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JsonapiErrorsHandler
|
4
|
+
# Maps any of the given error classes into the serializable errors
|
5
|
+
# from the predefined collection
|
6
|
+
#
|
4
7
|
class ErrorMapper
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
+
@mapped_errors = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :mapped_errors
|
8
12
|
end
|
9
13
|
|
10
14
|
def self.map_errors!(errors_hash = {})
|
11
|
-
|
15
|
+
@mapped_errors.merge!(errors_hash)
|
12
16
|
end
|
13
17
|
|
14
18
|
def self.mapped_error?(error_klass)
|
@@ -22,11 +26,13 @@ module JsonapiErrorsHandler
|
|
22
26
|
root_class = error_class.split('::').first
|
23
27
|
mapped = mapped_errors[error_class] || mapped_errors[root_class]
|
24
28
|
return unless mapped
|
29
|
+
|
25
30
|
Object.const_get(mapped).new
|
26
31
|
end
|
27
32
|
|
28
33
|
def self.descendant_of_predefined?(error)
|
29
34
|
return false if error.is_a?(Class)
|
35
|
+
|
30
36
|
error.class < JsonapiErrorsHandler::Errors::StandardError
|
31
37
|
end
|
32
38
|
end
|
@@ -4,11 +4,16 @@ require 'jsonapi_errors_handler/keys_stringifier'
|
|
4
4
|
|
5
5
|
module JsonapiErrorsHandler
|
6
6
|
module Errors
|
7
|
+
# Handles serialization of Unexpected HTTP error (500 status code)
|
8
|
+
# It's also a fallback for not mapped errors in the application.
|
9
|
+
#
|
7
10
|
class StandardError < ::StandardError
|
8
|
-
def initialize(
|
11
|
+
def initialize(
|
12
|
+
title: nil, status: nil, detail: nil, message: nil, source: {}
|
13
|
+
)
|
9
14
|
@title = title || 'Something went wrong'
|
10
|
-
@detail = detail
|
11
|
-
@detail ||= '
|
15
|
+
@detail = detail || message
|
16
|
+
@detail ||= "We've encountered unexpected error, but our developers had been already notified about it" # rubocop:disable Metrics/LineLength
|
12
17
|
@status = status || 500
|
13
18
|
@source = KeysStringifier.call(source)
|
14
19
|
end
|
@@ -1,44 +1,62 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'irb'
|
4
3
|
require 'jsonapi_errors_handler/version'
|
5
4
|
require 'jsonapi_errors_handler/configuration'
|
6
5
|
require 'jsonapi_errors_handler/errors'
|
7
6
|
require 'jsonapi_errors_handler/error_mapper'
|
8
7
|
require 'jsonapi_errors_handler/error_serializer'
|
9
8
|
|
9
|
+
# Allows to handle ruby errors and return the serialized JSON:API output
|
10
|
+
#
|
10
11
|
module JsonapiErrorsHandler
|
12
|
+
PREDEFINED_HASH = {
|
13
|
+
'JsonapiErrorsHandler::Errors::Invalid' =>
|
14
|
+
'JsonapiErrorsHandler::Errors::Invalid',
|
15
|
+
'JsonapiErrorsHandler::Errors::Forbidden' =>
|
16
|
+
'JsonapiErrorsHandler::Errors::Forbidden',
|
17
|
+
'JsonapiErrorsHandler::Errors::NotFound' => '
|
18
|
+
JsonapiErrorsHandler::Errors::NotFound',
|
19
|
+
'JsonapiErrorsHandler::Errors::Unauthorized' =>
|
20
|
+
'JsonapiErrorsHandler::Errors::Unauthorized'
|
21
|
+
}.freeze
|
22
|
+
|
11
23
|
def self.included(base)
|
12
24
|
base.class_eval do
|
13
|
-
ErrorMapper.map_errors!(
|
14
|
-
'JsonapiErrorsHandler::Errors::Invalid' => 'JsonapiErrorsHandler::Errors::Invalid',
|
15
|
-
'JsonapiErrorsHandler::Errors::Forbidden' => 'JsonapiErrorsHandler::Errors::Forbidden',
|
16
|
-
'JsonapiErrorsHandler::Errors::NotFound' => 'JsonapiErrorsHandler::Errors::NotFound',
|
17
|
-
'JsonapiErrorsHandler::Errors::Unauthorized' => 'JsonapiErrorsHandler::Errors::Unauthorized'
|
18
|
-
)
|
25
|
+
ErrorMapper.map_errors!(PREDEFINED_HASH)
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
29
|
def handle_error(error)
|
30
|
+
log_error(error) if respond_to?(:log_error)
|
31
|
+
# Handle every error which inherits from
|
32
|
+
# JsonapiErrorsHandler::Errors::StandardError
|
33
|
+
#
|
34
|
+
if JsonapiErrorsHandler::ErrorMapper.mapped_error?(error.class.superclass.to_s)
|
35
|
+
return render_error(error)
|
36
|
+
end
|
37
|
+
|
23
38
|
mapped = ErrorMapper.mapped_error(error)
|
24
39
|
mapped ? render_error(mapped) : handle_unexpected_error(error)
|
25
40
|
end
|
26
41
|
|
27
42
|
def handle_unexpected_error(error)
|
28
|
-
|
29
|
-
|
43
|
+
config = JsonapiErrorsHandler::Configuration.instance
|
44
|
+
raise error unless config.handle_unexpected?
|
45
|
+
|
46
|
+
notify_handle_unexpected_error(error) if respond_to?(:notify_handle_unexpected_error)
|
47
|
+
|
30
48
|
render_error(::JsonapiErrorsHandler::Errors::StandardError.new)
|
31
49
|
end
|
32
50
|
|
33
51
|
def render_error(error)
|
34
|
-
render
|
52
|
+
render(
|
53
|
+
json: ::JsonapiErrorsHandler::ErrorSerializer.new(error),
|
54
|
+
status: error.status,
|
55
|
+
content_type: Configuration.instance.content_type
|
56
|
+
)
|
35
57
|
end
|
36
58
|
|
37
59
|
def self.configure(&block)
|
38
60
|
Configuration.instance.configure(&block)
|
39
61
|
end
|
40
|
-
|
41
|
-
def configuration
|
42
|
-
Configuration.instance
|
43
|
-
end
|
44
62
|
end
|