dry-system 0.7.3 → 0.8.0
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 +17 -0
- data/lib/dry/system.rb +24 -0
- data/lib/dry/system/booter.rb +75 -43
- data/lib/dry/system/booter/component_registry.rb +37 -0
- data/lib/dry/system/component.rb +9 -4
- data/lib/dry/system/components.rb +6 -0
- data/lib/dry/system/components/bootable.rb +307 -0
- data/lib/dry/system/components/config.rb +33 -0
- data/lib/dry/system/constants.rb +2 -0
- data/lib/dry/system/container.rb +69 -22
- data/lib/dry/system/errors.rb +2 -2
- data/lib/dry/system/lifecycle.rb +40 -7
- data/lib/dry/system/provider.rb +46 -0
- data/lib/dry/system/provider_registry.rb +25 -0
- data/lib/dry/system/settings.rb +59 -0
- data/lib/dry/system/settings/file_loader.rb +28 -0
- data/lib/dry/system/settings/file_parser.rb +49 -0
- data/lib/dry/system/system_components/settings.rb +9 -0
- data/lib/dry/system/version.rb +1 -1
- metadata +27 -144
- data/.gitignore +0 -39
- data/.rspec +0 -3
- data/.travis.yml +0 -22
- data/.yardopts +0 -5
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -9
- data/Rakefile +0 -12
- data/dry-system.gemspec +0 -31
- data/examples/custom_configuration_auto_register/Gemfile +0 -5
- data/examples/custom_configuration_auto_register/lib/entities/user.rb +0 -7
- data/examples/custom_configuration_auto_register/lib/user_repo.rb +0 -5
- data/examples/custom_configuration_auto_register/run.rb +0 -8
- data/examples/custom_configuration_auto_register/system/boot/persistence.rb +0 -13
- data/examples/custom_configuration_auto_register/system/container.rb +0 -16
- data/examples/custom_configuration_auto_register/system/import.rb +0 -3
- data/examples/standalone/Gemfile +0 -5
- data/examples/standalone/lib/user_repo.rb +0 -5
- data/examples/standalone/run.rb +0 -8
- data/examples/standalone/system/boot/persistence.rb +0 -13
- data/examples/standalone/system/container.rb +0 -9
- data/examples/standalone/system/import.rb +0 -3
- data/spec/fixtures/components/bar.rb +0 -5
- data/spec/fixtures/components/bar/baz.rb +0 -4
- data/spec/fixtures/components/foo.rb +0 -2
- data/spec/fixtures/components/no_register.rb +0 -4
- data/spec/fixtures/import_test/config/application.yml +0 -2
- data/spec/fixtures/import_test/lib/test/bar.rb +0 -4
- data/spec/fixtures/import_test/lib/test/foo.rb +0 -5
- data/spec/fixtures/import_test/system/boot/bar.rb +0 -11
- data/spec/fixtures/lazytest/config/application.yml +0 -2
- data/spec/fixtures/lazytest/lib/test/dep.rb +0 -4
- data/spec/fixtures/lazytest/lib/test/foo.rb +0 -5
- data/spec/fixtures/lazytest/lib/test/models.rb +0 -4
- data/spec/fixtures/lazytest/lib/test/models/book.rb +0 -6
- data/spec/fixtures/lazytest/lib/test/models/user.rb +0 -6
- data/spec/fixtures/lazytest/system/boot/bar.rb +0 -15
- data/spec/fixtures/magic_comments/comments.rb +0 -17
- data/spec/fixtures/manual_registration/container/foo.rb +0 -6
- data/spec/fixtures/manual_registration/lib/test/foo.rb +0 -9
- data/spec/fixtures/multiple_namespaced_components/multiple/level/baz.rb +0 -7
- data/spec/fixtures/multiple_namespaced_components/multiple/level/foz.rb +0 -6
- data/spec/fixtures/namespaced_components/namespaced/bar.rb +0 -5
- data/spec/fixtures/namespaced_components/namespaced/foo.rb +0 -4
- data/spec/fixtures/other/config/boot/bar.rb +0 -11
- data/spec/fixtures/other/config/boot/hell.rb +0 -3
- data/spec/fixtures/other/lib/test/dep.rb +0 -4
- data/spec/fixtures/other/lib/test/foo.rb +0 -5
- data/spec/fixtures/other/lib/test/models.rb +0 -4
- data/spec/fixtures/other/lib/test/models/book.rb +0 -6
- data/spec/fixtures/other/lib/test/models/user.rb +0 -6
- data/spec/fixtures/stubbing/lib/test/car.rb +0 -7
- data/spec/fixtures/stubbing/system/boot/db.rb +0 -8
- data/spec/fixtures/test/config/application.yml +0 -2
- data/spec/fixtures/test/config/subapp.yml +0 -2
- data/spec/fixtures/test/lib/test/dep.rb +0 -4
- data/spec/fixtures/test/lib/test/foo.rb +0 -5
- data/spec/fixtures/test/lib/test/models.rb +0 -4
- data/spec/fixtures/test/lib/test/models/book.rb +0 -6
- data/spec/fixtures/test/lib/test/models/user.rb +0 -6
- data/spec/fixtures/test/lib/test/singleton_dep.rb +0 -7
- data/spec/fixtures/test/log/.gitkeep +0 -0
- data/spec/fixtures/test/system/boot/bar.rb +0 -11
- data/spec/fixtures/test/system/boot/client.rb +0 -7
- data/spec/fixtures/test/system/boot/db.rb +0 -1
- data/spec/fixtures/test/system/boot/hell.rb +0 -3
- data/spec/fixtures/test/system/boot/logger.rb +0 -5
- data/spec/fixtures/umbrella/system/boot/db.rb +0 -10
- data/spec/integration/boot_spec.rb +0 -18
- data/spec/integration/container/lazy_loading/manual_registration_spec.rb +0 -18
- data/spec/integration/import_spec.rb +0 -81
- data/spec/spec_helper.rb +0 -48
- data/spec/unit/auto_registrar/configuration_spec.rb +0 -26
- data/spec/unit/component_spec.rb +0 -121
- data/spec/unit/container/auto_register_spec.rb +0 -113
- data/spec/unit/container/config_spec.rb +0 -38
- data/spec/unit/container/finalize_spec.rb +0 -97
- data/spec/unit/container/import_spec.rb +0 -53
- data/spec/unit/container/injector_spec.rb +0 -29
- data/spec/unit/container_spec.rb +0 -244
- data/spec/unit/loader_spec.rb +0 -64
- data/spec/unit/magic_comments_parser_spec.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e2b3c4fc9aed09b6920d6c285df0407e8cb506f2
|
|
4
|
+
data.tar.gz: 5034704e210f09cae4f54e7ddb67371fc31bba31
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cff3f64d9fe0762d3e59893caf4f8e7f85da8b17ed40f7b6970a4518950e1ab60ad99531ae20383c10915ed296895df21a149f872a3d8dc0da214f7ed5caeabc
|
|
7
|
+
data.tar.gz: 51092e33d452c9008ddba0a384a989420287c9fce19f730b85f5903a99f7da5f4b4aa626ee4c83d693434135f8793b33aea7df037682b408f8fcfe1b751a3e00
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# 0.8.0 - 2017-10-16
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
* Support for external bootable components (solnic)
|
|
6
|
+
* Built-in `:system` components including `:settings` component (solnic)
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
* Lazy-loading components work when a container has `default_namespace` configured (GustavoCaso)
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
* [BREAKING] Improved boot DSL with support for namespacing and lifecycle before/after callbacks (solnic)
|
|
15
|
+
|
|
16
|
+
[Compare v0.7.3...v0.8.0](https://github.com/dry-rb/dry-system/compare/v0.7.3...v0.8.0)
|
|
17
|
+
|
|
1
18
|
# 0.7.3 - 2017-08-02
|
|
2
19
|
|
|
3
20
|
### Fixed
|
data/lib/dry/system.rb
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
|
+
require 'dry/system/provider'
|
|
2
|
+
require 'dry/system/provider_registry'
|
|
3
|
+
|
|
1
4
|
module Dry
|
|
2
5
|
module System
|
|
6
|
+
# Register external component provider
|
|
7
|
+
#
|
|
8
|
+
# @api public
|
|
9
|
+
def self.register_provider(identifier, options)
|
|
10
|
+
providers.register(identifier, options)
|
|
11
|
+
providers[identifier].load_components
|
|
12
|
+
self
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Register an external component that can be booted within other systems
|
|
16
|
+
#
|
|
17
|
+
# @api public
|
|
18
|
+
def self.register_component(identifier, provider:, &block)
|
|
19
|
+
providers[provider].register_component(identifier, block)
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @api private
|
|
24
|
+
def self.providers
|
|
25
|
+
@__providers__ ||= ProviderRegistry.new
|
|
26
|
+
end
|
|
3
27
|
end
|
|
4
28
|
end
|
data/lib/dry/system/booter.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
require 'dry/system/components/bootable'
|
|
1
2
|
require 'dry/system/errors'
|
|
2
3
|
require 'dry/system/lifecycle'
|
|
4
|
+
require 'dry/system/booter/component_registry'
|
|
3
5
|
|
|
4
6
|
module Dry
|
|
5
7
|
module System
|
|
@@ -13,93 +15,123 @@ module Dry
|
|
|
13
15
|
class Booter
|
|
14
16
|
attr_reader :path
|
|
15
17
|
|
|
16
|
-
attr_reader :finalizers
|
|
17
|
-
|
|
18
18
|
attr_reader :booted
|
|
19
19
|
|
|
20
|
+
attr_reader :components
|
|
21
|
+
|
|
20
22
|
# @api private
|
|
21
23
|
def initialize(path)
|
|
22
24
|
@path = path
|
|
23
|
-
@booted =
|
|
24
|
-
@
|
|
25
|
+
@booted = []
|
|
26
|
+
@components = ComponentRegistry.new
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
# @api private
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
+
def register_component(component)
|
|
31
|
+
components.register(component)
|
|
30
32
|
self
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
# @api private
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
def load_component(path)
|
|
37
|
+
identifier = Pathname(path).basename('.rb').to_s.to_sym
|
|
38
|
+
|
|
39
|
+
unless components.exists?(identifier)
|
|
40
|
+
require path
|
|
37
41
|
end
|
|
38
|
-
|
|
42
|
+
|
|
43
|
+
self
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
# @api private
|
|
42
|
-
def
|
|
43
|
-
|
|
47
|
+
def finalize!
|
|
48
|
+
boot_files.each do |path|
|
|
49
|
+
load_component(path)
|
|
50
|
+
end
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
yield(lifecycle) if block_given?
|
|
52
|
+
components.each do |component|
|
|
53
|
+
start(component)
|
|
48
54
|
end
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
freeze
|
|
51
57
|
end
|
|
52
58
|
|
|
53
59
|
# @api private
|
|
54
|
-
def
|
|
55
|
-
|
|
60
|
+
def init(name_or_component)
|
|
61
|
+
with_component(name_or_component) do |component|
|
|
62
|
+
call(component) do
|
|
63
|
+
component.init
|
|
64
|
+
yield if block_given?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
self
|
|
68
|
+
end
|
|
69
|
+
end
|
|
56
70
|
|
|
57
|
-
|
|
71
|
+
# @api private
|
|
72
|
+
def start(name_or_component)
|
|
73
|
+
with_component(name_or_component) do |component|
|
|
74
|
+
return self if booted.include?(component)
|
|
58
75
|
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
init(name_or_component) do
|
|
77
|
+
component.start
|
|
78
|
+
end
|
|
61
79
|
|
|
62
|
-
|
|
80
|
+
booted << component.finalize
|
|
81
|
+
|
|
82
|
+
self
|
|
83
|
+
end
|
|
63
84
|
end
|
|
64
85
|
|
|
65
86
|
# @api private
|
|
66
|
-
def call(
|
|
67
|
-
|
|
87
|
+
def call(name_or_component)
|
|
88
|
+
with_component(name_or_component) do |component|
|
|
89
|
+
unless component
|
|
90
|
+
raise ComponentFileMismatchError.new(name, registered_booted_keys)
|
|
91
|
+
end
|
|
68
92
|
|
|
69
|
-
|
|
93
|
+
yield(component) if block_given?
|
|
70
94
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
lifecycle
|
|
95
|
+
component
|
|
96
|
+
end
|
|
74
97
|
end
|
|
75
98
|
|
|
76
99
|
# @api private
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
start(boot_file.basename('.*').to_s.to_sym) if boot_file.exist?
|
|
100
|
+
def lifecycle_container(container)
|
|
101
|
+
LifecycleContainer.new(container)
|
|
80
102
|
end
|
|
81
103
|
|
|
82
|
-
private
|
|
104
|
+
# @api private
|
|
105
|
+
def with_component(id_or_component)
|
|
106
|
+
component =
|
|
107
|
+
case id_or_component
|
|
108
|
+
when Symbol
|
|
109
|
+
require_boot_file(id_or_component) unless components.exists?(id_or_component)
|
|
110
|
+
components[id_or_component]
|
|
111
|
+
when Components::Bootable
|
|
112
|
+
id_or_component
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
raise InvalidComponentError, id_or_component unless component
|
|
116
|
+
|
|
117
|
+
yield(component)
|
|
118
|
+
end
|
|
83
119
|
|
|
84
120
|
# @api private
|
|
85
|
-
def
|
|
86
|
-
|
|
121
|
+
def require_boot_file(identifier)
|
|
122
|
+
boot_file = boot_files.detect { |path| Pathname(path).basename('.rb').to_s == identifier.to_s }
|
|
123
|
+
require boot_file if boot_file
|
|
87
124
|
end
|
|
88
125
|
|
|
89
126
|
# @api private
|
|
90
127
|
def boot_files
|
|
91
|
-
path
|
|
128
|
+
Dir["#{path}/**/*.rb"]
|
|
92
129
|
end
|
|
93
130
|
|
|
94
131
|
# @api private
|
|
95
|
-
def
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
unless path.join("#{name}.rb").exist?
|
|
101
|
-
raise InvalidComponentIdentifierError, name
|
|
102
|
-
end
|
|
132
|
+
def boot_dependency(component)
|
|
133
|
+
boot_file = component.boot_file(path)
|
|
134
|
+
start(boot_file.basename('.*').to_s.to_sym) if boot_file.exist?
|
|
103
135
|
end
|
|
104
136
|
end
|
|
105
137
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Dry
|
|
2
|
+
module System
|
|
3
|
+
class Booter
|
|
4
|
+
class ComponentRegistry
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
attr_reader :components
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@components = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def each(&block)
|
|
14
|
+
components.each(&block)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def register(component)
|
|
18
|
+
@components << component
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def exists?(name)
|
|
22
|
+
components.any? { |component| component.identifier == name }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def [](name)
|
|
26
|
+
component = components.detect { |component| component.identifier == name }
|
|
27
|
+
|
|
28
|
+
if component
|
|
29
|
+
component
|
|
30
|
+
else
|
|
31
|
+
raise InvalidComponentIdentifierError, name
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/dry/system/component.rb
CHANGED
|
@@ -41,8 +41,8 @@ module Dry
|
|
|
41
41
|
attr_reader :loader
|
|
42
42
|
|
|
43
43
|
# @api private
|
|
44
|
-
def self.new(*args)
|
|
45
|
-
cache.fetch_or_store(args.hash) do
|
|
44
|
+
def self.new(*args, &block)
|
|
45
|
+
cache.fetch_or_store([*args, block].hash) do
|
|
46
46
|
name, options = args
|
|
47
47
|
options = DEFAULT_OPTIONS.merge(options || {})
|
|
48
48
|
|
|
@@ -67,8 +67,8 @@ module Dry
|
|
|
67
67
|
# @api private
|
|
68
68
|
def self.remove_namespace_from_path(name, ns)
|
|
69
69
|
match_value = name.match(/^(?<remove_namespace>#{ns}).(?<identifier>.*)/)
|
|
70
|
-
|
|
71
|
-
match_value[:identifier]
|
|
70
|
+
|
|
71
|
+
match_value ? match_value[:identifier] : name
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
# @api private
|
|
@@ -108,6 +108,11 @@ module Dry
|
|
|
108
108
|
loader.call(*args)
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
# @api private
|
|
112
|
+
def boot?
|
|
113
|
+
false
|
|
114
|
+
end
|
|
115
|
+
|
|
111
116
|
# @api private
|
|
112
117
|
def bootable?(path)
|
|
113
118
|
boot_file(path).exist?
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
require 'dry/system/lifecycle'
|
|
2
|
+
require 'dry/system/settings'
|
|
3
|
+
require 'dry/system/components/config'
|
|
4
|
+
|
|
5
|
+
module Dry
|
|
6
|
+
module System
|
|
7
|
+
module Components
|
|
8
|
+
# Bootable components can provide one or more objects and typically depend
|
|
9
|
+
# on 3rd-party code. A typical bootable component can be a database library,
|
|
10
|
+
# or an API client.
|
|
11
|
+
#
|
|
12
|
+
# These components can be registered via `Container.boot` and external component
|
|
13
|
+
# providers can register their components too, which then can be used and configured
|
|
14
|
+
# by your system.
|
|
15
|
+
#
|
|
16
|
+
# @example simple logger
|
|
17
|
+
# class App < Dry::System::Container
|
|
18
|
+
# boot(:logger) do
|
|
19
|
+
# init do
|
|
20
|
+
# require "logger"
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# start do
|
|
24
|
+
# register(:logger, Logger.new($stdout))
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# App[:logger] # returns configured logger
|
|
30
|
+
#
|
|
31
|
+
# @example using built-in system components
|
|
32
|
+
# class App < Dry::System::Container
|
|
33
|
+
# boot(:settings, from: :system) do
|
|
34
|
+
# settings do
|
|
35
|
+
# key :database_url, Types::String.constrained(filled: true)
|
|
36
|
+
# key :session_secret, Types::String.constrained(filled: true)
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
# App[:settings] # returns loaded settings
|
|
42
|
+
#
|
|
43
|
+
# @api public
|
|
44
|
+
class Bootable
|
|
45
|
+
DEFAULT_FINALIZE = proc {}
|
|
46
|
+
|
|
47
|
+
# @!attribute [r] identifier
|
|
48
|
+
# @return [Symbol] component's unique identifier
|
|
49
|
+
attr_reader :identifier
|
|
50
|
+
|
|
51
|
+
# @!attribute [r] finalize
|
|
52
|
+
# @return [Proc] Finalization proc
|
|
53
|
+
attr_reader :finalize
|
|
54
|
+
|
|
55
|
+
# @!attribute [r] options
|
|
56
|
+
# @return [Hash] component's options
|
|
57
|
+
attr_reader :options
|
|
58
|
+
|
|
59
|
+
# @!attribute [r] triggers
|
|
60
|
+
# @return [Hash] lifecycle step after/before callbacks
|
|
61
|
+
attr_reader :triggers
|
|
62
|
+
|
|
63
|
+
# @!attribute [r] namespace
|
|
64
|
+
# @return [Symbol,String] default namespace for the container keys
|
|
65
|
+
attr_reader :namespace
|
|
66
|
+
|
|
67
|
+
# @api private
|
|
68
|
+
def initialize(identifier, options = {}, &block)
|
|
69
|
+
@identifier = identifier
|
|
70
|
+
@triggers = { before: Hash.new { |h, k| h[k] = [] }, after: Hash.new { |h, k| h[k] = [] } }
|
|
71
|
+
@options = block ? options.merge(block: block) : options
|
|
72
|
+
@namespace = options[:namespace]
|
|
73
|
+
finalize = options[:finalize] || DEFAULT_FINALIZE
|
|
74
|
+
instance_exec(&finalize)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Execute `init` step
|
|
78
|
+
#
|
|
79
|
+
# @return [Bootable]
|
|
80
|
+
#
|
|
81
|
+
# @api public
|
|
82
|
+
def init
|
|
83
|
+
trigger(:before, :init)
|
|
84
|
+
lifecycle.(:init)
|
|
85
|
+
trigger(:after, :init)
|
|
86
|
+
self
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Execute `start` step
|
|
90
|
+
#
|
|
91
|
+
# @return [Bootable]
|
|
92
|
+
#
|
|
93
|
+
# @api public
|
|
94
|
+
def start
|
|
95
|
+
trigger(:before, :start)
|
|
96
|
+
lifecycle.(:start)
|
|
97
|
+
trigger(:after, :start)
|
|
98
|
+
self
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Execute `stop` step
|
|
102
|
+
#
|
|
103
|
+
# @return [Bootable]
|
|
104
|
+
#
|
|
105
|
+
# @api public
|
|
106
|
+
def stop
|
|
107
|
+
lifecycle.(:stop)
|
|
108
|
+
self
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Specify a before callback
|
|
112
|
+
#
|
|
113
|
+
# @return [Bootable]
|
|
114
|
+
#
|
|
115
|
+
# @api public
|
|
116
|
+
def before(event, &block)
|
|
117
|
+
triggers[:before][event] << block
|
|
118
|
+
self
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Specify an after callback
|
|
122
|
+
#
|
|
123
|
+
# @return [Bootable]
|
|
124
|
+
#
|
|
125
|
+
# @api public
|
|
126
|
+
def after(event, &block)
|
|
127
|
+
triggers[:after][event] << block
|
|
128
|
+
self
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Configure a component
|
|
132
|
+
#
|
|
133
|
+
# @return [Bootable]
|
|
134
|
+
#
|
|
135
|
+
# @api public
|
|
136
|
+
def configure(&block)
|
|
137
|
+
@config_block = block
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Define configuration settings with keys and types
|
|
141
|
+
#
|
|
142
|
+
# @return [Bootable]
|
|
143
|
+
#
|
|
144
|
+
# @api public
|
|
145
|
+
def settings(&block)
|
|
146
|
+
if block
|
|
147
|
+
@settings_block = block
|
|
148
|
+
elsif @settings_block
|
|
149
|
+
@settings = Settings::DSL.new(identifier, &@settings_block).call
|
|
150
|
+
else
|
|
151
|
+
@settings
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Return component's configuration
|
|
156
|
+
#
|
|
157
|
+
# @return [Dry::Struct]
|
|
158
|
+
#
|
|
159
|
+
# @api public
|
|
160
|
+
def config
|
|
161
|
+
if @config
|
|
162
|
+
@config
|
|
163
|
+
else
|
|
164
|
+
configure!
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Return a list of lifecycle steps that were executed
|
|
169
|
+
#
|
|
170
|
+
# @return [Array<Symbol>]
|
|
171
|
+
#
|
|
172
|
+
# @api public
|
|
173
|
+
def statuses
|
|
174
|
+
lifecycle.statuses
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Return system's container used by this component
|
|
178
|
+
#
|
|
179
|
+
# @return [Dry::Struct]
|
|
180
|
+
#
|
|
181
|
+
# @api public
|
|
182
|
+
def container
|
|
183
|
+
options.fetch(:container)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Automatically called by the booter object after starting a component
|
|
187
|
+
#
|
|
188
|
+
# @return [Bootable]
|
|
189
|
+
#
|
|
190
|
+
# @api private
|
|
191
|
+
def finalize
|
|
192
|
+
lifecycle.container.each do |key, item|
|
|
193
|
+
container.register(key, item) unless container.key?(key)
|
|
194
|
+
end
|
|
195
|
+
self
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Trigger a callback
|
|
199
|
+
#
|
|
200
|
+
# @return [Bootable]
|
|
201
|
+
#
|
|
202
|
+
# @api private
|
|
203
|
+
def trigger(key, event)
|
|
204
|
+
triggers[key][event].each do |fn|
|
|
205
|
+
container.instance_exec(lifecycle.container, &fn)
|
|
206
|
+
end
|
|
207
|
+
self
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Return a new instance with updated options
|
|
211
|
+
#
|
|
212
|
+
# @return [Dry::Struct]
|
|
213
|
+
#
|
|
214
|
+
# @api private
|
|
215
|
+
def with(new_options)
|
|
216
|
+
self.class.new(identifier, options.merge(new_options))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Return true
|
|
220
|
+
#
|
|
221
|
+
# @return [TrueClass]
|
|
222
|
+
#
|
|
223
|
+
# @api private
|
|
224
|
+
def boot?
|
|
225
|
+
true
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Return path to component's boot file
|
|
229
|
+
#
|
|
230
|
+
# @return [String]
|
|
231
|
+
#
|
|
232
|
+
# @api private
|
|
233
|
+
def boot_file
|
|
234
|
+
container_boot_files.
|
|
235
|
+
detect { |path| Pathname(path).basename('.rb').to_s == identifier.to_s }
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Return path to boot dir
|
|
239
|
+
#
|
|
240
|
+
# @return [String]
|
|
241
|
+
#
|
|
242
|
+
# @api private
|
|
243
|
+
def boot_path
|
|
244
|
+
container.boot_path
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Return all boot files defined under container's boot path
|
|
248
|
+
#
|
|
249
|
+
# @return [String]
|
|
250
|
+
#
|
|
251
|
+
# @api private
|
|
252
|
+
def container_boot_files
|
|
253
|
+
Dir[container.boot_path.join('**/*.rb')]
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
private
|
|
257
|
+
|
|
258
|
+
# Return lifecycle object used for this component
|
|
259
|
+
#
|
|
260
|
+
# @return [Lifecycle]
|
|
261
|
+
#
|
|
262
|
+
# @api private
|
|
263
|
+
def lifecycle
|
|
264
|
+
@lifecycle ||= Lifecycle.new(lf_container, component: self, &block)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Return configured container for the lifecycle object
|
|
268
|
+
#
|
|
269
|
+
# @return [Dry::Container]
|
|
270
|
+
#
|
|
271
|
+
# @api private
|
|
272
|
+
def lf_container
|
|
273
|
+
container = Dry::Container.new
|
|
274
|
+
|
|
275
|
+
case namespace
|
|
276
|
+
when String, Symbol
|
|
277
|
+
container.namespace(namespace) { |c| return c }
|
|
278
|
+
when true
|
|
279
|
+
container.namespace(identifier) { |c| return c }
|
|
280
|
+
when nil
|
|
281
|
+
container
|
|
282
|
+
else
|
|
283
|
+
raise RuntimeError, "+namespace+ boot option must be true, string or symbol #{namespace.inspect} given."
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Set config object
|
|
288
|
+
#
|
|
289
|
+
# @return [Dry::Struct]
|
|
290
|
+
#
|
|
291
|
+
# @api private
|
|
292
|
+
def configure!
|
|
293
|
+
@config = settings.new(Config.new(&@config_block)) if settings
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Return block that will be evaluated in the lifecycle context
|
|
297
|
+
#
|
|
298
|
+
# @return [Proc]
|
|
299
|
+
#
|
|
300
|
+
# @api private
|
|
301
|
+
def block
|
|
302
|
+
options.fetch(:block)
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|