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
@@ -0,0 +1,106 @@
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
+ module Extensions
11
+ module View
12
+ # View context for views in Hanami apps.
13
+ #
14
+ # @api public
15
+ # @since 2.0.0
16
+ module Context
17
+ def self.included(context_class)
18
+ super
19
+
20
+ context_class.extend(Hanami::SliceConfigurable)
21
+ context_class.extend(ClassMethods)
22
+ context_class.prepend(InstanceMethods)
23
+ end
24
+
25
+ module ClassMethods
26
+ def configure_for_slice(slice)
27
+ extend SliceConfiguredContext.new(slice)
28
+ end
29
+ end
30
+
31
+ module InstanceMethods
32
+ # @see SliceConfiguredContext#define_new
33
+ def initialize(**kwargs)
34
+ defaults = {content: {}}
35
+
36
+ super(**kwargs, **defaults)
37
+ end
38
+
39
+ def inflector
40
+ _options.fetch(:inflector)
41
+ end
42
+
43
+ def routes
44
+ _options.fetch(:routes)
45
+ end
46
+
47
+ def settings
48
+ _options.fetch(:settings)
49
+ end
50
+
51
+ def assets
52
+ unless _options[:assets]
53
+ raise Hanami::ComponentLoadError, "hanami-assets gem is required to access assets"
54
+ end
55
+
56
+ _options[:assets]
57
+ end
58
+
59
+ def content_for(key, value = nil, &block)
60
+ content = _options[:content]
61
+ output = nil
62
+
63
+ if block
64
+ content[key] = yield
65
+ elsif value
66
+ content[key] = value
67
+ else
68
+ output = content[key]
69
+ end
70
+
71
+ output
72
+ end
73
+
74
+ def current_path
75
+ request.fullpath
76
+ end
77
+
78
+ def csrf_token
79
+ request.session[Hanami::Action::CSRFProtection::CSRF_TOKEN]
80
+ end
81
+
82
+ def request
83
+ _options.fetch(:request)
84
+ end
85
+
86
+ def session
87
+ request.session
88
+ end
89
+
90
+ def flash
91
+ response.flash
92
+ end
93
+
94
+ private
95
+
96
+ # TODO: create `Request#flash` so we no longer need the `response`
97
+ def response
98
+ _options.fetch(:response)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ Hanami::View::Context.include(Hanami::Extensions::View::Context)
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/view"
4
+
5
+ module Hanami
6
+ module Extensions
7
+ module View
8
+ # Provides slice-specific configuration and behavior for any view context class
9
+ # defined within a slice's module namespace.
10
+ #
11
+ # @api private
12
+ # @since 2.0.0
13
+ class SliceConfiguredContext < Module
14
+ attr_reader :slice
15
+
16
+ def initialize(slice)
17
+ super()
18
+ @slice = slice
19
+ end
20
+
21
+ def extended(_context_class)
22
+ define_new
23
+ end
24
+
25
+ def inspect
26
+ "#<#{self.class.name}[#{slice.name}]>"
27
+ end
28
+
29
+ private
30
+
31
+ # Defines a {.new} method on the context class that resolves key components from
32
+ # the app container and provides them to {#initialize} as injected
33
+ # dependencies.
34
+ #
35
+ # This includes the following app components:
36
+ #
37
+ # - the configured inflector as `inflector`
38
+ # - "settings" from the app container as `settings`
39
+ # - "routes" from the app container as `routes`
40
+ # - "assets" from the app container as `assets`
41
+ def define_new
42
+ inflector = slice.inflector
43
+ resolve_settings = method(:resolve_settings)
44
+ resolve_routes = method(:resolve_routes)
45
+ resolve_assets = method(:resolve_assets)
46
+
47
+ define_method :new do |**kwargs|
48
+ kwargs[:inflector] ||= inflector
49
+ kwargs[:settings] ||= resolve_settings.()
50
+ kwargs[:routes] ||= resolve_routes.()
51
+ kwargs[:assets] ||= resolve_assets.()
52
+
53
+ super(**kwargs)
54
+ end
55
+ end
56
+
57
+ def resolve_settings
58
+ slice["settings"] if slice.key?("settings")
59
+ end
60
+
61
+ def resolve_routes
62
+ slice["routes"] if slice.key?("routes")
63
+ end
64
+
65
+ def resolve_assets
66
+ slice["assets"] if slice.key?("assets")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/view"
4
+
5
+ module Hanami
6
+ module Extensions
7
+ module View
8
+ # Provides slice-specific configuration and behavior for any view class defined
9
+ # within a slice's module namespace.
10
+ #
11
+ # @api private
12
+ # @since 2.0.0
13
+ class SliceConfiguredView < Module
14
+ attr_reader :slice
15
+
16
+ def initialize(slice)
17
+ super()
18
+ @slice = slice
19
+ end
20
+
21
+ def extended(view_class)
22
+ configure_view(view_class)
23
+ define_inherited
24
+ end
25
+
26
+ def inspect
27
+ "#<#{self.class.name}[#{slice.name}]>"
28
+ end
29
+
30
+ private
31
+
32
+ # rubocop:disable Metrics/AbcSize
33
+ def configure_view(view_class)
34
+ view_class.settings.each do |setting|
35
+ if slice.config.views.respond_to?(:"#{setting}")
36
+ view_class.config.public_send(
37
+ :"#{setting}=",
38
+ slice.config.views.public_send(:"#{setting}")
39
+ )
40
+ end
41
+ end
42
+
43
+ view_class.config.inflector = inflector
44
+ view_class.config.paths = prepare_paths(slice, view_class.config.paths)
45
+ view_class.config.template = template_name(view_class)
46
+
47
+ if (part_namespace = namespace_from_path(slice.config.views.parts_path))
48
+ view_class.config.part_namespace = part_namespace
49
+ end
50
+ end
51
+ # rubocop:enable Metrics/AbcSize
52
+
53
+ def define_inherited
54
+ template_name = method(:template_name)
55
+
56
+ define_method(:inherited) do |subclass|
57
+ super(subclass)
58
+ subclass.config.template = template_name.(subclass)
59
+ end
60
+ end
61
+
62
+ def prepare_paths(slice, configured_paths)
63
+ configured_paths.map { |path|
64
+ if path.dir.relative?
65
+ if slice.app.equal?(slice)
66
+ # App-level templates are in app/
67
+ slice.root.join(APP_DIR, path.dir)
68
+ else
69
+ # Other slice templates are in the root slice dir
70
+ slice.root.join(path.dir)
71
+ end
72
+ else
73
+ path
74
+ end
75
+ }
76
+ end
77
+
78
+ def namespace_from_path(path)
79
+ path = "#{slice.slice_name.path}/#{path}"
80
+
81
+ begin
82
+ require path
83
+ rescue LoadError => exception
84
+ raise exception unless exception.path == path
85
+ end
86
+
87
+ begin
88
+ inflector.constantize(inflector.camelize(path))
89
+ rescue NameError => exception
90
+ end
91
+ end
92
+
93
+ def template_name(view_class)
94
+ slice
95
+ .inflector
96
+ .underscore(view_class.name)
97
+ .sub(/^#{slice.slice_name.path}\//, "")
98
+ .sub(/^#{view_class.config.template_inference_base}\//, "")
99
+ end
100
+
101
+ def inflector
102
+ slice.inflector
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,33 @@
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
+ module Extensions
9
+ # Extended behavior for actions intended for use within an Hanami app.
10
+ #
11
+ # @see Hanami::View
12
+ #
13
+ # @api public
14
+ # @since 2.0.0
15
+ module View
16
+ def self.included(view_class)
17
+ super
18
+
19
+ view_class.extend(Hanami::SliceConfigurable)
20
+ view_class.extend(ClassMethods)
21
+ end
22
+
23
+ module ClassMethods
24
+ # @api private
25
+ def configure_for_slice(slice)
26
+ extend SliceConfiguredView.new(slice)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ Hanami::View.include(Hanami::Extensions::View)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ if Hanami.bundled?("hanami-controller")
4
+ require_relative "./extensions/action"
5
+ end
6
+
7
+ if Hanami.bundled?("hanami-view")
8
+ require_relative "./extensions/view"
9
+ require_relative "./extensions/view/context"
10
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/provider/source"
4
+
5
+ module Hanami
6
+ module Providers
7
+ class Inflector < Dry::System::Provider::Source
8
+ def start
9
+ register :inflector, Hanami.app.inflector
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/provider/source"
4
+
5
+ module Hanami
6
+ module Providers
7
+ class Logger < Dry::System::Provider::Source
8
+ def start
9
+ register :logger, Hanami.app.configuration.logger_instance
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/provider/source"
4
+
5
+ module Hanami
6
+ module Providers
7
+ class Rack < Dry::System::Provider::Source
8
+ def prepare
9
+ require "dry/monitor"
10
+ require "hanami/web/rack_logger"
11
+ end
12
+
13
+ def start
14
+ target.start :logger
15
+
16
+ notifications = target[:notifications]
17
+
18
+ monitor_middleware = Dry::Monitor::Rack::Middleware.new(notifications)
19
+
20
+ rack_logger = Hanami::Web::RackLogger.new(target[:logger])
21
+ rack_logger.attach(monitor_middleware)
22
+
23
+ register "monitor", monitor_middleware
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/provider/source"
4
+
5
+ module Hanami
6
+ module Providers
7
+ class Routes < Dry::System::Provider::Source
8
+ def self.for_slice(slice)
9
+ Class.new(self) do |klass|
10
+ klass.instance_variable_set(:@slice, slice)
11
+ end
12
+ end
13
+
14
+ def self.slice
15
+ @slice || Hanami.app
16
+ end
17
+
18
+ def prepare
19
+ require "hanami/slice/routes_helper"
20
+ end
21
+
22
+ def start
23
+ # Register a lazy instance of RoutesHelper to ensure we don't load prematurely
24
+ # load the router during the process of booting. This ensures the router's
25
+ # resolver can run strict action key checks once when it runs on a fully booted
26
+ # slice.
27
+ register :routes do
28
+ Hanami::Slice::RoutesHelper.new(self.class.slice.router)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/provider/source"
4
+
5
+ module Hanami
6
+ module Providers
7
+ class Settings < Dry::System::Provider::Source
8
+ def self.for_slice(slice)
9
+ Class.new(self) do |klass|
10
+ klass.instance_variable_set(:@slice, slice)
11
+ end
12
+ end
13
+
14
+ def self.slice
15
+ @slice || Hanami.app
16
+ end
17
+
18
+ def start
19
+ register :settings, self.class.slice.settings
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/cli/rake_tasks"
4
+ require "hanami/cli/command_line"
5
+
6
+ Hanami::CLI::RakeTasks.register_tasks do
7
+ @_hanami_command_line = Hanami::CLI::CommandLine.new
8
+
9
+ desc "Load the app environment"
10
+ task :environment do
11
+ require "hanami/prepare"
12
+ end
13
+
14
+ # Ruby ecosystem compatibility
15
+ #
16
+ # Most of the SaaS automatic tasks are designed after Ruby on Rails.
17
+ # They expect the following Rake tasks to be present:
18
+ #
19
+ # * db:migrate
20
+ # * assets:precompile
21
+ #
22
+ # See https://github.com/heroku/heroku-buildpack-ruby/issues/442
23
+ #
24
+ # ===
25
+ #
26
+ # These Rake tasks aren't listed when someone runs `rake -T`, because we
27
+ # want to encourage developers to use `hanami` commands.
28
+ #
29
+ # In order to migrate the database or precompile assets a developer should
30
+ # use:
31
+ #
32
+ # * hanami db migrate
33
+ # * hanami assets precompile
34
+ #
35
+ # This is the preferred way to run Hanami command line tasks.
36
+ # Please use them when you're in control of your deployment environment.
37
+ #
38
+ # If you're not in control and your deployment requires these "standard"
39
+ # Rake tasks, they are here to solve this only specific problem.
40
+ namespace :db do
41
+ task :migrate do
42
+ # TODO(@jodosha): Enable when we'll integrate with ROM
43
+ # run_hanami_command("db migrate")
44
+ end
45
+ end
46
+
47
+ namespace :assets do
48
+ task :precompile do
49
+ # TODO(@jodosha): Enable when we'll integrate with hanami-assets
50
+ # run_hanami_command("assets precompile")
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def run_hanami_command(command)
57
+ @_hanami_command_line.call(command)
58
+ end
59
+ end
60
+
61
+ Hanami::CLI::RakeTasks.install_tasks
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ # App routes
5
+ #
6
+ # Users are expected to inherit from this class to define their app
7
+ # routes.
8
+ #
9
+ # @example
10
+ # # config/routes.rb
11
+ # # frozen_string_literal: true
12
+ #
13
+ # require "hanami/routes"
14
+ #
15
+ # module MyApp
16
+ # class Routes < Hanami::Routes
17
+ # define do
18
+ # root to: "home.show"
19
+ # end
20
+ # end
21
+ # end
22
+ #
23
+ # See {Hanami::Slice::Router} for the syntax allowed within the
24
+ # `define` block.
25
+ #
26
+ # @see Hanami::Slice::Router
27
+ # @since 2.0.0
28
+ class Routes
29
+ # Defines app routes
30
+ #
31
+ # @yield DSL syntax to define app routes executed in the context
32
+ # of {Hanami::Slice::Router}
33
+ #
34
+ # @return [Proc]
35
+ def self.define(&block)
36
+ @_routes = block
37
+ end
38
+
39
+ # @api private
40
+ def self.routes
41
+ @_routes || raise(<<~MSG)
42
+ Routes need to be defined before being able to fetch them. E.g.,
43
+ define do
44
+ slice :main, at: "/" do
45
+ root to: "home.show"
46
+ end
47
+ end
48
+ MSG
49
+ end
50
+ end
51
+ end
data/lib/hanami/server.rb CHANGED
@@ -10,7 +10,7 @@ module Hanami
10
10
  #
11
11
  # `bundle exec hanami server`
12
12
  #
13
- # It runs the application, by using the server specified in your `Gemfile`
13
+ # It runs the app, by using the server specified in your `Gemfile`
14
14
  # (eg. Puma or Unicorn).
15
15
  #
16
16
  # @since 0.8.0
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/constants"
4
+
5
+ module Hanami
6
+ class Settings
7
+ # Default app settings store.
8
+ #
9
+ # Uses [dotenv](https://github.com/bkeepers/dotenv) (if available) to load
10
+ # .env files and then loads settings from ENV. For a given `HANAMI_ENV`
11
+ # environment, the following `.env` files are looked up in the following order:
12
+ #
13
+ # - .env.{environment}.local
14
+ # - .env.local (except if the environment is `test`)
15
+ # - .env.{environment}
16
+ # - .env
17
+ #
18
+ # @since 2.0.0
19
+ # @api private
20
+ class DotenvStore
21
+ Undefined = Dry::Core::Constants::Undefined
22
+
23
+ attr_reader :store,
24
+ :hanami_env
25
+
26
+ def initialize(store: ENV, hanami_env: Hanami.env)
27
+ @store = store
28
+ @hanami_env = hanami_env
29
+ end
30
+
31
+ def fetch(name, default_value = Undefined, &block)
32
+ name = name.to_s.upcase
33
+ args = (default_value == Undefined) ? [name] : [name, default_value]
34
+
35
+ store.fetch(*args, &block)
36
+ end
37
+
38
+ def with_dotenv_loaded
39
+ require "dotenv"
40
+ Dotenv.load(*dotenv_files) if defined?(Dotenv)
41
+ self
42
+ rescue LoadError
43
+ self
44
+ end
45
+
46
+ private
47
+
48
+ def dotenv_files
49
+ [
50
+ ".env.#{hanami_env}.local",
51
+ (".env.local" unless hanami_env == :test),
52
+ ".env.#{hanami_env}",
53
+ ".env"
54
+ ].compact
55
+ end
56
+ end
57
+ end
58
+ end