hanami 2.0.0.alpha2 → 2.0.0.alpha3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +47 -0
- data/README.md +6 -2
- data/hanami.gemspec +3 -2
- data/lib/hanami/application/container/boot/logger.rb +1 -2
- data/lib/hanami/application/container/boot/rack_logger.rb +1 -1
- data/lib/hanami/application/routes.rb +54 -0
- data/lib/hanami/application/routing/resolver.rb +1 -1
- data/lib/hanami/application/settings/dotenv_store.rb +60 -0
- data/lib/hanami/application/settings.rb +78 -8
- data/lib/hanami/application.rb +47 -42
- data/lib/hanami/configuration/logger.rb +40 -0
- data/lib/hanami/configuration/middleware.rb +2 -2
- data/lib/hanami/configuration/null_configuration.rb +14 -0
- data/lib/hanami/configuration/router.rb +28 -26
- data/lib/hanami/configuration/sessions.rb +5 -5
- data/lib/hanami/configuration.rb +85 -184
- data/lib/hanami/slice.rb +40 -11
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami.rb +4 -0
- metadata +32 -11
- data/lib/hanami/application/settings/definition.rb +0 -26
- data/lib/hanami/application/settings/loader.rb +0 -97
- data/lib/hanami/application/settings/struct.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f322cd4a751d83369d2d20f0f209bfb1dca92a78f6a3dd7c4027ea672df84e36
|
4
|
+
data.tar.gz: 801be572c3df6e61bfaee8b72f0a164dcbe83216f33c72972c67334f9b2619cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 244ab662705c248857bc4d4e3f42b1de6dc92003fb3c8fe6d3cd006194be272d1aac36f570baa319a971dfcdd6f24eb691c270fa57b852fdbc4da863bc1908d1
|
7
|
+
data.tar.gz: 3d6b72d227de112fbedefb7f8f6fbcb1e010fb37bf3d97e5826b6fe134dc0facd2a36bba0ad5e2118f731ee2bb1d18ae4f7307377c0fd31e5b81a3e307c56ae0
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,53 @@
|
|
1
1
|
# Hanami
|
2
2
|
The web, with simplicity.
|
3
3
|
|
4
|
+
## v2.0.0.alpha3 - 2021-11-09
|
5
|
+
### Added
|
6
|
+
- [Luca Guidi] Added `Hanami.shutdown` to stop all bootable components in the application container
|
7
|
+
- [Tim Riley] Added `component_dir_paths` application setting to allow for components to be loaded from additional directories inside each slice directory. To begin with, this defaults to `%w[actions repositories views]`. Components inside these directories are expected to be namespaced to match the directory name; e.g. given a `main` slice, `slices/main/actions/home.rb` is expected to define `Main::Actions::Home`, and will be registered in the slice container as `"actions.home"`.
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- [Tim Riley] A slice's classes can now be defined directly inside `slices/[slice_name]/lib/`; e.g. given a `main` slice, `slices/main/lib/example.rb` is expected to define `Main::Example`, and will be registered in the slice container as `"example"`
|
11
|
+
- [Tim Riley] The root `lib/` directory is no longer configured as a component dir, and classes inside `lib/[app_namespace]/` will no longer be auto-registered into the container. If you need to share components, create them in their own slices as appropriate, and import those slices into the other slices that require them.
|
12
|
+
- [Tim Riley] `lib/[app_namespace]/` is configured for autoloading, and `lib/` is added to `$LOAD_PATH` to support explicit requires for source files outside `lib/[app_namespace]/`.
|
13
|
+
- [Tim Riley] (Internal) Ported `Hanami::Configuration` and related classes to use dry-configurable
|
14
|
+
- [Tim Riley] Application inflector can be entirely replaced, if required, via `Hanami::Configuration#inflector=`. Custom inflection rules can still be provided to the default inflector via `Hanami::Configuration#inflections`.
|
15
|
+
- [Marc Busqué] App settings are defined within a concrete class rather than an anonymous block, to allow for users to leverage the typical behavior of Ruby classes, such as for defining their own types module to use for coercing setting values. This class also relies on dry-configurable for its settings implementation, so the standard dry-configurable `setting` API is available, such as the `constructor:` and `default:` options.
|
16
|
+
```ruby
|
17
|
+
# frozen_string_literal: true
|
18
|
+
|
19
|
+
require "dry/types"
|
20
|
+
require "hanami/application/settings"
|
21
|
+
|
22
|
+
module TestApp
|
23
|
+
class Settings < Hanami::Application::Settings
|
24
|
+
# Example usage of a types module (previously not possible inside the anonymous block)
|
25
|
+
Types = Dry.Types()
|
26
|
+
|
27
|
+
setting :session_secret, constructor: Types::String.constrained(min_size: 20)
|
28
|
+
|
29
|
+
setting :some_bool, constructor: Types::Params::Bool, default: false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
- [Marc Busqué] Application `settings_loader` and `settings_loader_options` have been replaced with `settings_store`, which is an updated abstraction for providing setting values to work with the new `Hanami::Application::Settings` implementation noted above (see `Application::Settings::DotenvStore` for the default store, which provides the same behavior as previously)
|
34
|
+
- [Marc Busqué] Routes are defined within a concrete class rather than an anonymous block, to provide consistency with the settings (noted above), as well a place for additional behavior (in future releases):
|
35
|
+
```ruby
|
36
|
+
# frozen_string_literal: true
|
37
|
+
|
38
|
+
require "hanami/application/routes"
|
39
|
+
|
40
|
+
module MyApp
|
41
|
+
class Routes < Hanami::Application::Routes
|
42
|
+
define do
|
43
|
+
slice :main, at: "/" do
|
44
|
+
root to: "home.show"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
4
51
|
## v2.0.0.alpha2 - 2021-05-04
|
5
52
|
### Added
|
6
53
|
- [Luca Guidi] Official support for Ruby: MRI 3.0
|
data/README.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
The web, with simplicity.
|
4
4
|
|
5
|
+
## Version
|
6
|
+
|
7
|
+
**This branch contains the code for `hanami` 2.0.x.**
|
8
|
+
|
5
9
|
## Frameworks
|
6
10
|
|
7
11
|
Hanami is a **full-stack** Ruby web framework.
|
@@ -25,8 +29,8 @@ These components are designed to be used independently or together in a Hanami a
|
|
25
29
|
## Status
|
26
30
|
|
27
31
|
[![Gem Version](https://badge.fury.io/rb/hanami.svg)](https://badge.fury.io/rb/hanami)
|
28
|
-
[![CI](https://github.com/hanami/hanami/workflows/ci/badge.svg?branch=
|
29
|
-
[![Test Coverage](https://codecov.io/gh/hanami/hanami/branch/
|
32
|
+
[![CI](https://github.com/hanami/hanami/workflows/ci/badge.svg?branch=main)](https://github.com/hanami/hanami/actions?query=workflow%3Aci+branch%3Amain)
|
33
|
+
[![Test Coverage](https://codecov.io/gh/hanami/hanami/branch/main/graph/badge.svg)](https://codecov.io/gh/hanami/hanami)
|
30
34
|
[![Depfu](https://badges.depfu.com/badges/ba000e0f69e6ef1c44cd3038caaa1841/overview.svg)](https://depfu.com/github/hanami/hanami?project=Bundler)
|
31
35
|
[![Inline Docs](http://inch-ci.org/github/hanami/hanami.svg)](http://inch-ci.org/github/hanami/hanami)
|
32
36
|
|
data/hanami.gemspec
CHANGED
@@ -22,10 +22,11 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
22
22
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
23
23
|
|
24
24
|
spec.add_dependency "bundler", ">= 1.16", "< 3"
|
25
|
+
spec.add_dependency "dry-configurable", "~> 0.12", ">= 0.12.1"
|
25
26
|
spec.add_dependency "dry-core", "~> 0.4"
|
26
|
-
spec.add_dependency "dry-inflector", "~> 0.
|
27
|
+
spec.add_dependency "dry-inflector", "~> 0.2", ">= 0.2.1"
|
27
28
|
spec.add_dependency "dry-monitor"
|
28
|
-
spec.add_dependency "dry-system", "~> 0.19", ">= 0.
|
29
|
+
spec.add_dependency "dry-system", "~> 0.19", ">= 0.21.0"
|
29
30
|
spec.add_dependency "hanami-cli", "~> 2.0.alpha"
|
30
31
|
spec.add_dependency "hanami-utils", "~> 2.0.alpha"
|
31
32
|
spec.add_dependency "zeitwerk", "~> 2.4"
|
@@ -9,7 +9,7 @@ Hanami.application.register_bootable :rack_logger do |container|
|
|
9
9
|
|
10
10
|
rack_logger = Hanami::Web::RackLogger.new(
|
11
11
|
container[:logger],
|
12
|
-
filter_params: Hanami.application.configuration.
|
12
|
+
filter_params: Hanami.application.configuration.logger.filter_params
|
13
13
|
)
|
14
14
|
|
15
15
|
rack_logger.attach container[:rack_monitor]
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
class Application
|
5
|
+
# Application routes
|
6
|
+
#
|
7
|
+
# Users are expected to inherit from this class to define their application
|
8
|
+
# routes.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # config/routes.rb
|
12
|
+
# # frozen_string_literal: true
|
13
|
+
#
|
14
|
+
# require "hanami/application/routes"
|
15
|
+
#
|
16
|
+
# module MyApp
|
17
|
+
# class Routes < Hanami::Application::Routes
|
18
|
+
# define do
|
19
|
+
# slice :main, at: "/" do
|
20
|
+
# root to: "home.show"
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# See {Hanami::Application::Router} for the syntax allowed within the
|
27
|
+
# `define` block.
|
28
|
+
#
|
29
|
+
# @see Hanami::Application::Router
|
30
|
+
# @since 2.0.0
|
31
|
+
class Routes
|
32
|
+
# Defines application routes
|
33
|
+
#
|
34
|
+
# @yield DSL syntax to define application routes executed in the context
|
35
|
+
# of {Hanami::Application::Router}
|
36
|
+
# @returns [Proc]
|
37
|
+
def self.define(&block)
|
38
|
+
@_routes = block
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
def self.routes
|
43
|
+
@_routes || raise(<<~MSG)
|
44
|
+
Routes need to be defined before being able to fetch them. E.g.,
|
45
|
+
define do
|
46
|
+
slice :main, at: "/" do
|
47
|
+
root to: "home.show"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
MSG
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -72,7 +72,7 @@ module Hanami
|
|
72
72
|
def resolve_string_identifier(path, identifier)
|
73
73
|
slice_name = slices_registry.find(path) or raise "missing slice for #{path.inspect} (#{identifier.inspect})"
|
74
74
|
slice = slices[slice_name]
|
75
|
-
action_key = "actions.#{identifier
|
75
|
+
action_key = "actions.#{identifier}"
|
76
76
|
|
77
77
|
slice[action_key]
|
78
78
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/constants"
|
4
|
+
|
5
|
+
module Hanami
|
6
|
+
class Application
|
7
|
+
class Settings
|
8
|
+
# Default application settings store.
|
9
|
+
#
|
10
|
+
# Uses [dotenv](https://github.com/bkeepers/dotenv) (if available) to load
|
11
|
+
# .env files and then loads settings from ENV. For a given `HANAMI_ENV`
|
12
|
+
# environment, the following `.env` files are looked up in the following order:
|
13
|
+
#
|
14
|
+
# - .env.{environment}.local
|
15
|
+
# - .env.local (except if the environment is `test`)
|
16
|
+
# - .env.{environment}
|
17
|
+
# - .env
|
18
|
+
#
|
19
|
+
# @since 2.0.0
|
20
|
+
# @api private
|
21
|
+
class DotenvStore
|
22
|
+
Undefined = Dry::Core::Constants::Undefined
|
23
|
+
|
24
|
+
attr_reader :store,
|
25
|
+
:hanami_env
|
26
|
+
|
27
|
+
def initialize(store: ENV, hanami_env: Hanami.env)
|
28
|
+
@store = store
|
29
|
+
@hanami_env = hanami_env
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch(name, default_value = Undefined, &block)
|
33
|
+
name = name.to_s.upcase
|
34
|
+
args = (default_value == Undefined) ? [name] : [name, default_value]
|
35
|
+
|
36
|
+
store.fetch(*args, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def with_dotenv_loaded
|
40
|
+
require "dotenv"
|
41
|
+
Dotenv.load(*dotenv_files) if defined?(Dotenv)
|
42
|
+
self
|
43
|
+
rescue LoadError
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def dotenv_files
|
50
|
+
[
|
51
|
+
".env.#{hanami_env}.local",
|
52
|
+
(".env.local" unless hanami_env == :test),
|
53
|
+
".env.#{hanami_env}",
|
54
|
+
".env"
|
55
|
+
].compact
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,22 +1,92 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "dry/configurable"
|
3
4
|
require "dry/core/constants"
|
4
|
-
require_relative "settings/definition"
|
5
|
-
require_relative "settings/struct"
|
6
5
|
|
7
6
|
module Hanami
|
8
7
|
class Application
|
9
8
|
# Application settings
|
10
9
|
#
|
10
|
+
# Users are expected to inherit from this class to define their application
|
11
|
+
# settings.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # config/settings.rb
|
15
|
+
# # frozen_string_literal: true
|
16
|
+
#
|
17
|
+
# require "hanami/application/settings"
|
18
|
+
# require "my_app/types"
|
19
|
+
#
|
20
|
+
# module MyApp
|
21
|
+
# class Settings < Hanami::Application::Settings
|
22
|
+
# setting :database_url
|
23
|
+
# setting :feature_flag, default: false, constructor: Types::Params::Bool
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Settings are defined with
|
28
|
+
# [dry-configurable](https://dry-rb.org/gems/dry-configurable/), so you can
|
29
|
+
# take a look there to see the supported syntax.
|
30
|
+
#
|
31
|
+
# Users work with an instance of this class made available within the
|
32
|
+
# `settings` key in the container. The instance gets its settings populated
|
33
|
+
# from a configurable store, which defaults to
|
34
|
+
# {Hanami::Application::Settings::DotenvStore}.
|
35
|
+
#
|
36
|
+
# A different store can be set through the `settings_store` Hanami
|
37
|
+
# configuration option. All it needs to do is implementing a `#fetch` method
|
38
|
+
# with the same signature as `Hash#fetch`.
|
39
|
+
#
|
40
|
+
# @see Hanami::Application::Settings::DotenvStore
|
11
41
|
# @since 2.0.0
|
12
|
-
|
13
|
-
|
42
|
+
class Settings
|
43
|
+
# Exception for errors in the definition of settings.
|
44
|
+
#
|
45
|
+
# Its message collects all the individual errors that can be raised for
|
46
|
+
# each setting.
|
47
|
+
InvalidSettingsError = Class.new(StandardError) do
|
48
|
+
def initialize(errors)
|
49
|
+
@errors = errors
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
<<~STR.strip
|
54
|
+
Could not initialize settings. The following settings were invalid:
|
55
|
+
|
56
|
+
#{@errors.map { |setting, message| "#{setting}: #{message}" }.join("\n")}
|
57
|
+
STR
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# @api private
|
62
|
+
EMPTY_STORE = Dry::Core::Constants::EMPTY_HASH
|
63
|
+
|
64
|
+
include Dry::Configurable
|
65
|
+
|
66
|
+
# @api private
|
67
|
+
def initialize(store = EMPTY_STORE)
|
68
|
+
errors = config._settings.map(&:name).reduce({}) do |errs, name|
|
69
|
+
public_send("#{name}=", store.fetch(name) { Dry::Core::Constants::Undefined })
|
70
|
+
errs
|
71
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
72
|
+
errs.merge(name => e)
|
73
|
+
end
|
14
74
|
|
15
|
-
|
16
|
-
|
17
|
-
|
75
|
+
raise InvalidSettingsError, errors if errors.any?
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def method_missing(name, *args, &block)
|
81
|
+
if config.respond_to?(name)
|
82
|
+
config.send(name, *args, &block)
|
83
|
+
else
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
18
87
|
|
19
|
-
|
88
|
+
def respond_to_missing?(name, _include_all = false)
|
89
|
+
config.respond_to?(name) || super
|
20
90
|
end
|
21
91
|
end
|
22
92
|
end
|
data/lib/hanami/application.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "dry/system/container"
|
4
|
+
require "dry/system/loader/autoloading"
|
4
5
|
require "hanami/configuration"
|
5
6
|
require "pathname"
|
6
7
|
require "rack"
|
8
|
+
require "zeitwerk"
|
7
9
|
require_relative "slice"
|
8
10
|
require_relative "application/autoloader/inflector_adapter"
|
11
|
+
require_relative "application/routes"
|
9
12
|
require_relative "application/settings"
|
10
13
|
|
11
14
|
module Hanami
|
@@ -52,7 +55,10 @@ module Hanami
|
|
52
55
|
def init # rubocop:disable Metrics/MethodLength
|
53
56
|
return self if inited?
|
54
57
|
|
55
|
-
configuration.finalize
|
58
|
+
configuration.finalize!
|
59
|
+
|
60
|
+
@autoloader = Zeitwerk::Loader.new
|
61
|
+
autoloader.inflector = Autoloader::InflectorAdapter.new(inflector)
|
56
62
|
|
57
63
|
load_settings
|
58
64
|
|
@@ -63,10 +69,7 @@ module Hanami
|
|
63
69
|
slices.values.each(&:init)
|
64
70
|
slices.freeze
|
65
71
|
|
66
|
-
|
67
|
-
configuration.autoloader.inflector = Autoloader::InflectorAdapter.new(inflector)
|
68
|
-
configuration.autoloader.setup
|
69
|
-
end
|
72
|
+
autoloader.setup
|
70
73
|
|
71
74
|
load_routes
|
72
75
|
|
@@ -78,6 +81,12 @@ module Hanami
|
|
78
81
|
@inited
|
79
82
|
end
|
80
83
|
|
84
|
+
def autoloader
|
85
|
+
raise "Application not init'ed" unless defined?(@autoloader)
|
86
|
+
|
87
|
+
@autoloader
|
88
|
+
end
|
89
|
+
|
81
90
|
def container
|
82
91
|
raise "Application not init'ed" unless defined?(@container)
|
83
92
|
|
@@ -151,32 +160,17 @@ module Hanami
|
|
151
160
|
@booted
|
152
161
|
end
|
153
162
|
|
154
|
-
def
|
155
|
-
|
156
|
-
@_settings = Application::Settings.build(
|
157
|
-
configuration.settings_loader,
|
158
|
-
configuration.settings_loader_options,
|
159
|
-
&block
|
160
|
-
)
|
161
|
-
elsif instance_variable_defined?(:@_settings)
|
162
|
-
@_settings
|
163
|
-
else
|
164
|
-
# Load settings lazily so they can be used to configure the
|
165
|
-
# Hanami::Application subclass (before the application has inited)
|
166
|
-
load_settings
|
167
|
-
@_settings ||= nil
|
168
|
-
end
|
163
|
+
def shutdown
|
164
|
+
container.shutdown!
|
169
165
|
end
|
170
166
|
|
171
|
-
def
|
172
|
-
@
|
173
|
-
|
174
|
-
raise "Hanami.application.routes not configured" unless defined?(@_routes)
|
167
|
+
def settings
|
168
|
+
@_settings ||= load_settings
|
169
|
+
end
|
175
170
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
end
|
171
|
+
def routes
|
172
|
+
@_mutex.synchronize do
|
173
|
+
@_routes ||= load_routes
|
180
174
|
end
|
181
175
|
end
|
182
176
|
|
@@ -187,6 +181,10 @@ module Hanami
|
|
187
181
|
inflector.constantize(name.split(MODULE_DELIMITER)[0..-2].join(MODULE_DELIMITER))
|
188
182
|
end
|
189
183
|
|
184
|
+
def namespace_name
|
185
|
+
namespace.name
|
186
|
+
end
|
187
|
+
|
190
188
|
def namespace_path
|
191
189
|
inflector.underscore(namespace)
|
192
190
|
end
|
@@ -256,21 +254,19 @@ module Hanami
|
|
256
254
|
Pathname(__dir__).join("application/container/boot").realpath,
|
257
255
|
]
|
258
256
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
config.component_dirs.add_to_load_path = false
|
263
|
-
end
|
264
|
-
|
265
|
-
if root.join("lib").directory?
|
266
|
-
config.component_dirs.add "lib" do |dir|
|
267
|
-
dir.default_namespace = application_name.to_s
|
268
|
-
end
|
257
|
+
config.component_dirs.loader = Dry::System::Loader::Autoloading
|
258
|
+
config.component_dirs.add_to_load_path = false
|
259
|
+
end
|
269
260
|
|
270
|
-
|
271
|
-
|
261
|
+
# Autoload classes defined in lib/[app_namespace]/
|
262
|
+
if root.join("lib", namespace_path).directory?
|
263
|
+
autoloader.push_dir(root.join("lib", namespace_path), namespace: namespace)
|
272
264
|
end
|
273
265
|
|
266
|
+
# Add lib/ to to the $LOAD_PATH so other files there (outside the app namespace)
|
267
|
+
# are require-able
|
268
|
+
container.add_to_load_path!("lib") if root.join("lib").directory?
|
269
|
+
|
274
270
|
container
|
275
271
|
end
|
276
272
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
@@ -317,14 +313,23 @@ module Hanami
|
|
317
313
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
318
314
|
|
319
315
|
def load_routes
|
320
|
-
require File.join(configuration.root, configuration.router.
|
316
|
+
require File.join(configuration.root, configuration.router.routes_path)
|
317
|
+
routes_class = autodiscover_application_constant(configuration.router.routes_class_name)
|
318
|
+
routes_class.routes
|
321
319
|
rescue LoadError # rubocop:disable Lint/SuppressedException
|
322
320
|
end
|
323
321
|
|
324
322
|
def load_settings
|
325
323
|
prepare_base_load_path
|
326
324
|
require File.join(configuration.root, configuration.settings_path)
|
327
|
-
|
325
|
+
settings_class = autodiscover_application_constant(configuration.settings_class_name)
|
326
|
+
settings_class.new(configuration.settings_store)
|
327
|
+
rescue LoadError
|
328
|
+
Settings.new
|
329
|
+
end
|
330
|
+
|
331
|
+
def autodiscover_application_constant(constants)
|
332
|
+
inflector.constantize([namespace_name, *constants].join(MODULE_DELIMITER))
|
328
333
|
end
|
329
334
|
end
|
330
335
|
# rubocop:enable Metrics/ModuleLength
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/configurable"
|
4
|
+
require "hanami/logger"
|
5
|
+
|
6
|
+
module Hanami
|
7
|
+
class Configuration
|
8
|
+
# Hanami logger configuration
|
9
|
+
#
|
10
|
+
# @since 2.0.0
|
11
|
+
class Logger
|
12
|
+
include Dry::Configurable
|
13
|
+
|
14
|
+
protected :config
|
15
|
+
|
16
|
+
setting :logger_class, default: Hanami::Logger
|
17
|
+
|
18
|
+
setting :options, default: {level: :debug}
|
19
|
+
|
20
|
+
# Currently used for logging of Rack requests only.
|
21
|
+
#
|
22
|
+
# TODO: incorporate this into the standard logging some way or another
|
23
|
+
setting :filter_params, default: %w[_csrf password password_confirmation].freeze
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def method_missing(name, *args, &block)
|
28
|
+
if config.respond_to?(name)
|
29
|
+
config.public_send(name, *args, &block)
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to_missing?(name, _incude_all = false)
|
36
|
+
config.respond_to?(name) || super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -6,6 +6,8 @@ module Hanami
|
|
6
6
|
#
|
7
7
|
# @since 2.0.0
|
8
8
|
class Middleware
|
9
|
+
attr_reader :stack
|
10
|
+
|
9
11
|
def initialize
|
10
12
|
@stack = []
|
11
13
|
end
|
@@ -13,8 +15,6 @@ module Hanami
|
|
13
15
|
def use(middleware, *args, &block)
|
14
16
|
stack.push([middleware, *args, block].compact)
|
15
17
|
end
|
16
|
-
|
17
|
-
attr_reader :stack
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/configurable"
|
4
|
+
|
5
|
+
module Hanami
|
6
|
+
class Configuration
|
7
|
+
# NullConfiguration can serve as a fallback configuration object when out-of-gem
|
8
|
+
# configuration objects are not available (specifically, when the hanami-controller or
|
9
|
+
# hanami-view gems are not loaded)
|
10
|
+
class NullConfiguration
|
11
|
+
include Dry::Configurable
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "dry/configurable"
|
4
|
+
require_relative "../application/routing/resolver"
|
5
|
+
|
3
6
|
module Hanami
|
4
7
|
class Configuration
|
5
8
|
# Hanami router configuration
|
@@ -7,44 +10,43 @@ module Hanami
|
|
7
10
|
# @since 2.0.0
|
8
11
|
# @api private
|
9
12
|
class Router
|
10
|
-
|
11
|
-
# @since 2.0.0
|
12
|
-
attr_writer :routes
|
13
|
-
|
14
|
-
# @api private
|
15
|
-
# @since 2.0.0
|
16
|
-
attr_reader :routes
|
13
|
+
include Dry::Configurable
|
17
14
|
|
18
|
-
#
|
19
|
-
|
20
|
-
|
15
|
+
# Base configuration is provided so router config can include the `base_url`
|
16
|
+
attr_reader :base_configuration
|
17
|
+
private :base_configuration
|
21
18
|
|
22
19
|
# @api private
|
23
20
|
# @since 2.0.0
|
24
|
-
def initialize(
|
25
|
-
@
|
26
|
-
@routes = routes
|
21
|
+
def initialize(base_configuration)
|
22
|
+
@base_configuration = base_configuration
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
Application::Routing::Resolver
|
35
|
-
end
|
36
|
-
end
|
25
|
+
setting :routes_path, default: File.join("config", "routes")
|
26
|
+
|
27
|
+
setting :routes_class_name, default: "Routes"
|
28
|
+
|
29
|
+
setting :resolver, default: Application::Routing::Resolver
|
37
30
|
|
38
31
|
# @api private
|
39
32
|
# @since 2.0.0
|
40
33
|
def options
|
41
|
-
{
|
34
|
+
{base_url: base_configuration.base_url}
|
42
35
|
end
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
private
|
38
|
+
|
39
|
+
def method_missing(name, *args, &block)
|
40
|
+
if config.respond_to?(name)
|
41
|
+
config.public_send(name, *args, &block)
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def respond_to_missing?(name, _include_all = false)
|
48
|
+
config.respond_to?(name) || super
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|