hanami 2.0.0.alpha8 → 2.0.0.beta1

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 (224) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +442 -241
  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 +5 -5
  9. data/lib/hanami/configuration/actions/cookies.rb +2 -2
  10. data/lib/hanami/configuration/actions.rb +10 -4
  11. data/lib/hanami/configuration/logger.rb +4 -4
  12. data/lib/hanami/configuration/router.rb +2 -6
  13. data/lib/hanami/configuration/sessions.rb +1 -1
  14. data/lib/hanami/configuration/views.rb +9 -4
  15. data/lib/hanami/configuration.rb +118 -46
  16. data/lib/hanami/constants.rb +24 -2
  17. data/lib/hanami/errors.rb +1 -1
  18. data/lib/hanami/{application → extensions}/action/slice_configured_action.rb +9 -9
  19. data/lib/hanami/extensions/action.rb +79 -0
  20. data/lib/hanami/extensions/view/context.rb +106 -0
  21. data/lib/hanami/{application → extensions}/view/slice_configured_context.rb +10 -10
  22. data/lib/hanami/{application → extensions}/view/slice_configured_view.rb +12 -6
  23. data/lib/hanami/extensions/view.rb +33 -0
  24. data/lib/hanami/extensions.rb +10 -0
  25. data/lib/hanami/providers/inflector.rb +13 -0
  26. data/lib/hanami/providers/logger.rb +13 -0
  27. data/lib/hanami/providers/rack.rb +27 -0
  28. data/lib/hanami/providers/routes.rb +33 -0
  29. data/lib/hanami/providers/settings.rb +23 -0
  30. data/lib/hanami/rake_tasks.rb +61 -0
  31. data/lib/hanami/routes.rb +51 -0
  32. data/lib/hanami/server.rb +1 -1
  33. data/lib/hanami/settings/dotenv_store.rb +58 -0
  34. data/lib/hanami/settings.rb +90 -0
  35. data/lib/hanami/setup.rb +4 -2
  36. data/lib/hanami/{application → slice}/router.rb +18 -13
  37. data/lib/hanami/slice/routes_helper.rb +37 -0
  38. data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
  39. data/lib/hanami/slice/routing/resolver.rb +97 -0
  40. data/lib/hanami/{application → slice}/view_name_inferrer.rb +3 -3
  41. data/lib/hanami/slice.rb +246 -73
  42. data/lib/hanami/slice_configurable.rb +4 -17
  43. data/lib/hanami/slice_name.rb +6 -6
  44. data/lib/hanami/slice_registrar.rb +119 -0
  45. data/lib/hanami/version.rb +1 -1
  46. data/lib/hanami/web/rack_logger.rb +1 -1
  47. data/lib/hanami.rb +34 -26
  48. data/spec/integration/application_middleware_stack_spec.rb +84 -0
  49. data/spec/integration/assets/cdn_spec.rb +48 -0
  50. data/spec/integration/assets/fingerprint_spec.rb +42 -0
  51. data/spec/integration/assets/helpers_spec.rb +50 -0
  52. data/spec/integration/assets/serve_spec.rb +70 -0
  53. data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
  54. data/spec/integration/body_parsers_spec.rb +50 -0
  55. data/spec/integration/cli/assets/precompile_spec.rb +147 -0
  56. data/spec/integration/cli/assets_spec.rb +14 -0
  57. data/spec/integration/cli/console_spec.rb +105 -0
  58. data/spec/integration/cli/db/apply_spec.rb +74 -0
  59. data/spec/integration/cli/db/console_spec.rb +40 -0
  60. data/spec/integration/cli/db/create_spec.rb +50 -0
  61. data/spec/integration/cli/db/drop_spec.rb +54 -0
  62. data/spec/integration/cli/db/migrate_spec.rb +108 -0
  63. data/spec/integration/cli/db/prepare_spec.rb +36 -0
  64. data/spec/integration/cli/db/rollback_spec.rb +96 -0
  65. data/spec/integration/cli/db/version_spec.rb +38 -0
  66. data/spec/integration/cli/db_spec.rb +21 -0
  67. data/spec/integration/cli/destroy/action_spec.rb +143 -0
  68. data/spec/integration/cli/destroy/app_spec.rb +118 -0
  69. data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
  70. data/spec/integration/cli/destroy/migration_spec.rb +70 -0
  71. data/spec/integration/cli/destroy/model_spec.rb +113 -0
  72. data/spec/integration/cli/destroy_spec.rb +18 -0
  73. data/spec/integration/cli/generate/action_spec.rb +469 -0
  74. data/spec/integration/cli/generate/app_spec.rb +215 -0
  75. data/spec/integration/cli/generate/mailer_spec.rb +189 -0
  76. data/spec/integration/cli/generate/migration_spec.rb +72 -0
  77. data/spec/integration/cli/generate/model_spec.rb +290 -0
  78. data/spec/integration/cli/generate/secret_spec.rb +56 -0
  79. data/spec/integration/cli/generate_spec.rb +19 -0
  80. data/spec/integration/cli/new/database_spec.rb +235 -0
  81. data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
  82. data/spec/integration/cli/new/template_spec.rb +118 -0
  83. data/spec/integration/cli/new/test_spec.rb +274 -0
  84. data/spec/integration/cli/new_spec.rb +970 -0
  85. data/spec/integration/cli/plugins_spec.rb +39 -0
  86. data/spec/integration/cli/routes_spec.rb +49 -0
  87. data/spec/integration/cli/server_spec.rb +626 -0
  88. data/spec/integration/cli/version_spec.rb +85 -0
  89. data/spec/integration/early_hints_spec.rb +35 -0
  90. data/spec/integration/handle_exceptions_spec.rb +244 -0
  91. data/spec/integration/head_spec.rb +89 -0
  92. data/spec/integration/http_headers_spec.rb +29 -0
  93. data/spec/integration/mailer_spec.rb +32 -0
  94. data/spec/integration/middleware_spec.rb +81 -0
  95. data/spec/integration/mount_applications_spec.rb +88 -0
  96. data/spec/integration/project_initializers_spec.rb +40 -0
  97. data/spec/integration/rackup_spec.rb +35 -0
  98. data/spec/integration/rake/with_minitest_spec.rb +67 -0
  99. data/spec/integration/rake/with_rspec_spec.rb +69 -0
  100. data/spec/integration/routing_helpers_spec.rb +61 -0
  101. data/spec/integration/security/content_security_policy_spec.rb +46 -0
  102. data/spec/integration/security/csrf_protection_spec.rb +42 -0
  103. data/spec/integration/security/force_ssl_spec.rb +29 -0
  104. data/spec/integration/security/x_content_type_options_spec.rb +46 -0
  105. data/spec/integration/security/x_frame_options_spec.rb +46 -0
  106. data/spec/integration/security/x_xss_protection_spec.rb +46 -0
  107. data/spec/integration/send_file_spec.rb +51 -0
  108. data/spec/integration/sessions_spec.rb +247 -0
  109. data/spec/integration/static_middleware_spec.rb +21 -0
  110. data/spec/integration/streaming_spec.rb +41 -0
  111. data/spec/integration/unsafe_send_file_spec.rb +52 -0
  112. data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
  113. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
  114. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
  115. data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
  116. data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
  117. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
  118. data/spec/isolation/hanami/boot/success_spec.rb +50 -0
  119. data/spec/new_integration/action/configuration_spec.rb +26 -0
  120. data/spec/new_integration/action/cookies_spec.rb +58 -0
  121. data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
  122. data/spec/new_integration/action/routes_spec.rb +73 -0
  123. data/spec/new_integration/action/sessions_spec.rb +50 -0
  124. data/spec/new_integration/action/view_integration_spec.rb +165 -0
  125. data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
  126. data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
  127. data/spec/new_integration/action/view_rendering_spec.rb +107 -0
  128. data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
  129. data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
  130. data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
  131. data/spec/new_integration/container/auto_injection_spec.rb +53 -0
  132. data/spec/new_integration/container/auto_registration_spec.rb +86 -0
  133. data/spec/new_integration/container/autoloader_spec.rb +80 -0
  134. data/spec/new_integration/container/imports_spec.rb +253 -0
  135. data/spec/new_integration/container/prepare_container_spec.rb +123 -0
  136. data/spec/new_integration/container/shutdown_spec.rb +91 -0
  137. data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
  138. data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
  139. data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
  140. data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
  141. data/spec/new_integration/settings_spec.rb +115 -0
  142. data/spec/new_integration/slices/external_slice_spec.rb +92 -0
  143. data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
  144. data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
  145. data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
  146. data/spec/new_integration/slices_spec.rb +101 -0
  147. data/spec/new_integration/view/configuration_spec.rb +49 -0
  148. data/spec/new_integration/view/context/assets_spec.rb +67 -0
  149. data/spec/new_integration/view/context/inflector_spec.rb +48 -0
  150. data/spec/new_integration/view/context/request_spec.rb +61 -0
  151. data/spec/new_integration/view/context/routes_spec.rb +86 -0
  152. data/spec/new_integration/view/context/settings_spec.rb +50 -0
  153. data/spec/new_integration/view/inflector_spec.rb +57 -0
  154. data/spec/new_integration/view/part_namespace_spec.rb +96 -0
  155. data/spec/new_integration/view/path_spec.rb +56 -0
  156. data/spec/new_integration/view/template_spec.rb +68 -0
  157. data/spec/new_integration/view/views_spec.rb +103 -0
  158. data/spec/spec_helper.rb +16 -0
  159. data/spec/support/app_integration.rb +91 -0
  160. data/spec/support/coverage.rb +1 -0
  161. data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
  162. data/spec/support/fixtures/hanami-plugin/README.md +35 -0
  163. data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
  164. data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
  165. data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
  166. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
  167. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
  168. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
  169. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
  170. data/spec/support/rspec.rb +27 -0
  171. data/spec/support/shared_examples/cli/generate/app.rb +494 -0
  172. data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
  173. data/spec/support/shared_examples/cli/generate/model.rb +81 -0
  174. data/spec/support/shared_examples/cli/new.rb +97 -0
  175. data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
  176. data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
  177. data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
  178. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
  179. data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
  180. data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
  181. data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
  182. data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
  183. data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
  184. data/spec/unit/hanami/configuration/views_spec.rb +120 -0
  185. data/spec/unit/hanami/configuration_spec.rb +43 -0
  186. data/spec/unit/hanami/env_spec.rb +54 -0
  187. data/spec/unit/hanami/routes_spec.rb +25 -0
  188. data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
  189. data/spec/unit/hanami/settings_spec.rb +56 -0
  190. data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
  191. data/spec/unit/hanami/slice_name_spec.rb +47 -0
  192. data/spec/unit/hanami/slice_spec.rb +17 -0
  193. data/spec/unit/hanami/version_spec.rb +7 -0
  194. data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
  195. metadata +353 -57
  196. data/lib/hanami/application/action.rb +0 -72
  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/view/context.rb +0 -95
  213. data/lib/hanami/application/view.rb +0 -24
  214. data/lib/hanami/application.rb +0 -273
  215. data/lib/hanami/cli/application/cli.rb +0 -40
  216. data/lib/hanami/cli/application/command.rb +0 -47
  217. data/lib/hanami/cli/application/commands/console.rb +0 -81
  218. data/lib/hanami/cli/application/commands.rb +0 -16
  219. data/lib/hanami/cli/base_command.rb +0 -48
  220. data/lib/hanami/cli/commands/command.rb +0 -171
  221. data/lib/hanami/cli/commands/server.rb +0 -88
  222. data/lib/hanami/cli/commands.rb +0 -65
  223. data/lib/hanami/configuration/middleware.rb +0 -20
  224. data/lib/hanami/configuration/source_dirs.rb +0 -42
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- class Application
5
- # Application routes
6
- #
7
- # Users are expected to inherit from this class to define their application
8
- # routes.
9
- #
10
- # @example
11
- # # config/routes.rb
12
- # # frozen_string_literal: true
13
- #
14
- # require "hanami/application/routes"
15
- #
16
- # module MyApp
17
- # class Routes < Hanami::Application::Routes
18
- # define do
19
- # slice :main, at: "/" do
20
- # root to: "home.show"
21
- # end
22
- # end
23
- # end
24
- # end
25
- #
26
- # See {Hanami::Application::Router} for the syntax allowed within the
27
- # `define` block.
28
- #
29
- # @see Hanami::Application::Router
30
- # @since 2.0.0
31
- class Routes
32
- # Defines application routes
33
- #
34
- # @yield DSL syntax to define application routes executed in the context
35
- # of {Hanami::Application::Router}
36
- #
37
- # @return [Proc]
38
- def self.define(&block)
39
- @_routes = block
40
- end
41
-
42
- # @api private
43
- def self.routes
44
- @_routes || raise(<<~MSG)
45
- Routes need to be defined before being able to fetch them. E.g.,
46
- define do
47
- slice :main, at: "/" do
48
- root to: "home.show"
49
- end
50
- end
51
- MSG
52
- end
53
- end
54
- end
55
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- class Application
5
- # Hanami application routes helpers
6
- #
7
- # An instance of this class gets registered in the container
8
- # (`routes_helper` key) once the Hanami application is booted. You can use
9
- # it to get the route helpers for your application.
10
- #
11
- # @example
12
- # MyApp::Application["routes_helper"].path(:root) # => "/"
13
- #
14
- # @see Hanami::Router::UrlHelpers
15
- # @since 2.0.0
16
- class RoutesHelper
17
- # @since 2.0.0
18
- # @api private
19
- def initialize(router)
20
- @router = router
21
- end
22
-
23
- # @see Hanami::Router::UrlHelpers#path
24
- def path(*args, **kwargs, &block)
25
- @router.path(*args, **kwargs, &block)
26
- end
27
-
28
- # @see Hanami::Router::UrlHelpers#url
29
- def url(*args, **kwargs, &block)
30
- @router.url(*args, **kwargs, &block)
31
- end
32
- end
33
- end
34
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- class Application
5
- module Routing
6
- class Resolver
7
- # Endpoint resolver node to register slices in a tree
8
- #
9
- # @api private
10
- # @since 2.0.0
11
- class Node
12
- # @api private
13
- # @since 2.0.0
14
- attr_reader :slice
15
-
16
- # @api private
17
- # @since 2.0.0
18
- def initialize
19
- @slice = nil
20
- @children = {}
21
- end
22
-
23
- # @api private
24
- # @since 2.0.0
25
- def put(segment)
26
- @children[segment] ||= self.class.new
27
- end
28
-
29
- # @api private
30
- # @since 2.0.0
31
- def get(segment)
32
- @children.fetch(segment) { self if leaf? }
33
- end
34
-
35
- # @api private
36
- # @since 2.0.0
37
- def leaf!(slice)
38
- @slice = slice
39
- end
40
-
41
- # @api private
42
- # @since 2.0.0
43
- def leaf?
44
- @slice
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/application/routing/resolver/node"
4
-
5
- module Hanami
6
- class Application
7
- module Routing
8
- class Resolver
9
- # Endpoint resolver trie to register slices
10
- #
11
- # @api private
12
- # @since 2.0.0
13
- class Trie
14
- # @api private
15
- # @since 2.0.0
16
- def initialize
17
- @root = Node.new
18
- end
19
-
20
- # @api private
21
- # @since 2.0.0
22
- def add(path, name)
23
- node = @root
24
- for_each_segment(path) do |segment|
25
- node = node.put(segment)
26
- end
27
-
28
- node.leaf!(name)
29
- end
30
-
31
- # @api private
32
- # @since 2.0.0
33
- def find(path)
34
- node = @root
35
-
36
- for_each_segment(path) do |segment|
37
- break unless node
38
-
39
- node = node.get(segment)
40
- end
41
-
42
- return node.slice if node&.leaf?
43
-
44
- nil
45
- end
46
-
47
- private
48
-
49
- # @api private
50
- # @since 2.0.0
51
- def for_each_segment(path, &blk)
52
- _, *segments = path.split(/\//)
53
- segments.each(&blk)
54
- end
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- class Application
5
- module Routing
6
- # Hanami application router endpoint resolver
7
- #
8
- # @since 2.0.0
9
- class Resolver
10
- ENDPOINT_KEY_NAMESPACE = "actions"
11
-
12
- require_relative "resolver/trie"
13
-
14
- # @since 2.0.0
15
- class NotCallableEndpointError < StandardError
16
- def initialize(endpoint)
17
- super("#{endpoint.inspect} is not compatible with Rack. Please make sure it implements #call.")
18
- end
19
- end
20
-
21
- # @api private
22
- # @since 2.0.0
23
- def initialize(slices:, inflector:)
24
- @slices = slices
25
- @inflector = inflector
26
- @slice_registry = Trie.new
27
- end
28
-
29
- # @api private
30
- # @since 2.0.0
31
- #
32
- # rubocop:disable Metrics/MethodLength
33
- def call(path, identifier)
34
- endpoint =
35
- case identifier
36
- when String
37
- resolve_string_identifier(path, identifier)
38
- when Class
39
- identifier.respond_to?(:call) ? identifier : identifier.new
40
- else
41
- identifier
42
- end
43
-
44
- unless endpoint.respond_to?(:call) # rubocop:disable Style/IfUnlessModifier
45
- raise NotCallableEndpointError.new(endpoint)
46
- end
47
-
48
- endpoint
49
- end
50
- # rubocop:enable Metrics/MethodLength
51
-
52
- # @api private
53
- # @since 2.0.0
54
- def register_slice_at_path(name, path)
55
- slice_registry.add(path, name)
56
- end
57
-
58
- private
59
-
60
- # @api private
61
- # @since 2.0.0
62
- attr_reader :slices
63
-
64
- # @api private
65
- # @since 2.0.0
66
- attr_reader :inflector
67
-
68
- # @api private
69
- # @since 2.0.0
70
- attr_reader :slice_registry
71
-
72
- # @api private
73
- # @since 2.0.0
74
- def resolve_string_identifier(path, identifier)
75
- slice_name = slice_registry.find(path) or raise "missing slice for #{path.inspect} (#{identifier.inspect})"
76
- slice = slices[slice_name]
77
- endpoint_key = "#{ENDPOINT_KEY_NAMESPACE}.#{identifier}"
78
-
79
- # Lazily resolve endpoint from the slice to reduce router initialization time,
80
- # and break potential endless loops from the resolved endpoint itself requiring
81
- # access to router-related concerns
82
- -> (*args) { slice[endpoint_key].call(*args) }
83
- end
84
- end
85
- end
86
- end
87
- end
@@ -1,36 +0,0 @@
1
- # # frozen_string_literal: true
2
-
3
- # require "hanami/application/router"
4
-
5
- # Hanami.application.register_provider :router do
6
- # start do
7
- # configuration = Hanami.application.configuration
8
-
9
- # routes = begin
10
- # require File.join(configuration.root, configuration.router.routes_path)
11
- # routes_class = Hanami.application.send(:autodiscover_application_constant, configuration.router.routes_class_name) # WIP private
12
- # routes_class.routes
13
- # rescue LoadError
14
- # proc {}
15
- # end
16
-
17
- # resolver = configuration.router.resolver.new(
18
- # slices: Hanami.application.slices,
19
- # inflector: Hanami.application.inflector # TODO: use container[:inflector]?
20
- # )
21
-
22
- # router = Hanami::Application::Router.new(
23
- # routes: routes,
24
- # resolver: resolver,
25
- # **configuration.router.options,
26
- # ) do
27
- # use Hanami.application[:rack_monitor]
28
-
29
- # Hanami.application.config.for_each_middleware do |m, *args, &block|
30
- # use(m, *args, &block)
31
- # end
32
- # end
33
-
34
- # register :router, router
35
- # end
36
- # end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dry/core/constants"
4
-
5
- module Hanami
6
- class Application
7
- class Settings
8
- # Default application settings store.
9
- #
10
- # Uses [dotenv](https://github.com/bkeepers/dotenv) (if available) to load
11
- # .env files and then loads settings from ENV. For a given `HANAMI_ENV`
12
- # environment, the following `.env` files are looked up in the following order:
13
- #
14
- # - .env.{environment}.local
15
- # - .env.local (except if the environment is `test`)
16
- # - .env.{environment}
17
- # - .env
18
- #
19
- # @since 2.0.0
20
- # @api private
21
- class DotenvStore
22
- Undefined = Dry::Core::Constants::Undefined
23
-
24
- attr_reader :store,
25
- :hanami_env
26
-
27
- def initialize(store: ENV, hanami_env: Hanami.env)
28
- @store = store
29
- @hanami_env = hanami_env
30
- end
31
-
32
- def fetch(name, default_value = Undefined, &block)
33
- name = name.to_s.upcase
34
- args = (default_value == Undefined) ? [name] : [name, default_value]
35
-
36
- store.fetch(*args, &block)
37
- end
38
-
39
- def with_dotenv_loaded
40
- require "dotenv"
41
- Dotenv.load(*dotenv_files) if defined?(Dotenv)
42
- self
43
- rescue LoadError
44
- self
45
- end
46
-
47
- private
48
-
49
- def dotenv_files
50
- [
51
- ".env.#{hanami_env}.local",
52
- (".env.local" unless hanami_env == :test),
53
- ".env.#{hanami_env}",
54
- ".env"
55
- ].compact
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dry/configurable"
4
- require "dry/core/constants"
5
-
6
- module Hanami
7
- class Application
8
- # Application settings
9
- #
10
- # Users are expected to inherit from this class to define their application
11
- # settings.
12
- #
13
- # @example
14
- # # config/settings.rb
15
- # # frozen_string_literal: true
16
- #
17
- # require "hanami/application/settings"
18
- # require "my_app/types"
19
- #
20
- # module MyApp
21
- # class Settings < Hanami::Application::Settings
22
- # setting :database_url
23
- # setting :feature_flag, default: false, constructor: Types::Params::Bool
24
- # end
25
- # end
26
- #
27
- # Settings are defined with
28
- # [dry-configurable](https://dry-rb.org/gems/dry-configurable/), so you can
29
- # take a look there to see the supported syntax.
30
- #
31
- # Users work with an instance of this class made available within the
32
- # `settings` key in the container. The instance gets its settings populated
33
- # from a configurable store, which defaults to
34
- # {Hanami::Application::Settings::DotenvStore}.
35
- #
36
- # A different store can be set through the `settings_store` Hanami
37
- # configuration option. All it needs to do is implementing a `#fetch` method
38
- # with the same signature as `Hash#fetch`.
39
- #
40
- # @see Hanami::Application::Settings::DotenvStore
41
- # @since 2.0.0
42
- class Settings
43
- # Exception for errors in the definition of settings.
44
- #
45
- # Its message collects all the individual errors that can be raised for
46
- # each setting.
47
- InvalidSettingsError = Class.new(StandardError) do
48
- def initialize(errors)
49
- @errors = errors
50
- end
51
-
52
- def to_s
53
- <<~STR.strip
54
- Could not initialize settings. The following settings were invalid:
55
-
56
- #{@errors.map { |setting, message| "#{setting}: #{message}" }.join("\n")}
57
- STR
58
- end
59
- end
60
-
61
- # @api private
62
- EMPTY_STORE = Dry::Core::Constants::EMPTY_HASH
63
-
64
- include Dry::Configurable
65
-
66
- # @api private
67
- def initialize(store = EMPTY_STORE)
68
- errors = config._settings.map(&:name).reduce({}) do |errs, name|
69
- public_send("#{name}=", store.fetch(name) { Dry::Core::Constants::Undefined })
70
- errs
71
- rescue => e # rubocop:disable Style/RescueStandardError
72
- errs.merge(name => e)
73
- end
74
-
75
- raise InvalidSettingsError, errors if errors.any?
76
- end
77
-
78
- private
79
-
80
- def method_missing(name, *args, &block)
81
- if config.respond_to?(name)
82
- config.send(name, *args, &block)
83
- else
84
- super
85
- end
86
- end
87
-
88
- def respond_to_missing?(name, _include_all = false)
89
- config.respond_to?(name) || super
90
- end
91
- end
92
- end
93
- end
@@ -1,106 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../constants"
4
- require_relative "../slice"
5
-
6
- module Hanami
7
- class Application
8
- # @api private
9
- class SliceRegistrar
10
- attr_reader :application, :slices
11
- private :application, :slices
12
-
13
- def initialize(application)
14
- @application = application
15
- @slices = {}
16
- end
17
-
18
- def register(name, slice_class = nil, &block)
19
- if slices.key?(name.to_sym)
20
- raise SliceLoadError, "Slice '#{name}' is already registered"
21
- end
22
-
23
- # TODO: raise error unless name meets format (i.e. single level depth only)
24
-
25
- slices[name.to_sym] = slice_class || build_slice(name, &block)
26
- end
27
-
28
- def [](name)
29
- slices.fetch(name) do
30
- raise SliceLoadError, "Slice '#{name}' not found"
31
- end
32
- end
33
-
34
- def freeze
35
- slices.freeze
36
- super
37
- end
38
-
39
- def load_slices
40
- slice_configs = Dir[root.join(CONFIG_DIR, "slices", "*#{RB_EXT}")]
41
- .map { |file| File.basename(file, RB_EXT) }
42
-
43
- slice_dirs = Dir[File.join(root, SLICES_DIR, "*")]
44
- .select { |path| File.directory?(path) }
45
- .map { |path| File.basename(path) }
46
-
47
- (slice_dirs + slice_configs).uniq.sort.each do |slice_name|
48
- load_slice(slice_name)
49
- end
50
-
51
- self
52
- end
53
-
54
- def each(&block)
55
- slices.each_value(&block)
56
- end
57
-
58
- def to_a
59
- slices.values
60
- end
61
-
62
- private
63
-
64
- # Attempts to load a slice class defined in `config/slices/[slice_name].rb`, then
65
- # registers the slice with the matching class, if found.
66
- def load_slice(slice_name)
67
- slice_const_name = inflector.camelize(slice_name)
68
- slice_require_path = root.join("config", "slices", slice_name).to_s
69
-
70
- begin
71
- require(slice_require_path)
72
- rescue LoadError => e
73
- raise e unless e.path == slice_require_path
74
- end
75
-
76
- slice_class =
77
- begin
78
- inflector.constantize("#{slice_const_name}::Slice")
79
- rescue NameError # rubocop:disable Lint/SuppressedException
80
- end
81
-
82
- register(slice_name, slice_class)
83
- end
84
-
85
- def build_slice(slice_name, &block)
86
- slice_module =
87
- begin
88
- slice_module_name = inflector.camelize(slice_name.to_s)
89
- inflector.constantize(slice_module_name)
90
- rescue NameError
91
- Object.const_set(inflector.camelize(slice_module_name), Module.new)
92
- end
93
-
94
- slice_module.const_set(:Slice, Class.new(Hanami::Slice, &block))
95
- end
96
-
97
- def root
98
- application.root
99
- end
100
-
101
- def inflector
102
- application.inflector
103
- end
104
- end
105
- end
106
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/view"
4
- require "hanami/view/context"
5
- require_relative "../../errors"
6
- require_relative "../../slice_configurable"
7
- require_relative "slice_configured_context"
8
-
9
- module Hanami
10
- class Application
11
- class View < Hanami::View
12
- # View context for views in Hanami applications.
13
- #
14
- # @api public
15
- # @since 2.0.0
16
- class Context < Hanami::View::Context
17
- extend Hanami::SliceConfigurable
18
-
19
- # @api private
20
- def self.configure_for_slice(slice)
21
- extend SliceConfiguredContext.new(slice)
22
- end
23
-
24
- # @see SliceConfiguredContext#define_new
25
- def initialize(**kwargs)
26
- defaults = {content: {}}
27
-
28
- super(**kwargs, **defaults)
29
- end
30
-
31
- def inflector
32
- _options.fetch(:inflector)
33
- end
34
-
35
- def routes
36
- _options.fetch(:routes)
37
- end
38
-
39
- def settings
40
- _options.fetch(:settings)
41
- end
42
-
43
- def assets
44
- unless _options[:assets]
45
- raise Hanami::ComponentLoadError, "hanami-assets gem is required to access assets"
46
- end
47
-
48
- _options[:assets]
49
- end
50
-
51
- def content_for(key, value = nil, &block)
52
- content = _options[:content]
53
- output = nil
54
-
55
- if block
56
- content[key] = yield
57
- elsif value
58
- content[key] = value
59
- else
60
- output = content[key]
61
- end
62
-
63
- output
64
- end
65
-
66
- def current_path
67
- request.fullpath
68
- end
69
-
70
- def csrf_token
71
- request.session[Hanami::Action::CSRFProtection::CSRF_TOKEN]
72
- end
73
-
74
- def request
75
- _options.fetch(:request)
76
- end
77
-
78
- def session
79
- request.session
80
- end
81
-
82
- def flash
83
- response.flash
84
- end
85
-
86
- private
87
-
88
- # TODO: create `Request#flash` so we no longer need the `response`
89
- def response
90
- _options.fetch(:response)
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/view"
4
- require_relative "../slice_configurable"
5
- require_relative "view/slice_configured_view"
6
-
7
- module Hanami
8
- class Application
9
- # Superclass for views intended for use within an Hanami application.
10
- #
11
- # @see Hanami::View
12
- #
13
- # @api public
14
- # @since 2.0.0
15
- class View < Hanami::View
16
- extend Hanami::SliceConfigurable
17
-
18
- # @api private
19
- def self.configure_for_slice(slice)
20
- extend SliceConfiguredView.new(slice)
21
- end
22
- end
23
- end
24
- end