waterdrop 2.3.2 → 2.3.3

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: 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