plumb 0.0.15 → 0.0.16
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 +4 -4
- data/.rubocop.yml +7 -1
- data/README.md +15 -11
- data/Rakefile +2 -0
- data/docs/styles.css +540 -0
- data/examples/concurrent_downloads.rb +1 -1
- data/examples/csv_stream.rb +1 -1
- data/lib/plumb/composable.rb +9 -3
- data/lib/plumb/json_schema_visitor.rb +7 -0
- data/lib/plumb/pipeline.rb +1 -2
- data/lib/plumb/schema.rb +2 -2
- data/lib/plumb/version.rb +1 -1
- metadata +8 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 13814b82e58449726341c0a26a398fee38818f852fe09f19ba7754a99b7c54ce
|
|
4
|
+
data.tar.gz: 2205b2bc5f48b19b417afe8403cdbd7afbcac3689307b6ba69237ad094718815
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 604b2d74cf5a78578471d5e6cf523f956025ea95c2e9b17dec7337cca41de10dc2254bc66b69ea2255ee18059b885ef6bb5bd64ea32a34a763cf095168c80022
|
|
7
|
+
data.tar.gz: 50e065d933d9c3a00ff04a0e3e2375997d43039fc8d5c3ba6c7c1a6dc9455bda9d056bfefb11e81b4c75f0a26c01919d7f18c5b0da6aefa33c1f668ddabbaa29
|
data/.rubocop.yml
CHANGED
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](#
|
|
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
|
-
### `#
|
|
332
|
+
### `#where`
|
|
333
333
|
|
|
334
|
-
The `#
|
|
334
|
+
The `#where` helper matches attributes of the object with values, using `#===`.
|
|
335
335
|
|
|
336
336
|
```ruby
|
|
337
|
-
LimitedArray = Types::Array[String].
|
|
338
|
-
LimitedString = Types::String.
|
|
339
|
-
LimitedSet = Types::Any[Set].
|
|
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.
|
|
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].
|
|
351
|
+
JoeBloggs = Types::Any[User].where(first_name: 'Joe', last_name: 'Bloggs')
|
|
352
352
|
```
|
|
353
353
|
|
|
354
354
|
#### `#transform`
|
|
@@ -1039,7 +1039,7 @@ end
|
|
|
1039
1039
|
|
|
1040
1040
|
### Types::Data
|
|
1041
1041
|
|
|
1042
|
-
`Types::Data` provides a superclass to define **
|
|
1042
|
+
`Types::Data` provides a superclass to define **immutable** structs or value objects with typed / coercible attributes.
|
|
1043
1043
|
|
|
1044
1044
|
#### `[]` Syntax
|
|
1045
1045
|
|
|
@@ -1816,3 +1816,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/ismasa
|
|
|
1816
1816
|
## License
|
|
1817
1817
|
|
|
1818
1818
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
1819
|
+
|
|
1820
|
+
## Credits
|
|
1821
|
+
|
|
1822
|
+
Created by [Ismael Celis](https://ismaelcelis.com)
|
data/Rakefile
CHANGED
data/docs/styles.css
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
/* Reset and Base Styles */
|
|
2
|
+
* {
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 0;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
:root {
|
|
9
|
+
--primary-color: #2563eb;
|
|
10
|
+
--primary-dark: #1e40af;
|
|
11
|
+
--secondary-color: #64748b;
|
|
12
|
+
--bg-color: #f8fafc;
|
|
13
|
+
--sidebar-bg: #1e293b;
|
|
14
|
+
--sidebar-text: #cbd5e1;
|
|
15
|
+
--sidebar-hover: #334155;
|
|
16
|
+
--content-bg: #ffffff;
|
|
17
|
+
--text-color: #1e293b;
|
|
18
|
+
--text-light: #64748b;
|
|
19
|
+
--border-color: #e2e8f0;
|
|
20
|
+
--code-bg: #f1f5f9;
|
|
21
|
+
--code-border: #cbd5e1;
|
|
22
|
+
--shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
|
23
|
+
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
html {
|
|
27
|
+
scroll-behavior: smooth;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
body {
|
|
31
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
32
|
+
line-height: 1.6;
|
|
33
|
+
color: var(--text-color);
|
|
34
|
+
background-color: var(--bg-color);
|
|
35
|
+
padding-top: 60px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Top Menu Bar */
|
|
39
|
+
.top-menu {
|
|
40
|
+
position: fixed;
|
|
41
|
+
top: 0;
|
|
42
|
+
left: 0;
|
|
43
|
+
right: 0;
|
|
44
|
+
height: 60px;
|
|
45
|
+
background-color: var(--content-bg);
|
|
46
|
+
border-bottom: 1px solid var(--border-color);
|
|
47
|
+
box-shadow: var(--shadow);
|
|
48
|
+
z-index: 1000;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.top-menu-content {
|
|
52
|
+
max-width: 100%;
|
|
53
|
+
height: 100%;
|
|
54
|
+
padding: 0 2rem;
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: space-between;
|
|
57
|
+
align-items: center;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.top-menu-brand {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: baseline;
|
|
63
|
+
gap: 0.75rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.brand-name {
|
|
67
|
+
font-size: 1.5rem;
|
|
68
|
+
font-weight: 700;
|
|
69
|
+
color: var(--text-color);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.brand-tagline {
|
|
73
|
+
font-size: 0.875rem;
|
|
74
|
+
color: var(--text-light);
|
|
75
|
+
font-weight: 400;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.top-menu .github-link {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 0.5rem;
|
|
82
|
+
padding: 0.5rem 1rem;
|
|
83
|
+
background-color: var(--text-color);
|
|
84
|
+
color: #ffffff;
|
|
85
|
+
border-radius: 6px;
|
|
86
|
+
text-decoration: none;
|
|
87
|
+
font-weight: 600;
|
|
88
|
+
font-size: 0.875rem;
|
|
89
|
+
transition: all 0.2s ease;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.top-menu .github-link:hover {
|
|
93
|
+
background-color: #000000;
|
|
94
|
+
text-decoration: none;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.top-menu .github-link svg {
|
|
98
|
+
width: 20px;
|
|
99
|
+
height: 20px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Layout */
|
|
103
|
+
.container {
|
|
104
|
+
display: flex;
|
|
105
|
+
min-height: calc(100vh - 60px);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Sidebar */
|
|
109
|
+
.sidebar {
|
|
110
|
+
width: 280px;
|
|
111
|
+
background-color: var(--sidebar-bg);
|
|
112
|
+
color: var(--sidebar-text);
|
|
113
|
+
padding: 2rem 0;
|
|
114
|
+
position: fixed;
|
|
115
|
+
top: 60px;
|
|
116
|
+
height: calc(100vh - 60px);
|
|
117
|
+
overflow-y: auto;
|
|
118
|
+
box-shadow: var(--shadow-lg);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.sidebar::-webkit-scrollbar {
|
|
122
|
+
width: 8px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.sidebar::-webkit-scrollbar-track {
|
|
126
|
+
background: var(--sidebar-bg);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.sidebar::-webkit-scrollbar-thumb {
|
|
130
|
+
background: var(--sidebar-hover);
|
|
131
|
+
border-radius: 4px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.logo {
|
|
135
|
+
padding: 0 1.5rem 1.5rem;
|
|
136
|
+
border-bottom: 1px solid var(--sidebar-hover);
|
|
137
|
+
margin-bottom: 1.5rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.logo h2 {
|
|
141
|
+
font-size: 1.75rem;
|
|
142
|
+
color: #ffffff;
|
|
143
|
+
margin-bottom: 0.25rem;
|
|
144
|
+
font-weight: 700;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.logo .tagline {
|
|
148
|
+
font-size: 0.875rem;
|
|
149
|
+
color: var(--sidebar-text);
|
|
150
|
+
font-weight: 400;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.nav-menu {
|
|
154
|
+
list-style: none;
|
|
155
|
+
padding-left: 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.nav-menu li {
|
|
159
|
+
margin: 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.nav-menu a {
|
|
163
|
+
display: block;
|
|
164
|
+
padding: 0.625rem 1.5rem;
|
|
165
|
+
color: var(--sidebar-text);
|
|
166
|
+
text-decoration: none;
|
|
167
|
+
transition: all 0.2s ease;
|
|
168
|
+
font-size: 0.9375rem;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.nav-menu li:not(.nav-submenu) > a {
|
|
172
|
+
font-weight: 600;
|
|
173
|
+
margin-top: 0.5rem;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.nav-submenu a {
|
|
177
|
+
padding-left: 2.5rem;
|
|
178
|
+
font-size: 0.875rem;
|
|
179
|
+
color: var(--sidebar-text);
|
|
180
|
+
opacity: 0.9;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.nav-menu a:hover {
|
|
184
|
+
background-color: var(--sidebar-hover);
|
|
185
|
+
color: #ffffff;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.nav-menu a.active {
|
|
189
|
+
background-color: var(--primary-color);
|
|
190
|
+
color: #ffffff;
|
|
191
|
+
border-left: 3px solid #ffffff;
|
|
192
|
+
padding-left: calc(1.5rem - 3px);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.nav-submenu a.active {
|
|
196
|
+
padding-left: calc(2.5rem - 3px);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Accordion Menus */
|
|
200
|
+
.nav-accordion {
|
|
201
|
+
position: relative;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.accordion-toggle {
|
|
205
|
+
display: flex;
|
|
206
|
+
justify-content: space-between;
|
|
207
|
+
align-items: center;
|
|
208
|
+
cursor: pointer;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.accordion-icon {
|
|
212
|
+
font-size: 0.75rem;
|
|
213
|
+
transition: transform 0.2s ease;
|
|
214
|
+
margin-left: 0.5rem;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.nav-accordion.expanded .accordion-icon {
|
|
218
|
+
transform: rotate(-180deg);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.accordion-content {
|
|
222
|
+
list-style: none;
|
|
223
|
+
padding-left: 0;
|
|
224
|
+
max-height: 0;
|
|
225
|
+
overflow: hidden;
|
|
226
|
+
transition: max-height 0.3s ease;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.nav-accordion.expanded .accordion-content {
|
|
230
|
+
max-height: 500px;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.nav-h4 a {
|
|
234
|
+
padding-left: 3.5rem;
|
|
235
|
+
font-size: 0.8125rem;
|
|
236
|
+
color: var(--sidebar-text);
|
|
237
|
+
opacity: 0.85;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.nav-h4 a.active {
|
|
241
|
+
padding-left: calc(3.5rem - 3px);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* Main Content */
|
|
245
|
+
.content {
|
|
246
|
+
flex: 1;
|
|
247
|
+
margin-left: 280px;
|
|
248
|
+
padding: 3rem;
|
|
249
|
+
max-width: 1200px;
|
|
250
|
+
width: 79vw;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Page Header */
|
|
254
|
+
.page-header {
|
|
255
|
+
margin-bottom: 3rem;
|
|
256
|
+
padding-bottom: 2rem;
|
|
257
|
+
border-bottom: 2px solid var(--border-color);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.page-header h1 {
|
|
261
|
+
font-size: 3rem;
|
|
262
|
+
font-weight: 800;
|
|
263
|
+
color: var(--text-color);
|
|
264
|
+
margin-bottom: 0.5rem;
|
|
265
|
+
letter-spacing: -0.025em;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.page-header .subtitle {
|
|
269
|
+
font-size: 1.25rem;
|
|
270
|
+
color: var(--text-light);
|
|
271
|
+
font-weight: 400;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Sections */
|
|
275
|
+
.section {
|
|
276
|
+
margin-bottom: 4rem;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.section h2 {
|
|
280
|
+
font-size: 2rem;
|
|
281
|
+
font-weight: 700;
|
|
282
|
+
color: var(--text-color);
|
|
283
|
+
margin-bottom: 1.5rem;
|
|
284
|
+
padding-bottom: 0.5rem;
|
|
285
|
+
border-bottom: 2px solid var(--primary-color);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.subsection {
|
|
289
|
+
margin-bottom: 2.5rem;
|
|
290
|
+
background-color: var(--content-bg);
|
|
291
|
+
padding: 2rem;
|
|
292
|
+
border-radius: 8px;
|
|
293
|
+
box-shadow: var(--shadow);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.subsection h3 {
|
|
297
|
+
font-size: 1.5rem;
|
|
298
|
+
font-weight: 600;
|
|
299
|
+
color: var(--text-color);
|
|
300
|
+
margin-bottom: 1rem;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.subsection h4 {
|
|
304
|
+
font-size: 1.25rem;
|
|
305
|
+
font-weight: 600;
|
|
306
|
+
color: var(--text-color);
|
|
307
|
+
margin: 1.5rem 0 1rem;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Typography */
|
|
311
|
+
p {
|
|
312
|
+
margin-bottom: 1rem;
|
|
313
|
+
line-height: 1.75;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
a {
|
|
317
|
+
color: var(--primary-color);
|
|
318
|
+
text-decoration: none;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
a:hover {
|
|
322
|
+
color: var(--primary-dark);
|
|
323
|
+
text-decoration: underline;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
strong {
|
|
327
|
+
font-weight: 600;
|
|
328
|
+
color: var(--text-color);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* Lists */
|
|
332
|
+
ul, ol {
|
|
333
|
+
margin-bottom: 1rem;
|
|
334
|
+
padding-left: 1.5rem;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
li {
|
|
338
|
+
margin-bottom: 0.5rem;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.feature-list {
|
|
342
|
+
list-style: none;
|
|
343
|
+
padding-left: 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.feature-list li {
|
|
347
|
+
padding-left: 1.5rem;
|
|
348
|
+
position: relative;
|
|
349
|
+
margin-bottom: 0.75rem;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.feature-list li::before {
|
|
353
|
+
content: "→";
|
|
354
|
+
position: absolute;
|
|
355
|
+
left: 0;
|
|
356
|
+
color: var(--primary-color);
|
|
357
|
+
font-weight: bold;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/* Code Blocks */
|
|
361
|
+
code {
|
|
362
|
+
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
|
363
|
+
font-size: 0.875em;
|
|
364
|
+
background-color: var(--code-bg);
|
|
365
|
+
padding: 0.2em 0.4em;
|
|
366
|
+
border-radius: 3px;
|
|
367
|
+
border: 1px solid var(--code-border);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
pre {
|
|
371
|
+
margin: 1.5rem 0;
|
|
372
|
+
padding: 0;
|
|
373
|
+
overflow-x: auto;
|
|
374
|
+
border-radius: 6px;
|
|
375
|
+
box-shadow: var(--shadow);
|
|
376
|
+
background-color: #282c34;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
pre code {
|
|
380
|
+
display: block;
|
|
381
|
+
padding: 1.25rem;
|
|
382
|
+
background-color: transparent;
|
|
383
|
+
color: inherit;
|
|
384
|
+
border: none;
|
|
385
|
+
border-radius: 6px;
|
|
386
|
+
line-height: 1.6;
|
|
387
|
+
overflow-x: auto;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
pre code::-webkit-scrollbar {
|
|
391
|
+
height: 8px;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
pre code::-webkit-scrollbar-track {
|
|
395
|
+
background: var(--sidebar-hover);
|
|
396
|
+
border-radius: 4px;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
pre code::-webkit-scrollbar-thumb {
|
|
400
|
+
background: var(--sidebar-text);
|
|
401
|
+
border-radius: 4px;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* Images */
|
|
405
|
+
.image-container {
|
|
406
|
+
margin: 2rem 0;
|
|
407
|
+
text-align: center;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.image-container img {
|
|
411
|
+
max-width: 100%;
|
|
412
|
+
height: auto;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.image-container .caption {
|
|
416
|
+
margin-top: 0.75rem;
|
|
417
|
+
font-size: 0.875rem;
|
|
418
|
+
color: var(--text-light);
|
|
419
|
+
font-style: italic;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@media (max-width: 1248px) {
|
|
423
|
+
.content p img {
|
|
424
|
+
width: 64vw;
|
|
425
|
+
height: auto;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/* Responsive Design */
|
|
430
|
+
@media (max-width: 1024px) {
|
|
431
|
+
.sidebar {
|
|
432
|
+
width: 240px;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.content {
|
|
436
|
+
width: 76vw;
|
|
437
|
+
margin-left: 240px;
|
|
438
|
+
padding: 2rem;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
@media (max-width: 768px) {
|
|
443
|
+
/* Stack sidebar and content vertically on handhelds */
|
|
444
|
+
.container {
|
|
445
|
+
flex-direction: column;
|
|
446
|
+
}
|
|
447
|
+
.top-menu-content {
|
|
448
|
+
padding: 0 1rem;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.brand-tagline {
|
|
452
|
+
display: none;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.top-menu .github-link span {
|
|
456
|
+
display: none;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.top-menu .github-link {
|
|
460
|
+
padding: 0.5rem;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.sidebar {
|
|
464
|
+
display:none;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.content {
|
|
468
|
+
margin-left: 0;
|
|
469
|
+
width: 100vw;
|
|
470
|
+
padding: 1.5rem;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.content p img {
|
|
474
|
+
width: 78vw;
|
|
475
|
+
height: auto;
|
|
476
|
+
}
|
|
477
|
+
.page-header h1 {
|
|
478
|
+
font-size: 2rem;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.page-header .subtitle {
|
|
482
|
+
font-size: 1rem;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.section h2 {
|
|
486
|
+
font-size: 1.5rem;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.subsection {
|
|
490
|
+
padding: 1.5rem;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.subsection h3 {
|
|
494
|
+
font-size: 1.25rem;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
pre code {
|
|
498
|
+
padding: 1rem;
|
|
499
|
+
font-size: 0.8125rem;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/* Smooth Scrolling and Anchor Offset */
|
|
504
|
+
section {
|
|
505
|
+
scroll-margin-top: 5rem;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
article {
|
|
509
|
+
scroll-margin-top: 5rem;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/* Print Styles */
|
|
513
|
+
@media print {
|
|
514
|
+
.top-menu {
|
|
515
|
+
display: none;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
body {
|
|
519
|
+
padding-top: 0;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.sidebar {
|
|
523
|
+
display: none;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.content {
|
|
527
|
+
margin-left: 0;
|
|
528
|
+
max-width: 100%;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.subsection {
|
|
532
|
+
box-shadow: none;
|
|
533
|
+
border: 1px solid var(--border-color);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
pre code {
|
|
537
|
+
background-color: var(--code-bg);
|
|
538
|
+
color: var(--text-color);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
@@ -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.
|
|
57
|
+
result.valid image.where(url: path, io: File.new(path))
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def path_for(url)
|
data/examples/csv_stream.rb
CHANGED
|
@@ -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 =
|
|
25
|
+
# ex. csv_enum = StringToCSV.parse('./files/data.csv') #=> Enumerator
|
|
26
26
|
StringToCSV = OpenFile >> FileToCSV
|
|
27
27
|
end
|
|
28
28
|
|
data/lib/plumb/composable.rb
CHANGED
|
@@ -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.
|
|
315
|
-
# type = Types::String.
|
|
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
|
|
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
|
|
@@ -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',
|
data/lib/plumb/pipeline.rb
CHANGED
data/lib/plumb/schema.rb
CHANGED
data/lib/plumb/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ismael Celis
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
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
|
|
40
|
+
description: Data structures, validation, coercion and processing toolkit for Ruby
|
|
42
41
|
email:
|
|
43
42
|
- ismaelct@gmail.com
|
|
44
43
|
executables: []
|
|
@@ -54,6 +53,7 @@ files:
|
|
|
54
53
|
- bench/compare_parametric_struct.rb
|
|
55
54
|
- bench/parametric_schema.rb
|
|
56
55
|
- bench/plumb_hash.rb
|
|
56
|
+
- docs/styles.css
|
|
57
57
|
- examples/command_objects.rb
|
|
58
58
|
- examples/concurrent_downloads.rb
|
|
59
59
|
- examples/csv_stream.rb
|
|
@@ -97,11 +97,11 @@ files:
|
|
|
97
97
|
- lib/plumb/value_class.rb
|
|
98
98
|
- lib/plumb/version.rb
|
|
99
99
|
- lib/plumb/visitor_handlers.rb
|
|
100
|
-
homepage: https://github.
|
|
100
|
+
homepage: https://ismasan.github.io/plumb
|
|
101
101
|
licenses:
|
|
102
102
|
- MIT
|
|
103
|
-
metadata:
|
|
104
|
-
|
|
103
|
+
metadata:
|
|
104
|
+
source_code_uri: https://github.com/ismasan/plumb
|
|
105
105
|
rdoc_options: []
|
|
106
106
|
require_paths:
|
|
107
107
|
- lib
|
|
@@ -116,8 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
117
|
version: '0'
|
|
118
118
|
requirements: []
|
|
119
|
-
rubygems_version: 3.
|
|
120
|
-
signing_key:
|
|
119
|
+
rubygems_version: 3.6.9
|
|
121
120
|
specification_version: 4
|
|
122
121
|
summary: Data validation and transformation library.
|
|
123
122
|
test_files: []
|