corindon 0.6.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae37025ed53b2bec8d329d9d640d40425406a0c6b2ba8fcf85ec573e5b0cdd6d
4
- data.tar.gz: 3d6c2d3acac3f22c5c15b5128a3a7e005a4f1c6ea1508472d29bdcfb5eefc19c
3
+ metadata.gz: e23965fecffcb108574ea3e42ae2889965914a65ebc80f71fbdb3f40e3b67e34
4
+ data.tar.gz: 96efc5116431669ef5ae2d88fa1945ba38d90fb14de3d35e7182154039efbde1
5
5
  SHA512:
6
- metadata.gz: c2d44b60b7a78a391211c194a62b1cabf76664dc2a2f2ab268bc716873468c7e9245f2c6acd18c344596d16b48e3b16ce8f1de028e3a8f30de6adc042f7e8dc9
7
- data.tar.gz: 704342b6b6afe491f9c21f9de07841356edc8c02e504ac66646d195fc88b34733f65dfa3a25a0b0f6ab40927429a11e2dec640c2cbf6a5861fc0a2926dca0b37
6
+ metadata.gz: b87c39aaa85e776fe0289cf9f97eafc80ce093d44775fb5753d864aa5e1ad1537c93b4f99dadce284ae4071f41ee15a03f873ee6230a3c2a246df5acb1fcd0c8
7
+ data.tar.gz: 13ff2f71fc510903f7430e4e37e528cc122a627d8e5228684c922c41b076aaf84a45f6620bcb9755c42a9e66676d117e2b83ef56218980abbe92550f4434f257
@@ -5,40 +5,66 @@ module Corindon
5
5
  class Container
6
6
  using Something::Ext
7
7
 
8
- attr_reader :id_generator
9
8
  attr_reader :injector
10
9
 
11
- # @param [Id::IdGenerator] id_generator
12
- def initialize(id_generator: Id::UuidGenerator.new)
13
- @id_generator = id_generator
10
+ # @param [Array<Definition>] definitions
11
+ def initialize(definitions: [], parameters: {}, service_built_listeners: [])
14
12
  @services = {}
15
13
  @definitions = {}
16
- @parameters = {}
14
+ @parameters = parameters
17
15
  @tags = Hash.new { |hash, key| hash[key] = [] }
18
16
 
19
17
  @injector = Injector.new(container: self)
18
+
19
+ definitions.each { |d| register_definition(d) }
20
+
21
+ @service_built_listeners = service_built_listeners
20
22
  end
21
23
 
22
- # @param [Class] klass
24
+ # @return [Container]
25
+ def dup
26
+ Container.new(
27
+ definitions: definitions.values,
28
+ parameters: parameters.dup,
29
+ service_built_listeners: service_built_listeners
30
+ )
31
+ end
32
+
33
+ # @param [Definition, Injectable, Class]
34
+ # @return [Definition]
35
+ def as_definition(def_or_injectable)
36
+ if def_or_injectable.is_a?(Definition)
37
+ def_or_injectable
38
+ elsif def_or_injectable.is_a?(Injectable)
39
+ def_or_injectable.definition
40
+ elsif def_or_injectable.is_a?(Class)
41
+ Definition.new(def_or_injectable)
42
+ else
43
+ raise StandardError.new("Don't know how to build #{def_or_injectable}")
44
+ end
45
+ end
46
+
47
+ # @param [Class, Injectable, Definition] def_or_injectable
23
48
  # @return [String]
24
- def add_definition(klass, id: nil, anonymous: false, context: {}, &block)
25
- definition = if injectable?(klass)
26
- klass.definition
27
- elsif block.sth?
28
- Dsl.new(klass).exec(context: context, &block)
29
- else
30
- Definition.new(klass)
31
- end
32
-
33
- # Generate an id if set to anonymous when registering
34
- # If a definition is set to be anonymous but an id is provided zhen registering, use this id instead<
35
- if anonymous || (definition.anonymous? && id.nil?)
36
- id = id_generator.generate
49
+ def add_definition(def_or_injectable, context: {}, &block)
50
+ definition = as_definition(def_or_injectable)
51
+
52
+ if block.sth?
53
+ definition = Dsl.from_definition(definition).exec(context: context, &block)
37
54
  end
38
55
 
39
- id = id || definition.id || to_id(klass)
40
- definitions[id] = definition
41
- definition.tags.each { |tag| tags[tag] << id }
56
+ id = definition.id || to_id(def_or_injectable)
57
+
58
+ register_definition(
59
+ Definition.new(
60
+ definition.object_source,
61
+ id: id,
62
+ args: definition.args,
63
+ kwargs: definition.kwargs,
64
+ calls: definition.calls,
65
+ tags: definition.tags
66
+ )
67
+ )
42
68
 
43
69
  id
44
70
  end
@@ -97,26 +123,49 @@ module Corindon
97
123
  parameters.fetch(to_id(key))
98
124
  end
99
125
 
126
+ # @param [Proc{Object, Container}] listener
127
+ def on_service_built(listener)
128
+ service_built_listeners << listener
129
+ end
130
+
100
131
  private
101
132
 
133
+ # @return [Hash{String=>Definition}]
102
134
  attr_reader :definitions
103
135
  attr_reader :parameters
104
136
  attr_reader :services
105
137
  attr_reader :tags
138
+ attr_reader :service_built_listeners
139
+
140
+ def register_definition(definition)
141
+ definitions[definition.id] = definition
142
+ definition.tags.each { |tag| tags[tag] << definition.id }
143
+ end
106
144
 
107
145
  def build_service(id)
108
- definitions.fetch(id).build(injector).tap do |service|
109
- services[id] = service
146
+ service = injector.resolve(definitions.fetch(id)).tap do |svc|
147
+ services[id] = svc
148
+ end
149
+
150
+ service_built_listeners.each do |listener|
151
+ listener.call(service, self)
110
152
  end
153
+
154
+ service
111
155
  end
112
156
 
113
- def injectable?(klass)
114
- klass.is_a?(Class) && klass.ancestors.include?(Injectable)
157
+ def injectable?(object)
158
+ object.is_a?(Injectable)
115
159
  end
116
160
 
117
- # @param [Class, #to_s] key
161
+ # @param [Injectable, Identifiable, Class, Definition, #to_s] key
162
+ # @return [String]
118
163
  def to_id(key)
119
- if key.is_a?(Class)
164
+ if key.is_a?(Definition)
165
+ key.id
166
+ elsif injectable?(key)
167
+ to_id(key.definition)
168
+ elsif key.is_a?(Class)
120
169
  key.name
121
170
  else
122
171
  key.to_s
@@ -5,59 +5,40 @@ require 'semantic'
5
5
  module Corindon
6
6
  module DependencyInjection
7
7
  class Definition
8
- attr_reader :klass
8
+ attr_reader :object_source
9
9
  attr_reader :args
10
10
  attr_reader :kwargs
11
11
  attr_reader :calls
12
12
  attr_reader :tags
13
+ # @return [String]
13
14
  attr_reader :id
14
15
 
15
- def initialize(klass, args: [], kwargs: {}, calls: [], tags: [], id: nil, anonymous: false)
16
- @klass = klass
16
+ def initialize(object_source, args: [], kwargs: {}, calls: [], tags: [], id: nil)
17
+ @object_source = object_source
17
18
  @args = args
18
19
  @kwargs = kwargs
19
20
  @calls = calls
20
21
  @tags = tags
21
22
  @id = id
22
- @anonymous = anonymous
23
23
  end
24
24
 
25
25
  # @param [Injector] injector
26
- # # @return [Object]
26
+ # @return [Object]
27
27
  def build(injector)
28
- object = do_call(klass, :new, injector.resolve(args), injector.resolve(kwargs))
28
+ source = if object_source.is_a?(Class)
29
+ [object_source, :new]
30
+ else
31
+ injector.resolve(object_source)
32
+ end
33
+
34
+ object = RubyCompat.do_call(*source, injector.resolve(args), injector.resolve(kwargs))
29
35
 
30
36
  calls.each do |(call, call_args, call_kwargs)|
31
- do_call(object, call, injector.resolve(call_args), injector.resolve(call_kwargs))
37
+ RubyCompat.do_call(object, call, injector.resolve(call_args), injector.resolve(call_kwargs))
32
38
  end
33
39
 
34
40
  object
35
41
  end
36
-
37
- # @return [Boolean]
38
- def anonymous?
39
- @anonymous
40
- end
41
-
42
- private
43
-
44
- if ::Semantic::Version.new(RUBY_VERSION).satisfies?(">= 2.7.0")
45
- def do_call(obj, method, args, kwargs)
46
- obj.send(method, *args, **kwargs)
47
- end
48
- else
49
- def do_call(obj, method, args, kwargs)
50
- if args.empty? && kwargs.empty?
51
- obj.send(method)
52
- elsif args.empty?
53
- obj.send(method, **kwargs)
54
- elsif kwargs.empty?
55
- obj.send(method, *args)
56
- else
57
- obj.send(method, *args, **kwargs)
58
- end
59
- end
60
- end
61
42
  end
62
43
  end
63
44
  end
@@ -3,15 +3,29 @@
3
3
  module Corindon
4
4
  module DependencyInjection
5
5
  class Dsl
6
+ class << self
7
+ # @param [Definition] definition
8
+ # @return [Dsl]
9
+ def from_definition(definition)
10
+ new(
11
+ definition.object_source,
12
+ id: definition.id,
13
+ args: definition.args,
14
+ kwargs: definition.kwargs,
15
+ calls: definition.calls,
16
+ tags: definition.tags
17
+ )
18
+ end
19
+ end
20
+
6
21
  # @param [Class] klass
7
- def initialize(klass, args: [], kwargs: {}, id: nil, anonymous: false)
22
+ def initialize(klass, args: [], kwargs: {}, id: nil, calls: [], tags: [])
8
23
  @klass = klass
9
24
  @args = args
10
25
  @kwargs = kwargs
11
- @calls = []
12
- @tags = []
26
+ @calls = calls
27
+ @tags = tags
13
28
  @id = id
14
- @anonymous = anonymous
15
29
  end
16
30
 
17
31
  # @param [Hash] context
@@ -23,7 +37,7 @@ module Corindon
23
37
 
24
38
  instance_exec(context, &block)
25
39
 
26
- Definition.new(@klass, args: @args, kwargs: @kwargs, calls: @calls, tags: @tags, id: @id, anonymous: @anonymous)
40
+ Definition.new(@klass, args: @args, kwargs: @kwargs, calls: @calls, tags: @tags, id: @id)
27
41
  end
28
42
 
29
43
  def args(*arguments, **kv_arguments)
@@ -42,11 +56,6 @@ module Corindon
42
56
  @id = id
43
57
  end
44
58
 
45
- def anonymous!
46
- @anonymous = true
47
- @id = nil
48
- end
49
-
50
59
  # @param [Class, #to_s] key
51
60
  # @return [Token::ParameterToken]
52
61
  def param(key)
@@ -3,22 +3,36 @@
3
3
  module Corindon
4
4
  module DependencyInjection
5
5
  module Injectable
6
- def definition
7
- Definition.new(self)
8
- end
9
-
10
6
  refine Class do
7
+ def factory(service, method)
8
+ Token::ServiceFactoryToken.new(service, method)
9
+ end
10
+
11
+ def make_parameter(name)
12
+ Token::ParameterToken.new(key: "#{self.name.downcase.gsub(/::/, '.')}.#{name}")
13
+ end
14
+
15
+ def make_definition(name, source, *args, **kwargs, &block)
16
+ do_make_definition("#{self.name.downcase.gsub(/::/, '.')}.#{name}", source, args: args, kwargs: kwargs, &block)
17
+ end
18
+
11
19
  def injectable(*args, **kwargs, &block)
12
- include Injectable
20
+ extend Injectable
13
21
 
14
22
  define_singleton_method :definition do
23
+ do_make_definition(name, self, args: args, kwargs: kwargs, &block)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def do_make_definition(name, source, args:, kwargs:, &block)
15
30
  if block.nil?
16
- Definition.new(self, args: args, kwargs: kwargs)
31
+ Definition.new(source, args: args, kwargs: kwargs, id: name)
17
32
  else
18
- Dsl.new(self).exec(&block)
33
+ Dsl.new(source, args: args, kwargs: kwargs, id: name).exec(&block)
19
34
  end
20
35
  end
21
- end
22
36
  end
23
37
  end
24
38
  end
@@ -19,6 +19,8 @@ module Corindon
19
19
  value.transform_values(&method(:resolve))
20
20
  elsif value.is_a?(Token::InjectionToken)
21
21
  value.resolve(injector: self)
22
+ elsif value.is_a?(Definition)
23
+ value.build(self)
22
24
  else
23
25
  container.get(value)
24
26
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Corindon
4
+ module DependencyInjection
5
+ class RubyCompat
6
+ class << self
7
+ if ::Semantic::Version.new(RUBY_VERSION).satisfies?(">= 2.7.0")
8
+ def do_call(obj, method, args, kwargs)
9
+ obj.send(method, *args, **kwargs)
10
+ end
11
+ else
12
+ def do_call(obj, method, args, kwargs)
13
+ if args.empty? && kwargs.empty?
14
+ obj.send(method)
15
+ elsif args.empty?
16
+ obj.send(method, **kwargs)
17
+ elsif kwargs.empty?
18
+ obj.send(method, *args)
19
+ else
20
+ obj.send(method, *args, **kwargs)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -27,33 +27,13 @@ module Corindon
27
27
 
28
28
  # @param [Injector] injector
29
29
  def resolve(injector:)
30
- do_call(
30
+ RubyCompat.do_call(
31
31
  injector.resolve(service),
32
32
  method,
33
33
  injector.resolve(args),
34
34
  injector.resolve(kwargs)
35
35
  )
36
36
  end
37
-
38
- private
39
-
40
- if ::Semantic::Version.new(RUBY_VERSION).satisfies?(">= 2.7.0")
41
- def do_call(obj, method, args, kwargs)
42
- obj.send(method, *args, **kwargs)
43
- end
44
- else
45
- def do_call(obj, method, args, kwargs)
46
- if args.empty? && kwargs.empty?
47
- obj.send(method)
48
- elsif args.empty?
49
- obj.send(method, **kwargs)
50
- elsif kwargs.empty?
51
- obj.send(method, *args)
52
- else
53
- obj.send(method, *args, **kwargs)
54
- end
55
- end
56
- end
57
37
  end
58
38
  end
59
39
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Corindon
4
+ module DependencyInjection
5
+ module Token
6
+ class ServiceFactoryToken < InjectionToken
7
+ attr_reader :service
8
+ attr_reader :method
9
+
10
+ def initialize(service, method)
11
+ super()
12
+
13
+ @service = service
14
+ @method = method
15
+ end
16
+
17
+ # @param [Injector] injector
18
+ def resolve(injector:)
19
+ [injector.resolve(service), method]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Corindon
4
- module Ext
5
- module Guards
4
+ module Guards
5
+ module Ext
6
6
  refine Object do
7
7
  def unimplemented!(message = nil)
8
- raise Error.new(message || "This method is not implemented.")
8
+ raise NotImplementedError.new(message || "This method is not implemented.")
9
9
  end
10
10
 
11
11
  def unreachable!(message = nil)
12
- raise Error.new(message || "Reached unreachable code.")
12
+ raise StandardError.new(message || "Reached unreachable code.")
13
13
  end
14
14
  end
15
15
  end
@@ -13,6 +13,11 @@ module Corindon
13
13
  @error = error
14
14
  end
15
15
 
16
+ # @raise [Exception]
17
+ def unwrap!
18
+ raise error
19
+ end
20
+
16
21
  # @return [Boolean]
17
22
  def failure?
18
23
  true
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ using Corindon::Guards::Ext
4
+
3
5
  module Corindon
4
6
  module Result
5
7
  class Result
@@ -13,6 +15,12 @@ module Corindon
13
15
  false
14
16
  end
15
17
 
18
+ # @raise [Exception] if called on a Failure
19
+ # @return [Object]
20
+ def unwrap!
21
+ unimplemented!
22
+ end
23
+
16
24
  # @yieldparam [Object] value
17
25
  # @yieldreturn [Result]
18
26
  # @return [Result]
@@ -18,6 +18,11 @@ module Corindon
18
18
  true
19
19
  end
20
20
 
21
+ # @return [Object]
22
+ def unwrap!
23
+ value
24
+ end
25
+
21
26
  def and_then(&block)
22
27
  retval = block.call(value)
23
28
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Corindon
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: corindon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémi Piotaix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-04 00:00:00.000000000 Z
11
+ date: 2020-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: semantic
@@ -95,17 +95,16 @@ files:
95
95
  - lib/corindon/dependency_injection/container.rb
96
96
  - lib/corindon/dependency_injection/definition.rb
97
97
  - lib/corindon/dependency_injection/dsl.rb
98
- - lib/corindon/dependency_injection/id/id_generator.rb
99
- - lib/corindon/dependency_injection/id/uuid_generator.rb
100
98
  - lib/corindon/dependency_injection/injectable.rb
101
99
  - lib/corindon/dependency_injection/injector.rb
100
+ - lib/corindon/dependency_injection/ruby_compat.rb
102
101
  - lib/corindon/dependency_injection/token/injection_token.rb
103
102
  - lib/corindon/dependency_injection/token/parameter_token.rb
104
103
  - lib/corindon/dependency_injection/token/service_call_token.rb
104
+ - lib/corindon/dependency_injection/token/service_factory_token.rb
105
105
  - lib/corindon/dependency_injection/token/tagged_token.rb
106
106
  - lib/corindon/dependency_injection/token/value_token.rb
107
- - lib/corindon/ext/guards.rb
108
- - lib/corindon/ext/guards/error.rb
107
+ - lib/corindon/guards/ext.rb
109
108
  - lib/corindon/result/errors/bad_return_type_error.rb
110
109
  - lib/corindon/result/errors/result_error.rb
111
110
  - lib/corindon/result/ext.rb
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Corindon
4
- module DependencyInjection
5
- module Id
6
- class IdGenerator
7
- # @return [String]
8
- def generate; end
9
- end
10
- end
11
- end
12
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Corindon
4
- module DependencyInjection
5
- module Id
6
- class UuidGenerator < IdGenerator
7
- # @return [String]
8
- def generate
9
- SecureRandom.uuid
10
- end
11
- end
12
- end
13
- end
14
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Corindon
4
- module Ext
5
- module Guards
6
- class Error < StandardError
7
- end
8
- end
9
- end
10
- end