waterdrop 2.3.2 → 2.3.3

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: 154b5f8a103fcfaa47c5d410583d1aa2c0b689b52cd284614b06e7f7a9460179
4
- data.tar.gz: c01ae313dbcf2830267438d3dd19f269a0a7bf29cad824af95f4313f6f04368e
3
+ metadata.gz: b1482f0d2955c43c2ab479372c9cbb4a8c039723121c26b2ff75d0e26700d71e
4
+ data.tar.gz: 1bb3e675c0c632d4940b2b661bdb75a74c44358a7e53fa9dc7051fdad62218b0
5
5
  SHA512:
6
- metadata.gz: 33e5ab153d45e265dd6cdb2b3ab9bb63bda7c8c4399097f1c5c130d4c493de635ee7fad957c83b97d6e5fdd6c4c049a0419ca5e0e063f8163478182cde6b92ed
7
- data.tar.gz: 3858e9ac8d2f860f888a5445ec8c59d98d35dce199816058da850bfaaf80308ccd40cff2eb5e872eb3ba111259c4c4d07d0a0219e0a641da0ad0c456d184030a
6
+ metadata.gz: 8921844cc44625916974c63478562b66a7f30a833b6f95e71e8c3448109d673bd3520a8a48bdf0fe7296e5e00b988c15c3dd92cab2e11ee37914f667966a14de
7
+ data.tar.gz: 6c6038c4f9a718d107fd885e66bf29cc3dde09c6f6e0be2ba41651f3494672ddd925e71574f53ec8ec70d4e766024018f73a43a5fadf99402117ac3a0751b0c0
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # WaterDrop changelog
2
2
 
3
+ ## 2.3.3 (2022-07-18)
4
+ - Replace `dry-validation` with home-brew validation layer and drop direct dependency on `dry-validation`.
5
+ - Remove indirect dependency on dry-configurable from DataDog listener (no changes required).
6
+
3
7
  ## 2.3.2 (2022-07-17)
4
8
  - Replace `dry-configurable` with home-brew config and drop direct dependency on `dry-configurable`.
5
9
 
data/Gemfile.lock CHANGED
@@ -1,10 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- waterdrop (2.3.2)
4
+ waterdrop (2.3.3)
5
5
  concurrent-ruby (>= 1.1)
6
6
  dry-monitor (~> 0.5)
7
- dry-validation (~> 1.7)
8
7
  rdkafka (>= 0.10)
9
8
  zeitwerk (~> 2.3)
10
9
 
@@ -23,42 +22,16 @@ GEM
23
22
  dry-configurable (0.15.0)
24
23
  concurrent-ruby (~> 1.0)
25
24
  dry-core (~> 0.6)
26
- dry-container (0.10.0)
27
- concurrent-ruby (~> 1.0)
28
25
  dry-core (0.8.0)
29
26
  concurrent-ruby (~> 1.0)
30
27
  dry-events (0.3.0)
31
28
  concurrent-ruby (~> 1.0)
32
29
  dry-core (~> 0.5, >= 0.5)
33
- dry-inflector (0.3.0)
34
- dry-initializer (3.1.1)
35
- dry-logic (1.2.0)
36
- concurrent-ruby (~> 1.0)
37
- dry-core (~> 0.5, >= 0.5)
38
30
  dry-monitor (0.6.1)
39
31
  dry-configurable (~> 0.13, >= 0.13.0)
40
32
  dry-core (~> 0.5, >= 0.5)
41
33
  dry-events (~> 0.2)
42
34
  zeitwerk (~> 2.5)
43
- dry-schema (1.9.3)
44
- concurrent-ruby (~> 1.0)
45
- dry-configurable (~> 0.13, >= 0.13.0)
46
- dry-core (~> 0.5, >= 0.5)
47
- dry-initializer (~> 3.0)
48
- dry-logic (~> 1.0)
49
- dry-types (~> 1.5)
50
- dry-types (1.5.1)
51
- concurrent-ruby (~> 1.0)
52
- dry-container (~> 0.3)
53
- dry-core (~> 0.5, >= 0.5)
54
- dry-inflector (~> 0.1, >= 0.1.2)
55
- dry-logic (~> 1.0, >= 1.0.2)
56
- dry-validation (1.8.1)
57
- concurrent-ruby (~> 1.0)
58
- dry-container (~> 0.7, >= 0.7.1)
59
- dry-core (~> 0.5, >= 0.5)
60
- dry-initializer (~> 3.0)
61
- dry-schema (~> 1.8, >= 1.8.0)
62
35
  factory_bot (6.2.1)
63
36
  activesupport (>= 5.0.0)
64
37
  ffi (1.15.5)
data/config/errors.yml CHANGED
@@ -1,7 +1,30 @@
1
1
  en:
2
- dry_validation:
3
- errors:
4
- invalid_key_type: all keys need to be of type String
5
- invalid_value_type: all values need to be of type String
6
- max_payload_size: is more than `max_payload_size` config value
2
+ validations:
3
+ config:
4
+ missing: must be present
5
+ logger_format: must be present
6
+ deliver_format: must be boolean
7
+ id_format: must be a non-empty string
8
+ max_payload_size_format: must be an integer that is equal or bigger than 1
9
+ wait_timeout_format: must be a numeric that is bigger than 0
10
+ max_wait_timeout_format: must be an integer that is equal or bigger than 0
11
+ kafka_format: must be a hash with symbol based keys
7
12
  kafka_key_must_be_a_symbol: All keys under the kafka settings scope need to be symbols
13
+
14
+ message:
15
+ missing: must be present
16
+ partition_format: must be an integer greater or equal to -1
17
+ topic_format: 'does not match the topic allowed format'
18
+ partition_key_format: must be a non-empty string
19
+ timestamp_format: must be either time or integer
20
+ payload_format: must be string
21
+ headers_format: must be a hash
22
+ key_format: must be a non-empty string
23
+ payload_max_size: is more than `max_payload_size` config value
24
+ headers_invalid_key_type: all headers keys need to be of type String
25
+ headers_invalid_value_type: all headers values need to be of type String
26
+
27
+ test:
28
+ missing: must be present
29
+ nested.id_format: 'is invalid'
30
+ nested.id2_format: 'is invalid'
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ module Contractable
5
+ # Base contract for all the contracts that check data format
6
+ #
7
+ # @note This contract does NOT support rules inheritance as it was never needed in Karafka
8
+ class Contract
9
+ extend Configurable
10
+
11
+ # Yaml based error messages data
12
+ setting(:error_messages)
13
+
14
+ # Class level API definitions
15
+ class << self
16
+ # @return [Array<Rule>] all the validation rules defined for a given contract
17
+ attr_reader :rules
18
+
19
+ # Allows for definition of a scope/namespace for nested validations
20
+ #
21
+ # @param path [Symbol] path in the hash for nesting
22
+ # @param block [Proc] nested rule code or more nestings inside
23
+ #
24
+ # @example
25
+ # nested(:key) do
26
+ # required(:inside) { |inside| inside.is_a?(String) }
27
+ # end
28
+ def nested(path, &block)
29
+ init_accu
30
+ @nested << path
31
+ instance_eval(&block)
32
+ @nested.pop
33
+ end
34
+
35
+ # Defines a rule for a required field (required means, that will automatically create an
36
+ # error if missing)
37
+ #
38
+ # @param keys [Array<Symbol>] single or full path
39
+ # @param block [Proc] validation rule
40
+ def required(*keys, &block)
41
+ init_accu
42
+ @rules << Rule.new(@nested + keys, :required, block).freeze
43
+ end
44
+
45
+ # @param keys [Array<Symbol>] single or full path
46
+ # @param block [Proc] validation rule
47
+ def optional(*keys, &block)
48
+ init_accu
49
+ @rules << Rule.new(@nested + keys, :optional, block).freeze
50
+ end
51
+
52
+ # @param block [Proc] validation rule
53
+ #
54
+ # @note Virtual rules have different result expectations. Please see contracts or specs for
55
+ # details.
56
+ def virtual(&block)
57
+ init_accu
58
+ @rules << Rule.new([], :virtual, block).freeze
59
+ end
60
+
61
+ private
62
+
63
+ # Initializes nestings and rules building accumulator
64
+ def init_accu
65
+ @nested ||= []
66
+ @rules ||= []
67
+ end
68
+ end
69
+
70
+ # Runs the validation
71
+ #
72
+ # @param data [Hash] hash with data we want to validate
73
+ # @return [Result] validaton result
74
+ def call(data)
75
+ errors = []
76
+
77
+ self.class.rules.map do |rule|
78
+ case rule.type
79
+ when :required
80
+ validate_required(data, rule, errors)
81
+ when :optional
82
+ validate_optional(data, rule, errors)
83
+ when :virtual
84
+ validate_virtual(data, rule, errors)
85
+ end
86
+ end
87
+
88
+ Result.new(errors, self)
89
+ end
90
+
91
+ # @param data [Hash] data for validation
92
+ # @param error_class [Class] error class that should be used when validation fails
93
+ # @return [Boolean] true
94
+ # @raise [StandardError] any error provided in the error_class that inherits from the
95
+ # standard error
96
+ def validate!(data, error_class)
97
+ result = call(data)
98
+
99
+ return true if result.success?
100
+
101
+ raise error_class, result.errors
102
+ end
103
+
104
+ private
105
+
106
+ # Runs validation for rules on fields that are required and adds errors (if any) to the
107
+ # errors array
108
+ #
109
+ # @param data [Hash] input hash
110
+ # @param rule [Rule] validation rule
111
+ # @param errors [Array] array with errors from previous rules (if any)
112
+ def validate_required(data, rule, errors)
113
+ for_checking = dig(data, rule.path)
114
+
115
+ if for_checking.first == :match
116
+ result = rule.validator.call(for_checking.last, data, errors, self)
117
+
118
+ return if result == true
119
+
120
+ errors << [rule.path, result || :format]
121
+ else
122
+ errors << [rule.path, :missing]
123
+ end
124
+ end
125
+
126
+ # Runs validation for rules on fields that are optional and adds errors (if any) to the
127
+ # errors array
128
+ #
129
+ # @param data [Hash] input hash
130
+ # @param rule [Rule] validation rule
131
+ # @param errors [Array] array with errors from previous rules (if any)
132
+ def validate_optional(data, rule, errors)
133
+ for_checking = dig(data, rule.path)
134
+
135
+ return unless for_checking.first == :match
136
+
137
+ result = rule.validator.call(for_checking.last, data, errors, self)
138
+
139
+ return if result == true
140
+
141
+ errors << [rule.path, result || :format]
142
+ end
143
+
144
+ # Runs validation for rules on virtual fields (aggregates, etc) and adds errors (if any) to
145
+ # the errors array
146
+ #
147
+ # @param data [Hash] input hash
148
+ # @param rule [Rule] validation rule
149
+ # @param errors [Array] array with errors from previous rules (if any)
150
+ def validate_virtual(data, rule, errors)
151
+ result = rule.validator.call(data, errors, self)
152
+
153
+ return if result == true
154
+
155
+ errors.push(*result)
156
+ end
157
+
158
+ # Tries to dig for a given key in a hash and returns it with indication whether or not it was
159
+ # possible to find it (dig returns nil and we don't know if it wasn't the digged key value)
160
+ #
161
+ # @param data [Hash]
162
+ # @param keys [Array<Symbol>]
163
+ # @return [Array<Symbol, Object>] array where the first element is `:match` or `:miss` and
164
+ # the digged value or nil if not found
165
+ def dig(data, keys)
166
+ current = data
167
+ result = :match
168
+
169
+ keys.each do |nesting|
170
+ unless current.key?(nesting)
171
+ result = :miss
172
+
173
+ break
174
+ end
175
+
176
+ current = current[nesting]
177
+ end
178
+
179
+ [result, current]
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ module Contractable
5
+ # Representation of a validaton result with resolved error messages
6
+ class Result
7
+ attr_reader :errors
8
+
9
+ # Builds a result object and remaps (if needed) error keys to proper error messages
10
+ #
11
+ # @param errors [Array<Array>] array with sub-arrays with paths and error keys
12
+ # @param contract [Object] contract that generated the error
13
+ def initialize(errors, contract)
14
+ # Short track to skip object allocation for the happy path
15
+ if errors.empty?
16
+ @errors = errors
17
+ return
18
+ end
19
+
20
+ hashed = {}
21
+
22
+ errors.each do |error|
23
+ scope = error.first.map(&:to_s).join('.').to_sym
24
+
25
+ # This will allow for usage of custom messages instead of yaml keys if needed
26
+ hashed[scope] = if error.last.is_a?(String)
27
+ error.last
28
+ else
29
+ build_message(contract, scope, error.last)
30
+ end
31
+ end
32
+
33
+ @errors = hashed
34
+ end
35
+
36
+ # @return [Boolean] true if no errors
37
+ def success?
38
+ errors.empty?
39
+ end
40
+
41
+ private
42
+
43
+ # Builds message based on the error messages
44
+ # @param contract [Object] contract for which we build the result
45
+ # @param scope [Symbol] path to the key that has an error
46
+ # @param error_key [Symbol] error key for yaml errors lookup
47
+ # @return [String] error message
48
+ def build_message(contract, scope, error_key)
49
+ messages = contract.class.config.error_messages
50
+
51
+ messages.fetch(error_key.to_s) do
52
+ messages.fetch("#{scope}_#{error_key}")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ module Contractable
5
+ # Representation of a single validation rule
6
+ Rule = Struct.new(:path, :type, :validator)
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ # Contract layer for WaterDrop and Karafka
5
+ # It aims to be "dry-validation" like but smaller and easier to handle + without dependencies
6
+ #
7
+ # It allows for nested validations, etc
8
+ #
9
+ # @note It is thread-safe to run but validations definitions should happen before threads are
10
+ # used.
11
+ module Contractable
12
+ end
13
+ end
@@ -3,27 +3,37 @@
3
3
  module WaterDrop
4
4
  module Contracts
5
5
  # Contract with validation rules for WaterDrop configuration details
6
- class Config < Base
7
- params do
8
- required(:id).filled(:str?)
9
- required(:logger).filled
10
- required(:deliver).filled(:bool?)
11
- required(:max_payload_size).filled(:int?, gteq?: 1)
12
- required(:max_wait_timeout).filled(:number?, gteq?: 0)
13
- required(:wait_timeout).filled(:number?, gt?: 0)
14
- required(:kafka).filled(:hash?)
6
+ class Config < Contractable::Contract
7
+ configure do |config|
8
+ config.error_messages = YAML.safe_load(
9
+ File.read(
10
+ File.join(WaterDrop.gem_root, 'config', 'errors.yml')
11
+ )
12
+ ).fetch('en').fetch('validations').fetch('config')
15
13
  end
16
14
 
15
+ required(:id) { |id| id.is_a?(String) && !id.empty? }
16
+ required(:logger) { |logger| !logger.nil? }
17
+ required(:deliver) { |deliver| [true, false].include?(deliver) }
18
+ required(:max_payload_size) { |ps| ps.is_a?(Integer) && ps >= 1 }
19
+ required(:max_wait_timeout) { |mwt| mwt.is_a?(Numeric) && mwt >= 0 }
20
+ required(:wait_timeout) { |wt| wt.is_a?(Numeric) && wt.positive? }
21
+ required(:kafka) { |kafka| kafka.is_a?(Hash) && !kafka.empty? }
22
+
17
23
  # rdkafka allows both symbols and strings as keys for config but then casts them to strings
18
24
  # This can be confusing, so we expect all keys to be symbolized
19
- rule(:kafka) do
20
- next unless value.is_a?(Hash)
25
+ virtual do |config, errors|
26
+ next true unless errors.empty?
27
+
28
+ errors = []
21
29
 
22
- value.each_key do |key|
23
- next if key.is_a?(Symbol)
30
+ config
31
+ .fetch(:kafka)
32
+ .keys
33
+ .reject { |key| key.is_a?(Symbol) }
34
+ .each { |key| errors << [[:kafka, key], :kafka_key_must_be_a_symbol] }
24
35
 
25
- key(:"kafka.#{key}").failure(:kafka_key_must_be_a_symbol)
26
- end
36
+ errors
27
37
  end
28
38
  end
29
39
  end
@@ -4,36 +4,56 @@ module WaterDrop
4
4
  module Contracts
5
5
  # Contract with validation rules for validating that all the message options that
6
6
  # we provide to producer ale valid and usable
7
- class Message < Base
7
+ class Message < Contractable::Contract
8
+ configure do |config|
9
+ config.error_messages = YAML.safe_load(
10
+ File.read(
11
+ File.join(WaterDrop.gem_root, 'config', 'errors.yml')
12
+ )
13
+ ).fetch('en').fetch('validations').fetch('message')
14
+ end
15
+
8
16
  # Regex to check that topic has a valid format
9
17
  TOPIC_REGEXP = /\A(\w|-|\.)+\z/
10
18
 
11
- # Checks, that the given value is a string
12
- STRING_ASSERTION = ->(value) { value.is_a?(String) }.to_proc
19
+ private_constant :TOPIC_REGEXP
13
20
 
14
- private_constant :TOPIC_REGEXP, :STRING_ASSERTION
21
+ attr_reader :max_payload_size
15
22
 
16
- option :max_payload_size
17
-
18
- params do
19
- required(:topic).filled(:str?, format?: TOPIC_REGEXP)
20
- required(:payload).filled(:str?)
21
- optional(:key).maybe(:str?, :filled?)
22
- optional(:partition).filled(:int?, gteq?: -1)
23
- optional(:partition_key).maybe(:str?, :filled?)
24
- optional(:timestamp).maybe { time? | int? }
25
- optional(:headers).maybe(:hash?)
23
+ # @param max_payload_size [Integer] max payload size
24
+ def initialize(max_payload_size:)
25
+ super()
26
+ @max_payload_size = max_payload_size
26
27
  end
27
28
 
28
- rule(:headers) do
29
- next unless value.is_a?(Hash)
29
+ required(:topic) { |topic| topic.is_a?(String) && TOPIC_REGEXP.match?(topic) }
30
+ required(:payload) { |payload| payload.is_a?(String) }
31
+ optional(:key) { |key| key.nil? || (key.is_a?(String) && !key.empty?) }
32
+ optional(:partition) { |partition| partition.is_a?(Integer) && partition >= -1 }
33
+ optional(:partition_key) { |p_key| p_key.nil? || (p_key.is_a?(String) && !p_key.empty?) }
34
+ optional(:timestamp) { |ts| ts.nil? || (ts.is_a?(Time) || ts.is_a?(Integer)) }
35
+ optional(:headers) { |headers| headers.nil? || headers.is_a?(Hash) }
36
+
37
+ virtual do |config, errors|
38
+ next true unless errors.empty?
39
+ next true unless config.key?(:headers)
40
+ next true if config[:headers].nil?
30
41
 
31
- key.failure(:invalid_key_type) unless value.keys.all?(&STRING_ASSERTION)
32
- key.failure(:invalid_value_type) unless value.values.all?(&STRING_ASSERTION)
42
+ errors = []
43
+
44
+ config.fetch(:headers).each do |key, value|
45
+ errors << [%i[headers], :invalid_key_type] unless key.is_a?(String)
46
+ errors << [%i[headers], :invalid_value_type] unless value.is_a?(String)
47
+ end
48
+
49
+ errors
33
50
  end
34
51
 
35
- rule(:payload) do
36
- key.failure(:max_payload_size) if value.bytesize > max_payload_size
52
+ virtual do |config, errors, validator|
53
+ next true unless errors.empty?
54
+ next true if config[:payload].bytesize <= validator.max_payload_size
55
+
56
+ [[%i[payload], :max_size]]
37
57
  end
38
58
  end
39
59
  end
@@ -11,26 +11,29 @@ module WaterDrop
11
11
  #
12
12
  # @note You need to setup the `dogstatsd-ruby` client and assign it
13
13
  class Listener
14
- include Dry::Configurable
14
+ include WaterDrop::Configurable
15
+ extend Forwardable
16
+
17
+ def_delegators :config, :client, :rd_kafka_metrics, :namespace, :default_tags
15
18
 
16
19
  # Value object for storing a single rdkafka metric publishing details
17
20
  RdKafkaMetric = Struct.new(:type, :scope, :name, :key_location)
18
21
 
19
22
  # Namespace under which the DD metrics should be published
20
- setting :namespace, default: 'waterdrop', reader: true
23
+ setting :namespace, default: 'waterdrop'
21
24
 
22
25
  # Datadog client that we should use to publish the metrics
23
- setting :client, reader: true
26
+ setting :client
24
27
 
25
28
  # Default tags we want to publish (for example hostname)
26
29
  # Format as followed (example for hostname): `["host:#{Socket.gethostname}"]`
27
- setting :default_tags, default: [], reader: true
30
+ setting :default_tags, default: []
28
31
 
29
32
  # All the rdkafka metrics we want to publish
30
33
  #
31
34
  # By default we publish quite a lot so this can be tuned
32
35
  # Note, that the once with `_d` come from WaterDrop, not rdkafka or Kafka
33
- setting :rd_kafka_metrics, reader: true, default: [
36
+ setting :rd_kafka_metrics, default: [
34
37
  # Client metrics
35
38
  RdKafkaMetric.new(:count, :root, 'calls', 'tx_d'),
36
39
  RdKafkaMetric.new(:histogram, :root, 'queue.size', 'msg_cnt_d'),
@@ -47,8 +50,11 @@ module WaterDrop
47
50
  RdKafkaMetric.new(:gauge, :brokers, 'network.latency.p99', %w[rtt p99])
48
51
  ].freeze
49
52
 
53
+ configure
54
+
50
55
  # @param block [Proc] configuration block
51
56
  def initialize(&block)
57
+ configure
52
58
  setup(&block) if block
53
59
  end
54
60
 
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '2.3.2'
6
+ VERSION = '2.3.3'
7
7
  end
data/lib/waterdrop.rb CHANGED
@@ -3,9 +3,11 @@
3
3
  # External components
4
4
  # delegate should be removed because we don't need it, we just add it because of ruby-kafka
5
5
  %w[
6
+ forwardable
6
7
  concurrent/array
8
+ concurrent/hash
9
+ yaml
7
10
  dry/monitor/notifications
8
- dry-validation
9
11
  rdkafka
10
12
  json
11
13
  zeitwerk
data/waterdrop.gemspec CHANGED
@@ -18,7 +18,6 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_dependency 'concurrent-ruby', '>= 1.1'
20
20
  spec.add_dependency 'dry-monitor', '~> 0.5'
21
- spec.add_dependency 'dry-validation', '~> 1.7'
22
21
  spec.add_dependency 'rdkafka', '>= 0.10'
23
22
  spec.add_dependency 'zeitwerk', '~> 2.3'
24
23
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterdrop
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -34,7 +34,7 @@ cert_chain:
34
34
  R2P11bWoCtr70BsccVrN8jEhzwXngMyI2gVt750Y+dbTu1KgRqZKp/ECe7ZzPzXj
35
35
  pIy9vHxTANKYVyI4qj8OrFdEM5BQNu8oQpL0iQ==
36
36
  -----END CERTIFICATE-----
37
- date: 2022-07-17 00:00:00.000000000 Z
37
+ date: 2022-07-18 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: concurrent-ruby
@@ -64,20 +64,6 @@ dependencies:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0.5'
67
- - !ruby/object:Gem::Dependency
68
- name: dry-validation
69
- requirement: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - "~>"
72
- - !ruby/object:Gem::Version
73
- version: '1.7'
74
- type: :runtime
75
- prerelease: false
76
- version_requirements: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - "~>"
79
- - !ruby/object:Gem::Version
80
- version: '1.7'
81
67
  - !ruby/object:Gem::Dependency
82
68
  name: rdkafka
83
69
  requirement: !ruby/object:Gem::Requirement
@@ -133,8 +119,11 @@ files:
133
119
  - lib/waterdrop/configurable.rb
134
120
  - lib/waterdrop/configurable/leaf.rb
135
121
  - lib/waterdrop/configurable/node.rb
122
+ - lib/waterdrop/contractable.rb
123
+ - lib/waterdrop/contractable/contract.rb
124
+ - lib/waterdrop/contractable/result.rb
125
+ - lib/waterdrop/contractable/rule.rb
136
126
  - lib/waterdrop/contracts.rb
137
- - lib/waterdrop/contracts/base.rb
138
127
  - lib/waterdrop/contracts/config.rb
139
128
  - lib/waterdrop/contracts/message.rb
140
129
  - lib/waterdrop/errors.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WaterDrop
4
- module Contracts
5
- # Base for all the contracts in WaterDrop
6
- class Base < Dry::Validation::Contract
7
- config.messages.load_paths << File.join(WaterDrop.gem_root, 'config', 'errors.yml')
8
-
9
- # @param data [Hash] data for validation
10
- # @param error_class [Class] error class that should be used when validation fails
11
- # @return [Boolean] true
12
- # @raise [StandardError] any error provided in the error_class that inherits from the
13
- # standard error
14
- def validate!(data, error_class)
15
- result = call(data)
16
-
17
- return true if result.success?
18
-
19
- raise error_class, result.errors.to_h
20
- end
21
- end
22
- end
23
- end