-
-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathplugins.rb
More file actions
142 lines (113 loc) · 3.61 KB
/
Copy pathplugins.rb
File metadata and controls
142 lines (113 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# frozen_string_literal: true
require "dry/system/constants"
module Dry
module System
module Plugins
# @api private
class Plugin
attr_reader :name
attr_reader :mod
attr_reader :block
# @api private
def initialize(name, mod, &block)
@name = name
@mod = mod
@block = block
end
# @api private
def apply_to(system, **options)
system.extend(stateful? ? mod.new(**options) : mod)
system.instance_eval(&block) if block
system
end
# @api private
def load_dependencies(dependencies = mod_dependencies, gem = nil)
Array(dependencies).each do |dependency|
if dependency.is_a?(Array) || dependency.is_a?(Hash)
dependency.each { |value| load_dependencies(*Array(value).reverse) }
elsif !Plugins.loaded_dependencies.include?(dependency.to_s)
load_dependency(dependency, gem)
end
end
end
# @api private
def load_dependency(dependency, gem)
Kernel.require dependency
Plugins.loaded_dependencies << dependency.to_s
rescue LoadError => e
raise PluginDependencyMissing.new(name, e.message, gem)
end
# @api private
def stateful?
mod < Module
end
# @api private
def mod_dependencies
return EMPTY_ARRAY unless mod.respond_to?(:dependencies)
mod.dependencies.is_a?(Array) ? mod.dependencies : [mod.dependencies]
end
end
# Register a plugin
#
# @param [Symbol] name The name of a plugin
# @param [Class] plugin Plugin module
#
# @return [Plugins]
#
# @api public
def self.register(name, plugin, &block)
registry[name] = Plugin.new(name, plugin, &block)
end
# @api private
def self.registry
@registry ||= {}
end
# @api private
def self.loaded_dependencies
@loaded_dependencies ||= []
end
# Enables a plugin if not already enabled.
# Raises error if plugin cannot be found in the plugin registry.
#
# @param [Symbol] name The plugin name
# @param [Hash] options Plugin options
#
# @return [self]
#
# @api public
def use(name, **options)
return self if enabled_plugins.include?(name)
raise PluginNotFoundError, name unless (plugin = Plugins.registry[name])
plugin.load_dependencies
plugin.apply_to(self, **options)
enabled_plugins << name
self
end
# @api private
def inherited(klass)
klass.instance_variable_set(:@enabled_plugins, enabled_plugins.dup)
super
end
# @api private
def enabled_plugins
@enabled_plugins ||= []
end
require "dry/system/plugins/bootsnap"
register(:bootsnap, Plugins::Bootsnap)
require "dry/system/plugins/logging"
register(:logging, Plugins::Logging)
require "dry/system/plugins/env"
register(:env, Plugins::Env)
require "dry/system/plugins/notifications"
register(:notifications, Plugins::Notifications)
require "dry/system/plugins/monitoring"
register(:monitoring, Plugins::Monitoring)
require "dry/system/plugins/dependency_graph"
register(:dependency_graph, Plugins::DependencyGraph)
require "dry/system/plugins/zeitwerk"
register(:zeitwerk, Plugins::Zeitwerk)
require_relative "plugins/injector_mixin"
register(:injector_mixin, Plugins::InjectorMixin)
end
end
end