hanami 1.3.5 → 2.0.0.alpha4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +196 -5
- data/FEATURES.md +1 -3
- data/README.md +4 -4
- data/hanami.gemspec +27 -30
- data/lib/hanami/application/autoloader/inflector_adapter.rb +22 -0
- data/lib/hanami/application/container/boot/inflector.rb +7 -0
- data/lib/hanami/application/container/boot/logger.rb +7 -0
- data/lib/hanami/application/container/boot/rack_logger.rb +19 -0
- data/lib/hanami/application/container/boot/rack_monitor.rb +12 -0
- data/lib/hanami/application/container/boot/routes_helper.rb +9 -0
- data/lib/hanami/application/container/boot/settings.rb +7 -0
- data/lib/hanami/application/router.rb +59 -0
- data/lib/hanami/application/routes.rb +55 -0
- data/lib/hanami/application/routes_helper.rb +34 -0
- data/lib/hanami/application/routing/middleware/stack.rb +89 -0
- data/lib/hanami/application/routing/resolver/node.rb +50 -0
- data/lib/hanami/application/routing/resolver/trie.rb +59 -0
- data/lib/hanami/application/routing/resolver.rb +87 -0
- data/lib/hanami/application/settings/dotenv_store.rb +60 -0
- data/lib/hanami/application/settings.rb +93 -0
- data/lib/hanami/application.rb +349 -174
- data/lib/hanami/assets/application_configuration.rb +63 -0
- data/lib/hanami/assets/configuration.rb +54 -0
- data/lib/hanami/boot.rb +5 -0
- data/lib/hanami/cli/application/cli.rb +40 -0
- data/lib/hanami/cli/application/command.rb +47 -0
- data/lib/hanami/cli/application/commands/console.rb +81 -0
- data/lib/hanami/cli/application/commands.rb +16 -0
- data/lib/hanami/cli/base_command.rb +48 -0
- data/lib/hanami/cli/commands/command.rb +23 -31
- data/lib/hanami/cli/commands/server.rb +63 -14
- data/lib/hanami/cli/commands.rb +5 -41
- data/lib/hanami/configuration/logger.rb +40 -0
- data/lib/hanami/configuration/middleware.rb +9 -29
- data/lib/hanami/configuration/null_configuration.rb +14 -0
- data/lib/hanami/configuration/router.rb +52 -0
- data/lib/hanami/configuration/sessions.rb +50 -0
- data/lib/hanami/configuration.rb +152 -185
- data/lib/hanami/init.rb +5 -0
- data/lib/hanami/server.rb +5 -69
- data/lib/hanami/setup.rb +8 -2
- data/lib/hanami/slice.rb +167 -0
- data/lib/hanami/version.rb +3 -1
- data/lib/hanami/web/rack_logger.rb +96 -0
- data/lib/hanami.rb +42 -241
- metadata +88 -222
- data/bin/hanami +0 -6
- data/lib/hanami/action/csrf_protection.rb +0 -211
- data/lib/hanami/action/routing_helpers.rb +0 -40
- data/lib/hanami/app.rb +0 -96
- data/lib/hanami/application_configuration.rb +0 -1495
- data/lib/hanami/application_name.rb +0 -108
- data/lib/hanami/application_namespace.rb +0 -14
- data/lib/hanami/assets/asset.rb +0 -72
- data/lib/hanami/assets/static.rb +0 -102
- data/lib/hanami/cli/commands/assets/precompile.rb +0 -42
- data/lib/hanami/cli/commands/assets.rb +0 -16
- data/lib/hanami/cli/commands/console.rb +0 -95
- data/lib/hanami/cli/commands/db/apply.rb +0 -32
- data/lib/hanami/cli/commands/db/console.rb +0 -44
- data/lib/hanami/cli/commands/db/create.rb +0 -32
- data/lib/hanami/cli/commands/db/drop.rb +0 -32
- data/lib/hanami/cli/commands/db/migrate.rb +0 -39
- data/lib/hanami/cli/commands/db/prepare.rb +0 -32
- data/lib/hanami/cli/commands/db/rollback.rb +0 -59
- data/lib/hanami/cli/commands/db/version.rb +0 -32
- data/lib/hanami/cli/commands/db.rb +0 -32
- data/lib/hanami/cli/commands/destroy/action.rb +0 -137
- data/lib/hanami/cli/commands/destroy/app.rb +0 -159
- data/lib/hanami/cli/commands/destroy/mailer.rb +0 -74
- data/lib/hanami/cli/commands/destroy/migration.rb +0 -51
- data/lib/hanami/cli/commands/destroy/model.rb +0 -84
- data/lib/hanami/cli/commands/destroy.rb +0 -26
- data/lib/hanami/cli/commands/generate/action/action.erb +0 -7
- data/lib/hanami/cli/commands/generate/action/action_spec.minitest.erb +0 -11
- data/lib/hanami/cli/commands/generate/action/action_spec.rspec.erb +0 -9
- data/lib/hanami/cli/commands/generate/action/action_without_view.erb +0 -7
- data/lib/hanami/cli/commands/generate/action/view.erb +0 -7
- data/lib/hanami/cli/commands/generate/action/view_spec.minitest.erb +0 -12
- data/lib/hanami/cli/commands/generate/action/view_spec.rspec.erb +0 -10
- data/lib/hanami/cli/commands/generate/action.rb +0 -321
- data/lib/hanami/cli/commands/generate/app/application.erb +0 -313
- data/lib/hanami/cli/commands/generate/app/favicon.ico +0 -0
- data/lib/hanami/cli/commands/generate/app/gitkeep.erb +0 -0
- data/lib/hanami/cli/commands/generate/app/layout.erb +0 -7
- data/lib/hanami/cli/commands/generate/app/layout_spec.minitest.erb +0 -10
- data/lib/hanami/cli/commands/generate/app/layout_spec.rspec.erb +0 -10
- data/lib/hanami/cli/commands/generate/app/routes.erb +0 -5
- data/lib/hanami/cli/commands/generate/app/template.erb.erb +0 -10
- data/lib/hanami/cli/commands/generate/app/template.haml.erb +0 -7
- data/lib/hanami/cli/commands/generate/app/template.slim.erb +0 -8
- data/lib/hanami/cli/commands/generate/app.rb +0 -243
- data/lib/hanami/cli/commands/generate/mailer/mailer.erb +0 -9
- data/lib/hanami/cli/commands/generate/mailer/mailer_spec.minitest.erb +0 -7
- data/lib/hanami/cli/commands/generate/mailer/mailer_spec.rspec.erb +0 -5
- data/lib/hanami/cli/commands/generate/mailer.rb +0 -104
- data/lib/hanami/cli/commands/generate/migration/migration.erb +0 -4
- data/lib/hanami/cli/commands/generate/migration.rb +0 -41
- data/lib/hanami/cli/commands/generate/model/entity.erb +0 -2
- data/lib/hanami/cli/commands/generate/model/entity_spec.minitest.erb +0 -5
- data/lib/hanami/cli/commands/generate/model/entity_spec.rspec.erb +0 -3
- data/lib/hanami/cli/commands/generate/model/migration.erb +0 -10
- data/lib/hanami/cli/commands/generate/model/repository.erb +0 -5
- data/lib/hanami/cli/commands/generate/model/repository_spec.minitest.erb +0 -5
- data/lib/hanami/cli/commands/generate/model/repository_spec.rspec.erb +0 -3
- data/lib/hanami/cli/commands/generate/model.rb +0 -125
- data/lib/hanami/cli/commands/generate/secret.rb +0 -48
- data/lib/hanami/cli/commands/generate.rb +0 -28
- data/lib/hanami/cli/commands/new/.env.development.erb +0 -3
- data/lib/hanami/cli/commands/new/.env.test.erb +0 -3
- data/lib/hanami/cli/commands/new/.gitkeep.erb +0 -0
- data/lib/hanami/cli/commands/new/Gemfile.erb +0 -57
- data/lib/hanami/cli/commands/new/README.md.erb +0 -33
- data/lib/hanami/cli/commands/new/config/boot.erb +0 -2
- data/lib/hanami/cli/commands/new/config/environment.erb +0 -49
- data/lib/hanami/cli/commands/new/config.ru.erb +0 -3
- data/lib/hanami/cli/commands/new/gitignore.erb +0 -4
- data/lib/hanami/cli/commands/new/gitignore_with_sqlite.erb +0 -5
- data/lib/hanami/cli/commands/new/hanamirc.erb +0 -3
- data/lib/hanami/cli/commands/new/lib/project.erb +0 -2
- data/lib/hanami/cli/commands/new/minitest/Rakefile.erb +0 -12
- data/lib/hanami/cli/commands/new/minitest/features_helper.erb +0 -11
- data/lib/hanami/cli/commands/new/minitest/spec_helper.erb +0 -7
- data/lib/hanami/cli/commands/new/rspec/Rakefile.erb +0 -9
- data/lib/hanami/cli/commands/new/rspec/capybara.erb +0 -8
- data/lib/hanami/cli/commands/new/rspec/features_helper.erb +0 -12
- data/lib/hanami/cli/commands/new/rspec/rspec.erb +0 -2
- data/lib/hanami/cli/commands/new/rspec/spec_helper.erb +0 -103
- data/lib/hanami/cli/commands/new/schema.sql.erb +0 -0
- data/lib/hanami/cli/commands/new.rb +0 -578
- data/lib/hanami/cli/commands/project.rb +0 -421
- data/lib/hanami/cli/commands/routes.rb +0 -21
- data/lib/hanami/cli/commands/templates.rb +0 -31
- data/lib/hanami/cli/commands/version.rb +0 -19
- data/lib/hanami/common_logger.rb +0 -109
- data/lib/hanami/components/app/assets.rb +0 -59
- data/lib/hanami/components/app/controller.rb +0 -74
- data/lib/hanami/components/app/routes.rb +0 -59
- data/lib/hanami/components/app/view.rb +0 -44
- data/lib/hanami/components/component.rb +0 -182
- data/lib/hanami/components/components.rb +0 -479
- data/lib/hanami/components/routes_inspector.rb +0 -72
- data/lib/hanami/components.rb +0 -156
- data/lib/hanami/config/cookies.rb +0 -69
- data/lib/hanami/config/framework_configuration.rb +0 -43
- data/lib/hanami/config/load_paths.rb +0 -46
- data/lib/hanami/config/mapper.rb +0 -47
- data/lib/hanami/config/routes.rb +0 -20
- data/lib/hanami/config/security.rb +0 -110
- data/lib/hanami/config/sessions.rb +0 -119
- data/lib/hanami/configuration/app.rb +0 -21
- data/lib/hanami/early_hints.rb +0 -129
- data/lib/hanami/env.rb +0 -69
- data/lib/hanami/environment.rb +0 -541
- data/lib/hanami/environment_application_configurations.rb +0 -37
- data/lib/hanami/frameworks.rb +0 -22
- data/lib/hanami/hanamirc.rb +0 -169
- data/lib/hanami/mailer/glue.rb +0 -27
- data/lib/hanami/middleware_stack.rb +0 -172
- data/lib/hanami/rake_helper.rb +0 -78
- data/lib/hanami/rake_tasks.rb +0 -3
- data/lib/hanami/rendering_policy.rb +0 -94
- data/lib/hanami/routes.rb +0 -219
- data/lib/hanami/routing/default.rb +0 -32
- data/lib/hanami/static.rb +0 -63
- data/lib/hanami/templates/default.html.erb +0 -30
- data/lib/hanami/templates/welcome.html.erb +0 -52
- data/lib/hanami/views/default.rb +0 -37
- data/lib/hanami/views/default_template_finder.rb +0 -22
- data/lib/hanami/views/null_view.rb +0 -15
- data/lib/hanami/welcome.rb +0 -41
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hanami/utils/string"
|
4
|
+
require "hanami/utils/class"
|
5
|
+
|
6
|
+
module Hanami
|
7
|
+
class Configuration
|
8
|
+
# Hanami configuration for HTTP sessions
|
9
|
+
#
|
10
|
+
# @since 2.0.0
|
11
|
+
class Sessions
|
12
|
+
NULL_SESSION_OPTION = :null
|
13
|
+
private_constant :NULL_SESSION_OPTION
|
14
|
+
|
15
|
+
def self.null
|
16
|
+
self.class.new(NULL_SESSION_OPTION)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :storage, :options
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
storage, options, = Array(args.dup).flatten
|
23
|
+
|
24
|
+
@storage = storage
|
25
|
+
@options = options || {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def enabled?
|
29
|
+
storage != NULL_SESSION_OPTION
|
30
|
+
end
|
31
|
+
|
32
|
+
def middleware
|
33
|
+
[[storage_middleware, options]]
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def storage_middleware
|
39
|
+
require_storage
|
40
|
+
|
41
|
+
name = Utils::String.classify(storage)
|
42
|
+
Utils::Class.load!(name, Rack::Session)
|
43
|
+
end
|
44
|
+
|
45
|
+
def require_storage
|
46
|
+
require "rack/session/#{storage}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/hanami/configuration.rb
CHANGED
@@ -1,215 +1,182 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
require "concurrent/hash"
|
5
|
+
require "concurrent/array"
|
6
|
+
require "dry/configurable"
|
7
|
+
require "dry/inflector"
|
8
|
+
require "pathname"
|
9
|
+
|
10
|
+
require_relative "application/settings/dotenv_store"
|
11
|
+
require_relative "configuration/logger"
|
12
|
+
require_relative "configuration/middleware"
|
13
|
+
require_relative "configuration/router"
|
14
|
+
require_relative "configuration/sessions"
|
5
15
|
|
6
16
|
module Hanami
|
7
|
-
#
|
17
|
+
# Hanami application configuration
|
18
|
+
#
|
19
|
+
# @since 2.0.0
|
20
|
+
#
|
21
|
+
# rubocop:disable Metrics/ClassLength
|
8
22
|
class Configuration
|
9
|
-
|
10
|
-
|
23
|
+
include Dry::Configurable
|
24
|
+
|
25
|
+
DEFAULT_ENVIRONMENTS = Concurrent::Hash.new { |h, k| h[k] = Concurrent::Array.new }
|
26
|
+
private_constant :DEFAULT_ENVIRONMENTS
|
27
|
+
|
28
|
+
attr_reader :actions
|
29
|
+
attr_reader :middleware
|
30
|
+
attr_reader :router
|
31
|
+
attr_reader :views, :assets
|
32
|
+
|
33
|
+
attr_reader :environments
|
34
|
+
private :environments
|
35
|
+
|
36
|
+
def initialize(env:)
|
37
|
+
@environments = DEFAULT_ENVIRONMENTS.clone
|
38
|
+
config.env = env
|
39
|
+
|
40
|
+
# Some default setting values must be assigned at initialize-time to ensure they
|
41
|
+
# have appropriate values for the current application
|
42
|
+
self.root = Dir.pwd
|
43
|
+
self.settings_store = Application::Settings::DotenvStore.new.with_dotenv_loaded
|
44
|
+
|
45
|
+
@assets = begin
|
46
|
+
require_path = "hanami/assets/application_configuration"
|
47
|
+
require require_path
|
48
|
+
Hanami::Assets::ApplicationConfiguration.new
|
49
|
+
rescue LoadError => e
|
50
|
+
raise e unless e.path == require_path
|
51
|
+
require_relative "configuration/null_configuration"
|
52
|
+
NullConfiguration.new
|
53
|
+
end
|
54
|
+
|
55
|
+
# Config for actions (same for views, below) may not be available if the gem isn't
|
56
|
+
# loaded; fall back to a null config object if it's missing
|
57
|
+
@actions = begin
|
58
|
+
require_path = "hanami/action/application_configuration"
|
59
|
+
require require_path
|
60
|
+
Hanami::Action::ApplicationConfiguration.new(assets_server_url: assets.server_url)
|
61
|
+
rescue LoadError => e
|
62
|
+
raise e unless e.path == require_path
|
63
|
+
require_relative "configuration/null_configuration"
|
64
|
+
NullConfiguration.new
|
65
|
+
end
|
11
66
|
|
12
|
-
|
13
|
-
|
14
|
-
@
|
15
|
-
|
67
|
+
@middleware = Middleware.new
|
68
|
+
|
69
|
+
@router = Router.new(self)
|
70
|
+
|
71
|
+
@views = begin
|
72
|
+
require_path = "hanami/view/application_configuration"
|
73
|
+
require require_path
|
74
|
+
Hanami::View::ApplicationConfiguration.new
|
75
|
+
rescue LoadError => e
|
76
|
+
raise e unless e.path == require_path
|
77
|
+
require_relative "configuration/null_configuration"
|
78
|
+
NullConfiguration.new
|
79
|
+
end
|
80
|
+
|
81
|
+
yield self if block_given?
|
16
82
|
end
|
17
83
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# @option :host [String] options the mount point
|
24
|
-
#
|
25
|
-
# @since 0.9.0
|
26
|
-
#
|
27
|
-
# @example
|
28
|
-
# # config/environment.rb
|
29
|
-
# # ...
|
30
|
-
# Hanami.configure do
|
31
|
-
# mount Beta::Application, at: '/', host: 'beta.bookshelf.com'
|
32
|
-
# mount Admin::Application, at: '/api'
|
33
|
-
# mount Web::Application, at: '/'
|
34
|
-
#
|
35
|
-
# # ...
|
36
|
-
# end
|
37
|
-
def mount(app, options)
|
38
|
-
mounted[app] = App.new(app, options)
|
84
|
+
def environment(env_name, &block)
|
85
|
+
environments[env_name] << block
|
86
|
+
apply_env_config
|
87
|
+
|
88
|
+
self
|
39
89
|
end
|
40
90
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# adapter :sql, ENV['DATABASE_URL']
|
53
|
-
#
|
54
|
-
# migrations 'db/migrations'
|
55
|
-
# schema 'db/schema.sql'
|
56
|
-
# end
|
57
|
-
#
|
58
|
-
# # ...
|
59
|
-
# end
|
60
|
-
def model(&blk)
|
61
|
-
if block_given?
|
62
|
-
settings.put_if_absent(:model, blk)
|
63
|
-
else
|
64
|
-
settings.fetch(:model)
|
65
|
-
end
|
91
|
+
def finalize!
|
92
|
+
apply_env_config
|
93
|
+
|
94
|
+
# Finalize nested configurations
|
95
|
+
assets.finalize!
|
96
|
+
actions.finalize!
|
97
|
+
views.finalize!
|
98
|
+
logger.finalize!
|
99
|
+
router.finalize!
|
100
|
+
|
101
|
+
super
|
66
102
|
end
|
67
103
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
#
|
74
|
-
# @example
|
75
|
-
# # config/environment.rb
|
76
|
-
# # ...
|
77
|
-
# Hanami.configure do
|
78
|
-
# mailer do
|
79
|
-
# root 'lib/bookshelf/mailers'
|
80
|
-
#
|
81
|
-
# # See https://guides.hanamirb.org/mailers/delivery
|
82
|
-
# delivery :test
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# # ...
|
86
|
-
# end
|
87
|
-
def mailer(&blk)
|
88
|
-
mailer_settings.push(blk) if block_given?
|
104
|
+
setting :env
|
105
|
+
|
106
|
+
def env=(new_env)
|
107
|
+
config.env = env
|
108
|
+
apply_env_config(new_env)
|
89
109
|
end
|
90
110
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
111
|
+
setting :root, constructor: -> path { Pathname(path) }
|
112
|
+
|
113
|
+
setting :inflector, default: Dry::Inflector.new, cloneable: true
|
114
|
+
|
115
|
+
def inflections(&block)
|
116
|
+
self.inflector = Dry::Inflector.new(&block)
|
95
117
|
end
|
96
118
|
|
97
|
-
|
98
|
-
|
99
|
-
def
|
100
|
-
|
119
|
+
setting :logger, default: Configuration::Logger.new, cloneable: true
|
120
|
+
|
121
|
+
def logger=(logger_instance)
|
122
|
+
@logger_instance = logger_instance
|
101
123
|
end
|
102
124
|
|
103
|
-
|
104
|
-
|
105
|
-
# @example
|
106
|
-
# # config/environment.rb
|
107
|
-
# # ...
|
108
|
-
# Hanami.configure do
|
109
|
-
# middleware.use MyRackMiddleware
|
110
|
-
# end
|
111
|
-
def middleware
|
112
|
-
settings.fetch_or_store(:middleware, Configuration::Middleware.new)
|
125
|
+
def logger_instance
|
126
|
+
@logger_instance || logger.logger_class.new(**logger.options)
|
113
127
|
end
|
114
128
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
#
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
#
|
130
|
-
#
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
else
|
136
|
-
settings[:early_hints] = value
|
137
|
-
end
|
129
|
+
setting :settings_path, default: File.join("config", "settings")
|
130
|
+
|
131
|
+
setting :settings_class_name, default: "Settings"
|
132
|
+
|
133
|
+
setting :settings_store, default: Application::Settings::DotenvStore
|
134
|
+
|
135
|
+
setting :slices_dir, default: "slices"
|
136
|
+
|
137
|
+
setting :slices_namespace, default: Object
|
138
|
+
|
139
|
+
# TODO: convert into a dedicated object with explicit behaviour around blocks per
|
140
|
+
# slice, etc.
|
141
|
+
setting :slices, default: {}, constructor: :dup.to_proc
|
142
|
+
|
143
|
+
# TODO: turn this into a richer "source dirs" setting that can support enabling
|
144
|
+
# of container component loading as an opt in behvior
|
145
|
+
setting :component_dir_paths, default: %w[actions repositories views]
|
146
|
+
|
147
|
+
def slice(slice_name, &block)
|
148
|
+
slices[slice_name] = block
|
138
149
|
end
|
139
150
|
|
140
|
-
|
141
|
-
|
142
|
-
def
|
143
|
-
|
144
|
-
|
151
|
+
setting :base_url, default: "http://0.0.0.0:2300", constructor: -> url { URI(url) }
|
152
|
+
|
153
|
+
def for_each_middleware(&blk)
|
154
|
+
stack = middleware.stack.dup
|
155
|
+
stack += sessions.middleware if sessions.enabled?
|
156
|
+
|
157
|
+
stack.each(&blk)
|
158
|
+
end
|
159
|
+
|
160
|
+
setting :sessions, default: :null, constructor: -> *args { Sessions.new(*args) }
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def apply_env_config(env = self.env)
|
165
|
+
environments[env].each do |block|
|
166
|
+
instance_eval(&block)
|
145
167
|
end
|
146
168
|
end
|
147
169
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
#
|
152
|
-
# @param options [Array] a set of options
|
153
|
-
#
|
154
|
-
# @see Hanami.logger
|
155
|
-
# @see Hanami::Logger
|
156
|
-
#
|
157
|
-
# @see https://guides.hanamirb.org/projects/logging
|
158
|
-
#
|
159
|
-
# @example Basic Usage
|
160
|
-
# # config/environment.rb
|
161
|
-
# # ...
|
162
|
-
# Hanami.configure do
|
163
|
-
# # ...
|
164
|
-
# environment :development do
|
165
|
-
# logger level: :debug
|
166
|
-
# end
|
167
|
-
# end
|
168
|
-
#
|
169
|
-
# @example Daily Rotation
|
170
|
-
# # config/environment.rb
|
171
|
-
# # ...
|
172
|
-
# Hanami.configure do
|
173
|
-
# # ...
|
174
|
-
# environment :development do
|
175
|
-
# logger 'daily', level: :debug
|
176
|
-
# end
|
177
|
-
# end
|
178
|
-
def logger(*options)
|
179
|
-
if options.empty?
|
180
|
-
settings.fetch(:logger, nil)
|
170
|
+
def method_missing(name, *args, &block)
|
171
|
+
if config.respond_to?(name)
|
172
|
+
config.public_send(name, *args, &block)
|
181
173
|
else
|
182
|
-
|
174
|
+
super
|
183
175
|
end
|
184
176
|
end
|
185
177
|
|
186
|
-
|
187
|
-
|
188
|
-
#
|
189
|
-
# @param name [Symbol] the name of the Hanami environment
|
190
|
-
#
|
191
|
-
# @see Hanami.env
|
192
|
-
#
|
193
|
-
# @example Configure Logging for Different Environments
|
194
|
-
# # config/environment.rb
|
195
|
-
# # ...
|
196
|
-
# Hanami.configure do
|
197
|
-
# # ...
|
198
|
-
# environment :development do
|
199
|
-
# logger level: :debug
|
200
|
-
# end
|
201
|
-
#
|
202
|
-
# environment :production do
|
203
|
-
# logger level: :info, formatter: :json
|
204
|
-
# end
|
205
|
-
# end
|
206
|
-
def environment(name)
|
207
|
-
yield if ENV['HANAMI_ENV'] == name.to_s
|
178
|
+
def respond_to_missing?(name, _incude_all = false)
|
179
|
+
config.respond_to?(name) || super
|
208
180
|
end
|
209
|
-
|
210
|
-
private
|
211
|
-
|
212
|
-
# @api private
|
213
|
-
attr_reader :settings
|
214
181
|
end
|
215
182
|
end
|
data/lib/hanami/init.rb
ADDED
data/lib/hanami/server.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hanami"
|
4
|
+
require "rack"
|
2
5
|
|
3
6
|
module Hanami
|
4
7
|
# Rack compatible server.
|
@@ -13,81 +16,14 @@ module Hanami
|
|
13
16
|
# @since 0.8.0
|
14
17
|
# @api private
|
15
18
|
class Server < ::Rack::Server
|
16
|
-
# @api private
|
17
|
-
attr_reader :options
|
18
|
-
|
19
|
-
# @since 0.8.0
|
20
|
-
# @api private
|
21
|
-
#
|
22
|
-
# @see Hanami::Environment#initialize
|
23
|
-
def initialize
|
24
|
-
@options = _extract_options
|
25
|
-
setup
|
26
|
-
end
|
27
|
-
|
28
19
|
# Primarily this removes the ::Rack::Chunked middleware
|
29
20
|
# which is the cause of Safari content-length bugs.
|
30
21
|
#
|
31
22
|
# @since 0.8.0
|
32
23
|
def middleware
|
33
|
-
mw = Hash.new { |e, m| e[m] = [] }
|
24
|
+
mw = ::Hash.new { |e, m| e[m] = [] }
|
34
25
|
mw["development"].concat([::Rack::ShowExceptions, ::Rack::Lint])
|
35
|
-
require 'hanami/assets/static'
|
36
|
-
mw["development"].push(::Hanami::Assets::Static)
|
37
26
|
mw
|
38
27
|
end
|
39
|
-
|
40
|
-
# @api private
|
41
|
-
def start
|
42
|
-
preload
|
43
|
-
super
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
# @api private
|
49
|
-
def setup
|
50
|
-
return unless code_reloading?
|
51
|
-
@app = Shotgun::Loader.new(rackup)
|
52
|
-
end
|
53
|
-
|
54
|
-
# @api private
|
55
|
-
def environment
|
56
|
-
Components['environment']
|
57
|
-
end
|
58
|
-
|
59
|
-
# @since 0.8.0
|
60
|
-
# @api private
|
61
|
-
def code_reloading?
|
62
|
-
Hanami.code_reloading?
|
63
|
-
end
|
64
|
-
|
65
|
-
# @api private
|
66
|
-
def rackup
|
67
|
-
environment.rackup.to_s
|
68
|
-
end
|
69
|
-
|
70
|
-
# @api private
|
71
|
-
def preload
|
72
|
-
if code_reloading?
|
73
|
-
Shotgun.enable_copy_on_write
|
74
|
-
Shotgun.preload
|
75
|
-
else
|
76
|
-
Hanami.boot
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Options for Rack::Server superclass
|
81
|
-
#
|
82
|
-
# @since 0.8.0
|
83
|
-
# @api private
|
84
|
-
def _extract_options
|
85
|
-
environment.to_options.merge(
|
86
|
-
config: rackup,
|
87
|
-
Host: environment.host,
|
88
|
-
Port: environment.port,
|
89
|
-
AccessLog: []
|
90
|
-
)
|
91
|
-
end
|
92
28
|
end
|
93
29
|
end
|
data/lib/hanami/setup.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "bundler/setup"
|
4
|
+
require "hanami"
|
5
|
+
|
6
|
+
begin
|
7
|
+
require File.join(Dir.pwd, "config/application")
|
8
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
9
|
+
end
|
data/lib/hanami/slice.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/system/container"
|
4
|
+
require "dry/system/loader/autoloading"
|
5
|
+
require "pathname"
|
6
|
+
|
7
|
+
module Hanami
|
8
|
+
# Distinct area of concern within an Hanami application
|
9
|
+
#
|
10
|
+
# @since 2.0.0
|
11
|
+
class Slice
|
12
|
+
attr_reader :application, :name, :namespace, :root
|
13
|
+
|
14
|
+
def initialize(application, name:, namespace: nil, root: nil, container: nil)
|
15
|
+
@application = application
|
16
|
+
@name = name.to_sym
|
17
|
+
@namespace = namespace
|
18
|
+
@root = root ? Pathname(root) : root
|
19
|
+
@container = container || define_container
|
20
|
+
end
|
21
|
+
|
22
|
+
def inflector
|
23
|
+
application.inflector
|
24
|
+
end
|
25
|
+
|
26
|
+
def namespace_path
|
27
|
+
@namespace_path ||= inflector.underscore(namespace.to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
def init
|
31
|
+
container.import application: application.container
|
32
|
+
|
33
|
+
slice_block = application.configuration.slices[name]
|
34
|
+
instance_eval(&slice_block) if slice_block
|
35
|
+
end
|
36
|
+
|
37
|
+
def boot
|
38
|
+
container.finalize! do
|
39
|
+
container.config.env = application.container.config.env
|
40
|
+
end
|
41
|
+
|
42
|
+
@booted = true
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
# rubocop:disable Style/DoubleNegation
|
47
|
+
def booted?
|
48
|
+
!!@booted
|
49
|
+
end
|
50
|
+
# rubocop:enable Style/DoubleNegation
|
51
|
+
|
52
|
+
def container
|
53
|
+
@container ||= define_container
|
54
|
+
end
|
55
|
+
|
56
|
+
def import(*slice_names)
|
57
|
+
raise "Cannot import after booting" if booted?
|
58
|
+
|
59
|
+
slice_names.each do |slice_name|
|
60
|
+
container.import slice_name.to_sym => application.slices.fetch(slice_name.to_sym).container
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def register(*args, &block)
|
65
|
+
container.register(*args, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def register_bootable(*args, &block)
|
69
|
+
container.boot(*args, &block)
|
70
|
+
end
|
71
|
+
|
72
|
+
def init_bootable(*args)
|
73
|
+
container.init(*args)
|
74
|
+
end
|
75
|
+
|
76
|
+
def start_bootable(*args)
|
77
|
+
container.start(*args)
|
78
|
+
end
|
79
|
+
|
80
|
+
def key?(*args)
|
81
|
+
container.key?(*args)
|
82
|
+
end
|
83
|
+
|
84
|
+
def keys
|
85
|
+
container.keys
|
86
|
+
end
|
87
|
+
|
88
|
+
def [](*args)
|
89
|
+
container[*args]
|
90
|
+
end
|
91
|
+
|
92
|
+
def resolve(*args)
|
93
|
+
container.resolve(*args)
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
99
|
+
def define_container
|
100
|
+
container = Class.new(Dry::System::Container)
|
101
|
+
container.use :env
|
102
|
+
|
103
|
+
container.configure do |config|
|
104
|
+
config.name = name
|
105
|
+
config.inflector = application.configuration.inflector
|
106
|
+
|
107
|
+
config.component_dirs.loader = Dry::System::Loader::Autoloading
|
108
|
+
config.component_dirs.add_to_load_path = false
|
109
|
+
|
110
|
+
if root&.directory?
|
111
|
+
config.root = root
|
112
|
+
config.bootable_dirs = ["config/boot"]
|
113
|
+
|
114
|
+
# Add the "lib" component dir; all slices will load components from lib
|
115
|
+
if root.join("lib").directory?
|
116
|
+
config.component_dirs.add("lib") do |component_dir|
|
117
|
+
# Expect component files in the root of the lib
|
118
|
+
# component dir to define classes inside the slice's namespace.
|
119
|
+
#
|
120
|
+
# e.g. "lib/foo.rb" should define SliceNamespace::Foo, and will be
|
121
|
+
# registered as "foo"
|
122
|
+
component_dir.namespaces.root(key: nil, const: namespace_path)
|
123
|
+
|
124
|
+
application.autoloader.push_dir(root.join("lib"), namespace: namespace)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Add component dirs for each configured component path
|
129
|
+
application.configuration.component_dir_paths.each do |slice_dir|
|
130
|
+
next unless root.join(slice_dir).directory?
|
131
|
+
|
132
|
+
config.component_dirs.add(slice_dir) do |component_dir|
|
133
|
+
# Expect component files in the root of these component dirs to define
|
134
|
+
# classes inside a namespace matching the dir.
|
135
|
+
#
|
136
|
+
# e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, and
|
137
|
+
# will be registered as "actions.foo"
|
138
|
+
|
139
|
+
dir_namespace_path = File.join(namespace_path, slice_dir)
|
140
|
+
|
141
|
+
autoloader_namespace = begin
|
142
|
+
inflector.constantize(inflector.camelize(dir_namespace_path))
|
143
|
+
rescue NameError
|
144
|
+
namespace.const_set(inflector.camelize(slice_dir), Module.new)
|
145
|
+
end
|
146
|
+
|
147
|
+
component_dir.namespaces.root(const: dir_namespace_path, key: slice_dir)
|
148
|
+
|
149
|
+
application.autoloader.push_dir(
|
150
|
+
container.root.join(slice_dir),
|
151
|
+
namespace: autoloader_namespace
|
152
|
+
)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
if namespace
|
159
|
+
namespace.const_set :Container, container
|
160
|
+
namespace.const_set :Deps, container.injector
|
161
|
+
end
|
162
|
+
|
163
|
+
container
|
164
|
+
end
|
165
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
166
|
+
end
|
167
|
+
end
|