smart_initializer 0.1.0.alpha4 → 0.1.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/.rubocop.yml +1 -1
- data/.travis.yml +36 -5
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +48 -31
- data/README.md +151 -22
- data/Rakefile +1 -1
- data/bin/rspec +54 -0
- data/gemfiles/with_external_deps.gemfile +7 -0
- data/gemfiles/with_external_deps.gemfile.lock +99 -0
- data/gemfiles/without_external_deps.gemfile +5 -0
- data/gemfiles/without_external_deps.gemfile.lock +97 -0
- data/lib/smart_core/initializer.rb +38 -35
- data/lib/smart_core/initializer/attribute.rb +12 -4
- data/lib/smart_core/initializer/attribute/factory.rb +47 -27
- data/lib/smart_core/initializer/attribute/parameters.rb +12 -4
- data/lib/smart_core/initializer/configurable_module.rb +27 -0
- data/lib/smart_core/initializer/configuration.rb +33 -0
- data/lib/smart_core/initializer/constructor.rb +9 -6
- data/lib/smart_core/initializer/constructor/definer.rb +34 -11
- data/lib/smart_core/initializer/dsl.rb +23 -6
- data/lib/smart_core/initializer/errors.rb +44 -0
- data/lib/smart_core/initializer/plugins.rb +17 -0
- data/lib/smart_core/initializer/plugins/abstract.rb +55 -0
- data/lib/smart_core/initializer/plugins/access_mixin.rb +47 -0
- data/lib/smart_core/initializer/plugins/registry.rb +166 -0
- data/lib/smart_core/initializer/plugins/registry_interface.rb +77 -0
- data/lib/smart_core/initializer/plugins/thy_types.rb +30 -0
- data/lib/smart_core/initializer/plugins/thy_types/errors.rb +11 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types.rb +23 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +78 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation.rb +12 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/base.rb +9 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/cast.rb +21 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/valid.rb +16 -0
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/validate.rb +19 -0
- data/lib/smart_core/initializer/settings.rb +49 -0
- data/lib/smart_core/initializer/settings/duplicator.rb +20 -0
- data/lib/smart_core/initializer/settings/type_system.rb +69 -0
- data/lib/smart_core/initializer/type_system.rb +16 -0
- data/lib/smart_core/initializer/type_system/interop.rb +103 -0
- data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +70 -0
- data/lib/smart_core/initializer/type_system/interop/aliasing.rb +72 -0
- data/lib/smart_core/initializer/type_system/interop/aliasing/alias_list.rb +141 -0
- data/lib/smart_core/initializer/type_system/interop/operation.rb +30 -0
- data/lib/smart_core/initializer/type_system/registry.rb +174 -0
- data/lib/smart_core/initializer/type_system/registry_interface.rb +102 -0
- data/lib/smart_core/initializer/type_system/smart_types.rb +48 -0
- data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +72 -0
- data/lib/smart_core/initializer/type_system/smart_types/operation.rb +13 -0
- data/lib/smart_core/initializer/type_system/smart_types/operation/base.rb +8 -0
- data/lib/smart_core/initializer/type_system/smart_types/operation/cast.rb +16 -0
- data/lib/smart_core/initializer/type_system/smart_types/operation/valid.rb +16 -0
- data/lib/smart_core/initializer/type_system/smart_types/operation/validate.rb +16 -0
- data/lib/smart_core/initializer/version.rb +1 -1
- data/smart_initializer.gemspec +13 -9
- metadata +67 -17
- data/lib/smart_core/initializer/attribute/init_extension.rb +0 -4
- data/lib/smart_core/initializer/type_aliasing.rb +0 -50
- data/lib/smart_core/initializer/type_aliasing/alias_list.rb +0 -101
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module SmartCore::Initializer::Plugins::AccessMixin
|
6
|
+
# @param plugin_name [Symbol, String]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @see SmartCore::Initializer::Plugins
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
# @since 0.1.0
|
13
|
+
def plugin(plugin_name)
|
14
|
+
SmartCore::Initializer::Plugins.load(plugin_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Array<String>]
|
18
|
+
#
|
19
|
+
# @see SmartCore::Initializer::Plugins
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
# @since 0.1.0
|
23
|
+
def plugins
|
24
|
+
SmartCore::Initializer::Plugins.names
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Hash<String,Class<SmartCore::Initializer::Plugins::Abstract>>]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
def loaded_plugins
|
32
|
+
SmartCore::Initializer::Plugins.loaded_plugins
|
33
|
+
end
|
34
|
+
alias_method :enabled_plugins, :loaded_plugins
|
35
|
+
|
36
|
+
# @param plugin_name [String, Symbol]
|
37
|
+
# @param plugin_klass [Class<SmartCore::Initializer::Plugins::Abstract>]
|
38
|
+
# @return [void]
|
39
|
+
#
|
40
|
+
# @see SmartCore::Initializer::Plugins
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
# @since 0.1.0
|
44
|
+
def register_plugin(plugin_name, plugin_klass)
|
45
|
+
SmartCore::Initializer::Plugins.register_plugin(plugin_name, plugin_klass)
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Plugins::Registry
|
6
|
+
# @since 0.1.0
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def initialize
|
14
|
+
@plugin_set = {}
|
15
|
+
@access_lock = Mutex.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param plugin_name [Symbol, String]
|
19
|
+
# @return [SmartCore::Initializer::Plugins::Abstract]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
def [](plugin_name)
|
24
|
+
thread_safe { fetch(plugin_name) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param plugin_name [Symbol, String]
|
28
|
+
# @param plugin_module [SmartCore::Initializer::Plugins::Abstract]
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.1.0
|
33
|
+
def register(plugin_name, plugin_module)
|
34
|
+
thread_safe { apply(plugin_name, plugin_module) }
|
35
|
+
end
|
36
|
+
alias_method :[]=, :register
|
37
|
+
|
38
|
+
# @return [Array<String>]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
def names
|
43
|
+
thread_safe { plugin_names }
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Hash<String,Class<SmartCore::Initializer::Plugins::Abstract>>]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.1.0
|
50
|
+
def loaded
|
51
|
+
thread_safe { loaded_plugins }
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param block [Block]
|
55
|
+
# @return [Enumerable]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
def each(&block)
|
60
|
+
thread_safe { iterate(&block) }
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# @return [Hash]
|
66
|
+
#
|
67
|
+
# @api private
|
68
|
+
# @since 0.1.0
|
69
|
+
attr_reader :plugin_set
|
70
|
+
|
71
|
+
# @return [Mutex]
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
# @since 0.1.0
|
75
|
+
attr_reader :access_lock
|
76
|
+
|
77
|
+
# @return [void]
|
78
|
+
#
|
79
|
+
# @api private
|
80
|
+
# @since 0.1.0
|
81
|
+
def thread_safe
|
82
|
+
access_lock.synchronize { yield if block_given? }
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [Array<String>]
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
# @since 0.1.0
|
89
|
+
def plugin_names
|
90
|
+
plugin_set.keys
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param block [Block]
|
94
|
+
# @return [Enumerable]
|
95
|
+
#
|
96
|
+
# @api private
|
97
|
+
# @since 0.1.0
|
98
|
+
def iterate(&block)
|
99
|
+
block_given? ? plugin_set.each_pair(&block) : plugin_set.each_pair
|
100
|
+
end
|
101
|
+
|
102
|
+
# @param plugin_name [String]
|
103
|
+
# @return [Boolean]
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
# @since 0.1.0
|
107
|
+
def registered?(plugin_name)
|
108
|
+
plugin_set.key?(plugin_name)
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [Array<SmartCore::Initializer::Plugins::Abstract>]
|
112
|
+
#
|
113
|
+
# @api private
|
114
|
+
# @since 0.1.0
|
115
|
+
def loaded_plugins
|
116
|
+
plugin_set.select { |_plugin_name, plugin_module| plugin_module.loaded? }
|
117
|
+
end
|
118
|
+
|
119
|
+
# @param plugin_name [Symbol, String]
|
120
|
+
# @param plugin_module [SmartCore::Initializer::Plugins::Abstract]
|
121
|
+
# @return [void]
|
122
|
+
#
|
123
|
+
# @raise [SmartCore::Initializer::AlreadyRegisteredPluginError]
|
124
|
+
#
|
125
|
+
# @api private
|
126
|
+
# @since 0.1.0
|
127
|
+
def apply(plugin_name, plugin_module)
|
128
|
+
plugin_name = indifferently_accessible_plugin_name(plugin_name)
|
129
|
+
|
130
|
+
if registered?(plugin_name)
|
131
|
+
raise(SmartCore::Initializer::AlreadyRegisteredPluginError, <<~ERROR_MESSAGE)
|
132
|
+
#{plugin_name} plugin already exists
|
133
|
+
ERROR_MESSAGE
|
134
|
+
end
|
135
|
+
|
136
|
+
plugin_set[plugin_name] = plugin_module
|
137
|
+
end
|
138
|
+
|
139
|
+
# @param plugin_name [Symbol, String]
|
140
|
+
# @return [SmartCore::Initializer::Plugins::Abstract]
|
141
|
+
#
|
142
|
+
# @raise [SmartCore::Initializer::UnregisteredPluginError]
|
143
|
+
#
|
144
|
+
# @api private
|
145
|
+
# @since 0.1.0
|
146
|
+
def fetch(plugin_name)
|
147
|
+
plugin_name = indifferently_accessible_plugin_name(plugin_name)
|
148
|
+
|
149
|
+
unless registered?(plugin_name)
|
150
|
+
raise(SmartCore::Initializer::UnregisteredPluginError, <<~ERROR_MESSAGE)
|
151
|
+
#{plugin_name} plugin is not registered
|
152
|
+
ERROR_MESSAGE
|
153
|
+
end
|
154
|
+
|
155
|
+
plugin_set[plugin_name]
|
156
|
+
end
|
157
|
+
|
158
|
+
# @param key [Symbol, String]
|
159
|
+
# @return [String]
|
160
|
+
#
|
161
|
+
# @api private
|
162
|
+
# @since 0.1.0
|
163
|
+
def indifferently_accessible_plugin_name(plugin_name)
|
164
|
+
plugin_name.to_s
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module SmartCore::Initializer::Plugins::RegistryInterface
|
6
|
+
class << self
|
7
|
+
# @param base_module [Class, Module]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def extended(base_module)
|
13
|
+
base_module.instance_variable_set(
|
14
|
+
:@plugin_registry, SmartCore::Initializer::Plugins::Registry.new
|
15
|
+
)
|
16
|
+
base_module.instance_variable_set(
|
17
|
+
:@access_lock, SmartCore::Engine::Lock.new
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param plugin_name [Symbol, String]
|
23
|
+
# @return [void]
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
# @since 0.1.0
|
27
|
+
def load(plugin_name)
|
28
|
+
thread_safe { plugin_registry[plugin_name].load! }
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Array<String>]
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
# @since 0.1.0
|
35
|
+
def loaded_plugins
|
36
|
+
thread_safe { plugin_registry.loaded.keys }
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array<String>]
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
# @since 0.1.0
|
43
|
+
def names
|
44
|
+
thread_safe { plugin_registry.names }
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param plugin_name [Symbol, String]
|
48
|
+
# @return [void]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
# @since 0.1.0
|
52
|
+
def register_plugin(plugin_name, plugin_module)
|
53
|
+
thread_safe { plugin_registry[plugin_name] = plugin_module }
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# @return [SmartCore::Initializer::Plugins::Registry]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.1.0
|
62
|
+
attr_reader :plugin_registry
|
63
|
+
|
64
|
+
# @return [SmartCore::Engine::Lock]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
# @since 0.1.0
|
68
|
+
attr_reader :access_lock
|
69
|
+
|
70
|
+
# @return [void]
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
# @since 0.1.0
|
74
|
+
def thread_safe
|
75
|
+
access_lock.synchronize { yield if block_given? }
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Plugins::ThyTypes < SmartCore::Initializer::Plugins::Abstract
|
6
|
+
class << self
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
def install!
|
12
|
+
raise(
|
13
|
+
SmartCore::Initializer::UnresolvedPluginDependencyError,
|
14
|
+
'::Thy does not exist or "thy" gem is not loaded'
|
15
|
+
) unless const_defined?('::Thy')
|
16
|
+
|
17
|
+
# NOTE: require necessary dependencies
|
18
|
+
require 'date'
|
19
|
+
|
20
|
+
# NOTE: add thy-types type system implementation
|
21
|
+
require_relative 'thy_types/errors'
|
22
|
+
require_relative 'thy_types/thy_types'
|
23
|
+
|
24
|
+
# NOTE: register thy-types type system
|
25
|
+
SmartCore::Initializer::TypeSystem.register(
|
26
|
+
:thy_types, SmartCore::Initializer::TypeSystem::ThyTypes
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore::Initializer::TypeSystem
|
4
|
+
# @api public
|
5
|
+
# @since 0.1.0
|
6
|
+
class ThyTypes < Interop
|
7
|
+
require_relative 'thy_types/abstract_factory'
|
8
|
+
require_relative 'thy_types/operation'
|
9
|
+
|
10
|
+
type_alias(:any, AbstractFactory.generic_type_object)
|
11
|
+
type_alias(:nil, ::Thy::Types::Nil)
|
12
|
+
type_alias(:string, ::Thy::Types::String)
|
13
|
+
type_alias(:symbol, ::Thy::Types::Symbol)
|
14
|
+
type_alias(:integer, ::Thy::Types::Integer)
|
15
|
+
type_alias(:float, ::Thy::Types::Float)
|
16
|
+
type_alias(:numeric, ::Thy::Types::Numeric)
|
17
|
+
type_alias(:boolean, ::Thy::Types::Boolean)
|
18
|
+
type_alias(:time, ::Thy::Types::Time)
|
19
|
+
type_alias(:date_time, ::Thy::Types::DateTime)
|
20
|
+
type_alias(:untyped_array, ::Thy::Types::UntypedArray)
|
21
|
+
type_alias(:untyped_hash, ::Thy::Types::UntypedHash)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore::Initializer::TypeSystem
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class ThyTypes::AbstractFactory < Interop::AbstractFactory
|
7
|
+
# @return [Thy::Type]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
GENERIC_TYPE = ::Thy::Type.new { true }
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# @param type [Thy::Type, #check]
|
15
|
+
# @return [void]
|
16
|
+
#
|
17
|
+
# @raise [SmartCore::Initializer::IncorrectTypeObjectError]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
# @since 0.1.0
|
21
|
+
def prevent_incompatible_type!(type)
|
22
|
+
unless type.respond_to?(:check) || type.is_a?(::Thy::Type)
|
23
|
+
raise(
|
24
|
+
SmartCore::Initializer::IncorrectTypeObjectError,
|
25
|
+
'Incorrect Thy::Type primitive ' \
|
26
|
+
'(type object should respond to :check method)'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param type [Thy::Type, #check]
|
32
|
+
# @return [SmartCore::Initializer::TypeSystem::ThyTypes::Operation::Valid]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
def build_valid_operation(type)
|
37
|
+
ThyTypes::Operation::Valid.new(type)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Thy::Type, #check]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
# @since 0.1.0
|
44
|
+
def generic_type_object
|
45
|
+
GENERIC_TYPE
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param type [Thy::Type, #check]
|
49
|
+
# @return [SmartCore::Initializer::TypeSystem::ThyTypes::Operation::Validate]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.1.0
|
53
|
+
def build_validate_operation(type)
|
54
|
+
ThyTypes::Operation::Validate.new(type)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param type [Thy::Type, #check]
|
58
|
+
# @return [SmartCore::Initializer::TypeSystem::ThyTypes::Operation::Cast]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.1.0
|
62
|
+
def build_cast_operation(type)
|
63
|
+
ThyTypes::Operation::Cast.new(type)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param valid_op [SmartCore::Initializer::TypeSystem::ThyTypes::Operation::Valid]
|
67
|
+
# @param valid_op [SmartCore::Initializer::TypeSystem::ThyTypes::Operation::Validate]
|
68
|
+
# @param valid_op [SmartCore::Initializer::TypeSystem::ThyTypes::Operation::Cast]
|
69
|
+
# @return [SmartCore::Initializer::TypeSystem::ThyTypes]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
# @since 0.1.0
|
73
|
+
def build_interop(valid_op, validate_op, cast_op)
|
74
|
+
ThyTypes.new(valid_op, validate_op, cast_op)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore::Initializer::TypeSystem
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
module ThyTypes::Operation
|
7
|
+
require_relative 'operation/base'
|
8
|
+
require_relative 'operation/valid'
|
9
|
+
require_relative 'operation/validate'
|
10
|
+
require_relative 'operation/cast'
|
11
|
+
end
|
12
|
+
end
|