plumb 0.0.15 → 0.0.17

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: 104313a59a2f9187f582058b8f0f3c6dce43763079518d68fde511aef6112400
4
- data.tar.gz: 4fc765c09d840145ebf5777cfd4e326f3705db5cfda8ee5324c5f6f4f81e0070
3
+ metadata.gz: 24a6b9a58d29c5aa9e443586d0d529aaf79fcf91a5ee724366d9153174c73fa9
4
+ data.tar.gz: c6200d6bc762aecf985e359c5326c6014003950f998406dabbfaa9c7aca8fc10
5
5
  SHA512:
6
- metadata.gz: 2ca83f0ed1b4fbb2a83e11ff05bded28ed99550de9bfbec2d20d79943d886209c6b4cabeb2055857e24e60748642f0f7b541dcf5dc433107073772b085c5025a
7
- data.tar.gz: 9d7b79dc0509f481730331bd3e65a1b85378d3609279b6c575ec8d77d8e786ccbe33b8dd54b0abfa826df06454793b235c1f8086a581c9a143359899cebb0318
6
+ metadata.gz: d683a2a89fc717f406efcc16b884cafa10dafa148be86ffc1810a377b4f065e1e40e0d21719fe70752e67d5c4eef86843076fa9ffd1513a2d345f666b705577f
7
+ data.tar.gz: 5788b7b83dfb2c342a9c59f1080b30e3db93f9ff7b3c3f6eda0060021275ae648406559bb9bbee96fe204463a3715571e7e042401771e98c9836f5d5306a4087
data/.rubocop.yml CHANGED
@@ -1,5 +1,11 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.2.2
2
+ TargetRubyVersion: 3.4
3
+ inherit_from:
4
+ - ~/.rubocop.yml
5
+ Style/StringLiterals:
6
+ Enabled: true
7
+ Style/Documentation:
8
+ Enabled: false
3
9
  Style/CaseEquality:
4
10
  Enabled: false
5
11
  Style/LambdaCall:
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  **This library is work in progress!**
4
4
 
5
- Composable data validation, coercion and processing in Ruby. Takes over from https://github.com/ismasan/parametric
5
+ Composable data validation, coercion and processing in Ruby. Takes over from [https://github.com/ismasan/parametric](https://github.com/ismasan/parametric)
6
6
 
7
- This library takes ideas from the excellent https://dry-rb.org ecosystem, with some of the features offered by Dry-Types, Dry-Schema, Dry-Struct. However, I'm aiming at a subset of the functionality with a (hopefully) smaller API surface and fewer concepts, focusing on lessons learned after using Parametric in production for many years.
7
+ This library takes ideas from the excellent [https://dry-rb.org](https://dry-rb.org) ecosystem, with some of the features offered by Dry-Types, Dry-Schema, Dry-Struct. However, I'm aiming at a subset of the functionality with a (hopefully) smaller API surface and fewer concepts, focusing on lessons learned after using Parametric in production for many years.
8
8
 
9
9
  If you're after raw performance and versatility I strongly recommend you use the Dry gems.
10
10
 
@@ -135,7 +135,7 @@ joe = User.parse({ name: 'Joe', email: 'joe@email.com', age: 20}) # returns vali
135
135
  Users.parse([joe]) # returns valid array of user hashes
136
136
  ```
137
137
 
138
- More about [Types::Hash](#typeshash) and [Types::Array](#typesarray). There's also [tuples](#typestuple), [hash maps](#hash-maps), [data structs](#typesdata) and [streams](#typesstream), and it's possible to create your own composite types.
138
+ More about [Types::Hash](#typeshash) and [Types::Array](#typesarray). There's also [tuples](#typestuple), [hash maps](#maps), [data structs](#typesdata) and [streams](#typesstream), and it's possible to create your own composite types.
139
139
 
140
140
  ### Type composition
141
141
 
@@ -329,26 +329,26 @@ type.resolve(['a', 'a', 'b']) # Valid
329
329
  type.resolve(['a', 'x', 'b']) # Failure
330
330
  ```
331
331
 
332
- ### `#with`
332
+ ### `#where`
333
333
 
334
- The `#with` helper matches attributes of the object with values, using `#===`.
334
+ The `#where` helper matches attributes of the object with values, using `#===`.
335
335
 
336
336
  ```ruby
337
- LimitedArray = Types::Array[String].with(size: 10)
338
- LimitedString = Types::String.with(size: 10)
339
- LimitedSet = Types::Any[Set].with(size: 10)
337
+ LimitedArray = Types::Array[String].where(size: 10)
338
+ LimitedString = Types::String.where(size: 10)
339
+ LimitedSet = Types::Any[Set].where(size: 10)
340
340
  ```
341
341
 
342
342
  The size is matched via `#===`, so ranges also work.
343
343
 
344
344
  ```ruby
345
- Password = Types::String.with(bytesize: 10..20)
345
+ Password = Types::String.where(bytesize: 10..20)
346
346
  ```
347
347
 
348
348
  The helper accepts multiple attribute/value pairs
349
349
 
350
350
  ```ruby
351
- JoeBloggs = Types::Any[User].with(first_name: 'Joe', last_name: 'Bloggs')
351
+ JoeBloggs = Types::Any[User].where(first_name: 'Joe', last_name: 'Bloggs')
352
352
  ```
353
353
 
354
354
  #### `#transform`
@@ -669,6 +669,40 @@ when Readable
669
669
  end
670
670
  ```
671
671
 
672
+ Or pattern matching
673
+
674
+ ```ruby
675
+ case args
676
+ in [Iterable => list, String => id]
677
+ # etc
678
+ in [Resolvable => r]
679
+ # etc
680
+ end
681
+ ```
682
+
683
+ #### Merging interfaces
684
+
685
+ Use the `+` operator to merge two interfaces into a new one that must support both sets of method names.
686
+
687
+ ```ruby
688
+ Iterable = Types::Interface[:each, :map]
689
+ Countable = Types::Interface[:size]
690
+ # This one expects objects with methods :each, :map and :size
691
+ CountableIterable = Iterable + Countable
692
+ ```
693
+
694
+ #### Intersecting interfaces
695
+
696
+ Use the `&` operator to produce a new interface with the intersection of method names
697
+
698
+ ```ruby
699
+ I1 = Types::Interface[:a, :b, :c]
700
+ I2 = Types::Interface[:b, :c, :d]
701
+ # This one expects methods :b and :c
702
+ I3 = Types::Interface[:b, :c]
703
+ ```
704
+
705
+
672
706
  TODO: make this a bit more advanced. Check for method arity.
673
707
 
674
708
  ### `Types::Hash`
@@ -1039,7 +1073,7 @@ end
1039
1073
 
1040
1074
  ### Types::Data
1041
1075
 
1042
- `Types::Data` provides a superclass to define **inmutable** structs or value objects with typed / coercible attributes.
1076
+ `Types::Data` provides a superclass to define **immutable** structs or value objects with typed / coercible attributes.
1043
1077
 
1044
1078
  #### `[]` Syntax
1045
1079
 
@@ -1816,3 +1850,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/ismasa
1816
1850
  ## License
1817
1851
 
1818
1852
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
1853
+
1854
+ ## Credits
1855
+
1856
+ Created by [Ismael Celis](https://ismaelcelis.com)
data/Rakefile CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
+ require 'docco/tasks'
6
+
5
7
 
6
8
  RSpec::Core::RakeTask.new(:spec)
7
9
 
@@ -54,7 +54,7 @@ module Types
54
54
  image = result.value
55
55
  path = path_for(image.url)
56
56
  File.open(path, 'wb') { |f| f.write(image.io.read) }
57
- result.valid image.with(url: path, io: File.new(path))
57
+ result.valid image.where(url: path, io: File.new(path))
58
58
  end
59
59
 
60
60
  def path_for(url)
@@ -22,7 +22,7 @@ module Types
22
22
  .transform(::Enumerator, &:each)
23
23
 
24
24
  # Turn a string file path into a CSV stream
25
- # ex. csv_enum = StrinToCSV.parse('./files/data.csv') #=> Enumerator
25
+ # ex. csv_enum = StringToCSV.parse('./files/data.csv') #=> Enumerator
26
26
  StringToCSV = OpenFile >> FileToCSV
27
27
  end
28
28
 
@@ -311,16 +311,22 @@ module Plumb
311
311
 
312
312
  # Check attributes of an object against values, using #===
313
313
  # @example
314
- # type = Types::Array.with(size: 1..10)
315
- # type = Types::String.with(bytesize: 1..10)
314
+ # type = Types::Array.where(size: 1..10)
315
+ # type = Types::String.where(bytesize: 1..10)
316
316
  #
317
317
  # @param attrs [Hash]
318
- def with(attrs)
318
+ def where(attrs)
319
319
  attrs.reduce(self) do |t, (name, value)|
320
320
  t >> AttributeValueMatch.new(t, name, value)
321
321
  end
322
322
  end
323
323
 
324
+ # @deprecated User {#where} instead
325
+ def with(...)
326
+ warn 'Composable#with() is deprecated. Use #where() instead. #with is reserved to make copies of Data structs'
327
+ where(...)
328
+ end
329
+
324
330
  # Register a policy for this step.
325
331
  # Mode 1.a: #policy(:name, arg) a single policy with an argument
326
332
  # Mode 1.b: #policy(:name) a single policy without an argument
@@ -28,6 +28,34 @@ module Plumb
28
28
 
29
29
  alias [] of
30
30
 
31
+ # Merge two interfaces into a new one with the method names of both
32
+ # @example
33
+ # i1 = Types::Interface[:foo]
34
+ # i2 = Types::Interface[:bar, :lol]
35
+ # i3 = i1 + i2 # expects objects with methods :foo, :bar, :lol
36
+ #
37
+ # @param other [InterfaceClass]
38
+ # @return [InterfaceClass]
39
+ def +(other)
40
+ raise ArgumentError, "expected another Types::Interface, but got #{other.inspect}" unless other.is_a?(self.class)
41
+
42
+ self.class.new((method_names + other.method_names).uniq)
43
+ end
44
+
45
+ # Produce a new Interface with the intersection of two interfaces
46
+ # @example
47
+ # i1 = Types::Interface[:foo, :bar]
48
+ # i2 = Types::Interface[:bar, :lol]
49
+ # i3 = i1 + i2 # expects objects with methods :bar
50
+ #
51
+ # @param other [InterfaceClass]
52
+ # @return [InterfaceClass]
53
+ def &(other)
54
+ raise ArgumentError, "expected another Types::Interface, but got #{other.inspect}" unless other.is_a?(self.class)
55
+
56
+ self.class.new(method_names & other.method_names)
57
+ end
58
+
31
59
  def call(result)
32
60
  obj = result.value
33
61
  missing_methods = @method_names.reject { |m| obj.respond_to?(m) }
@@ -61,6 +61,13 @@ module Plumb
61
61
  props
62
62
  end
63
63
 
64
+ # Trying to visit the deferred could go into infinite recursion
65
+ # if a type is deferring to itself
66
+ # Not clear what deferred types would mean for JSON Schema anyway.
67
+ on(:deferred) do |node, props|
68
+ props
69
+ end
70
+
64
71
  on(:hash) do |node, props|
65
72
  props.merge(
66
73
  TYPE => 'object',
@@ -41,9 +41,8 @@ module Plumb
41
41
  @type = type
42
42
  @children = [type].freeze
43
43
  @around_blocks = self.class.around_blocks.dup
44
- return unless block_given?
45
44
 
46
- configure(&setup)
45
+ configure(&setup) if block_given?
47
46
  freeze if freeze_after
48
47
  end
49
48
 
data/lib/plumb/schema.rb CHANGED
@@ -178,8 +178,8 @@ module Plumb
178
178
  self
179
179
  end
180
180
 
181
- def with(...)
182
- @_type = @_type.with(...)
181
+ def where(...)
182
+ @_type = @_type.where(...)
183
183
  self
184
184
  end
185
185
 
data/lib/plumb/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plumb
4
- VERSION = '0.0.15'
4
+ VERSION = '0.0.17'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plumb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-10-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bigdecimal
@@ -38,7 +37,7 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
- description: Data validation and transformation library.
40
+ description: Data structures, validation, coercion and processing toolkit for Ruby
42
41
  email:
43
42
  - ismaelct@gmail.com
44
43
  executables: []
@@ -97,11 +96,11 @@ files:
97
96
  - lib/plumb/value_class.rb
98
97
  - lib/plumb/version.rb
99
98
  - lib/plumb/visitor_handlers.rb
100
- homepage: https://github.com/ismasan/plumb
99
+ homepage: https://ismasan.github.io/plumb
101
100
  licenses:
102
101
  - MIT
103
- metadata: {}
104
- post_install_message:
102
+ metadata:
103
+ source_code_uri: https://github.com/ismasan/plumb
105
104
  rdoc_options: []
106
105
  require_paths:
107
106
  - lib
@@ -116,8 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
115
  - !ruby/object:Gem::Version
117
116
  version: '0'
118
117
  requirements: []
119
- rubygems_version: 3.5.21
120
- signing_key:
118
+ rubygems_version: 3.6.9
121
119
  specification_version: 4
122
120
  summary: Data validation and transformation library.
123
121
  test_files: []