mayak 0.0.15 → 0.2.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.
@@ -0,0 +1,273 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Mayak
5
+ module Validations
6
+ class Rule
7
+ extend T::Sig
8
+ extend T::Helpers
9
+ extend T::Generic
10
+
11
+ Value = type_member
12
+ Error = type_member
13
+
14
+ sig {
15
+ params(
16
+ blk: T.proc.params(arg0: Value).returns(::Mayak::ValidationResult[Error])
17
+ ).void
18
+ }
19
+ def initialize(&blk)
20
+ @blk = T.let(@blk, T.proc.params(arg0: Value).returns(::Mayak::ValidationResult[Error]))
21
+ end
22
+
23
+ sig { params(value: Value).returns(::Mayak::ValidationResult[Error]) }
24
+ def check(value)
25
+ @blk.call(value)
26
+ end
27
+
28
+ sig {
29
+ type_parameters(:NewError)
30
+ .params(blk: T.proc.params(arg0: Value).returns(T.type_parameter(:NewError)))
31
+ .returns(Rule[Value, T.type_parameter(:NewError)])
32
+ }
33
+ def error_from_value(&blk)
34
+ Rule[Value, T.type_parameter(:NewError)].new do |checked|
35
+ result = check(checked)
36
+
37
+ case result
38
+ when ::Mayak::ValidationResult::Valid
39
+ ::Mayak::ValidationResult::Valid[T.type_parameter(:NewError)].new
40
+ when ::Mayak::ValidationResult::Invalid
41
+ ::Mayak::ValidationResult::Invalid[T.type_parameter(:NewError)].new(errors: [blk.call(checked)])
42
+ else
43
+ T.absurd(result)
44
+ end
45
+ end
46
+ end
47
+
48
+ sig {
49
+ type_parameters(:NewError)
50
+ .params(new_error: T.type_parameter(:NewError))
51
+ .returns(Rule[Value, T.type_parameter(:NewError)])
52
+ }
53
+ def error(new_error)
54
+ error_from_value { |_| new_error }
55
+ end
56
+
57
+ sig {
58
+ params(another: Rule[Value, Error]).returns(Rule[Value, Error])
59
+ }
60
+ def any(another)
61
+ Rule[Value, Error].new do |checked|
62
+ first_result = check(checked)
63
+ case first_result
64
+ when ::Mayak::ValidationResult::Valid
65
+ another.check(checked)
66
+ when ::Mayak::ValidationResult::Invalid
67
+ first_result
68
+ else
69
+ T.absurd(first_result)
70
+ end
71
+ end
72
+ end
73
+
74
+ alias | any
75
+
76
+ sig {
77
+ params(another: Rule[Value, Error]).returns(Rule[Value, Error])
78
+ }
79
+ def both(another)
80
+ Rule[Value, Error].new do |checked|
81
+ first_result = check(checked)
82
+ case first_result
83
+ when ::Mayak::ValidationResult::Valid
84
+ another.check(checked)
85
+ when ::Mayak::ValidationResult::Invalid
86
+ second_result = another.check(checked)
87
+ case second_result
88
+ when ::Mayak::ValidationResult::Valid
89
+ first_result
90
+ when ::Mayak::ValidationResult::Invalid
91
+ ::Mayak::ValidationResult::Invalid.new(errors: first_result.errors + second_result.errors)
92
+ else
93
+ T.absurd(first_result)
94
+ end
95
+ else
96
+ T.absurd(first_result)
97
+ end
98
+ end
99
+ end
100
+
101
+ alias & both
102
+
103
+ sig { params(key: Symbol).returns(Rule[Value, [Symbol, Error]]) }
104
+ def with_key(key)
105
+ Rule[Value, [Symbol, Error]].new do |checked|
106
+ result = check(checked)
107
+ case result
108
+ when ::Mayak::ValidationResult::Valid
109
+ ::Mayak::ValidationResult::Valid[[Symbol, Error]].new
110
+ when ::Mayak::ValidationResult::Invalid
111
+ ::Mayak::ValidationResult::Invalid[[Symbol, Error]].new(
112
+ errors: result.errors.map { |error| [key, error] }
113
+ )
114
+ else
115
+ T.absurd(result)
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+ sig {
122
+ params(
123
+ value: T.any(Float, Integer)
124
+ ).returns(Rule[T.any(Float, Integer), String])
125
+ }
126
+ def self.greater_than(value)
127
+ Rule[T.any(Float, Integer), String].new do |checked|
128
+ if checked > value
129
+ ::Mayak::ValidationResult::Valid.new
130
+ else
131
+ ::Mayak::ValidationResult::Invalid.new(
132
+ errors: ["Value #{checked} should be greater than the #{value}"]
133
+ )
134
+ end
135
+ end
136
+ end
137
+
138
+ sig {
139
+ params(
140
+ value: T.any(Float, Integer)
141
+ ).returns(Rule[T.any(Float, Integer), String])
142
+ }
143
+ def self.less_than(value)
144
+ Rule[T.any(Float, Integer), String].new do |checked|
145
+ if checked < value
146
+ ::Mayak::ValidationResult::Valid.new
147
+ else
148
+ ::Mayak::ValidationResult::Invalid.new(
149
+ errors: ["Value #{checked} should be less than the #{value}"]
150
+ )
151
+ end
152
+ end
153
+ end
154
+
155
+ sig {
156
+ params(
157
+ value: T.any(Float, Integer)
158
+ ).returns(Rule[T.any(Float, Integer), String])
159
+ }
160
+ def self.equal_to(value)
161
+ Rule[T.any(Float, Integer), String].new do |checked|
162
+ if checked == value
163
+ ::Mayak::ValidationResult::Valid.new
164
+ else
165
+ ::Mayak::ValidationResult::Invalid.new(
166
+ errors: ["Value #{checked} should equal to #{value}"]
167
+ )
168
+ end
169
+ end
170
+ end
171
+
172
+ sig {
173
+ params(
174
+ value: T.any(Float, Integer)
175
+ ).returns(Rule[T.any(Float, Integer), String])
176
+ }
177
+ def self.greater_than_or_equal_to(value)
178
+ (greater_than(value) | equal_to(value)).error_from_value do |checked|
179
+ "Value #{checked} should greater than or equal to #{value}"
180
+ end
181
+ end
182
+
183
+ sig {
184
+ params(
185
+ value: T.any(Float, Integer)
186
+ ).returns(Rule[T.any(Float, Integer), String])
187
+ }
188
+ def self.less_than_or_equal_to(value)
189
+ (less_than(value) | equal_to(value)).error_from_value do |checked|
190
+ "Value #{checked} should less than or equal to #{value}"
191
+ end
192
+ end
193
+
194
+ sig {
195
+ params(
196
+ value: T.any(Float, Integer)
197
+ ).returns(Rule[T.any(Float, Integer), String])
198
+ }
199
+ def self.positive(value)
200
+ greater_than(0)
201
+ end
202
+
203
+ sig {
204
+ params(
205
+ value: T.any(Float, Integer)
206
+ ).returns(Rule[T.any(Float, Integer), String])
207
+ }
208
+ def self.negative(value)
209
+ less_than(0)
210
+ end
211
+
212
+ sig {
213
+ returns(Rule[T.any(String, T::Array[T.anything], T::Hash[T.anything, T.anything], String), String])
214
+ }
215
+ def self.not_empty
216
+ Rule[T.any(String, Array, Hash, String), String].new do |checked|
217
+ if checked.empty?
218
+ ::Mayak::ValidationResult::Invalid.new(
219
+ errors: ["Value #{checked} should not be empty equal"]
220
+ )
221
+ else
222
+ ::Mayak::ValidationResult::Valid.new
223
+ end
224
+ end
225
+ end
226
+
227
+ sig {
228
+ type_parameters(:Value, :Error)
229
+ .params(rule: Rule[T.type_parameter(:Value), T.type_parameter(:Error)])
230
+ .returns(Rule[T.nilable(T.type_parameter(:Value)), T.type_parameter(:Error)])
231
+ }
232
+ def self.not_nil(rule)
233
+ Rule[T.nilable(T.type_parameter(:Value)), T.type_parameter(:Error)].new do |checked|
234
+ case checked
235
+ when NilClass
236
+ ::Mayak::ValidationResult::Invalid.new(errors: ["Should not be nil"])
237
+ else
238
+ rule.check(checked)
239
+ end
240
+ end
241
+ end
242
+
243
+ sig {
244
+ type_parameters(:Value, :Error)
245
+ .params(rule: Rule[T.type_parameter(:Value), [Symbol, T.type_parameter(:Error)]])
246
+ .returns(Rule[T.type_parameter(:Value), T::Hash[Symbol, T.type_parameter(:Error)]])
247
+ }
248
+ def self.with_keys_aggregated(rule)
249
+ Rule[T.type_parameter(:Value), T::Hash[Symbol, T.type_parameter(:Error)]].new do |checked|
250
+ result = rule.check(checked)
251
+ case result
252
+ when ::Mayak::ValidationResult::Valid
253
+ ::Mayak::ValidationResult::Valid[T::Hash[Symbol, T.type_parameter(:Error)]].new
254
+ when ::Mayak::ValidationResult::Invalid
255
+ accumulated = result.errors.reduce({}) do |acc, tuple|
256
+ key, error = tuple
257
+ if acc.key?(key)
258
+ acc[key] << error
259
+ else
260
+ acc[key] = [error]
261
+ end
262
+ end
263
+ ::Mayak::ValidationResult::Invalid[T::Hash[Symbol, T.type_parameter(:Error)]].new(
264
+ accumulated
265
+ )
266
+ else
267
+ T.absurd(result)
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Mayak
5
+ module Validations
6
+ class Contract
7
+ extend T::Sig
8
+ extend T::Generic
9
+
10
+ Value = type_member
11
+ Error = type_member
12
+
13
+ sig { returns(T::Set[Rule[Value, [Symbol, Error]]]) }
14
+ attr_reader :rule_set
15
+
16
+ sig { params(rule_set: T::Set[Rule[Value, [Symbol, Error]]]).void }
17
+ def initialize(rule_set = Set.new)
18
+ @rule_set = T.let(rule_set, T::Set[Rule[Value, [Symbol, Error]]])
19
+ end
20
+
21
+ sig {
22
+ type_parameters(:MappedValue)
23
+ .params(
24
+ rule: Rule[T.type_parameter(:MappedValue), Error],
25
+ key: Symbol,
26
+ blk: T.proc.params(arg0: Value).returns(T.type_parameter(:MappedValue))
27
+ ).returns(Contract[Value, Error])
28
+ }
29
+ def validate(rule, key:, &blk)
30
+ rule = Rule[Value, Error].new do |checked|
31
+ rule.check(blk.call(checked))
32
+ end
33
+ Contract.new(rule_set.add(rule.with_key(key)))
34
+ end
35
+
36
+ sig { params(value: Value).returns(::Mayak::ValidationResult[T::Hash[Symbol, Error]]) }
37
+ def check(value)
38
+ initial = T.let(
39
+ ::Mayak::ValidationResult::Valid[T::Hash[Symbol, Error]].new,
40
+ ::Mayak::ValidationResult[T::Hash[Symbol, Error]]
41
+ )
42
+ rule_set.reduce(initial) do |aggreated_result, rule|
43
+ current_result = Rule.with_keys_aggregated(rule).check(value)
44
+ case aggreated_result
45
+ when ::Mayak::ValidationResult::Valid
46
+ current_result
47
+ when ::Mayak::ValidationResult::Invalid
48
+ case current_result
49
+ when ::Mayak::ValidationResult::Valid
50
+ aggreated_result
51
+ when ::Mayak::ValidationResult::Invalid
52
+ ::Mayak::ValidationResult::Invalid[T::Hash[Symbol, Error]].new(errors: [ ])
53
+ else
54
+ T.absurd(current_result)
55
+ end
56
+ else
57
+ T.absurd(aggreated_result)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+
data/lib/mayak/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # typed: strict
3
3
 
4
4
  module Mayak
5
- VERSION = T.let("0.0.1", String)
5
+ VERSION = T.let("0.1.0", String)
6
6
  end
data/lib/mayak.rb CHANGED
@@ -16,6 +16,7 @@ require_relative 'mayak/weak_ref'
16
16
  require_relative 'mayak/decoder'
17
17
  require_relative 'mayak/encoder'
18
18
  require_relative 'mayak/hash_serializable'
19
+ require_relative 'mayak/lazy'
19
20
 
20
21
  require_relative 'mayak/caching/unbounded_cache'
21
22
  require_relative 'mayak/caching/lru_cache'
@@ -29,7 +30,6 @@ require_relative 'mayak/http/request'
29
30
  require_relative 'mayak/http/response'
30
31
  require_relative 'mayak/http/verb'
31
32
  require_relative 'mayak/http/client'
32
- require_relative 'mayak/http/codec'
33
33
 
34
34
  require_relative 'mayak/monads/maybe'
35
35
  require_relative 'mayak/monads/result'
data/mayak.gemspec CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "mayak"
7
- spec.version = "0.0.15"
7
+ spec.version = "0.2.0"
8
8
  spec.summary = "Set of fully typed utility classes and interfaces integrated with Sorbet."
9
9
  spec.description = spec.summary
10
10
  spec.authors = ["Daniil Bober"]
@@ -18,6 +18,5 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_development_dependency "bundler"
20
20
  spec.add_development_dependency "rspec"
21
- spec.add_development_dependency "parlour"
22
21
  spec.add_development_dependency "tapioca"
23
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mayak
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniil Bober
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-21 00:00:00.000000000 Z
11
+ date: 2025-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: parlour
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: tapioca
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,15 +86,26 @@ executables: []
100
86
  extensions: []
101
87
  extra_rdoc_files: []
102
88
  files:
89
+ - LICENSE
103
90
  - README.md
104
91
  - lib/mayak.rb
105
92
  - lib/mayak/cache.rb
106
93
  - lib/mayak/caching/README.md
107
94
  - lib/mayak/caching/lru_cache.rb
108
95
  - lib/mayak/caching/unbounded_cache.rb
96
+ - lib/mayak/codec.rb
109
97
  - lib/mayak/collections/README.md
110
98
  - lib/mayak/collections/priority_queue.rb
111
99
  - lib/mayak/collections/queue.rb
100
+ - lib/mayak/csv/body.rb
101
+ - lib/mayak/csv/codec.rb
102
+ - lib/mayak/csv/column.rb
103
+ - lib/mayak/csv/decoder.rb
104
+ - lib/mayak/csv/document.rb
105
+ - lib/mayak/csv/encoder.rb
106
+ - lib/mayak/csv/header.rb
107
+ - lib/mayak/csv/parse_error.rb
108
+ - lib/mayak/csv/row.rb
112
109
  - lib/mayak/decoder.rb
113
110
  - lib/mayak/encoder.rb
114
111
  - lib/mayak/failable_function.rb
@@ -116,7 +113,6 @@ files:
116
113
  - lib/mayak/hash_serializable.rb
117
114
  - lib/mayak/http/README.md
118
115
  - lib/mayak/http/client.rb
119
- - lib/mayak/http/codec.rb
120
116
  - lib/mayak/http/decoder.rb
121
117
  - lib/mayak/http/encoder.rb
122
118
  - lib/mayak/http/request.rb
@@ -124,6 +120,8 @@ files:
124
120
  - lib/mayak/http/verb.rb
125
121
  - lib/mayak/json.rb
126
122
  - lib/mayak/json/encoder.rb
123
+ - lib/mayak/lazy.rb
124
+ - lib/mayak/lazy/README.md
127
125
  - lib/mayak/monads/README.md
128
126
  - lib/mayak/monads/maybe.rb
129
127
  - lib/mayak/monads/result.rb
@@ -133,6 +131,8 @@ files:
133
131
  - lib/mayak/predicates/rule.rb
134
132
  - lib/mayak/random.rb
135
133
  - lib/mayak/validation_result.rb
134
+ - lib/mayak/validations/rule.rb
135
+ - lib/mayak/validations/validation.rb
136
136
  - lib/mayak/version.rb
137
137
  - lib/mayak/weak_ref.rb
138
138
  - mayak.gemspec
@@ -1,25 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require_relative 'encoder'
5
- require_relative 'decoder'
6
-
7
- module Mayak
8
- module Http
9
- module Codec
10
- extend T::Sig
11
- extend T::Generic
12
- extend T::Helpers
13
-
14
- abstract!
15
-
16
- include ::Mayak::Http::Encoder
17
- include ::Mayak::Http::Decoder
18
-
19
- ResponseEntity = type_member
20
- ResponseType = type_member {{ fixed: ::Mayak::Http::Response }}
21
- RequestType = type_member {{ fixed: ::Mayak::Http::Request }}
22
- RequestEntity = type_member
23
- end
24
- end
25
- end