hanami 2.0.0.alpha5 → 2.0.0.alpha6
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/CHANGELOG.md +77 -0
- data/README.md +2 -6
- data/hanami.gemspec +5 -4
- data/lib/hanami/application/container/{boot → providers}/inflector.rb +1 -1
- data/lib/hanami/application/container/{boot → providers}/logger.rb +1 -1
- data/lib/hanami/application/container/providers/rack_logger.rb +15 -0
- data/lib/hanami/application/container/{boot → providers}/rack_monitor.rb +2 -2
- data/lib/hanami/application/container/{boot → providers}/routes_helper.rb +1 -1
- data/lib/hanami/application/container/{boot → providers}/settings.rb +1 -1
- data/lib/hanami/application.rb +59 -69
- data/lib/hanami/cli/application/cli.rb +1 -1
- data/lib/hanami/configuration.rb +1 -1
- data/lib/hanami/{init.rb → prepare.rb} +1 -1
- data/lib/hanami/slice.rb +97 -94
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +27 -51
- data/lib/hanami.rb +2 -2
- metadata +16 -18
- data/lib/hanami/application/autoloader/inflector_adapter.rb +0 -22
- data/lib/hanami/application/container/boot/rack_logger.rb +0 -19
- data/lib/hanami/application/routing/router.rb +0 -36
- data/lib/hanami/boot/source_dirs.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fc76408b7d97db32194d24bf73739bde8405fbd13855b7e4ea744f634d0739e
|
4
|
+
data.tar.gz: 30d954f8332ea7579898a87187a89a0ae2a1b34b5d9f564a86b6f61c0844f2af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f64124d027449d451f5be703f4c00850c826e4d55ebef1e6c396be63dea59a9019cb74438f7844f1e68a187299ea45c7f89ba1e98267380e7d8e1b1f8666e4b9
|
7
|
+
data.tar.gz: 8ea32aae47f0fe9536726c977af03904fa23f7258ef747b2cdd1a3b324eb064466beccc9340b7dddfb46d3d6a49c8aba899b1b488c6016377581599efd594577
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,83 @@
|
|
1
1
|
# Hanami
|
2
2
|
The web, with simplicity.
|
3
3
|
|
4
|
+
## v2.0.0.alpha6 - 2022-02-10
|
5
|
+
### Added
|
6
|
+
- [Luca Guidi] Official support for Ruby: MRI 3.1
|
7
|
+
- [Tim Riley] Introduce partial Slice imports and exports. It allows to selectively export a functionality from a slice and import into another.
|
8
|
+
|
9
|
+
Import from `search` slice, uses `search` as the imported key namespace:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# config/application.rb
|
13
|
+
|
14
|
+
module MyApp
|
15
|
+
class Application < Hanami::Application
|
16
|
+
config.slice(:admin) do
|
17
|
+
import(from: :search)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
Import from `search` slice with custom namespace:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# config/application.rb
|
27
|
+
|
28
|
+
module MyApp
|
29
|
+
class Application < Hanami::Application
|
30
|
+
config.slice(:admin) do
|
31
|
+
import(from: :search, as: :search_engine)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
Import specific keys from `search` slice
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
# config/application.rb
|
41
|
+
|
42
|
+
module MyApp
|
43
|
+
class Application < Hanami::Application
|
44
|
+
config.slice(:admin) do
|
45
|
+
import(keys: ["run_query"], from: :search)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
Export only specific keys from `search` slice, and import them in `admin`
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# config/application.rb
|
55
|
+
|
56
|
+
module MyApp
|
57
|
+
class Application < Hanami::Application
|
58
|
+
config.slice(:admin) do
|
59
|
+
import(from: :search)
|
60
|
+
end
|
61
|
+
|
62
|
+
config.slice(:search) do
|
63
|
+
container.config.exports = %w[run_query index_item]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### Fixed
|
70
|
+
- [Luca Guidi] Ensure request logger to respect logger formatter option.
|
71
|
+
|
72
|
+
### Changed
|
73
|
+
- [Luca Guidi] Drop support for Ruby: MRI 2.6 and 2.7.
|
74
|
+
- [Tim Riley] `Hanami.init` => `Hanami.prepare` and `hanami/init` => `hanami/prepare`
|
75
|
+
- [Tim Riley] `Hanami.register_bootable` => `Hanami.register_provider`
|
76
|
+
- [Tim Riley] `Hanami.start_bootable` => `Hanami.start`
|
77
|
+
- [Tim Riley] `Hanami::Slice#init` => `Hanami::Slice#prepare`
|
78
|
+
- [Tim Riley] `Hanami::Slice#register_bootable` => `Hanami::Slice#register_provider`
|
79
|
+
- [Tim Riley] `Hanami::Slice#start_bootable` => `Hanami::Slice#start`
|
80
|
+
|
4
81
|
## v2.0.0.alpha5 - 2022-01-12
|
5
82
|
### Changed
|
6
83
|
- [Luca Guidi] Sensible default configuration for application logger, with per-environment defaults:
|
data/README.md
CHANGED
@@ -36,7 +36,7 @@ These components are designed to be used independently or together in a Hanami a
|
|
36
36
|
|
37
37
|
## Installation
|
38
38
|
|
39
|
-
__Hanami__ supports Ruby (MRI)
|
39
|
+
__Hanami__ supports Ruby (MRI) 3.0+
|
40
40
|
|
41
41
|
```shell
|
42
42
|
gem install hanami
|
@@ -136,8 +136,4 @@ __Hanami__ uses [Semantic Versioning 2.0.0](http://semver.org)
|
|
136
136
|
|
137
137
|
## Copyright
|
138
138
|
|
139
|
-
Released under MIT License.
|
140
|
-
|
141
|
-
This project was formerly known as Lotus (`lotusrb`).
|
142
|
-
|
143
|
-
Copyright © 2014-2021 Luca Guidi.
|
139
|
+
Copyright © 2014-2022 Hanami Team – Released under MIT License.
|
data/hanami.gemspec
CHANGED
@@ -4,7 +4,7 @@ lib = File.expand_path("../lib", __FILE__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require "hanami/version"
|
6
6
|
|
7
|
-
Gem::Specification.new do |spec|
|
7
|
+
Gem::Specification.new do |spec|
|
8
8
|
spec.name = "hanami"
|
9
9
|
spec.version = Hanami::VERSION
|
10
10
|
spec.authors = ["Luca Guidi"]
|
@@ -14,10 +14,11 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
14
14
|
spec.homepage = "http://hanamirb.org"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.files = `git ls-files -c -o --exclude-standard -z -- lib/* bin/* LICENSE.md README.md CODE_OF_CONDUCT.md CHANGELOG.md FEATURES.md hanami.gemspec`.split("\x0")
|
17
|
+
spec.files = `git ls-files -c -o --exclude-standard -z -- lib/* bin/* LICENSE.md README.md CODE_OF_CONDUCT.md CHANGELOG.md FEATURES.md hanami.gemspec`.split("\x0") # rubocop:disable Layout/LineLength
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
|
-
spec.
|
20
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
21
|
+
spec.required_ruby_version = ">= 3.0"
|
21
22
|
|
22
23
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
23
24
|
|
@@ -26,7 +27,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
26
27
|
spec.add_dependency "dry-core", "~> 0.4"
|
27
28
|
spec.add_dependency "dry-inflector", "~> 0.2", ">= 0.2.1"
|
28
29
|
spec.add_dependency "dry-monitor"
|
29
|
-
spec.add_dependency "dry-system", "~> 0.
|
30
|
+
spec.add_dependency "dry-system", "~> 0.23", ">= 0.23.0"
|
30
31
|
spec.add_dependency "hanami-cli", "~> 2.0.alpha"
|
31
32
|
spec.add_dependency "hanami-utils", "~> 2.0.alpha"
|
32
33
|
spec.add_dependency "zeitwerk", "~> 2.4"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Hanami.application.register_provider :rack_logger do
|
4
|
+
start do
|
5
|
+
require "hanami/web/rack_logger"
|
6
|
+
|
7
|
+
target.start :logger
|
8
|
+
target.start :rack_monitor
|
9
|
+
|
10
|
+
rack_logger = Hanami::Web::RackLogger.new(target[:logger])
|
11
|
+
rack_logger.attach target[:rack_monitor]
|
12
|
+
|
13
|
+
register :rack_logger, rack_logger
|
14
|
+
end
|
15
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
Hanami.application.
|
3
|
+
Hanami.application.register_provider :rack_monitor do
|
4
4
|
start do
|
5
5
|
require "dry/monitor"
|
6
6
|
require "dry/monitor/rack/middleware"
|
7
7
|
|
8
|
-
middleware = Dry::Monitor::Rack::Middleware.new(
|
8
|
+
middleware = Dry::Monitor::Rack::Middleware.new(target[:notifications])
|
9
9
|
|
10
10
|
register :rack_monitor, middleware
|
11
11
|
end
|
data/lib/hanami/application.rb
CHANGED
@@ -7,7 +7,6 @@ require "pathname"
|
|
7
7
|
require "rack"
|
8
8
|
require "zeitwerk"
|
9
9
|
require_relative "slice"
|
10
|
-
require_relative "application/autoloader/inflector_adapter"
|
11
10
|
|
12
11
|
module Hanami
|
13
12
|
# Hanami application class
|
@@ -18,6 +17,7 @@ module Hanami
|
|
18
17
|
|
19
18
|
class << self
|
20
19
|
def inherited(klass)
|
20
|
+
super
|
21
21
|
@_mutex.synchronize do
|
22
22
|
klass.class_eval do
|
23
23
|
@_mutex = Mutex.new
|
@@ -39,7 +39,7 @@ module Hanami
|
|
39
39
|
module ClassMethods
|
40
40
|
def self.extended(klass)
|
41
41
|
klass.class_eval do
|
42
|
-
@
|
42
|
+
@prepared = @booted = false
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -47,35 +47,38 @@ module Hanami
|
|
47
47
|
@_configuration
|
48
48
|
end
|
49
49
|
|
50
|
-
|
50
|
+
alias_method :config, :configuration
|
51
51
|
|
52
|
-
def
|
53
|
-
|
52
|
+
def prepare(provider_name = nil)
|
53
|
+
if provider_name
|
54
|
+
container.prepare(provider_name)
|
55
|
+
return self
|
56
|
+
end
|
54
57
|
|
55
|
-
|
58
|
+
return self if prepared?
|
56
59
|
|
57
|
-
|
58
|
-
autoloader.inflector = Autoloader::InflectorAdapter.new(inflector)
|
60
|
+
configuration.finalize!
|
59
61
|
|
60
62
|
load_settings
|
61
63
|
|
64
|
+
@autoloader = Zeitwerk::Loader.new
|
62
65
|
@container = prepare_container
|
63
66
|
@deps_module = prepare_deps_module
|
64
67
|
|
65
68
|
load_slices
|
66
|
-
slices.
|
69
|
+
slices.each_value(&:prepare)
|
67
70
|
slices.freeze
|
68
71
|
|
69
|
-
autoloader.setup
|
72
|
+
@autoloader.setup
|
70
73
|
|
71
|
-
@
|
74
|
+
@prepared = true
|
72
75
|
self
|
73
76
|
end
|
74
77
|
|
75
78
|
def boot(&block)
|
76
79
|
return self if booted?
|
77
80
|
|
78
|
-
|
81
|
+
prepare
|
79
82
|
|
80
83
|
container.finalize!(&block)
|
81
84
|
|
@@ -89,8 +92,8 @@ module Hanami
|
|
89
92
|
container.shutdown!
|
90
93
|
end
|
91
94
|
|
92
|
-
def
|
93
|
-
@
|
95
|
+
def prepared?
|
96
|
+
@prepared
|
94
97
|
end
|
95
98
|
|
96
99
|
def booted?
|
@@ -98,25 +101,25 @@ module Hanami
|
|
98
101
|
end
|
99
102
|
|
100
103
|
def autoloader
|
101
|
-
raise "Application not
|
104
|
+
raise "Application not yet prepared" unless defined?(@autoloader)
|
102
105
|
|
103
106
|
@autoloader
|
104
107
|
end
|
105
108
|
|
106
109
|
def container
|
107
|
-
raise "Application not
|
110
|
+
raise "Application not yet prepared" unless defined?(@container)
|
108
111
|
|
109
112
|
@container
|
110
113
|
end
|
111
114
|
|
112
115
|
def deps
|
113
|
-
raise "Application not
|
116
|
+
raise "Application not yet prepared" unless defined?(@deps_module)
|
114
117
|
|
115
118
|
@deps_module
|
116
119
|
end
|
117
120
|
|
118
121
|
def router
|
119
|
-
raise "Application not
|
122
|
+
raise "Application not yet prepared" unless prepared?
|
120
123
|
|
121
124
|
@_mutex.synchronize do
|
122
125
|
@_router ||= load_router
|
@@ -139,36 +142,32 @@ module Hanami
|
|
139
142
|
slices[name.to_sym] = slice
|
140
143
|
end
|
141
144
|
|
142
|
-
def register(
|
143
|
-
container.register(
|
144
|
-
end
|
145
|
-
|
146
|
-
def register_bootable(*args, **opts, &block)
|
147
|
-
container.boot(*args, **opts, &block)
|
145
|
+
def register(...)
|
146
|
+
container.register(...)
|
148
147
|
end
|
149
148
|
|
150
|
-
def
|
151
|
-
container.
|
149
|
+
def register_provider(...)
|
150
|
+
container.register_provider(...)
|
152
151
|
end
|
153
152
|
|
154
|
-
def
|
155
|
-
container.start(
|
153
|
+
def start(...)
|
154
|
+
container.start(...)
|
156
155
|
end
|
157
156
|
|
158
|
-
def key?(
|
159
|
-
container.key?(
|
157
|
+
def key?(...)
|
158
|
+
container.key?(...)
|
160
159
|
end
|
161
160
|
|
162
161
|
def keys
|
163
162
|
container.keys
|
164
163
|
end
|
165
164
|
|
166
|
-
def [](
|
167
|
-
container[
|
165
|
+
def [](...)
|
166
|
+
container.[](...)
|
168
167
|
end
|
169
168
|
|
170
|
-
def resolve(
|
171
|
-
container.resolve(
|
169
|
+
def resolve(...)
|
170
|
+
container.resolve(...)
|
172
171
|
end
|
173
172
|
|
174
173
|
def settings
|
@@ -201,7 +200,7 @@ module Hanami
|
|
201
200
|
|
202
201
|
# @api private
|
203
202
|
def component_provider(component)
|
204
|
-
raise "Hanami.application must be
|
203
|
+
raise "Hanami.application must be prepared before detecting providers" unless prepared?
|
205
204
|
|
206
205
|
# [Admin, Main, MyApp] or [MyApp::Admin, MyApp::Main, MyApp]
|
207
206
|
providers = slices.values + [self]
|
@@ -221,53 +220,46 @@ module Hanami
|
|
221
220
|
$LOAD_PATH.unshift base_path unless $LOAD_PATH.include?(base_path)
|
222
221
|
end
|
223
222
|
|
223
|
+
# rubocop:disable Metrics/AbcSize
|
224
224
|
def prepare_container
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
end
|
233
|
-
|
234
|
-
def define_container
|
235
|
-
require "#{application_name}/container"
|
236
|
-
namespace.const_get :Container
|
237
|
-
rescue LoadError, NameError
|
238
|
-
namespace.const_set :Container, Class.new(Dry::System::Container)
|
239
|
-
end
|
225
|
+
container =
|
226
|
+
begin
|
227
|
+
require "#{application_name}/container"
|
228
|
+
namespace.const_get :Container
|
229
|
+
rescue LoadError, NameError
|
230
|
+
namespace.const_set :Container, Class.new(Dry::System::Container)
|
231
|
+
end
|
240
232
|
|
241
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
242
|
-
def configure_container(container)
|
243
233
|
container.use :env, inferrer: -> { Hanami.env }
|
234
|
+
container.use :zeitwerk, loader: autoloader, run_setup: false, eager_load: false
|
244
235
|
container.use :notifications
|
245
236
|
|
246
|
-
container.
|
247
|
-
|
248
|
-
|
249
|
-
config.root = configuration.root
|
250
|
-
config.bootable_dirs = [
|
251
|
-
"config/boot",
|
252
|
-
Pathname(__dir__).join("application/container/boot").realpath,
|
253
|
-
]
|
237
|
+
container.config.root = configuration.root
|
238
|
+
container.config.inflector = configuration.inflector
|
254
239
|
|
255
|
-
|
256
|
-
config
|
257
|
-
|
240
|
+
container.config.provider_dirs = [
|
241
|
+
"config/providers",
|
242
|
+
Pathname(__dir__).join("application/container/providers").realpath,
|
243
|
+
]
|
258
244
|
|
259
245
|
# Autoload classes defined in lib/[app_namespace]/
|
260
246
|
if root.join("lib", namespace_path).directory?
|
261
|
-
autoloader.push_dir(root.join("lib", namespace_path), namespace: namespace)
|
247
|
+
container.autoloader.push_dir(root.join("lib", namespace_path), namespace: namespace)
|
262
248
|
end
|
263
249
|
|
264
|
-
# Add lib/ to to the $LOAD_PATH so
|
265
|
-
#
|
250
|
+
# Add lib/ to to the $LOAD_PATH so any files there (outside the app namespace) can
|
251
|
+
# be required
|
266
252
|
container.add_to_load_path!("lib") if root.join("lib").directory?
|
267
253
|
|
254
|
+
container.configured!
|
255
|
+
|
268
256
|
container
|
269
257
|
end
|
270
|
-
# rubocop:enable Metrics/AbcSize
|
258
|
+
# rubocop:enable Metrics/AbcSize
|
259
|
+
|
260
|
+
def prepare_deps_module
|
261
|
+
define_deps_module
|
262
|
+
end
|
271
263
|
|
272
264
|
def define_deps_module
|
273
265
|
require "#{application_name}/deps"
|
@@ -286,7 +278,6 @@ module Hanami
|
|
286
278
|
File.join(root, config.slices_dir)
|
287
279
|
end
|
288
280
|
|
289
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
290
281
|
def load_slice(slice_path)
|
291
282
|
slice_path = Pathname(slice_path)
|
292
283
|
|
@@ -308,7 +299,6 @@ module Hanami
|
|
308
299
|
root: slice_path.realpath
|
309
300
|
)
|
310
301
|
end
|
311
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
312
302
|
|
313
303
|
def load_settings
|
314
304
|
require_relative "application/settings"
|
@@ -26,7 +26,7 @@ module Hanami
|
|
26
26
|
# of the boot process respect the provided env
|
27
27
|
ENV["HANAMI_ENV"] = arguments[:env] if arguments[:env]
|
28
28
|
|
29
|
-
require "hanami/
|
29
|
+
require "hanami/prepare"
|
30
30
|
application = Hanami.application
|
31
31
|
|
32
32
|
[command.with_application(application), arguments]
|
data/lib/hanami/configuration.rb
CHANGED
@@ -126,7 +126,7 @@ module Hanami
|
|
126
126
|
|
127
127
|
setting :root, constructor: -> path { Pathname(path) }
|
128
128
|
|
129
|
-
setting :inflector, default: Dry::Inflector.new
|
129
|
+
setting :inflector, default: Dry::Inflector.new
|
130
130
|
|
131
131
|
def inflections(&block)
|
132
132
|
self.inflector = Dry::Inflector.new(&block)
|
data/lib/hanami/slice.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "dry/system/container"
|
4
|
-
require "dry/system/loader/autoloading"
|
5
4
|
require "pathname"
|
6
5
|
|
7
6
|
module Hanami
|
@@ -16,7 +15,7 @@ module Hanami
|
|
16
15
|
@name = name.to_sym
|
17
16
|
@namespace = namespace
|
18
17
|
@root = root ? Pathname(root) : root
|
19
|
-
@container = container
|
18
|
+
@container = container
|
20
19
|
end
|
21
20
|
|
22
21
|
def inflector
|
@@ -27,17 +26,28 @@ module Hanami
|
|
27
26
|
@namespace_path ||= inflector.underscore(namespace.to_s)
|
28
27
|
end
|
29
28
|
|
30
|
-
def
|
31
|
-
|
29
|
+
def prepare(provider_name = nil)
|
30
|
+
if provider_name
|
31
|
+
container.prepare(provider_name)
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
|
35
|
+
@container ||= define_container
|
36
|
+
|
37
|
+
container.import from: application.container, as: :application
|
32
38
|
|
33
39
|
slice_block = application.configuration.slices[name]
|
34
40
|
instance_eval(&slice_block) if slice_block
|
41
|
+
|
42
|
+
# This is here and not inside define_container to allow for the slice block to
|
43
|
+
# interact with container config
|
44
|
+
container.configured!
|
45
|
+
|
46
|
+
self
|
35
47
|
end
|
36
48
|
|
37
49
|
def boot
|
38
|
-
container.finalize!
|
39
|
-
container.config.env = application.container.config.env
|
40
|
-
end
|
50
|
+
container.finalize!
|
41
51
|
|
42
52
|
@booted = true
|
43
53
|
self
|
@@ -53,44 +63,47 @@ module Hanami
|
|
53
63
|
@container ||= define_container
|
54
64
|
end
|
55
65
|
|
56
|
-
def import(
|
66
|
+
def import(from:, **kwargs)
|
67
|
+
# TODO: This should be handled via dry-system (see dry-rb/dry-system#228)
|
57
68
|
raise "Cannot import after booting" if booted?
|
58
69
|
|
59
|
-
|
60
|
-
|
70
|
+
if from.is_a?(Symbol) || from.is_a?(String)
|
71
|
+
slice_name = from
|
72
|
+
# TODO: better error than the KeyError from fetch if the slice doesn't exist
|
73
|
+
from = application.slices.fetch(from.to_sym).container
|
61
74
|
end
|
75
|
+
|
76
|
+
as = kwargs[:as] || slice_name
|
77
|
+
|
78
|
+
container.import(from: from, as: as, **kwargs)
|
62
79
|
end
|
63
80
|
|
64
81
|
def register(*args, &block)
|
65
82
|
container.register(*args, &block)
|
66
83
|
end
|
67
84
|
|
68
|
-
def
|
69
|
-
container.
|
70
|
-
end
|
71
|
-
|
72
|
-
def init_bootable(*args)
|
73
|
-
container.init(*args)
|
85
|
+
def register_provider(...)
|
86
|
+
container.register_provider(...)
|
74
87
|
end
|
75
88
|
|
76
|
-
def
|
77
|
-
container.start(
|
89
|
+
def start(...)
|
90
|
+
container.start(...)
|
78
91
|
end
|
79
92
|
|
80
|
-
def key?(
|
81
|
-
container.key?(
|
93
|
+
def key?(...)
|
94
|
+
container.key?(...)
|
82
95
|
end
|
83
96
|
|
84
97
|
def keys
|
85
98
|
container.keys
|
86
99
|
end
|
87
100
|
|
88
|
-
def [](
|
89
|
-
container[
|
101
|
+
def [](...)
|
102
|
+
container.[](...)
|
90
103
|
end
|
91
104
|
|
92
|
-
def resolve(
|
93
|
-
container.resolve(
|
105
|
+
def resolve(...)
|
106
|
+
container.resolve(...)
|
94
107
|
end
|
95
108
|
|
96
109
|
private
|
@@ -98,82 +111,72 @@ module Hanami
|
|
98
111
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
99
112
|
def define_container
|
100
113
|
container = Class.new(Dry::System::Container)
|
101
|
-
container.use :env
|
102
114
|
|
103
|
-
container.
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
component_dir.namespaces.delete_root
|
149
|
-
component_dir.namespaces.add_root(const: dir_namespace_path, key: component_dir.path) # TODO: do we need to swap path delimiters for key delimiters here?
|
150
|
-
|
151
|
-
config.component_dirs.add(component_dir)
|
152
|
-
|
153
|
-
application.autoloader.push_dir(
|
154
|
-
container.root.join(component_dir.path),
|
155
|
-
namespace: autoloader_namespace
|
156
|
-
)
|
157
|
-
end
|
115
|
+
container.use :env
|
116
|
+
container.use :zeitwerk,
|
117
|
+
loader: application.autoloader,
|
118
|
+
run_setup: false,
|
119
|
+
eager_load: false
|
120
|
+
|
121
|
+
container.config.name = name
|
122
|
+
container.config.env = application.configuration.env
|
123
|
+
container.config.inflector = application.configuration.inflector
|
124
|
+
|
125
|
+
if root&.directory?
|
126
|
+
container.config.root = root
|
127
|
+
container.config.provider_dirs = ["config/providers"]
|
128
|
+
|
129
|
+
# Add component dirs for each configured component path
|
130
|
+
application.configuration.source_dirs.component_dirs.each do |component_dir|
|
131
|
+
next unless root.join(component_dir.path).directory?
|
132
|
+
|
133
|
+
component_dir = component_dir.dup
|
134
|
+
|
135
|
+
# TODO: this `== "lib"` check should be codified into a method somewhere
|
136
|
+
if component_dir.path == "lib"
|
137
|
+
# Expect component files in the root of the lib/ component dir to define
|
138
|
+
# classes inside the slice's namespace.
|
139
|
+
#
|
140
|
+
# e.g. "lib/foo.rb" should define SliceNamespace::Foo, to be registered as
|
141
|
+
# "foo"
|
142
|
+
component_dir.namespaces.delete_root
|
143
|
+
component_dir.namespaces.add_root(key: nil, const: namespace_path)
|
144
|
+
|
145
|
+
container.config.component_dirs.add(component_dir)
|
146
|
+
else
|
147
|
+
# Expect component files in the root of non-lib/ component dirs to define
|
148
|
+
# classes inside a namespace matching that dir.
|
149
|
+
#
|
150
|
+
# e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, to be
|
151
|
+
# registered as "actions.foo"
|
152
|
+
|
153
|
+
dir_namespace_path = File.join(namespace_path, component_dir.path)
|
154
|
+
|
155
|
+
component_dir.namespaces.delete_root
|
156
|
+
component_dir.namespaces.add_root(const: dir_namespace_path, key: component_dir.path)
|
157
|
+
|
158
|
+
container.config.component_dirs.add(component_dir)
|
158
159
|
end
|
160
|
+
end
|
161
|
+
end
|
159
162
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
dir_namespace_path = File.join(namespace_path, autoload_path)
|
163
|
+
if root&.directory?
|
164
|
+
# Pass configured autoload dirs to the autoloader
|
165
|
+
application.configuration.source_dirs.autoload_paths.each do |autoload_path|
|
166
|
+
next unless root.join(autoload_path).directory?
|
165
167
|
|
166
|
-
|
167
|
-
inflector.constantize(inflector.camelize(dir_namespace_path))
|
168
|
-
rescue NameError
|
169
|
-
namespace.const_set(inflector.camelize(autoload_path), Module.new)
|
170
|
-
end
|
168
|
+
dir_namespace_path = File.join(namespace_path, autoload_path)
|
171
169
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
)
|
170
|
+
autoloader_namespace = begin
|
171
|
+
inflector.constantize(inflector.camelize(dir_namespace_path))
|
172
|
+
rescue NameError
|
173
|
+
namespace.const_set(inflector.camelize(autoload_path), Module.new)
|
176
174
|
end
|
175
|
+
|
176
|
+
container.config.autoloader.push_dir(
|
177
|
+
container.root.join(autoload_path),
|
178
|
+
namespace: autoloader_namespace
|
179
|
+
)
|
177
180
|
end
|
178
181
|
end
|
179
182
|
|
data/lib/hanami/version.rb
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "json"
|
4
|
-
require "rack/request"
|
5
|
-
require "hanami/utils/hash"
|
6
|
-
|
7
3
|
module Hanami
|
8
4
|
module Web
|
9
5
|
# Rack logger for Hanami applications
|
10
6
|
class RackLogger
|
11
|
-
|
12
|
-
|
7
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
8
|
+
private_constant :REQUEST_METHOD
|
9
|
+
|
10
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
11
|
+
private_constant :HTTP_X_FORWARDED_FOR
|
12
|
+
|
13
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
14
|
+
private_constant :REMOTE_ADDR
|
15
|
+
|
16
|
+
SCRIPT_NAME = "SCRIPT_NAME"
|
17
|
+
private_constant :SCRIPT_NAME
|
18
|
+
|
19
|
+
PATH_INFO = "PATH_INFO"
|
20
|
+
private_constant :PATH_INFO
|
21
|
+
|
22
|
+
ROUTER_PARAMS = "router.params"
|
23
|
+
private_constant :ROUTER_PARAMS
|
24
|
+
|
25
|
+
CONTENT_LENGTH = "Content-Length"
|
26
|
+
private_constant :CONTENT_LENGTH
|
13
27
|
|
14
|
-
def initialize(logger
|
28
|
+
def initialize(logger)
|
15
29
|
@logger = logger
|
16
|
-
@filter_params = filter_params
|
17
30
|
end
|
18
31
|
|
19
32
|
def attach(rack_monitor)
|
@@ -26,22 +39,20 @@ module Hanami
|
|
26
39
|
end
|
27
40
|
end
|
28
41
|
|
29
|
-
|
30
|
-
def log_request(env, status, time)
|
42
|
+
def log_request(env, status, elapsed)
|
31
43
|
data = {
|
32
|
-
http: env[HTTP_VERSION],
|
33
44
|
verb: env[REQUEST_METHOD],
|
34
45
|
status: status,
|
46
|
+
elapsed: "#{elapsed}ms",
|
35
47
|
ip: env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR],
|
36
48
|
path: env[SCRIPT_NAME] + env[PATH_INFO].to_s,
|
37
49
|
length: extract_content_length(env),
|
38
|
-
params:
|
39
|
-
|
50
|
+
params: env[ROUTER_PARAMS],
|
51
|
+
time: Time.now,
|
40
52
|
}
|
41
53
|
|
42
|
-
logger.info
|
54
|
+
logger.info(data)
|
43
55
|
end
|
44
|
-
# rubocop:enable Metrics/MethodLength
|
45
56
|
|
46
57
|
def log_exception(exception)
|
47
58
|
logger.error exception.message
|
@@ -50,47 +61,12 @@ module Hanami
|
|
50
61
|
|
51
62
|
private
|
52
63
|
|
53
|
-
|
54
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
55
|
-
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
56
|
-
REMOTE_ADDR = "REMOTE_ADDR"
|
57
|
-
SCRIPT_NAME = "SCRIPT_NAME"
|
58
|
-
PATH_INFO = "PATH_INFO"
|
59
|
-
RACK_ERRORS = "rack.errors"
|
60
|
-
QUERY_HASH = "rack.request.query_hash"
|
61
|
-
FORM_HASH = "rack.request.form_hash"
|
62
|
-
ROUTER_PARAMS = "router.params"
|
63
|
-
CONTENT_LENGTH = "Content-Length"
|
64
|
+
attr_reader :logger
|
64
65
|
|
65
66
|
def extract_content_length(env)
|
66
67
|
value = env[CONTENT_LENGTH]
|
67
68
|
!value || value.to_s == "0" ? "-" : value
|
68
69
|
end
|
69
|
-
|
70
|
-
def extract_params(env)
|
71
|
-
result = env.fetch(QUERY_HASH, {})
|
72
|
-
result.merge!(env.fetch(FORM_HASH, {}))
|
73
|
-
result.merge!(Hanami::Utils::Hash.deep_stringify(env.fetch(ROUTER_PARAMS, {})))
|
74
|
-
result
|
75
|
-
end
|
76
|
-
|
77
|
-
FILTERED = "[FILTERED]"
|
78
|
-
|
79
|
-
# rubocop:disable Metrics/MethodLength
|
80
|
-
def filter(params)
|
81
|
-
params.each_with_object({}) do |(k, v), h|
|
82
|
-
if filter_params.include?(k)
|
83
|
-
h.update(k => FILTERED)
|
84
|
-
elsif v.is_a?(Hash)
|
85
|
-
h.update(k => filter(v))
|
86
|
-
elsif v.is_a?(Array)
|
87
|
-
h.update(k => v.map { |m| m.is_a?(Hash) ? filter(m) : m })
|
88
|
-
else
|
89
|
-
h[k] = v
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
# rubocop:enable Metrics/MethodLength
|
94
70
|
end
|
95
71
|
end
|
96
72
|
end
|
data/lib/hanami.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hanami
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.alpha6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -104,20 +104,20 @@ dependencies:
|
|
104
104
|
requirements:
|
105
105
|
- - "~>"
|
106
106
|
- !ruby/object:Gem::Version
|
107
|
-
version: '0.
|
107
|
+
version: '0.23'
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.23.0
|
111
111
|
type: :runtime
|
112
112
|
prerelease: false
|
113
113
|
version_requirements: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0.
|
117
|
+
version: '0.23'
|
118
118
|
- - ">="
|
119
119
|
- !ruby/object:Gem::Version
|
120
|
-
version: 0.
|
120
|
+
version: 0.23.0
|
121
121
|
- !ruby/object:Gem::Dependency
|
122
122
|
name: hanami-cli
|
123
123
|
requirement: !ruby/object:Gem::Requirement
|
@@ -217,13 +217,12 @@ files:
|
|
217
217
|
- hanami.gemspec
|
218
218
|
- lib/hanami.rb
|
219
219
|
- lib/hanami/application.rb
|
220
|
-
- lib/hanami/application/
|
221
|
-
- lib/hanami/application/container/
|
222
|
-
- lib/hanami/application/container/
|
223
|
-
- lib/hanami/application/container/
|
224
|
-
- lib/hanami/application/container/
|
225
|
-
- lib/hanami/application/container/
|
226
|
-
- lib/hanami/application/container/boot/settings.rb
|
220
|
+
- lib/hanami/application/container/providers/inflector.rb
|
221
|
+
- lib/hanami/application/container/providers/logger.rb
|
222
|
+
- lib/hanami/application/container/providers/rack_logger.rb
|
223
|
+
- lib/hanami/application/container/providers/rack_monitor.rb
|
224
|
+
- lib/hanami/application/container/providers/routes_helper.rb
|
225
|
+
- lib/hanami/application/container/providers/settings.rb
|
227
226
|
- lib/hanami/application/router.rb
|
228
227
|
- lib/hanami/application/routes.rb
|
229
228
|
- lib/hanami/application/routes_helper.rb
|
@@ -231,13 +230,11 @@ files:
|
|
231
230
|
- lib/hanami/application/routing/resolver.rb
|
232
231
|
- lib/hanami/application/routing/resolver/node.rb
|
233
232
|
- lib/hanami/application/routing/resolver/trie.rb
|
234
|
-
- lib/hanami/application/routing/router.rb
|
235
233
|
- lib/hanami/application/settings.rb
|
236
234
|
- lib/hanami/application/settings/dotenv_store.rb
|
237
235
|
- lib/hanami/assets/application_configuration.rb
|
238
236
|
- lib/hanami/assets/configuration.rb
|
239
237
|
- lib/hanami/boot.rb
|
240
|
-
- lib/hanami/boot/source_dirs.rb
|
241
238
|
- lib/hanami/cli/application/cli.rb
|
242
239
|
- lib/hanami/cli/application/command.rb
|
243
240
|
- lib/hanami/cli/application/commands.rb
|
@@ -253,7 +250,7 @@ files:
|
|
253
250
|
- lib/hanami/configuration/router.rb
|
254
251
|
- lib/hanami/configuration/sessions.rb
|
255
252
|
- lib/hanami/configuration/source_dirs.rb
|
256
|
-
- lib/hanami/
|
253
|
+
- lib/hanami/prepare.rb
|
257
254
|
- lib/hanami/server.rb
|
258
255
|
- lib/hanami/setup.rb
|
259
256
|
- lib/hanami/slice.rb
|
@@ -263,6 +260,7 @@ homepage: http://hanamirb.org
|
|
263
260
|
licenses:
|
264
261
|
- MIT
|
265
262
|
metadata:
|
263
|
+
rubygems_mfa_required: 'true'
|
266
264
|
allowed_push_host: https://rubygems.org
|
267
265
|
post_install_message:
|
268
266
|
rdoc_options: []
|
@@ -272,14 +270,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
272
270
|
requirements:
|
273
271
|
- - ">="
|
274
272
|
- !ruby/object:Gem::Version
|
275
|
-
version:
|
273
|
+
version: '3.0'
|
276
274
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
277
275
|
requirements:
|
278
276
|
- - ">"
|
279
277
|
- !ruby/object:Gem::Version
|
280
278
|
version: 1.3.1
|
281
279
|
requirements: []
|
282
|
-
rubygems_version: 3.
|
280
|
+
rubygems_version: 3.3.3
|
283
281
|
signing_key:
|
284
282
|
specification_version: 4
|
285
283
|
summary: The web, with simplicity
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Hanami
|
2
|
-
class Application
|
3
|
-
module Autoloader
|
4
|
-
# Allows the Hanami standard inflector (from dry-inflector) to be used with Zeitwerk
|
5
|
-
class InflectorAdapter
|
6
|
-
def initialize(inflector)
|
7
|
-
@inflector = inflector
|
8
|
-
end
|
9
|
-
|
10
|
-
def camelize(basename, _abspath)
|
11
|
-
# Discard unused `_abspath` argument before calling our own inflector's
|
12
|
-
# `#camelize` (which takes only one argument)
|
13
|
-
inflector.camelize(basename)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
attr_reader :inflector
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
Hanami.application.register_bootable :rack_logger do |container|
|
4
|
-
start do
|
5
|
-
require "hanami/web/rack_logger"
|
6
|
-
|
7
|
-
use :logger
|
8
|
-
use :rack_monitor
|
9
|
-
|
10
|
-
rack_logger = Hanami::Web::RackLogger.new(
|
11
|
-
container[:logger],
|
12
|
-
filter_params: Hanami.application.configuration.logger.filters
|
13
|
-
)
|
14
|
-
|
15
|
-
rack_logger.attach container[:rack_monitor]
|
16
|
-
|
17
|
-
register :rack_logger, rack_logger
|
18
|
-
end
|
19
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# # frozen_string_literal: true
|
2
|
-
|
3
|
-
# require "hanami/application/router"
|
4
|
-
|
5
|
-
# Hanami.application.register_bootable :router do
|
6
|
-
# start do
|
7
|
-
# configuration = Hanami.application.configuration
|
8
|
-
|
9
|
-
# routes = begin
|
10
|
-
# require File.join(configuration.root, configuration.router.routes_path)
|
11
|
-
# routes_class = Hanami.application.send(:autodiscover_application_constant, configuration.router.routes_class_name) # WIP private
|
12
|
-
# routes_class.routes
|
13
|
-
# rescue LoadError
|
14
|
-
# proc {}
|
15
|
-
# end
|
16
|
-
|
17
|
-
# resolver = configuration.router.resolver.new(
|
18
|
-
# slices: Hanami.application.slices,
|
19
|
-
# inflector: Hanami.application.inflector # TODO: use container[:inflector]?
|
20
|
-
# )
|
21
|
-
|
22
|
-
# router = Hanami::Application::Router.new(
|
23
|
-
# routes: routes,
|
24
|
-
# resolver: resolver,
|
25
|
-
# **configuration.router.options,
|
26
|
-
# ) do
|
27
|
-
# use Hanami.application[:rack_monitor]
|
28
|
-
|
29
|
-
# Hanami.application.config.for_each_middleware do |m, *args, &block|
|
30
|
-
# use(m, *args, &block)
|
31
|
-
# end
|
32
|
-
# end
|
33
|
-
|
34
|
-
# register :router, router
|
35
|
-
# end
|
36
|
-
# end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Hanami
|
2
|
-
module Boot
|
3
|
-
module SourceDirs
|
4
|
-
def self.setup_component_dir!(component_dir, slice, container)
|
5
|
-
# TODO: this `== "lib"` check should be codified into a method somewhere
|
6
|
-
if component_dir.path == "lib"
|
7
|
-
# Expect component files in the root of the lib
|
8
|
-
# component dir to define classes inside the slice's namespace.
|
9
|
-
#
|
10
|
-
# e.g. "lib/foo.rb" should define SliceNamespace::Foo, and will be
|
11
|
-
# registered as "foo"
|
12
|
-
component_dir.namespaces.root(key: nil, const: slice.namespace_path)
|
13
|
-
|
14
|
-
slice.application.autoloader.push_dir(slice.root.join("lib"), namespace: slice.namespace)
|
15
|
-
|
16
|
-
container.config.component_dirs.add(component_dir)
|
17
|
-
else
|
18
|
-
# Expect component files in the root of these component dirs to define
|
19
|
-
# classes inside a namespace matching the dir.
|
20
|
-
#
|
21
|
-
# e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, and
|
22
|
-
# will be registered as "actions.foo"
|
23
|
-
|
24
|
-
dir_namespace_path = File.join(slice.namespace_path, component_dir.path)
|
25
|
-
|
26
|
-
autoloader_namespace = begin
|
27
|
-
slice.inflector.constantize(slice.inflector.camelize(dir_namespace_path))
|
28
|
-
rescue NameError
|
29
|
-
slice.namespace.const_set(slice.inflector.camelize(component_dir.path), Module.new)
|
30
|
-
end
|
31
|
-
|
32
|
-
# TODO: do we need to do something special to clear out any previously configured root namespace here?
|
33
|
-
component_dir.namespaces.root(const: dir_namespace_path, key: component_dir.path) # TODO: do we need to swap path delimiters for key delimiters here?
|
34
|
-
container.config.component_dirs.add(component_dir)
|
35
|
-
|
36
|
-
slice.application.autoloader.push_dir(
|
37
|
-
slice.root.join(component_dir.path),
|
38
|
-
namespace: autoloader_namespace
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|