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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +442 -241
- data/FEATURES.md +30 -9
- data/README.md +1 -3
- data/hanami.gemspec +21 -11
- data/lib/hanami/app.rb +141 -0
- data/lib/hanami/assets/application_configuration.rb +10 -4
- data/lib/hanami/configuration/actions/content_security_policy.rb +5 -5
- data/lib/hanami/configuration/actions/cookies.rb +2 -2
- data/lib/hanami/configuration/actions.rb +10 -4
- data/lib/hanami/configuration/logger.rb +4 -4
- data/lib/hanami/configuration/router.rb +2 -6
- data/lib/hanami/configuration/sessions.rb +1 -1
- data/lib/hanami/configuration/views.rb +9 -4
- data/lib/hanami/configuration.rb +118 -46
- data/lib/hanami/constants.rb +24 -2
- data/lib/hanami/errors.rb +1 -1
- data/lib/hanami/{application → extensions}/action/slice_configured_action.rb +9 -9
- data/lib/hanami/extensions/action.rb +79 -0
- data/lib/hanami/extensions/view/context.rb +106 -0
- data/lib/hanami/{application → extensions}/view/slice_configured_context.rb +10 -10
- data/lib/hanami/{application → extensions}/view/slice_configured_view.rb +12 -6
- data/lib/hanami/extensions/view.rb +33 -0
- data/lib/hanami/extensions.rb +10 -0
- data/lib/hanami/providers/inflector.rb +13 -0
- data/lib/hanami/providers/logger.rb +13 -0
- data/lib/hanami/providers/rack.rb +27 -0
- data/lib/hanami/providers/routes.rb +33 -0
- data/lib/hanami/providers/settings.rb +23 -0
- data/lib/hanami/rake_tasks.rb +61 -0
- data/lib/hanami/routes.rb +51 -0
- data/lib/hanami/server.rb +1 -1
- data/lib/hanami/settings/dotenv_store.rb +58 -0
- data/lib/hanami/settings.rb +90 -0
- data/lib/hanami/setup.rb +4 -2
- data/lib/hanami/{application → slice}/router.rb +18 -13
- data/lib/hanami/slice/routes_helper.rb +37 -0
- data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
- data/lib/hanami/slice/routing/resolver.rb +97 -0
- data/lib/hanami/{application → slice}/view_name_inferrer.rb +3 -3
- data/lib/hanami/slice.rb +246 -73
- data/lib/hanami/slice_configurable.rb +4 -17
- data/lib/hanami/slice_name.rb +6 -6
- data/lib/hanami/slice_registrar.rb +119 -0
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +1 -1
- data/lib/hanami.rb +34 -26
- data/spec/integration/application_middleware_stack_spec.rb +84 -0
- data/spec/integration/assets/cdn_spec.rb +48 -0
- data/spec/integration/assets/fingerprint_spec.rb +42 -0
- data/spec/integration/assets/helpers_spec.rb +50 -0
- data/spec/integration/assets/serve_spec.rb +70 -0
- data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
- data/spec/integration/body_parsers_spec.rb +50 -0
- data/spec/integration/cli/assets/precompile_spec.rb +147 -0
- data/spec/integration/cli/assets_spec.rb +14 -0
- data/spec/integration/cli/console_spec.rb +105 -0
- data/spec/integration/cli/db/apply_spec.rb +74 -0
- data/spec/integration/cli/db/console_spec.rb +40 -0
- data/spec/integration/cli/db/create_spec.rb +50 -0
- data/spec/integration/cli/db/drop_spec.rb +54 -0
- data/spec/integration/cli/db/migrate_spec.rb +108 -0
- data/spec/integration/cli/db/prepare_spec.rb +36 -0
- data/spec/integration/cli/db/rollback_spec.rb +96 -0
- data/spec/integration/cli/db/version_spec.rb +38 -0
- data/spec/integration/cli/db_spec.rb +21 -0
- data/spec/integration/cli/destroy/action_spec.rb +143 -0
- data/spec/integration/cli/destroy/app_spec.rb +118 -0
- data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
- data/spec/integration/cli/destroy/migration_spec.rb +70 -0
- data/spec/integration/cli/destroy/model_spec.rb +113 -0
- data/spec/integration/cli/destroy_spec.rb +18 -0
- data/spec/integration/cli/generate/action_spec.rb +469 -0
- data/spec/integration/cli/generate/app_spec.rb +215 -0
- data/spec/integration/cli/generate/mailer_spec.rb +189 -0
- data/spec/integration/cli/generate/migration_spec.rb +72 -0
- data/spec/integration/cli/generate/model_spec.rb +290 -0
- data/spec/integration/cli/generate/secret_spec.rb +56 -0
- data/spec/integration/cli/generate_spec.rb +19 -0
- data/spec/integration/cli/new/database_spec.rb +235 -0
- data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
- data/spec/integration/cli/new/template_spec.rb +118 -0
- data/spec/integration/cli/new/test_spec.rb +274 -0
- data/spec/integration/cli/new_spec.rb +970 -0
- data/spec/integration/cli/plugins_spec.rb +39 -0
- data/spec/integration/cli/routes_spec.rb +49 -0
- data/spec/integration/cli/server_spec.rb +626 -0
- data/spec/integration/cli/version_spec.rb +85 -0
- data/spec/integration/early_hints_spec.rb +35 -0
- data/spec/integration/handle_exceptions_spec.rb +244 -0
- data/spec/integration/head_spec.rb +89 -0
- data/spec/integration/http_headers_spec.rb +29 -0
- data/spec/integration/mailer_spec.rb +32 -0
- data/spec/integration/middleware_spec.rb +81 -0
- data/spec/integration/mount_applications_spec.rb +88 -0
- data/spec/integration/project_initializers_spec.rb +40 -0
- data/spec/integration/rackup_spec.rb +35 -0
- data/spec/integration/rake/with_minitest_spec.rb +67 -0
- data/spec/integration/rake/with_rspec_spec.rb +69 -0
- data/spec/integration/routing_helpers_spec.rb +61 -0
- data/spec/integration/security/content_security_policy_spec.rb +46 -0
- data/spec/integration/security/csrf_protection_spec.rb +42 -0
- data/spec/integration/security/force_ssl_spec.rb +29 -0
- data/spec/integration/security/x_content_type_options_spec.rb +46 -0
- data/spec/integration/security/x_frame_options_spec.rb +46 -0
- data/spec/integration/security/x_xss_protection_spec.rb +46 -0
- data/spec/integration/send_file_spec.rb +51 -0
- data/spec/integration/sessions_spec.rb +247 -0
- data/spec/integration/static_middleware_spec.rb +21 -0
- data/spec/integration/streaming_spec.rb +41 -0
- data/spec/integration/unsafe_send_file_spec.rb +52 -0
- data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
- data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
- data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
- data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
- data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
- data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
- data/spec/isolation/hanami/boot/success_spec.rb +50 -0
- data/spec/new_integration/action/configuration_spec.rb +26 -0
- data/spec/new_integration/action/cookies_spec.rb +58 -0
- data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
- data/spec/new_integration/action/routes_spec.rb +73 -0
- data/spec/new_integration/action/sessions_spec.rb +50 -0
- data/spec/new_integration/action/view_integration_spec.rb +165 -0
- data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
- data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
- data/spec/new_integration/action/view_rendering_spec.rb +107 -0
- data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
- data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
- data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
- data/spec/new_integration/container/auto_injection_spec.rb +53 -0
- data/spec/new_integration/container/auto_registration_spec.rb +86 -0
- data/spec/new_integration/container/autoloader_spec.rb +80 -0
- data/spec/new_integration/container/imports_spec.rb +253 -0
- data/spec/new_integration/container/prepare_container_spec.rb +123 -0
- data/spec/new_integration/container/shutdown_spec.rb +91 -0
- data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
- data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
- data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
- data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
- data/spec/new_integration/settings_spec.rb +115 -0
- data/spec/new_integration/slices/external_slice_spec.rb +92 -0
- data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
- data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
- data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
- data/spec/new_integration/slices_spec.rb +101 -0
- data/spec/new_integration/view/configuration_spec.rb +49 -0
- data/spec/new_integration/view/context/assets_spec.rb +67 -0
- data/spec/new_integration/view/context/inflector_spec.rb +48 -0
- data/spec/new_integration/view/context/request_spec.rb +61 -0
- data/spec/new_integration/view/context/routes_spec.rb +86 -0
- data/spec/new_integration/view/context/settings_spec.rb +50 -0
- data/spec/new_integration/view/inflector_spec.rb +57 -0
- data/spec/new_integration/view/part_namespace_spec.rb +96 -0
- data/spec/new_integration/view/path_spec.rb +56 -0
- data/spec/new_integration/view/template_spec.rb +68 -0
- data/spec/new_integration/view/views_spec.rb +103 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/app_integration.rb +91 -0
- data/spec/support/coverage.rb +1 -0
- data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
- data/spec/support/fixtures/hanami-plugin/README.md +35 -0
- data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
- data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
- data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
- data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
- data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
- data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
- data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
- data/spec/support/rspec.rb +27 -0
- data/spec/support/shared_examples/cli/generate/app.rb +494 -0
- data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
- data/spec/support/shared_examples/cli/generate/model.rb +81 -0
- data/spec/support/shared_examples/cli/new.rb +97 -0
- data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
- data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
- data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
- data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
- data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
- data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
- data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
- data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
- data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
- data/spec/unit/hanami/configuration/views_spec.rb +120 -0
- data/spec/unit/hanami/configuration_spec.rb +43 -0
- data/spec/unit/hanami/env_spec.rb +54 -0
- data/spec/unit/hanami/routes_spec.rb +25 -0
- data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
- data/spec/unit/hanami/settings_spec.rb +56 -0
- data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
- data/spec/unit/hanami/slice_name_spec.rb +47 -0
- data/spec/unit/hanami/slice_spec.rb +17 -0
- data/spec/unit/hanami/version_spec.rb +7 -0
- data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
- metadata +353 -57
- data/lib/hanami/application/action.rb +0 -72
- data/lib/hanami/application/container/providers/inflector.rb +0 -7
- data/lib/hanami/application/container/providers/logger.rb +0 -7
- data/lib/hanami/application/container/providers/rack_logger.rb +0 -15
- data/lib/hanami/application/container/providers/rack_monitor.rb +0 -12
- data/lib/hanami/application/container/providers/routes_helper.rb +0 -9
- data/lib/hanami/application/container/providers/settings.rb +0 -7
- data/lib/hanami/application/routes.rb +0 -55
- data/lib/hanami/application/routes_helper.rb +0 -34
- data/lib/hanami/application/routing/resolver/node.rb +0 -50
- data/lib/hanami/application/routing/resolver/trie.rb +0 -59
- data/lib/hanami/application/routing/resolver.rb +0 -87
- data/lib/hanami/application/routing/router.rb +0 -36
- data/lib/hanami/application/settings/dotenv_store.rb +0 -60
- data/lib/hanami/application/settings.rb +0 -93
- data/lib/hanami/application/slice_registrar.rb +0 -106
- data/lib/hanami/application/view/context.rb +0 -95
- data/lib/hanami/application/view.rb +0 -24
- data/lib/hanami/application.rb +0 -273
- data/lib/hanami/cli/application/cli.rb +0 -40
- data/lib/hanami/cli/application/command.rb +0 -47
- data/lib/hanami/cli/application/commands/console.rb +0 -81
- data/lib/hanami/cli/application/commands.rb +0 -16
- data/lib/hanami/cli/base_command.rb +0 -48
- data/lib/hanami/cli/commands/command.rb +0 -171
- data/lib/hanami/cli/commands/server.rb +0 -88
- data/lib/hanami/cli/commands.rb +0 -65
- data/lib/hanami/configuration/middleware.rb +0 -20
- data/lib/hanami/configuration/source_dirs.rb +0 -42
data/lib/hanami/configuration.rb
CHANGED
|
@@ -7,51 +7,108 @@ require "dry/configurable"
|
|
|
7
7
|
require "dry/inflector"
|
|
8
8
|
require "pathname"
|
|
9
9
|
|
|
10
|
-
require_relative "
|
|
10
|
+
require_relative "constants"
|
|
11
11
|
require_relative "configuration/logger"
|
|
12
|
-
require_relative "configuration/middleware"
|
|
13
12
|
require_relative "configuration/router"
|
|
14
13
|
require_relative "configuration/sessions"
|
|
15
|
-
require_relative "
|
|
16
|
-
require_relative "
|
|
14
|
+
require_relative "settings/dotenv_store"
|
|
15
|
+
require_relative "slice/routing/middleware/stack"
|
|
17
16
|
|
|
18
17
|
module Hanami
|
|
19
|
-
# Hanami
|
|
18
|
+
# Hanami app configuration
|
|
20
19
|
#
|
|
21
20
|
# @since 2.0.0
|
|
22
21
|
class Configuration
|
|
23
22
|
include Dry::Configurable
|
|
24
23
|
|
|
24
|
+
setting :root, constructor: ->(path) { Pathname(path) if path }
|
|
25
|
+
|
|
26
|
+
setting :no_auto_register_paths, default: %w[entities]
|
|
27
|
+
|
|
28
|
+
setting :inflector, default: Dry::Inflector.new
|
|
29
|
+
|
|
30
|
+
setting :settings_store, default: Hanami::Settings::DotenvStore
|
|
31
|
+
|
|
32
|
+
setting :slices do
|
|
33
|
+
setting :shared_component_keys, default: %w[
|
|
34
|
+
inflector
|
|
35
|
+
logger
|
|
36
|
+
notifications
|
|
37
|
+
rack.monitor
|
|
38
|
+
routes
|
|
39
|
+
settings
|
|
40
|
+
]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
setting :base_url, default: "http://0.0.0.0:2300", constructor: ->(url) { URI(url) }
|
|
44
|
+
|
|
45
|
+
setting :sessions, default: :null, constructor: ->(*args) { Sessions.new(*args) }
|
|
46
|
+
|
|
47
|
+
setting :logger, cloneable: true
|
|
48
|
+
|
|
25
49
|
DEFAULT_ENVIRONMENTS = Concurrent::Hash.new { |h, k| h[k] = Concurrent::Array.new }
|
|
26
50
|
private_constant :DEFAULT_ENVIRONMENTS
|
|
27
51
|
|
|
28
|
-
|
|
52
|
+
# @return [Symbol] The name of the application
|
|
53
|
+
#
|
|
54
|
+
# @api public
|
|
55
|
+
attr_reader :app_name
|
|
56
|
+
|
|
57
|
+
# @return [String] The current environment
|
|
58
|
+
#
|
|
59
|
+
# @api public
|
|
29
60
|
attr_reader :env
|
|
30
61
|
|
|
62
|
+
# @return [Hanami::Configuration::Actions]
|
|
63
|
+
#
|
|
64
|
+
# @api public
|
|
31
65
|
attr_reader :actions
|
|
66
|
+
|
|
67
|
+
# @return [Hanami::Slice::Routing::Middleware::Stack]
|
|
68
|
+
#
|
|
69
|
+
# @api public
|
|
32
70
|
attr_reader :middleware
|
|
71
|
+
|
|
72
|
+
# @api private
|
|
73
|
+
alias_method :middleware_stack, :middleware
|
|
74
|
+
|
|
75
|
+
# @return [Hanami::Configuration::Router]
|
|
76
|
+
#
|
|
77
|
+
# @api public
|
|
33
78
|
attr_reader :router
|
|
34
|
-
attr_reader :views, :assets
|
|
35
79
|
|
|
80
|
+
# @return [Hanami::Configuration::Views]
|
|
81
|
+
#
|
|
82
|
+
# @api public
|
|
83
|
+
attr_reader :views
|
|
84
|
+
|
|
85
|
+
# @return [Hanami::Assets::AppConfiguration]
|
|
86
|
+
#
|
|
87
|
+
# @api public
|
|
88
|
+
attr_reader :assets
|
|
89
|
+
|
|
90
|
+
# @return [Concurrent::Hash] A hash of default environments
|
|
91
|
+
#
|
|
92
|
+
# @api private
|
|
36
93
|
attr_reader :environments
|
|
37
94
|
private :environments
|
|
38
95
|
|
|
39
|
-
#
|
|
40
|
-
def initialize(
|
|
41
|
-
@
|
|
96
|
+
# @api private
|
|
97
|
+
def initialize(app_name:, env:)
|
|
98
|
+
@app_name = app_name
|
|
42
99
|
|
|
43
100
|
@environments = DEFAULT_ENVIRONMENTS.clone
|
|
44
101
|
@env = env
|
|
45
102
|
|
|
46
103
|
# Some default setting values must be assigned at initialize-time to ensure they
|
|
47
|
-
# have appropriate values for the current
|
|
104
|
+
# have appropriate values for the current app
|
|
48
105
|
self.root = Dir.pwd
|
|
49
|
-
self.settings_store =
|
|
106
|
+
self.settings_store = Hanami::Settings::DotenvStore.new.with_dotenv_loaded
|
|
50
107
|
|
|
51
|
-
config.logger = Configuration::Logger.new(env: env,
|
|
108
|
+
config.logger = Configuration::Logger.new(env: env, app_name: app_name)
|
|
52
109
|
|
|
53
|
-
@assets = load_dependent_config("hanami/assets/
|
|
54
|
-
Hanami::Assets::
|
|
110
|
+
@assets = load_dependent_config("hanami/assets/app_configuration") {
|
|
111
|
+
Hanami::Assets::AppConfiguration.new
|
|
55
112
|
}
|
|
56
113
|
|
|
57
114
|
@actions = load_dependent_config("hanami/action") {
|
|
@@ -59,7 +116,7 @@ module Hanami
|
|
|
59
116
|
Actions.new
|
|
60
117
|
}
|
|
61
118
|
|
|
62
|
-
@middleware = Middleware.new
|
|
119
|
+
@middleware = Slice::Routing::Middleware::Stack.new
|
|
63
120
|
|
|
64
121
|
@router = Router.new(self)
|
|
65
122
|
|
|
@@ -70,8 +127,14 @@ module Hanami
|
|
|
70
127
|
|
|
71
128
|
yield self if block_given?
|
|
72
129
|
end
|
|
73
|
-
# rubocop:enable Metrics/AbcSize
|
|
74
130
|
|
|
131
|
+
# Apply configuration for the given environment
|
|
132
|
+
#
|
|
133
|
+
# @param env [String] the environment name
|
|
134
|
+
#
|
|
135
|
+
# @return [Hanami::Configuration]
|
|
136
|
+
#
|
|
137
|
+
# @api public
|
|
75
138
|
def environment(env_name, &block)
|
|
76
139
|
environments[env_name] << block
|
|
77
140
|
apply_env_config
|
|
@@ -79,6 +142,34 @@ module Hanami
|
|
|
79
142
|
self
|
|
80
143
|
end
|
|
81
144
|
|
|
145
|
+
# Configure application's inflections
|
|
146
|
+
#
|
|
147
|
+
# @see https://dry-rb.org/gems/dry-inflector
|
|
148
|
+
#
|
|
149
|
+
# @return [Dry::Inflector]
|
|
150
|
+
#
|
|
151
|
+
# @api public
|
|
152
|
+
def inflections(&block)
|
|
153
|
+
self.inflector = Dry::Inflector.new(&block)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# @api private
|
|
157
|
+
def initialize_copy(source)
|
|
158
|
+
super
|
|
159
|
+
|
|
160
|
+
@app_name = app_name.dup
|
|
161
|
+
@environments = environments.dup
|
|
162
|
+
|
|
163
|
+
@assets = source.assets.dup
|
|
164
|
+
@actions = source.actions.dup
|
|
165
|
+
@middleware = source.middleware.dup
|
|
166
|
+
@router = source.router.dup.tap do |router|
|
|
167
|
+
router.instance_variable_set(:@base_configuration, self)
|
|
168
|
+
end
|
|
169
|
+
@views = source.views.dup
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# @api private
|
|
82
173
|
def finalize!
|
|
83
174
|
apply_env_config
|
|
84
175
|
|
|
@@ -92,51 +183,30 @@ module Hanami
|
|
|
92
183
|
super
|
|
93
184
|
end
|
|
94
185
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def inflections(&block)
|
|
100
|
-
self.inflector = Dry::Inflector.new(&block)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
setting :logger, cloneable: true
|
|
104
|
-
|
|
186
|
+
# Set a default global logger instance
|
|
187
|
+
#
|
|
188
|
+
# @api public
|
|
105
189
|
def logger=(logger_instance)
|
|
106
190
|
@logger_instance = logger_instance
|
|
107
191
|
end
|
|
108
192
|
|
|
193
|
+
# Return configured logger instance
|
|
194
|
+
#
|
|
195
|
+
# @api public
|
|
109
196
|
def logger_instance
|
|
110
197
|
@logger_instance || logger.instance
|
|
111
198
|
end
|
|
112
199
|
|
|
113
|
-
setting :settings_path, default: File.join("config", "settings")
|
|
114
|
-
|
|
115
|
-
setting :settings_class_name, default: "Settings"
|
|
116
|
-
|
|
117
|
-
setting :settings_store, default: Application::Settings::DotenvStore
|
|
118
|
-
|
|
119
|
-
setting :source_dirs, default: Configuration::SourceDirs.new, cloneable: true
|
|
120
|
-
|
|
121
|
-
setting :base_url, default: "http://0.0.0.0:2300", constructor: -> url { URI(url) }
|
|
122
|
-
|
|
123
|
-
def for_each_middleware(&blk)
|
|
124
|
-
stack = middleware.stack.dup
|
|
125
|
-
stack += sessions.middleware if sessions.enabled?
|
|
126
|
-
|
|
127
|
-
stack.each(&blk)
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
setting :sessions, default: :null, constructor: -> *args { Sessions.new(*args) }
|
|
131
|
-
|
|
132
200
|
private
|
|
133
201
|
|
|
202
|
+
# @api private
|
|
134
203
|
def apply_env_config(env = self.env)
|
|
135
204
|
environments[env].each do |block|
|
|
136
205
|
instance_eval(&block)
|
|
137
206
|
end
|
|
138
207
|
end
|
|
139
208
|
|
|
209
|
+
# @api private
|
|
140
210
|
def load_dependent_config(require_path, &block)
|
|
141
211
|
require require_path
|
|
142
212
|
yield
|
|
@@ -147,6 +217,7 @@ module Hanami
|
|
|
147
217
|
NullConfiguration.new
|
|
148
218
|
end
|
|
149
219
|
|
|
220
|
+
# @api private
|
|
150
221
|
def method_missing(name, *args, &block)
|
|
151
222
|
if config.respond_to?(name)
|
|
152
223
|
config.public_send(name, *args, &block)
|
|
@@ -155,6 +226,7 @@ module Hanami
|
|
|
155
226
|
end
|
|
156
227
|
end
|
|
157
228
|
|
|
229
|
+
# @api private
|
|
158
230
|
def respond_to_missing?(name, _incude_all = false)
|
|
159
231
|
config.respond_to?(name) || super
|
|
160
232
|
end
|
data/lib/hanami/constants.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Hanami
|
|
4
|
+
# @api private
|
|
4
5
|
CONTAINER_KEY_DELIMITER = "."
|
|
5
6
|
private_constant :CONTAINER_KEY_DELIMITER
|
|
6
7
|
|
|
@@ -8,6 +9,7 @@ module Hanami
|
|
|
8
9
|
MODULE_DELIMITER = "::"
|
|
9
10
|
private_constant :MODULE_DELIMITER
|
|
10
11
|
|
|
12
|
+
# @api private
|
|
11
13
|
PATH_DELIMITER = "/"
|
|
12
14
|
private_constant :PATH_DELIMITER
|
|
13
15
|
|
|
@@ -16,13 +18,33 @@ module Hanami
|
|
|
16
18
|
private_constant :CONFIG_DIR
|
|
17
19
|
|
|
18
20
|
# @api private
|
|
19
|
-
|
|
20
|
-
private_constant :
|
|
21
|
+
APP_DIR = "app"
|
|
22
|
+
private_constant :APP_DIR
|
|
21
23
|
|
|
22
24
|
# @api private
|
|
23
25
|
LIB_DIR = "lib"
|
|
24
26
|
private_constant :LIB_DIR
|
|
25
27
|
|
|
28
|
+
# @api private
|
|
29
|
+
SLICES_DIR = "slices"
|
|
30
|
+
private_constant :SLICES_DIR
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
ROUTES_PATH = File.join(CONFIG_DIR, "routes")
|
|
34
|
+
private_constant :ROUTES_PATH
|
|
35
|
+
|
|
36
|
+
# @api private
|
|
37
|
+
ROUTES_CLASS_NAME = "Routes"
|
|
38
|
+
private_constant :ROUTES_CLASS_NAME
|
|
39
|
+
|
|
40
|
+
# @api private
|
|
41
|
+
SETTINGS_PATH = File.join(CONFIG_DIR, "settings")
|
|
42
|
+
private_constant :SETTINGS_PATH
|
|
43
|
+
|
|
44
|
+
# @api private
|
|
45
|
+
SETTINGS_CLASS_NAME = "Settings"
|
|
46
|
+
private_constant :SETTINGS_CLASS_NAME
|
|
47
|
+
|
|
26
48
|
# @api private
|
|
27
49
|
RB_EXT = ".rb"
|
|
28
50
|
private_constant :RB_EXT
|
data/lib/hanami/errors.rb
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
require "hanami/action"
|
|
4
4
|
|
|
5
5
|
module Hanami
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
module Extensions
|
|
7
|
+
module Action
|
|
8
8
|
# Provides slice-specific configuration and behavior for any action class defined
|
|
9
9
|
# within a slice's module namespace.
|
|
10
10
|
#
|
|
@@ -30,7 +30,7 @@ module Hanami
|
|
|
30
30
|
|
|
31
31
|
private
|
|
32
32
|
|
|
33
|
-
# @see Hanami::
|
|
33
|
+
# @see Hanami::Extensions::Action::InstanceMethods#initialize
|
|
34
34
|
def define_new
|
|
35
35
|
resolve_view = method(:resolve_paired_view)
|
|
36
36
|
resolve_view_context = method(:resolve_view_context)
|
|
@@ -39,7 +39,7 @@ module Hanami
|
|
|
39
39
|
define_method(:new) do |**kwargs|
|
|
40
40
|
super(
|
|
41
41
|
view: kwargs.fetch(:view) { resolve_view.(self) },
|
|
42
|
-
view_context: kwargs.fetch(:view_context) { resolve_view_context.(
|
|
42
|
+
view_context: kwargs.fetch(:view_context) { resolve_view_context.() },
|
|
43
43
|
routes: kwargs.fetch(:routes) { resolve_routes.() },
|
|
44
44
|
**kwargs,
|
|
45
45
|
)
|
|
@@ -80,22 +80,22 @@ module Hanami
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
def resolve_view_context
|
|
83
|
+
def resolve_view_context
|
|
84
84
|
identifier = actions_config.view_context_identifier
|
|
85
85
|
|
|
86
86
|
if slice.key?(identifier)
|
|
87
87
|
slice[identifier]
|
|
88
|
-
elsif slice.
|
|
89
|
-
slice.
|
|
88
|
+
elsif slice.app.key?(identifier)
|
|
89
|
+
slice.app[identifier]
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
def resolve_routes
|
|
94
|
-
slice.
|
|
94
|
+
slice.app["routes"] if slice.app.key?("routes")
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
def actions_config
|
|
98
|
-
slice.
|
|
98
|
+
slice.config.actions
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hanami/action"
|
|
4
|
+
require_relative "../slice_configurable"
|
|
5
|
+
require_relative "action/slice_configured_action"
|
|
6
|
+
|
|
7
|
+
module Hanami
|
|
8
|
+
module Extensions
|
|
9
|
+
# Extended behavior for actions intended for use within an Hanami app.
|
|
10
|
+
#
|
|
11
|
+
# @see Hanami::Action
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
# @since 2.0.0
|
|
15
|
+
module Action
|
|
16
|
+
def self.included(action_class)
|
|
17
|
+
super
|
|
18
|
+
|
|
19
|
+
action_class.extend(Hanami::SliceConfigurable)
|
|
20
|
+
action_class.extend(ClassMethods)
|
|
21
|
+
action_class.prepend(InstanceMethods)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module ClassMethods
|
|
25
|
+
def configure_for_slice(slice)
|
|
26
|
+
extend SliceConfiguredAction.new(slice)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module InstanceMethods
|
|
31
|
+
attr_reader :view, :view_context, :routes
|
|
32
|
+
|
|
33
|
+
def initialize(view: nil, view_context: nil, routes: nil, **kwargs)
|
|
34
|
+
@view = view
|
|
35
|
+
@view_context = view_context
|
|
36
|
+
@routes = routes
|
|
37
|
+
|
|
38
|
+
super(**kwargs)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def build_response(**options)
|
|
44
|
+
options = options.merge(view_options: method(:view_options))
|
|
45
|
+
super(**options)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def finish(req, res, halted)
|
|
49
|
+
res.render(view, **req.params) if !halted && auto_render?(res)
|
|
50
|
+
super
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def view_options(req, res)
|
|
54
|
+
{context: view_context&.with(**view_context_options(req, res))}.compact
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def view_context_options(req, res)
|
|
58
|
+
{request: req, response: res}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns true if a view should automatically be rendered onto the response body.
|
|
62
|
+
#
|
|
63
|
+
# This may be overridden to enable/disable automatic rendering.
|
|
64
|
+
#
|
|
65
|
+
# @param res [Hanami::Action::Response]
|
|
66
|
+
#
|
|
67
|
+
# @return [Boolean]
|
|
68
|
+
#
|
|
69
|
+
# @since 2.0.0
|
|
70
|
+
# @api public
|
|
71
|
+
def auto_render?(res)
|
|
72
|
+
view && res.body.empty?
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
Hanami::Action.include(Hanami::Extensions::Action)
|
|
@@ -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)
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
require "hanami/view"
|
|
4
4
|
|
|
5
5
|
module Hanami
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
module Extensions
|
|
7
|
+
module View
|
|
8
8
|
# Provides slice-specific configuration and behavior for any view context class
|
|
9
9
|
# defined within a slice's module namespace.
|
|
10
10
|
#
|
|
@@ -29,15 +29,15 @@ module Hanami
|
|
|
29
29
|
private
|
|
30
30
|
|
|
31
31
|
# Defines a {.new} method on the context class that resolves key components from
|
|
32
|
-
# the
|
|
32
|
+
# the app container and provides them to {#initialize} as injected
|
|
33
33
|
# dependencies.
|
|
34
34
|
#
|
|
35
|
-
# This includes the following
|
|
35
|
+
# This includes the following app components:
|
|
36
36
|
#
|
|
37
37
|
# - the configured inflector as `inflector`
|
|
38
|
-
# - "settings" from the
|
|
39
|
-
# - "routes" from the
|
|
40
|
-
# - "assets" from the
|
|
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
41
|
def define_new
|
|
42
42
|
inflector = slice.inflector
|
|
43
43
|
resolve_settings = method(:resolve_settings)
|
|
@@ -55,15 +55,15 @@ module Hanami
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def resolve_settings
|
|
58
|
-
slice.
|
|
58
|
+
slice.app[:settings] if slice.app.key?(:settings)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def resolve_routes
|
|
62
|
-
slice.
|
|
62
|
+
slice.app["routes"] if slice.app.key?("routes")
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def resolve_assets
|
|
66
|
-
slice.
|
|
66
|
+
slice.app[:assets] if slice.app.key?(:assets)
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
require "hanami/view"
|
|
4
4
|
|
|
5
5
|
module Hanami
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
module Extensions
|
|
7
|
+
module View
|
|
8
8
|
# Provides slice-specific configuration and behavior for any view class defined
|
|
9
9
|
# within a slice's module namespace.
|
|
10
10
|
#
|
|
@@ -32,10 +32,10 @@ module Hanami
|
|
|
32
32
|
# rubocop:disable Metrics/AbcSize
|
|
33
33
|
def configure_view(view_class)
|
|
34
34
|
view_class.settings.each do |setting|
|
|
35
|
-
if slice.
|
|
35
|
+
if slice.config.views.respond_to?(:"#{setting}")
|
|
36
36
|
view_class.config.public_send(
|
|
37
37
|
:"#{setting}=",
|
|
38
|
-
slice.
|
|
38
|
+
slice.config.views.public_send(:"#{setting}")
|
|
39
39
|
)
|
|
40
40
|
end
|
|
41
41
|
end
|
|
@@ -44,7 +44,7 @@ module Hanami
|
|
|
44
44
|
view_class.config.paths = prepare_paths(slice, view_class.config.paths)
|
|
45
45
|
view_class.config.template = template_name(view_class)
|
|
46
46
|
|
|
47
|
-
if (part_namespace = namespace_from_path(slice.
|
|
47
|
+
if (part_namespace = namespace_from_path(slice.config.views.parts_path))
|
|
48
48
|
view_class.config.part_namespace = part_namespace
|
|
49
49
|
end
|
|
50
50
|
end
|
|
@@ -62,7 +62,13 @@ module Hanami
|
|
|
62
62
|
def prepare_paths(slice, configured_paths)
|
|
63
63
|
configured_paths.map { |path|
|
|
64
64
|
if path.dir.relative?
|
|
65
|
-
slice.
|
|
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
|
|
66
72
|
else
|
|
67
73
|
path
|
|
68
74
|
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)
|