dry-system 0.22.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +424 -0
  3. data/LICENSE +1 -1
  4. data/README.md +3 -3
  5. data/dry-system.gemspec +4 -5
  6. data/lib/dry/system/component.rb +10 -5
  7. data/lib/dry/system/component_dir.rb +14 -35
  8. data/lib/dry/system/components.rb +8 -4
  9. data/lib/dry/system/config/component_dir.rb +60 -16
  10. data/lib/dry/system/config/component_dirs.rb +23 -10
  11. data/lib/dry/system/config/namespace.rb +4 -6
  12. data/lib/dry/system/constants.rb +1 -1
  13. data/lib/dry/system/container.rb +275 -192
  14. data/lib/dry/system/errors.rb +73 -53
  15. data/lib/dry/system/identifier.rb +62 -20
  16. data/lib/dry/system/importer.rb +90 -12
  17. data/lib/dry/system/indirect_component.rb +1 -1
  18. data/lib/dry/system/loader.rb +6 -1
  19. data/lib/dry/system/{manual_registrar.rb → manifest_registrar.rb} +9 -6
  20. data/lib/dry/system/plugins/bootsnap.rb +2 -1
  21. data/lib/dry/system/plugins/dependency_graph/strategies.rb +37 -1
  22. data/lib/dry/system/plugins/dependency_graph.rb +26 -20
  23. data/lib/dry/system/plugins/env.rb +2 -1
  24. data/lib/dry/system/plugins/logging.rb +2 -2
  25. data/lib/dry/system/plugins/monitoring.rb +1 -1
  26. data/lib/dry/system/plugins/notifications.rb +1 -1
  27. data/lib/dry/system/plugins/zeitwerk/compat_inflector.rb +22 -0
  28. data/lib/dry/system/plugins/zeitwerk.rb +109 -0
  29. data/lib/dry/system/plugins.rb +7 -4
  30. data/lib/dry/system/provider/source.rb +329 -0
  31. data/lib/dry/system/provider/source_dsl.rb +94 -0
  32. data/lib/dry/system/provider.rb +262 -22
  33. data/lib/dry/system/provider_registrar.rb +276 -0
  34. data/lib/dry/system/provider_source_registry.rb +70 -0
  35. data/lib/dry/system/provider_sources/settings/config.rb +86 -0
  36. data/lib/dry/system/provider_sources/settings/loader.rb +53 -0
  37. data/lib/dry/system/provider_sources/settings.rb +40 -0
  38. data/lib/dry/system/provider_sources.rb +5 -0
  39. data/lib/dry/system/version.rb +1 -1
  40. data/lib/dry/system.rb +44 -12
  41. metadata +23 -37
  42. data/lib/dry/system/booter/component_registry.rb +0 -35
  43. data/lib/dry/system/booter.rb +0 -200
  44. data/lib/dry/system/components/bootable.rb +0 -280
  45. data/lib/dry/system/components/config.rb +0 -35
  46. data/lib/dry/system/lifecycle.rb +0 -135
  47. data/lib/dry/system/provider_registry.rb +0 -27
  48. data/lib/dry/system/settings/file_loader.rb +0 -30
  49. data/lib/dry/system/settings/file_parser.rb +0 -51
  50. data/lib/dry/system/settings.rb +0 -64
  51. data/lib/dry/system/system_components/settings.rb +0 -11
@@ -2,25 +2,24 @@
2
2
 
3
3
  require "pathname"
4
4
 
5
- require "dry-auto_inject"
6
- require "dry-configurable"
7
- require "dry-container"
8
- require "dry/inflector"
9
-
10
- require "dry/core/constants"
5
+ require "dry/configurable"
6
+ require "dry/auto_inject"
7
+ require "dry/container"
11
8
  require "dry/core/deprecations"
9
+ require "dry/inflector"
12
10
 
13
- require "dry/system"
14
11
  require "dry/system/auto_registrar"
15
- require "dry/system/booter"
16
12
  require "dry/system/component"
17
13
  require "dry/system/constants"
18
14
  require "dry/system/errors"
19
15
  require "dry/system/identifier"
20
16
  require "dry/system/importer"
21
17
  require "dry/system/indirect_component"
22
- require "dry/system/manual_registrar"
18
+ require "dry/system/manifest_registrar"
23
19
  require "dry/system/plugins"
20
+ require "dry/system/provider_registrar"
21
+ require "dry/system/provider"
22
+ require "dry/system/provider/source"
24
23
 
25
24
  require_relative "component_dir"
26
25
  require_relative "config/component_dirs"
@@ -71,67 +70,102 @@ module Dry
71
70
  #
72
71
  # @api public
73
72
  class Container
74
- extend Dry::Configurable
75
73
  extend Dry::Container::Mixin
76
74
  extend Dry::System::Plugins
77
75
 
78
76
  setting :name
79
- setting :root, default: Pathname.pwd.freeze, constructor: -> path { Pathname(path) }
80
- setting :system_dir, default: "system"
81
- setting :bootable_dirs, default: ["system/boot"]
82
- setting :registrations_dir, default: "container"
77
+ setting :root, default: Pathname.pwd.freeze, constructor: ->(path) { Pathname(path) }
78
+ setting :provider_dirs, default: ["system/providers"]
79
+ setting :bootable_dirs # Deprecated for provider_dirs, see .provider_paths below
80
+ setting :registrations_dir, default: "system/registrations"
83
81
  setting :component_dirs, default: Config::ComponentDirs.new, cloneable: true
82
+ setting :exports, reader: true
84
83
  setting :inflector, default: Dry::Inflector.new
85
- setting :booter, default: Dry::System::Booter
86
84
  setting :auto_registrar, default: Dry::System::AutoRegistrar
87
- setting :manual_registrar, default: Dry::System::ManualRegistrar
85
+ setting :manifest_registrar, default: Dry::System::ManifestRegistrar
86
+ setting :provider_registrar, default: Dry::System::ProviderRegistrar
88
87
  setting :importer, default: Dry::System::Importer
89
- setting :components, default: {}, reader: true, constructor: :dup.to_proc
90
88
 
91
- class << self
92
- def strategies(value = nil)
93
- if value
94
- @strategies = value
95
- else
96
- @strategies ||= Dry::AutoInject::Strategies
97
- end
98
- end
89
+ # We presume "." as key namespace separator. This is not intended to be
90
+ # user-configurable.
91
+ config.namespace_separator = KEY_SEPARATOR
99
92
 
93
+ class << self
100
94
  extend Dry::Core::Deprecations["Dry::System::Container"]
101
95
 
102
- # Define a new configuration setting
96
+ # @!method config
97
+ # Returns the configuration for the container
103
98
  #
104
- # @see https://dry-rb.org/gems/dry-configurable
99
+ # @example
100
+ # container.config.root = "/path/to/app"
101
+ # container.config.root # => #<Pathname:/path/to/app>
105
102
  #
106
- # @api public
107
- def setting(name, default = Dry::Core::Constants::Undefined, **options, &block)
108
- super(name, default, **options, &block)
109
- # TODO: dry-configurable needs a public API for this
110
- config._settings << _settings[name]
111
- self
112
- end
103
+ # @return [Dry::Configurable::Config]
104
+ #
105
+ # @api public
113
106
 
114
- # Configures the container
107
+ # Yields a configuration object for the container, which you can use to modify the
108
+ # configuration, then runs the after-`configured` hooks and finalizes (freezes)
109
+ # the {config}.
110
+ #
111
+ # Does not finalize the config when given `finalize_config: false`
115
112
  #
116
113
  # @example
117
114
  # class MyApp < Dry::System::Container
118
115
  # configure do |config|
119
116
  # config.root = Pathname("/path/to/app")
120
117
  # config.name = :my_app
121
- # config.auto_register = %w(lib/apis lib/core)
122
118
  # end
123
119
  # end
124
120
  #
121
+ # @param finalize_config [Boolean]
122
+ #
125
123
  # @return [self]
126
124
  #
125
+ # @see after
126
+ #
127
127
  # @api public
128
- def configure(&block)
129
- hooks[:before_configure].each { |hook| instance_eval(&hook) }
128
+ def configure(finalize_config: true, &block)
130
129
  super(&block)
130
+
131
+ unless configured?
132
+ hooks[:after_configure].each { |hook| instance_eval(&hook) }
133
+ config.finalize! if finalize_config
134
+ @__configured__ = true
135
+ end
136
+
137
+ self
138
+ end
139
+
140
+ # Marks the container as configured, runs the after-`configured` hooks, then
141
+ # finalizes (freezes) the {config}.
142
+ #
143
+ # This method is useful to call if you're modifying the container's {config}
144
+ # directly, rather than via the config object yielded when calling {configure}.
145
+ #
146
+ # Does not finalize the config if given `finalize_config: false`.
147
+ #
148
+ # @param finalize_config [Boolean]
149
+ #
150
+ # @return [self]
151
+ #
152
+ # @see after
153
+ #
154
+ # @api public
155
+ def configured!(finalize_config: true)
156
+ return self if configured?
157
+
131
158
  hooks[:after_configure].each { |hook| instance_eval(&hook) }
159
+ config.finalize! if finalize_config
160
+ @__configured__ = true
161
+
132
162
  self
133
163
  end
134
164
 
165
+ def configured?
166
+ @__configured__.equal?(true)
167
+ end
168
+
135
169
  # Registers another container for import
136
170
  #
137
171
  # @example
@@ -158,122 +192,142 @@ module Dry
158
192
  # @param other [Hash, Dry::Container::Namespace]
159
193
  #
160
194
  # @api public
161
- def import(other)
162
- case other
163
- when Hash then importer.register(other)
164
- when Dry::Container::Namespace then super
165
- else
166
- raise ArgumentError, <<-STR
167
- +other+ must be a hash of names and systems, or a Dry::Container namespace
168
- STR
195
+ def import(keys: nil, from: Undefined, as: Undefined, **deprecated_import_hash)
196
+ if deprecated_import_hash.any?
197
+ Dry::Core::Deprecations.announce(
198
+ "Dry::System::Container.import with {namespace => container} hash",
199
+ "Use Dry::System::Container.import(from: container, as: namespace) instead",
200
+ tag: "dry-system",
201
+ uplevel: 1
202
+ )
203
+
204
+ deprecated_import_hash.each do |namespace, container|
205
+ importer.register(container: container, namespace: namespace)
206
+ end
207
+ return self
208
+ elsif from == Undefined || as == Undefined
209
+ # These keyword arguments can become properly required in the params list once
210
+ # we remove the deprecation shim above
211
+ raise ArgumentError, "required keyword arguments: :from, :as"
169
212
  end
213
+
214
+ importer.register(container: from, namespace: as, keys: keys)
215
+
216
+ self
170
217
  end
171
218
 
172
- # Registers finalization function for a bootable component
219
+ # rubocop:disable Layout/LineLength
220
+
221
+ # @overload register_provider(name, namespace: nil, from: nil, source: nil, if: true, &block)
222
+ # Registers a provider and its lifecycle hooks
173
223
  #
174
- # By convention, boot files for components should be placed in a
175
- # `bootable_dirs` entry and they will be loaded on demand when
176
- # components are loaded in isolation, or during the finalization
177
- # process.
224
+ # By convention, you should place a file for each provider in one of the
225
+ # configured `provider_dirs`, and they will be loaded on demand when components
226
+ # are loaded in isolation, or during container finalization.
178
227
  #
179
- # @example
180
- # # system/container.rb
181
- # class MyApp < Dry::System::Container
182
- # configure do |config|
183
- # config.root = Pathname("/path/to/app")
184
- # config.name = :core
185
- # config.auto_register = %w(lib/apis lib/core)
228
+ # @example
229
+ # # system/container.rb
230
+ # class MyApp < Dry::System::Container
231
+ # configure do |config|
232
+ # config.root = Pathname("/path/to/app")
233
+ # end
186
234
  # end
187
235
  #
188
- # # system/boot/db.rb
189
- # #
190
- # # Simple component registration
191
- # MyApp.boot(:db) do |container|
192
- # require 'db'
193
- #
194
- # container.register(:db, DB.new)
195
- # end
196
- #
197
- # # system/boot/db.rb
198
- # #
199
- # # Component registration with lifecycle triggers
200
- # MyApp.boot(:db) do |container|
201
- # init do
202
- # require 'db'
203
- # DB.configure(ENV['DB_URL'])
204
- # container.register(:db, DB.new)
236
+ # # system/providers/db.rb
237
+ # #
238
+ # # Simple provider registration
239
+ # MyApp.register_provider(:db) do
240
+ # start do
241
+ # require "db"
242
+ # register("db", DB.new)
243
+ # end
205
244
  # end
206
245
  #
207
- # start do
208
- # db.establish_connection
246
+ # # system/providers/db.rb
247
+ # #
248
+ # # Provider registration with lifecycle triggers
249
+ # MyApp.register_provider(:db) do |container|
250
+ # init do
251
+ # require "db"
252
+ # DB.configure(ENV["DB_URL"])
253
+ # container.register("db", DB.new)
254
+ # end
255
+ #
256
+ # start do
257
+ # container["db"].establish_connection
258
+ # end
259
+ #
260
+ # stop do
261
+ # container["db"].close_connection
262
+ # end
209
263
  # end
210
264
  #
211
- # stop do
212
- # db.close_connection
265
+ # # system/providers/db.rb
266
+ # #
267
+ # # Provider registration which uses another provider
268
+ # MyApp.register_provider(:db) do |container|
269
+ # start do
270
+ # use :logger
271
+ #
272
+ # require "db"
273
+ # DB.configure(ENV['DB_URL'], logger: logger)
274
+ # container.register("db", DB.new)
275
+ # end
213
276
  # end
214
- # end
215
277
  #
216
- # # system/boot/db.rb
217
- # #
218
- # # Component registration which uses another bootable component
219
- # MyApp.boot(:db) do |container|
220
- # use :logger
221
- #
222
- # start do
223
- # require 'db'
224
- # DB.configure(ENV['DB_URL'], logger: logger)
225
- # container.register(:db, DB.new)
278
+ # # system/providers/db.rb
279
+ # #
280
+ # # Provider registration under a namespace. This will register the
281
+ # # db object with the "persistence.db" key
282
+ # MyApp.register_provider(:persistence, namespace: "db") do
283
+ # start do
284
+ # require "db"
285
+ # DB.configure(ENV["DB_URL"])
286
+ # register("db", DB.new)
287
+ # end
226
288
  # end
227
- # end
228
289
  #
229
- # # system/boot/db.rb
230
- # #
231
- # # Component registration under a namespace. This will register the
232
- # # db object under `persistence.db` key
233
- # MyApp.namespace(:persistence) do |persistence|
234
- # require 'db'
235
- # DB.configure(ENV['DB_URL'], logger: logger)
236
- # persistence.register(:db, DB.new)
237
- # end
238
- #
239
- # @param name [Symbol] a unique name for a bootable component
290
+ # @param name [Symbol] a unique name for the provider
291
+ # @param namespace [String, nil] the key namespace to use for any registrations
292
+ # made during the provider's lifecycle
293
+ # @param from [Symbol, nil] the group for the external provider source (with the
294
+ # provider source name inferred from `name` or passsed explicitly as
295
+ # `source:`)
296
+ # @param source [Symbol, nil] the name of the external provider source to use
297
+ # (if different from the value provided as `name`)
298
+ # @param if [Boolean] a boolean to determine whether to register the provider
240
299
  #
241
- # @see Lifecycle
300
+ # @see Provider
301
+ # @see Provider::Source
242
302
  #
243
- # @return [self]
303
+ # @return [self]
244
304
  #
245
- # @api public
246
- def boot(name, **opts, &block)
247
- if components.key?(name)
248
- raise DuplicatedComponentKeyError, <<-STR
249
- Bootable component #{name.inspect} was already registered
250
- STR
251
- end
252
-
253
- component =
254
- if opts[:from]
255
- boot_external(name, **opts, &block)
256
- else
257
- boot_local(name, **opts, &block)
258
- end
259
-
260
- booter.register_component component
261
-
262
- components[name] = component
305
+ # @api public
306
+ def register_provider(...)
307
+ providers.register_provider(...)
263
308
  end
264
- deprecate :finalize, :boot
265
309
 
266
- # @api private
267
- def boot_external(name, from:, key: nil, namespace: nil, &block)
268
- System.providers[from].component(
269
- name, key: key, namespace: namespace, finalize: block, container: self
310
+ # rubocop:enable Layout/LineLength
311
+
312
+ # @see .register_provider
313
+ # @api public
314
+ def boot(name, **opts, &block)
315
+ Dry::Core::Deprecations.announce(
316
+ "Dry::System::Container.boot",
317
+ "Use `Dry::System::Container.register_provider` instead",
318
+ tag: "dry-system",
319
+ uplevel: 1
270
320
  )
271
- end
272
321
 
273
- # @api private
274
- def boot_local(name, namespace: nil, &block)
275
- Components::Bootable.new(name, container: self, namespace: namespace, &block)
322
+ register_provider(
323
+ name,
324
+ namespace: opts[:namespace],
325
+ from: opts[:from],
326
+ source: opts[:key],
327
+ &block
328
+ )
276
329
  end
330
+ deprecate :finalize, :boot
277
331
 
278
332
  # Return if a container was finalized
279
333
  #
@@ -316,71 +370,77 @@ module Dry
316
370
  def finalize!(freeze: true, &block)
317
371
  return self if finalized?
318
372
 
373
+ configured!
374
+
375
+ hooks[:before_finalize].each { |hook| instance_eval(&hook) }
319
376
  yield(self) if block
320
377
 
321
- importer.finalize!
322
- booter.finalize!
323
- manual_registrar.finalize!
378
+ providers.finalize!
324
379
  auto_registrar.finalize!
380
+ manifest_registrar.finalize!
381
+ importer.finalize!
325
382
 
326
383
  @__finalized__ = true
327
384
 
328
385
  self.freeze if freeze
386
+ hooks[:after_finalize].each { |hook| instance_eval(&hook) }
329
387
  self
330
388
  end
331
389
 
332
- # Boots a specific component
390
+ # Starts a provider
333
391
  #
334
- # As a result, `init` and `start` lifecycle triggers are called
392
+ # As a result, the provider's `prepare` and `start` lifecycle triggers are called
335
393
  #
336
394
  # @example
337
395
  # MyApp.start(:persistence)
338
396
  #
339
- # @param name [Symbol] the name of a registered bootable component
397
+ # @param name [Symbol] the name of a registered provider to start
340
398
  #
341
399
  # @return [self]
342
400
  #
343
401
  # @api public
344
402
  def start(name)
345
- booter.start(name)
403
+ providers.start(name)
346
404
  self
347
405
  end
348
406
 
349
- # Boots a specific component but calls only `init` lifecycle trigger
407
+ # Prepares a provider using its `prepare` lifecycle trigger
350
408
  #
351
- # This way of booting is useful in places where a heavy dependency is
352
- # needed but its started environment is not required
409
+ # Preparing (as opposed to starting) a provider is useful in places where some
410
+ # aspects of a heavier dependency are needed, but its fully started environment
353
411
  #
354
412
  # @example
355
- # MyApp.init(:persistence)
413
+ # MyApp.prepare(:persistence)
356
414
  #
357
- # @param [Symbol] name The name of a registered bootable component
415
+ # @param name [Symbol] The name of the registered provider to prepare
358
416
  #
359
417
  # @return [self]
360
418
  #
361
419
  # @api public
362
- def init(name)
363
- booter.init(name)
420
+ def prepare(name)
421
+ providers.prepare(name)
364
422
  self
365
423
  end
424
+ deprecate :init, :prepare
366
425
 
367
426
  # Stop a specific component but calls only `stop` lifecycle trigger
368
427
  #
369
428
  # @example
370
429
  # MyApp.stop(:persistence)
371
430
  #
372
- # @param [Symbol] name The name of a registered bootable component
431
+ # @param name [Symbol] The name of a registered bootable component
373
432
  #
374
433
  # @return [self]
375
434
  #
376
435
  # @api public
377
436
  def stop(name)
378
- booter.stop(name)
437
+ providers.stop(name)
379
438
  self
380
439
  end
381
440
 
441
+ # @api public
382
442
  def shutdown!
383
- booter.shutdown
443
+ providers.shutdown
384
444
  self
385
445
  end
386
446
 
@@ -395,7 +455,7 @@ module Dry
395
455
  # add_to_load_path!('lib')
396
456
  # end
397
457
  #
398
- # @param [Array<String>] dirs
458
+ # @param dirs [Array<String>]
399
459
  #
400
460
  # @return [self]
401
461
  #
@@ -409,7 +469,7 @@ module Dry
409
469
 
410
470
  # @api public
411
471
  def load_registrations!(name)
412
- manual_registrar.(name)
472
+ manifest_registrar.(name)
413
473
  self
414
474
  end
415
475
 
@@ -438,8 +498,8 @@ module Dry
438
498
  # @param options [Hash] injector options
439
499
  #
440
500
  # @api public
441
- def injector(options = {strategies: strategies})
442
- Dry::AutoInject(self, options)
501
+ def injector(**options)
502
+ Dry::AutoInject(self, **options)
443
503
  end
444
504
 
445
505
  # Requires one or more files relative to the container's root
@@ -491,7 +551,7 @@ module Dry
491
551
  #
492
552
  # @!method registered?(key)
493
553
  # Whether a +key+ is registered (doesn't trigger loading)
494
- # @param [String,Symbol] key The key
554
+ # @param key [String,Symbol] The key
495
555
  # @return [Boolean]
496
556
  # @api public
497
557
  #
@@ -499,7 +559,7 @@ module Dry
499
559
  # Check if identifier is registered.
500
560
  # If not, try to load the component
501
561
  #
502
- # @param [String,Symbol] key Identifier
562
+ # @param key [String,Symbol] Identifier
503
563
  # @return [Boolean]
504
564
  #
505
565
  # @api public
@@ -518,22 +578,10 @@ module Dry
518
578
  end
519
579
 
520
580
  # @api private
521
- def booter
522
- @booter ||= config.booter.new(boot_paths)
523
- end
524
-
525
- # @api private
526
- def boot_paths
527
- config.bootable_dirs.map { |dir|
528
- dir = Pathname(dir)
529
-
530
- if dir.relative?
531
- root.join(dir)
532
- else
533
- dir
534
- end
535
- }
581
+ def providers
582
+ @providers ||= config.provider_registrar.new(self)
536
583
  end
584
+ deprecate :booter, :providers
537
585
 
538
586
  # @api private
539
587
  def auto_registrar
@@ -541,8 +589,8 @@ module Dry
541
589
  end
542
590
 
543
591
  # @api private
544
- def manual_registrar
545
- @manual_registrar ||= config.manual_registrar.new(self)
592
+ def manifest_registrar
593
+ @manifest_registrar ||= config.manifest_registrar.new(self)
546
594
  end
547
595
 
548
596
  # @api private
@@ -550,13 +598,45 @@ module Dry
550
598
  @importer ||= config.importer.new(self)
551
599
  end
552
600
 
553
- # @api private
554
- def after(event, &block)
555
- hooks[:"after_#{event}"] << block
556
- end
557
-
601
+ # Registers a callback hook to run before container lifecycle events.
602
+ #
603
+ # Currently, the only supported event is `:finalized`. This hook is called when
604
+ # you run `{finalize!}`.
605
+ #
606
+ # When the given block is called, `self` is the container class, and no block
607
+ # arguments are given.
608
+ #
609
+ # @param event [Symbol] the event name
610
+ # @param block [Proc] the callback hook to run
611
+ #
612
+ # @return [self]
613
+ #
614
+ # @api public
558
615
  def before(event, &block)
559
616
  hooks[:"before_#{event}"] << block
617
+ self
618
+ end
619
+
620
+ # Registers a callback hook to run after container lifecycle events.
621
+ #
622
+ # The supported events are:
623
+ #
624
+ # - `:configured`, called when you run {configure} or {configured!}, or when
625
+ # running {finalize!} and neither of the prior two methods have been called.
626
+ # - `:finalized`, called when you run {finalize!}.
627
+ #
628
+ # When the given block is called, `self` is the container class, and no block
629
+ # arguments are given.
630
+ #
631
+ # @param event [Symbol] the event name
632
+ # @param block [Proc] the callback hook to run
633
+ #
634
+ # @return [self]
635
+ #
636
+ # @api public
637
+ def after(event, &block)
638
+ hooks[:"after_#{event}"] << block
639
+ self
560
640
  end
561
641
 
562
642
  # @api private
@@ -570,6 +650,7 @@ module Dry
570
650
  klass.hooks[event].concat blocks.dup
571
651
  end
572
652
 
653
+ klass.instance_variable_set(:@__configured__, false)
573
654
  klass.instance_variable_set(:@__finalized__, false)
574
655
 
575
656
  super
@@ -577,30 +658,34 @@ module Dry
577
658
 
578
659
  protected
579
660
 
661
+ # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
580
662
  # @api private
581
663
  def load_component(key)
582
664
  return self if registered?(key)
583
665
 
584
- if (bootable_component = booter.find_component(key))
585
- booter.start(bootable_component)
666
+ if (provider = providers.find_and_load_provider(key))
667
+ provider.start
586
668
  return self
587
669
  end
588
670
 
589
671
  component = find_component(key)
590
672
 
591
- booter.boot_dependency(component)
673
+ providers.start_provider_dependency(component)
592
674
  return self if registered?(key)
593
675
 
594
676
  if component.loadable?
595
677
  load_local_component(component)
596
- elsif manual_registrar.file_exists?(component)
597
- manual_registrar.(component)
598
- elsif importer.key?(component.identifier.root_key)
599
- load_imported_component(component.identifier)
678
+ elsif manifest_registrar.file_exists?(component)
679
+ manifest_registrar.(component)
680
+ elsif importer.namespace?(component.identifier.root_key)
681
+ load_imported_component(component.identifier, namespace: component.identifier.root_key)
682
+ elsif importer.namespace?(nil)
683
+ load_imported_component(component.identifier, namespace: nil)
600
684
  end
601
685
 
602
686
  self
603
687
  end
688
+ # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
604
689
 
605
690
  private
606
691
 
@@ -610,26 +695,24 @@ module Dry
610
695
  end
611
696
  end
612
697
 
613
- def load_imported_component(identifier)
614
- import_namespace = identifier.root_key
615
-
616
- container = importer[import_namespace]
698
+ def load_imported_component(identifier, namespace:)
699
+ return unless importer.namespace?(namespace)
617
700
 
618
- container.load_component(identifier.namespaced(from: import_namespace, to: nil).key)
701
+ import_key = identifier.namespaced(from: namespace, to: nil).key
619
702
 
620
- importer.(import_namespace, container)
703
+ importer.import(namespace, keys: [import_key])
621
704
  end
622
705
 
623
706
  def find_component(key)
624
707
  # Find the first matching component from within the configured component dirs.
625
708
  # If no matching component is found, return a null component; this fallback is
626
- # important because the component may still be loadable via the manual registrar
627
- # or an imported container.
709
+ # important because the component may still be loadable via the manifest
710
+ # registrar or an imported container.
628
711
  component_dirs.detect { |dir|
629
712
  if (component = dir.component_for_key(key))
630
713
  break component
631
714
  end
632
- } || IndirectComponent.new(Identifier.new(key, separator: config.namespace_separator))
715
+ } || IndirectComponent.new(Identifier.new(key))
633
716
  end
634
717
  end
635
718