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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +36 -5
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile.lock +48 -31
  6. data/README.md +151 -22
  7. data/Rakefile +1 -1
  8. data/bin/rspec +54 -0
  9. data/gemfiles/with_external_deps.gemfile +7 -0
  10. data/gemfiles/with_external_deps.gemfile.lock +99 -0
  11. data/gemfiles/without_external_deps.gemfile +5 -0
  12. data/gemfiles/without_external_deps.gemfile.lock +97 -0
  13. data/lib/smart_core/initializer.rb +38 -35
  14. data/lib/smart_core/initializer/attribute.rb +12 -4
  15. data/lib/smart_core/initializer/attribute/factory.rb +47 -27
  16. data/lib/smart_core/initializer/attribute/parameters.rb +12 -4
  17. data/lib/smart_core/initializer/configurable_module.rb +27 -0
  18. data/lib/smart_core/initializer/configuration.rb +33 -0
  19. data/lib/smart_core/initializer/constructor.rb +9 -6
  20. data/lib/smart_core/initializer/constructor/definer.rb +34 -11
  21. data/lib/smart_core/initializer/dsl.rb +23 -6
  22. data/lib/smart_core/initializer/errors.rb +44 -0
  23. data/lib/smart_core/initializer/plugins.rb +17 -0
  24. data/lib/smart_core/initializer/plugins/abstract.rb +55 -0
  25. data/lib/smart_core/initializer/plugins/access_mixin.rb +47 -0
  26. data/lib/smart_core/initializer/plugins/registry.rb +166 -0
  27. data/lib/smart_core/initializer/plugins/registry_interface.rb +77 -0
  28. data/lib/smart_core/initializer/plugins/thy_types.rb +30 -0
  29. data/lib/smart_core/initializer/plugins/thy_types/errors.rb +11 -0
  30. data/lib/smart_core/initializer/plugins/thy_types/thy_types.rb +23 -0
  31. data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +78 -0
  32. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation.rb +12 -0
  33. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/base.rb +9 -0
  34. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/cast.rb +21 -0
  35. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/valid.rb +16 -0
  36. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/validate.rb +19 -0
  37. data/lib/smart_core/initializer/settings.rb +49 -0
  38. data/lib/smart_core/initializer/settings/duplicator.rb +20 -0
  39. data/lib/smart_core/initializer/settings/type_system.rb +69 -0
  40. data/lib/smart_core/initializer/type_system.rb +16 -0
  41. data/lib/smart_core/initializer/type_system/interop.rb +103 -0
  42. data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +70 -0
  43. data/lib/smart_core/initializer/type_system/interop/aliasing.rb +72 -0
  44. data/lib/smart_core/initializer/type_system/interop/aliasing/alias_list.rb +141 -0
  45. data/lib/smart_core/initializer/type_system/interop/operation.rb +30 -0
  46. data/lib/smart_core/initializer/type_system/registry.rb +174 -0
  47. data/lib/smart_core/initializer/type_system/registry_interface.rb +102 -0
  48. data/lib/smart_core/initializer/type_system/smart_types.rb +48 -0
  49. data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +72 -0
  50. data/lib/smart_core/initializer/type_system/smart_types/operation.rb +13 -0
  51. data/lib/smart_core/initializer/type_system/smart_types/operation/base.rb +8 -0
  52. data/lib/smart_core/initializer/type_system/smart_types/operation/cast.rb +16 -0
  53. data/lib/smart_core/initializer/type_system/smart_types/operation/valid.rb +16 -0
  54. data/lib/smart_core/initializer/type_system/smart_types/operation/validate.rb +16 -0
  55. data/lib/smart_core/initializer/version.rb +1 -1
  56. data/smart_initializer.gemspec +13 -9
  57. metadata +67 -17
  58. data/lib/smart_core/initializer/attribute/init_extension.rb +0 -4
  59. data/lib/smart_core/initializer/type_aliasing.rb +0 -50
  60. 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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Initializer
4
+ # @api public
5
+ # @since 0.1.0
6
+ ThyTypesError = Class.new(SmartCore::Initializer::Error)
7
+
8
+ # @api public
9
+ # @since 0.1.0
10
+ ThyTypeValidationError = Class.new(ThyTypesError)
11
+ 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