hanami 2.0.3 → 2.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -2
  3. data/LICENSE.md +1 -1
  4. data/README.md +26 -10
  5. data/hanami.gemspec +2 -2
  6. data/lib/hanami/app.rb +5 -0
  7. data/lib/hanami/config/actions.rb +4 -11
  8. data/lib/hanami/config/assets.rb +84 -0
  9. data/lib/hanami/config/null_config.rb +3 -0
  10. data/lib/hanami/config/views.rb +0 -4
  11. data/lib/hanami/config.rb +71 -5
  12. data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
  13. data/lib/hanami/extensions/action.rb +8 -6
  14. data/lib/hanami/extensions/router/errors.rb +58 -0
  15. data/lib/hanami/extensions/view/context.rb +129 -60
  16. data/lib/hanami/extensions/view/part.rb +26 -0
  17. data/lib/hanami/extensions/view/scope.rb +26 -0
  18. data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
  19. data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
  20. data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
  21. data/lib/hanami/extensions/view/standard_helpers.rb +18 -0
  22. data/lib/hanami/extensions.rb +10 -3
  23. data/lib/hanami/helpers/assets_helper.rb +752 -0
  24. data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
  25. data/lib/hanami/helpers/form_helper/values.rb +75 -0
  26. data/lib/hanami/helpers/form_helper.rb +213 -0
  27. data/lib/hanami/middleware/assets.rb +21 -0
  28. data/lib/hanami/middleware/public_errors_app.rb +75 -0
  29. data/lib/hanami/middleware/render_errors.rb +90 -0
  30. data/lib/hanami/providers/assets.rb +44 -0
  31. data/lib/hanami/rake_tasks.rb +19 -18
  32. data/lib/hanami/settings.rb +1 -1
  33. data/lib/hanami/slice.rb +48 -2
  34. data/lib/hanami/slice_configurable.rb +3 -2
  35. data/lib/hanami/version.rb +1 -1
  36. data/lib/hanami/web/rack_logger.rb +1 -1
  37. data/lib/hanami.rb +3 -3
  38. data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
  39. data/spec/integration/action/view_rendering_spec.rb +0 -18
  40. data/spec/integration/assets/assets_spec.rb +101 -0
  41. data/spec/integration/assets/serve_static_assets_spec.rb +152 -0
  42. data/spec/integration/logging/exception_logging_spec.rb +115 -0
  43. data/spec/integration/logging/notifications_spec.rb +68 -0
  44. data/spec/integration/logging/request_logging_spec.rb +128 -0
  45. data/spec/integration/rack_app/middleware_spec.rb +22 -22
  46. data/spec/integration/rack_app/rack_app_spec.rb +3 -220
  47. data/spec/integration/rake_tasks_spec.rb +107 -0
  48. data/spec/integration/view/config/default_context_spec.rb +149 -0
  49. data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
  50. data/spec/integration/view/config/part_class_spec.rb +147 -0
  51. data/spec/integration/view/config/part_namespace_spec.rb +103 -0
  52. data/spec/integration/view/config/paths_spec.rb +119 -0
  53. data/spec/integration/view/config/scope_class_spec.rb +147 -0
  54. data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
  55. data/spec/integration/view/config/template_spec.rb +38 -0
  56. data/spec/integration/view/context/assets_spec.rb +3 -9
  57. data/spec/integration/view/context/request_spec.rb +3 -7
  58. data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
  59. data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
  60. data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
  61. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
  62. data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
  63. data/spec/integration/view/slice_configuration_spec.rb +9 -9
  64. data/spec/integration/web/render_detailed_errors_spec.rb +107 -0
  65. data/spec/integration/web/render_errors_spec.rb +242 -0
  66. data/spec/spec_helper.rb +1 -1
  67. data/spec/support/app_integration.rb +46 -2
  68. data/spec/support/matchers.rb +32 -0
  69. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +24 -36
  70. data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +4 -3
  71. data/spec/unit/hanami/config/actions/default_values_spec.rb +3 -6
  72. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
  73. data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
  74. data/spec/unit/hanami/config/views_spec.rb +0 -18
  75. data/spec/unit/hanami/env_spec.rb +11 -25
  76. data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
  77. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +109 -0
  78. data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +132 -0
  79. data/spec/unit/hanami/helpers/assets_helper/favicon_link_tag_spec.rb +91 -0
  80. data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +92 -0
  81. data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +143 -0
  82. data/spec/unit/hanami/helpers/assets_helper/stylesheet_link_tag_spec.rb +126 -0
  83. data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +132 -0
  84. data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
  85. data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
  86. data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
  87. data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
  88. data/spec/unit/hanami/version_spec.rb +1 -1
  89. data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
  90. metadata +95 -35
  91. data/lib/hanami/assets/app_config.rb +0 -61
  92. data/lib/hanami/assets/config.rb +0 -53
  93. data/spec/integration/action/view_integration_spec.rb +0 -165
  94. data/spec/integration/view/part_namespace_spec.rb +0 -96
  95. data/spec/integration/view/path_spec.rb +0 -56
  96. data/spec/integration/view/template_spec.rb +0 -68
  97. data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
  98. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
  99. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
  100. data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
  101. data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
  102. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
  103. data/spec/isolation/hanami/boot/success_spec.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e4e96c0b8ba475c9f256fa14b1af20a353804df3f0db3847b814899f7cdd394
4
- data.tar.gz: 8bc463f8095b0bff1ac433fe1869f90e5d7a98e88198546e2fd78ac0caf13639
3
+ metadata.gz: 06d7766d5bdb4f510945a2065cc15457acbf00f43970d691afda74219f0aeb02
4
+ data.tar.gz: 58935ca7f23c3d3612a91b277827ed941c30839d04c9bf577e35a095fa667f6f
5
5
  SHA512:
6
- metadata.gz: 5fc16cc328fc1756b03875d8e6ce6383771b432d85deab7c9fb55c77f9e9a573c0ed449312456c322dd202c0402dd40f5eb126d25b3d6c2b6666e6ff4d9d69c1
7
- data.tar.gz: 903eaccd76b79b10d1ff1197fa6f12d99ce824d41a66be2579549884a9d45d25d3d186fc6f56e33b7badafec427b64da1455443ff674488f2bfb5e3502ca65f4
6
+ metadata.gz: 50a785250f4cf249c5721dd37a5e5a7a240282e5d3820fe848a53c133b1727ea57e5beb351429e636bb4a7d89812bfc53794b5357865b134598a5d54e60666db
7
+ data.tar.gz: 677f40136e0477c57e493e41ed9a25666d9b53d6dd4ae4c23ee6e61d062f9537c39d86eb16d264f194eda4209e5eb0e38fa0554fd3efaf2d39ea23afa1ead27b
data/CHANGELOG.md CHANGED
@@ -2,11 +2,46 @@
2
2
 
3
3
  The web, with simplicity.
4
4
 
5
- ## v2.0.3 - 2023-02-01
5
+ ## v2.1.0.beta2 - 2023-10-04
6
6
 
7
7
  ### Added
8
8
 
9
- - [Luca Guidi] Official support for Ruby 3.2
9
+ - [Luca Guidi, Tim Riley] Reimplement assets integration (#1319, #1332, #1333, #1336)
10
+ - [Tim Riley] Introduce `Hanami::Helpers::AssetsHelper`, automatically included in view templates, scopes and parts when hanami-assets is bundled (#1319)
11
+ - [Tim Riley] Renamed assets helpers (#1319):
12
+ - Removed `#asset_path` in favour of `#asset_url` only
13
+ - Renamed `#javascript` to `#javascript_tag`, retaining `#js` alias
14
+ - Renamed `#stylesheet` to `#stylesheet_link_tag`, retaining `#css` alias
15
+ - Renamed `#image` to `#image_tag`
16
+ - Renamed `#favicon` to `#favicon_link_tag`, with `#favicon` retained as an alias
17
+ - Renamed `#video` to `#video_tag`
18
+ - Renamed `#audio` to `#audio_tag`
19
+
20
+
21
+ ### Fixed
22
+
23
+ - [Tim Riley] Return appropriate response statuses based on error type (#1330)
24
+
25
+ ## v2.1.0.beta1 - 2023-06-29
26
+
27
+ ### Added
28
+
29
+ - [Tim Riley] Introduce `Hanami::View` extensions to use alongside hanami-view v2.1.0.beta1 (#1292)
30
+ - [Tim Riley] Enable standard helpers (from hanami-view) for all view parts and scopes (#1303,
31
+ #1307)
32
+ - [Tim Riley] Add `Hanami::Helpers::FormHelper` and include in all view parts and scopes (#1305,
33
+ #1307)
34
+ - [Tim Riley] Include user defined helpers (at `MyApp::Views::Helpers` or `MySlice::Views::Helpers`)
35
+ in all view parts and scopes (#1307)
36
+ - [Tim Riley] Introduce `Hanami::Middleware::RenderErrors` middleware to render error responses (in HTML or JSON) when errors are raised. For HTML responses, the error pages are expected to be found in `public/{404,500}.html` (#1309)
37
+ - [Tim Riley] Use hanami-webconsole (if bundled) to render detailed error pages in development mode (#1311).
38
+
39
+ ### Fixed
40
+
41
+ - [Tim Riley] Prevent matching incorrect slice names (due to partial matches) in `Hanami::SliceConfigurable`. This ensures appropriate config is applied to actions and views within their respective slices. (#1302)
42
+ - [Masanori Ohnishi] Ensure content-length properly appears in rack logs (#1306)
43
+
44
+ ## v2.0.3 - 2023-02-01
10
45
 
11
46
  ### Fixed
12
47
 
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2014-2021 Luca Guidi
1
+ Copyright © 2014 Hanami Team
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -62,7 +62,7 @@ You can give back to Open Source, by supporting Hanami development via [GitHub S
62
62
  * Guides: https://guides.hanamirb.org
63
63
  * Snippets: https://snippets.hanamirb.org
64
64
  * Mailing List: http://hanamirb.org/mailing-list
65
- * API Doc: http://rdoc.info/gems/hanami
65
+ * API Doc: https://gemdocs.org/gems/hanami/latest
66
66
  * Bugs/Issues: https://github.com/hanami/hanami/issues
67
67
  * Stack Overflow: http://stackoverflow.com/questions/tagged/hanami
68
68
  * Forum: https://discourse.hanamirb.org
@@ -82,26 +82,42 @@ We strive for an inclusive and helpful community. We have a [Code of Conduct](ht
82
82
 
83
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).
84
84
 
85
- ### Development Requirements
85
+ ### Tests
86
86
 
87
- * Ruby >= 3.0
88
- * Bundler
89
- * Node.js (MacOS)
87
+ To run all test suite:
88
+
89
+ ```shell
90
+ $ bundle exec rake
91
+ ```
90
92
 
91
- ### Testing
93
+ To run all the unit tests:
92
94
 
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/`.
95
+ ```shell
96
+ $ bundle exec rspec spec/unit
97
+ ```
94
98
 
95
- **Before running a test, please make sure you have a fresh version of the code:**
99
+ To run all the integration tests:
96
100
 
97
101
  ```shell
98
- bundle exec rspec spec/path/to/file_spec.rb
102
+ $ bundle exec rspec spec/integration
99
103
  ```
100
104
 
105
+ To run a single test:
106
+
107
+ ```shell
108
+ $ bundle exec rspec path/to/spec.rb
109
+ ```
110
+
111
+ ### Development Requirements
112
+
113
+ * Ruby >= 3.0
114
+ * Bundler
115
+ * Node.js (MacOS)
116
+
101
117
  ## Versioning
102
118
 
103
119
  __Hanami__ uses [Semantic Versioning 2.0.0](http://semver.org)
104
120
 
105
121
  ## Copyright
106
122
 
107
- Copyright © 2014-2022 Hanami Team – Released under MIT License.
123
+ Copyright © 2014 Hanami Team – Released under MIT License.
data/hanami.gemspec CHANGED
@@ -38,8 +38,8 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
39
39
  spec.add_dependency "dry-system", "~> 1.0", "< 2"
40
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"
41
+ spec.add_dependency "hanami-cli", "~> 2.1.beta"
42
+ spec.add_dependency "hanami-utils", "~> 2.1.beta"
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
@@ -161,6 +161,11 @@ module Hanami
161
161
  require_relative "providers/rack"
162
162
  register_provider(:rack, source: Hanami::Providers::Rack, namespace: true)
163
163
  end
164
+
165
+ if Hanami.bundled?("hanami-assets")
166
+ require_relative "providers/assets"
167
+ register_provider(:assets, source: Providers::Assets.for_slice(self))
168
+ end
164
169
  end
165
170
 
166
171
  def prepare_autoloader
@@ -82,10 +82,6 @@ module Hanami
82
82
  # @api private
83
83
  setting :name_inference_base, default: "actions"
84
84
 
85
- # @!attribute [rw] view_context_identifier
86
- # @api private
87
- setting :view_context_identifier, default: "views.context"
88
-
89
85
  # @!attribute [rw] view_name_inferrer
90
86
  # @api private
91
87
  setting :view_name_inferrer, default: Slice::ViewNameInferrer
@@ -103,12 +99,7 @@ module Hanami
103
99
  super()
104
100
 
105
101
  @base_config = Hanami::Action.config.dup
106
- @content_security_policy = ContentSecurityPolicy.new do |csp|
107
- if assets_server_url = options[:assets_server_url]
108
- csp[:script_src] += " #{assets_server_url}"
109
- csp[:style_src] += " #{assets_server_url}"
110
- end
111
- end
102
+ @content_security_policy = ContentSecurityPolicy.new
112
103
 
113
104
  configure_defaults
114
105
  end
@@ -122,7 +113,9 @@ module Hanami
122
113
  private :initialize_copy
123
114
 
124
115
  # @api private
125
- def finalize!
116
+ def finalize!(app_config)
117
+ @base_config.root_directory = app_config.root
118
+
126
119
  # A nil value for `csrf_protection` means it has not been explicitly configured
127
120
  # (neither true nor false), so we can default it to whether sessions are enabled
128
121
  self.csrf_protection = sessions.enabled? if csrf_protection.nil?
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/configurable"
4
+ require "hanami/assets"
5
+
6
+ module Hanami
7
+ class Config
8
+ # Hanami assets config
9
+ #
10
+ # This exposes all the settings from the standalone `Hanami::Assets` class, pre-configured with
11
+ # sensible defaults for actions within a full Hanami app. It also provides additional settings
12
+ # for further integration of actions with other full stack app components.
13
+ #
14
+ # @since 2.1.0
15
+ # @api public
16
+ class Assets
17
+ include Dry::Configurable
18
+
19
+ # @!attribute [rw] serve
20
+ # Serve static assets.
21
+ #
22
+ # When this is `true`, the app will serve static assets.
23
+ #
24
+ # If not set, this will:
25
+ #
26
+ # * Check if the `HANAMI_SERVE_ASSETS` environment variable is set to `"true"`.
27
+ # * If not, it will check if the app is running in the `development` or `test` environment.
28
+ #
29
+ # @example
30
+ # config.assets.serve = true
31
+ #
32
+ # @return [Hanami::Config::Actions::Cookies]
33
+ #
34
+ # @api public
35
+ # @since 2.1.0
36
+ setting :serve
37
+
38
+ # @api private
39
+ attr_reader :base_config
40
+ protected :base_config
41
+
42
+ # @api private
43
+ def initialize(*, **options)
44
+ super()
45
+
46
+ @base_config = Hanami::Assets::Config.new(**options)
47
+
48
+ configure_defaults
49
+ end
50
+
51
+ # @api private
52
+ def initialize_copy(source)
53
+ super
54
+ @base_config = source.base_config.dup
55
+ end
56
+ private :initialize_copy
57
+
58
+ private
59
+
60
+ def configure_defaults
61
+ self.serve =
62
+ if ENV.key?("HANAMI_SERVE_ASSETS")
63
+ ENV["HANAMI_SERVE_ASSETS"] == "true"
64
+ else
65
+ Hanami.env?(:development, :test)
66
+ end
67
+ end
68
+
69
+ def method_missing(name, *args, &block)
70
+ if config.respond_to?(name)
71
+ config.public_send(name, *args, &block)
72
+ elsif base_config.respond_to?(name)
73
+ base_config.public_send(name, *args, &block)
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ def respond_to_missing?(name, _incude_all = false)
80
+ config.respond_to?(name) || base_config.respond_to?(name) || super
81
+ end
82
+ end
83
+ end
84
+ end
@@ -9,6 +9,9 @@ module Hanami
9
9
  # loaded)
10
10
  class NullConfig
11
11
  include Dry::Configurable
12
+
13
+ def finalize!(*)
14
+ end
12
15
  end
13
16
  end
14
17
  end
@@ -13,8 +13,6 @@ module Hanami
13
13
  class Views
14
14
  include Dry::Configurable
15
15
 
16
- setting :parts_path, default: "views/parts"
17
-
18
16
  attr_reader :base_config
19
17
  protected :base_config
20
18
 
@@ -46,8 +44,6 @@ module Hanami
46
44
  private
47
45
 
48
46
  def configure_defaults
49
- self.paths = ["templates"]
50
- self.template_inference_base = "views"
51
47
  self.layout = "app"
52
48
  end
53
49
 
data/lib/hanami/config.rb CHANGED
@@ -99,6 +99,7 @@ module Hanami
99
99
  rack.monitor
100
100
  routes
101
101
  settings
102
+ assets
102
103
  ]
103
104
 
104
105
  # @!attribute [rw] no_auto_register_paths
@@ -127,6 +128,58 @@ module Hanami
127
128
  # @since 2.0.0
128
129
  setting :base_url, default: "http://0.0.0.0:2300", constructor: ->(url) { URI(url) }
129
130
 
131
+ # @!attribute [rw] render_errors
132
+ # Sets whether to catch exceptions and render error pages.
133
+ #
134
+ # For HTML responses, these error pages are in `public/{404,500}.html`.
135
+ #
136
+ # Defaults to `true` in production mode, `false` in all others.
137
+ #
138
+ # @return [Boolean]
139
+ #
140
+ # @api public
141
+ # @since 2.1.0
142
+ setting :render_errors, default: false
143
+
144
+ # @!attribute [rw] render_detailed_errors
145
+ # Sets whether to catch exceptions and render detailed, interactive error pages.
146
+ #
147
+ # Requires the hanami-webconsole gem to be available.
148
+ #
149
+ # Defaults to `false` in production mode, `true` in all others.
150
+ #
151
+ # @return [Boolean]
152
+ #
153
+ # @api public
154
+ # @since 2.1.0
155
+ setting :render_detailed_errors, default: false
156
+
157
+ # @!attribute [rw] render_error_responses
158
+ # Sets a mapping of exception class names (as strings) to symbolic response status codes used
159
+ # for rendering error responses.
160
+ #
161
+ # The response status codes will be passed to `Rack::Utils.status_code`.
162
+ #
163
+ # In ordinary usage, you should not replace this hash. Instead, add keys and values for the
164
+ # errors you want handled.
165
+ #
166
+ # @example
167
+ # config.render_error_responses
168
+ # # => {"Hanami::Router::NotFoundError" => :not_found}
169
+ #
170
+ # config.render_error_responses["MyNotFoundError"] = :not_found
171
+ #
172
+ # @return [Hash{String => Symbol}]
173
+ #
174
+ # @see #render_errors
175
+ #
176
+ # @api public
177
+ # @since 2.1.0
178
+ setting :render_error_responses, default: Hash.new(:internal_server_error).merge!(
179
+ "Hanami::Router::NotAllowedError" => :not_found,
180
+ "Hanami::Router::NotFoundError" => :not_found,
181
+ )
182
+
130
183
  # Returns the app or slice's {Hanami::SliceName slice_name}.
131
184
  #
132
185
  # This is useful for default config values that depend on this name.
@@ -211,20 +264,19 @@ module Hanami
211
264
  attr_reader :assets
212
265
 
213
266
  # @api private
267
+ # rubocop:disable Metrics/AbcSize
214
268
  def initialize(app_name:, env:)
215
269
  @app_name = app_name
216
270
  @env = env
217
271
 
218
272
  # Apply default values that are only knowable at initialize-time (vs require-time)
219
273
  self.root = Dir.pwd
274
+ self.render_errors = (env == :production)
275
+ self.render_detailed_errors = (env != :production)
220
276
  load_from_env
221
277
 
222
278
  @logger = Config::Logger.new(env: env, app_name: app_name)
223
279
 
224
- # TODO: Make assets config dependent
225
- require "hanami/assets/app_config"
226
- @assets = Hanami::Assets::AppConfig.new
227
-
228
280
  @actions = load_dependent_config("hanami-controller") {
229
281
  require_relative "config/actions"
230
282
  Actions.new
@@ -241,8 +293,22 @@ module Hanami
241
293
  Views.new
242
294
  }
243
295
 
296
+ @assets = load_dependent_config("hanami-assets") {
297
+ require_relative "config/assets"
298
+
299
+ public_dir = root.join("public")
300
+
301
+ Hanami::Config::Assets.new(
302
+ # TODO: check if `sources` are still needed
303
+ sources: root.join("app", "assets"),
304
+ destination: public_dir.join("assets"),
305
+ manifest_path: public_dir.join("assets.json")
306
+ )
307
+ }
308
+
244
309
  yield self if block_given?
245
310
  end
311
+ # rubocop:enable Metrics/AbcSize
246
312
 
247
313
  # @api private
248
314
  def initialize_copy(source)
@@ -269,7 +335,7 @@ module Hanami
269
335
  def finalize!
270
336
  # Finalize nested configs
271
337
  assets.finalize!
272
- actions.finalize!
338
+ actions.finalize!(self)
273
339
  views.finalize!
274
340
  logger.finalize!
275
341
  router.finalize!
@@ -121,18 +121,26 @@ module Hanami
121
121
  slice: slice,
122
122
  )
123
123
 
124
- view_identifiers.detect do |identifier|
125
- break slice[identifier] if slice.key?(identifier)
124
+ view_identifiers.each do |identifier|
125
+ return slice[identifier] if slice.key?(identifier)
126
126
  end
127
+
128
+ nil
127
129
  end
128
130
 
129
131
  def resolve_view_context
130
- identifier = actions_config.view_context_identifier
132
+ if Hanami.bundled?("hanami-view")
133
+ return Extensions::View::Context.context_class(slice).new
134
+ end
135
+
136
+ # If hanami-view isn't bundled, try and find a possible third party context class with the
137
+ # same `Views::Context` name (but don't fall back to automatically defining one).
138
+ if slice.namespace.const_defined?(:Views)
139
+ views_namespace = slice.namespace.const_get(:Views)
131
140
 
132
- if slice.key?(identifier)
133
- slice[identifier]
134
- elsif slice.app.key?(identifier)
135
- slice.app[identifier]
141
+ if views_namespace.const_defined?(:Context)
142
+ views_namespace.const_get(:Context).new
143
+ end
136
144
  end
137
145
  end
138
146
 
@@ -94,20 +94,22 @@ module Hanami
94
94
  end
95
95
 
96
96
  # @api private
97
- def _handle_exception(request, _response, exception)
97
+ def _handle_exception(request, _response, _exception)
98
+ super
99
+ rescue StandardError => exception
98
100
  rack_monitor&.instrument(:error, exception: exception, env: request.env)
99
101
 
100
- super
102
+ raise
101
103
  end
102
104
 
103
105
  # @api private
104
- def view_options(req, res)
105
- {context: view_context&.with(**view_context_options(req, res))}.compact
106
+ def view_options(request, response)
107
+ {context: view_context&.with(**view_context_options(request, response))}.compact
106
108
  end
107
109
 
108
110
  # @api private
109
- def view_context_options(req, res)
110
- {request: req, response: res}
111
+ def view_context_options(request, response) # rubocop:disable Lint:UnusedMethodArgument
112
+ {request: request}
111
113
  end
112
114
 
113
115
  # Returns true if a view should automatically be rendered onto the response body.
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/router"
4
+
5
+ module Hanami
6
+ class Router
7
+ # Error raised when a request is made for a missing route.
8
+ #
9
+ # Raised only when using hanami-router as part of a full Hanami app. When using hanami-router
10
+ # standalone, the behavior for such requests is to return a "Not Found" response.
11
+ #
12
+ # @api public
13
+ # @since 2.1.0
14
+ class NotFoundError < Hanami::Router::Error
15
+ # @return [Hash] the Rack environment for the request
16
+ #
17
+ # @api public
18
+ # @since 2.1.0
19
+ attr_reader :env
20
+
21
+ def initialize(env)
22
+ @env = env
23
+
24
+ message = "No route found for #{env["REQUEST_METHOD"]} #{env["PATH_INFO"]}"
25
+ super(message)
26
+ end
27
+ end
28
+
29
+ # Error raised when a request is made for a route using a HTTP method not allowed on the route.
30
+ #
31
+ # Raised only when using hanami-router as part of a full Hanami app. When using hanami-router
32
+ # standalone, the behavior for such requests is to return a "Method Not Allowed" response.
33
+ #
34
+ # @api public
35
+ # @since 2.1.0
36
+ class NotAllowedError < Hanami::Router::Error
37
+ # @return [Hash] the Rack environment for the request
38
+ #
39
+ # @api public
40
+ # @since 2.1.0
41
+ attr_reader :env
42
+
43
+ # @return [Array<String>] the allowed methods for the route
44
+ #
45
+ # @api public
46
+ # @since 2.1.0
47
+ attr_reader :allowed_methods
48
+
49
+ def initialize(env, allowed_methods)
50
+ @env = env
51
+ @allowed_methods = allowed_methods
52
+
53
+ message = "Only #{allowed_methods.join(', ')} requests are allowed at #{env["PATH_INFO"]}"
54
+ super(message)
55
+ end
56
+ end
57
+ end
58
+ end