corindon 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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