hanami 2.0.0.alpha4 → 2.0.0.alpha7
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 +256 -0
- data/README.md +3 -7
- data/hanami.gemspec +5 -4
- data/lib/hanami/application/container/{boot → providers}/inflector.rb +1 -1
- data/lib/hanami/application/container/{boot → providers}/logger.rb +1 -1
- data/lib/hanami/application/container/providers/rack_logger.rb +15 -0
- data/lib/hanami/application/container/{boot → providers}/rack_monitor.rb +2 -2
- data/lib/hanami/application/container/{boot → providers}/routes_helper.rb +1 -1
- data/lib/hanami/application/container/{boot → providers}/settings.rb +1 -1
- data/lib/hanami/application/router.rb +7 -7
- data/lib/hanami/application/routing/router.rb +36 -0
- data/lib/hanami/application/slice_registrar.rb +107 -0
- data/lib/hanami/application.rb +124 -202
- data/lib/hanami/boot/source_dirs.rb +44 -0
- data/lib/hanami/cli/application/cli.rb +1 -1
- data/lib/hanami/configuration/actions.rb +90 -0
- data/lib/hanami/configuration/logger.rb +49 -5
- data/lib/hanami/configuration/source_dirs.rb +42 -0
- data/lib/hanami/configuration.rb +19 -24
- data/lib/hanami/constants.rb +23 -0
- data/lib/hanami/errors.rb +12 -0
- data/lib/hanami/{init.rb → prepare.rb} +1 -1
- data/lib/hanami/slice.rb +198 -112
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +27 -51
- data/lib/hanami.rb +19 -29
- metadata +23 -16
- data/lib/hanami/application/autoloader/inflector_adapter.rb +0 -22
- data/lib/hanami/application/container/boot/rack_logger.rb +0 -19
data/lib/hanami/application.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "dry/system/container"
|
4
|
-
require "dry/system/loader/autoloading"
|
5
4
|
require "hanami/configuration"
|
6
5
|
require "pathname"
|
7
6
|
require "rack"
|
8
7
|
require "zeitwerk"
|
8
|
+
require_relative "constants"
|
9
9
|
require_relative "slice"
|
10
|
-
require_relative "application/
|
11
|
-
require_relative "application/router"
|
12
|
-
require_relative "application/routes"
|
13
|
-
require_relative "application/settings"
|
10
|
+
require_relative "application/slice_registrar"
|
14
11
|
|
15
12
|
module Hanami
|
16
13
|
# Hanami application class
|
@@ -21,13 +18,15 @@ module Hanami
|
|
21
18
|
|
22
19
|
class << self
|
23
20
|
def inherited(klass)
|
21
|
+
super
|
24
22
|
@_mutex.synchronize do
|
25
23
|
klass.class_eval do
|
26
|
-
@_mutex
|
27
|
-
@_configuration = Hanami::Configuration.new(env: Hanami.env)
|
24
|
+
@_mutex = Mutex.new
|
25
|
+
@_configuration = Hanami::Configuration.new(application_name: name, env: Hanami.env)
|
26
|
+
@autoloader = Zeitwerk::Loader.new
|
27
|
+
@container = Class.new(Dry::System::Container)
|
28
28
|
|
29
29
|
extend ClassMethods
|
30
|
-
include InstanceMethods
|
31
30
|
end
|
32
31
|
|
33
32
|
klass.send :prepare_base_load_path
|
@@ -41,9 +40,11 @@ module Hanami
|
|
41
40
|
#
|
42
41
|
# rubocop:disable Metrics/ModuleLength
|
43
42
|
module ClassMethods
|
43
|
+
attr_reader :autoloader, :container
|
44
|
+
|
44
45
|
def self.extended(klass)
|
45
46
|
klass.class_eval do
|
46
|
-
@
|
47
|
+
@prepared = @booted = false
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -51,129 +52,102 @@ module Hanami
|
|
51
52
|
@_configuration
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
+
alias_method :config, :configuration
|
56
|
+
|
57
|
+
def prepare(provider_name = nil)
|
58
|
+
container.prepare(provider_name) and return self if provider_name
|
55
59
|
|
56
|
-
|
57
|
-
return self if inited?
|
60
|
+
return self if prepared?
|
58
61
|
|
59
62
|
configuration.finalize!
|
60
63
|
|
61
|
-
|
62
|
-
autoloader.inflector = Autoloader::InflectorAdapter.new(inflector)
|
64
|
+
prepare_all
|
63
65
|
|
64
|
-
|
66
|
+
@prepared = true
|
67
|
+
self
|
68
|
+
end
|
65
69
|
|
66
|
-
|
67
|
-
|
70
|
+
def boot(&block)
|
71
|
+
return self if booted?
|
68
72
|
|
69
|
-
|
70
|
-
slices.values.each(&:init)
|
71
|
-
slices.freeze
|
73
|
+
prepare
|
72
74
|
|
73
|
-
|
75
|
+
container.finalize!(&block)
|
74
76
|
|
75
|
-
|
77
|
+
slices.each(&:boot)
|
78
|
+
|
79
|
+
@booted = true
|
76
80
|
self
|
77
81
|
end
|
78
82
|
|
79
|
-
def
|
80
|
-
|
83
|
+
def shutdown
|
84
|
+
slices.each(&:shutdown)
|
85
|
+
container.shutdown!
|
86
|
+
self
|
81
87
|
end
|
82
88
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
@autoloader
|
89
|
+
def prepared?
|
90
|
+
!!@prepared
|
87
91
|
end
|
88
92
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
@container
|
93
|
+
def booted?
|
94
|
+
!!@booted
|
93
95
|
end
|
94
96
|
|
95
|
-
def
|
96
|
-
raise "Application not
|
97
|
+
def router
|
98
|
+
raise "Application not yet prepared" unless prepared?
|
97
99
|
|
98
|
-
@
|
100
|
+
@_mutex.synchronize do
|
101
|
+
@_router ||= load_router
|
102
|
+
end
|
99
103
|
end
|
100
104
|
|
101
|
-
def
|
102
|
-
@
|
105
|
+
def rack_app
|
106
|
+
@rack_app ||= router.to_rack_app
|
103
107
|
end
|
104
108
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
slice = Slice.new(self, name: name, **slice_args)
|
109
|
-
slice.namespace.const_set :Slice, slice if slice.namespace # rubocop:disable Style/SafeNavigation
|
110
|
-
slices[name.to_sym] = slice
|
109
|
+
def slices
|
110
|
+
@slices ||= SliceRegistrar.new(self)
|
111
111
|
end
|
112
112
|
|
113
|
-
def
|
114
|
-
|
113
|
+
def register_slice(...)
|
114
|
+
slices.register(...)
|
115
115
|
end
|
116
116
|
|
117
|
-
def
|
118
|
-
container.
|
117
|
+
def register(...)
|
118
|
+
container.register(...)
|
119
119
|
end
|
120
120
|
|
121
|
-
def
|
122
|
-
container.
|
121
|
+
def register_provider(...)
|
122
|
+
container.register_provider(...)
|
123
123
|
end
|
124
124
|
|
125
|
-
def
|
126
|
-
container.start(
|
125
|
+
def start(...)
|
126
|
+
container.start(...)
|
127
127
|
end
|
128
128
|
|
129
|
-
def key?(
|
130
|
-
container.key?(
|
129
|
+
def key?(...)
|
130
|
+
container.key?(...)
|
131
131
|
end
|
132
132
|
|
133
133
|
def keys
|
134
134
|
container.keys
|
135
135
|
end
|
136
136
|
|
137
|
-
def [](
|
138
|
-
container[
|
137
|
+
def [](...)
|
138
|
+
container.[](...)
|
139
139
|
end
|
140
140
|
|
141
|
-
def resolve(
|
142
|
-
container.resolve(
|
143
|
-
end
|
144
|
-
|
145
|
-
def boot(&block)
|
146
|
-
return self if booted?
|
147
|
-
|
148
|
-
init
|
149
|
-
|
150
|
-
load_router
|
151
|
-
|
152
|
-
container.finalize!(&block)
|
153
|
-
|
154
|
-
slices.values.each(&:boot)
|
155
|
-
|
156
|
-
@booted = true
|
157
|
-
self
|
158
|
-
end
|
159
|
-
|
160
|
-
def booted?
|
161
|
-
@booted
|
162
|
-
end
|
163
|
-
|
164
|
-
def shutdown
|
165
|
-
container.shutdown!
|
141
|
+
def resolve(...)
|
142
|
+
container.resolve(...)
|
166
143
|
end
|
167
144
|
|
168
145
|
def settings
|
169
146
|
@_settings ||= load_settings
|
170
147
|
end
|
171
148
|
|
172
|
-
MODULE_DELIMITER = "::"
|
173
|
-
private_constant :MODULE_DELIMITER
|
174
|
-
|
175
149
|
def namespace
|
176
|
-
|
150
|
+
configuration.namespace
|
177
151
|
end
|
178
152
|
|
179
153
|
def namespace_name
|
@@ -185,7 +159,7 @@ module Hanami
|
|
185
159
|
end
|
186
160
|
|
187
161
|
def application_name
|
188
|
-
|
162
|
+
configuration.application_name
|
189
163
|
end
|
190
164
|
|
191
165
|
def root
|
@@ -198,10 +172,10 @@ module Hanami
|
|
198
172
|
|
199
173
|
# @api private
|
200
174
|
def component_provider(component)
|
201
|
-
raise "Hanami.application must be
|
175
|
+
raise "Hanami.application must be prepared before detecting providers" unless prepared?
|
202
176
|
|
203
|
-
#
|
204
|
-
providers = slices.
|
177
|
+
# e.g. [Admin, Main, MyApp]
|
178
|
+
providers = slices.to_a + [self]
|
205
179
|
|
206
180
|
component_class = component.is_a?(Class) ? component : component.class
|
207
181
|
component_name = component_class.name
|
@@ -211,41 +185,6 @@ module Hanami
|
|
211
185
|
providers.detect { |provider| component_name.include?(provider.namespace.to_s) }
|
212
186
|
end
|
213
187
|
|
214
|
-
def router
|
215
|
-
@_mutex.synchronize do
|
216
|
-
@_router ||= load_router
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def load_router
|
221
|
-
Router.new(
|
222
|
-
routes: routes,
|
223
|
-
resolver: resolver,
|
224
|
-
**configuration.router.options,
|
225
|
-
) do
|
226
|
-
use Hanami.application[:rack_monitor]
|
227
|
-
|
228
|
-
Hanami.application.config.for_each_middleware do |m, *args, &block|
|
229
|
-
use(m, *args, &block)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def routes
|
235
|
-
require File.join(configuration.root, configuration.router.routes_path)
|
236
|
-
routes_class = autodiscover_application_constant(configuration.router.routes_class_name)
|
237
|
-
routes_class.routes
|
238
|
-
rescue LoadError
|
239
|
-
proc {}
|
240
|
-
end
|
241
|
-
|
242
|
-
def resolver
|
243
|
-
config.router.resolver.new(
|
244
|
-
slices: slices,
|
245
|
-
inflector: inflector
|
246
|
-
)
|
247
|
-
end
|
248
|
-
|
249
188
|
private
|
250
189
|
|
251
190
|
def prepare_base_load_path
|
@@ -253,96 +192,63 @@ module Hanami
|
|
253
192
|
$LOAD_PATH.unshift base_path unless $LOAD_PATH.include?(base_path)
|
254
193
|
end
|
255
194
|
|
256
|
-
def
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
195
|
+
def prepare_all
|
196
|
+
load_settings
|
197
|
+
prepare_container_plugins
|
198
|
+
prepare_container_base_config
|
199
|
+
prepare_container_consts
|
200
|
+
container.configured!
|
201
|
+
prepare_slices
|
202
|
+
# For the application, the autoloader must be prepared after the slices, since
|
203
|
+
# they'll be configuring the autoloader with their own dirs
|
204
|
+
prepare_autoloader
|
264
205
|
end
|
265
206
|
|
266
|
-
def
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
namespace.const_set :Container, Class.new(Dry::System::Container)
|
207
|
+
def prepare_container_plugins
|
208
|
+
container.use(:env, inferrer: -> { Hanami.env })
|
209
|
+
container.use(:zeitwerk, loader: autoloader, run_setup: false, eager_load: false)
|
210
|
+
container.use(:notifications)
|
271
211
|
end
|
272
212
|
|
273
|
-
|
274
|
-
|
275
|
-
container.
|
276
|
-
container.use :notifications
|
277
|
-
|
278
|
-
container.configure do |config|
|
279
|
-
config.inflector = configuration.inflector
|
213
|
+
def prepare_container_base_config
|
214
|
+
container.config.root = configuration.root
|
215
|
+
container.config.inflector = configuration.inflector
|
280
216
|
|
281
|
-
|
282
|
-
config
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
config.component_dirs.loader = Dry::System::Loader::Autoloading
|
288
|
-
config.component_dirs.add_to_load_path = false
|
289
|
-
end
|
217
|
+
container.config.provider_dirs = [
|
218
|
+
"config/providers",
|
219
|
+
Pathname(__dir__).join("application/container/providers").realpath,
|
220
|
+
]
|
221
|
+
end
|
290
222
|
|
223
|
+
def prepare_autoload_paths
|
291
224
|
# Autoload classes defined in lib/[app_namespace]/
|
292
225
|
if root.join("lib", namespace_path).directory?
|
293
226
|
autoloader.push_dir(root.join("lib", namespace_path), namespace: namespace)
|
294
227
|
end
|
295
|
-
|
296
|
-
# Add lib/ to to the $LOAD_PATH so other files there (outside the app namespace)
|
297
|
-
# are require-able
|
298
|
-
container.add_to_load_path!("lib") if root.join("lib").directory?
|
299
|
-
|
300
|
-
container
|
301
228
|
end
|
302
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
303
229
|
|
304
|
-
def
|
305
|
-
|
306
|
-
namespace.const_get :Deps
|
307
|
-
rescue LoadError, NameError
|
230
|
+
def prepare_container_consts
|
231
|
+
namespace.const_set :Container, container
|
308
232
|
namespace.const_set :Deps, container.injector
|
309
233
|
end
|
310
234
|
|
311
|
-
def
|
312
|
-
|
313
|
-
|
314
|
-
.each(&method(:load_slice))
|
315
|
-
end
|
316
|
-
|
317
|
-
def slices_path
|
318
|
-
File.join(root, config.slices_dir)
|
235
|
+
def prepare_slices
|
236
|
+
slices.load_slices.each(&:prepare)
|
237
|
+
slices.freeze
|
319
238
|
end
|
320
239
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
slice_name = slice_path.relative_path_from(Pathname(slices_path)).to_s
|
326
|
-
slice_const_name = inflector.camelize(slice_name)
|
327
|
-
|
328
|
-
if config.slices_namespace.const_defined?(slice_const_name)
|
329
|
-
slice_module = config.slices_namespace.const_get(slice_const_name)
|
330
|
-
|
331
|
-
raise "Cannot use slice +#{slice_const_name}+ since it is not a module" unless slice_module.is_a?(Module)
|
332
|
-
else
|
333
|
-
slice_module = Module.new
|
334
|
-
config.slices_namespace.const_set inflector.camelize(slice_name), slice_module
|
240
|
+
def prepare_autoloader
|
241
|
+
# Autoload classes defined in lib/[app_namespace]/
|
242
|
+
if root.join("lib", namespace_path).directory?
|
243
|
+
autoloader.push_dir(root.join("lib", namespace_path), namespace: namespace)
|
335
244
|
end
|
336
245
|
|
337
|
-
|
338
|
-
slice_name,
|
339
|
-
namespace: slice_module,
|
340
|
-
root: slice_path.realpath
|
341
|
-
)
|
246
|
+
autoloader.setup
|
342
247
|
end
|
343
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
344
248
|
|
345
249
|
def load_settings
|
250
|
+
require_relative "application/settings"
|
251
|
+
|
346
252
|
prepare_base_load_path
|
347
253
|
require File.join(configuration.root, configuration.settings_path)
|
348
254
|
settings_class = autodiscover_application_constant(configuration.settings_class_name)
|
@@ -354,24 +260,40 @@ module Hanami
|
|
354
260
|
def autodiscover_application_constant(constants)
|
355
261
|
inflector.constantize([namespace_name, *constants].join(MODULE_DELIMITER))
|
356
262
|
end
|
357
|
-
end
|
358
|
-
# rubocop:enable Metrics/ModuleLength
|
359
263
|
|
360
|
-
|
361
|
-
module InstanceMethods
|
362
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
363
|
-
def initialize(application = self.class)
|
264
|
+
def load_router
|
364
265
|
require_relative "application/router"
|
365
266
|
|
366
|
-
|
267
|
+
Router.new(
|
268
|
+
routes: load_routes,
|
269
|
+
resolver: router_resolver,
|
270
|
+
**configuration.router.options,
|
271
|
+
) do
|
272
|
+
use Hanami.application[:rack_monitor]
|
273
|
+
|
274
|
+
Hanami.application.config.for_each_middleware do |m, *args, &block|
|
275
|
+
use(m, *args, &block)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def load_routes
|
281
|
+
require_relative "application/routes"
|
367
282
|
|
368
|
-
|
283
|
+
require File.join(configuration.root, configuration.router.routes_path)
|
284
|
+
routes_class = autodiscover_application_constant(configuration.router.routes_class_name)
|
285
|
+
routes_class.routes
|
286
|
+
rescue LoadError
|
287
|
+
proc {}
|
369
288
|
end
|
370
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
371
289
|
|
372
|
-
def
|
373
|
-
|
290
|
+
def router_resolver
|
291
|
+
config.router.resolver.new(
|
292
|
+
slices: slices,
|
293
|
+
inflector: inflector
|
294
|
+
)
|
374
295
|
end
|
375
296
|
end
|
297
|
+
# rubocop:enable Metrics/ModuleLength
|
376
298
|
end
|
377
299
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Hanami
|
2
|
+
module Boot
|
3
|
+
module SourceDirs
|
4
|
+
def self.setup_component_dir!(component_dir, slice, container)
|
5
|
+
# TODO: this `== "lib"` check should be codified into a method somewhere
|
6
|
+
if component_dir.path == "lib"
|
7
|
+
# Expect component files in the root of the lib
|
8
|
+
# component dir to define classes inside the slice's namespace.
|
9
|
+
#
|
10
|
+
# e.g. "lib/foo.rb" should define SliceNamespace::Foo, and will be
|
11
|
+
# registered as "foo"
|
12
|
+
component_dir.namespaces.root(key: nil, const: slice.namespace_path)
|
13
|
+
|
14
|
+
slice.application.autoloader.push_dir(slice.root.join("lib"), namespace: slice.namespace)
|
15
|
+
|
16
|
+
container.config.component_dirs.add(component_dir)
|
17
|
+
else
|
18
|
+
# Expect component files in the root of these component dirs to define
|
19
|
+
# classes inside a namespace matching the dir.
|
20
|
+
#
|
21
|
+
# e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, and
|
22
|
+
# will be registered as "actions.foo"
|
23
|
+
|
24
|
+
dir_namespace_path = File.join(slice.namespace_path, component_dir.path)
|
25
|
+
|
26
|
+
autoloader_namespace = begin
|
27
|
+
slice.inflector.constantize(slice.inflector.camelize(dir_namespace_path))
|
28
|
+
rescue NameError
|
29
|
+
slice.namespace.const_set(slice.inflector.camelize(component_dir.path), Module.new)
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: do we need to do something special to clear out any previously configured root namespace here?
|
33
|
+
component_dir.namespaces.root(const: dir_namespace_path, key: component_dir.path) # TODO: do we need to swap path delimiters for key delimiters here?
|
34
|
+
container.config.component_dirs.add(component_dir)
|
35
|
+
|
36
|
+
slice.application.autoloader.push_dir(
|
37
|
+
slice.root.join(component_dir.path),
|
38
|
+
namespace: autoloader_namespace
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -26,7 +26,7 @@ module Hanami
|
|
26
26
|
# of the boot process respect the provided env
|
27
27
|
ENV["HANAMI_ENV"] = arguments[:env] if arguments[:env]
|
28
28
|
|
29
|
-
require "hanami/
|
29
|
+
require "hanami/prepare"
|
30
30
|
application = Hanami.application
|
31
31
|
|
32
32
|
[command.with_application(application), arguments]
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# require_relative "application_configuration/cookies"
|
4
|
+
# require_relative "application_configuration/sessions"
|
5
|
+
# require_relative "application_configuration/content_security_policy"
|
6
|
+
# require_relative "configuration"
|
7
|
+
# require_relative "view_name_inferrer"
|
8
|
+
|
9
|
+
module Hanami
|
10
|
+
class Configuration
|
11
|
+
class Actions
|
12
|
+
include Dry::Configurable
|
13
|
+
|
14
|
+
setting :cookies, default: {}, constructor: -> options { Cookies.new(options) }
|
15
|
+
setting :sessions, constructor: proc { |storage, *options| Sessions.new(storage, *options) }
|
16
|
+
setting :csrf_protection
|
17
|
+
|
18
|
+
setting :name_inference_base, default: "actions"
|
19
|
+
setting :view_context_identifier, default: "view.context"
|
20
|
+
setting :view_name_inferrer, default: ViewNameInferrer
|
21
|
+
setting :view_name_inference_base, default: "views"
|
22
|
+
|
23
|
+
attr_accessor :content_security_policy
|
24
|
+
|
25
|
+
def initialize(*, **options)
|
26
|
+
super()
|
27
|
+
|
28
|
+
@base_configuration = Configuration.new
|
29
|
+
@content_security_policy = ContentSecurityPolicy.new do |csp|
|
30
|
+
if assets_server_url = options[:assets_server_url]
|
31
|
+
csp[:script_src] += " #{assets_server_url}"
|
32
|
+
csp[:style_src] += " #{assets_server_url}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
configure_defaults
|
37
|
+
end
|
38
|
+
|
39
|
+
def finalize!
|
40
|
+
# A nil value for `csrf_protection` means it has not been explicitly configured
|
41
|
+
# (neither true nor false), so we can default it to whether sessions are enabled
|
42
|
+
self.csrf_protection = sessions.enabled? if csrf_protection.nil?
|
43
|
+
|
44
|
+
if self.content_security_policy
|
45
|
+
self.default_headers["Content-Security-Policy"] = self.content_security_policy.to_str
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the list of available settings
|
50
|
+
#
|
51
|
+
# @return [Set]
|
52
|
+
#
|
53
|
+
# @since 2.0.0
|
54
|
+
# @api private
|
55
|
+
def settings
|
56
|
+
base_configuration.settings + self.class.settings
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
attr_reader :base_configuration
|
62
|
+
|
63
|
+
# Apply defaults for base configuration settings
|
64
|
+
def configure_defaults
|
65
|
+
self.default_request_format = :html
|
66
|
+
self.default_response_format = :html
|
67
|
+
|
68
|
+
self.default_headers = {
|
69
|
+
"X-Frame-Options" => "DENY",
|
70
|
+
"X-Content-Type-Options" => "nosniff",
|
71
|
+
"X-XSS-Protection" => "1; mode=block"
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def method_missing(name, *args, &block)
|
76
|
+
if config.respond_to?(name)
|
77
|
+
config.public_send(name, *args, &block)
|
78
|
+
elsif base_configuration.respond_to?(name)
|
79
|
+
base_configuration.public_send(name, *args, &block)
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def respond_to_missing?(name, _incude_all = false)
|
86
|
+
config.respond_to?(name) || base_configuration.respond_to?(name) || super
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -13,14 +13,58 @@ module Hanami
|
|
13
13
|
|
14
14
|
protected :config
|
15
15
|
|
16
|
+
setting :application_name
|
17
|
+
|
18
|
+
setting :level
|
19
|
+
|
20
|
+
setting :stream
|
21
|
+
|
22
|
+
setting :formatter
|
23
|
+
|
24
|
+
setting :colors
|
25
|
+
|
26
|
+
setting :filters, default: %w[_csrf password password_confirmation].freeze
|
27
|
+
|
28
|
+
setting :options, default: [], constructor: ->(value) { Array(value).flatten }, cloneable: true
|
29
|
+
|
16
30
|
setting :logger_class, default: Hanami::Logger
|
17
31
|
|
18
|
-
|
32
|
+
def initialize(env:, application_name:)
|
33
|
+
@env = env
|
34
|
+
@application_name = application_name
|
35
|
+
|
36
|
+
config.level = case env
|
37
|
+
when :production
|
38
|
+
:info
|
39
|
+
else
|
40
|
+
:debug
|
41
|
+
end
|
19
42
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
43
|
+
config.stream = case env
|
44
|
+
when :test
|
45
|
+
File.join("log", "#{env}.log")
|
46
|
+
else
|
47
|
+
$stdout
|
48
|
+
end
|
49
|
+
|
50
|
+
config.formatter = case env
|
51
|
+
when :production
|
52
|
+
:json
|
53
|
+
end
|
54
|
+
|
55
|
+
config.colors = case env
|
56
|
+
when :production, :test
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def finalize!
|
62
|
+
config.application_name = @application_name.call
|
63
|
+
end
|
64
|
+
|
65
|
+
def instance
|
66
|
+
logger_class.new(application_name, *options, stream: stream, level: level, formatter: formatter, filter: filters, colorizer: colors)
|
67
|
+
end
|
24
68
|
|
25
69
|
private
|
26
70
|
|