@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 CHANGED
@@ -5,7 +5,7 @@ title: "ZIO Blocks"
5
5
 
6
6
  **Modular, zero-dependency building blocks for modern Scala applications.**
7
7
 
8
- @PROJECT_BADGES@
8
+ [![Development](https://img.shields.io/badge/Project%20Stage-Development-green.svg)](https://github.com/zio/zio/wiki/Project-Stages) ![CI Badge](https://github.com/zio/zio-blocks/workflows/CI/badge.svg) [![Sonatype Releases](https://img.shields.io/nexus/r/https/oss.sonatype.org/dev.zio/zio-blocks-next-schema_3.svg?label=Sonatype%20Release)](https://oss.sonatype.org/content/repositories/releases/dev/zio/zio-blocks-next-schema_3/) [![Sonatype Snapshots](https://img.shields.io/nexus/s/https/oss.sonatype.org/dev.zio/zio-blocks-next-schema_3.svg?label=Sonatype%20Snapshot)](https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-blocks-next-schema_3/) [![javadoc](https://javadoc.io/badge2/dev.zio/zio-blocks-docs_3/javadoc.svg)](https://javadoc.io/doc/dev.zio/zio-blocks-docs_3) [![ZIO Blocks](https://img.shields.io/github/stars/zio/zio-blocks?style=social)](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" % "@VERSION@"
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" % "@VERSION@"
86
- libraryDependencies += "dev.zio" %% "zio-blocks-schema-toon" % "@VERSION@"
87
- libraryDependencies += "dev.zio" %% "zio-blocks-schema-messagepack" % "@VERSION@"
88
- libraryDependencies += "dev.zio" %% "zio-blocks-schema-thrift" % "@VERSION@"
89
- libraryDependencies += "dev.zio" %% "zio-blocks-schema-bson" % "@VERSION@"
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" % "@VERSION@"
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" % "@VERSION@"
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" % "@VERSION@"
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" % "@VERSION@"
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
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "@zio.dev/zio-blocks",
3
- "version": "0.0.1",
4
3
  "description": "ZIO Blocks Documentation",
5
- "license": "Apache-2.0"
4
+ "license": "Apache-2.0",
5
+ "version": "0.0.22",
6
+ "repository": {
7
+ "url": "https://github.com/zio/zio-blocks"
8
+ }
6
9
  }
@@ -1,6 +1,7 @@
1
- # Path Interpolator
2
-
3
- ## Overview
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 | Description |
219
- |--------|--------|-------------|
220
- | `\n` | newline | Line feed |
221
- | `\t` | tab | Horizontal tab |
222
- | `\r` | return | Carriage return |
223
- | `\'` | `'` | Single quote |
224
- | `\"` | `"` | Double quote |
225
- | `\\` | `\` | Backslash |
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 | toString Output |
622
- |---------------------------|-----------------|
623
- | `DynamicOptic.root.field("name")` | `.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")` | `<Some>` |
626
- | `DynamicOptic.root.at(0)` | `[0]` |
627
- | `DynamicOptic.root.atIndices(0, 2, 5)` | `[0,2,5]` |
628
- | `DynamicOptic.elements` | `[*]` |
629
- | `DynamicOptic.root.atKey("host")` | `{"host"}` |
630
- | `DynamicOptic.root.atKey(80)` | `{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
 
@@ -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 mdoc:compile-only
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 mdoc:compile-only
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`, returning `Right(a)` on success or `Left(SchemaError)` on failure
306
- - `unwrap`: Extracts the underlying `B` from an `A`, returning `Right(b)` on success or `Left(SchemaError)` on failure
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 with validation:
306
+ Here is an example of a `Binding.Wrapper` for an `Email` newtype:
309
307
 
310
- ```scala mdoc:compile-only
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
- case x@EmailRegex(_*) => Right(new Email(x))
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
  ```