dry-system 0.21.0 → 0.24.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 +424 -0
- data/LICENSE +1 -1
- data/README.md +4 -4
- data/dry-system.gemspec +3 -4
- data/lib/dry/system/component.rb +2 -3
- data/lib/dry/system/component_dir.rb +8 -34
- data/lib/dry/system/components.rb +8 -4
- data/lib/dry/system/config/component_dir.rb +75 -19
- data/lib/dry/system/config/component_dirs.rb +151 -32
- data/lib/dry/system/config/namespace.rb +11 -6
- data/lib/dry/system/config/namespaces.rb +96 -9
- data/lib/dry/system/constants.rb +1 -1
- data/lib/dry/system/container.rb +264 -182
- data/lib/dry/system/errors.rb +73 -53
- data/lib/dry/system/identifier.rb +62 -20
- data/lib/dry/system/importer.rb +83 -12
- data/lib/dry/system/indirect_component.rb +1 -1
- data/lib/dry/system/loader.rb +6 -1
- data/lib/dry/system/{manual_registrar.rb → manifest_registrar.rb} +8 -5
- data/lib/dry/system/plugins/bootsnap.rb +3 -2
- data/lib/dry/system/plugins/dependency_graph/strategies.rb +37 -1
- data/lib/dry/system/plugins/dependency_graph.rb +26 -20
- data/lib/dry/system/plugins/env.rb +2 -1
- data/lib/dry/system/plugins/logging.rb +2 -2
- data/lib/dry/system/plugins/monitoring.rb +1 -1
- data/lib/dry/system/plugins/notifications.rb +1 -1
- data/lib/dry/system/plugins/zeitwerk/compat_inflector.rb +22 -0
- data/lib/dry/system/plugins/zeitwerk.rb +109 -0
- data/lib/dry/system/plugins.rb +7 -4
- data/lib/dry/system/provider/source.rb +324 -0
- data/lib/dry/system/provider/source_dsl.rb +94 -0
- data/lib/dry/system/provider.rb +262 -22
- data/lib/dry/system/provider_registrar.rb +276 -0
- data/lib/dry/system/provider_source_registry.rb +70 -0
- data/lib/dry/system/provider_sources/settings/config.rb +86 -0
- data/lib/dry/system/provider_sources/settings/loader.rb +53 -0
- data/lib/dry/system/provider_sources/settings.rb +40 -0
- data/lib/dry/system/provider_sources.rb +5 -0
- data/lib/dry/system/version.rb +1 -1
- data/lib/dry/system.rb +44 -12
- metadata +23 -37
- data/lib/dry/system/booter/component_registry.rb +0 -35
- data/lib/dry/system/booter.rb +0 -200
- data/lib/dry/system/components/bootable.rb +0 -280
- data/lib/dry/system/components/config.rb +0 -35
- data/lib/dry/system/lifecycle.rb +0 -135
- data/lib/dry/system/provider_registry.rb +0 -27
- data/lib/dry/system/settings/file_loader.rb +0 -30
- data/lib/dry/system/settings/file_parser.rb +0 -51
- data/lib/dry/system/settings.rb +0 -64
- data/lib/dry/system/system_components/settings.rb +0 -11
@@ -9,6 +9,7 @@ require_relative "namespaces"
|
|
9
9
|
module Dry
|
10
10
|
module System
|
11
11
|
module Config
|
12
|
+
# @api public
|
12
13
|
class ComponentDir
|
13
14
|
include Dry::Configurable
|
14
15
|
|
@@ -19,7 +20,7 @@ module Dry
|
|
19
20
|
# Sets the auto-registration policy for the component dir.
|
20
21
|
#
|
21
22
|
# This may be a simple boolean to enable or disable auto-registration for all
|
22
|
-
# components, or a proc accepting a
|
23
|
+
# components, or a proc accepting a {Dry::System::Component} and returning a
|
23
24
|
# boolean to configure auto-registration on a per-component basis
|
24
25
|
#
|
25
26
|
# Defaults to `true`.
|
@@ -37,6 +38,7 @@ module Dry
|
|
37
38
|
#
|
38
39
|
# @see auto_register
|
39
40
|
# @see Component
|
41
|
+
# @api public
|
40
42
|
#
|
41
43
|
# @!method auto_register
|
42
44
|
#
|
@@ -45,30 +47,51 @@ module Dry
|
|
45
47
|
# @return [Boolean, Proc] the configured policy
|
46
48
|
#
|
47
49
|
# @see auto_register=
|
50
|
+
# @api public
|
48
51
|
setting :auto_register, default: true
|
49
52
|
|
50
|
-
# @!method
|
53
|
+
# @!method instance=(instance_proc)
|
51
54
|
#
|
52
|
-
# Sets
|
53
|
-
#
|
55
|
+
# Sets a proc used to return the instance of any component within the component
|
56
|
+
# dir.
|
54
57
|
#
|
55
|
-
#
|
56
|
-
#
|
58
|
+
# This proc should accept a {Dry::System::Component} and return the object to
|
59
|
+
# serve as the component's instance.
|
57
60
|
#
|
58
|
-
#
|
59
|
-
#
|
61
|
+
# When you provide an instance proc, it will be used in preference to the
|
62
|
+
# {loader} (either the default loader or an explicitly configured one). Provide
|
63
|
+
# an instance proc when you want a simple way to customize the instance for
|
64
|
+
# certain components. For complete control, provide a replacement loader via
|
65
|
+
# {loader=}.
|
60
66
|
#
|
61
|
-
#
|
62
|
-
# @see Container.configure
|
67
|
+
# Defaults to `nil`.
|
63
68
|
#
|
64
|
-
#
|
69
|
+
# @param instance_proc [Proc, nil]
|
70
|
+
# @return [Proc]
|
65
71
|
#
|
66
|
-
#
|
72
|
+
# @example
|
73
|
+
# dir.instance = proc do |component|
|
74
|
+
# if component.key.match?(/workers\./)
|
75
|
+
# # Register classes for jobs
|
76
|
+
# component.loader.constant(component)
|
77
|
+
# else
|
78
|
+
# # Otherwise register regular instances per default loader
|
79
|
+
# component.loader.call(component)
|
80
|
+
# end
|
81
|
+
# end
|
67
82
|
#
|
68
|
-
# @
|
83
|
+
# @see Component, Loader
|
84
|
+
# @api public
|
69
85
|
#
|
70
|
-
#
|
71
|
-
|
86
|
+
# @!method instance
|
87
|
+
#
|
88
|
+
# Returns the configured instance proc.
|
89
|
+
#
|
90
|
+
# @return [Proc, nil]
|
91
|
+
#
|
92
|
+
# @see instance=
|
93
|
+
# @api public
|
94
|
+
setting :instance
|
72
95
|
|
73
96
|
# @!method loader=(loader)
|
74
97
|
#
|
@@ -77,7 +100,8 @@ module Dry
|
|
77
100
|
#
|
78
101
|
# Defaults to `Dry::System::Loader`.
|
79
102
|
#
|
80
|
-
# When using
|
103
|
+
# When using an autoloader like Zeitwerk, consider using
|
104
|
+
# `Dry::System::Loader::Autoloading`
|
81
105
|
#
|
82
106
|
# @param loader [#call] the loader
|
83
107
|
# @return [#call] the configured loader
|
@@ -85,6 +109,7 @@ module Dry
|
|
85
109
|
# @see loader
|
86
110
|
# @see Loader
|
87
111
|
# @see Loader::Autoloading
|
112
|
+
# @api public
|
88
113
|
#
|
89
114
|
# @!method loader
|
90
115
|
#
|
@@ -93,6 +118,7 @@ module Dry
|
|
93
118
|
# @return [#call]
|
94
119
|
#
|
95
120
|
# @see loader=
|
121
|
+
# @api public
|
96
122
|
setting :loader, default: Dry::System::Loader
|
97
123
|
|
98
124
|
# @!method memoize=(policy)
|
@@ -119,6 +145,7 @@ module Dry
|
|
119
145
|
#
|
120
146
|
# @see memoize
|
121
147
|
# @see Component
|
148
|
+
# @api public
|
122
149
|
#
|
123
150
|
# @!method memoize
|
124
151
|
#
|
@@ -127,6 +154,7 @@ module Dry
|
|
127
154
|
# @return [Boolean, Proc] the configured memoization policy
|
128
155
|
#
|
129
156
|
# @see memoize=
|
157
|
+
# @api public
|
130
158
|
setting :memoize, default: false
|
131
159
|
|
132
160
|
# @!method namespaces
|
@@ -135,11 +163,38 @@ module Dry
|
|
135
163
|
#
|
136
164
|
# Allows namespaces to added on the returned object via {Namespaces#add}.
|
137
165
|
#
|
138
|
-
# @see Namespaces#add
|
139
|
-
#
|
140
166
|
# @return [Namespaces] the namespaces
|
167
|
+
#
|
168
|
+
# @see Namespaces#add
|
169
|
+
# @api public
|
141
170
|
setting :namespaces, default: Namespaces.new, cloneable: true
|
142
171
|
|
172
|
+
# @!method add_to_load_path=(policy)
|
173
|
+
#
|
174
|
+
# Sets whether the dir should be added to the `$LOAD_PATH` after the container
|
175
|
+
# is configured.
|
176
|
+
#
|
177
|
+
# Defaults to `true`. This may need to be set to `false` when using a class
|
178
|
+
# autoloading system.
|
179
|
+
#
|
180
|
+
# @param policy [Boolean]
|
181
|
+
# @return [Boolean]
|
182
|
+
#
|
183
|
+
# @see add_to_load_path
|
184
|
+
# @see Container.configure
|
185
|
+
# @api public
|
186
|
+
#
|
187
|
+
# @!method add_to_load_path
|
188
|
+
#
|
189
|
+
# Returns the configured value.
|
190
|
+
#
|
191
|
+
# @return [Boolean]
|
192
|
+
#
|
193
|
+
# @see add_to_load_path=
|
194
|
+
# @api public
|
195
|
+
setting :add_to_load_path, default: true
|
196
|
+
|
197
|
+
# @api public
|
143
198
|
def default_namespace=(namespace)
|
144
199
|
Dry::Core::Deprecations.announce(
|
145
200
|
"Dry::System::Config::ComponentDir#default_namespace=",
|
@@ -157,6 +212,7 @@ module Dry
|
|
157
212
|
namespaces.add namespace_path, key: nil
|
158
213
|
end
|
159
214
|
|
215
|
+
# @api public
|
160
216
|
def default_namespace
|
161
217
|
Dry::Core::Deprecations.announce(
|
162
218
|
"Dry::System::Config::ComponentDir#default_namespace",
|
@@ -179,7 +235,7 @@ module Dry
|
|
179
235
|
# @return [String] the path
|
180
236
|
attr_reader :path
|
181
237
|
|
182
|
-
# @api
|
238
|
+
# @api public
|
183
239
|
def initialize(path)
|
184
240
|
super()
|
185
241
|
@path = path
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "concurrent/map"
|
4
3
|
require "dry/system/constants"
|
5
4
|
require "dry/system/errors"
|
6
5
|
require_relative "component_dir"
|
@@ -8,6 +7,9 @@ require_relative "component_dir"
|
|
8
7
|
module Dry
|
9
8
|
module System
|
10
9
|
module Config
|
10
|
+
# The configured component dirs for a container
|
11
|
+
#
|
12
|
+
# @api public
|
11
13
|
class ComponentDirs
|
12
14
|
# @!group Settings
|
13
15
|
|
@@ -15,7 +17,7 @@ module Dry
|
|
15
17
|
#
|
16
18
|
# Sets a default `auto_register` for all added component dirs
|
17
19
|
#
|
18
|
-
# @see ComponentDir.auto_register
|
20
|
+
# @see ComponentDir.auto_register=
|
19
21
|
# @see auto_register
|
20
22
|
#
|
21
23
|
# @!method auto_register
|
@@ -24,24 +26,24 @@ module Dry
|
|
24
26
|
#
|
25
27
|
# @see auto_register=
|
26
28
|
|
27
|
-
# @!method
|
29
|
+
# @!method instance=(value)
|
28
30
|
#
|
29
|
-
# Sets a default `
|
31
|
+
# Sets a default `instance` for all added component dirs
|
30
32
|
#
|
31
|
-
# @see ComponentDir.
|
32
|
-
# @see
|
33
|
+
# @see ComponentDir.instance=
|
34
|
+
# @see auto_register
|
33
35
|
#
|
34
|
-
# @!method
|
36
|
+
# @!method auto_register
|
35
37
|
#
|
36
|
-
# Returns the configured default `
|
38
|
+
# Returns the configured default `instance`
|
37
39
|
#
|
38
|
-
# @see
|
40
|
+
# @see instance=
|
39
41
|
|
40
42
|
# @!method loader=(value)
|
41
43
|
#
|
42
44
|
# Sets a default `loader` value for all added component dirs
|
43
45
|
#
|
44
|
-
# @see ComponentDir.loader
|
46
|
+
# @see ComponentDir.loader=
|
45
47
|
# @see loader
|
46
48
|
#
|
47
49
|
# @!method loader
|
@@ -54,7 +56,7 @@ module Dry
|
|
54
56
|
#
|
55
57
|
# Sets a default `memoize` value for all added component dirs
|
56
58
|
#
|
57
|
-
# @see ComponentDir.memoize
|
59
|
+
# @see ComponentDir.memoize=
|
58
60
|
# @see memoize
|
59
61
|
#
|
60
62
|
# @!method memoize
|
@@ -63,71 +65,154 @@ module Dry
|
|
63
65
|
#
|
64
66
|
# @see memoize=
|
65
67
|
|
68
|
+
# rubocop:disable Layout/LineLength
|
69
|
+
|
66
70
|
# @!method namespaces
|
67
71
|
#
|
68
72
|
# Returns the default configured namespaces for all added component dirs
|
69
73
|
#
|
70
|
-
# Allows namespaces to added on the returned object via {Namespaces#add}.
|
74
|
+
# Allows namespaces to added on the returned object via {Dry::System::Config::Namespaces#add}.
|
71
75
|
#
|
72
|
-
# @see Namespaces#add
|
76
|
+
# @see Dry::System::Config::Namespaces#add
|
73
77
|
#
|
74
78
|
# @return [Namespaces] the namespaces
|
75
79
|
|
80
|
+
# @!method add_to_load_path=(value)
|
81
|
+
#
|
82
|
+
# Sets a default `add_to_load_path` value for all added component dirs
|
83
|
+
#
|
84
|
+
# @see ComponentDir.add_to_load_path=
|
85
|
+
# @see add_to_load_path
|
86
|
+
#
|
87
|
+
# @!method add_to_load_path
|
88
|
+
#
|
89
|
+
# Returns the configured default `add_to_load_path`
|
90
|
+
#
|
91
|
+
# @see add_to_load_path=
|
92
|
+
|
93
|
+
# rubocop:enable Layout/LineLength
|
94
|
+
|
76
95
|
# @!endgroup
|
77
96
|
|
78
97
|
# A ComponentDir for configuring the default values to apply to all added
|
79
98
|
# component dirs
|
80
99
|
#
|
100
|
+
# @see #method_missing
|
81
101
|
# @api private
|
82
102
|
attr_reader :defaults
|
83
103
|
|
104
|
+
# Creates a new component dirs
|
105
|
+
#
|
84
106
|
# @api private
|
85
107
|
def initialize
|
86
|
-
@dirs =
|
108
|
+
@dirs = {}
|
87
109
|
@defaults = ComponentDir.new(nil)
|
88
110
|
end
|
89
111
|
|
90
112
|
# @api private
|
91
113
|
def initialize_copy(source)
|
92
|
-
@dirs = source.dirs.dup
|
114
|
+
@dirs = source.dirs.map { |path, dir| [path, dir.dup] }.to_h
|
93
115
|
@defaults = source.defaults.dup
|
94
116
|
end
|
95
117
|
|
96
|
-
#
|
118
|
+
# Returns and optionally yields a previously added component dir
|
119
|
+
#
|
120
|
+
# @param path [String] the path for the component dir
|
121
|
+
# @yieldparam dir [ComponentDir] the component dir
|
122
|
+
#
|
123
|
+
# @return [ComponentDir] the component dir
|
124
|
+
#
|
125
|
+
# @api public
|
126
|
+
def dir(path)
|
127
|
+
dirs[path].tap do |dir|
|
128
|
+
# Defaults can be (re-)applied first, since the dir has already been added
|
129
|
+
apply_defaults_to_dir(dir) if dir
|
130
|
+
yield dir if block_given?
|
131
|
+
end
|
132
|
+
end
|
133
|
+
alias_method :[], :dir
|
134
|
+
|
135
|
+
# @overload add(path)
|
136
|
+
# Adds and configures a component dir for the given path
|
137
|
+
#
|
138
|
+
# @param path [String] the path for the component dir, relative to the configured
|
139
|
+
# container root
|
140
|
+
# @yieldparam dir [ComponentDir] the component dir to configure
|
141
|
+
#
|
142
|
+
# @return [ComponentDir] the added component dir
|
97
143
|
#
|
98
|
-
#
|
99
|
-
#
|
144
|
+
# @example
|
145
|
+
# component_dirs.add "lib" do |dir|
|
146
|
+
# dir.default_namespace = "my_app"
|
147
|
+
# end
|
100
148
|
#
|
101
|
-
#
|
149
|
+
# @see ComponentDir
|
150
|
+
# @api public
|
102
151
|
#
|
103
|
-
# @
|
152
|
+
# @overload add(dir)
|
153
|
+
# Adds a configured component dir
|
104
154
|
#
|
105
|
-
#
|
106
|
-
# component_dirs.add "lib" do |dir|
|
107
|
-
# dir.default_namespace = "my_app"
|
108
|
-
# end
|
155
|
+
# @param dir [ComponentDir] the configured component dir
|
109
156
|
#
|
110
|
-
#
|
111
|
-
|
157
|
+
# @return [ComponentDir] the added component dir
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# dir = Dry::System::ComponentDir.new("lib")
|
161
|
+
# component_dirs.add dir
|
162
|
+
#
|
163
|
+
# @see ComponentDir
|
164
|
+
# @api public
|
165
|
+
def add(path_or_dir)
|
166
|
+
path, dir_to_add = path_and_dir(path_or_dir)
|
167
|
+
|
112
168
|
raise ComponentDirAlreadyAddedError, path if dirs.key?(path)
|
113
169
|
|
114
|
-
dirs[path] =
|
115
|
-
|
170
|
+
dirs[path] = dir_to_add.tap do |dir|
|
171
|
+
# Defaults must be applied after yielding, since the dir is being newly added,
|
172
|
+
# and must have its configuration fully in place before we can know which
|
173
|
+
# defaults to apply
|
174
|
+
yield dir if path_or_dir == path && block_given?
|
116
175
|
apply_defaults_to_dir(dir)
|
117
176
|
end
|
118
177
|
end
|
119
178
|
|
120
|
-
#
|
179
|
+
# Deletes and returns a previously added component dir
|
180
|
+
#
|
181
|
+
# @param path [String] the path for the component dir
|
182
|
+
#
|
183
|
+
# @return [ComponentDir] the removed component dir
|
184
|
+
#
|
185
|
+
# @api public
|
186
|
+
def delete(path)
|
187
|
+
dirs.delete(path)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Returns the paths of the component dirs
|
191
|
+
#
|
192
|
+
# @return [Array<String>] the component dir paths
|
193
|
+
#
|
194
|
+
# @api public
|
195
|
+
def paths
|
196
|
+
dirs.keys
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the count of component dirs
|
121
200
|
#
|
122
|
-
# @return [
|
123
|
-
|
124
|
-
|
201
|
+
# @return [Integer]
|
202
|
+
#
|
203
|
+
# @api public
|
204
|
+
def length
|
205
|
+
dirs.length
|
125
206
|
end
|
207
|
+
alias_method :size, :length
|
126
208
|
|
127
209
|
# Returns the added component dirs, with default settings applied
|
128
210
|
#
|
129
211
|
# @return [Array<ComponentDir>]
|
212
|
+
#
|
213
|
+
# @api public
|
130
214
|
def to_a
|
215
|
+
dirs.each { |_, dir| apply_defaults_to_dir(dir) }
|
131
216
|
dirs.values
|
132
217
|
end
|
133
218
|
|
@@ -135,12 +220,46 @@ module Dry
|
|
135
220
|
# argument.
|
136
221
|
#
|
137
222
|
# @yieldparam dir [ComponentDir] the yielded component dir
|
223
|
+
#
|
224
|
+
# @api public
|
138
225
|
def each(&block)
|
139
226
|
to_a.each(&block)
|
140
227
|
end
|
141
228
|
|
229
|
+
protected
|
230
|
+
|
231
|
+
# Returns the hash of component dirs, keyed by their paths
|
232
|
+
#
|
233
|
+
# Recently changed default configuration may not be applied to these dirs. Use
|
234
|
+
# #to_a or #each to access dirs with default configuration fully applied.
|
235
|
+
#
|
236
|
+
# This method exists to encapsulate the instance variable and to serve the needs
|
237
|
+
# of #initialize_copy
|
238
|
+
#
|
239
|
+
# @return [Hash{String => ComponentDir}]
|
240
|
+
#
|
241
|
+
# @api private
|
242
|
+
attr_reader :dirs
|
243
|
+
|
142
244
|
private
|
143
245
|
|
246
|
+
# Converts a path string or pre-built component dir into a path and dir tuple
|
247
|
+
#
|
248
|
+
# @param path_or_dir [String,ComponentDir]
|
249
|
+
#
|
250
|
+
# @return [Array<(String, ComponentDir)>]
|
251
|
+
#
|
252
|
+
# @see #add
|
253
|
+
def path_and_dir(path_or_dir)
|
254
|
+
if path_or_dir.is_a?(ComponentDir)
|
255
|
+
dir = path_or_dir
|
256
|
+
[dir.path, dir]
|
257
|
+
else
|
258
|
+
path = path_or_dir
|
259
|
+
[path, ComponentDir.new(path)]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
144
263
|
# Applies default settings to a component dir. This is run every time the dirs are
|
145
264
|
# accessed to ensure defaults are applied regardless of when new component dirs
|
146
265
|
# are added. This method must be idempotent.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "dry/core/equalizer"
|
4
|
+
require "dry/system/constants"
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module System
|
@@ -21,16 +22,19 @@ module Dry
|
|
21
22
|
#
|
22
23
|
# @see Namespaces#add
|
23
24
|
#
|
24
|
-
# @api
|
25
|
+
# @api public
|
25
26
|
class Namespace
|
26
27
|
ROOT_PATH = nil
|
27
28
|
|
28
29
|
include Dry::Equalizer(:path, :key, :const)
|
29
30
|
|
31
|
+
# @api public
|
30
32
|
attr_reader :path
|
31
33
|
|
34
|
+
# @api public
|
32
35
|
attr_reader :key
|
33
36
|
|
37
|
+
# @api public
|
34
38
|
attr_reader :const
|
35
39
|
|
36
40
|
# Returns a namespace configured to serve as the default root namespace for a
|
@@ -48,23 +52,24 @@ module Dry
|
|
48
52
|
)
|
49
53
|
end
|
50
54
|
|
55
|
+
# @api private
|
51
56
|
def initialize(path:, key:, const:)
|
52
57
|
@path = path
|
53
|
-
|
58
|
+
# Default keys (i.e. when the user does not explicitly provide one) for non-root
|
59
|
+
# paths will include path separators, which we must convert into key separators
|
60
|
+
@key = key && key == path ? key.gsub(PATH_SEPARATOR, KEY_SEPARATOR) : key
|
54
61
|
@const = const
|
55
62
|
end
|
56
63
|
|
64
|
+
# @api public
|
57
65
|
def root?
|
58
66
|
path == ROOT_PATH
|
59
67
|
end
|
60
68
|
|
69
|
+
# @api public
|
61
70
|
def path?
|
62
71
|
!root?
|
63
72
|
end
|
64
|
-
|
65
|
-
def default_key?
|
66
|
-
key == path
|
67
|
-
end
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "dry/core/deprecations"
|
3
4
|
require "dry/system/errors"
|
4
5
|
require_relative "namespace"
|
5
6
|
|
@@ -26,6 +27,39 @@ module Dry
|
|
26
27
|
@namespaces = source.namespaces.dup
|
27
28
|
end
|
28
29
|
|
30
|
+
# Returns the namespace configured for the path, or nil if no such namespace has
|
31
|
+
# been configured
|
32
|
+
#
|
33
|
+
# @return [Namespace, nil] the namespace, if configured
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def namespace(path)
|
37
|
+
namespaces[path]
|
38
|
+
end
|
39
|
+
alias_method :[], :namespace
|
40
|
+
|
41
|
+
# Returns the namespace configured for the root path, or nil if the root namespace
|
42
|
+
# has not been configured
|
43
|
+
#
|
44
|
+
# @return [Namespace, nil] the root namespace, if configured
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def root(**options)
|
48
|
+
if options.any?
|
49
|
+
Dry::Core::Deprecations.announce(
|
50
|
+
"Dry::System::Config::Namespaces#root (with arguments)",
|
51
|
+
"Use `#add_root(key: nil, const: nil)` instead",
|
52
|
+
tag: "dry-system",
|
53
|
+
uplevel: 1
|
54
|
+
)
|
55
|
+
|
56
|
+
add_root(**options)
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
namespaces[Namespace::ROOT_PATH]
|
61
|
+
end
|
62
|
+
|
29
63
|
# rubocop:disable Layout/LineLength
|
30
64
|
|
31
65
|
# Adds a component dir namespace
|
@@ -62,8 +96,8 @@ module Dry
|
|
62
96
|
#
|
63
97
|
# @param path [String] the path to the sub-directory of source files to which this
|
64
98
|
# namespace should apply, relative to the component dir
|
65
|
-
# @param
|
66
|
-
#
|
99
|
+
# @param key [String, nil] the leading namespace to apply to the container keys
|
100
|
+
# for the components. Set `nil` for the keys to be top-level.
|
67
101
|
# @param const [String, nil] the Ruby constant namespace to expect for constants
|
68
102
|
# defined within the components. This should be provided in underscored string
|
69
103
|
# form, e.g. "hello_there/world" for a Ruby constant of `HelloThere::World`. Set
|
@@ -87,31 +121,84 @@ module Dry
|
|
87
121
|
# @see #add
|
88
122
|
#
|
89
123
|
# @api public
|
90
|
-
def
|
124
|
+
def add_root(key: nil, const: nil)
|
91
125
|
add(Namespace::ROOT_PATH, key: key, const: const)
|
92
126
|
end
|
93
127
|
|
94
|
-
#
|
128
|
+
# Deletes the configured namespace for the given path and returns the namespace
|
129
|
+
#
|
130
|
+
# If no namespace was previously configured for the given path, returns nil
|
131
|
+
#
|
132
|
+
# @param path [String] the path for the namespace
|
133
|
+
#
|
134
|
+
# @return [Namespace, nil]
|
135
|
+
#
|
136
|
+
# @api public
|
137
|
+
def delete(path)
|
138
|
+
namespaces.delete(path)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Deletes the configured root namespace and returns the namespace
|
142
|
+
#
|
143
|
+
# If no root namespace was previously configured, returns nil
|
144
|
+
#
|
145
|
+
# @return [Namespace, nil]
|
146
|
+
#
|
147
|
+
# @api public
|
148
|
+
def delete_root
|
149
|
+
delete(Namespace::ROOT_PATH)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns the paths of the configured namespaces
|
153
|
+
#
|
154
|
+
# @return [Array<String,nil>] the namespace paths, with nil representing the root
|
155
|
+
# namespace
|
156
|
+
#
|
157
|
+
# @api public
|
158
|
+
def paths
|
159
|
+
namespaces.keys
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns the count of configured namespaces
|
163
|
+
#
|
164
|
+
# @return [Integer]
|
165
|
+
#
|
166
|
+
# @api public
|
167
|
+
def length
|
168
|
+
namespaces.length
|
169
|
+
end
|
170
|
+
alias_method :size, :length
|
171
|
+
|
172
|
+
# Returns true if there are no configured namespaces
|
173
|
+
#
|
174
|
+
# @return [Boolean]
|
175
|
+
#
|
176
|
+
# @api public
|
95
177
|
def empty?
|
96
178
|
namespaces.empty?
|
97
179
|
end
|
98
180
|
|
99
181
|
# Returns the configured namespaces as an array
|
100
182
|
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
# loaded.
|
183
|
+
# Adds a default root namespace to the end of the array if one was not added
|
184
|
+
# explicitly. This fallback ensures that all components in the component dir can
|
185
|
+
# be loaded.
|
104
186
|
#
|
105
187
|
# @return [Array<Namespace>] the namespaces
|
106
188
|
#
|
107
|
-
# @api
|
189
|
+
# @api public
|
108
190
|
def to_a
|
109
191
|
namespaces.values.tap do |arr|
|
110
192
|
arr << Namespace.default_root unless arr.any?(&:root?)
|
111
193
|
end
|
112
194
|
end
|
113
195
|
|
114
|
-
#
|
196
|
+
# Calls the given block once for each configured namespace, passing the namespace
|
197
|
+
# as an argument.
|
198
|
+
#
|
199
|
+
# @yieldparam namespace [Namespace] the yielded namespace
|
200
|
+
#
|
201
|
+
# @api public
|
115
202
|
def each(&block)
|
116
203
|
to_a.each(&block)
|
117
204
|
end
|