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

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.
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