shark-on-lambda 1.0.1 → 2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/changelog.md +10 -0
- data/doc/upgrade-from-0.6.x-to-1.x.md +3 -3
- data/lib/shark-on-lambda.rb +9 -0
- data/lib/shark_on_lambda.rb +10 -58
- data/lib/shark_on_lambda/api_gateway_handler.rb +3 -55
- data/lib/shark_on_lambda/application.rb +72 -2
- data/lib/shark_on_lambda/base_controller.rb +29 -9
- data/lib/shark_on_lambda/configuration.rb +1 -65
- data/lib/shark_on_lambda/inferrers/serializer_inferrer.rb +10 -7
- data/lib/shark_on_lambda/jsonapi_renderer.rb +1 -2
- data/lib/shark_on_lambda/middleware/honeybadger.rb +5 -3
- data/lib/shark_on_lambda/middleware/jsonapi_rescuer.rb +21 -1
- data/lib/shark_on_lambda/middleware/lambda_logger.rb +5 -13
- data/lib/shark_on_lambda/rake_tasks.rb +16 -0
- data/lib/shark_on_lambda/request.rb +0 -3
- data/lib/shark_on_lambda/rspec/env_builder.rb +71 -37
- data/lib/shark_on_lambda/rspec/helpers.rb +5 -88
- data/lib/shark_on_lambda/rspec/request_helpers.rb +63 -0
- data/lib/shark_on_lambda/rspec/{jsonapi_helpers.rb → response_helpers.rb} +4 -10
- data/lib/shark_on_lambda/version.rb +1 -1
- data/shark-on-lambda.gemspec +7 -5
- metadata +32 -39
- data/lib/shark_on_lambda/concerns/resettable_singleton.rb +0 -18
- data/lib/shark_on_lambda/concerns/yaml_config_loader.rb +0 -28
- data/lib/shark_on_lambda/dispatcher.rb +0 -26
- data/lib/shark_on_lambda/inferrers/name_inferrer.rb +0 -66
- data/lib/shark_on_lambda/jsonapi_controller.rb +0 -32
- data/lib/shark_on_lambda/middleware/rescuer.rb +0 -37
- data/lib/shark_on_lambda/query.rb +0 -67
- data/lib/shark_on_lambda/rack_adapters/api_gateway.rb +0 -128
- data/lib/shark_on_lambda/secrets.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 642998e593034c083639724031920edfe7568de50d276cc3c58932c099d94a0e
|
4
|
+
data.tar.gz: 8101e725e3ef4f710422625726f87c7a324e986b9eb6184a988e0fdd3812bdda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d23eac59ce2797aac609444509d571a54ffb22024f11070a54dd43d600ceeeb2b527e421c1c9463ac08cceb4fa2b9ad6a366e496cebb47c2873276e9abf4a9ec
|
7
|
+
data.tar.gz: 8932eeb3134b88fb0da09b35a3a70eb1b4d1bfb5b2a1f522b9f4bc23c07890b4c6c9cd061374aebf4eb80c09695ef69420da95cc7f608c415b81692724f41e56
|
data/.rubocop.yml
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
AllCops:
|
2
|
+
NewCops: enable
|
2
3
|
TargetRubyVersion: 2.5
|
3
4
|
|
4
5
|
Metrics/BlockLength:
|
@@ -6,6 +7,9 @@ Metrics/BlockLength:
|
|
6
7
|
- 'spec/**/*_spec.rb'
|
7
8
|
- 'spec/factories/*.rb'
|
8
9
|
|
10
|
+
Layout/LineLength:
|
11
|
+
Max: 80
|
12
|
+
|
9
13
|
Naming/FileName:
|
10
14
|
Exclude:
|
11
15
|
- lib/shark-on-lambda.rb
|
data/changelog.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
#### Unreleased
|
4
4
|
|
5
|
+
#### 2.0.0
|
6
|
+
- [Deprecate] Requiring `shark-on-lambda` is marked as deprecated in favour of requiring `shark_on_lambda`.
|
7
|
+
- [Break] `SharkOnLambda::Dispatcher` was removed in favour of routing via `ActionDispatch::Routing`.
|
8
|
+
- [Break] `SharkOnLambda::BaseController` now renders _JSON API_-compliant responses.
|
9
|
+
- [Break] `SharkOnLambda::JsonapiController` was removed.
|
10
|
+
- [Break] Support for `path_parameters` in RSpec helpers was removed.
|
11
|
+
- [Break] Configuration files are not loaded automatically anymore.
|
12
|
+
- Added support for routing.
|
13
|
+
- Use `rack-on-lambda` as an adapter for events from the (REST API flavoured) API Gateway.
|
14
|
+
|
5
15
|
#### 1.0.1
|
6
16
|
|
7
17
|
- [Fix] `Jsonapi::Renderer#render` should always return a hash.
|
@@ -31,13 +31,13 @@ your RSpec tests and then use the methods `delete`, `get`, `patch`, `post`, or
|
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
RSpec.describe MyController do
|
34
|
-
let
|
35
|
-
let
|
34
|
+
let(:service_token) { 'my-super-secret-service-token' }
|
35
|
+
let(:headers) do
|
36
36
|
{
|
37
37
|
'authorization' => "Bearer #{service_token}"
|
38
38
|
}
|
39
39
|
end
|
40
|
-
let
|
40
|
+
let(:params) do
|
41
41
|
{
|
42
42
|
id: 1
|
43
43
|
}
|
data/lib/shark-on-lambda.rb
CHANGED
@@ -1,3 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
require 'active_support/deprecation'
|
5
|
+
|
6
|
+
deprecation_message = <<-MESSAGE.squish
|
7
|
+
Requiring `shark-on-lambda` is deprecated and will be removed in version 3.0.
|
8
|
+
Please require `shark_on_lambda` instead.
|
9
|
+
MESSAGE
|
10
|
+
ActiveSupport::Deprecation.warn(deprecation_message, caller(2))
|
11
|
+
|
3
12
|
require 'shark_on_lambda'
|
data/lib/shark_on_lambda.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'pry' if Gem.loaded_specs.key?('pry')
|
4
4
|
|
5
|
+
require 'erb'
|
5
6
|
require 'forwardable'
|
6
7
|
require 'ostruct'
|
7
8
|
require 'pathname'
|
@@ -14,6 +15,7 @@ require 'active_support/all'
|
|
14
15
|
require 'jsonapi/deserializable'
|
15
16
|
require 'jsonapi/serializable'
|
16
17
|
require 'rack/utils'
|
18
|
+
require 'rack-on-lambda'
|
17
19
|
require 'yaml'
|
18
20
|
require 'zeitwerk'
|
19
21
|
|
@@ -22,6 +24,7 @@ module SharkOnLambda; end
|
|
22
24
|
|
23
25
|
Zeitwerk::Loader.for_gem.tap do |loader|
|
24
26
|
loader.ignore(File.expand_path('shark-on-lambda.rb', __dir__))
|
27
|
+
loader.ignore(File.expand_path('shark_on_lambda/rake_tasks.rb', __dir__))
|
25
28
|
loader.inflector.inflect(
|
26
29
|
'rspec' => 'RSpec',
|
27
30
|
'version' => 'VERSION'
|
@@ -35,75 +38,24 @@ module SharkOnLambda
|
|
35
38
|
class << self
|
36
39
|
extend Forwardable
|
37
40
|
|
38
|
-
attr_writer :logger
|
41
|
+
attr_writer :application, :env, :logger
|
39
42
|
|
40
|
-
def_instance_delegators :
|
43
|
+
def_instance_delegators :application, :initialize!, :root
|
41
44
|
|
42
45
|
def application
|
43
46
|
@application ||= Application.new
|
44
47
|
end
|
45
48
|
|
46
|
-
def
|
47
|
-
|
49
|
+
def configuration
|
50
|
+
application.config
|
48
51
|
end
|
49
52
|
|
50
|
-
def
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def initialize!
|
55
|
-
enable_jsonapi!
|
56
|
-
|
57
|
-
yield(config, secrets)
|
58
|
-
|
59
|
-
Configuration.load(stage)
|
60
|
-
Secrets.load(stage)
|
61
|
-
run_initializers
|
62
|
-
|
63
|
-
true
|
64
|
-
end
|
65
|
-
|
66
|
-
def load_configuration
|
67
|
-
Configuration.load(stage)
|
68
|
-
Secrets.load(stage)
|
69
|
-
|
70
|
-
true
|
53
|
+
def env
|
54
|
+
@env || ENV['STAGE'].presence || 'development'
|
71
55
|
end
|
72
56
|
|
73
57
|
def logger
|
74
|
-
@logger ||= Logger.new(
|
75
|
-
end
|
76
|
-
|
77
|
-
def reset_configuration
|
78
|
-
known_stage = config.stage
|
79
|
-
known_root = config.root
|
80
|
-
|
81
|
-
Configuration.reset
|
82
|
-
Secrets.reset
|
83
|
-
|
84
|
-
config.root = known_root
|
85
|
-
config.stage = known_stage
|
86
|
-
|
87
|
-
true
|
88
|
-
end
|
89
|
-
|
90
|
-
def secrets
|
91
|
-
Secrets.instance
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def enable_jsonapi!
|
97
|
-
::Mime::Type.register('application/vnd.api+json', :jsonapi)
|
98
|
-
::ActionDispatch::Request.parameter_parsers[:jsonapi] =
|
99
|
-
::ActionDispatch::Request.parameter_parsers[:json].dup
|
100
|
-
end
|
101
|
-
|
102
|
-
def run_initializers
|
103
|
-
initializers_path = root.join('config', 'initializers')
|
104
|
-
Dir.glob(initializers_path.join('*.rb')).each do |path|
|
105
|
-
load path
|
106
|
-
end
|
58
|
+
@logger ||= Logger.new($stdout)
|
107
59
|
end
|
108
60
|
end
|
109
61
|
end
|
@@ -1,61 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module SharkOnLambda
|
4
|
-
class ApiGatewayHandler
|
5
|
-
|
6
|
-
|
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)
|
4
|
+
class ApiGatewayHandler < RackOnLambda::Handlers::RestApi
|
5
|
+
def self.call(event:, context:)
|
6
|
+
super(event: event, context: context, app: SharkOnLambda.application)
|
59
7
|
end
|
60
8
|
end
|
61
9
|
end
|
@@ -2,14 +2,84 @@
|
|
2
2
|
|
3
3
|
module SharkOnLambda
|
4
4
|
class Application
|
5
|
+
attr_reader :routes
|
6
|
+
|
7
|
+
delegate :middleware, :root, to: :config
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def config
|
11
|
+
@config ||= Configuration.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def inherited(subclass)
|
15
|
+
super
|
16
|
+
|
17
|
+
SharkOnLambda.application = subclass.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
register_jsonapi_rendering
|
23
|
+
initialize_router
|
24
|
+
end
|
25
|
+
|
5
26
|
def call(env)
|
6
27
|
dup.call!(env)
|
7
28
|
end
|
8
29
|
|
9
30
|
def call!(env)
|
10
|
-
|
11
|
-
middleware_stack = SharkOnLambda.config.middleware.build(dispatcher)
|
31
|
+
middleware_stack = middleware.build(routes)
|
12
32
|
middleware_stack.call(env)
|
13
33
|
end
|
34
|
+
|
35
|
+
def config
|
36
|
+
self.class.config
|
37
|
+
end
|
38
|
+
|
39
|
+
def config_for(name, env: SharkOnLambda.env)
|
40
|
+
config = load_config_file(name, env: env)
|
41
|
+
config.deep_merge(load_config_file("#{name}.local", env: env))
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize!
|
45
|
+
load_routes
|
46
|
+
run_initializers
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def initialize_router
|
52
|
+
router_config = ActionDispatch::Routing::RouteSet::Config.new(nil, true)
|
53
|
+
@routes = ActionDispatch::Routing::RouteSet.new_with_config(router_config)
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_config_file(name, env:)
|
57
|
+
filename = "#{name}.yml"
|
58
|
+
config_file = SharkOnLambda.root.join('config', filename)
|
59
|
+
unless config_file.exist?
|
60
|
+
raise ArgumentError,
|
61
|
+
"Could not load configuration. No such file - #{config_file}"
|
62
|
+
end
|
63
|
+
|
64
|
+
erb_parsed_config = ERB.new(config_file.read).result
|
65
|
+
config = YAML.safe_load(erb_parsed_config, [], [], true, filename) || {}
|
66
|
+
config.fetch(env, {}).with_indifferent_access
|
67
|
+
end
|
68
|
+
|
69
|
+
def load_routes
|
70
|
+
routes_path = SharkOnLambda.root.join('config', 'routes.rb').to_s
|
71
|
+
load routes_path if File.exist?(routes_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def register_jsonapi_rendering
|
75
|
+
::Mime::Type.register('application/vnd.api+json', :jsonapi)
|
76
|
+
::ActionDispatch::Request.parameter_parsers[:jsonapi] =
|
77
|
+
::ActionDispatch::Request.parameter_parsers[:json].dup
|
78
|
+
end
|
79
|
+
|
80
|
+
def run_initializers
|
81
|
+
initializers_folder = SharkOnLambda.root.join('config', 'initializers')
|
82
|
+
Dir.glob(initializers_folder.join('*.rb')).each { |path| load path }
|
83
|
+
end
|
14
84
|
end
|
15
85
|
end
|
@@ -6,13 +6,6 @@ module SharkOnLambda
|
|
6
6
|
AbstractController::Translation,
|
7
7
|
AbstractController::AssetPaths,
|
8
8
|
|
9
|
-
ActionController::UrlFor,
|
10
|
-
ActionController::ConditionalGet,
|
11
|
-
ActionController::EtagWithTemplateDigest,
|
12
|
-
ActionController::EtagWithFlash,
|
13
|
-
ActionController::Caching,
|
14
|
-
ActionController::MimeResponds,
|
15
|
-
ActionController::ImplicitRender,
|
16
9
|
ActionController::Cookies,
|
17
10
|
ActionController::Flash,
|
18
11
|
ActionController::FormBuilder,
|
@@ -24,10 +17,27 @@ module SharkOnLambda
|
|
24
17
|
ActionController::HttpAuthentication::Token::ControllerMethods,
|
25
18
|
ActionView::Layouts
|
26
19
|
].freeze
|
27
|
-
ActionController::
|
20
|
+
ActionController::API.without_modules(EXCLUDED_MODULES).each do |mod|
|
28
21
|
include mod
|
29
22
|
end
|
30
23
|
|
24
|
+
ActionController::Renderers.add :jsonapi do |object, options|
|
25
|
+
response.set_header('content-type', 'application/vnd.api+json')
|
26
|
+
return { data: {} }.to_json if object.nil?
|
27
|
+
|
28
|
+
jsonapi_renderer = JsonapiRenderer.new(object)
|
29
|
+
|
30
|
+
jsonapi_params = params.slice(:fields, :include)
|
31
|
+
jsonapi_params.permit!
|
32
|
+
jsonapi_params = JsonapiParameters.new(jsonapi_params.to_h)
|
33
|
+
|
34
|
+
render_options = jsonapi_params.to_h.deep_merge(options)
|
35
|
+
jsonapi_object = jsonapi_renderer.render(render_options)
|
36
|
+
|
37
|
+
response.status = jsonapi_renderer.status
|
38
|
+
jsonapi_object.to_json
|
39
|
+
end
|
40
|
+
|
31
41
|
def self.dispatch(*)
|
32
42
|
super
|
33
43
|
rescue AbstractController::ActionNotFound,
|
@@ -38,7 +48,17 @@ module SharkOnLambda
|
|
38
48
|
|
39
49
|
def redirect_to(*)
|
40
50
|
super
|
41
|
-
|
51
|
+
|
52
|
+
self.response_body = no_body? ? nil : { data: {} }.to_json
|
53
|
+
end
|
54
|
+
|
55
|
+
def render(object, options = {})
|
56
|
+
options.merge!(
|
57
|
+
jsonapi: object,
|
58
|
+
content_type: 'application/vnd.api+json'
|
59
|
+
)
|
60
|
+
|
61
|
+
super(options)
|
42
62
|
end
|
43
63
|
|
44
64
|
private
|
@@ -2,63 +2,7 @@
|
|
2
2
|
|
3
3
|
module SharkOnLambda
|
4
4
|
class Configuration < OpenStruct
|
5
|
-
|
6
|
-
|
7
|
-
attr_writer :dispatcher, :stage
|
8
|
-
|
9
|
-
class << self
|
10
|
-
include Concerns::YamlConfigLoader
|
11
|
-
|
12
|
-
attr_writer :database_files, :settings_files
|
13
|
-
|
14
|
-
def database_files
|
15
|
-
return @database_files if defined?(@database_files)
|
16
|
-
|
17
|
-
files = %w[config/database.yml config/database.local.yml]
|
18
|
-
@database_files = paths(files)
|
19
|
-
end
|
20
|
-
|
21
|
-
def load(stage, fallback: :default)
|
22
|
-
load_settings(stage, fallback: fallback)
|
23
|
-
load_database_configuration(stage, fallback: fallback)
|
24
|
-
|
25
|
-
instance
|
26
|
-
end
|
27
|
-
|
28
|
-
def settings_files
|
29
|
-
return @settings_files if defined?(@settings_files)
|
30
|
-
|
31
|
-
files = %w[config/settings.yml config/settings.local.yml]
|
32
|
-
@settings_files = paths(files)
|
33
|
-
end
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
def load_database_configuration(stage, fallback:)
|
38
|
-
instance.database = load_yaml_files(stage: stage,
|
39
|
-
fallback: fallback,
|
40
|
-
paths: paths(database_files))
|
41
|
-
end
|
42
|
-
|
43
|
-
def load_settings(stage, fallback:)
|
44
|
-
settings = load_yaml_files(stage: stage,
|
45
|
-
fallback: fallback,
|
46
|
-
paths: paths(settings_files))
|
47
|
-
settings.each_pair do |key, value|
|
48
|
-
next if key.to_s == 'serverless'
|
49
|
-
|
50
|
-
instance.send("#{key}=", value)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def paths(files)
|
55
|
-
files.map { |file| SharkOnLambda.config.root.join(file) }
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def dispatcher
|
60
|
-
@dispatcher ||= Dispatcher.new
|
61
|
-
end
|
5
|
+
attr_reader :root
|
62
6
|
|
63
7
|
def middleware
|
64
8
|
@middleware ||= ActionDispatch::MiddlewareStack.new do |middleware_stack|
|
@@ -66,16 +10,8 @@ module SharkOnLambda
|
|
66
10
|
end
|
67
11
|
end
|
68
12
|
|
69
|
-
def root
|
70
|
-
@root ||= Pathname.new('.')
|
71
|
-
end
|
72
|
-
|
73
13
|
def root=(new_root)
|
74
14
|
@root = Pathname.new(new_root)
|
75
15
|
end
|
76
|
-
|
77
|
-
def stage
|
78
|
-
@stage || 'development'
|
79
|
-
end
|
80
16
|
end
|
81
17
|
end
|