dry-system 0.22.0 → 0.25.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.
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