shark-on-lambda 0.6.10 → 1.0.0.rc1

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/push-gem.yml +67 -0
  3. data/.github/workflows/tests.yml +32 -0
  4. data/README.md +10 -12
  5. data/changelog.md +11 -0
  6. data/gems.locked +73 -23
  7. data/lib/shark_on_lambda/api_gateway_handler.rb +61 -0
  8. data/lib/shark_on_lambda/application.rb +17 -0
  9. data/lib/shark_on_lambda/base_controller.rb +50 -0
  10. data/lib/shark_on_lambda/configuration.rb +9 -1
  11. data/lib/shark_on_lambda/dispatcher.rb +26 -0
  12. data/lib/shark_on_lambda/errors/base.rb +47 -0
  13. data/lib/shark_on_lambda/errors/base_serializer.rb +18 -0
  14. data/lib/shark_on_lambda/jsonapi_controller.rb +29 -0
  15. data/lib/shark_on_lambda/jsonapi_parameters.rb +66 -0
  16. data/lib/shark_on_lambda/jsonapi_renderer.rb +115 -0
  17. data/lib/shark_on_lambda/middleware/base.rb +23 -0
  18. data/lib/shark_on_lambda/middleware/jsonapi_rescuer.rb +31 -0
  19. data/lib/shark_on_lambda/middleware/rescuer.rb +38 -0
  20. data/lib/shark_on_lambda/query.rb +67 -0
  21. data/lib/shark_on_lambda/rack_adapters/api_gateway.rb +127 -0
  22. data/lib/shark_on_lambda/request.rb +9 -0
  23. data/lib/shark_on_lambda/response.rb +6 -0
  24. data/lib/shark_on_lambda/rspec/env_builder.rb +64 -0
  25. data/lib/shark_on_lambda/rspec/helpers.rb +84 -0
  26. data/lib/shark_on_lambda/rspec/jsonapi_helpers.rb +27 -0
  27. data/lib/shark_on_lambda/version.rb +1 -1
  28. data/lib/shark_on_lambda.rb +25 -28
  29. data/shark-on-lambda.gemspec +8 -3
  30. metadata +104 -24
  31. data/.gitlab-ci.yml +0 -39
  32. data/.travis.yml +0 -14
  33. data/lib/shark_on_lambda/api_gateway/base_controller.rb +0 -76
  34. data/lib/shark_on_lambda/api_gateway/base_handler.rb +0 -82
  35. data/lib/shark_on_lambda/api_gateway/concerns/http_response_validation.rb +0 -61
  36. data/lib/shark_on_lambda/api_gateway/errors.rb +0 -49
  37. data/lib/shark_on_lambda/api_gateway/headers.rb +0 -37
  38. data/lib/shark_on_lambda/api_gateway/jsonapi_controller.rb +0 -77
  39. data/lib/shark_on_lambda/api_gateway/jsonapi_parameters.rb +0 -68
  40. data/lib/shark_on_lambda/api_gateway/jsonapi_renderer.rb +0 -105
  41. data/lib/shark_on_lambda/api_gateway/parameters.rb +0 -18
  42. data/lib/shark_on_lambda/api_gateway/query.rb +0 -69
  43. data/lib/shark_on_lambda/api_gateway/request.rb +0 -148
  44. data/lib/shark_on_lambda/api_gateway/response.rb +0 -82
  45. data/lib/shark_on_lambda/api_gateway/serializers/base_error_serializer.rb +0 -20
  46. data/lib/shark_on_lambda/concerns/filter_actions.rb +0 -93
  47. data/lib/shark_on_lambda/tasks/build.rake +0 -146
  48. data/lib/shark_on_lambda/tasks.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6436ab76f14afebb7ef7601936489cd9304db7f6591db4262f29b76f1561cfd0
4
- data.tar.gz: eab44e17a31afc1933b6be70401b89f0d935c49871e65dfd6edc69c5e5334580
3
+ metadata.gz: 9de95366ac135aebf072c6ecdbb5cae42b25f072bffdd1e01bee446e8262f17b
4
+ data.tar.gz: a09d5288e281447de50cfbbd8f97a18c023d9750e5d5b5ab456f4d6187b229a6
5
5
  SHA512:
6
- metadata.gz: '08b36668e651e1448a6075990c11682188819cd45c0a654d4f1798ceafca83a2f7af52be9c25e49d6104820ff55c5bbdfb5d50751c6201d44378deb63d38a0c6'
7
- data.tar.gz: '08b8b93027da580a481c9f7ea91de8b0ef488dd4096a9ab7430f6939b2b4238d40987a822d005d9f7e111de36bb58c1227d0407d063d593d54b5313392d9670a'
6
+ metadata.gz: 9643f2cb448d20396f43ab9fd124e0aca1ae436773f1b29626ce44a644f12f6bd1477deb5c468a30b1992d824d1bf6049f8340705c11dde6a65432f1104bba38
7
+ data.tar.gz: '09d2eb6a2ffb09b969f3cd383a0f9a19ee6bd68fbf32b37ba1fc0acab488144dcf38d516788b421b601158d390e4eee162500c65efcb25e89f979ac4bb487c21'
@@ -0,0 +1,67 @@
1
+ name: Push Gem
2
+ on:
3
+ push:
4
+ tags:
5
+ - 'v*'
6
+
7
+ jobs:
8
+ rspec:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v1
12
+ - name: Set up Ruby 2.5
13
+ uses: actions/setup-ruby@v1
14
+ with:
15
+ ruby-version: 2.5.x
16
+ - name: Run RSpec
17
+ run: |
18
+ gem install bundler
19
+ bundle install --jobs 4 --retry 3
20
+ bundle exec rspec
21
+
22
+ rubocop:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v1
26
+ - name: Set up Ruby 2.5
27
+ uses: actions/setup-ruby@v1
28
+ with:
29
+ ruby-version: 2.5.x
30
+ - name: Run rubocop
31
+ run: |
32
+ gem install bundler
33
+ bundle install --jobs 4 --retry 3
34
+ bundle exec rubocop
35
+
36
+ push-gem:
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - uses: actions/checkout@master
40
+ - name: Set up Ruby 2.5
41
+ uses: actions/setup-ruby@v1
42
+ with:
43
+ ruby-version: 2.5.x
44
+ - name: Build gem
45
+ run: |
46
+ gem install bundler
47
+ bundle install --jobs 4 --retry 3
48
+ bundle exec rake build
49
+ - name: Push to GitHub Package Repository
50
+ run: |
51
+ mkdir -p $HOME/.gem
52
+ echo ":github: Bearer $GEM_HOST_API_KEY" >> $HOME/.gem/credentials
53
+ chmod 0600 $HOME/.gem/credentials
54
+ bundle exec rake build
55
+ gem push --key github --host https://rubygems.pkg.github.com/Skudo pkg/`ls -1t pkg | head -1`
56
+ env:
57
+ GEM_HOST_API_KEY: ${{secrets.GITHUB_AUTH_TOKEN}}
58
+ OWNER: username
59
+ - name: Push to RubyGems
60
+ run: |
61
+ mkdir -p $HOME/.gem
62
+ echo ":rubygems_api_key: $GEM_HOST_API_KEY" >> ~/.gem/credentials
63
+ chmod 0600 $HOME/.gem/credentials
64
+ bundle exec rake build
65
+ gem push pkg/`ls -1t pkg | head -1`
66
+ env:
67
+ GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
@@ -0,0 +1,32 @@
1
+ name: Tests
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ rspec:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v1
10
+ - name: Set up Ruby 2.5
11
+ uses: actions/setup-ruby@v1
12
+ with:
13
+ ruby-version: 2.5.x
14
+ - name: Run RSpec
15
+ run: |
16
+ gem install bundler
17
+ bundle install --jobs 4 --retry 3
18
+ bundle exec rspec
19
+
20
+ rubocop:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v1
24
+ - name: Set up Ruby 2.5
25
+ uses: actions/setup-ruby@v1
26
+ with:
27
+ ruby-version: 2.5.x
28
+ - name: Run rubocop
29
+ run: |
30
+ gem install bundler
31
+ bundle install --jobs 4 --retry 3
32
+ bundle exec rubocop
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # shark-on-lambda
2
-
3
- [![Travis CI Build Status](https://travis-ci.org/Skudo/shark-on-lambda.svg?branch=develop)](https://travis-ci.org/Skudo/shark-on-lambda)
2
+ [![GitHub Actions Test Status](https://github.com/Skudo/shark-on-lambda/workflows/Tests/badge.svg?branch=develop)](https://github.com/Skudo/shark-on-lambda/actions)
4
3
  [![CodeClimate Maintainability Score](https://api.codeclimate.com/v1/badges/fb0c16b3c6212f97b753/maintainability)](https://codeclimate.com/github/Skudo/shark-on-lambda/maintainability)
5
4
 
6
5
  `shark-on-lambda` provides a lightweight framework to write Ruby on AWS Lambda
@@ -24,8 +23,7 @@ maintaining a smaller memory footprint.
24
23
 
25
24
  ## Changelog
26
25
 
27
- ### Pre-1.0
28
- * Supports events from the API Gateway.
26
+ Have a look at the [actual changelog](changelog.md).
29
27
 
30
28
  ## Installation
31
29
 
@@ -50,11 +48,11 @@ are triggered by HTTP requests on the API Gateway. They also are responsible for
50
48
  responding with a well-formed response to the caller.
51
49
 
52
50
  ```ruby
53
- class MyHandler < SharkOnLambda::ApiGateway::BaseHandler
51
+ class MyHandler < SharkOnLambda::BaseHandler
54
52
  end
55
53
  ```
56
54
 
57
- By inheriting from `SharkOnLambda::ApiGateway::BaseHandler`, your own handler
55
+ By inheriting from `SharkOnLambda::BaseHandler`, your own handler
58
56
  class is indirectly tied to your controller class by convention: It assumes
59
57
  the controller name is `MyController` and it will dispatch events to that
60
58
  controller.
@@ -63,7 +61,7 @@ If you however bring your own class with a different name, you can configure
63
61
  your handler to use that controller instead:
64
62
 
65
63
  ```ruby
66
- class MyHandler < SharkOnLambda::ApiGateway::BaseHandler
64
+ class MyHandler < SharkOnLambda::BaseHandler
67
65
  self.controller_class = AnotherController
68
66
  end
69
67
  ```
@@ -72,7 +70,7 @@ All controller methods are going to be automagically mapped to class methods
72
70
  on the handler class.
73
71
 
74
72
  ```ruby
75
- class MyController < SharkOnLambda::ApiGateway::BaseController
73
+ class MyController < SharkOnLambda::BaseController
76
74
  def index
77
75
  end
78
76
 
@@ -80,7 +78,7 @@ class MyController < SharkOnLambda::ApiGateway::BaseController
80
78
  end
81
79
  end
82
80
 
83
- class MyHandler < SharkOnLambda::ApiGateway::BaseHandler
81
+ class MyHandler < SharkOnLambda::BaseHandler
84
82
  end
85
83
  ```
86
84
 
@@ -103,7 +101,7 @@ functions you may know from Rails and `render` does not really support multiple
103
101
  renderers (yet).
104
102
 
105
103
  ```ruby
106
- class MyController < SharkOnLambda::ApiGateway::BaseController
104
+ class MyController < SharkOnLambda::BaseController
107
105
  def index
108
106
  # Make the API Gateway respond with a 201 response saying "Hello, World!"
109
107
  # in the response body.
@@ -124,7 +122,7 @@ end
124
122
  ### _JSON API_-compliant controllers
125
123
 
126
124
  If you inherit your controller from
127
- `SharkOnLambda::ApiGateway::JsonapiController`, `render` and `redirect_to` will
125
+ `SharkOnLambda::JsonapiController`, `render` and `redirect_to` will
128
126
  create _JSON API_-compliant responses.
129
127
 
130
128
  You however __must__ have a serialiser for the objects you want to render.
@@ -141,7 +139,7 @@ _JSON API_ compatibility. Therefore, we expect the serialisers to be inherited
141
139
  from `::JSONAPI::Serializable::Resource` (or `::JSONAPI::Serializable::Error`).
142
140
 
143
141
  ```ruby
144
- class SomethingSerializer < ::JSONAPI::Serializable::Resource
142
+ class SomethingSerializer < JSONAPI::Serializable::Resource
145
143
  type :somethings
146
144
 
147
145
  attributes :foo, :bar, :baz
data/changelog.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## Changelog
2
2
 
3
+ #### Unreleaesed
4
+
5
+ - [Break] HTTP redirection now uses the status code `302`.
6
+ - [Break] Remove the `ApiGateway` namespace, move all items from that namespace up by one level.
7
+ - [Break] Remove build rake tasks.
8
+ - Added support for Rack-compatible middleware.
9
+ - `SharkOnLambda::BaseController` now acts more like `ActionController::BaseController`.
10
+ - Support `ActiveModel::Errors` nested validation errors.
11
+ - Added `SharkOnLambda::RSpec::Helpers` and `SharkOnLambda::RSpec::JsonapiHelpers`.
12
+ - Moved to GitHub.
13
+
3
14
  #### 0.6.10
4
15
 
5
16
  - Upgrade `rack` for good measure.
data/gems.locked CHANGED
@@ -1,14 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shark-on-lambda (0.6.10)
4
+ shark-on-lambda (1.0.0.rc1)
5
+ actionpack
5
6
  activesupport
6
7
  jsonapi-rb
7
- rack (>= 2.0.8)
8
+ rack (>= 2.0.8, < 3)
9
+ zeitwerk (~> 2.2)
8
10
 
9
11
  GEM
10
12
  remote: https://rubygems.org/
11
13
  specs:
14
+ actionpack (6.0.0)
15
+ actionview (= 6.0.0)
16
+ activesupport (= 6.0.0)
17
+ rack (~> 2.0)
18
+ rack-test (>= 0.6.3)
19
+ rails-dom-testing (~> 2.0)
20
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
21
+ actionview (6.0.0)
22
+ activesupport (= 6.0.0)
23
+ builder (~> 3.1)
24
+ erubi (~> 1.4)
25
+ rails-dom-testing (~> 2.0)
26
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
12
27
  activemodel (6.0.0)
13
28
  activesupport (= 6.0.0)
14
29
  activesupport (6.0.0)
@@ -18,14 +33,23 @@ GEM
18
33
  tzinfo (~> 1.1)
19
34
  zeitwerk (~> 2.1, >= 2.1.8)
20
35
  ast (2.4.0)
36
+ builder (3.2.4)
37
+ byebug (11.0.1)
38
+ coderay (1.1.2)
39
+ colorize (0.8.1)
21
40
  concurrent-ruby (1.1.5)
41
+ crass (1.0.6)
22
42
  diff-lcs (1.3)
23
43
  docile (1.3.2)
24
- factory_bot (5.1.0)
44
+ erubi (1.9.0)
45
+ factory_bot (5.1.1)
25
46
  activesupport (>= 4.2.0)
26
- i18n (1.6.0)
47
+ fasterer (0.8.2)
48
+ colorize (~> 0.7)
49
+ ruby_parser (>= 3.14.1)
50
+ i18n (1.7.0)
27
51
  concurrent-ruby (~> 1.0)
28
- jaro_winkler (1.5.3)
52
+ jaro_winkler (1.5.4)
29
53
  json (2.2.0)
30
54
  jsonapi-deserializable (0.2.0)
31
55
  jsonapi-rb (0.5.0)
@@ -34,27 +58,47 @@ GEM
34
58
  jsonapi-renderer (0.2.2)
35
59
  jsonapi-serializable (0.3.1)
36
60
  jsonapi-renderer (~> 0.2.0)
37
- minitest (5.12.0)
38
- parallel (1.17.0)
39
- parser (2.6.4.1)
61
+ loofah (2.4.0)
62
+ crass (~> 1.0.2)
63
+ nokogiri (>= 1.5.9)
64
+ method_source (0.9.2)
65
+ mini_portile2 (2.4.0)
66
+ minitest (5.13.0)
67
+ nokogiri (1.10.8)
68
+ mini_portile2 (~> 2.4.0)
69
+ parallel (1.18.0)
70
+ parser (2.6.5.0)
40
71
  ast (~> 2.4.0)
41
- rack (2.0.8)
72
+ pry (0.12.2)
73
+ coderay (~> 1.1.0)
74
+ method_source (~> 0.9.0)
75
+ pry-byebug (3.7.0)
76
+ byebug (~> 11.0)
77
+ pry (~> 0.10)
78
+ rack (2.2.2)
79
+ rack-test (1.1.0)
80
+ rack (>= 1.0, < 3)
81
+ rails-dom-testing (2.0.3)
82
+ activesupport (>= 4.2.0)
83
+ nokogiri (>= 1.6)
84
+ rails-html-sanitizer (1.3.0)
85
+ loofah (~> 2.3)
42
86
  rainbow (3.0.0)
43
87
  rake (13.0.0)
44
- rspec (3.8.0)
45
- rspec-core (~> 3.8.0)
46
- rspec-expectations (~> 3.8.0)
47
- rspec-mocks (~> 3.8.0)
48
- rspec-core (3.8.2)
49
- rspec-support (~> 3.8.0)
50
- rspec-expectations (3.8.4)
88
+ rspec (3.9.0)
89
+ rspec-core (~> 3.9.0)
90
+ rspec-expectations (~> 3.9.0)
91
+ rspec-mocks (~> 3.9.0)
92
+ rspec-core (3.9.0)
93
+ rspec-support (~> 3.9.0)
94
+ rspec-expectations (3.9.0)
51
95
  diff-lcs (>= 1.2.0, < 2.0)
52
- rspec-support (~> 3.8.0)
53
- rspec-mocks (3.8.1)
96
+ rspec-support (~> 3.9.0)
97
+ rspec-mocks (3.9.0)
54
98
  diff-lcs (>= 1.2.0, < 2.0)
55
- rspec-support (~> 3.8.0)
56
- rspec-support (3.8.2)
57
- rubocop (0.74.0)
99
+ rspec-support (~> 3.9.0)
100
+ rspec-support (3.9.0)
101
+ rubocop (0.76.0)
58
102
  jaro_winkler (~> 1.5.1)
59
103
  parallel (~> 1.10)
60
104
  parser (>= 2.6)
@@ -62,6 +106,9 @@ GEM
62
106
  ruby-progressbar (~> 1.7)
63
107
  unicode-display_width (>= 1.4.0, < 1.7)
64
108
  ruby-progressbar (1.10.1)
109
+ ruby_parser (3.14.2)
110
+ sexp_processor (~> 4.9)
111
+ sexp_processor (4.14.1)
65
112
  simplecov (0.17.1)
66
113
  docile (~> 1.1)
67
114
  json (>= 1.8, < 3)
@@ -72,7 +119,7 @@ GEM
72
119
  thread_safe (~> 0.1)
73
120
  unicode-display_width (1.6.0)
74
121
  yard (0.9.20)
75
- zeitwerk (2.1.10)
122
+ zeitwerk (2.2.1)
76
123
 
77
124
  PLATFORMS
78
125
  ruby
@@ -81,6 +128,9 @@ DEPENDENCIES
81
128
  activemodel
82
129
  bundler
83
130
  factory_bot
131
+ fasterer
132
+ pry
133
+ pry-byebug
84
134
  rake
85
135
  rspec
86
136
  rubocop
@@ -89,4 +139,4 @@ DEPENDENCIES
89
139
  yard
90
140
 
91
141
  BUNDLED WITH
92
- 2.1.2
142
+ 2.1.4
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ class ApiGatewayHandler
5
+ class << self
6
+ attr_writer :controller_class_name
7
+
8
+ def controller_action?(action)
9
+ controller_actions.include?(action.to_sym)
10
+ end
11
+
12
+ def controller_class_name
13
+ return @controller_class_name if defined?(@controller_class_name)
14
+
15
+ name_inferrer = Inferrers::NameInferrer.from_handler_name(name)
16
+ @controller_class_name = name_inferrer.controller
17
+ end
18
+
19
+ private
20
+
21
+ def controller_actions
22
+ return [] if controller_class.nil?
23
+
24
+ controller_class.public_instance_methods(false)
25
+ end
26
+
27
+ def controller_class
28
+ controller_class_name.safe_constantize
29
+ end
30
+
31
+ def method_missing(action, *args, &_block)
32
+ return super unless respond_to_missing?(action)
33
+
34
+ new.call(action, *args)
35
+ end
36
+
37
+ def respond_to_missing?(name, _include_all = false)
38
+ controller_action?(name)
39
+ end
40
+ end
41
+
42
+ attr_reader :application, :env
43
+ delegate :context, :event, to: :adapter
44
+
45
+ def initialize
46
+ @application = Application.new
47
+ end
48
+
49
+ def call(action, event:, context:)
50
+ raise NoMethodError unless self.class.controller_action?(action)
51
+
52
+ adapter = RackAdapters::ApiGateway.new(context: context, event: event)
53
+ env = adapter.env
54
+ env['shark.controller'] = self.class.controller_class_name
55
+ env['shark.action'] = action.to_s
56
+
57
+ status, headers, body = @application.call(env)
58
+ adapter.build_response(status, headers, body)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ class Application
5
+ def call(env)
6
+ dup.send('_call', env)
7
+ end
8
+
9
+ private
10
+
11
+ def _call(env)
12
+ dispatcher = SharkOnLambda.config.dispatcher
13
+ middleware_stack = SharkOnLambda.config.middleware.build(dispatcher)
14
+ middleware_stack.call(env)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ class BaseController < ActionController::Metal
5
+ EXCLUDED_MODULES = [
6
+ AbstractController::Translation,
7
+ AbstractController::AssetPaths,
8
+
9
+ ActionController::UrlFor,
10
+ ActionController::ConditionalGet,
11
+ ActionController::EtagWithTemplateDigest,
12
+ ActionController::EtagWithFlash,
13
+ ActionController::Caching,
14
+ ActionController::MimeResponds,
15
+ ActionController::ImplicitRender,
16
+ ActionController::Cookies,
17
+ ActionController::Flash,
18
+ ActionController::FormBuilder,
19
+ ActionController::RequestForgeryProtection,
20
+ ActionController::ContentSecurityPolicy,
21
+ ActionController::ForceSSL,
22
+ ActionController::HttpAuthentication::Basic::ControllerMethods,
23
+ ActionController::HttpAuthentication::Digest::ControllerMethods,
24
+ ActionController::HttpAuthentication::Token::ControllerMethods,
25
+ ActionView::Layouts
26
+ ].freeze
27
+ ActionController::Base.without_modules(EXCLUDED_MODULES).each do |mod|
28
+ include mod
29
+ end
30
+
31
+ def self.dispatch(*)
32
+ super
33
+ rescue AbstractController::ActionNotFound,
34
+ AbstractController::DoubleRenderError,
35
+ ActionController::ActionControllerError => e
36
+ raise Errors[500], e.message
37
+ end
38
+
39
+ def redirect_to(*)
40
+ super
41
+ self.response_body = '' if no_body?
42
+ end
43
+
44
+ private
45
+
46
+ def no_body?
47
+ response.status.in?(Response::NO_CONTENT_CODES)
48
+ end
49
+ end
50
+ end
@@ -4,7 +4,7 @@ module SharkOnLambda
4
4
  class Configuration < OpenStruct
5
5
  include Concerns::ResettableSingleton
6
6
 
7
- attr_writer :stage
7
+ attr_writer :dispatcher, :stage
8
8
 
9
9
  class << self
10
10
  include Concerns::YamlConfigLoader
@@ -56,6 +56,14 @@ module SharkOnLambda
56
56
  end
57
57
  end
58
58
 
59
+ def dispatcher
60
+ @dispatcher ||= Dispatcher.new
61
+ end
62
+
63
+ def middleware
64
+ @middleware ||= ActionDispatch::MiddlewareStack.new
65
+ end
66
+
59
67
  def root
60
68
  @root ||= Pathname.new('.')
61
69
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ class Dispatcher
5
+ def call(env)
6
+ request = Request.new(env)
7
+ response = Response.new
8
+
9
+ controller = controller_class(env)
10
+ action = controller_action(env)
11
+ controller.dispatch(action, request, response)
12
+
13
+ response.prepare!
14
+ end
15
+
16
+ private
17
+
18
+ def controller_action(env)
19
+ env['shark.action']
20
+ end
21
+
22
+ def controller_class(env)
23
+ env['shark.controller'].camelize.constantize
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ module Errors
5
+ class Base < StandardError
6
+ attr_accessor :id, :code, :meta, :pointer, :parameter
7
+ attr_writer :detail
8
+
9
+ def self.status(status_code)
10
+ define_method :status do
11
+ status_code
12
+ end
13
+ end
14
+
15
+ def detail
16
+ return @detail if @detail.present?
17
+ return nil if message == self.class.name
18
+
19
+ message
20
+ end
21
+
22
+ def title
23
+ Rack::Utils::HTTP_STATUS_CODES[status]
24
+ end
25
+ end
26
+
27
+ def self.[](status_code)
28
+ @errors[status_code]
29
+ end
30
+
31
+ @errors = Rack::Utils::HTTP_STATUS_CODES.map do |status_code, message|
32
+ next unless (400..599).cover?(status_code) && message.present?
33
+
34
+ error_class = Class.new(Base) do
35
+ status status_code
36
+ end
37
+ class_name_parts = message.to_s.split(/\s+/)
38
+ class_name_parts.map! { |word| word.gsub(/[^a-z]/i, '').capitalize }
39
+ class_name = class_name_parts.join('')
40
+ const_set(class_name, error_class)
41
+
42
+ [status_code, error_class]
43
+ end
44
+ @errors.compact!
45
+ @errors = @errors.to_h
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ module Errors
5
+ class BaseSerializer < JSONAPI::Serializable::Error
6
+ id { @object.id }
7
+ status { @object.status }
8
+ code { @object.code }
9
+ title { @object.title }
10
+ detail { @object.detail }
11
+ meta { @object.meta }
12
+ source do
13
+ pointer @object.pointer if @object.pointer.present?
14
+ parameter @object.parameter if @object.parameter.present?
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SharkOnLambda
4
+ class JsonapiController < BaseController
5
+ ActionController::Renderers.add :jsonapi do |object, options|
6
+ response.set_header('content-type', 'application/vnd.api+json')
7
+ return { data: {} }.to_json if object.nil?
8
+
9
+ jsonapi_params = JsonapiParameters.new(params)
10
+ jsonapi_renderer = JsonapiRenderer.new
11
+ render_options = jsonapi_params.to_h.deep_merge(options)
12
+
13
+ jsonapi_renderer.render(object, render_options)
14
+ end
15
+
16
+ def redirect_to(options = {}, response_status = {})
17
+ super
18
+ return if response_status[:status] == 304
19
+
20
+ self.response_body = { data: {} }.to_json
21
+ end
22
+
23
+ def render(object, options = {})
24
+ options.merge!(jsonapi: object, content_type: 'application/vnd.api+json')
25
+
26
+ super(options)
27
+ end
28
+ end
29
+ end