hanami 2.0.0.rc1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/FEATURES.md +15 -21
  4. data/README.md +7 -37
  5. data/hanami.gemspec +5 -5
  6. data/lib/hanami/app.rb +2 -33
  7. data/lib/hanami/config/actions/content_security_policy.rb +1 -1
  8. data/lib/hanami/config/actions.rb +0 -3
  9. data/lib/hanami/config/logger.rb +52 -29
  10. data/lib/hanami/config.rb +22 -1
  11. data/lib/hanami/env.rb +52 -0
  12. data/lib/hanami/extensions/action/slice_configured_action.rb +5 -2
  13. data/lib/hanami/extensions/view/slice_configured_view.rb +4 -1
  14. data/lib/hanami/port.rb +45 -0
  15. data/lib/hanami/providers/rack.rb +15 -7
  16. data/lib/hanami/rake_tasks.rb +4 -5
  17. data/lib/hanami/slice.rb +3 -1
  18. data/lib/hanami/version.rb +1 -1
  19. data/lib/hanami/web/rack_logger.rb +64 -15
  20. data/lib/hanami.rb +24 -5
  21. data/spec/integration/action/format_config_spec.rb +194 -0
  22. data/spec/integration/action/slice_configuration_spec.rb +39 -42
  23. data/spec/integration/code_loading/loading_from_lib_spec.rb +34 -0
  24. data/spec/integration/dotenv_loading_spec.rb +1 -0
  25. data/spec/integration/rack_app/body_parser_spec.rb +2 -5
  26. data/spec/integration/rack_app/rack_app_spec.rb +132 -5
  27. data/spec/integration/settings/access_in_slice_class_body_spec.rb +1 -0
  28. data/spec/integration/settings/loading_from_env_spec.rb +1 -0
  29. data/spec/integration/setup_spec.rb +2 -2
  30. data/spec/spec_helper.rb +12 -0
  31. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +14 -14
  32. data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -8
  33. data/spec/unit/hanami/config/actions_spec.rb +7 -10
  34. data/spec/unit/hanami/config/logger_spec.rb +4 -4
  35. data/spec/unit/hanami/port_spec.rb +117 -0
  36. data/spec/unit/hanami/version_spec.rb +1 -1
  37. data/spec/unit/hanami/web/rack_logger_spec.rb +4 -1
  38. metadata +36 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a1a430f511f0bda44248e88d4fb2c87d10dc3d8fbabf092b895ff2a3bbb78db
4
- data.tar.gz: 75c6e767584d34103505eb3637fc0fb72dde6118b35fa5f4a76a186681031e7a
3
+ metadata.gz: feb360b6ea1b56e04569faecc65485d6bba65a6a59d4ef764830f0ae191fa62f
4
+ data.tar.gz: 420ee35b85415b3db8a8c55c7a09ca5bb4d2207f19dd8d1cd47ad767c6c5681c
5
5
  SHA512:
6
- metadata.gz: 306e3261fb72d114ddcb9128de3a3c9a499bff57f1b2c51fd3cee54e644248c3bd981f54b626d7e5549e1fa9c467d86156a7c2c3e4c14c869501e698d07f6423
7
- data.tar.gz: a59bf43bf07700e282abe6e83919fd53a5e277b7efa5706b743a25537006eef76b49409bedf0af49cae8122bd39d5c396f705f1e148a01367565e1accb46d9a6
6
+ metadata.gz: b85cb4483d1aff46916141a5802ac179f63603e124e10dc0ee71c3193e289becafec130fe67551ad6ca1da166611c91c2fcefd4aea636b84a79dfc129f9bb831
7
+ data.tar.gz: 19aab9a7f4d054ccca8d311cb077967b0d4fad48b55b86b5fbe8d367a43f86a17406ef21a2712597cc5f5e8344e0e0bbd2e55964b6bcae4e9e8ada25a85c1a11
data/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  The web, with simplicity.
4
4
 
5
+ ## v2.0.1 - 2022-12-06
6
+
7
+ ### Fixed
8
+
9
+ - [Luca Guidi] Ensure `Content-Security-Policy` HTTP response header to be returned as a single line
10
+ - [Tim Riley] Ensure Rack events are on internal notifications system
11
+
12
+ ## v2.0.0 - 2022-11-22
13
+
14
+ ### Added
15
+
16
+ - [Tim Riley] Allow custom code from Hanami app `lib/` to be required before to load the app
17
+ - [Tim Riley] Support the new `Hanami::Action::Config#formats` config from hanami-controller 2.0.0
18
+ - [Tim Riley] Automatically use body_parser middleware when actions `:json` format is configured
19
+
20
+ ### Fixed
21
+
22
+ - [Luca Guidi] Ensure Hanami app to not crash when `hanami-controller` isn't bundled
23
+ - [Piotr Solnica] Several logger fixes
24
+
25
+ ### Changed
26
+
27
+ - [Tim Riley] Don't assign a default MIME Type for Hanami apps
28
+
5
29
  ## v2.0.0.rc1 - 2022-11-08
6
30
 
7
31
  ### Added
data/FEATURES.md CHANGED
@@ -4,27 +4,21 @@
4
4
 
5
5
  ## Features
6
6
 
7
- ## v2.0.0.beta1 - 2021-07-20
8
-
9
- - Generate new apps using `app/` directory
10
-
11
- ## v2.0.0.alpha8 - 2021-05-19
12
-
13
- ## v2.0.0.alpha7.1 - 2021-03-09
14
-
15
- ## v2.0.0.alpha7 - 2021-03-08
16
-
17
- ## v2.0.0.alpha6 - 2021-02-10
18
-
19
- ## v2.0.0.alpha5 - 2021-01-12
20
-
21
- ## v2.0.0.alpha4 - 2021-12-07
22
-
23
- ## v2.0.0.alpha3 - 2021-11-09
24
-
25
- ## v2.0.0.alpha2 - 2021-05-04
26
-
27
- ## v2.0.0.alpha1 - 2019-01-30
7
+ ## v2.0.0 - 2021-11-22
8
+
9
+ - Renamed _apps_ into _slices_, and _project_ into _app_
10
+ - The core of new applications is going to be `app/`. Slices are now optional.
11
+ - App class built around a container for managing app components; code from `app/` is loaded into the app
12
+ - Apps may have multiple Slices; code from `slices/[slice_name]/` is loaded into the corresponding slice
13
+ - `MyApp::Deps` or `MySlice::Deps` mixin for auto-registering dependencies from the app or a slice
14
+ - Code autoloading using Zeitwerk
15
+ - Code reloading via Guard
16
+ - Providers for setting up and managing the lifecycle of your app's critical components and integrations
17
+ - Type-safe app settings
18
+ - Rebuilt high-performance router
19
+ - Redesigned stateless `Hamami::Action` classes supporting the Deps mixin; add your behavior to `#handle(request, response)`
20
+ - Simplified action format configuration via `config.format` and `config.formats`
21
+ - Rewritten CLI and console
28
22
 
29
23
  ## v1.3.3 - 2019-09-20
30
24
 
data/README.md CHANGED
@@ -8,19 +8,16 @@ The web, with simplicity.
8
8
 
9
9
  ## Frameworks
10
10
 
11
- Hanami is a **full-stack** Ruby web framework.
12
- It's made up of smaller, single-purpose libraries.
11
+ Hanami is a **full-stack** Ruby web framework. It's made up of smaller, single-purpose libraries.
13
12
 
14
- This repository is for the full-stack framework,
15
- which provides the glue that ties all the parts together:
13
+ This repository is for the full-stack framework, which provides the glue that ties all the parts together:
16
14
 
17
- * [**Hanami::View**](https://github.com/hanami/view) - Presentation with a separation between views and templates
18
- * [**Hanami::Controller**](https://github.com/hanami/controller) - Full featured, fast and testable actions for Rack
19
15
  * [**Hanami::Router**](https://github.com/hanami/router) - Rack compatible HTTP router for Ruby
16
+ * [**Hanami::Controller**](https://github.com/hanami/controller) - Full featured, fast and testable actions for Rack
17
+ * [**Hanami::View**](https://github.com/hanami/view) - Presentation with a separation between views and templates
20
18
  * [**Hanami::Helpers**](https://github.com/hanami/helpers) - View helpers for Ruby applications
21
19
  * [**Hanami::Mailer**](https://github.com/hanami/mailer) - Mail for Ruby applications
22
20
  * [**Hanami::Assets**](https://github.com/hanami/assets) - Assets management for Ruby
23
- * [**Hanami::Utils**](https://github.com/hanami/utils) - Ruby core extensions and class utilities
24
21
 
25
22
  These components are designed to be used independently or together in a Hanami application.
26
23
 
@@ -28,9 +25,7 @@ These components are designed to be used independently or together in a Hanami a
28
25
 
29
26
  [![Gem Version](https://badge.fury.io/rb/hanami.svg)](https://badge.fury.io/rb/hanami)
30
27
  [![CI](https://github.com/hanami/hanami/workflows/ci/badge.svg?branch=main)](https://github.com/hanami/hanami/actions?query=workflow%3Aci+branch%3Amain)
31
- [![Test Coverage](https://codecov.io/gh/hanami/hanami/branch/main/graph/badge.svg)](https://codecov.io/gh/hanami/hanami)
32
28
  [![Depfu](https://badges.depfu.com/badges/ba000e0f69e6ef1c44cd3038caaa1841/overview.svg)](https://depfu.com/github/hanami/hanami?project=Bundler)
33
- [![Inline Docs](http://inch-ci.org/github/hanami/hanami.svg)](http://inch-ci.org/github/hanami/hanami)
34
29
 
35
30
  ## Installation
36
31
 
@@ -75,10 +70,7 @@ You can give back to Open Source, by supporting Hanami development via [GitHub S
75
70
 
76
71
  ## Community
77
72
 
78
- We strive for an inclusive and helpful community.
79
- We have a [Code of Conduct](http://hanamirb.org/community/#code-of-conduct) to handle controversial cases.
80
- In general, we expect **you** to be **nice** with other people.
81
- Our hope is for a great software and a great Community.
73
+ We strive for an inclusive and helpful community. We have a [Code of Conduct](http://hanamirb.org/community/#code-of-conduct) to handle controversial cases. In general, we expect **you** to be **nice** with other people. Our hope is for a great software and a great Community.
82
74
 
83
75
  ## Contributing [![Open Source Helpers](https://www.codetriage.com/hanami/hanami/badges/users.svg)](https://www.codetriage.com/hanami/hanami)
84
76
 
@@ -90,44 +82,22 @@ Our hope is for a great software and a great Community.
90
82
 
91
83
  In addition to contributing code, you can help to triage issues. This can include reproducing bug reports, or asking for vital information such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to hanami on CodeTriage](https://www.codetriage.com/hanami/hanami).
92
84
 
93
- ### How To Use Hanami HEAD
94
-
95
- If you want to test Hanami's HEAD to try a new feature or to test a bug fix, here's how to do:
96
-
97
- ```
98
- git clone https://github.com/hanami/hanami.git
99
- cd hanami && bundle
100
- bundle exec hanami new bookshelf --hanami-head
101
- cd bookshelf
102
- vim Gemfile # edit with: gem 'hanami', path: '..'
103
- bundle
104
- ```
105
-
106
85
  ### Development Requirements
107
86
 
108
- * Ruby 2.3+ / JRuby 9.1.5.0+
87
+ * Ruby >= 3.0
109
88
  * Bundler
110
- * [PhantomJS](http://phantomjs.org/download.html)
111
89
  * Node.js (MacOS)
112
90
 
113
91
  ### Testing
114
92
 
115
- In order to simulate installed gems on developers' computers, the build installs
116
- all the gems locally in `vendor/cache`, including `hanami` code from `lib/`.
93
+ In order to simulate installed gems on developers' computers, the build installs all the gems locally in `vendor/cache`, including `hanami` code from `lib/`.
117
94
 
118
95
  **Before running a test, please make sure you have a fresh version of the code:**
119
96
 
120
97
  ```shell
121
- ./script/setup
122
98
  bundle exec rspec spec/path/to/file_spec.rb
123
99
  ```
124
100
 
125
- To run all the tests, please use:
126
-
127
- ```shell
128
- ./script/ci
129
- ```
130
-
131
101
  ## Versioning
132
102
 
133
103
  __Hanami__ uses [Semantic Versioning 2.0.0](http://semver.org)
data/hanami.gemspec CHANGED
@@ -35,11 +35,11 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency "dry-configurable", "~> 1.0", "< 2"
36
36
  spec.add_dependency "dry-core", "~> 1.0", "< 2"
37
37
  spec.add_dependency "dry-inflector", "~> 1.0", "< 2"
38
- spec.add_dependency "dry-monitor", "~> 1.0", "< 2"
39
- spec.add_dependency "dry-system", "~> 1.0.rc"
40
- spec.add_dependency "dry-logger", "~> 1.0.rc"
41
- spec.add_dependency "hanami-cli", "~> 2.0.rc"
42
- spec.add_dependency "hanami-utils", "~> 2.0.rc"
38
+ spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
39
+ spec.add_dependency "dry-system", "~> 1.0", "< 2"
40
+ spec.add_dependency "dry-logger", "~> 1.0", "< 2"
41
+ spec.add_dependency "hanami-cli", "~> 2.0"
42
+ spec.add_dependency "hanami-utils", "~> 2.0"
43
43
  spec.add_dependency "zeitwerk", "~> 2.6"
44
44
 
45
45
  spec.add_development_dependency "rspec", "~> 3.8"
data/lib/hanami/app.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "constants"
4
+ require_relative "env"
4
5
 
5
6
  module Hanami
6
7
  # The Hanami app is a singular slice tasked with managing the core components of the app and
@@ -28,13 +29,7 @@ module Hanami
28
29
  @_mutex.synchronize do
29
30
  subclass.class_eval do
30
31
  @config = Hanami::Config.new(app_name: slice_name, env: Hanami.env)
31
-
32
- # Prepare the load path (based on the default root of `Dir.pwd`) as early as possible, so
33
- # you can make a `require` inside the body of an `App` subclass, which may be useful for
34
- # certain kinds of app configuration.
35
- prepare_load_path
36
-
37
- load_dotenv
32
+ Hanami::Env.load
38
33
  end
39
34
  end
40
35
  end
@@ -102,32 +97,6 @@ module Hanami
102
97
 
103
98
  private
104
99
 
105
- # Uses [dotenv](https://github.com/bkeepers/dotenv) (if available) to populate `ENV` from
106
- # various `.env` files.
107
- #
108
- # For a given `HANAMI_ENV` environment, the `.env` files are looked up in the following order:
109
- #
110
- # - .env.{environment}.local
111
- # - .env.local (unless the environment is `test`)
112
- # - .env.{environment}
113
- # - .env
114
- #
115
- # If dotenv is unavailable, the method exits and does nothing.
116
- def load_dotenv
117
- return unless Hanami.bundled?("dotenv")
118
-
119
- hanami_env = Hanami.env
120
- dotenv_files = [
121
- ".env.#{hanami_env}.local",
122
- (".env.local" unless hanami_env == :test),
123
- ".env.#{hanami_env}",
124
- ".env"
125
- ].compact
126
-
127
- require "dotenv"
128
- Dotenv.load(*dotenv_files)
129
- end
130
-
131
100
  def prepare_all
132
101
  prepare_load_path
133
102
 
@@ -102,7 +102,7 @@ module Hanami
102
102
  def to_s
103
103
  @policy.map do |key, value|
104
104
  "#{dasherize(key)} #{value}"
105
- end.join(";\n")
105
+ end.join(";")
106
106
  end
107
107
 
108
108
  private
@@ -136,9 +136,6 @@ module Hanami
136
136
 
137
137
  # Apply defaults for base config
138
138
  def configure_defaults
139
- self.default_request_format = :html
140
- self.default_response_format = :html
141
-
142
139
  self.default_headers = {
143
140
  "X-Frame-Options" => "DENY",
144
141
  "X-Content-Type-Options" => "nosniff",
@@ -15,9 +15,15 @@ module Hanami
15
15
  # @return [Hanami::SliceName]
16
16
  #
17
17
  # @api private
18
- # @since 2.0.o
18
+ # @since 2.0.0
19
19
  attr_reader :app_name
20
20
 
21
+ # @return [Symbol]
22
+ #
23
+ # @api private
24
+ # @since 2.0.0
25
+ attr_reader :env
26
+
21
27
  # @!attribute [rw] level
22
28
  # Sets or returns the logger level.
23
29
  #
@@ -40,7 +46,7 @@ module Hanami
40
46
  #
41
47
  # @api public
42
48
  # @since 2.0.0
43
- setting :stream
49
+ setting :stream, default: $stdout
44
50
 
45
51
  # @!attribute [rw] formatter
46
52
  # Sets or returns the logger's formatter.
@@ -57,7 +63,7 @@ module Hanami
57
63
  #
58
64
  # @api public
59
65
  # @since 2.0.0
60
- setting :formatter
66
+ setting :formatter, default: :string
61
67
 
62
68
  # @!attribute [rw] template
63
69
  # Sets or returns log entry string template
@@ -68,7 +74,7 @@ module Hanami
68
74
  #
69
75
  # @api public
70
76
  # @since 2.0.0
71
- setting :template, default: "[%<progname>s] [%<severity>s] [%<time>s] %<message>s"
77
+ setting :template, default: :details
72
78
 
73
79
  # @!attribute [rw] filters
74
80
  # Sets or returns an array of attribute names to filter from logs.
@@ -85,11 +91,11 @@ module Hanami
85
91
  # @!attribute [rw] logger_constructor
86
92
  # Sets or returns the constructor proc to use for the logger instantiation.
87
93
  #
88
- # Defaults to `Dry.method(:Logger)`.
94
+ # Defaults to either `Config#production_logger` or `Config#development_logger`
89
95
  #
90
96
  # @api public
91
97
  # @since 2.0.0
92
- setting :logger_constructor, default: Dry.method(:Logger)
98
+ setting :logger_constructor
93
99
 
94
100
  # @!attribute [rw] options
95
101
  # Sets or returns a hash of options to pass to the {logger_constructor} when initializing
@@ -113,27 +119,18 @@ module Hanami
113
119
  # @api private
114
120
  def initialize(env:, app_name:)
115
121
  @app_name = app_name
116
-
117
- config.level = case env
118
- when :production
119
- :info
120
- else
121
- :debug
122
- end
123
-
124
- config.stream = case env
125
- when :test
126
- File.join("log", "#{env}.log")
127
- else
128
- $stdout
129
- end
130
-
131
- config.formatter = case env
132
- when :production
133
- :json
134
- else
135
- :rack
136
- end
122
+ @env = env
123
+
124
+ case env
125
+ when :development, :test
126
+ config.level = :debug
127
+ config.stream = File.join("log", "#{env}.log") if env == :test
128
+ config.logger_constructor = method(:development_logger)
129
+ when :production
130
+ config.level = :info
131
+ config.formatter = :json
132
+ config.logger_constructor = method(:production_logger)
133
+ end
137
134
  end
138
135
 
139
136
  # Returns a new instance of the logger.
@@ -143,13 +140,39 @@ module Hanami
143
140
  # @api public
144
141
  # @since 2.0.0
145
142
  def instance
146
- logger_constructor.call(app_name.name, **logger_constructor_opts)
143
+ logger_constructor.call(env, app_name.name, **logger_constructor_options)
144
+ end
145
+
146
+ # Build an instance of a development logger
147
+ #
148
+ # This logger is used in both development and test
149
+ #
150
+ # @return [Dry::Logger::Dispatcher]
151
+ # @since 2.0.0
152
+ # @api private
153
+ def development_logger(_env, app_name, **options)
154
+ Dry.Logger(app_name, **options) do |setup|
155
+ setup
156
+ .add_backend(log_if: -> entry { !entry.tag?(:rack) })
157
+ .add_backend(formatter: :rack, log_if: -> entry { entry.tag?(:rack) })
158
+ end
159
+ end
160
+
161
+ # Build an instance of a production logger
162
+ #
163
+ # This logger is used in both development and test
164
+ #
165
+ # @return [Dry::Logger::Dispatcher]
166
+ # @since 2.0.0
167
+ # @api private
168
+ def production_logger(_env, app_name, **options)
169
+ Dry.Logger(app_name, **options)
147
170
  end
148
171
 
149
172
  private
150
173
 
151
174
  # @api private
152
- def logger_constructor_opts
175
+ def logger_constructor_options
153
176
  {stream: stream,
154
177
  level: level,
155
178
  formatter: formatter,
data/lib/hanami/config.rb CHANGED
@@ -274,6 +274,8 @@ module Hanami
274
274
  logger.finalize!
275
275
  router.finalize!
276
276
 
277
+ use_body_parser_middleware
278
+
277
279
  super
278
280
  end
279
281
 
@@ -371,7 +373,26 @@ module Hanami
371
373
  self.slices = ENV["HANAMI_SLICES"]&.split(",")&.map(&:strip)
372
374
  end
373
375
 
374
- # @api private
376
+ SUPPORTED_MIDDLEWARE_PARSERS = %i[json].freeze
377
+ private_constant :SUPPORTED_MIDDLEWARE_PARSERS
378
+
379
+ def use_body_parser_middleware
380
+ return unless Hanami.bundled?("hanami-controller")
381
+
382
+ return if actions.formats.empty?
383
+ return if middleware.stack["/"].map(&:first).any? { |klass| klass == "Hanami::Middleware::BodyParser" }
384
+
385
+ parsers = SUPPORTED_MIDDLEWARE_PARSERS & actions.formats.values
386
+ return if parsers.empty?
387
+
388
+ middleware.use(
389
+ :body_parser,
390
+ [parsers.to_h { |parser_format|
391
+ [parser_format, actions.formats.mime_types_for(parser_format)]
392
+ }]
393
+ )
394
+ end
395
+
375
396
  def load_dependent_config(gem_name)
376
397
  if Hanami.bundled?(gem_name)
377
398
  yield
data/lib/hanami/env.rb ADDED
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module Env
5
+ # @since 2.0.1
6
+ # @api private
7
+ @_loaded = false
8
+
9
+ # Uses [dotenv](https://github.com/bkeepers/dotenv) (if available) to populate `ENV` from
10
+ # various `.env` files.
11
+ #
12
+ # For a given `HANAMI_ENV` environment, the `.env` files are looked up in the following order:
13
+ #
14
+ # - .env.{environment}.local
15
+ # - .env.local (unless the environment is `test`)
16
+ # - .env.{environment}
17
+ # - .env
18
+ #
19
+ # If dotenv is unavailable, the method exits and does nothing.
20
+ #
21
+ # @since 2.0.1
22
+ # @api private
23
+ def self.load(env = Hanami.env)
24
+ return unless Hanami.bundled?("dotenv")
25
+ return if loaded?
26
+
27
+ dotenv_files = [
28
+ ".env.#{env}.local",
29
+ (".env.local" unless env == :test),
30
+ ".env.#{env}",
31
+ ".env"
32
+ ].compact
33
+
34
+ require "dotenv"
35
+ Dotenv.load(*dotenv_files)
36
+
37
+ loaded!
38
+ end
39
+
40
+ # @since 2.0.1
41
+ # @api private
42
+ def self.loaded?
43
+ @_loaded
44
+ end
45
+
46
+ # @since 2.0.1
47
+ # @api private
48
+ def self.loaded!
49
+ @_loaded = true
50
+ end
51
+ end
52
+ end
@@ -60,7 +60,7 @@ module Hanami
60
60
  #
61
61
  # module MyApp
62
62
  # class Action < Hanami::Action
63
- # config.default_response_format = :json
63
+ # config.format :json
64
64
  # end
65
65
  # end
66
66
  #
@@ -91,7 +91,10 @@ module Hanami
91
91
 
92
92
  next if slice.parent && slice_value == parent_value
93
93
 
94
- action_class.config.public_send(:"#{setting.name}=", slice_value)
94
+ action_class.config.public_send(
95
+ :"#{setting.name}=",
96
+ setting.mutable? ? slice_value.dup : slice_value
97
+ )
95
98
  end
96
99
  end
97
100
 
@@ -77,7 +77,10 @@ module Hanami
77
77
 
78
78
  next if slice.parent && slice_value == parent_value
79
79
 
80
- view_class.config.public_send(:"#{setting.name}=", slice_value)
80
+ view_class.config.public_send(
81
+ :"#{setting.name}=",
82
+ setting.mutable? ? slice_value.dup : slice_value
83
+ )
81
84
  end
82
85
 
83
86
  view_class.config.inflector = inflector
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ # @since 2.0.1
5
+ # @api private
6
+ module Port
7
+ # @since 2.0.1
8
+ # @api private
9
+ DEFAULT = 2300
10
+
11
+ # @since 2.0.1
12
+ # @api private
13
+ ENV_VAR = "HANAMI_PORT"
14
+
15
+ # @since 2.0.1
16
+ # @api private
17
+ def self.call(value, env = ENV.fetch(ENV_VAR, nil))
18
+ return Integer(value) if !value.nil? && !default?(value)
19
+ return Integer(env) unless env.nil?
20
+ return Integer(value) unless value.nil?
21
+
22
+ DEFAULT
23
+ end
24
+
25
+ # @since 2.0.1
26
+ # @api private
27
+ def self.call!(value)
28
+ return if default?(value)
29
+
30
+ ENV[ENV_VAR] = value.to_s
31
+ end
32
+
33
+ # @since 2.0.1
34
+ # @api private
35
+ def self.default?(value)
36
+ value.to_i == DEFAULT
37
+ end
38
+
39
+ class << self
40
+ # @since 2.0.1
41
+ # @api private
42
+ alias_method :[], :call
43
+ end
44
+ end
45
+ end
@@ -15,21 +15,29 @@ module Hanami
15
15
  class Rack < Dry::System::Provider::Source
16
16
  # @api private
17
17
  def prepare
18
- require "dry/monitor"
19
- require "hanami/web/rack_logger"
20
-
21
18
  Dry::Monitor.load_extensions(:rack)
19
+
20
+ # Explicitly register the Rack middleware events on our notifications bus. The Dry::Monitor
21
+ # rack extension (activated above) does register these globally, but if the notifications
22
+ # bus has been used before this provider loads, then it will have created its own separate
23
+ # locally copy of all registered events as of that moment in time, which will not included
24
+ # the Rack events globally reigstered above.
25
+ notifications = target["notifications"]
26
+ notifications.register_event(Dry::Monitor::Rack::Middleware::REQUEST_START)
27
+ notifications.register_event(Dry::Monitor::Rack::Middleware::REQUEST_STOP)
28
+ notifications.register_event(Dry::Monitor::Rack::Middleware::REQUEST_ERROR)
22
29
  end
23
30
 
24
31
  # @api private
25
32
  def start
26
33
  target.start :logger
27
34
 
28
- notifications = target[:notifications]
29
-
30
- monitor_middleware = Dry::Monitor::Rack::Middleware.new(notifications)
35
+ monitor_middleware = Dry::Monitor::Rack::Middleware.new(
36
+ target["notifications"],
37
+ clock: Dry::Monitor::Clock.new(unit: :microsecond)
38
+ )
31
39
 
32
- rack_logger = Hanami::Web::RackLogger.new(target[:logger])
40
+ rack_logger = Hanami::Web::RackLogger.new(target[:logger], env: target.env)
33
41
  rack_logger.attach(monitor_middleware)
34
42
 
35
43
  register "monitor", monitor_middleware
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hanami/cli/rake_tasks"
4
- require "hanami/cli/command_line"
3
+ require "hanami/cli"
5
4
 
6
5
  Hanami::CLI::RakeTasks.register_tasks do
7
- @_hanami_command_line = Hanami::CLI::CommandLine.new
8
-
9
6
  desc "Load the app environment"
10
7
  task :environment do
11
8
  require "hanami/prepare"
@@ -53,8 +50,10 @@ Hanami::CLI::RakeTasks.register_tasks do
53
50
 
54
51
  private
55
52
 
53
+ @_hanami_cli_bundler = Hanami::CLI::Bundler.new
54
+
56
55
  def run_hanami_command(command)
57
- @_hanami_command_line.call(command)
56
+ @_hanami_cli_bundler.exec(command)
58
57
  end
59
58
  end
60
59
 
data/lib/hanami/slice.rb CHANGED
@@ -957,7 +957,9 @@ module Hanami
957
957
  **config.router.options
958
958
  ) do
959
959
  use(rack_monitor)
960
- use(*config.actions.sessions.middleware) if config.actions.sessions.enabled?
960
+ if Hanami.bundled?("hanami-controller")
961
+ use(*config.actions.sessions.middleware) if config.actions.sessions.enabled?
962
+ end
961
963
 
962
964
  middleware_stack.update(config.middleware_stack)
963
965
  end
@@ -7,7 +7,7 @@ module Hanami
7
7
  # @api private
8
8
  module Version
9
9
  # @api public
10
- VERSION = "2.0.0.rc1"
10
+ VERSION = "2.0.1"
11
11
 
12
12
  # @since 0.9.0
13
13
  # @api private