smart_container 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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +15 -0
  5. data/.travis.yml +28 -0
  6. data/CHANGELOG.md +6 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +83 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +39 -0
  12. data/Rakefile +21 -0
  13. data/bin/console +8 -0
  14. data/bin/setup +8 -0
  15. data/lib/smart_core/container.rb +135 -0
  16. data/lib/smart_core/container/arbitary_lock.rb +22 -0
  17. data/lib/smart_core/container/definition_dsl.rb +109 -0
  18. data/lib/smart_core/container/definition_dsl/command_set.rb +87 -0
  19. data/lib/smart_core/container/definition_dsl/commands.rb +9 -0
  20. data/lib/smart_core/container/definition_dsl/commands/base.rb +48 -0
  21. data/lib/smart_core/container/definition_dsl/commands/definition.rb +9 -0
  22. data/lib/smart_core/container/definition_dsl/commands/definition/compose.rb +49 -0
  23. data/lib/smart_core/container/definition_dsl/commands/definition/namespace.rb +54 -0
  24. data/lib/smart_core/container/definition_dsl/commands/definition/register.rb +54 -0
  25. data/lib/smart_core/container/definition_dsl/commands/instantiation.rb +8 -0
  26. data/lib/smart_core/container/definition_dsl/commands/instantiation/compose.rb +53 -0
  27. data/lib/smart_core/container/definition_dsl/commands/instantiation/freeze_state.rb +27 -0
  28. data/lib/smart_core/container/definition_dsl/inheritance.rb +23 -0
  29. data/lib/smart_core/container/dependency_compatability.rb +9 -0
  30. data/lib/smart_core/container/dependency_compatability/definition.rb +38 -0
  31. data/lib/smart_core/container/dependency_compatability/general.rb +61 -0
  32. data/lib/smart_core/container/dependency_compatability/registry.rb +36 -0
  33. data/lib/smart_core/container/dependency_resolver.rb +93 -0
  34. data/lib/smart_core/container/dependency_resolver/route.rb +83 -0
  35. data/lib/smart_core/container/dependency_resolver/route/cursor.rb +47 -0
  36. data/lib/smart_core/container/entities.rb +11 -0
  37. data/lib/smart_core/container/entities/base.rb +26 -0
  38. data/lib/smart_core/container/entities/dependency.rb +38 -0
  39. data/lib/smart_core/container/entities/dependency_builder.rb +50 -0
  40. data/lib/smart_core/container/entities/namespace.rb +73 -0
  41. data/lib/smart_core/container/entities/namespace_builder.rb +41 -0
  42. data/lib/smart_core/container/errors.rb +65 -0
  43. data/lib/smart_core/container/key_guard.rb +31 -0
  44. data/lib/smart_core/container/mixin.rb +83 -0
  45. data/lib/smart_core/container/registry.rb +250 -0
  46. data/lib/smart_core/container/registry_builder.rb +51 -0
  47. data/lib/smart_core/container/version.rb +9 -0
  48. data/smart_container.gemspec +38 -0
  49. metadata +191 -0
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Container::ArbitaryLock
6
+ # @return [void]
7
+ #
8
+ # @api private
9
+ # @since 0.1.0
10
+ def initialize
11
+ @lock = Mutex.new
12
+ end
13
+
14
+ # @param block [Proc]
15
+ # @return [Any]
16
+ #
17
+ # @api private
18
+ # @since 0.1.0
19
+ def thread_safe(&block)
20
+ @lock.owned? ? yield : @lock.synchronize(&block)
21
+ end
22
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SmartCore::Container
4
+ # @api private
5
+ # @since 0.1.0
6
+ module DefinitionDSL
7
+ require_relative 'definition_dsl/commands'
8
+ require_relative 'definition_dsl/command_set'
9
+ require_relative 'definition_dsl/inheritance'
10
+
11
+ class << self
12
+ # @param base_klass [Class<SmartCore::Container>]
13
+ # @return [void]
14
+ #
15
+ # @api private
16
+ # @since 0.1.0
17
+ def included(base_klass)
18
+ base_klass.instance_variable_set(:@__container_definition_commands__, CommandSet.new)
19
+ base_klass.instance_variable_set(:@__container_instantiation_commands__, CommandSet.new)
20
+ base_klass.instance_variable_set(:@__container_definition_lock__, ArbitaryLock.new)
21
+ base_klass.singleton_class.send(:attr_reader, :__container_definition_commands__)
22
+ base_klass.singleton_class.send(:attr_reader, :__container_instantiation_commands__)
23
+ base_klass.extend(ClassMethods)
24
+ base_klass.singleton_class.prepend(ClassInheritance)
25
+ end
26
+ end
27
+
28
+ # @api private
29
+ # @since 0.1.0
30
+ module ClassInheritance
31
+ # @param child_klass [Class<SmartCore::Container>]
32
+ # @return [void]
33
+ #
34
+ # @api private
35
+ # @since 0.1.0
36
+ def inherited(child_klass)
37
+ child_klass.instance_variable_set(:@__container_definition_commands__, CommandSet.new)
38
+ child_klass.instance_variable_set(:@__container_instantiation_commands__, CommandSet.new)
39
+ child_klass.instance_variable_set(:@__container_definition_lock__, ArbitaryLock.new)
40
+ SmartCore::Container::DefinitionDSL::Inheritance.inherit(base: self, child: child_klass)
41
+ child_klass.singleton_class.prepend(ClassInheritance)
42
+ super
43
+ end
44
+ end
45
+
46
+ # @api private
47
+ # @since 0.1.0
48
+ module ClassMethods
49
+ # @param namespace_name [String, Symbol]
50
+ # @param dependencies_definition [Block]
51
+ # @return [void]
52
+ #
53
+ # @api public
54
+ # @since 0.1.0
55
+ def namespace(namespace_name, &dependencies_definition)
56
+ @__container_definition_lock__.thread_safe do
57
+ DependencyCompatability::Definition.prevent_dependency_overlap!(self, namespace_name)
58
+
59
+ __container_definition_commands__ << Commands::Definition::Namespace.new(
60
+ namespace_name, dependencies_definition
61
+ )
62
+ end
63
+ end
64
+
65
+ # @param dependency_name [String, Symbol]
66
+ # @param dependency_definition [Block]
67
+ # @return [void]
68
+ #
69
+ # @api public
70
+ # @since 0.1.0
71
+ def register(dependency_name, &dependency_definition)
72
+ @__container_definition_lock__.thread_safe do
73
+ DependencyCompatability::Definition.prevent_namespace_overlap!(self, dependency_name)
74
+
75
+ __container_definition_commands__ << Commands::Definition::Register.new(
76
+ dependency_name, dependency_definition
77
+ )
78
+ end
79
+ end
80
+
81
+ # @param container_klass [Class<SmartCore::Container>]
82
+ # @return [void]
83
+ #
84
+ # @api public
85
+ # @since 0.1.0
86
+ def compose(container_klass)
87
+ @__container_definition_lock__.thread_safe do
88
+ __container_definition_commands__ << Commands::Definition::Compose.new(
89
+ container_klass
90
+ )
91
+
92
+ __container_instantiation_commands__ << Commands::Instantiation::Compose.new(
93
+ container_klass
94
+ )
95
+ end
96
+ end
97
+
98
+ # @return [void]
99
+ #
100
+ # @api public
101
+ # @since 0.1.0
102
+ def freeze_state!
103
+ @__container_definition_lock__.thread_safe do
104
+ __container_instantiation_commands__ << Commands::Instantiation::FreezeState.new
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Container::DefinitionDSL::CommandSet
6
+ # @since 0.1.0
7
+ include Enumerable
8
+
9
+ # @return [Array<SmartCore::Container::DefinitionDSL::Commands::Base>]
10
+ #
11
+ # @api private
12
+ # @since 0.1.0
13
+ attr_reader :commands
14
+
15
+ # @return [void]
16
+ #
17
+ # @api private
18
+ # @since 0.1.0
19
+ def initialize
20
+ @commands = []
21
+ @access_lock = SmartCore::Container::ArbitaryLock.new
22
+ end
23
+
24
+ # @param [SmartCore::Container::DefinitionDSL::Commands::Base]
25
+ # @return [void]
26
+ #
27
+ # @api private
28
+ # @since 0.1.0
29
+ def add_command(command)
30
+ thread_safe { commands << command }
31
+ end
32
+ alias_method :<<, :add_command
33
+
34
+ # @param block [Block]
35
+ # @return [Enumerable]
36
+ #
37
+ # @api private
38
+ # @since 0.1.0
39
+ def each(&block)
40
+ thread_safe { block_given? ? commands.each(&block) : commands.each }
41
+ end
42
+
43
+ # @param command_set [SmartCore::Container::DefinitionDSL::CommandSet]
44
+ # @param concat_condition [Block]
45
+ # @yield [command]
46
+ # @yieldparam command [SmartCore::Container::DefinitionDSL::Commands::Base]
47
+ # @return [void]
48
+ #
49
+ # @api private
50
+ # @since 0.1.0
51
+ def concat(command_set, &concat_condition)
52
+ thread_safe do
53
+ if block_given?
54
+ command_set.dup.each { |command| (commands << command) if yield(command) }
55
+ else
56
+ # :nocov:
57
+ commands.concat(command_set.dup.commands) # NOTE: unreachable code at this moment
58
+ # :nocov:
59
+ end
60
+ end
61
+ end
62
+
63
+ # @return [SmartCore::Container::DefinitionDSL::CommandSet]
64
+ #
65
+ # @api private
66
+ # @since 0.1.0
67
+ def dup
68
+ thread_safe do
69
+ self.class.new.tap do |duplicate|
70
+ commands.each do |command|
71
+ duplicate.add_command(command.dup)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ # @param block [Block]
80
+ # @return [Any]
81
+ #
82
+ # @api private
83
+ # @since 0.1.0
84
+ def thread_safe(&block)
85
+ @access_lock.thread_safe(&block)
86
+ end
87
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Container::DefinitionDSL::Commands
6
+ require_relative 'commands/base'
7
+ require_relative 'commands/instantiation'
8
+ require_relative 'commands/definition'
9
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Container::DefinitionDSL::Commands::Base
6
+ class << self
7
+ # @param identifier [Boolean]
8
+ # @return [Boolean]
9
+ #
10
+ # @api private
11
+ # @since 0.19.0
12
+ def inheritable=(identifier)
13
+ @inheritable = identifier
14
+ end
15
+
16
+ # @return [Boolean]
17
+ #
18
+ # @api private
19
+ # @since 0.19.0
20
+ def inheritable?
21
+ @inheritable
22
+ end
23
+
24
+ # @return [Boolean]
25
+ #
26
+ # @api private
27
+ # @since 0.19.0
28
+ def inherited(child_klass)
29
+ child_klass.instance_variable_set(:@inheritable, true)
30
+ super
31
+ end
32
+ end
33
+
34
+ # @param regsitry [SmartCore::Container::Registry]
35
+ # @return [void]
36
+ #
37
+ # @api private
38
+ # @since 0.1.0
39
+ def call(registry); end
40
+
41
+ # @return [Boolean]
42
+ #
43
+ # @api private
44
+ # @since 0.19.0
45
+ def inheritable?
46
+ self.class.inheritable?
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
6
+ require_relative 'definition/namespace'
7
+ require_relative 'definition/register'
8
+ require_relative 'definition/compose'
9
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Compose < SmartCore::Container::DefinitionDSL::Commands::Base
7
+ # @since 0.1.0
8
+ self.inheritable = true
9
+
10
+ # @param container_klass [Class<SmartCore::Container>]
11
+ # @return [void]
12
+ #
13
+ # @api private
14
+ # @since 0.1.0
15
+ def initialize(container_klass)
16
+ raise(
17
+ SmartCore::ArgumentError,
18
+ 'Container class should be a subtype of Quantum::Container'
19
+ ) unless container_klass < SmartCore::Container
20
+
21
+ @container_klass = container_klass
22
+ end
23
+
24
+ # @param registry [SmartCore::Container::Registry]
25
+ # @return [void]
26
+ #
27
+ # @api private
28
+ # @since 0.1.0
29
+ def call(registry)
30
+ SmartCore::Container::RegistryBuilder.build_definitions(container_klass, registry)
31
+ end
32
+
33
+ # @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Compose]
34
+ #
35
+ # @api private
36
+ # @since 0.1.0
37
+ def dup
38
+ self.class.new(container_klass)
39
+ end
40
+
41
+ private
42
+
43
+ # @return [Class<SmartCore::Container>]
44
+ #
45
+ # @api private
46
+ # @since 0.1.0
47
+ attr_reader :container_klass
48
+ end
49
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Namespace < SmartCore::Container::DefinitionDSL::Commands::Base
7
+ # @since 0.1.0
8
+ self.inheritable = true
9
+
10
+ # @return [String]
11
+ #
12
+ # @api private
13
+ # @since 0.1.0
14
+ attr_reader :namespace_name
15
+
16
+ # @param namespace_name [String, Symbol]
17
+ # @param dependencies_definition [Proc]
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def initialize(namespace_name, dependencies_definition)
23
+ SmartCore::Container::KeyGuard.indifferently_accessable_key(namespace_name).tap do |name|
24
+ @namespace_name = name
25
+ @dependencies_definition = dependencies_definition
26
+ end
27
+ end
28
+
29
+ # @param registry [SmartCore::Container::Registry]
30
+ # @return [void]
31
+ #
32
+ # @api private
33
+ # @since 0.1.0
34
+ def call(registry)
35
+ registry.register_namespace(namespace_name, &dependencies_definition)
36
+ end
37
+
38
+ # @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Namespace]
39
+ #
40
+ # @api private
41
+ # @since 0.1.0
42
+ def dup
43
+ self.class.new(namespace_name, dependencies_definition)
44
+ end
45
+
46
+ private
47
+
48
+ # @return [Proc]
49
+ #
50
+ # @api private
51
+ # @since 0.1.0
52
+ attr_reader :dependencies_definition
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Register < SmartCore::Container::DefinitionDSL::Commands::Base
7
+ # @since 0.1.0
8
+ self.inheritable = true
9
+
10
+ # @return [String]
11
+ #
12
+ # @api private
13
+ # @since 0.1.0
14
+ attr_reader :dependency_name
15
+
16
+ # @param dependency_name [String, Symbol]
17
+ # @param dependency_definition [Proc]
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def initialize(dependency_name, dependency_definition)
23
+ SmartCore::Container::KeyGuard.indifferently_accessable_key(dependency_name).tap do |name|
24
+ @dependency_name = name
25
+ @dependency_definition = dependency_definition
26
+ end
27
+ end
28
+
29
+ # @param registry [SmartCore::Container::Registry]
30
+ # @return [void]
31
+ #
32
+ # @api private
33
+ # @since 0.1.0
34
+ def call(registry)
35
+ registry.register_dependency(dependency_name, &dependency_definition)
36
+ end
37
+
38
+ # @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Register]
39
+ #
40
+ # @api private
41
+ # @since 0.1.0
42
+ def dup
43
+ self.class.new(dependency_name, dependency_definition)
44
+ end
45
+
46
+ private
47
+
48
+ # @return [Proc]
49
+ #
50
+ # @api private
51
+ # @since 0.1.0
52
+ attr_reader :dependency_definition
53
+ end
54
+ end