dry-plugins 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c3f397db9409161943cf1beb2b08991137bea56
4
+ data.tar.gz: 421e745136b991141b11b2254a9d6d5a4d545ace
5
+ SHA512:
6
+ metadata.gz: 1aafce2b121f32b1c726cf7948dbb9517ec6830e487acdad85c96bccea58e89248a96d47795129968ac34c0d7df05acd1e4fa925eef561d4e869352f030fc387
7
+ data.tar.gz: e3d80259a5e6700e7eb1009726365e319430e164b5c291237cd12e22a88ed6172b7853561298d455bc79c4ccf284119004d9f2405a9e2a2df863221b2fd21631
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .bundle
2
+ .rspec_status
3
+ .yardoc
4
+ _yardoc
5
+ coverage
6
+ doc
7
+ Gemfile.lock
8
+ pkg
9
+ spec/examples.txt
10
+ spec/reports
11
+ tmp
12
+ vendor/bundle
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,32 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+ DefaultFormatter: fuubar
4
+ DisplayCopNames: true
5
+ ExtraDetails: true
6
+ Exclude:
7
+ - vendor/**/*.rb
8
+
9
+ inherit_from: .rubocop_todo.yml
10
+
11
+ Metrics/BlockLength:
12
+ Exclude:
13
+ - rakelib/**/*.rb
14
+ - spec/**/*.rb
15
+ - vendor/**/*.rb
16
+
17
+ # It is 2017, UTF time!
18
+ Style/AsciiComments:
19
+ Enabled: false
20
+
21
+ Style/Documentation:
22
+ Exclude:
23
+ # Specification is doc itself
24
+ - spec/**/*
25
+ # Tests are docs itself
26
+ - test/**/*
27
+
28
+ Style/FileName:
29
+ Exclude:
30
+ # cozy name for gem requirement
31
+ - 'lib/dry-plugins.rb'
32
+ - 'lib/rspec/dry-plugins.rb'
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,35 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2017-06-15 22:45:51 +0300 using RuboCop version 0.49.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
12
+ Lint/UnusedMethodArgument:
13
+ Exclude:
14
+ - 'lib/rspec/dry-plugins.rb'
15
+
16
+ # Offense count: 1
17
+ # Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
18
+ Lint/UselessAccessModifier:
19
+ Exclude:
20
+ - 'lib/dry/plugins/registry/builder.rb'
21
+
22
+ # Offense count: 2
23
+ Metrics/AbcSize:
24
+ Max: 20
25
+
26
+ # Offense count: 14
27
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
28
+ # URISchemes: http, https
29
+ Metrics/LineLength:
30
+ Max: 120
31
+
32
+ # Offense count: 1
33
+ # Configuration parameters: CountComments.
34
+ Metrics/MethodLength:
35
+ Max: 14
data/.simplecov ADDED
@@ -0,0 +1,6 @@
1
+ SimpleCov.start do
2
+ add_filter '/bin/'
3
+ add_filter '/spec/'
4
+ add_group('Missing') { |src| src.covered_percent < 100 }
5
+ add_group('Covered') { |src| src.covered_percent == 100 }
6
+ end
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ --title 'dry-plugins'
2
+ --plugin yard-commonmarker
3
+ --markup-provider commonmarker
4
+ --markup markdown
5
+ --readme README.md
6
+ --tag "default:Default values"
7
+ lib/**/*.rb
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec name: 'dry-plugins'
data/Gemfile.lock ADDED
@@ -0,0 +1,99 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dry-plugins (0.1.0)
5
+ dry-auto_inject
6
+ dry-configurable
7
+ dry-container (~> 0.6.0)
8
+ dry-core
9
+ dry-equalizer
10
+ inflecto
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ ast (2.3.0)
16
+ bundler-audit (0.5.0)
17
+ bundler (~> 1.2)
18
+ thor (~> 0.18)
19
+ commonmarker (0.16.0)
20
+ ruby-enum (~> 0.5)
21
+ concurrent-ruby (1.0.5)
22
+ development-toolbox (0.7.0)
23
+ bundler (~> 1.13)
24
+ bundler-audit (~> 0.5)
25
+ rake (~> 12.0)
26
+ rspec (~> 3.5)
27
+ rspec-its (~> 1.2)
28
+ rubocop (~> 0.48)
29
+ yard-commonmarker (~> 0.3)
30
+ diff-lcs (1.3)
31
+ docile (1.1.5)
32
+ dry-auto_inject (0.4.3)
33
+ dry-container (>= 0.3.4)
34
+ dry-configurable (0.7.0)
35
+ concurrent-ruby (~> 1.0)
36
+ dry-container (0.6.0)
37
+ concurrent-ruby (~> 1.0)
38
+ dry-configurable (~> 0.1, >= 0.1.3)
39
+ dry-core (0.3.1)
40
+ concurrent-ruby (~> 1.0)
41
+ dry-equalizer (0.2.0)
42
+ i18n (0.8.1)
43
+ inflecto (0.0.2)
44
+ json (2.1.0)
45
+ parallel (1.11.2)
46
+ parser (2.4.0.0)
47
+ ast (~> 2.2)
48
+ powerpack (0.1.1)
49
+ rainbow (2.2.2)
50
+ rake
51
+ rake (12.0.0)
52
+ rspec (3.6.0)
53
+ rspec-core (~> 3.6.0)
54
+ rspec-expectations (~> 3.6.0)
55
+ rspec-mocks (~> 3.6.0)
56
+ rspec-core (3.6.0)
57
+ rspec-support (~> 3.6.0)
58
+ rspec-expectations (3.6.0)
59
+ diff-lcs (>= 1.2.0, < 2.0)
60
+ rspec-support (~> 3.6.0)
61
+ rspec-its (1.2.0)
62
+ rspec-core (>= 3.0.0)
63
+ rspec-expectations (>= 3.0.0)
64
+ rspec-mocks (3.6.0)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.6.0)
67
+ rspec-support (3.6.0)
68
+ rubocop (0.49.0)
69
+ parallel (~> 1.10)
70
+ parser (>= 2.3.3.1, < 3.0)
71
+ powerpack (~> 0.1)
72
+ rainbow (>= 1.99.1, < 3.0)
73
+ ruby-progressbar (~> 1.7)
74
+ unicode-display_width (~> 1.0, >= 1.0.1)
75
+ ruby-enum (0.7.1)
76
+ i18n
77
+ ruby-progressbar (1.8.1)
78
+ simplecov (0.14.1)
79
+ docile (~> 1.1.0)
80
+ json (>= 1.8, < 3)
81
+ simplecov-html (~> 0.10.0)
82
+ simplecov-html (0.10.1)
83
+ thor (0.19.4)
84
+ unicode-display_width (1.2.1)
85
+ yard (0.9.9)
86
+ yard-commonmarker (0.3.0)
87
+ commonmarker (~> 0.16)
88
+ yard (~> 0.9)
89
+
90
+ PLATFORMS
91
+ ruby
92
+
93
+ DEPENDENCIES
94
+ development-toolbox (~> 0.6)
95
+ dry-plugins!
96
+ simplecov
97
+
98
+ BUNDLED WITH
99
+ 1.15.1
data/LICENSE.md ADDED
@@ -0,0 +1,28 @@
1
+ # @title dry-plugins: The MIT License (MIT)
2
+
3
+ # The MIT License (MIT)
4
+
5
+ ## Copyright
6
+
7
+ * [Alex Semyonov] <[alex@semyonov.us]>, 2017
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in
17
+ all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ THE SOFTWARE.
26
+
27
+ [Alex Semyonov]: https://alex.semyonov.us/ "Alex Semyonov"
28
+ [alex@semyonov.us]: mailto:alex@semyonov.us?subject=dry-plugins "Email Alex about dry-plugins"
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @title dry-plugins: DSL for plugins
2
+ # @author Alex Semyonov <alex@semyonov.us>
3
+
4
+ # dry-plugins: DSL for plugins
5
+
6
+ Abstract DSL for providing plug-in interface for PORO and complex structures.
7
+
8
+ Wikipedia says following:
9
+
10
+ > The host application {Dry::Plugins::Host::DSL provides services} which the plug-in can use, including {Dry::Plugins::Registry#register a way for plug-ins to register themselves} with the host application and a protocol for the exchange of data with plug-ins. Plug-ins depend on the services provided by the host application and do not usually work by themselves. Conversely, the host application operates independently of the plug-ins, making it possible for end-users to add and update plug-ins dynamically without needing to make changes to the host application.
11
+ >
12
+ > Programmers typically implement plug-in functionality using shared libraries installed in a place prescribed by the host application. HyperCard supported a similar facility, but more commonly included the plug-in code in the HyperCard documents (called stacks) themselves. Thus the HyperCard stack became a self-contained application in its own right, distributable as a single entity that end-users could run without the need for additional installation-steps. Programs may also implement plugins by loading a directory of simple script files written in a scripting language like Python or Lua.
13
+
14
+ ## TL;DR
15
+
16
+ dry-plugins is a utility to provide plug-ins interface for your Ruby class (called *host* in documentation).
17
+
18
+ See {Dry::Plugins}.
19
+
20
+ Configuration: see {Dry::Plugins::Config}.
21
+
22
+ ##
23
+
24
+ Documentation:
25
+
26
+ * {Dry::Plugins::Registry} - a plug-ins registry;
27
+ * {Dry::Plugins::Registry::Resolver} - a plug-in resolver;
28
+ * {Dry::Plugins::Plugin} — a proxy for a plug-in;
29
+
30
+ ## Copyright and License
31
+
32
+ © [Alex Semyonov](https://alex.semyonov.us/) <[alex@semyonov.us](mailto:alex@semyonov.us?subject=dry-plugins)>, 2017, [MIT license](LICENSE.md)
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'development/tasks'
4
+ Development::Tasks.install
data/bin/rake ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ require 'rubygems'
16
+ require 'bundler/setup'
17
+
18
+ load Gem.bin_path('rake', 'rake')
data/bin/rspec ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ require 'rubygems'
16
+ require 'bundler/setup'
17
+
18
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/yard ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'yard' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ require 'rubygems'
16
+ require 'bundler/setup'
17
+
18
+ load Gem.bin_path('yard', 'yard')
data/bin/yardoc ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'yardoc' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ require 'rubygems'
16
+ require 'bundler/setup'
17
+
18
+ load Gem.bin_path('yard', 'yardoc')
data/bin/yri ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'yri' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ require 'rubygems'
16
+ require 'bundler/setup'
17
+
18
+ load Gem.bin_path('yard', 'yri')
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'dry/plugins/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'dry-plugins'
10
+ spec.version = Dry::Plugins::VERSION
11
+ spec.authors = ['Alex Semyonov']
12
+ spec.email = ['alex@semyonov.us']
13
+
14
+ spec.summary = 'Dry way to add plugins to your framework'
15
+ spec.description = 'Generic plugin interface.'
16
+ spec.homepage = 'http://alsemyonov.gitlab.com/dry-plugins/'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(test|spec|features)/})
21
+ end
22
+ spec.bindir = 'exe'
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_runtime_dependency 'dry-configurable'
27
+ spec.add_runtime_dependency 'dry-container', '~> 0.6.0'
28
+ spec.add_runtime_dependency 'dry-auto_inject'
29
+ spec.add_runtime_dependency 'dry-equalizer'
30
+ spec.add_runtime_dependency 'dry-core'
31
+ spec.add_runtime_dependency 'inflecto'
32
+
33
+ spec.add_development_dependency 'development-toolbox', '~> 0.6'
34
+ spec.add_development_dependency 'simplecov'
35
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/plugins/config'
4
+ require 'dry/plugins/host/dsl'
5
+
6
+ module Dry
7
+ module Plugins
8
+ # Plug-ins builder
9
+ # @see Builder#call
10
+ class Builder
11
+ # @!method module_builder
12
+ # @return [ModuleBuilder]
13
+ #
14
+ # @!method registry_builder
15
+ # @return [Registry::Builder]
16
+ #
17
+ # @!method host_builder
18
+ # @return [Host::Builder]
19
+ include Import[:module_builder, :registry_builder, :host_builder]
20
+
21
+ # Build a plug-in registry for given `host`
22
+ #
23
+ # 1. Extend `host` with a {Host::DSL plug-ins host DSL}
24
+ # 2. Create a {Registry plug-ins registry} for `host`,
25
+ # Find or create a `Module` containing plug-ins for `host`,
26
+ # and extend it with {DSL plug-ins registry DSL}
27
+ #
28
+ # @param host [Module]
29
+ # @return [Registry]
30
+ def call(host, registry: registry_builder.call(host))
31
+ host_builder.call(host, registry)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ # noinspection RubyConstantNamingConvention
4
+
5
+ require 'dry-auto_inject'
6
+ require 'dry-container'
7
+ require 'dry-configurable'
8
+
9
+ # rubocop:disable Style/Documentation
10
+
11
+ module Dry
12
+ module Plugins
13
+ extend Dry::Container::Mixin
14
+
15
+ Import = Dry.AutoInject(self)
16
+
17
+ # @!parse
18
+ # # Global configuration of {Dry::Plugins}
19
+ # #
20
+ # # @!group Method names
21
+ # #
22
+ # # @!attribute [rw] configure_method
23
+ # # Name of the method that will be used for configuration when
24
+ # # {Dry::Plugins::Host::DSL#use} called with block
25
+ # # @return [Symbol]
26
+ # # @default `:configure`
27
+ # #
28
+ # # @!attribute [rw] load_dependencies_method
29
+ # # Name of the method that will be used for loading dependencies when
30
+ # # {Dry::Plugins::Host::DSL#use} called
31
+ # # @return [Symbol]
32
+ # # @default `:load_dependencies`
33
+ # #
34
+ # # @!attribute [rw] registry_method
35
+ # # @return [Symbol]
36
+ # # @default `:plugins_registry`
37
+ # #
38
+ # # @!group Constant names
39
+ # #
40
+ # # @!attribute [rw] class_interface_name
41
+ # # Name of the module that will be used as a class extension
42
+ # # when plug-in is included
43
+ # # @return [Symbol]
44
+ # # @default `:ClassInterface`
45
+ # #
46
+ # # @!attribute [rw] plugins_module_name
47
+ # # Name of the module that will be used for plug-ins
48
+ # # @return [Symbol]
49
+ # # @default `:Plugins`
50
+ # #
51
+ # # @!attribute [rw] registry_class_name
52
+ # # Name of the class that will be used for plug-ins registry
53
+ # # @return [Symbol]
54
+ # # @default `:Registry`
55
+ # #
56
+ # class Config < Dry::Configurable::Config
57
+ # end
58
+ #
59
+ # @!method self.config
60
+ # @return [Config]
61
+ #
62
+ # @!method self.configure
63
+ # @yieldparam config [Config]
64
+ #
65
+ # @return [Config]
66
+ #
67
+ # @see Config#configure_method config.configure_method
68
+ # @see Config#load_dependencies_method config.load_dependencies_method
69
+ # @see Config#registry_method config.registry_method
70
+ # @see Config#class_interface_name config.class_interface_name
71
+ # @see Config#plugins_module_name config.plugins_module_name
72
+ # @see Config#registry_class_name config.registry_class_name
73
+ #
74
+ # @example dry-plugins default configuration
75
+ # Dry::Plugins.configure do |config|
76
+ # config.configure_method = :configure
77
+ # config.load_dependencies_method = :load_dependencies
78
+ # config.class_interface_name = :ClassInterface
79
+ # config.plugins_module_name = :Plugins
80
+ # config.registry_class_name = :Registry
81
+ # end
82
+ setting :container, Dry::Plugins
83
+ setting :configure_method, :configure
84
+ setting :load_dependencies_method, :load_dependencies
85
+ setting :registry_method, :plugins_registry
86
+ setting :class_interface_name, :ClassInterface
87
+ setting :plugins_module_name, :Plugins
88
+ setting :registry_class_name, :Registry
89
+
90
+ register :host_builder do
91
+ require 'dry/plugins/host/builder'
92
+ Host::Builder.new
93
+ end
94
+
95
+ register :module_builder do
96
+ require 'dry/plugins/module_builder'
97
+ ModuleBuilder.new
98
+ end
99
+
100
+ register :builder do
101
+ require 'dry/plugins/builder'
102
+ Builder.new
103
+ end
104
+
105
+ register :registry_builder do
106
+ require 'dry/plugins/registry/builder'
107
+ Registry::Builder.new
108
+ end
109
+
110
+ register :registry_class_builder do
111
+ require 'dry/plugins/registry/class_builder'
112
+ Registry::ClassBuilder.new
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Dry
6
+ module Plugins
7
+ # Plug-ins DSL
8
+ module DSL
9
+ # @api private
10
+ def self.extended(plugins)
11
+ super(plugins)
12
+ plugins.extend SingleForwardable
13
+ plugins.def_single_delegators Plugins.config.registry_method,
14
+ :register,
15
+ :resolve,
16
+ :[]
17
+ end
18
+
19
+ # @return [Module, Host::DSL]
20
+ def host
21
+ @host ||= Inflecto.constantize(name.gsub(/::[^:]+$/, ''))
22
+ end
23
+
24
+ # @!method register(name, plugin)
25
+ # @param name [#to_sym]
26
+ # @param plugin [Module, Plugin]
27
+ #
28
+ # @return [Plugin]
29
+ #
30
+ # @see Dry::Plugins::Registry#register
31
+
32
+ # @!method resolve(name)
33
+ # @param name [#to_sym]
34
+ #
35
+ # @return [Plugin]
36
+ #
37
+ # @see Dry::Plugins::Registry#resolve
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Plugins
5
+ # Plug-ins error
6
+ class Error < StandardError
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/plugins/config'
4
+ require 'dry/plugins/host/dsl'
5
+
6
+ module Dry
7
+ module Plugins
8
+ module Host
9
+ # Extends a host with plug-ins interfaces
10
+ class Builder
11
+ def initialize(registry_method: Plugins.config.registry_method)
12
+ @registry_method = registry_method
13
+ end
14
+
15
+ # @return [Symbol]
16
+ attr_reader :registry_method
17
+
18
+ # @param host [Module]
19
+ #
20
+ # @return [Module]
21
+ #
22
+ # @example
23
+ # require 'dry/plugins/module_builder'
24
+ #
25
+ # class Host
26
+ # end
27
+ #
28
+ # module_builder = Dry::Plugins::HostExtender.new
29
+ # module_builder.call(Host) #=> Host::Plugins
30
+ def call(host, registry)
31
+ unless host.respond_to? registry_method
32
+ host.define_singleton_method registry_method do
33
+ registry
34
+ end
35
+ end
36
+
37
+ unless host.singleton_class.included_modules.include? Host::DSL
38
+ host.extend Host::DSL
39
+ end
40
+
41
+ host
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end