@zio.dev/zio-blocks 0.0.1 → 0.0.22
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.
- package/index.md +163 -15
- package/package.json +5 -2
- package/path-interpolator.md +24 -23
- package/reference/binding.md +8 -14
- package/reference/chunk.md +36 -36
- package/reference/codec.md +384 -0
- package/reference/docs.md +2 -2
- package/reference/dynamic-optic.md +392 -0
- package/reference/dynamic-value.md +34 -34
- package/reference/formats.md +84 -28
- package/reference/json-schema.md +33 -30
- package/reference/json.md +47 -47
- package/reference/lazy.md +361 -0
- package/reference/modifier.md +151 -87
- package/reference/optics.md +51 -37
- package/reference/reflect.md +3 -3
- package/reference/registers.md +7 -7
- package/reference/schema.md +18 -18
- package/reference/syntax.md +27 -27
- package/reference/type-class-derivation.md +1959 -0
- package/scope.md +521 -203
- package/sidebars.js +6 -1
- package/reference/reflect-transform.md +0 -387
- package/reference/type-class-derivation-internals.md +0 -632
package/index.md
CHANGED
|
@@ -5,7 +5,7 @@ title: "ZIO Blocks"
|
|
|
5
5
|
|
|
6
6
|
**Modular, zero-dependency building blocks for modern Scala applications.**
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
[](https://github.com/zio/zio/wiki/Project-Stages)  [](https://oss.sonatype.org/content/repositories/releases/dev/zio/zio-blocks-next-schema_3/) [](https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-blocks-next-schema_3/) [](https://javadoc.io/doc/dev.zio/zio-blocks-docs_3) [](https://github.com/zio/zio-blocks)
|
|
9
9
|
|
|
10
10
|
## What Is ZIO Blocks?
|
|
11
11
|
|
|
@@ -19,6 +19,7 @@ The philosophy is simple: **use what you need, nothing more**. Each block is ind
|
|
|
19
19
|
|-------|-------------|--------|
|
|
20
20
|
| **Schema** | Type-safe schemas with automatic codec derivation | ✅ Available |
|
|
21
21
|
| **Chunk** | High-performance immutable indexed sequences | ✅ Available |
|
|
22
|
+
| **Scope** | Compile-time safe resource management and DI | ✅ Available |
|
|
22
23
|
| **Docs** | GitHub Flavored Markdown parsing and rendering | ✅ Available |
|
|
23
24
|
| **TypeId** | Compile-time type identity with rich metadata | ✅ Available |
|
|
24
25
|
| **Context** | Type-indexed heterogeneous collections | ✅ Available |
|
|
@@ -79,14 +80,14 @@ val thriftCodec = Schema[Person].derive(ThriftFormat) // Thrift
|
|
|
79
80
|
### Installation
|
|
80
81
|
|
|
81
82
|
```scala
|
|
82
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "
|
|
83
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.22"
|
|
83
84
|
|
|
84
85
|
// Optional format modules:
|
|
85
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema-avro" % "
|
|
86
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema-toon" % "
|
|
87
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema-messagepack" % "
|
|
88
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema-thrift" % "
|
|
89
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema-bson" % "
|
|
86
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-avro" % "0.0.22"
|
|
87
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-toon" % "0.0.22"
|
|
88
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-messagepack" % "0.0.22"
|
|
89
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-thrift" % "0.0.22"
|
|
90
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-bson" % "0.0.22"
|
|
90
91
|
```
|
|
91
92
|
|
|
92
93
|
### Example: Optics
|
|
@@ -141,7 +142,7 @@ Chunk is designed for:
|
|
|
141
142
|
### Installation
|
|
142
143
|
|
|
143
144
|
```scala
|
|
144
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-chunk" % "
|
|
145
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-chunk" % "0.0.22"
|
|
145
146
|
```
|
|
146
147
|
|
|
147
148
|
### Example
|
|
@@ -170,6 +171,151 @@ val head: Int = nonEmpty.head // Always safe, no Option needed
|
|
|
170
171
|
|
|
171
172
|
---
|
|
172
173
|
|
|
174
|
+
## Scope
|
|
175
|
+
|
|
176
|
+
Compile-time verified resource safety for synchronous Scala code. Scope prevents resource leaks at compile time by tagging values with an unnameable type-level identity—values allocated in a scope can only be used within that scope. Child scope values cannot escape to parent scopes, enforced by both the abstract scope-tagged type and the `Unscoped` constraint on `scoped`.
|
|
177
|
+
|
|
178
|
+
### The Problem
|
|
179
|
+
|
|
180
|
+
Resource management in Scala is error-prone:
|
|
181
|
+
|
|
182
|
+
```scala
|
|
183
|
+
// Classic try/finally - verbose and easy to get wrong
|
|
184
|
+
val db = openDatabase()
|
|
185
|
+
try {
|
|
186
|
+
val tx = db.beginTransaction()
|
|
187
|
+
try {
|
|
188
|
+
doWork(tx)
|
|
189
|
+
tx.commit()
|
|
190
|
+
} finally tx.close() // What if commit() throws?
|
|
191
|
+
} finally db.close()
|
|
192
|
+
|
|
193
|
+
// Using - better, but doesn't prevent returning resources
|
|
194
|
+
Using(openDatabase()) { db =>
|
|
195
|
+
db // Oops! Returned the resource - use after close!
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### The Solution
|
|
200
|
+
|
|
201
|
+
Scope makes resource leaks a **compile error**, not a runtime bug:
|
|
202
|
+
|
|
203
|
+
```scala
|
|
204
|
+
import zio.blocks.scope._
|
|
205
|
+
|
|
206
|
+
Scope.global.scoped { scope =>
|
|
207
|
+
import scope._
|
|
208
|
+
|
|
209
|
+
val db: $[Database] = allocate(Resource(openDatabase()))
|
|
210
|
+
|
|
211
|
+
// Methods are hidden - can't call db.query() directly
|
|
212
|
+
// Must use scope.use to access:
|
|
213
|
+
val result = scope.use(db)(_.query("SELECT 1"))
|
|
214
|
+
|
|
215
|
+
// Trying to return `db` would be a compile error!
|
|
216
|
+
result // Only pure data escapes
|
|
217
|
+
}
|
|
218
|
+
// db.close() called automatically
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Key Features
|
|
222
|
+
|
|
223
|
+
- **Compile-Time Leak Prevention**: Values of type `scope.$[A]` are opaque and unique to each scope instance. Returning a scoped value from its scope is a type error.
|
|
224
|
+
- **Zero Runtime Overhead**: `$[A]` erases to `A` at runtime—zero allocation overhead.
|
|
225
|
+
- **Structured Scopes**: Child scopes nest within parents; resources clean up LIFO when scopes exit.
|
|
226
|
+
- **Built-in Dependency Injection**: Wire up your application with `Resource.from[T](wires*)` for automatic constructor-based DI.
|
|
227
|
+
- **AutoCloseable Integration**: Resources implementing `AutoCloseable` have `close()` registered automatically.
|
|
228
|
+
- **Unscoped Constraint**: The `scoped` method requires `Unscoped[A]` evidence on the return type, ensuring only pure data (not resources or closures) can escape.
|
|
229
|
+
|
|
230
|
+
### Installation
|
|
231
|
+
|
|
232
|
+
```scala
|
|
233
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-scope" % "0.0.22"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Example: Basic Resource Management
|
|
237
|
+
|
|
238
|
+
```scala
|
|
239
|
+
import zio.blocks.scope._
|
|
240
|
+
|
|
241
|
+
final class Database extends AutoCloseable {
|
|
242
|
+
def query(sql: String): String = s"Result: $sql"
|
|
243
|
+
def close(): Unit = println("Database closed")
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
Scope.global.scoped { scope =>
|
|
247
|
+
import scope._
|
|
248
|
+
|
|
249
|
+
// Allocate returns scope.$[Database] (scoped value)
|
|
250
|
+
val db: $[Database] = allocate(Resource(new Database))
|
|
251
|
+
|
|
252
|
+
// Access via scope.use - result (String) escapes, db does not
|
|
253
|
+
val result = scope.use(db)(_.query("SELECT * FROM users"))
|
|
254
|
+
|
|
255
|
+
println(result)
|
|
256
|
+
}
|
|
257
|
+
// Output: Result: SELECT * FROM users
|
|
258
|
+
// Database closed
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Example: Dependency Injection
|
|
262
|
+
|
|
263
|
+
```scala
|
|
264
|
+
import zio.blocks.scope._
|
|
265
|
+
|
|
266
|
+
case class Config(dbUrl: String)
|
|
267
|
+
class Database(config: Config) extends AutoCloseable { ... }
|
|
268
|
+
class UserRepo(db: Database) { ... }
|
|
269
|
+
class UserService(repo: UserRepo) extends AutoCloseable { ... }
|
|
270
|
+
|
|
271
|
+
// Resource.from auto-wires the dependency graph
|
|
272
|
+
// Only provide leaf values - concrete classes are auto-wired
|
|
273
|
+
val serviceResource: Resource[UserService] = Resource.from[UserService](
|
|
274
|
+
Wire(Config("jdbc:postgresql://localhost/mydb"))
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
Scope.global.scoped { scope =>
|
|
278
|
+
import scope._
|
|
279
|
+
|
|
280
|
+
val service = allocate(serviceResource)
|
|
281
|
+
|
|
282
|
+
scope.use(service)(_.createUser("Alice"))
|
|
283
|
+
}
|
|
284
|
+
// Cleanup runs LIFO: UserService → Database (UserRepo has no cleanup)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Example: Nested Scopes with Transactions
|
|
288
|
+
|
|
289
|
+
```scala
|
|
290
|
+
Scope.global.scoped { connScope =>
|
|
291
|
+
import connScope._
|
|
292
|
+
|
|
293
|
+
val conn = allocate(Resource.fromAutoCloseable(new Connection))
|
|
294
|
+
|
|
295
|
+
// Transaction lives in child scope - cleaned up before connection
|
|
296
|
+
val result: String = scoped { txScope =>
|
|
297
|
+
import txScope._
|
|
298
|
+
|
|
299
|
+
// For-comprehension: flatMap unwraps $[Connection] to Connection,
|
|
300
|
+
// so c.beginTransaction() returns a raw Resource[Transaction]
|
|
301
|
+
for {
|
|
302
|
+
c <- lower(conn)
|
|
303
|
+
tx <- allocate(c.beginTransaction())
|
|
304
|
+
} yield {
|
|
305
|
+
tx.execute("INSERT INTO users VALUES (1, 'Alice')")
|
|
306
|
+
tx.commit()
|
|
307
|
+
"success"
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Transaction closed here, connection still open
|
|
311
|
+
|
|
312
|
+
println(result)
|
|
313
|
+
}
|
|
314
|
+
// Connection closed here
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
173
319
|
## Docs
|
|
174
320
|
|
|
175
321
|
A zero-dependency GitHub Flavored Markdown library for parsing, rendering, and programmatic construction of Markdown documents.
|
|
@@ -194,7 +340,7 @@ Generating documentation, README files, or any Markdown content programmatically
|
|
|
194
340
|
### Installation
|
|
195
341
|
|
|
196
342
|
```scala
|
|
197
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-docs" % "
|
|
343
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-docs" % "0.0.22"
|
|
198
344
|
```
|
|
199
345
|
|
|
200
346
|
### Example
|
|
@@ -278,7 +424,7 @@ Compile-time type identity with rich metadata. TypeId captures comprehensive inf
|
|
|
278
424
|
### Installation
|
|
279
425
|
|
|
280
426
|
```scala
|
|
281
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-typeid" % "
|
|
427
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-typeid" % "0.0.22"
|
|
282
428
|
```
|
|
283
429
|
|
|
284
430
|
### Example
|
|
@@ -321,7 +467,7 @@ A type-indexed heterogeneous collection that stores values by their types with c
|
|
|
321
467
|
### Installation
|
|
322
468
|
|
|
323
469
|
```scala
|
|
324
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-context" % "
|
|
470
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-context" % "0.0.22"
|
|
325
471
|
```
|
|
326
472
|
|
|
327
473
|
### Example
|
|
@@ -385,10 +531,10 @@ Each block has zero dependencies on effect systems. Use the blocks directly, or
|
|
|
385
531
|
|
|
386
532
|
ZIO Blocks supports **Scala 2.13** and **Scala 3.x** with full source compatibility. Write your code once and compile it against either version—migrate to Scala 3 when your team is ready, not when your dependencies force you.
|
|
387
533
|
|
|
388
|
-
| Platform | Schema | Chunk | Docs | TypeId | Context | Streams |
|
|
389
|
-
|
|
390
|
-
| JVM | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
391
|
-
| Scala.js | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
534
|
+
| Platform | Schema | Chunk | Scope | Docs | TypeId | Context | Streams |
|
|
535
|
+
|----------|--------|-------|-------|------|--------|---------|---------|
|
|
536
|
+
| JVM | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
537
|
+
| Scala.js | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
392
538
|
|
|
393
539
|
## Documentation
|
|
394
540
|
|
|
@@ -407,6 +553,7 @@ ZIO Blocks supports **Scala 2.13** and **Scala 3.x** with full source compatibil
|
|
|
407
553
|
|
|
408
554
|
### Serialization
|
|
409
555
|
|
|
556
|
+
- [Codec & Format](./reference/codec.md) - Codec, Format, BinaryCodec & TextCodec
|
|
410
557
|
- [JSON](./reference/json.md) - JSON codec and parsing
|
|
411
558
|
- [JSON Schema](./reference/json-schema.md) - JSON Schema generation and validation
|
|
412
559
|
- [Formats](./reference/formats.md) - Avro, TOON, MessagePack, BSON, Thrift
|
|
@@ -421,6 +568,7 @@ ZIO Blocks supports **Scala 2.13** and **Scala 3.x** with full source compatibil
|
|
|
421
568
|
### Other Blocks
|
|
422
569
|
|
|
423
570
|
- [Chunk](./reference/chunk.md) - High-performance immutable sequences
|
|
571
|
+
- [Scope](./scope.md) - Compile-time safe resource management and DI
|
|
424
572
|
- [TypeId](./reference/typeid.md) - Type identity and metadata
|
|
425
573
|
- [Context](./reference/context.md) - Type-indexed heterogeneous collections
|
|
426
574
|
- [Docs (Markdown)](./reference/docs.md) - Markdown parsing and rendering
|
package/package.json
CHANGED
package/path-interpolator.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
---
|
|
2
|
+
id: path-interpolator
|
|
3
|
+
title: "Path Interpolator"
|
|
4
|
+
---
|
|
4
5
|
|
|
5
6
|
The path interpolator `p"..."` is a compile-time string interpolator for constructing `DynamicOptic` instances in ZIO Blocks. It provides a clean, concise syntax for building optic paths that navigate through complex data structures, with all parsing and validation happening at compile time for zero runtime overhead.
|
|
6
7
|
|
|
@@ -215,14 +216,14 @@ p"<A><B><C>" // Nested variants
|
|
|
215
216
|
|
|
216
217
|
String and character literals support standard escape sequences:
|
|
217
218
|
|
|
218
|
-
| Escape | Result
|
|
219
|
-
|
|
220
|
-
| `\n` | newline | Line feed
|
|
221
|
-
| `\t` | tab
|
|
222
|
-
| `\r` | return
|
|
223
|
-
| `\'` | `'`
|
|
224
|
-
| `\"` | `"`
|
|
225
|
-
| `\\` | `\`
|
|
219
|
+
| Escape | Result | Description |
|
|
220
|
+
|--------|---------|-----------------|
|
|
221
|
+
| `\n` | newline | Line feed |
|
|
222
|
+
| `\t` | tab | Horizontal tab |
|
|
223
|
+
| `\r` | return | Carriage return |
|
|
224
|
+
| `\'` | `'` | Single quote |
|
|
225
|
+
| `\"` | `"` | Double quote |
|
|
226
|
+
| `\\` | `\` | Backslash |
|
|
226
227
|
|
|
227
228
|
**Examples:**
|
|
228
229
|
|
|
@@ -618,19 +619,19 @@ val same = p".users[*].email"
|
|
|
618
619
|
|
|
619
620
|
**Examples:**
|
|
620
621
|
|
|
621
|
-
| DynamicOptic Construction
|
|
622
|
-
|
|
623
|
-
| `DynamicOptic.root.field("name")`
|
|
622
|
+
| DynamicOptic Construction | toString Output |
|
|
623
|
+
|------------------------------------------------------|-------------------|
|
|
624
|
+
| `DynamicOptic.root.field("name")` | `.name` |
|
|
624
625
|
| `DynamicOptic.root.field("address").field("street")` | `.address.street` |
|
|
625
|
-
| `DynamicOptic.root.caseOf("Some")`
|
|
626
|
-
| `DynamicOptic.root.at(0)`
|
|
627
|
-
| `DynamicOptic.root.atIndices(0, 2, 5)`
|
|
628
|
-
| `DynamicOptic.elements`
|
|
629
|
-
| `DynamicOptic.root.atKey("host")`
|
|
630
|
-
| `DynamicOptic.root.atKey(80)`
|
|
631
|
-
| `DynamicOptic.mapValues`
|
|
632
|
-
| `DynamicOptic.mapKeys`
|
|
633
|
-
| `DynamicOptic.wrapped`
|
|
626
|
+
| `DynamicOptic.root.caseOf("Some")` | `<Some>` |
|
|
627
|
+
| `DynamicOptic.root.at(0)` | `[0]` |
|
|
628
|
+
| `DynamicOptic.root.atIndices(0, 2, 5)` | `[0,2,5]` |
|
|
629
|
+
| `DynamicOptic.elements` | `[*]` |
|
|
630
|
+
| `DynamicOptic.root.atKey("host")` | `{"host"}` |
|
|
631
|
+
| `DynamicOptic.root.atKey(80)` | `{80}` |
|
|
632
|
+
| `DynamicOptic.mapValues` | `{*}` |
|
|
633
|
+
| `DynamicOptic.mapKeys` | `{*:}` |
|
|
634
|
+
| `DynamicOptic.wrapped` | `.~` |
|
|
634
635
|
|
|
635
636
|
## Summary
|
|
636
637
|
|
package/reference/binding.md
CHANGED
|
@@ -66,7 +66,7 @@ final case class Record[A](
|
|
|
66
66
|
|
|
67
67
|
Here is an example of a `Binding.Record` for a simple `Person` case class:
|
|
68
68
|
|
|
69
|
-
```scala
|
|
69
|
+
```scala
|
|
70
70
|
import zio.blocks.schema.binding._
|
|
71
71
|
import zio.blocks.schema.binding.RegisterOffset._
|
|
72
72
|
|
|
@@ -115,13 +115,11 @@ final case class Variant[A](
|
|
|
115
115
|
- `Discriminator`: Given a value of a sum type, determine which case it belongs to by returning a numerical index.
|
|
116
116
|
- `Matchers`: Given a value and a case index, safely downcast the value to the specific case type, or return null if it doesn't match.
|
|
117
117
|
|
|
118
|
-
```scala
|
|
118
|
+
```scala
|
|
119
119
|
import zio.blocks.schema.binding._
|
|
120
120
|
|
|
121
121
|
sealed trait Shape extends Product with Serializable
|
|
122
|
-
|
|
123
122
|
case class Circle(radius: Double) extends Shape
|
|
124
|
-
|
|
125
123
|
case class Rectangle(width: Double, height: Double) extends Shape
|
|
126
124
|
|
|
127
125
|
val shapeBinding = Binding.Variant[Shape](
|
|
@@ -302,25 +300,21 @@ final case class Wrapper[A, B](
|
|
|
302
300
|
|
|
303
301
|
**Components:**
|
|
304
302
|
|
|
305
|
-
- `wrap`: Converts from the underlying type `B` to the wrapper type `A
|
|
306
|
-
- `unwrap`: Extracts the underlying `B` from an `A
|
|
303
|
+
- `wrap`: Converts from the underlying type `B` to the wrapper type `A`
|
|
304
|
+
- `unwrap`: Extracts the underlying `B` from an `A`
|
|
307
305
|
|
|
308
|
-
Here is an example of a `Binding.Wrapper` for an `Email` newtype
|
|
306
|
+
Here is an example of a `Binding.Wrapper` for an `Email` newtype:
|
|
309
307
|
|
|
310
|
-
```scala
|
|
308
|
+
```scala
|
|
311
309
|
import zio.blocks.schema._
|
|
312
310
|
import zio.blocks.schema.binding._
|
|
313
311
|
|
|
314
312
|
case class Email(value: String)
|
|
315
313
|
|
|
316
314
|
object Email {
|
|
317
|
-
private val EmailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$".r
|
|
318
315
|
new Binding.Wrapper[Email, String](
|
|
319
|
-
wrap =
|
|
320
|
-
|
|
321
|
-
case _ => Left(SchemaError.validationFailed("Expected valid email format"))
|
|
322
|
-
},
|
|
323
|
-
email => Right(email.value)
|
|
316
|
+
wrap = value => new Email(value),
|
|
317
|
+
unwrap = email => email.value
|
|
324
318
|
)
|
|
325
319
|
}
|
|
326
320
|
```
|