hanami 2.0.0.alpha1 → 2.0.0.alpha2
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 +70 -5
- data/FEATURES.md +9 -1
- data/LICENSE.md +1 -1
- data/README.md +4 -5
- data/hanami.gemspec +11 -11
- data/lib/hanami.rb +19 -18
- data/lib/hanami/application.rb +322 -26
- data/lib/hanami/application/autoloader/inflector_adapter.rb +22 -0
- data/lib/hanami/application/container/boot/inflector.rb +7 -0
- data/lib/hanami/application/container/boot/logger.rb +8 -0
- data/lib/hanami/application/container/boot/rack_logger.rb +19 -0
- data/lib/hanami/application/container/boot/rack_monitor.rb +12 -0
- data/lib/hanami/application/container/boot/settings.rb +7 -0
- data/lib/hanami/application/router.rb +59 -0
- data/lib/hanami/application/routing/middleware/stack.rb +89 -0
- data/lib/hanami/application/routing/resolver.rb +82 -0
- data/lib/hanami/application/routing/resolver/node.rb +50 -0
- data/lib/hanami/application/routing/resolver/trie.rb +59 -0
- data/lib/hanami/application/settings.rb +23 -0
- data/lib/hanami/application/settings/definition.rb +26 -0
- data/lib/hanami/application/settings/loader.rb +97 -0
- data/lib/hanami/application/settings/struct.rb +65 -0
- data/lib/hanami/boot.rb +1 -2
- data/lib/hanami/cli/application/cli.rb +40 -0
- data/lib/hanami/cli/application/command.rb +47 -0
- data/lib/hanami/cli/application/commands.rb +16 -0
- data/lib/hanami/cli/application/commands/console.rb +81 -0
- data/lib/hanami/cli/base_command.rb +48 -0
- data/lib/hanami/cli/commands.rb +3 -2
- data/lib/hanami/cli/commands/command.rb +4 -4
- data/lib/hanami/configuration.rb +129 -64
- data/lib/hanami/configuration/middleware.rb +2 -2
- data/lib/hanami/configuration/router.rb +50 -0
- data/lib/hanami/init.rb +5 -0
- data/lib/hanami/setup.rb +9 -0
- data/lib/hanami/slice.rb +138 -0
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +96 -0
- metadata +92 -54
- data/bin/hanami +0 -8
- data/lib/hanami/configuration/cookies.rb +0 -24
- data/lib/hanami/configuration/security.rb +0 -141
- data/lib/hanami/container.rb +0 -107
- data/lib/hanami/frameworks.rb +0 -28
- data/lib/hanami/routes.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee3c6a367cfd05f2b18ae080da80b75a08a8680bd922ac8b00433e0c59f53f2b
|
4
|
+
data.tar.gz: 2de0d4102bf80606d130c04d83716370fe2c1c985986cd034ce232ff08e9be61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7d143ccf35f088d91fa1702d40b5aac22b3cada72cf566b239403d97fdd22b0839f93a1c20286853ae440ea4898902605b0bfbd3b05854f149de98ef9a78a83
|
7
|
+
data.tar.gz: 8f512b014ed54456df5beb0d3ecccbe260f0186d3ebfba7fb2fc51f9d80956b511ab87e08e1149dd2dd02d94939a1b260059f2cfcaa1ee34ca6681aee1408434
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,40 @@
|
|
1
1
|
# Hanami
|
2
2
|
The web, with simplicity.
|
3
3
|
|
4
|
+
## v2.0.0.alpha2 - 2021-05-04
|
5
|
+
### Added
|
6
|
+
- [Luca Guidi] Official support for Ruby: MRI 3.0
|
7
|
+
- [Tim Riley] Code autoloading via Zeitwerk
|
8
|
+
- [Tim Riley] `Hanami::Application` subclasses generate and configure a `Dry::System::Container`, accessible via `.container` and `AppNamespace::Container`, with several common container methods available directly via the application subclass (e.g. `Bookshelf::Application["foo"]` or `Hanami.application["foo"]`)
|
9
|
+
- [Tim Riley] Introduced `Hanami::Application.register_bootable` to register custom components
|
10
|
+
- [Tim Riley] Introduced `Hanami::Application.keys` to get the list of resolved components
|
11
|
+
- [Tim Riley] Dynamically create an auto-injection mixin (e.g. `Bookshelf::Deps`)
|
12
|
+
```ruby
|
13
|
+
# frozen_string_literal: true
|
14
|
+
|
15
|
+
module Bookshelf
|
16
|
+
class CreateThing
|
17
|
+
include Deps[service_client: "some_service.client"]
|
18
|
+
|
19
|
+
def call(attrs)
|
20
|
+
# Validate attrs, etc.
|
21
|
+
service_client.create(attrs)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
```
|
26
|
+
- [Tim Riley] Introduced application settings. They are accessible via `Hanami.application.settings` in `config/settings.rb`
|
27
|
+
- [Tim Riley] Introduced application slices to organise high-level application concerns. Slices are generated based on subdirectories of `slices/`, and map onto corresponding ruby module namespaces, e.g. `slices/main` -> `Main`, with the slice instance itself being `Main::Slice` (as well as being accessible via `Hanami.application.slices[:main]`)
|
28
|
+
- [Tim Riley] Each slice generates and configures has its own `Dry::System::Container`, accessible via the slice instance (e.g. `Main::Slice.container`) as well as via its own constant (e.g. `Main::Container`)
|
29
|
+
- [Tim Riley] Slice containers automatically import the application container, under the `"application"` namespace
|
30
|
+
- [Tim Riley] Allow slice containers to be imported by other slice containers
|
31
|
+
|
32
|
+
### Changed
|
33
|
+
- [Luca Guidi] Drop support for Ruby: MRI 2.5
|
34
|
+
- [Tim Riley] Removed `config.cookies` in favor of `config.actions.cookies`
|
35
|
+
- [Tim Riley] Removed `config.sessions` in favor of `config.actions.sessions`
|
36
|
+
- [Tim Riley] Removed `config.security` settings
|
37
|
+
|
4
38
|
## v2.0.0.alpha1 - 2019-01-30
|
5
39
|
### Added
|
6
40
|
- [Luca Guidi] Implemented from scratch `hanami version`
|
@@ -50,6 +84,37 @@ end
|
|
50
84
|
- [Luca Guidi] Removed `shotgun` and code reloading from the core. Code reloading is implemented by `hanami-reloader` gem.
|
51
85
|
- [Luca Guidi] Removed support for `.hanamirc`
|
52
86
|
|
87
|
+
## v1.3.4 - 2021-05-02
|
88
|
+
### Fixed
|
89
|
+
- [Slava Kardakov] Fix generated `config.ru` `require_relative` statement
|
90
|
+
- [Armin] Fix `Hanami::CommonLogger` elapsed time compatibility with `rack` 2.1.0+
|
91
|
+
- [Adam Daniels] Fix generated tests compatibility with `minitest` 6.0+
|
92
|
+
|
93
|
+
## v1.3.3 - 2019-09-20
|
94
|
+
### Added
|
95
|
+
- [Gray Manley] Standardize file loading for `.env` files (see: https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use)
|
96
|
+
|
97
|
+
### Fixed
|
98
|
+
- [Alfonso Uceda & Luca Guidi] Ensure to use `:host` option when mounting an application in main router (e.g. `mount Beta::Application.new, at: "/", host: "beta.hanami.test"`)
|
99
|
+
|
100
|
+
## v1.3.2 - 2019-07-26
|
101
|
+
### Added
|
102
|
+
- [Luca Guidi] Support both `hanami-validations` 1 and 2
|
103
|
+
|
104
|
+
### Fixed
|
105
|
+
- [Wisnu Adi Nurcahyo] Ensure `hanami generate` syntax for Welcome page is compatible with ZSH
|
106
|
+
- [Luca Guidi] Don't let `hanami` to crash when called without `bundle exec`
|
107
|
+
|
108
|
+
## v1.3.1 - 2019-01-18
|
109
|
+
### Added
|
110
|
+
- [Luca Guidi] Official support for Ruby: MRI 2.6
|
111
|
+
- [Luca Guidi] Support `bundler` 2.0+
|
112
|
+
|
113
|
+
### Fixed
|
114
|
+
- [Aidan Coyle] Remove from app generator support for deprecated `force_ssl` setting
|
115
|
+
- [Alessandro Caporrini] Remove from app generator support for deprecated `body_parsers` setting
|
116
|
+
- [Daphne Rouw & Sean Collins] Make app generator to work when code in `config/environment.rb` uses double quotes
|
117
|
+
|
53
118
|
## v1.3.0 - 2018-10-24
|
54
119
|
### Added
|
55
120
|
- [Luca Guidi] Automatically log body payload from body parsers
|
@@ -65,7 +130,7 @@ end
|
|
65
130
|
|
66
131
|
### Fixed
|
67
132
|
- [Anton Davydov] Make possible to pass extra settings for custom logger instances (eg. `logger SemanticLogger.new, :foo, :bar`)
|
68
|
-
- [graywolf] Ensure `hanami generate app` to work without `require_relative` entries in `config/
|
133
|
+
- [graywolf] Ensure `hanami generate app` to work without `require_relative` entries in `config/environment.rb`
|
69
134
|
- [Makoto Tajitsu & Luca Guidi] Fixed regression for `hanami new .` that used to generate a broken project
|
70
135
|
|
71
136
|
### Fixed
|
@@ -182,7 +247,7 @@ end
|
|
182
247
|
- [Luca Guidi] Make compatible with Rack 2.0 only
|
183
248
|
- [Luca Guidi] Removed `logger` settings from Hanami applications
|
184
249
|
- [Luca Guidi] Removed logger for Hanami applications (eg `Web.logger`)
|
185
|
-
- [Luca Guidi] Changed mailer syntax in `config/
|
250
|
+
- [Luca Guidi] Changed mailer syntax in `config/environment.rb`
|
186
251
|
|
187
252
|
## v0.9.2 - 2016-12-19
|
188
253
|
## Added
|
@@ -271,11 +336,11 @@ end
|
|
271
336
|
|
272
337
|
## v0.7.2 - 2016-02-09
|
273
338
|
### Fixed
|
274
|
-
- [Alfonso Uceda Pompa] Fixed routing issue when static assets server tried to
|
339
|
+
- [Alfonso Uceda Pompa] Fixed routing issue when static assets server tried to hijack paths that are matching directories in public directory
|
275
340
|
|
276
341
|
## v0.7.1 - 2016-02-05
|
277
342
|
### Fixed
|
278
|
-
- [Anton Davydov] Fixed routing issue when static assets server tried to
|
343
|
+
- [Anton Davydov] Fixed routing issue when static assets server tried to hijack requests belonging to dynamic endpoints
|
279
344
|
- [Anatolii Didukh] Ensure to fallback to default engine for `hanami console`
|
280
345
|
|
281
346
|
## v0.7.0 - 2016-01-22
|
@@ -410,7 +475,7 @@ end
|
|
410
475
|
## v0.3.0 - 2015-03-23
|
411
476
|
### Added
|
412
477
|
- [Luca Guidi] Introduced action generator. Eg. `bundle exec lotus generate action web dashboard#index`
|
413
|
-
- [Alfonso Uceda Pompa] Allow to specify default
|
478
|
+
- [Alfonso Uceda Pompa] Allow to specify default cookies options in application configuration. Eg. `cookies true, { domain: 'lotusrb.org' }`
|
414
479
|
- [Tom Kadwill] Include `Lotus::Helpers` in views.
|
415
480
|
- [Linus Pettersson] Allow to specify `--database` CLI option when generate a new project. Eg. `lotus new bookshelf --database=postgresql`
|
416
481
|
- [Linus Pettersson] Initialize a Git repository when generating a new project
|
data/FEATURES.md
CHANGED
@@ -5,6 +5,14 @@
|
|
5
5
|
|
6
6
|
## v2.0.0.alpha1 - 2019-01-30
|
7
7
|
|
8
|
+
## v1.3.3 - 2019-09-20
|
9
|
+
|
10
|
+
- Standardize file loading for `.env` files (see: https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use)
|
11
|
+
|
12
|
+
## v1.3.2 - 2019-07-26
|
13
|
+
|
14
|
+
## v1.3.1 - 2019-01-18
|
15
|
+
|
8
16
|
## v1.3.0 - 2018-10-24
|
9
17
|
|
10
18
|
- Default testing framework is RSpec
|
@@ -20,7 +28,7 @@
|
|
20
28
|
- Unobtrusive JavaScript (UJS) (via `hanami-ujs` gem)
|
21
29
|
- Interactive console for development error page (via `hanami-webconsole` gem)
|
22
30
|
- CLI: register callbacks for `hanami` commands (`Hanami::CLI.after("db migrate", MyCallback.new)` or `Hanami::CLI.after("db migrate") { ... }`)
|
23
|
-
- Project level Rack middleware stack (`Hanami.configure { middleware.use
|
31
|
+
- Project level Rack middleware stack (`Hanami.configure { middleware.use MyRackMiddleware }`)
|
24
32
|
- Plugins can hook into project configuration (`Hanami.plugin { middleware.use AnotherRackMiddleware }`)
|
25
33
|
- Custom repository commands
|
26
34
|
- Coloured logging
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,6 @@ which provides the glue that ties all the parts together:
|
|
18
18
|
* [**Hanami::Helpers**](https://github.com/hanami/helpers) - View helpers for Ruby applications
|
19
19
|
* [**Hanami::Mailer**](https://github.com/hanami/mailer) - Mail for Ruby applications
|
20
20
|
* [**Hanami::Assets**](https://github.com/hanami/assets) - Assets management for Ruby
|
21
|
-
* [**Hanami::CLI**](https://github.com/hanami/cli) - Ruby command line interface
|
22
21
|
* [**Hanami::Utils**](https://github.com/hanami/utils) - Ruby core extensions and class utilities
|
23
22
|
|
24
23
|
These components are designed to be used independently or together in a Hanami application.
|
@@ -26,14 +25,14 @@ These components are designed to be used independently or together in a Hanami a
|
|
26
25
|
## Status
|
27
26
|
|
28
27
|
[](https://badge.fury.io/rb/hanami)
|
29
|
-
[](https://github.com/hanami/hanami/actions?query=workflow%3Aci+branch%3Aunstable)
|
29
|
+
[](https://codecov.io/gh/hanami/hanami)
|
31
30
|
[](https://depfu.com/github/hanami/hanami?project=Bundler)
|
32
31
|
[](http://inch-ci.org/github/hanami/hanami)
|
33
32
|
|
34
33
|
## Installation
|
35
34
|
|
36
|
-
__Hanami__ supports Ruby (MRI) 2.
|
35
|
+
__Hanami__ supports Ruby (MRI) 2.6+
|
37
36
|
|
38
37
|
```shell
|
39
38
|
gem install hanami
|
@@ -137,4 +136,4 @@ Released under MIT License.
|
|
137
136
|
|
138
137
|
This project was formerly known as Lotus (`lotusrb`).
|
139
138
|
|
140
|
-
Copyright © 2014-
|
139
|
+
Copyright © 2014-2021 Luca Guidi.
|
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| # rubocop:disable Metrics/BlockLength
|
8
8
|
spec.name = "hanami"
|
9
9
|
spec.version = Hanami::VERSION
|
10
10
|
spec.authors = ["Luca Guidi"]
|
@@ -15,22 +15,22 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
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")
|
18
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
18
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
20
19
|
spec.require_paths = ["lib"]
|
21
|
-
spec.required_ruby_version = ">= 2.
|
20
|
+
spec.required_ruby_version = ">= 2.6.0"
|
22
21
|
|
23
22
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
24
23
|
|
25
|
-
spec.add_dependency "hanami-utils", "~> 2.0.alpha"
|
26
|
-
spec.add_dependency "hanami-router", "~> 2.0.alpha"
|
27
|
-
spec.add_dependency "hanami-controller", "~> 2.0.alpha"
|
28
|
-
spec.add_dependency "hanami-cli", "~> 1.0.alpha"
|
29
|
-
spec.add_dependency "dry-system", "~> 0.10"
|
30
|
-
spec.add_dependency "dry-inflector", "~> 0.1", ">= 0.1.2"
|
31
24
|
spec.add_dependency "bundler", ">= 1.16", "< 3"
|
25
|
+
spec.add_dependency "dry-core", "~> 0.4"
|
26
|
+
spec.add_dependency "dry-inflector", "~> 0.1", ">= 0.1.2"
|
27
|
+
spec.add_dependency "dry-monitor"
|
28
|
+
spec.add_dependency "dry-system", "~> 0.19", ">= 0.19.0"
|
29
|
+
spec.add_dependency "hanami-cli", "~> 2.0.alpha"
|
30
|
+
spec.add_dependency "hanami-utils", "~> 2.0.alpha"
|
31
|
+
spec.add_dependency "zeitwerk", "~> 2.4"
|
32
32
|
|
33
|
-
spec.add_development_dependency "rspec", "~>
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.8"
|
34
34
|
spec.add_development_dependency "rack-test", "~> 1.1"
|
35
|
-
spec.add_development_dependency "rake", "~>
|
35
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
36
36
|
end
|
data/lib/hanami.rb
CHANGED
@@ -7,25 +7,27 @@
|
|
7
7
|
# @see http://hanamirb.org
|
8
8
|
module Hanami
|
9
9
|
require "hanami/version"
|
10
|
-
require "hanami/frameworks"
|
11
|
-
require "hanami/container"
|
12
10
|
require "hanami/application"
|
13
11
|
|
14
12
|
@_mutex = Mutex.new
|
15
13
|
|
16
14
|
def self.application
|
17
15
|
@_mutex.synchronize do
|
18
|
-
raise "Hanami
|
16
|
+
raise "Hanami.application not configured" unless defined?(@_application)
|
19
17
|
|
20
18
|
@_application
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
24
|
-
def self.application
|
22
|
+
def self.application?
|
23
|
+
defined?(@_application)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.application=(klass)
|
25
27
|
@_mutex.synchronize do
|
26
|
-
raise "Hanami
|
28
|
+
raise "Hanami.application already configured" if defined?(@_application)
|
27
29
|
|
28
|
-
@_application =
|
30
|
+
@_application = klass unless klass.name.nil?
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -45,10 +47,6 @@ module Hanami
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def self.root
|
49
|
-
Container.root
|
50
|
-
end
|
51
|
-
|
52
50
|
def self.env
|
53
51
|
(ENV["HANAMI_ENV"] || "development").to_sym
|
54
52
|
end
|
@@ -58,18 +56,21 @@ module Hanami
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def self.logger
|
61
|
-
|
59
|
+
application[:logger]
|
62
60
|
end
|
63
61
|
|
64
|
-
def self.
|
65
|
-
|
66
|
-
|
62
|
+
def self.init
|
63
|
+
application.init
|
64
|
+
end
|
67
65
|
|
68
|
-
|
69
|
-
|
66
|
+
def self.boot(web: true)
|
67
|
+
if defined?(@_app)
|
68
|
+
@_app
|
69
|
+
else
|
70
|
+
application.boot
|
70
71
|
|
71
|
-
|
72
|
-
|
72
|
+
@_app = application.new if web
|
73
|
+
end
|
73
74
|
end
|
74
75
|
|
75
76
|
def self.bundler_groups
|
data/lib/hanami/application.rb
CHANGED
@@ -1,66 +1,362 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "dry/system/container"
|
3
4
|
require "hanami/configuration"
|
4
|
-
require "
|
5
|
-
require "
|
5
|
+
require "pathname"
|
6
|
+
require "rack"
|
7
|
+
require_relative "slice"
|
8
|
+
require_relative "application/autoloader/inflector_adapter"
|
9
|
+
require_relative "application/settings"
|
6
10
|
|
7
11
|
module Hanami
|
8
|
-
# Hanami application
|
12
|
+
# Hanami application class
|
9
13
|
#
|
10
14
|
# @since 2.0.0
|
11
15
|
class Application
|
12
16
|
@_mutex = Mutex.new
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
class << self
|
19
|
+
def inherited(klass)
|
20
|
+
@_mutex.synchronize do
|
21
|
+
klass.class_eval do
|
22
|
+
@_mutex = Mutex.new
|
23
|
+
@_configuration = Hanami::Configuration.new(env: Hanami.env)
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
extend ClassMethods
|
26
|
+
include InstanceMethods
|
27
|
+
end
|
28
|
+
|
29
|
+
klass.send :prepare_base_load_path
|
23
30
|
|
24
|
-
|
31
|
+
Hanami.application = klass
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
28
|
-
#
|
36
|
+
# Application class interface
|
29
37
|
#
|
30
|
-
#
|
38
|
+
# rubocop:disable Metrics/ModuleLength
|
31
39
|
module ClassMethods
|
40
|
+
def self.extended(klass)
|
41
|
+
klass.class_eval do
|
42
|
+
@inited = @booted = false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
32
46
|
def configuration
|
33
47
|
@_configuration
|
34
48
|
end
|
35
49
|
|
36
50
|
alias config configuration
|
37
51
|
|
38
|
-
def
|
52
|
+
def init # rubocop:disable Metrics/MethodLength
|
53
|
+
return self if inited?
|
54
|
+
|
55
|
+
configuration.finalize
|
56
|
+
|
57
|
+
load_settings
|
58
|
+
|
59
|
+
@container = prepare_container
|
60
|
+
@deps_module = prepare_deps_module
|
61
|
+
|
62
|
+
load_slices
|
63
|
+
slices.values.each(&:init)
|
64
|
+
slices.freeze
|
65
|
+
|
66
|
+
if configuration.autoloader
|
67
|
+
configuration.autoloader.inflector = Autoloader::InflectorAdapter.new(inflector)
|
68
|
+
configuration.autoloader.setup
|
69
|
+
end
|
70
|
+
|
71
|
+
load_routes
|
72
|
+
|
73
|
+
@inited = true
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def inited?
|
78
|
+
@inited
|
79
|
+
end
|
80
|
+
|
81
|
+
def container
|
82
|
+
raise "Application not init'ed" unless defined?(@container)
|
83
|
+
|
84
|
+
@container
|
85
|
+
end
|
86
|
+
|
87
|
+
def deps
|
88
|
+
raise "Application not init'ed" unless defined?(@deps_module)
|
89
|
+
|
90
|
+
@deps_module
|
91
|
+
end
|
92
|
+
|
93
|
+
def slices
|
94
|
+
@slices ||= {}
|
95
|
+
end
|
96
|
+
|
97
|
+
def register_slice(name, **slice_args)
|
98
|
+
raise "Slice +#{name}+ already registered" if slices.key?(name.to_sym)
|
99
|
+
|
100
|
+
slice = Slice.new(self, name: name, **slice_args)
|
101
|
+
slice.namespace.const_set :Slice, slice if slice.namespace # rubocop:disable Style/SafeNavigation
|
102
|
+
slices[name.to_sym] = slice
|
103
|
+
end
|
104
|
+
|
105
|
+
def register(*args, **opts, &block)
|
106
|
+
container.register(*args, **opts, &block)
|
107
|
+
end
|
108
|
+
|
109
|
+
def register_bootable(*args, **opts, &block)
|
110
|
+
container.boot(*args, **opts, &block)
|
111
|
+
end
|
112
|
+
|
113
|
+
def init_bootable(*args)
|
114
|
+
container.init(*args)
|
115
|
+
end
|
116
|
+
|
117
|
+
def start_bootable(*args)
|
118
|
+
container.start(*args)
|
119
|
+
end
|
120
|
+
|
121
|
+
def key?(*args)
|
122
|
+
container.key?(*args)
|
123
|
+
end
|
124
|
+
|
125
|
+
def keys
|
126
|
+
container.keys
|
127
|
+
end
|
128
|
+
|
129
|
+
def [](*args)
|
130
|
+
container[*args]
|
131
|
+
end
|
132
|
+
|
133
|
+
def resolve(*args)
|
134
|
+
container.resolve(*args)
|
135
|
+
end
|
136
|
+
|
137
|
+
def boot(&block)
|
138
|
+
return self if booted?
|
139
|
+
|
140
|
+
init
|
141
|
+
|
142
|
+
container.finalize!(&block)
|
143
|
+
|
144
|
+
slices.values.each(&:boot)
|
145
|
+
|
146
|
+
@booted = true
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
def booted?
|
151
|
+
@booted
|
152
|
+
end
|
153
|
+
|
154
|
+
def settings(&block) # rubocop:disable Metrics/MethodLength
|
155
|
+
if block
|
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
|
169
|
+
end
|
170
|
+
|
171
|
+
def routes(&block)
|
39
172
|
@_mutex.synchronize do
|
40
|
-
if
|
173
|
+
if block.nil?
|
41
174
|
raise "Hanami.application.routes not configured" unless defined?(@_routes)
|
42
175
|
|
43
176
|
@_routes
|
44
177
|
else
|
45
|
-
@_routes =
|
178
|
+
@_routes = block
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
MODULE_DELIMITER = "::"
|
184
|
+
private_constant :MODULE_DELIMITER
|
185
|
+
|
186
|
+
def namespace
|
187
|
+
inflector.constantize(name.split(MODULE_DELIMITER)[0..-2].join(MODULE_DELIMITER))
|
188
|
+
end
|
189
|
+
|
190
|
+
def namespace_path
|
191
|
+
inflector.underscore(namespace)
|
192
|
+
end
|
193
|
+
|
194
|
+
def application_name
|
195
|
+
inflector.underscore(namespace).to_sym
|
196
|
+
end
|
197
|
+
|
198
|
+
def root
|
199
|
+
configuration.root
|
200
|
+
end
|
201
|
+
|
202
|
+
def inflector
|
203
|
+
configuration.inflector
|
204
|
+
end
|
205
|
+
|
206
|
+
# @api private
|
207
|
+
def component_provider(component)
|
208
|
+
raise "Hanami.application must be inited before detecting providers" unless inited?
|
209
|
+
|
210
|
+
# [Admin, Main, MyApp] or [MyApp::Admin, MyApp::Main, MyApp]
|
211
|
+
providers = slices.values + [self]
|
212
|
+
|
213
|
+
component_class = component.is_a?(Class) ? component : component.class
|
214
|
+
component_name = component_class.name
|
215
|
+
|
216
|
+
return unless component_name
|
217
|
+
|
218
|
+
providers.detect { |provider| component_name.include?(provider.namespace.to_s) }
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def prepare_base_load_path
|
224
|
+
base_path = File.join(root, "lib")
|
225
|
+
$LOAD_PATH.unshift base_path unless $LOAD_PATH.include?(base_path)
|
226
|
+
end
|
227
|
+
|
228
|
+
def prepare_container
|
229
|
+
define_container.tap do |container|
|
230
|
+
configure_container container
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def prepare_deps_module
|
235
|
+
define_deps_module
|
236
|
+
end
|
237
|
+
|
238
|
+
def define_container
|
239
|
+
require "#{application_name}/container"
|
240
|
+
namespace.const_get :Container
|
241
|
+
rescue LoadError, NameError
|
242
|
+
namespace.const_set :Container, Class.new(Dry::System::Container)
|
243
|
+
end
|
244
|
+
|
245
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
246
|
+
def configure_container(container)
|
247
|
+
container.use :env, inferrer: -> { Hanami.env }
|
248
|
+
container.use :notifications
|
249
|
+
|
250
|
+
container.configure do |config|
|
251
|
+
config.inflector = configuration.inflector
|
252
|
+
|
253
|
+
config.root = configuration.root
|
254
|
+
config.bootable_dirs = [
|
255
|
+
"config/boot",
|
256
|
+
Pathname(__dir__).join("application/container/boot").realpath,
|
257
|
+
]
|
258
|
+
|
259
|
+
if configuration.autoloader
|
260
|
+
require "dry/system/loader/autoloading"
|
261
|
+
config.component_dirs.loader = Dry::System::Loader::Autoloading
|
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
|
269
|
+
|
270
|
+
configuration.autoloader&.push_dir(root.join("lib"))
|
46
271
|
end
|
47
272
|
end
|
273
|
+
|
274
|
+
container
|
275
|
+
end
|
276
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
277
|
+
|
278
|
+
def define_deps_module
|
279
|
+
require "#{application_name}/deps"
|
280
|
+
namespace.const_get :Deps
|
281
|
+
rescue LoadError, NameError
|
282
|
+
namespace.const_set :Deps, container.injector
|
283
|
+
end
|
284
|
+
|
285
|
+
def load_slices
|
286
|
+
Dir[File.join(slices_path, "*")]
|
287
|
+
.select(&File.method(:directory?))
|
288
|
+
.each(&method(:load_slice))
|
289
|
+
end
|
290
|
+
|
291
|
+
def slices_path
|
292
|
+
File.join(root, config.slices_dir)
|
293
|
+
end
|
294
|
+
|
295
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
296
|
+
def load_slice(slice_path)
|
297
|
+
slice_path = Pathname(slice_path)
|
298
|
+
|
299
|
+
slice_name = slice_path.relative_path_from(Pathname(slices_path)).to_s
|
300
|
+
slice_const_name = inflector.camelize(slice_name)
|
301
|
+
|
302
|
+
if config.slices_namespace.const_defined?(slice_const_name)
|
303
|
+
slice_module = config.slices_namespace.const_get(slice_const_name)
|
304
|
+
|
305
|
+
raise "Cannot use slice +#{slice_const_name}+ since it is not a module" unless slice_module.is_a?(Module)
|
306
|
+
else
|
307
|
+
slice_module = Module.new
|
308
|
+
config.slices_namespace.const_set inflector.camelize(slice_name), slice_module
|
309
|
+
end
|
310
|
+
|
311
|
+
register_slice(
|
312
|
+
slice_name,
|
313
|
+
namespace: slice_module,
|
314
|
+
root: slice_path.realpath
|
315
|
+
)
|
316
|
+
end
|
317
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
318
|
+
|
319
|
+
def load_routes
|
320
|
+
require File.join(configuration.root, configuration.router.routes)
|
321
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
322
|
+
end
|
323
|
+
|
324
|
+
def load_settings
|
325
|
+
prepare_base_load_path
|
326
|
+
require File.join(configuration.root, configuration.settings_path)
|
327
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
48
328
|
end
|
49
329
|
end
|
330
|
+
# rubocop:enable Metrics/ModuleLength
|
50
331
|
|
51
|
-
#
|
52
|
-
#
|
53
|
-
# @since 2.0.0
|
332
|
+
# Application instance interface
|
54
333
|
module InstanceMethods
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
334
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
335
|
+
def initialize(application = self.class)
|
336
|
+
require_relative "application/router"
|
337
|
+
|
338
|
+
application.boot
|
339
|
+
|
340
|
+
resolver = application.config.router.resolver.new(
|
341
|
+
slices: application.slices,
|
342
|
+
inflector: application.inflector
|
343
|
+
)
|
60
344
|
|
61
|
-
|
345
|
+
router = Application::Router.new(
|
346
|
+
routes: application.routes,
|
347
|
+
resolver: resolver,
|
348
|
+
**application.configuration.router.options,
|
349
|
+
) do
|
350
|
+
use application[:rack_monitor]
|
351
|
+
|
352
|
+
application.config.for_each_middleware do |m, *args, &block|
|
353
|
+
use(m, *args, &block)
|
354
|
+
end
|
62
355
|
end
|
356
|
+
|
357
|
+
@app = router.to_rack_app
|
63
358
|
end
|
359
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
64
360
|
|
65
361
|
def call(env)
|
66
362
|
@app.call(env)
|