@zio.dev/zio-blocks 0.0.33 → 0.0.55

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.
Files changed (215) hide show
  1. package/adr/2026-07-18-data-migration.md +123 -0
  2. package/guides/async-getting-started.md +687 -0
  3. package/guides/compile-time-resource-safety-with-scope.md +21 -16
  4. package/guides/getting-started-with-mux.md +1395 -0
  5. package/guides/query-dsl-extending.md +161 -102
  6. package/guides/query-dsl-fluent-builder.md +217 -157
  7. package/guides/query-dsl-reified-optics.md +12 -10
  8. package/guides/query-dsl-sql.md +640 -165
  9. package/guides/sql-checked-interpolation.md +173 -0
  10. package/guides/sql-transactions.md +286 -0
  11. package/guides/telemetry-guide.md +1130 -0
  12. package/guides/zio-schema-migration.md +29 -22
  13. package/index.md +248 -389
  14. package/package.json +1 -1
  15. package/plans/config-follow-up-prs.md +188 -0
  16. package/plans/config-pr-assessment-roadmap.md +310 -0
  17. package/reference/MuxDataFlow.jsx +250 -0
  18. package/reference/async.md +1499 -0
  19. package/reference/chunk.md +3533 -308
  20. package/reference/codegen/case-class.md +436 -0
  21. package/reference/codegen/emitter-config.md +383 -0
  22. package/reference/codegen/examples.md +664 -0
  23. package/reference/codegen/field.md +316 -0
  24. package/reference/codegen/index.md +317 -0
  25. package/reference/codegen/scala-emitter.md +392 -0
  26. package/reference/codegen/scala-file.md +276 -0
  27. package/reference/codegen/sealed-trait.md +408 -0
  28. package/reference/codegen/type-definition.md +340 -0
  29. package/reference/codegen/type-ref.md +201 -0
  30. package/reference/combinators.md +347 -117
  31. package/reference/config/config-decoder.md +460 -0
  32. package/reference/config/config-source.md +489 -0
  33. package/reference/config/errors.md +278 -0
  34. package/reference/config/flags.md +369 -0
  35. package/reference/config/formats.md +314 -0
  36. package/reference/config/index.md +304 -0
  37. package/reference/config/rollout.md +336 -0
  38. package/reference/context.md +9 -52
  39. package/reference/data-migration.md +269 -0
  40. package/reference/datastar/attributes.md +302 -0
  41. package/reference/datastar/events.md +234 -0
  42. package/reference/datastar/index.md +256 -0
  43. package/reference/datastar/signals.md +230 -0
  44. package/reference/datastar/sse.md +295 -0
  45. package/reference/datastar.md +346 -0
  46. package/reference/docs.md +1461 -345
  47. package/reference/endpoint/auth-type.md +146 -0
  48. package/reference/endpoint/bulk-creation.md +96 -0
  49. package/reference/endpoint/endpoint.md +297 -0
  50. package/reference/endpoint/http-codec.md +249 -0
  51. package/reference/endpoint/index.md +745 -0
  52. package/reference/endpoint/path-codec.md +225 -0
  53. package/reference/endpoint/route-pattern.md +194 -0
  54. package/reference/endpoint/route-tree.md +111 -0
  55. package/reference/endpoint/segment-codec.md +199 -0
  56. package/reference/html.md +1424 -0
  57. package/reference/htmx/attribute-values.md +359 -0
  58. package/reference/htmx/hx-encoding.md +111 -0
  59. package/reference/htmx/hx-params.md +204 -0
  60. package/reference/htmx/hx-swap.md +276 -0
  61. package/reference/htmx/hx-sync.md +251 -0
  62. package/reference/htmx/hx-target.md +314 -0
  63. package/reference/htmx/hx-trigger.md +457 -0
  64. package/reference/htmx/hx-url-update.md +239 -0
  65. package/reference/htmx/index.md +807 -0
  66. package/reference/htmx/response-headers.md +240 -0
  67. package/reference/http-model/headers.md +735 -0
  68. package/reference/http-model/index.md +49 -0
  69. package/reference/http-model/model.md +1517 -0
  70. package/reference/http-model/schema-codecs.md +522 -0
  71. package/reference/http-model/schema.md +750 -0
  72. package/reference/http-model/server-sent-event.md +341 -0
  73. package/reference/jwt.md +195 -0
  74. package/reference/maybe.md +943 -0
  75. package/reference/media-type.md +2 -2
  76. package/reference/mux.md +254 -0
  77. package/reference/mux.mdx +828 -0
  78. package/reference/openapi.md +1351 -0
  79. package/reference/projection.md +654 -0
  80. package/reference/resource-management/defer-handle.md +1 -1
  81. package/reference/resource-management/resource.md +31 -98
  82. package/reference/resource-management/scope.md +28 -220
  83. package/reference/resource-management/wire.md +5 -55
  84. package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
  85. package/reference/ringbuffer/MpscDiagram.jsx +618 -0
  86. package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
  87. package/reference/ringbuffer/SpscDiagram.jsx +677 -0
  88. package/reference/ringbuffer/advanced.mdx +109 -0
  89. package/reference/ringbuffer/index.mdx +145 -0
  90. package/reference/ringbuffer/mpmc.mdx +185 -0
  91. package/reference/ringbuffer/mpsc.mdx +164 -0
  92. package/reference/ringbuffer/spmc.mdx +108 -0
  93. package/reference/ringbuffer/spsc.mdx +416 -0
  94. package/reference/{allows.md → schema/allows.md} +4 -100
  95. package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
  96. package/reference/{binding.md → schema/binding.md} +3 -4
  97. package/reference/schema/built-in-codecs/avro.md +451 -0
  98. package/reference/schema/built-in-codecs/bson.md +510 -0
  99. package/reference/schema/built-in-codecs/csv.md +564 -0
  100. package/reference/schema/built-in-codecs/index.md +77 -0
  101. package/reference/schema/built-in-codecs/json/index.md +295 -0
  102. package/reference/schema/built-in-codecs/json/json-config.md +217 -0
  103. package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
  104. package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
  105. package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
  106. package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
  107. package/reference/schema/built-in-codecs/messagepack.md +508 -0
  108. package/reference/schema/built-in-codecs/thrift.md +433 -0
  109. package/reference/schema/built-in-codecs/toon.md +1078 -0
  110. package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
  111. package/reference/schema/built-in-codecs/yaml.md +552 -0
  112. package/reference/{codec.md → schema/codec.md} +11 -11
  113. package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +196 -5
  114. package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
  115. package/reference/schema/format.md +92 -0
  116. package/reference/schema/index.md +52 -0
  117. package/reference/schema/migration.md +297 -0
  118. package/reference/{modifier.md → schema/modifier.md} +58 -7
  119. package/reference/{optics.md → schema/optics.md} +2 -2
  120. package/reference/{patch.md → schema/patch.md} +1 -1
  121. package/{path-interpolator.md → reference/schema/path-interpolator.md} +167 -72
  122. package/reference/schema/reflect-transformer.md +140 -0
  123. package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
  124. package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
  125. package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
  126. package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
  127. package/reference/schema/schema-search.md +263 -0
  128. package/reference/{schema.md → schema/schema.md} +22 -2
  129. package/reference/{structural-types.md → schema/structural-types.md} +1 -1
  130. package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
  131. package/reference/smithy.md +1032 -0
  132. package/reference/sql/db-codec-deriver.md +71 -0
  133. package/reference/sql/db-codec.md +687 -0
  134. package/reference/sql/db-con.md +271 -0
  135. package/reference/sql/db-connection.md +153 -0
  136. package/reference/sql/db-param-writer.md +77 -0
  137. package/reference/sql/db-param.md +66 -0
  138. package/reference/sql/db-result-reader.md +148 -0
  139. package/reference/sql/db-tx.md +114 -0
  140. package/reference/sql/db-value.md +41 -0
  141. package/reference/sql/ddl.md +85 -0
  142. package/reference/sql/frag.md +288 -0
  143. package/reference/sql/index.md +341 -0
  144. package/reference/sql/repo.md +600 -0
  145. package/reference/sql/sql-dialect.md +73 -0
  146. package/reference/sql/sql-logger.md +62 -0
  147. package/reference/sql/sql-name-mapper.md +70 -0
  148. package/reference/sql/table-metadata.md +134 -0
  149. package/reference/sql/table.md +448 -0
  150. package/reference/sql/transactor-zio.md +399 -0
  151. package/reference/sql/transactor.md +363 -0
  152. package/reference/sql-zio.md +112 -0
  153. package/reference/streams/core/index.md +32 -0
  154. package/reference/streams/core/pipeline.md +854 -0
  155. package/reference/streams/core/sink.md +1404 -0
  156. package/reference/streams/core/stream.md +3236 -0
  157. package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
  158. package/reference/streams/execution-and-compatibility/index.md +35 -0
  159. package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
  160. package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
  161. package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
  162. package/reference/streams/index.md +726 -0
  163. package/reference/streams/primitives/index.md +30 -0
  164. package/reference/streams/primitives/reader.md +1992 -0
  165. package/reference/streams/primitives/writer.md +1201 -0
  166. package/reference/telemetry/common/any-value.md +90 -0
  167. package/reference/telemetry/common/attribute-key.md +87 -0
  168. package/reference/telemetry/common/attributes.md +118 -0
  169. package/reference/telemetry/common/index.md +39 -0
  170. package/reference/telemetry/common/instrumentation-scope.md +24 -0
  171. package/reference/telemetry/common/resource.md +34 -0
  172. package/reference/telemetry/index.md +311 -0
  173. package/reference/telemetry/logging/index.md +197 -0
  174. package/reference/telemetry/logging/log-enrichment.md +72 -0
  175. package/reference/telemetry/logging/log-formatter.md +100 -0
  176. package/reference/telemetry/logging/log-record-processor.md +56 -0
  177. package/reference/telemetry/logging/log-record.md +44 -0
  178. package/reference/telemetry/logging/log-writer.md +64 -0
  179. package/reference/telemetry/logging/logger-provider.md +142 -0
  180. package/reference/telemetry/logging/logger.md +83 -0
  181. package/reference/telemetry/logging/severity.md +62 -0
  182. package/reference/telemetry/metrics/index.md +150 -0
  183. package/reference/telemetry/metrics/instruments.md +183 -0
  184. package/reference/telemetry/metrics/labeled-instruments.md +74 -0
  185. package/reference/telemetry/metrics/meter-provider.md +76 -0
  186. package/reference/telemetry/metrics/meter.md +98 -0
  187. package/reference/telemetry/metrics/metric-data.md +57 -0
  188. package/reference/telemetry/otel/custom-exporter.md +216 -0
  189. package/reference/telemetry/otel/index.md +212 -0
  190. package/reference/telemetry/tracing/index.md +155 -0
  191. package/reference/telemetry/tracing/sampler.md +89 -0
  192. package/reference/telemetry/tracing/span-builder.md +57 -0
  193. package/reference/telemetry/tracing/span-context.md +39 -0
  194. package/reference/telemetry/tracing/span-data.md +32 -0
  195. package/reference/telemetry/tracing/span-kind.md +55 -0
  196. package/reference/telemetry/tracing/span-processor.md +53 -0
  197. package/reference/telemetry/tracing/span-status.md +47 -0
  198. package/reference/telemetry/tracing/span.md +117 -0
  199. package/reference/telemetry/tracing/tracer-provider.md +91 -0
  200. package/reference/telemetry/tracing/tracer.md +52 -0
  201. package/reference/typeid.md +5 -83
  202. package/sidebars.js +376 -43
  203. package/undocumented-report.md +528 -270
  204. package/reference/formats.md +0 -694
  205. package/reference/http-model.md +0 -1716
  206. package/reference/streams.md +0 -989
  207. package/ringbuffer.md +0 -249
  208. /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
  209. /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
  210. /package/reference/{lazy.md → schema/lazy.md} +0 -0
  211. /package/reference/{reflect.md → schema/reflect.md} +0 -0
  212. /package/reference/{registers.md → schema/registers.md} +0 -0
  213. /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
  214. /package/reference/{syntax.md → schema/syntax.md} +0 -0
  215. /package/reference/{validation.md → schema/validation.md} +0 -0
@@ -26,7 +26,7 @@ val result = data.get(path).one
26
26
  ```
27
27
 
28
28
  :::tip
29
- For a practical example of extracting column names from `DynamicOptic` paths to generate SQL, see the [Query DSL Part 2: SQL Generation](../guides/query-dsl-sql.md) guide.
29
+ For a practical example of extracting column names from `DynamicOptic` paths to generate SQL, see the [Query DSL Part 2: SQL Generation](../../guides/query-dsl-sql.md) guide.
30
30
  :::
31
31
 
32
32
  ## Motivation
@@ -57,7 +57,7 @@ The relationship between typed and dynamic optics:
57
57
  └──────────────────┘ └──────────────────┘
58
58
  ```
59
59
 
60
- The `Optic[S, A]` and `DynamicOptic` types serve complementary roles in ZIO Blocks' optics system. `Optic[S, A]` provides compile-time type safety through macros or manual construction, operates on typed Scala values, and can be converted to a `DynamicOptic` via the `optic.toDynamic` method. In contrast, `DynamicOptic` performs runtime type checking and is constructed through a builder API or [path interpolator](../path-interpolator.md), operating directly on [DynamicValue](./dynamic-value.md), [Schema](./schema.md), and [Reflect](./reflect.md) representations.
60
+ The `Optic[S, A]` and `DynamicOptic` types serve complementary roles in ZIO Blocks' optics system. `Optic[S, A]` provides compile-time type safety through macros or manual construction, operates on typed Scala values, and can be converted to a `DynamicOptic` via the `optic.toDynamic` method. In contrast, `DynamicOptic` performs runtime type checking and is constructed through a builder API or [path interpolator](./path-interpolator.md), operating directly on [DynamicValue](./dynamic-value.md), [Schema](./schema.md), and [Reflect](./reflect.md) representations.
61
61
 
62
62
  ## Design & Structure
63
63
 
@@ -157,7 +157,7 @@ Note: `.atKey` and `.atKeys` require an implicit `Schema[K]` to convert the type
157
157
 
158
158
  ### Path Interpolator
159
159
 
160
- The [`p"..."` path interpolator](../path-interpolator.md) provides a concise compile-time syntax for building
160
+ The [`p"..."` path interpolator](./path-interpolator.md) provides a concise compile-time syntax for building
161
161
  `DynamicOptic` values:
162
162
 
163
163
  ```scala
@@ -181,7 +181,7 @@ val success = p".result<Success>.value"
181
181
  val complex = p""".groups[*].members[0].contacts{"email"}"""
182
182
  ```
183
183
 
184
- See [Path Interpolator](../path-interpolator.md) for the full syntax reference.
184
+ See [Path Interpolator](./path-interpolator.md) for the full syntax reference.
185
185
 
186
186
  ### From Typed Optics
187
187
 
@@ -360,7 +360,7 @@ expected Email, but got Push
360
360
 
361
361
  `DynamicOptic` provides two string formats for different contexts:
362
362
 
363
- - **`toString`** — Compact path syntax matching the [`p"..."` interpolator](../path-interpolator.md) format
363
+ - **`toString`** — Compact path syntax matching the [`p"..."` interpolator](./path-interpolator.md) format
364
364
  - **`toScalaString`** — Scala method call syntax used in error messages
365
365
 
366
366
  | Node | `toString` | `toScalaString` |
@@ -396,6 +396,197 @@ val serialized: DynamicValue = opticSchema.toDynamicValue(path)
396
396
  ```
397
397
 
398
398
 
399
+ ## Search Optics
400
+
401
+ A **Search optic** recursively traverses a data structure to find **all occurrences** matching a type or schema. It produces a `Traversal[S, A]` that collects matches in depth-first, left-to-right order. This section covers the two DSLs for building a search path; for the `SearchTraversal` engine that executes one — `fold`/`modify`/`check`, composing a search with other optics, and the `SchemaMatch` predicate behind `#Pattern` matching — see [Schema Search and Update](./schema-search.md).
402
+
403
+ ### Motivation
404
+
405
+ Search optics address scenarios where you need to:
406
+
407
+ - **Find all values of a specific type** across deeply nested structures (e.g., all `String` fields in a nested record)
408
+ - **Extract all data matching a structural pattern** (e.g., all records with `{ name: string, age: int }` schema)
409
+ - **Transform all matching occurrences** in untyped or partially-typed data
410
+ - **Query data without knowing the exact path** — the search discovers all paths automatically
411
+
412
+ ### Typed API: `.searchFor[T]`
413
+
414
+ Use the `.searchFor[T]` extension method on a `CompanionOptics` to search for all values of type `T`:
415
+
416
+ ```scala
417
+ import zio.blocks.schema._
418
+
419
+ case class Person(name: String, age: Int)
420
+ object Person {
421
+ implicit val schema: Schema[Person] = Schema.derived
422
+ }
423
+
424
+ case class Address(city: String)
425
+ object Address {
426
+ implicit val schema: Schema[Address] = Schema.derived
427
+ }
428
+
429
+ case class Company(name: String, employees: List[Person], hq: Address)
430
+ object Company extends CompanionOptics[Company] {
431
+ implicit val schema: Schema[Company] = Schema.derived
432
+ }
433
+
434
+ // Find all Person instances within a Company
435
+ val personSearch: Traversal[Company, Person] = Company.optic(_.searchFor[Person])
436
+
437
+ val company = Company(
438
+ "Acme",
439
+ List(Person("Alice", 30), Person("Bob", 25)),
440
+ Address("NYC")
441
+ )
442
+
443
+ // Modify all persons (increment their age)
444
+ val updated: Company = personSearch.modify(company, p => p.copy(age = p.age + 1))
445
+ // Company("Acme", List(Person("Alice", 31), Person("Bob", 26)), Address("NYC"))
446
+ ```
447
+
448
+ ### Dynamic API: Path Strings with `#` Prefix
449
+
450
+ Use the `#` prefix in path strings to specify type or schema patterns:
451
+
452
+ ```scala
453
+ import zio.blocks.schema._
454
+
455
+ val data = DynamicValue.Record(
456
+ "company" -> DynamicValue.Record(
457
+ "name" -> DynamicValue.string("Acme"),
458
+ "employees" -> DynamicValue.Sequence(
459
+ DynamicValue.Record("name" -> DynamicValue.string("Alice")),
460
+ DynamicValue.Record("name" -> DynamicValue.string("Bob"))
461
+ )
462
+ )
463
+ )
464
+
465
+ // Find all strings in the data
466
+ val allStrings = data.get(p"#string").toChunk
467
+ // Chunk(
468
+ // DynamicValue.string("Acme"),
469
+ // DynamicValue.string("Alice"),
470
+ // DynamicValue.string("Bob")
471
+ // )
472
+
473
+ // Find all records matching a schema
474
+ val recordsWithName = data.get(p"#record { name: string }").toChunk
475
+
476
+ // Modify all matching values
477
+ val modified = data.modify(p"#string")(dv =>
478
+ dv match {
479
+ case DynamicValue.Primitive(PrimitiveValue.String(s)) =>
480
+ DynamicValue.string(s.toUpperCase)
481
+ case other => other
482
+ }
483
+ )
484
+ ```
485
+
486
+ ### The `SchemaRepr` Pattern Type
487
+
488
+ Every `#Pattern` string above parses into a `SchemaRepr` — a plain, immutable ADT you can also build by hand, independent of the interpolator. `DynamicOptic#searchSchema(schemaRepr)` takes one directly, and `Node.SchemaSearch(schemaRepr)` is the node it produces, exactly the node `#Pattern` syntax builds under the hood:
489
+
490
+ ```scala
491
+ import zio.blocks.schema._
492
+
493
+ val pattern: SchemaRepr = SchemaRepr.Record(
494
+ IndexedSeq("name" -> SchemaRepr.Primitive("string"), "age" -> SchemaRepr.Primitive("int"))
495
+ )
496
+ ```
497
+
498
+ `SchemaRepr#toString` renders the same syntax `#Pattern` strings use, so a pattern built by hand and one parsed from a literal print identically:
499
+
500
+ ```scala
501
+ pattern.toString
502
+ // res13: String = "record { name: string, age: int }"
503
+
504
+ val path: DynamicOptic = DynamicOptic.root.searchSchema(pattern)
505
+ // path: DynamicOptic = DynamicOptic(
506
+ // IndexedSeq(
507
+ // SchemaSearch(
508
+ // Record(Vector(("name", Primitive("string")), ("age", Primitive("int"))))
509
+ // )
510
+ // )
511
+ // )
512
+ path == p"#record { name: string, age: int }"
513
+ // res14: Boolean = true
514
+ ```
515
+
516
+ The eight cases cover every shape the grammar recognizes:
517
+
518
+ | Case | Renders as | Matches |
519
+ |------|------------|---------|
520
+ | `Nominal(name)` | the bare name, e.g. `Person` | a value of that Scala type — only against a `Reflect` tree, see below |
521
+ | `Primitive(name)` | the bare name, e.g. `string` | a primitive of that kind (case-insensitive) |
522
+ | `Record(fields)` | `record { name: string, ... }` | a record with at least those fields, by subset match |
523
+ | `Variant(cases)` | `variant { Case: type, ... }` | a variant whose active case matches one of those entries |
524
+ | `Sequence(element)` | `list(...)` | a sequence whose elements all match — parses from `list(...)`, `set(...)`, or `vector(...)`, all three producing the same case |
525
+ | `Map(key, value)` | `map(key, value)` | a map whose entries all match both patterns |
526
+ | `Optional(inner)` | `option(...)` | `Null`, or a value matching the inner pattern |
527
+ | `Wildcard` | `_` | anything |
528
+
529
+ Parsing a `#Pattern` string is itself layered: the path interpolator recognizes the `#` prefix and hands the substring after it to a small recursive-descent parser, which reports a specific error (unexpected character, an empty `record {}`/`variant {}`, an unterminated expression) at the exact offset where parsing failed — that's what turns a typo like `#record { name: strnig }` into a compile-time interpolator error rather than a pattern that silently matches nothing.
530
+
531
+ ### Supported Patterns
532
+
533
+ Search optics support both **type-based** and **schema-based** patterns:
534
+
535
+ | Pattern | Matches | Example |
536
+ |--------------------------------|----------------------------------------|---------------------------|
537
+ | `#Nominal` (type name) | Values of that type name | `#Person` |
538
+ | `#int`, `#string`, `#boolean` | Specific primitive types (case-insensitive) | `#int`, `#string`, `#boolean` |
539
+ | `#record { ... }` | Records with matching fields | `#record { name: string }` |
540
+ | `#variant { ... }` | Variant cases with matching content | `#variant { Error: string }` |
541
+ | `#list(...)`, `#set(...)`, `#vector(...)` | Sequences with a matching element type, regardless of which of the three keywords appears | `#list(string)` |
542
+ | `#map(...)` | Maps with key and value types | `#map(string, int)` |
543
+ | `#option(...)` | Optional values with inner type | `#option(int)` |
544
+
545
+ ### Traversal Order
546
+
547
+ Results are collected in **depth-first, left-to-right order**:
548
+
549
+ ```scala
550
+ import zio.blocks.schema._
551
+
552
+ val nested = DynamicValue.Record(
553
+ "a" -> DynamicValue.int(1),
554
+ "b" -> DynamicValue.Record(
555
+ "c" -> DynamicValue.int(2),
556
+ "d" -> DynamicValue.int(3)
557
+ ),
558
+ "e" -> DynamicValue.int(4)
559
+ )
560
+
561
+ // Depth-first, left-to-right: 1, 2, 3, 4
562
+ val allInts = nested.get(p"#int").toChunk
563
+ // Chunk(1, 2, 3, 4)
564
+ ```
565
+
566
+ ### Known Limitation: Nominal Matching in Untyped Contexts
567
+
568
+ `Nominal` pattern matching (e.g., `#Person`) returns `false` against a `DynamicValue` or `Json` value because these untyped structures carry no type identity. The one exception is searching a `Schema`/`Reflect` tree itself (as `DynamicSchema#get` does) rather than a value — there, `Nominal` matches by comparing against the tree's own `TypeId`, since a `Reflect` node still carries the type identity a plain `DynamicValue`/`Json` value never does. For searching values, use one of these approaches instead:
569
+
570
+ - **Use the typed API**: `optic(_.searchFor[Person])`
571
+ - **Or use structural patterns**: `p"#record { name: string, age: int }"`
572
+
573
+ Here's how the two approaches differ in practice:
574
+
575
+ ```scala
576
+ import zio.blocks.schema._
577
+
578
+ val dynamicData: DynamicValue = ???
579
+
580
+ // This won't match — no type identity available
581
+ val nominalMatch = dynamicData.get(p"#Person").toChunk
582
+ // Chunk()
583
+
584
+ // This works — structural matching
585
+ val structuralMatch = dynamicData.get(p"#record { name: string, age: int }").toChunk
586
+ // Chunk(...matching records...)
587
+ ```
588
+
399
589
  ## See Also
400
590
 
401
591
  - [DynamicSchema](./dynamic-schema.md) — use `DynamicSchema#get` with a `DynamicOptic` to navigate schema trees and inspect nested type structures.
592
+ - [Optics](./optics.md) — reference page for typed `Optic[S, A]` and reflective optics concepts.
@@ -41,7 +41,7 @@ DynamicSchema ←── reconstructed from storage
41
41
  Schema[OrderPlaced] ←── operational again, can encode and decode
42
42
  ```
43
43
 
44
- This pattern enables schema registries: the Checkout Service registers its event schema on startup; the Fulfillment Service fetches it and rebinds it against its own type definitions, guaranteeing it uses the exact schema that was in effect when the event was encoded. See [BindingResolver](./binding-resolver.md) for the complete rebinding API.
44
+ This pattern enables schema registries: the Checkout Service registers its event schema on startup; the Fulfillment Service fetches it and rebinds it against its own type definitions, guaranteeing it uses the exact schema that was in effect when the event was encoded. See [BindingResolver](binding-resolver.md) for the complete rebinding API.
45
45
 
46
46
  ## Creating a DynamicSchema
47
47
 
@@ -83,7 +83,7 @@ dynamic
83
83
  // value = Primitive(
84
84
  // primitiveType = String(None),
85
85
  // typeId = String,
86
- // primitiveBinding = zio.blocks.schema.binding.NoBinding$$anon$1@5ca5d848,
86
+ // primitiveBinding = zio.blocks.schema.binding.NoBinding$$anon$1@5fb4c2ef,
87
87
  // doc = Doc(blocks = IndexedSeq(), metadata = Map()),
88
88
  // modifiers = List(),
89
89
  // storedDefaultValue = None,
@@ -97,7 +97,7 @@ dynamic
97
97
  // value = Primitive(
98
98
  // primitiveType = Int(None),
99
99
  // typeId = Int,
100
- // primitiveBinding = zio.blocks.schema.binding.NoBinding$$anon$1@5ca5d848,
100
+ // primitiveBinding = zio.blocks.schema.binding.NoBinding$$anon$1@5fb4c2ef,
101
101
  // doc = Doc(blocks = IndexedSeq(), metadata = Map()),
102
102
  // modifiers = List(),
103
103
  // storedDefaultValue = None,
@@ -115,7 +115,7 @@ dynamic
115
115
  // value = Primitive(
116
116
  // primitiveType = String(None),
117
117
  // typeId = String,
118
- // primitiveBinding = zio.blocks.schema.binding.NoBinding$$anon$1@5ca5d848,
118
+ // primitiveBinding = zio.blocks.schema.binding.NoBinding$$anon$1@5fb4c2ef,
119
119
  // doc = Doc(blocks = IndexedSeq(), metadata = Map()),
120
120
  // modifiers = List(),
121
121
  // storedDefaultValue = None,
@@ -232,7 +232,7 @@ dynSchema.check(valid)
232
232
  dynSchema.check(missing)
233
233
  // res8: Option[SchemaError] = Some(
234
234
  // SchemaError(
235
- // List(MissingField(source = DynamicOptic(IndexedSeq()), fieldName = "y"))
235
+ // List(MissingField(source = DynamicOptic(ArraySeq()), fieldName = "y"))
236
236
  // )
237
237
  // )
238
238
  dynSchema.check(wrongType)
@@ -240,7 +240,7 @@ dynSchema.check(wrongType)
240
240
  // SchemaError(
241
241
  // List(
242
242
  // ExpectationMismatch(
243
- // source = DynamicOptic(IndexedSeq(Field("y"))),
243
+ // source = DynamicOptic(ArraySeq(Field("y"))),
244
244
  // expectation = "Expected Int, got String"
245
245
  // )
246
246
  // )
@@ -339,7 +339,7 @@ rebound.fromDynamicValue(encoded)
339
339
  If `DynamicSchema#rebind` cannot find a binding for any type in the unbound schema tree, it throws a `RebindException` at runtime. Ensure the resolver covers every concrete type — records, variants, wrappers, primitives, and standard collections — that appears in the schema. `BindingResolver.defaults` covers all standard primitives, `java.time` types, `List`, `Map`, `Option`, and other standard collections.
340
340
  :::
341
341
 
342
- See [BindingResolver](./binding-resolver.md) for the full resolver API including `BindingResolver.reflection` for automatic binding via reflection.
342
+ See [BindingResolver](binding-resolver.md) for the full resolver API including `BindingResolver.reflection` for automatic binding via reflection.
343
343
 
344
344
  ## Structural Navigation
345
345
 
@@ -546,7 +546,7 @@ gatewaySchema.fromDynamicValue(incoming)
546
546
 
547
547
  ### With `BindingResolver`
548
548
 
549
- The primary consumer of `DynamicSchema` in a type-safe context is `DynamicSchema#rebind`, which requires a `BindingResolver` to reattach runtime bindings. See [BindingResolver](./binding-resolver.md) for the complete rebinding API, including `BindingResolver.reflection` for automatic binding discovery.
549
+ The primary consumer of `DynamicSchema` in a type-safe context is `DynamicSchema#rebind`, which requires a `BindingResolver` to reattach runtime bindings. See [BindingResolver](binding-resolver.md) for the complete rebinding API, including `BindingResolver.reflection` for automatic binding discovery.
550
550
 
551
551
  ### With `DynamicOptic`
552
552
 
@@ -0,0 +1,92 @@
1
+ ---
2
+ id: format
3
+ title: "Format Type"
4
+ sidebar_label: "Format"
5
+ ---
6
+
7
+ A `Format` is an abstraction that bundles together everything needed to serialize and deserialize data in a specific format (JSON, Avro, MessagePack, etc.). It unifies metadata related to serialization formats, such as MIME type and codec deriver, in a single place.
8
+
9
+ ## Overview
10
+
11
+ The `Format` trait defines the structure for any serialization format. Each format specifies the types for decoding input, encoding output, the codec typeclass, MIME type, and the deriver used to generate codecs from schemas:
12
+
13
+ ```scala
14
+ import zio.blocks.schema.codec.Codec
15
+ import zio.blocks.schema.derive.Deriver
16
+
17
+ trait Format {
18
+ type DecodeInput
19
+ type EncodeOutput
20
+ type TypeClass[A] <: Codec[DecodeInput, EncodeOutput, A]
21
+ def mimeType: String
22
+ def deriver: Deriver[TypeClass]
23
+ }
24
+ ```
25
+
26
+ This design allows for a consistent API across different formats when deriving codecs from schemas. Having MIME type information helps with runtime content negotiation and format routing, for example in HTTP servers or message queues.
27
+
28
+ ## Using a Format
29
+
30
+ You can easily call [`Schema[A].derive(format)`](./type-class-derivation.md#using-the-deriver-to-derive-type-class-instances) for any format that implements the `Format` trait to obtain a codec that can encode and decode values of type `A` according to that format's rules:
31
+
32
+ ```scala
33
+ import zio.blocks.schema._
34
+ import zio.blocks.schema.toon._
35
+
36
+ case class Person(name: String, age: Int)
37
+
38
+ object Person {
39
+ implicit val schema: Schema[Person] = Schema.derived
40
+ }
41
+
42
+ val codec = Schema[Person].derive(ToonFormat)
43
+ val bytes: Array[Byte] = codec.encode(Person("Alice", 30))
44
+ val decoded: Either[SchemaError, Person] = codec.decode(bytes)
45
+ ```
46
+
47
+ ## Format Categories
48
+
49
+ Formats are categorized into `BinaryFormat` and `TextFormat`, which specify the types of input and output for encoding and decoding:
50
+
51
+ ```scala
52
+ sealed trait Format
53
+ abstract class BinaryFormat[A] extends Format { }
54
+ abstract class TextFormat[A] extends Format { }
55
+ ```
56
+
57
+ **BinaryFormat** — Encodes and decodes data as bytes. Used for compact, efficient serialization (e.g., Avro, Thrift, MessagePack).
58
+
59
+ **TextFormat** — Encodes and decodes data as text strings. Used for human-readable formats (e.g., JSON, YAML, TOON).
60
+
61
+ ### Example: JsonFormat
62
+
63
+ The `JsonFormat` is a `BinaryFormat` that represents JSON serialization, where both the input for decoding and output for encoding are `ByteBuffer`, the MIME type is `application/json`, and the deriver for generating codecs from schemas is `JsonCodecDeriver`:
64
+
65
+ ```scala
66
+ import zio.blocks.schema.json._
67
+
68
+ object MyJsonFormat extends zio.blocks.schema.codec.BinaryFormat("application/json", JsonCodecDeriver)
69
+ ```
70
+
71
+ ## Defining a Custom Format
72
+
73
+ To add a new serialization format, define a `BinaryFormat` (or `TextFormat`) singleton with a custom `Deriver`:
74
+
75
+ ```scala
76
+ import zio.blocks.schema.codec.BinaryCodec
77
+
78
+ // 1. Define your codec base class
79
+ abstract class MyCodec[A] extends BinaryCodec[A]
80
+
81
+ // 2. Implement a Deriver[MyCodec] (see Type-class Derivation docs)
82
+ // val myDeriver: Deriver[MyCodec] = ...
83
+
84
+ // 3. Create the format singleton
85
+ // object MyFormat extends BinaryFormat[MyCodec]("application/x-myformat", myDeriver)
86
+ ```
87
+
88
+ For details on implementing a `Deriver`, see [Type-class Derivation](./type-class-derivation.md).
89
+
90
+ ## Available Formats
91
+
92
+ ZIO Blocks provides multiple built-in formats. See the [Built-in Formats and Codecs](./built-in-codecs/index.md) section for a complete list of supported serialization formats and their respective codec modules.
@@ -0,0 +1,52 @@
1
+ ---
2
+ id: index
3
+ title: "ZIO Blocks Schema"
4
+ sidebar_label: "Schema"
5
+ ---
6
+
7
+ ## Introduction
8
+
9
+ ZIO Blocks Schema is the core type system and serialization framework that provides reified structural metadata for Scala data types. It enables type-safe schema definition, validation, optics-based data access, multi-format serialization, and runtime introspection — all derived from a single `Schema` definition.
10
+
11
+ **Core Type System:**
12
+ - [`Schema`](./schema.md) — Primary data type containing reified structure of a Scala data type
13
+ - [`Reflect`](./reflect.md) — Foundational data structure containing reified structural information
14
+ - [`Binding`](./binding.md) — Operational machinery for constructing and deconstructing values
15
+ - [`ReflectTransformer`](./reflect-transformer.md) — Generic mechanism for rewriting a Reflect tree's binding type, powering schema (de)serialization and derivation
16
+ - [`Registers`](./registers.md) — Register-based design for zero-allocation construction and deconstruction
17
+ - [`Structural Types`](./structural-types.md) — Duck typing with ZIO Blocks schemas
18
+
19
+ **Dynamic & Runtime Data:**
20
+ - [`DynamicValue`](./dynamic-value.md) — Schema-less, dynamically-typed representation of any structured value
21
+ - [`DynamicSchema`](./dynamic-schema.md) — Type-erased schema container for serialization and transport
22
+ - [`Lazy`](./lazy.md) — Deferred computation with monadic abstraction, memoization, and stack-safe evaluation
23
+
24
+ **Navigation & Transformation:**
25
+ - [`Optics`](./optics.md) — Reflective optics for type-safe, composable access to nested data structures
26
+ - [`DynamicOptic`](./dynamic-optic.md) — Runtime path through nested data structures
27
+ - [`Path Interpolator`](./path-interpolator.md) — Compile-time string interpolator `p"..."` for constructing `DynamicOptic` instances
28
+ - [`Schema Search and Update`](./schema-search.md) — Executing type/schema-pattern searches with `SearchTraversal`, and rewriting schema metadata with `Reflect.Updater`/`Term.Updater`
29
+ - [`SchemaExpr`](./schema-expr.md) — Schema-aware expressions for evaluation and query language translation
30
+ - [`Patch`](./patch.md) — Type-safe, serializable transformations of data structures
31
+ - [`Modifier`](./modifier.md) — Mechanism to attach metadata and configuration to schema elements
32
+
33
+ **Serialization:**
34
+ - [`Codec`](./codec.md) — Base abstraction for encoding and decoding values between formats
35
+ - [`Format`](./format.md) — Unified abstraction bundling serialization and deserialization for a specific format
36
+ - [`Type Class Derivation`](./type-class-derivation.md) — Automatic generation of type class instances from schemas
37
+ - [`Syntax`](./syntax.md) — Extension methods for fluent JSON encoding/decoding and patching
38
+
39
+ **Formats:**
40
+ - [`JSON Codec`](./built-in-codecs/json/) — Complete JSON support: ADT for JSON values, fluent navigation, encoding/decoding, diffs, patches, and JSON Schema 2020-12 validation
41
+ - [`Xml`](./built-in-codecs/xml.md) — Type-safe, immutable representation of XML document structures
42
+
43
+ **Validation & Errors:**
44
+ - [`Validation`](./validation.md) — Declarative constraints on primitive values
45
+ - [`SchemaError`](./schema-error.md) — Structured error type for schema operations
46
+ - [`Allows`](./allows.md) — Compile-time capability token proving a type satisfies a structural grammar
47
+
48
+ ## Overview
49
+
50
+ The ZIO Blocks Schema module revolves around the `Schema` and `Reflect` types, which capture the complete structural description of Scala data types at runtime. From a single schema definition, you get automatic derivation of codecs (`Codec`, `Formats`), type-safe data access (`Optics`, `DynamicOptic`), structural validation (`Validation`, `SchemaError`), patching (`Patch`, `JsonPatch`), and serialization to multiple formats (`Json`, `Xml`, `JSON Schema`).
51
+
52
+ The type system is powered by a register-based architecture (`Registers`) that eliminates boxing overhead, and supports both compile-time (`Allows`) and runtime (`DynamicValue`, `DynamicSchema`) type manipulation. The `Deriver` system (`Type Class Derivation`) enables automatic generation of any type class instance from schema metadata.