hanami 2.0.0.alpha7.1 → 2.0.0.beta1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (223) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +457 -237
  3. data/FEATURES.md +30 -9
  4. data/README.md +1 -3
  5. data/hanami.gemspec +21 -11
  6. data/lib/hanami/app.rb +141 -0
  7. data/lib/hanami/assets/application_configuration.rb +10 -4
  8. data/lib/hanami/configuration/actions/content_security_policy.rb +118 -0
  9. data/lib/hanami/configuration/actions/cookies.rb +29 -0
  10. data/lib/hanami/configuration/actions/sessions.rb +46 -0
  11. data/lib/hanami/configuration/actions.rb +23 -12
  12. data/lib/hanami/configuration/logger.rb +13 -10
  13. data/lib/hanami/configuration/router.rb +2 -6
  14. data/lib/hanami/configuration/sessions.rb +1 -1
  15. data/lib/hanami/configuration/views.rb +86 -0
  16. data/lib/hanami/configuration.rb +139 -82
  17. data/lib/hanami/constants.rb +30 -2
  18. data/lib/hanami/errors.rb +4 -1
  19. data/lib/hanami/extensions/action/slice_configured_action.rb +103 -0
  20. data/lib/hanami/extensions/action.rb +79 -0
  21. data/lib/hanami/extensions/view/context.rb +106 -0
  22. data/lib/hanami/extensions/view/slice_configured_context.rb +71 -0
  23. data/lib/hanami/extensions/view/slice_configured_view.rb +107 -0
  24. data/lib/hanami/extensions/view.rb +33 -0
  25. data/lib/hanami/extensions.rb +10 -0
  26. data/lib/hanami/providers/inflector.rb +13 -0
  27. data/lib/hanami/providers/logger.rb +13 -0
  28. data/lib/hanami/providers/rack.rb +27 -0
  29. data/lib/hanami/providers/routes.rb +33 -0
  30. data/lib/hanami/providers/settings.rb +23 -0
  31. data/lib/hanami/rake_tasks.rb +61 -0
  32. data/lib/hanami/routes.rb +51 -0
  33. data/lib/hanami/server.rb +1 -1
  34. data/lib/hanami/settings/dotenv_store.rb +58 -0
  35. data/lib/hanami/settings.rb +90 -0
  36. data/lib/hanami/setup.rb +4 -2
  37. data/lib/hanami/{application → slice}/router.rb +18 -13
  38. data/lib/hanami/slice/routes_helper.rb +37 -0
  39. data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
  40. data/lib/hanami/slice/routing/resolver.rb +97 -0
  41. data/lib/hanami/slice/view_name_inferrer.rb +63 -0
  42. data/lib/hanami/slice.rb +252 -82
  43. data/lib/hanami/slice_configurable.rb +62 -0
  44. data/lib/hanami/slice_name.rb +111 -0
  45. data/lib/hanami/slice_registrar.rb +119 -0
  46. data/lib/hanami/version.rb +1 -1
  47. data/lib/hanami/web/rack_logger.rb +1 -1
  48. data/lib/hanami.rb +34 -26
  49. data/spec/integration/application_middleware_stack_spec.rb +84 -0
  50. data/spec/integration/assets/cdn_spec.rb +48 -0
  51. data/spec/integration/assets/fingerprint_spec.rb +42 -0
  52. data/spec/integration/assets/helpers_spec.rb +50 -0
  53. data/spec/integration/assets/serve_spec.rb +70 -0
  54. data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
  55. data/spec/integration/body_parsers_spec.rb +50 -0
  56. data/spec/integration/cli/assets/precompile_spec.rb +147 -0
  57. data/spec/integration/cli/assets_spec.rb +14 -0
  58. data/spec/integration/cli/console_spec.rb +105 -0
  59. data/spec/integration/cli/db/apply_spec.rb +74 -0
  60. data/spec/integration/cli/db/console_spec.rb +40 -0
  61. data/spec/integration/cli/db/create_spec.rb +50 -0
  62. data/spec/integration/cli/db/drop_spec.rb +54 -0
  63. data/spec/integration/cli/db/migrate_spec.rb +108 -0
  64. data/spec/integration/cli/db/prepare_spec.rb +36 -0
  65. data/spec/integration/cli/db/rollback_spec.rb +96 -0
  66. data/spec/integration/cli/db/version_spec.rb +38 -0
  67. data/spec/integration/cli/db_spec.rb +21 -0
  68. data/spec/integration/cli/destroy/action_spec.rb +143 -0
  69. data/spec/integration/cli/destroy/app_spec.rb +118 -0
  70. data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
  71. data/spec/integration/cli/destroy/migration_spec.rb +70 -0
  72. data/spec/integration/cli/destroy/model_spec.rb +113 -0
  73. data/spec/integration/cli/destroy_spec.rb +18 -0
  74. data/spec/integration/cli/generate/action_spec.rb +469 -0
  75. data/spec/integration/cli/generate/app_spec.rb +215 -0
  76. data/spec/integration/cli/generate/mailer_spec.rb +189 -0
  77. data/spec/integration/cli/generate/migration_spec.rb +72 -0
  78. data/spec/integration/cli/generate/model_spec.rb +290 -0
  79. data/spec/integration/cli/generate/secret_spec.rb +56 -0
  80. data/spec/integration/cli/generate_spec.rb +19 -0
  81. data/spec/integration/cli/new/database_spec.rb +235 -0
  82. data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
  83. data/spec/integration/cli/new/template_spec.rb +118 -0
  84. data/spec/integration/cli/new/test_spec.rb +274 -0
  85. data/spec/integration/cli/new_spec.rb +970 -0
  86. data/spec/integration/cli/plugins_spec.rb +39 -0
  87. data/spec/integration/cli/routes_spec.rb +49 -0
  88. data/spec/integration/cli/server_spec.rb +626 -0
  89. data/spec/integration/cli/version_spec.rb +85 -0
  90. data/spec/integration/early_hints_spec.rb +35 -0
  91. data/spec/integration/handle_exceptions_spec.rb +244 -0
  92. data/spec/integration/head_spec.rb +89 -0
  93. data/spec/integration/http_headers_spec.rb +29 -0
  94. data/spec/integration/mailer_spec.rb +32 -0
  95. data/spec/integration/middleware_spec.rb +81 -0
  96. data/spec/integration/mount_applications_spec.rb +88 -0
  97. data/spec/integration/project_initializers_spec.rb +40 -0
  98. data/spec/integration/rackup_spec.rb +35 -0
  99. data/spec/integration/rake/with_minitest_spec.rb +67 -0
  100. data/spec/integration/rake/with_rspec_spec.rb +69 -0
  101. data/spec/integration/routing_helpers_spec.rb +61 -0
  102. data/spec/integration/security/content_security_policy_spec.rb +46 -0
  103. data/spec/integration/security/csrf_protection_spec.rb +42 -0
  104. data/spec/integration/security/force_ssl_spec.rb +29 -0
  105. data/spec/integration/security/x_content_type_options_spec.rb +46 -0
  106. data/spec/integration/security/x_frame_options_spec.rb +46 -0
  107. data/spec/integration/security/x_xss_protection_spec.rb +46 -0
  108. data/spec/integration/send_file_spec.rb +51 -0
  109. data/spec/integration/sessions_spec.rb +247 -0
  110. data/spec/integration/static_middleware_spec.rb +21 -0
  111. data/spec/integration/streaming_spec.rb +41 -0
  112. data/spec/integration/unsafe_send_file_spec.rb +52 -0
  113. data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
  114. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
  115. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
  116. data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
  117. data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
  118. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
  119. data/spec/isolation/hanami/boot/success_spec.rb +50 -0
  120. data/spec/new_integration/action/configuration_spec.rb +26 -0
  121. data/spec/new_integration/action/cookies_spec.rb +58 -0
  122. data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
  123. data/spec/new_integration/action/routes_spec.rb +73 -0
  124. data/spec/new_integration/action/sessions_spec.rb +50 -0
  125. data/spec/new_integration/action/view_integration_spec.rb +165 -0
  126. data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
  127. data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
  128. data/spec/new_integration/action/view_rendering_spec.rb +107 -0
  129. data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
  130. data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
  131. data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
  132. data/spec/new_integration/container/auto_injection_spec.rb +53 -0
  133. data/spec/new_integration/container/auto_registration_spec.rb +86 -0
  134. data/spec/new_integration/container/autoloader_spec.rb +80 -0
  135. data/spec/new_integration/container/imports_spec.rb +253 -0
  136. data/spec/new_integration/container/prepare_container_spec.rb +123 -0
  137. data/spec/new_integration/container/shutdown_spec.rb +91 -0
  138. data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
  139. data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
  140. data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
  141. data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
  142. data/spec/new_integration/settings_spec.rb +115 -0
  143. data/spec/new_integration/slices/external_slice_spec.rb +92 -0
  144. data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
  145. data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
  146. data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
  147. data/spec/new_integration/slices_spec.rb +101 -0
  148. data/spec/new_integration/view/configuration_spec.rb +49 -0
  149. data/spec/new_integration/view/context/assets_spec.rb +67 -0
  150. data/spec/new_integration/view/context/inflector_spec.rb +48 -0
  151. data/spec/new_integration/view/context/request_spec.rb +61 -0
  152. data/spec/new_integration/view/context/routes_spec.rb +86 -0
  153. data/spec/new_integration/view/context/settings_spec.rb +50 -0
  154. data/spec/new_integration/view/inflector_spec.rb +57 -0
  155. data/spec/new_integration/view/part_namespace_spec.rb +96 -0
  156. data/spec/new_integration/view/path_spec.rb +56 -0
  157. data/spec/new_integration/view/template_spec.rb +68 -0
  158. data/spec/new_integration/view/views_spec.rb +103 -0
  159. data/spec/spec_helper.rb +16 -0
  160. data/spec/support/app_integration.rb +91 -0
  161. data/spec/support/coverage.rb +1 -0
  162. data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
  163. data/spec/support/fixtures/hanami-plugin/README.md +35 -0
  164. data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
  165. data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
  166. data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
  167. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
  168. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
  169. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
  170. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
  171. data/spec/support/rspec.rb +27 -0
  172. data/spec/support/shared_examples/cli/generate/app.rb +494 -0
  173. data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
  174. data/spec/support/shared_examples/cli/generate/model.rb +81 -0
  175. data/spec/support/shared_examples/cli/new.rb +97 -0
  176. data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
  177. data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
  178. data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
  179. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
  180. data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
  181. data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
  182. data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
  183. data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
  184. data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
  185. data/spec/unit/hanami/configuration/views_spec.rb +120 -0
  186. data/spec/unit/hanami/configuration_spec.rb +43 -0
  187. data/spec/unit/hanami/env_spec.rb +54 -0
  188. data/spec/unit/hanami/routes_spec.rb +25 -0
  189. data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
  190. data/spec/unit/hanami/settings_spec.rb +56 -0
  191. data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
  192. data/spec/unit/hanami/slice_name_spec.rb +47 -0
  193. data/spec/unit/hanami/slice_spec.rb +17 -0
  194. data/spec/unit/hanami/version_spec.rb +7 -0
  195. data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
  196. metadata +363 -55
  197. data/lib/hanami/application/container/providers/inflector.rb +0 -7
  198. data/lib/hanami/application/container/providers/logger.rb +0 -7
  199. data/lib/hanami/application/container/providers/rack_logger.rb +0 -15
  200. data/lib/hanami/application/container/providers/rack_monitor.rb +0 -12
  201. data/lib/hanami/application/container/providers/routes_helper.rb +0 -9
  202. data/lib/hanami/application/container/providers/settings.rb +0 -7
  203. data/lib/hanami/application/routes.rb +0 -55
  204. data/lib/hanami/application/routes_helper.rb +0 -34
  205. data/lib/hanami/application/routing/resolver/node.rb +0 -50
  206. data/lib/hanami/application/routing/resolver/trie.rb +0 -59
  207. data/lib/hanami/application/routing/resolver.rb +0 -87
  208. data/lib/hanami/application/routing/router.rb +0 -36
  209. data/lib/hanami/application/settings/dotenv_store.rb +0 -60
  210. data/lib/hanami/application/settings.rb +0 -93
  211. data/lib/hanami/application/slice_registrar.rb +0 -106
  212. data/lib/hanami/application.rb +0 -299
  213. data/lib/hanami/boot/source_dirs.rb +0 -44
  214. data/lib/hanami/cli/application/cli.rb +0 -40
  215. data/lib/hanami/cli/application/command.rb +0 -47
  216. data/lib/hanami/cli/application/commands/console.rb +0 -81
  217. data/lib/hanami/cli/application/commands.rb +0 -16
  218. data/lib/hanami/cli/base_command.rb +0 -48
  219. data/lib/hanami/cli/commands/command.rb +0 -171
  220. data/lib/hanami/cli/commands/server.rb +0 -88
  221. data/lib/hanami/cli/commands.rb +0 -65
  222. data/lib/hanami/configuration/middleware.rb +0 -20
  223. data/lib/hanami/configuration/source_dirs.rb +0 -42
data/FEATURES.md CHANGED
@@ -1,8 +1,29 @@
1
1
  # Hanami
2
+
2
3
  ### The web, with simplicity.
3
4
 
4
5
  ## Features
5
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
+
6
27
  ## v2.0.0.alpha1 - 2019-01-30
7
28
 
8
29
  ## v1.3.3 - 2019-09-20
@@ -110,14 +131,14 @@
110
131
  - Assets preprocessors support (eg. Sass, ES6, Opal, Less, CoffeScript..)
111
132
  - Assets compressors (eg. YUI, UglifyJS2, Google Closure Compiler, Sass..)
112
133
  - Assets helpers:
113
- * `javascript`
114
- * `stylesheet`
115
- * `favicon`
116
- * `image`
117
- * `video`
118
- * `audio`
119
- * `asset_path`
120
- * `asset_url`
134
+ - `javascript`
135
+ - `stylesheet`
136
+ - `favicon`
137
+ - `image`
138
+ - `video`
139
+ - `audio`
140
+ - `asset_path`
141
+ - `asset_url`
121
142
  - Content Delivery Network (CDN) support for static assets (CDN mode)
122
143
  - Checksum suffix for static assets in production mode (Digest mode)
123
144
  - Support for third party gems as assets distribution channel (eg. `lotus-jquery`)
@@ -159,7 +180,7 @@
159
180
  - `Lotus.env` and `Lotus.env?` for current environment introspection (eg. `Lotus.env?(:test)` or `Lotus.env?(:staging, :production)`)
160
181
  - Allow repositories to execute raw query/commands against database
161
182
  - Automatic timestamps update for entities
162
- – Dirty Tracking for entities (via `Lotus::Entity::DirtyTracking`)
183
+ – Dirty Tracking for entities (via `Lotus::Entity::DirtyTracking`)
163
184
  - Nested RESTful resource(s)
164
185
  - String pluralization and singularization
165
186
 
data/README.md CHANGED
@@ -14,10 +14,8 @@ It's made up of smaller, single-purpose libraries.
14
14
  This repository is for the full-stack framework,
15
15
  which provides the glue that ties all the parts together:
16
16
 
17
- * [**Hanami::Model**](https://github.com/hanami/model) - Persistence with entities, repositories and data mapper
18
17
  * [**Hanami::View**](https://github.com/hanami/view) - Presentation with a separation between views and templates
19
18
  * [**Hanami::Controller**](https://github.com/hanami/controller) - Full featured, fast and testable actions for Rack
20
- * [**Hanami::Validations**](https://github.com/hanami/validations) - Validations mixin for Ruby objects
21
19
  * [**Hanami::Router**](https://github.com/hanami/router) - Rack compatible HTTP router for Ruby
22
20
  * [**Hanami::Helpers**](https://github.com/hanami/helpers) - View helpers for Ruby applications
23
21
  * [**Hanami::Mailer**](https://github.com/hanami/mailer) - Mail for Ruby applications
@@ -54,7 +52,7 @@ Please follow along with the [Getting Started guide](https://guides.hanamirb.org
54
52
 
55
53
  ## Donations
56
54
 
57
- You can give back to Open Source, by supporting Hanami development via a [donation](https://salt.bountysource.com/teams/hanami). :green_heart:
55
+ You can give back to Open Source, by supporting Hanami development via [GitHub Sponsors](https://github.com/sponsors/hanami).
58
56
 
59
57
  ### Supporters
60
58
 
data/hanami.gemspec CHANGED
@@ -14,23 +14,33 @@ Gem::Specification.new do |spec|
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") # rubocop:disable Layout/LineLength
18
- spec.test_files = spec.files.grep(%r{^(test)/})
17
+ spec.files = Dir[
18
+ "CODE_OF_CONDUCT.md",
19
+ "CHANGELOG.md",
20
+ "FEATURES.md",
21
+ "LICENSE.md",
22
+ "README.md",
23
+ "hanami.gemspec",
24
+ "lib/**/*"
25
+ ]
26
+
27
+ spec.test_files = Dir["spec/**/*"]
19
28
  spec.require_paths = ["lib"]
20
29
  spec.metadata["rubygems_mfa_required"] = "true"
21
30
  spec.required_ruby_version = ">= 3.0"
22
31
 
23
32
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
24
33
 
25
- spec.add_dependency "bundler", ">= 1.16", "< 3"
26
- spec.add_dependency "dry-configurable", "~> 0.12", ">= 0.12.1"
27
- spec.add_dependency "dry-core", "~> 0.4"
28
- spec.add_dependency "dry-inflector", "~> 0.2", ">= 0.2.1"
29
- spec.add_dependency "dry-monitor"
30
- spec.add_dependency "dry-system", "~> 0.23", ">= 0.23.0"
31
- spec.add_dependency "hanami-cli", "~> 2.0.alpha"
32
- spec.add_dependency "hanami-utils", "~> 2.0.alpha"
33
- spec.add_dependency "zeitwerk", "~> 2.4"
34
+ spec.add_dependency "bundler", ">= 1.16", "< 3"
35
+ spec.add_dependency "dry-configurable", "~> 0.15"
36
+ spec.add_dependency "dry-core", "~> 0.7"
37
+ spec.add_dependency "dry-types", "~> 1.5"
38
+ spec.add_dependency "dry-inflector", "~> 0.2", ">= 0.2.1"
39
+ spec.add_dependency "dry-system", "~> 0.25", ">= 0.25.0"
40
+ spec.add_dependency "dry-monitor", "~> 0.6", ">= 0.6.0"
41
+ spec.add_dependency "hanami-cli", "~> 2.0.beta"
42
+ spec.add_dependency "hanami-utils", "~> 2.0.beta"
43
+ spec.add_dependency "zeitwerk", "~> 2.4"
34
44
 
35
45
  spec.add_development_dependency "rspec", "~> 3.8"
36
46
  spec.add_development_dependency "rack-test", "~> 1.1"
data/lib/hanami/app.rb ADDED
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zeitwerk"
4
+ require_relative "configuration"
5
+ require_relative "constants"
6
+ require_relative "slice"
7
+ require_relative "slice_name"
8
+
9
+ module Hanami
10
+ # The Hanami app is a singular slice tasked with managing the core components of
11
+ # the app and coordinating overall app boot.
12
+ #
13
+ # For smaller apps, the app may be the only slice present, whereas larger apps
14
+ # may consist of many slices, with the app reserved for holding a small number
15
+ # of shared components only.
16
+ #
17
+ # @see Slice
18
+ #
19
+ # @api public
20
+ # @since 2.0.0
21
+ class App < Slice
22
+ @_mutex = Mutex.new
23
+
24
+ def self.inherited(subclass)
25
+ super
26
+
27
+ Hanami.app = subclass
28
+
29
+ subclass.extend(ClassMethods)
30
+
31
+ @_mutex.synchronize do
32
+ subclass.class_eval do
33
+ @configuration = Hanami::Configuration.new(app_name: slice_name, env: Hanami.env)
34
+ @autoloader = Zeitwerk::Loader.new
35
+
36
+ prepare_base_load_path
37
+ end
38
+ end
39
+ end
40
+
41
+ # App class interface
42
+ module ClassMethods
43
+ attr_reader :autoloader, :configuration
44
+
45
+ def app_name
46
+ slice_name
47
+ end
48
+
49
+ private
50
+
51
+ def prepare_base_load_path
52
+ base_path = root.join(LIB_DIR)
53
+ $LOAD_PATH.unshift(base_path) unless $LOAD_PATH.include?(base_path)
54
+ end
55
+
56
+ def prepare_all
57
+ # Make app-wide notifications available as early as possible
58
+ container.use(:notifications)
59
+
60
+ # Ensure all basic slice preparation is complete before we make adjustments below
61
+ # (which rely on the basic prepare steps having already run)
62
+ super
63
+
64
+ # Run specific prepare steps for the app slice. Note also that some
65
+ # standard steps have been skipped via the empty method overrides below.
66
+ prepare_app_component_dirs
67
+ prepare_app_providers
68
+
69
+ # The autoloader must be setup after the container is configured, which is the
70
+ # point at which any component dirs from other slices are added to the autoloader
71
+ app = self
72
+ container.after(:configure) do
73
+ app.send(:prepare_app_autoloader)
74
+ end
75
+ end
76
+
77
+ # Skip standard slice prepare steps that do not apply to the app slice
78
+ def prepare_container_component_dirs; end
79
+ def prepare_container_imports; end
80
+
81
+ # rubocop:disable Metrics/AbcSize
82
+
83
+ def prepare_app_component_dirs
84
+ # Component files in both `app/` and `app/lib/` define classes in the
85
+ # app's namespace
86
+
87
+ if root.join(APP_DIR, LIB_DIR).directory?
88
+ container.config.component_dirs.add(File.join(APP_DIR, LIB_DIR)) do |dir|
89
+ dir.namespaces.add_root(key: nil, const: app_name.name)
90
+ end
91
+ end
92
+
93
+ # When auto-registering components in app/, ignore files in `app/lib/` (these will
94
+ # be auto-registered as above), as well as the configured no_auto_register_paths
95
+ no_auto_register_paths = ([LIB_DIR] + configuration.no_auto_register_paths)
96
+ .map { |path|
97
+ path.end_with?(File::SEPARATOR) ? path : "#{path}#{File::SEPARATOR}"
98
+ }
99
+
100
+ if root.join(APP_DIR).directory?
101
+ container.config.component_dirs.add(APP_DIR) do |dir|
102
+ dir.namespaces.add_root(key: nil, const: app_name.name)
103
+ dir.auto_register = -> component {
104
+ relative_path = component.file_path.relative_path_from(root.join(APP_DIR)).to_s
105
+ !relative_path.start_with?(*no_auto_register_paths)
106
+ }
107
+ end
108
+ end
109
+ end
110
+
111
+ def prepare_app_providers
112
+ require_relative "providers/inflector"
113
+ register_provider(:inflector, source: Hanami::Providers::Inflector)
114
+
115
+ # Allow logger to be replaced by users with a manual provider, for advanced cases
116
+ unless container.providers.find_and_load_provider(:logger)
117
+ require_relative "providers/logger"
118
+ register_provider(:logger, source: Hanami::Providers::Logger)
119
+ end
120
+
121
+ require_relative "providers/rack"
122
+ register_provider(:rack, source: Hanami::Providers::Rack, namespace: true)
123
+ end
124
+
125
+ def prepare_app_autoloader
126
+ # Component dirs are automatically pushed to the autoloader by dry-system's
127
+ # zeitwerk plugin. This method adds other dirs that are not otherwise configured
128
+ # as component dirs.
129
+
130
+ # Autoload classes from `lib/[app_namespace]/`
131
+ if root.join(LIB_DIR, app_name.name).directory?
132
+ autoloader.push_dir(root.join(LIB_DIR, app_name.name), namespace: namespace)
133
+ end
134
+
135
+ autoloader.setup
136
+ end
137
+
138
+ # rubocop:enable Metrics/AbcSize
139
+ end
140
+ end
141
+ end
@@ -10,6 +10,11 @@ module Hanami
10
10
  class ApplicationConfiguration
11
11
  include Dry::Configurable
12
12
 
13
+ # @since 2.0.0
14
+ # @api private
15
+ attr_reader :base_configuration
16
+ protected :base_configuration
17
+
13
18
  setting :server_url, default: "http://localhost:8080"
14
19
 
15
20
  # @since 2.0.0
@@ -20,6 +25,11 @@ module Hanami
20
25
  @base_configuration = Assets::Configuration.new
21
26
  end
22
27
 
28
+ def initialize_copy(source)
29
+ super
30
+ @base_configuration = source.base_configuration.dup
31
+ end
32
+
23
33
  # @since 2.0.0
24
34
  # @api private
25
35
  def finalize!
@@ -37,10 +47,6 @@ module Hanami
37
47
 
38
48
  private
39
49
 
40
- # @since 2.0.0
41
- # @api private
42
- attr_reader :base_configuration
43
-
44
50
  # @since 2.0.0
45
51
  # @api private
46
52
  def method_missing(name, *args, &block)
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ class Configuration
5
+ class Actions
6
+ # Configuration for Content Security Policy in Hanami apps
7
+ #
8
+ # @since 2.0.0
9
+ class ContentSecurityPolicy
10
+ # @since 2.0.0
11
+ # @api private
12
+ def initialize(&blk)
13
+ @policy = {
14
+ base_uri: "'self'",
15
+ child_src: "'self'",
16
+ connect_src: "'self'",
17
+ default_src: "'none'",
18
+ font_src: "'self'",
19
+ form_action: "'self'",
20
+ frame_ancestors: "'self'",
21
+ frame_src: "'self'",
22
+ img_src: "'self' https: data:",
23
+ media_src: "'self'",
24
+ object_src: "'none'",
25
+ plugin_types: "application/pdf",
26
+ script_src: "'self'",
27
+ style_src: "'self' 'unsafe-inline' https:"
28
+ }
29
+
30
+ blk&.(self)
31
+ end
32
+
33
+ # @since 2.0.0
34
+ # @api private
35
+ def initialize_copy(original_object)
36
+ @policy = original_object.instance_variable_get(:@policy).dup
37
+ super
38
+ end
39
+
40
+ # Get a CSP setting
41
+ #
42
+ # @param key [Symbol] the underscored name of the CPS setting
43
+ # @return [String,NilClass] the CSP setting, if any
44
+ #
45
+ # @since 2.0.0
46
+ # @api public
47
+ #
48
+ # @example
49
+ # module MyApp
50
+ # class App < Hanami::App
51
+ # config.actions.content_security_policy[:base_uri] # => "'self'"
52
+ # end
53
+ # end
54
+ def [](key)
55
+ @policy[key]
56
+ end
57
+
58
+ # Set a CSP setting
59
+ #
60
+ # @param key [Symbol] the underscored name of the CPS setting
61
+ # @param value [String] the CSP setting value
62
+ #
63
+ # @since 2.0.0
64
+ # @api public
65
+ #
66
+ # @example Replace a default value
67
+ # module MyApp
68
+ # class App < Hanami::App
69
+ # config.actions.content_security_policy[:plugin_types] = nil
70
+ # end
71
+ # end
72
+ #
73
+ # @example Append to a default value
74
+ # module MyApp
75
+ # class App < Hanami::App
76
+ # config.actions.content_security_policy[:script_src] += " https://my.cdn.test"
77
+ # end
78
+ # end
79
+ def []=(key, value)
80
+ @policy[key] = value
81
+ end
82
+
83
+ # Deletes a CSP key
84
+ #
85
+ # @param key [Symbol] the underscored name of the CPS setting
86
+ #
87
+ # @since 2.0.0
88
+ # @api public
89
+ #
90
+ # @example
91
+ # module MyApp
92
+ # class App < Hanami::App
93
+ # config.actions.content_security_policy.delete(:object_src)
94
+ # end
95
+ # end
96
+ def delete(key)
97
+ @policy.delete(key)
98
+ end
99
+
100
+ # @since 2.0.0
101
+ # @api private
102
+ def to_str
103
+ @policy.map do |key, value|
104
+ "#{dasherize(key)} #{value}"
105
+ end.join(";\n")
106
+ end
107
+
108
+ private
109
+
110
+ # @since 2.0.0
111
+ # @api private
112
+ def dasherize(key)
113
+ key.to_s.gsub("_", "-")
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ class Configuration
5
+ class Actions
6
+ # Wrapper for app-level configuration of HTTP cookies for Hanami actions.
7
+ # This decorates the hash of cookie options that is otherwise directly configurable
8
+ # on actions, and adds the `enabled?` method to allow app base action to
9
+ # determine whether to include the `Action::Cookies` module.
10
+ #
11
+ # @since 2.0.0
12
+ class Cookies
13
+ attr_reader :options
14
+
15
+ def initialize(options)
16
+ @options = options
17
+ end
18
+
19
+ def enabled?
20
+ !options.nil?
21
+ end
22
+
23
+ def to_h
24
+ options.to_h
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/constants"
4
+ require "hanami/utils/string"
5
+ require "hanami/utils/class"
6
+
7
+ module Hanami
8
+ class Configuration
9
+ class Actions
10
+ # Configuration for HTTP sessions in Hanami actions
11
+ #
12
+ # @since 2.0.0
13
+ class Sessions
14
+ attr_reader :storage, :options
15
+
16
+ def initialize(storage = nil, *options)
17
+ @storage = storage
18
+ @options = options
19
+ end
20
+
21
+ def enabled?
22
+ !storage.nil?
23
+ end
24
+
25
+ def middleware
26
+ return [] if !enabled?
27
+
28
+ [[storage_middleware, options]]
29
+ end
30
+
31
+ private
32
+
33
+ def storage_middleware
34
+ require_storage
35
+
36
+ name = Utils::String.classify(storage)
37
+ Utils::Class.load!(name, ::Rack::Session)
38
+ end
39
+
40
+ def require_storage
41
+ require "rack/session/#{storage}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # require_relative "application_configuration/cookies"
4
- # require_relative "application_configuration/sessions"
5
- # require_relative "application_configuration/content_security_policy"
6
- # require_relative "configuration"
7
- # require_relative "view_name_inferrer"
3
+ require "dry/configurable"
4
+ require "hanami/action/configuration"
5
+ require_relative "actions/cookies"
6
+ require_relative "actions/sessions"
7
+ require_relative "actions/content_security_policy"
8
+ require_relative "../slice/view_name_inferrer"
8
9
 
9
10
  module Hanami
10
11
  class Configuration
12
+ # Hanami actions configuration
13
+ #
14
+ # @since 2.0.0
11
15
  class Actions
12
16
  include Dry::Configurable
13
17
 
@@ -16,16 +20,19 @@ module Hanami
16
20
  setting :csrf_protection
17
21
 
18
22
  setting :name_inference_base, default: "actions"
19
- setting :view_context_identifier, default: "view.context"
20
- setting :view_name_inferrer, default: ViewNameInferrer
23
+ setting :view_context_identifier, default: "views.context"
24
+ setting :view_name_inferrer, default: Slice::ViewNameInferrer
21
25
  setting :view_name_inference_base, default: "views"
22
26
 
23
27
  attr_accessor :content_security_policy
24
28
 
29
+ attr_reader :base_configuration
30
+ protected :base_configuration
31
+
25
32
  def initialize(*, **options)
26
33
  super()
27
34
 
28
- @base_configuration = Configuration.new
35
+ @base_configuration = Hanami::Action::Configuration.new
29
36
  @content_security_policy = ContentSecurityPolicy.new do |csp|
30
37
  if assets_server_url = options[:assets_server_url]
31
38
  csp[:script_src] += " #{assets_server_url}"
@@ -36,13 +43,19 @@ module Hanami
36
43
  configure_defaults
37
44
  end
38
45
 
46
+ def initialize_copy(source)
47
+ super
48
+ @base_configuration = source.base_configuration.dup
49
+ @content_security_policy = source.content_security_policy.dup
50
+ end
51
+
39
52
  def finalize!
40
53
  # A nil value for `csrf_protection` means it has not been explicitly configured
41
54
  # (neither true nor false), so we can default it to whether sessions are enabled
42
55
  self.csrf_protection = sessions.enabled? if csrf_protection.nil?
43
56
 
44
- if self.content_security_policy
45
- self.default_headers["Content-Security-Policy"] = self.content_security_policy.to_str
57
+ if content_security_policy
58
+ default_headers["Content-Security-Policy"] = content_security_policy.to_str
46
59
  end
47
60
  end
48
61
 
@@ -58,8 +71,6 @@ module Hanami
58
71
 
59
72
  private
60
73
 
61
- attr_reader :base_configuration
62
-
63
74
  # Apply defaults for base configuration settings
64
75
  def configure_defaults
65
76
  self.default_request_format = :html
@@ -11,9 +11,9 @@ module Hanami
11
11
  class Logger
12
12
  include Dry::Configurable
13
13
 
14
- protected :config
14
+ attr_reader :app_name
15
15
 
16
- setting :application_name
16
+ protected :config
17
17
 
18
18
  setting :level
19
19
 
@@ -29,9 +29,8 @@ module Hanami
29
29
 
30
30
  setting :logger_class, default: Hanami::Logger
31
31
 
32
- def initialize(env:, application_name:)
33
- @env = env
34
- @application_name = application_name
32
+ def initialize(env:, app_name:)
33
+ @app_name = app_name
35
34
 
36
35
  config.level = case env
37
36
  when :production
@@ -58,12 +57,16 @@ module Hanami
58
57
  end
59
58
  end
60
59
 
61
- def finalize!
62
- config.application_name = @application_name.call
63
- end
64
-
65
60
  def instance
66
- logger_class.new(application_name, *options, stream: stream, level: level, formatter: formatter, filter: filters, colorizer: colors)
61
+ logger_class.new(
62
+ app_name.name,
63
+ *options,
64
+ stream: stream,
65
+ level: level,
66
+ formatter: formatter,
67
+ filter: filters,
68
+ colorizer: colors
69
+ )
67
70
  end
68
71
 
69
72
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/configurable"
4
- require_relative "../application/routing/resolver"
4
+ require_relative "../slice/routing/resolver"
5
5
 
6
6
  module Hanami
7
7
  class Configuration
@@ -22,11 +22,7 @@ module Hanami
22
22
  @base_configuration = base_configuration
23
23
  end
24
24
 
25
- setting :routes_path, default: File.join("config", "routes")
26
-
27
- setting :routes_class_name, default: "Routes"
28
-
29
- setting :resolver, default: Application::Routing::Resolver
25
+ setting :resolver, default: Slice::Routing::Resolver
30
26
 
31
27
  # @api private
32
28
  # @since 2.0.0
@@ -30,7 +30,7 @@ module Hanami
30
30
  end
31
31
 
32
32
  def middleware
33
- [[storage_middleware, options]]
33
+ [storage_middleware, options]
34
34
  end
35
35
 
36
36
  private