piko-lite-box 0.0.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.
- checksums.yaml +7 -0
- data/hanami-3.0.1/CHANGELOG.md +1701 -0
- data/hanami-3.0.1/LICENSE +20 -0
- data/hanami-3.0.1/README.md +89 -0
- data/hanami-3.0.1/hanami.gemspec +49 -0
- data/hanami-3.0.1/lib/hanami/app.rb +197 -0
- data/hanami-3.0.1/lib/hanami/boot.rb +5 -0
- data/hanami-3.0.1/lib/hanami/config/actions/content_security_policy.rb +140 -0
- data/hanami-3.0.1/lib/hanami/config/actions/cookies.rb +57 -0
- data/hanami-3.0.1/lib/hanami/config/actions/sessions.rb +83 -0
- data/hanami-3.0.1/lib/hanami/config/actions.rb +189 -0
- data/hanami-3.0.1/lib/hanami/config/assets.rb +84 -0
- data/hanami-3.0.1/lib/hanami/config/console.rb +79 -0
- data/hanami-3.0.1/lib/hanami/config/db.rb +35 -0
- data/hanami-3.0.1/lib/hanami/config/i18n.rb +138 -0
- data/hanami-3.0.1/lib/hanami/config/logger.rb +207 -0
- data/hanami-3.0.1/lib/hanami/config/null_config.rb +17 -0
- data/hanami-3.0.1/lib/hanami/config/router.rb +48 -0
- data/hanami-3.0.1/lib/hanami/config/views.rb +103 -0
- data/hanami-3.0.1/lib/hanami/config.rb +564 -0
- data/hanami-3.0.1/lib/hanami/constants.rb +62 -0
- data/hanami-3.0.1/lib/hanami/env.rb +52 -0
- data/hanami-3.0.1/lib/hanami/errors.rb +41 -0
- data/hanami-3.0.1/lib/hanami/extensions/action/i18n_helper.rb +64 -0
- data/hanami-3.0.1/lib/hanami/extensions/action/name_inferrer.rb +34 -0
- data/hanami-3.0.1/lib/hanami/extensions/action/slice_configured_action.rb +190 -0
- data/hanami-3.0.1/lib/hanami/extensions/action.rb +147 -0
- data/hanami-3.0.1/lib/hanami/extensions/db/repo.rb +108 -0
- data/hanami-3.0.1/lib/hanami/extensions/mailer/slice_configured_mailer.rb +134 -0
- data/hanami-3.0.1/lib/hanami/extensions/mailer.rb +28 -0
- data/hanami-3.0.1/lib/hanami/extensions/operation/slice_configured_db_operation.rb +90 -0
- data/hanami-3.0.1/lib/hanami/extensions/operation.rb +33 -0
- data/hanami-3.0.1/lib/hanami/extensions/router/errors.rb +58 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/context.rb +298 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/part.rb +92 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/scope.rb +36 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_context.rb +73 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_helpers.rb +55 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_part.rb +73 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_view.rb +243 -0
- data/hanami-3.0.1/lib/hanami/extensions/view/standard_helpers.rb +26 -0
- data/hanami-3.0.1/lib/hanami/extensions/view.rb +38 -0
- data/hanami-3.0.1/lib/hanami/extensions.rb +30 -0
- data/hanami-3.0.1/lib/hanami/helpers/assets_helper.rb +804 -0
- data/hanami-3.0.1/lib/hanami/helpers/form_helper/form_builder.rb +1389 -0
- data/hanami-3.0.1/lib/hanami/helpers/form_helper/values.rb +75 -0
- data/hanami-3.0.1/lib/hanami/helpers/form_helper.rb +213 -0
- data/hanami-3.0.1/lib/hanami/helpers/i18n_helper.rb +241 -0
- data/hanami-3.0.1/lib/hanami/logger/rack_formatter.rb +73 -0
- data/hanami-3.0.1/lib/hanami/logger/sql_formatter.rb +80 -0
- data/hanami-3.0.1/lib/hanami/logger/sql_logger.rb +48 -0
- data/hanami-3.0.1/lib/hanami/middleware/assets.rb +21 -0
- data/hanami-3.0.1/lib/hanami/middleware/content_security_policy_nonce.rb +53 -0
- data/hanami-3.0.1/lib/hanami/middleware/public_errors_app.rb +75 -0
- data/hanami-3.0.1/lib/hanami/middleware/render_errors.rb +90 -0
- data/hanami-3.0.1/lib/hanami/port.rb +45 -0
- data/hanami-3.0.1/lib/hanami/prepare.rb +5 -0
- data/hanami-3.0.1/lib/hanami/provider/source.rb +16 -0
- data/hanami-3.0.1/lib/hanami/provider_registrar.rb +28 -0
- data/hanami-3.0.1/lib/hanami/providers/assets.rb +28 -0
- data/hanami-3.0.1/lib/hanami/providers/db/adapter.rb +75 -0
- data/hanami-3.0.1/lib/hanami/providers/db/adapters.rb +66 -0
- data/hanami-3.0.1/lib/hanami/providers/db/config.rb +44 -0
- data/hanami-3.0.1/lib/hanami/providers/db/gateway.rb +87 -0
- data/hanami-3.0.1/lib/hanami/providers/db/sql_adapter.rb +100 -0
- data/hanami-3.0.1/lib/hanami/providers/db.rb +325 -0
- data/hanami-3.0.1/lib/hanami/providers/db_logging.rb +19 -0
- data/hanami-3.0.1/lib/hanami/providers/i18n/backend.rb +373 -0
- data/hanami-3.0.1/lib/hanami/providers/i18n/locale/en.yml +57 -0
- data/hanami-3.0.1/lib/hanami/providers/i18n.rb +114 -0
- data/hanami-3.0.1/lib/hanami/providers/inflector.rb +17 -0
- data/hanami-3.0.1/lib/hanami/providers/logger.rb +41 -0
- data/hanami-3.0.1/lib/hanami/providers/mailers.rb +101 -0
- data/hanami-3.0.1/lib/hanami/providers/rack.rb +47 -0
- data/hanami-3.0.1/lib/hanami/providers/relations.rb +31 -0
- data/hanami-3.0.1/lib/hanami/providers/routes.rb +29 -0
- data/hanami-3.0.1/lib/hanami/rake_tasks.rb +54 -0
- data/hanami-3.0.1/lib/hanami/routes.rb +146 -0
- data/hanami-3.0.1/lib/hanami/settings/composite_store.rb +53 -0
- data/hanami-3.0.1/lib/hanami/settings/env_store.rb +32 -0
- data/hanami-3.0.1/lib/hanami/settings.rb +234 -0
- data/hanami-3.0.1/lib/hanami/setup.rb +6 -0
- data/hanami-3.0.1/lib/hanami/slice/router.rb +280 -0
- data/hanami-3.0.1/lib/hanami/slice/routes_helper.rb +37 -0
- data/hanami-3.0.1/lib/hanami/slice/routing/middleware/stack.rb +216 -0
- data/hanami-3.0.1/lib/hanami/slice/routing/resolver.rb +88 -0
- data/hanami-3.0.1/lib/hanami/slice/view_name_inferrer.rb +63 -0
- data/hanami-3.0.1/lib/hanami/slice.rb +1239 -0
- data/hanami-3.0.1/lib/hanami/slice_configurable.rb +72 -0
- data/hanami-3.0.1/lib/hanami/slice_name.rb +111 -0
- data/hanami-3.0.1/lib/hanami/slice_registrar.rb +215 -0
- data/hanami-3.0.1/lib/hanami/universal_logger.rb +250 -0
- data/hanami-3.0.1/lib/hanami/version.rb +45 -0
- data/hanami-3.0.1/lib/hanami/web/rack_logger.rb +126 -0
- data/hanami-3.0.1/lib/hanami/web/welcome.html.erb +584 -0
- data/hanami-3.0.1/lib/hanami/web/welcome.rb +46 -0
- data/hanami-3.0.1/lib/hanami.rb +276 -0
- data/piko-lite-box.gemspec +11 -0
- metadata +137 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module Logger
|
|
5
|
+
# SQL query logger that integrates with the Hanami logger using structured, tagged logging.
|
|
6
|
+
#
|
|
7
|
+
# Subscribes to `:sql` notification events (emitted by ROM via the Hanami app's
|
|
8
|
+
# `"notifications"` component) and logs each query as a structured payload. The log entries are
|
|
9
|
+
# tagged as `:sql`, which allows Dry Logger backends to route them to a dedicated formatter (see
|
|
10
|
+
# {SQLFormatter}), in the same way that rack log entries are routed using the `:rack` tag.
|
|
11
|
+
#
|
|
12
|
+
# @see SQLFormatter
|
|
13
|
+
# @see Hanami::Providers::DBLogging
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
class SQLLogger
|
|
17
|
+
attr_reader :logger, :level
|
|
18
|
+
|
|
19
|
+
# @param logger [#tagged, #info] a Hanami-compatible logger (typically a
|
|
20
|
+
# Dry::Logger::Dispatcher or a {Hanami::UniversalLogger}-wrapped logger)
|
|
21
|
+
def initialize(logger, level: :debug)
|
|
22
|
+
@logger = logger
|
|
23
|
+
@level = level
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Subscribes to `:sql` notification events.
|
|
27
|
+
#
|
|
28
|
+
# @param notifications [Dry::Monitor::Notifications] the notifications bus
|
|
29
|
+
# @return [void]
|
|
30
|
+
def subscribe(notifications)
|
|
31
|
+
notifications.subscribe(:sql) { |params| log_query(**params) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Log a SQL query with structured data.
|
|
35
|
+
#
|
|
36
|
+
# @param time [Numeric] elapsed time in milliseconds
|
|
37
|
+
# @param name [Symbol] database adapter name (e.g. `:sqlite`, `:postgres`)
|
|
38
|
+
# @param query [String] the SQL query string
|
|
39
|
+
def log_query(time:, name:, query:)
|
|
40
|
+
logger.tagged(:sql) do
|
|
41
|
+
logger.public_send(@level) do
|
|
42
|
+
{query:, db: name, elapsed: time.round(3), elapsed_unit: "ms"}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rack/static"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module Middleware
|
|
7
|
+
class Assets < Rack::Static
|
|
8
|
+
def initialize(app, options = {}, config: Hanami.app.config)
|
|
9
|
+
root = config.actions.public_directory
|
|
10
|
+
urls = [config.assets.path_prefix]
|
|
11
|
+
|
|
12
|
+
defaults = {
|
|
13
|
+
root: root,
|
|
14
|
+
urls: urls
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
super(app, defaults.merge(options))
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rack"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
require_relative "../constants"
|
|
6
|
+
|
|
7
|
+
module Hanami
|
|
8
|
+
module Middleware
|
|
9
|
+
# Generates a random per request nonce value like `mSMnSwfVZVe+LyQy1SPCGw==`, stores it as
|
|
10
|
+
# `"hanami.content_security_policy_nonce"` in the Rack environment, and replaces all occurrences
|
|
11
|
+
# of `'nonce'` in the `Content-Security-Policy header with the actual nonce value for the
|
|
12
|
+
# request, e.g. `'nonce-mSMnSwfVZVe+LyQy1SPCGw=='`.
|
|
13
|
+
#
|
|
14
|
+
# @see Hanami::Middleware::ContentSecurityPolicyNonce
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
# @since 2.3.0
|
|
18
|
+
class ContentSecurityPolicyNonce
|
|
19
|
+
# @api private
|
|
20
|
+
# @since 2.3.0
|
|
21
|
+
def initialize(app)
|
|
22
|
+
@app = app
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
# @since 2.3.0
|
|
27
|
+
def call(env)
|
|
28
|
+
return @app.call(env) unless Hanami.app.config.actions.content_security_policy?
|
|
29
|
+
|
|
30
|
+
args = nonce_generator.arity == 1 ? [Rack::Request.new(env)] : []
|
|
31
|
+
request_nonce = nonce_generator.call(*args)
|
|
32
|
+
|
|
33
|
+
env[CONTENT_SECURITY_POLICY_NONCE_REQUEST_KEY] = request_nonce
|
|
34
|
+
|
|
35
|
+
_, headers, _ = response = @app.call(env)
|
|
36
|
+
|
|
37
|
+
headers["Content-Security-Policy"] = sub_nonce(headers["Content-Security-Policy"], request_nonce)
|
|
38
|
+
|
|
39
|
+
response
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def nonce_generator
|
|
45
|
+
Hanami.app.config.actions.content_security_policy_nonce_generator
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def sub_nonce(string, nonce)
|
|
49
|
+
string&.gsub("'nonce'", "'nonce-#{nonce}'")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rack"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module Middleware
|
|
7
|
+
# The errors app given to {Hanami::Middleware::RenderErrors}, which renders error responses
|
|
8
|
+
# from HTML pages kept in `public/` as simple JSON structures.
|
|
9
|
+
#
|
|
10
|
+
# @see Hanami::Middleware::RenderErrors
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
# @since 2.1.0
|
|
14
|
+
class PublicErrorsApp
|
|
15
|
+
# @api private
|
|
16
|
+
# @since 2.1.0
|
|
17
|
+
attr_reader :public_path
|
|
18
|
+
|
|
19
|
+
# @api private
|
|
20
|
+
# @since 2.1.0
|
|
21
|
+
def initialize(public_path)
|
|
22
|
+
@public_path = public_path
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
# @since 2.1.0
|
|
27
|
+
def call(env)
|
|
28
|
+
request = Rack::Request.new(env)
|
|
29
|
+
status = request.path_info[1..].to_i
|
|
30
|
+
content_type = request.get_header("HTTP_ACCEPT")
|
|
31
|
+
|
|
32
|
+
default_body = {
|
|
33
|
+
status: status,
|
|
34
|
+
error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
render(status, content_type, default_body)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def render(status, content_type, default_body)
|
|
43
|
+
body, rendered_content_type = render_content(status, content_type, default_body)
|
|
44
|
+
|
|
45
|
+
[
|
|
46
|
+
status,
|
|
47
|
+
{
|
|
48
|
+
"Content-Type" => "#{rendered_content_type}; charset=utf-8",
|
|
49
|
+
"Content-Length" => body.bytesize.to_s
|
|
50
|
+
},
|
|
51
|
+
[body]
|
|
52
|
+
]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def render_content(status, content_type, default_body)
|
|
56
|
+
if content_type.to_s.start_with?("application/json")
|
|
57
|
+
require "json"
|
|
58
|
+
[JSON.generate(default_body), "application/json"]
|
|
59
|
+
else
|
|
60
|
+
[render_html_content(status, default_body), "text/html"]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def render_html_content(status, default_body)
|
|
65
|
+
path = "#{public_path}/#{status}.html"
|
|
66
|
+
|
|
67
|
+
if File.exist?(path)
|
|
68
|
+
File.read(path)
|
|
69
|
+
else
|
|
70
|
+
default_body[:error]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rack"
|
|
4
|
+
|
|
5
|
+
# rubocop:disable Lint/RescueException
|
|
6
|
+
|
|
7
|
+
module Hanami
|
|
8
|
+
module Middleware
|
|
9
|
+
# Rack middleware that rescues errors raised by the app renders friendly error responses, via a
|
|
10
|
+
# given "errors app".
|
|
11
|
+
#
|
|
12
|
+
# By default, this is enabled only in production mode.
|
|
13
|
+
#
|
|
14
|
+
# @see Hanami::Config#render_errors
|
|
15
|
+
# @see Hanani::Middleware::PublicErrorsApp
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
# @since 2.1.0
|
|
19
|
+
class RenderErrors
|
|
20
|
+
# @api private
|
|
21
|
+
# @since 2.1.0
|
|
22
|
+
class RenderableException
|
|
23
|
+
attr_reader :exception
|
|
24
|
+
attr_reader :responses
|
|
25
|
+
|
|
26
|
+
# @api private
|
|
27
|
+
# @since 2.1.0
|
|
28
|
+
def initialize(exception, responses:)
|
|
29
|
+
@exception = exception
|
|
30
|
+
@responses = responses
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
# @since 2.1.0
|
|
35
|
+
def rescue_response?
|
|
36
|
+
responses.key?(exception.class.name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @api private
|
|
40
|
+
# @since 2.1.0
|
|
41
|
+
def status_code
|
|
42
|
+
Rack::Utils.status_code(responses[exception.class.name])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @api private
|
|
47
|
+
# @since 2.1.0
|
|
48
|
+
def initialize(app, config, errors_app)
|
|
49
|
+
@app = app
|
|
50
|
+
@config = config
|
|
51
|
+
@errors_app = errors_app
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @api private
|
|
55
|
+
# @since 2.1.0
|
|
56
|
+
def call(env)
|
|
57
|
+
@app.call(env)
|
|
58
|
+
rescue Exception => exception
|
|
59
|
+
raise unless @config.render_errors
|
|
60
|
+
|
|
61
|
+
render_exception(env, exception)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def render_exception(env, exception)
|
|
67
|
+
request = Rack::Request.new(env)
|
|
68
|
+
renderable = RenderableException.new(exception, responses: @config.render_error_responses)
|
|
69
|
+
|
|
70
|
+
status = renderable.status_code
|
|
71
|
+
request.path_info = "/#{status}"
|
|
72
|
+
request.set_header(Rack::REQUEST_METHOD, "GET")
|
|
73
|
+
|
|
74
|
+
@errors_app.call(request.env)
|
|
75
|
+
rescue Exception => exception
|
|
76
|
+
# rubocop:disable Style/StderrPuts
|
|
77
|
+
$stderr.puts "Error during exception rendering: #{exception}\n #{exception.backtrace * "\n "}"
|
|
78
|
+
# rubocop:enable Style/StderrPuts
|
|
79
|
+
|
|
80
|
+
[
|
|
81
|
+
500,
|
|
82
|
+
{"Content-Type" => "text/plain; charset=utf-8"},
|
|
83
|
+
["Internal Server Error"]
|
|
84
|
+
]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# rubocop:enable Lint/RescueException
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
# @since 2.0.1
|
|
5
|
+
# @api private
|
|
6
|
+
module Port
|
|
7
|
+
# @since 2.0.1
|
|
8
|
+
# @api private
|
|
9
|
+
DEFAULT = 2300
|
|
10
|
+
|
|
11
|
+
# @since 2.0.1
|
|
12
|
+
# @api private
|
|
13
|
+
ENV_VAR = "HANAMI_PORT"
|
|
14
|
+
|
|
15
|
+
# @since 2.0.1
|
|
16
|
+
# @api private
|
|
17
|
+
def self.call(value, env = ENV.fetch(ENV_VAR, nil))
|
|
18
|
+
return Integer(value) if !value.nil? && !default?(value)
|
|
19
|
+
return Integer(env) unless env.nil?
|
|
20
|
+
return Integer(value) unless value.nil?
|
|
21
|
+
|
|
22
|
+
DEFAULT
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @since 2.0.1
|
|
26
|
+
# @api private
|
|
27
|
+
def self.call!(value)
|
|
28
|
+
return if default?(value)
|
|
29
|
+
|
|
30
|
+
ENV[ENV_VAR] = value.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @since 2.0.1
|
|
34
|
+
# @api private
|
|
35
|
+
def self.default?(value)
|
|
36
|
+
value.to_i == DEFAULT
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
# @since 2.0.1
|
|
41
|
+
# @api private
|
|
42
|
+
alias_method :[], :call
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module Provider
|
|
5
|
+
class Source < Dry::System::Provider::Source
|
|
6
|
+
attr_reader :slice
|
|
7
|
+
|
|
8
|
+
def initialize(slice:, **options, &block)
|
|
9
|
+
@slice = slice
|
|
10
|
+
super(**options, &block)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def target_container = slice
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @api private
|
|
4
|
+
# @since 2.2.0
|
|
5
|
+
module Hanami
|
|
6
|
+
class ProviderRegistrar < Dry::System::ProviderRegistrar
|
|
7
|
+
def self.for_slice(slice)
|
|
8
|
+
Class.new(self) do
|
|
9
|
+
define_singleton_method(:new) do |container|
|
|
10
|
+
super(container, slice)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :slice
|
|
16
|
+
|
|
17
|
+
def initialize(container, slice)
|
|
18
|
+
super(container)
|
|
19
|
+
@slice = slice
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def provider_source_class = Hanami::Provider::Source
|
|
23
|
+
|
|
24
|
+
def provider_source_options
|
|
25
|
+
{slice: slice}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
# @api private
|
|
5
|
+
module Providers
|
|
6
|
+
# Provider source to register routes helper component in Hanami slices.
|
|
7
|
+
#
|
|
8
|
+
# @see Hanami::Slice::RoutesHelper
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
# @since 2.0.0
|
|
12
|
+
class Assets < Hanami::Provider::Source
|
|
13
|
+
# @api private
|
|
14
|
+
def prepare
|
|
15
|
+
require "hanami/assets"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @api private
|
|
19
|
+
def start
|
|
20
|
+
root = slice.app.root.join("public", "assets", Hanami::Assets.public_assets_dir(target).to_s)
|
|
21
|
+
|
|
22
|
+
assets = Hanami::Assets.new(config: slice.config.assets, root: root)
|
|
23
|
+
|
|
24
|
+
register(:assets, assets)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/configurable"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module Providers
|
|
7
|
+
class DB < Hanami::Provider::Source
|
|
8
|
+
# @api public
|
|
9
|
+
# @since 2.2.0
|
|
10
|
+
class Adapter
|
|
11
|
+
include Dry::Configurable
|
|
12
|
+
|
|
13
|
+
# @api public
|
|
14
|
+
# @since 2.2.0
|
|
15
|
+
setting :plugins, mutable: true
|
|
16
|
+
|
|
17
|
+
# @api private
|
|
18
|
+
def initialize(...)
|
|
19
|
+
@skip_defaults = Hash.new(false)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @api public
|
|
23
|
+
# @since 2.2.0
|
|
24
|
+
def skip_defaults(setting_name = nil)
|
|
25
|
+
@skip_defaults[setting_name] = true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @api private
|
|
29
|
+
private def skip_defaults?(setting_name = nil)
|
|
30
|
+
@skip_defaults[setting_name]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
def configure_from_adapter(other_adapter)
|
|
35
|
+
return if skip_defaults?
|
|
36
|
+
|
|
37
|
+
plugins.concat(other_adapter.plugins).uniq! unless skip_defaults?(:plugins)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @api private
|
|
41
|
+
def configure_for_database(database_url)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @api public
|
|
45
|
+
# @since 2.2.0
|
|
46
|
+
def plugin(**plugin_spec, &config_block)
|
|
47
|
+
plugins << [plugin_spec, config_block]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @api public
|
|
51
|
+
# @since 2.2.0
|
|
52
|
+
def plugins
|
|
53
|
+
config.plugins ||= []
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @api private
|
|
57
|
+
def gateway_cache_keys
|
|
58
|
+
gateway_options
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @api private
|
|
62
|
+
def gateway_options
|
|
63
|
+
{}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @api public
|
|
67
|
+
# @since 2.2.0
|
|
68
|
+
def clear
|
|
69
|
+
config.plugins = nil
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module Providers
|
|
5
|
+
class DB < Hanami::Provider::Source
|
|
6
|
+
# @api public
|
|
7
|
+
# @since 2.2.0
|
|
8
|
+
class Adapters
|
|
9
|
+
# @api private
|
|
10
|
+
# @since 2.2.0
|
|
11
|
+
ADAPTER_CLASSES = Hash.new(Adapter).update(
|
|
12
|
+
sql: SQLAdapter
|
|
13
|
+
).freeze
|
|
14
|
+
private_constant :ADAPTER_CLASSES
|
|
15
|
+
|
|
16
|
+
extend Forwardable
|
|
17
|
+
|
|
18
|
+
def_delegators :adapters, :[], :[]=, :each, :to_h
|
|
19
|
+
|
|
20
|
+
# @api private
|
|
21
|
+
# @since 2.2.0
|
|
22
|
+
def self.new_adapter(name)
|
|
23
|
+
ADAPTER_CLASSES[name].new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @api private
|
|
27
|
+
# @since 2.2.0
|
|
28
|
+
attr_reader :adapters
|
|
29
|
+
|
|
30
|
+
# @api private
|
|
31
|
+
# @since 2.2.0
|
|
32
|
+
def initialize
|
|
33
|
+
@adapters = {}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @api private
|
|
37
|
+
# @since 2.2.0
|
|
38
|
+
def initialize_copy(source)
|
|
39
|
+
@adapters = source.adapters.dup
|
|
40
|
+
|
|
41
|
+
source.adapters.each do |key, val|
|
|
42
|
+
@adapters[key] = val.dup
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @api private
|
|
47
|
+
# @since 2.2.0
|
|
48
|
+
def adapter(key)
|
|
49
|
+
adapters[key] ||= new(key)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @api private
|
|
53
|
+
# @since 2.2.0
|
|
54
|
+
def find(key)
|
|
55
|
+
adapters.fetch(key) { new(key) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @api private
|
|
59
|
+
# @since 2.2.0
|
|
60
|
+
def new(key)
|
|
61
|
+
self.class.new_adapter(key)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/core"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module Providers
|
|
7
|
+
class DB < Hanami::Provider::Source
|
|
8
|
+
# @api public
|
|
9
|
+
# @since 2.2.0
|
|
10
|
+
class Config < Dry::Configurable::Config
|
|
11
|
+
include Dry::Core::Constants
|
|
12
|
+
|
|
13
|
+
# @api public
|
|
14
|
+
# @since 2.2.0
|
|
15
|
+
def gateway(key)
|
|
16
|
+
gateway = (gateways[key] ||= Gateway.new)
|
|
17
|
+
yield gateway if block_given?
|
|
18
|
+
gateway
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @api public
|
|
22
|
+
# @since 2.2.0
|
|
23
|
+
def adapter(name)
|
|
24
|
+
adapter = adapters.adapter(name)
|
|
25
|
+
yield adapter if block_given?
|
|
26
|
+
adapter
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @api private
|
|
30
|
+
def each_plugin
|
|
31
|
+
return to_enum(__method__) unless block_given?
|
|
32
|
+
|
|
33
|
+
gateways.values.group_by(&:adapter_name).each do |adapter_name, adapter_gateways|
|
|
34
|
+
per_adapter_plugins = adapter_gateways.map { _1.adapter.plugins }.flatten(1).uniq
|
|
35
|
+
|
|
36
|
+
per_adapter_plugins.each do |plugin_spec, config_block|
|
|
37
|
+
yield adapter_name, plugin_spec, config_block
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/configurable"
|
|
4
|
+
require "dry/core"
|
|
5
|
+
|
|
6
|
+
module Hanami
|
|
7
|
+
module Providers
|
|
8
|
+
class DB < Hanami::Provider::Source
|
|
9
|
+
# @api public
|
|
10
|
+
# @since 2.2.0
|
|
11
|
+
class Gateway
|
|
12
|
+
include Dry::Core::Constants
|
|
13
|
+
include Dry::Configurable
|
|
14
|
+
|
|
15
|
+
setting :database_url
|
|
16
|
+
setting :adapter_name, default: :sql
|
|
17
|
+
setting :adapter, mutable: true
|
|
18
|
+
setting :connection_options, default: {}
|
|
19
|
+
|
|
20
|
+
# @api public
|
|
21
|
+
# @since 2.2.0
|
|
22
|
+
def adapter(name = Undefined)
|
|
23
|
+
return config.adapter if name.eql?(Undefined)
|
|
24
|
+
|
|
25
|
+
if block_given?
|
|
26
|
+
# If a block is given, explicitly configure the gateway's adapter
|
|
27
|
+
config.adapter_name = name
|
|
28
|
+
adapter = (config.adapter ||= Adapters.new_adapter(name))
|
|
29
|
+
yield adapter
|
|
30
|
+
adapter
|
|
31
|
+
else
|
|
32
|
+
# If an adapter name is given without a block, use the default adapter configured with
|
|
33
|
+
# the same name
|
|
34
|
+
config.adapter_name = adapter_name
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @api public
|
|
39
|
+
# @since 2.2.0
|
|
40
|
+
def connection_options(**options)
|
|
41
|
+
if options.any?
|
|
42
|
+
config.connection_options.merge!(options)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
config.connection_options
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @api public
|
|
49
|
+
# @since 2.2.0
|
|
50
|
+
def options
|
|
51
|
+
{**connection_options, **config.adapter.gateway_options}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @api private
|
|
55
|
+
def configure_adapter(default_adapters)
|
|
56
|
+
default_adapter = default_adapters.find(config.adapter_name)
|
|
57
|
+
config.adapter ||= default_adapter.dup
|
|
58
|
+
|
|
59
|
+
config.adapter.configure_from_adapter(default_adapter)
|
|
60
|
+
|
|
61
|
+
config.adapter.configure_for_database(config.database_url)
|
|
62
|
+
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @api private
|
|
67
|
+
def cache_keys
|
|
68
|
+
[config.database_url, config.connection_options, config.adapter.gateway_cache_keys]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def method_missing(name, *args, &block)
|
|
74
|
+
if config.respond_to?(name)
|
|
75
|
+
config.public_send(name, *args, &block)
|
|
76
|
+
else
|
|
77
|
+
super
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def respond_to_missing?(name, _include_all = false)
|
|
82
|
+
config.respond_to?(name) || super
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|