@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.
- package/adr/2026-07-18-data-migration.md +123 -0
- package/guides/async-getting-started.md +687 -0
- package/guides/compile-time-resource-safety-with-scope.md +21 -16
- package/guides/getting-started-with-mux.md +1395 -0
- package/guides/query-dsl-extending.md +161 -102
- package/guides/query-dsl-fluent-builder.md +217 -157
- package/guides/query-dsl-reified-optics.md +12 -10
- package/guides/query-dsl-sql.md +640 -165
- package/guides/sql-checked-interpolation.md +173 -0
- package/guides/sql-transactions.md +286 -0
- package/guides/telemetry-guide.md +1130 -0
- package/guides/zio-schema-migration.md +29 -22
- package/index.md +248 -389
- package/package.json +1 -1
- package/plans/config-follow-up-prs.md +188 -0
- package/plans/config-pr-assessment-roadmap.md +310 -0
- package/reference/MuxDataFlow.jsx +250 -0
- package/reference/async.md +1499 -0
- package/reference/chunk.md +3533 -308
- package/reference/codegen/case-class.md +436 -0
- package/reference/codegen/emitter-config.md +383 -0
- package/reference/codegen/examples.md +664 -0
- package/reference/codegen/field.md +316 -0
- package/reference/codegen/index.md +317 -0
- package/reference/codegen/scala-emitter.md +392 -0
- package/reference/codegen/scala-file.md +276 -0
- package/reference/codegen/sealed-trait.md +408 -0
- package/reference/codegen/type-definition.md +340 -0
- package/reference/codegen/type-ref.md +201 -0
- package/reference/combinators.md +347 -117
- package/reference/config/config-decoder.md +460 -0
- package/reference/config/config-source.md +489 -0
- package/reference/config/errors.md +278 -0
- package/reference/config/flags.md +369 -0
- package/reference/config/formats.md +314 -0
- package/reference/config/index.md +304 -0
- package/reference/config/rollout.md +336 -0
- package/reference/context.md +9 -52
- package/reference/data-migration.md +269 -0
- package/reference/datastar/attributes.md +302 -0
- package/reference/datastar/events.md +234 -0
- package/reference/datastar/index.md +256 -0
- package/reference/datastar/signals.md +230 -0
- package/reference/datastar/sse.md +295 -0
- package/reference/datastar.md +346 -0
- package/reference/docs.md +1461 -345
- package/reference/endpoint/auth-type.md +146 -0
- package/reference/endpoint/bulk-creation.md +96 -0
- package/reference/endpoint/endpoint.md +297 -0
- package/reference/endpoint/http-codec.md +249 -0
- package/reference/endpoint/index.md +745 -0
- package/reference/endpoint/path-codec.md +225 -0
- package/reference/endpoint/route-pattern.md +194 -0
- package/reference/endpoint/route-tree.md +111 -0
- package/reference/endpoint/segment-codec.md +199 -0
- package/reference/html.md +1424 -0
- package/reference/htmx/attribute-values.md +359 -0
- package/reference/htmx/hx-encoding.md +111 -0
- package/reference/htmx/hx-params.md +204 -0
- package/reference/htmx/hx-swap.md +276 -0
- package/reference/htmx/hx-sync.md +251 -0
- package/reference/htmx/hx-target.md +314 -0
- package/reference/htmx/hx-trigger.md +457 -0
- package/reference/htmx/hx-url-update.md +239 -0
- package/reference/htmx/index.md +807 -0
- package/reference/htmx/response-headers.md +240 -0
- package/reference/http-model/headers.md +735 -0
- package/reference/http-model/index.md +49 -0
- package/reference/http-model/model.md +1517 -0
- package/reference/http-model/schema-codecs.md +522 -0
- package/reference/http-model/schema.md +750 -0
- package/reference/http-model/server-sent-event.md +341 -0
- package/reference/jwt.md +195 -0
- package/reference/maybe.md +943 -0
- package/reference/media-type.md +2 -2
- package/reference/mux.md +254 -0
- package/reference/mux.mdx +828 -0
- package/reference/openapi.md +1351 -0
- package/reference/projection.md +654 -0
- package/reference/resource-management/defer-handle.md +1 -1
- package/reference/resource-management/resource.md +31 -98
- package/reference/resource-management/scope.md +28 -220
- package/reference/resource-management/wire.md +5 -55
- package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
- package/reference/ringbuffer/MpscDiagram.jsx +618 -0
- package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
- package/reference/ringbuffer/SpscDiagram.jsx +677 -0
- package/reference/ringbuffer/advanced.mdx +109 -0
- package/reference/ringbuffer/index.mdx +145 -0
- package/reference/ringbuffer/mpmc.mdx +185 -0
- package/reference/ringbuffer/mpsc.mdx +164 -0
- package/reference/ringbuffer/spmc.mdx +108 -0
- package/reference/ringbuffer/spsc.mdx +416 -0
- package/reference/{allows.md → schema/allows.md} +4 -100
- package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
- package/reference/{binding.md → schema/binding.md} +3 -4
- package/reference/schema/built-in-codecs/avro.md +451 -0
- package/reference/schema/built-in-codecs/bson.md +510 -0
- package/reference/schema/built-in-codecs/csv.md +564 -0
- package/reference/schema/built-in-codecs/index.md +77 -0
- package/reference/schema/built-in-codecs/json/index.md +295 -0
- package/reference/schema/built-in-codecs/json/json-config.md +217 -0
- package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
- package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
- package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
- package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
- package/reference/schema/built-in-codecs/messagepack.md +508 -0
- package/reference/schema/built-in-codecs/thrift.md +433 -0
- package/reference/schema/built-in-codecs/toon.md +1078 -0
- package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
- package/reference/schema/built-in-codecs/yaml.md +552 -0
- package/reference/{codec.md → schema/codec.md} +11 -11
- package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +196 -5
- package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
- package/reference/schema/format.md +92 -0
- package/reference/schema/index.md +52 -0
- package/reference/schema/migration.md +297 -0
- package/reference/{modifier.md → schema/modifier.md} +58 -7
- package/reference/{optics.md → schema/optics.md} +2 -2
- package/reference/{patch.md → schema/patch.md} +1 -1
- package/{path-interpolator.md → reference/schema/path-interpolator.md} +167 -72
- package/reference/schema/reflect-transformer.md +140 -0
- package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
- package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
- package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
- package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
- package/reference/schema/schema-search.md +263 -0
- package/reference/{schema.md → schema/schema.md} +22 -2
- package/reference/{structural-types.md → schema/structural-types.md} +1 -1
- package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
- package/reference/smithy.md +1032 -0
- package/reference/sql/db-codec-deriver.md +71 -0
- package/reference/sql/db-codec.md +687 -0
- package/reference/sql/db-con.md +271 -0
- package/reference/sql/db-connection.md +153 -0
- package/reference/sql/db-param-writer.md +77 -0
- package/reference/sql/db-param.md +66 -0
- package/reference/sql/db-result-reader.md +148 -0
- package/reference/sql/db-tx.md +114 -0
- package/reference/sql/db-value.md +41 -0
- package/reference/sql/ddl.md +85 -0
- package/reference/sql/frag.md +288 -0
- package/reference/sql/index.md +341 -0
- package/reference/sql/repo.md +600 -0
- package/reference/sql/sql-dialect.md +73 -0
- package/reference/sql/sql-logger.md +62 -0
- package/reference/sql/sql-name-mapper.md +70 -0
- package/reference/sql/table-metadata.md +134 -0
- package/reference/sql/table.md +448 -0
- package/reference/sql/transactor-zio.md +399 -0
- package/reference/sql/transactor.md +363 -0
- package/reference/sql-zio.md +112 -0
- package/reference/streams/core/index.md +32 -0
- package/reference/streams/core/pipeline.md +854 -0
- package/reference/streams/core/sink.md +1404 -0
- package/reference/streams/core/stream.md +3236 -0
- package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
- package/reference/streams/execution-and-compatibility/index.md +35 -0
- package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
- package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
- package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
- package/reference/streams/index.md +726 -0
- package/reference/streams/primitives/index.md +30 -0
- package/reference/streams/primitives/reader.md +1992 -0
- package/reference/streams/primitives/writer.md +1201 -0
- package/reference/telemetry/common/any-value.md +90 -0
- package/reference/telemetry/common/attribute-key.md +87 -0
- package/reference/telemetry/common/attributes.md +118 -0
- package/reference/telemetry/common/index.md +39 -0
- package/reference/telemetry/common/instrumentation-scope.md +24 -0
- package/reference/telemetry/common/resource.md +34 -0
- package/reference/telemetry/index.md +311 -0
- package/reference/telemetry/logging/index.md +197 -0
- package/reference/telemetry/logging/log-enrichment.md +72 -0
- package/reference/telemetry/logging/log-formatter.md +100 -0
- package/reference/telemetry/logging/log-record-processor.md +56 -0
- package/reference/telemetry/logging/log-record.md +44 -0
- package/reference/telemetry/logging/log-writer.md +64 -0
- package/reference/telemetry/logging/logger-provider.md +142 -0
- package/reference/telemetry/logging/logger.md +83 -0
- package/reference/telemetry/logging/severity.md +62 -0
- package/reference/telemetry/metrics/index.md +150 -0
- package/reference/telemetry/metrics/instruments.md +183 -0
- package/reference/telemetry/metrics/labeled-instruments.md +74 -0
- package/reference/telemetry/metrics/meter-provider.md +76 -0
- package/reference/telemetry/metrics/meter.md +98 -0
- package/reference/telemetry/metrics/metric-data.md +57 -0
- package/reference/telemetry/otel/custom-exporter.md +216 -0
- package/reference/telemetry/otel/index.md +212 -0
- package/reference/telemetry/tracing/index.md +155 -0
- package/reference/telemetry/tracing/sampler.md +89 -0
- package/reference/telemetry/tracing/span-builder.md +57 -0
- package/reference/telemetry/tracing/span-context.md +39 -0
- package/reference/telemetry/tracing/span-data.md +32 -0
- package/reference/telemetry/tracing/span-kind.md +55 -0
- package/reference/telemetry/tracing/span-processor.md +53 -0
- package/reference/telemetry/tracing/span-status.md +47 -0
- package/reference/telemetry/tracing/span.md +117 -0
- package/reference/telemetry/tracing/tracer-provider.md +91 -0
- package/reference/telemetry/tracing/tracer.md +52 -0
- package/reference/typeid.md +5 -83
- package/sidebars.js +376 -43
- package/undocumented-report.md +528 -270
- package/reference/formats.md +0 -694
- package/reference/http-model.md +0 -1716
- package/reference/streams.md +0 -989
- package/ringbuffer.md +0 -249
- /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
- /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
- /package/reference/{lazy.md → schema/lazy.md} +0 -0
- /package/reference/{reflect.md → schema/reflect.md} +0 -0
- /package/reference/{registers.md → schema/registers.md} +0 -0
- /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
- /package/reference/{syntax.md → schema/syntax.md} +0 -0
- /package/reference/{validation.md → schema/validation.md} +0 -0
|
@@ -584,29 +584,13 @@ sbt "schema-examples/runMain comptime.AllowsCsvExample"
|
|
|
584
584
|
```
|
|
585
585
|
|
|
586
586
|
```scala title="schema-examples/src/main/scala/comptime/AllowsCsvExample.scala"
|
|
587
|
-
/*
|
|
588
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
589
|
-
*
|
|
590
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
591
|
-
* you may not use this file except in compliance with the License.
|
|
592
|
-
* You may obtain a copy of the License at
|
|
593
|
-
*
|
|
594
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
595
|
-
*
|
|
596
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
597
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
598
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
599
|
-
* See the License for the specific language governing permissions and
|
|
600
|
-
* limitations under the License.
|
|
601
|
-
*/
|
|
602
|
-
|
|
603
587
|
package comptime
|
|
604
588
|
|
|
605
589
|
import zio.blocks.schema._
|
|
606
590
|
import zio.blocks.schema.comptime.Allows
|
|
607
591
|
import Allows.{Primitive, Record, `|`}
|
|
608
592
|
import Allows.{Optional => AOptional}
|
|
609
|
-
import
|
|
593
|
+
import zio.sbt.ExprEval.show
|
|
610
594
|
|
|
611
595
|
// ---------------------------------------------------------------------------
|
|
612
596
|
// CSV serializer example using Allows[A, S] compile-time shape constraints
|
|
@@ -708,29 +692,13 @@ sbt "schema-examples/runMain comptime.AllowsEventBusExample"
|
|
|
708
692
|
```
|
|
709
693
|
|
|
710
694
|
```scala title="schema-examples/src/main/scala/comptime/AllowsEventBusExample.scala"
|
|
711
|
-
/*
|
|
712
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
713
|
-
*
|
|
714
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
715
|
-
* you may not use this file except in compliance with the License.
|
|
716
|
-
* You may obtain a copy of the License at
|
|
717
|
-
*
|
|
718
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
719
|
-
*
|
|
720
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
721
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
722
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
723
|
-
* See the License for the specific language governing permissions and
|
|
724
|
-
* limitations under the License.
|
|
725
|
-
*/
|
|
726
|
-
|
|
727
695
|
package comptime
|
|
728
696
|
|
|
729
697
|
import zio.blocks.schema._
|
|
730
698
|
import zio.blocks.schema.comptime.Allows
|
|
731
699
|
import Allows.{Primitive, Record, Sequence, `|`}
|
|
732
700
|
import Allows.{Optional => AOptional}
|
|
733
|
-
import
|
|
701
|
+
import zio.sbt.ExprEval.show
|
|
734
702
|
|
|
735
703
|
// ---------------------------------------------------------------------------
|
|
736
704
|
// Event bus / message broker example using Allows[A, S]
|
|
@@ -830,29 +798,13 @@ sbt "schema-examples/runMain comptime.AllowsGraphQLTreeExample"
|
|
|
830
798
|
```
|
|
831
799
|
|
|
832
800
|
```scala title="schema-examples/src/main/scala/comptime/AllowsGraphQLTreeExample.scala"
|
|
833
|
-
/*
|
|
834
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
835
|
-
*
|
|
836
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
837
|
-
* you may not use this file except in compliance with the License.
|
|
838
|
-
* You may obtain a copy of the License at
|
|
839
|
-
*
|
|
840
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
841
|
-
*
|
|
842
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
843
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
844
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
845
|
-
* See the License for the specific language governing permissions and
|
|
846
|
-
* limitations under the License.
|
|
847
|
-
*/
|
|
848
|
-
|
|
849
801
|
package comptime
|
|
850
802
|
|
|
851
803
|
import zio.blocks.schema._
|
|
852
804
|
import zio.blocks.schema.comptime.Allows
|
|
853
805
|
import Allows.{Primitive, Record, Sequence, `|`}
|
|
854
806
|
import Allows.{Optional => AOptional, Self => ASelf}
|
|
855
|
-
import
|
|
807
|
+
import zio.sbt.ExprEval.show
|
|
856
808
|
|
|
857
809
|
// ---------------------------------------------------------------------------
|
|
858
810
|
// GraphQL / tree structure example using Self for recursive grammars
|
|
@@ -970,28 +922,12 @@ sbt "schema-examples/runMain comptime.AllowsSealedTraitExample"
|
|
|
970
922
|
```
|
|
971
923
|
|
|
972
924
|
```scala title="schema-examples/src/main/scala/comptime/AllowsSealedTraitExample.scala"
|
|
973
|
-
/*
|
|
974
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
975
|
-
*
|
|
976
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
977
|
-
* you may not use this file except in compliance with the License.
|
|
978
|
-
* You may obtain a copy of the License at
|
|
979
|
-
*
|
|
980
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
981
|
-
*
|
|
982
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
983
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
984
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
985
|
-
* See the License for the specific language governing permissions and
|
|
986
|
-
* limitations under the License.
|
|
987
|
-
*/
|
|
988
|
-
|
|
989
925
|
package comptime
|
|
990
926
|
|
|
991
927
|
import zio.blocks.schema._
|
|
992
928
|
import zio.blocks.schema.comptime.Allows
|
|
993
929
|
import Allows.{Primitive, Record}
|
|
994
|
-
import
|
|
930
|
+
import zio.sbt.ExprEval.show
|
|
995
931
|
|
|
996
932
|
// ---------------------------------------------------------------------------
|
|
997
933
|
// Sealed trait auto-unwrap example
|
|
@@ -1081,22 +1017,6 @@ object AllowsSealedTraitExample extends App {
|
|
|
1081
1017
|
Demonstrates how Allows constraints are verified at compile time — the code below shows valid examples that compile successfully, and includes comments showing which patterns would be rejected:
|
|
1082
1018
|
|
|
1083
1019
|
```scala title="schema-examples/src/main/scala/comptime/RdbmsExample.scala"
|
|
1084
|
-
/*
|
|
1085
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
1086
|
-
*
|
|
1087
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1088
|
-
* you may not use this file except in compliance with the License.
|
|
1089
|
-
* You may obtain a copy of the License at
|
|
1090
|
-
*
|
|
1091
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1092
|
-
*
|
|
1093
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
1094
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1095
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1096
|
-
* See the License for the specific language governing permissions and
|
|
1097
|
-
* limitations under the License.
|
|
1098
|
-
*/
|
|
1099
|
-
|
|
1100
1020
|
package comptime
|
|
1101
1021
|
|
|
1102
1022
|
import zio.blocks.schema._
|
|
@@ -1290,22 +1210,6 @@ object RdbmsDemo {
|
|
|
1290
1210
|
Demonstrates how Allows enforces recursive schema constraints at compile time:
|
|
1291
1211
|
|
|
1292
1212
|
```scala title="schema-examples/src/main/scala/comptime/DocumentStoreExample.scala"
|
|
1293
|
-
/*
|
|
1294
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
1295
|
-
*
|
|
1296
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1297
|
-
* you may not use this file except in compliance with the License.
|
|
1298
|
-
* You may obtain a copy of the License at
|
|
1299
|
-
*
|
|
1300
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1301
|
-
*
|
|
1302
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
1303
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1304
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1305
|
-
* See the License for the specific language governing permissions and
|
|
1306
|
-
* limitations under the License.
|
|
1307
|
-
*/
|
|
1308
|
-
|
|
1309
1213
|
package comptime
|
|
1310
1214
|
|
|
1311
1215
|
import zio.blocks.schema._
|
|
@@ -466,4 +466,4 @@ val rebound: Schema[Address] = Schema[Address].toDynamicSchema.rebind[Address](r
|
|
|
466
466
|
If `DynamicSchema#rebind` cannot find a binding for any type present in the unbound schema tree, it throws at runtime. Make sure the resolver covers every concrete type—records, variants, wrappers, primitives, and collections—that appears in the schema.
|
|
467
467
|
:::
|
|
468
468
|
|
|
469
|
-
See [Binding](
|
|
469
|
+
See [Binding](binding.md) for details on each binding kind, and [Schema](schema.md) for the overall structure of the schema system.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: binding
|
|
3
|
-
title: "
|
|
4
|
-
sidebar_label: Binding
|
|
3
|
+
title: "Binding"
|
|
5
4
|
---
|
|
6
5
|
|
|
7
6
|
`Binding` is a sealed trait in ZIO Blocks that provides the operational machinery for constructing and deconstructing values of schema-described types. While `Reflect` describes the **structure** of data types, `Binding` provides the **behavior** needed to work with those types at runtime.
|
|
@@ -337,9 +336,9 @@ Used when the schema of the data is not known at compile time, such as JSON payl
|
|
|
337
336
|
When `F[_, _] = NoBinding` in `Reflect[F[_, _], A]` the `Reflect` structure contains only pure data (no functions) and becomes fully serializable. This enables:
|
|
338
337
|
|
|
339
338
|
1. **Schema serialization**: Convert schemas to JSON Schema or other formats, making them portable
|
|
340
|
-
2. **Schema rebinding**: Deserialize a schema and rebind it using a `
|
|
339
|
+
2. **Schema rebinding**: Deserialize a schema and rebind it using a `BindingResolver`, so it becomes type-safe and operational again
|
|
341
340
|
|
|
342
|
-
|
|
341
|
+
[ReflectTransformer](./reflect-transformer.md) covers schema serialization and rebinding in full detail — the transformer that strips bindings, the one that reattaches them, and how each is exposed as `Schema#toDynamicSchema`/`DynamicSchema#rebind`. For the full API of the binding lookup mechanism used during rebinding, see [BindingResolver](binding-resolver.md).
|
|
343
342
|
|
|
344
343
|
## Summary
|
|
345
344
|
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: avro
|
|
3
|
+
title: "Avro Codec Module"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`zio-blocks-schema-avro` is a **schema-driven Avro codec module** for serializing and deserializing Scala types to and from Avro binary format. It provides comprehensive encoding and decoding with support for 27 primitive types, records, variants, sequences, maps, and recursive types. Core types: `AvroCodec`, `AvroCodecDeriver`, `AvroFormat`.
|
|
7
|
+
|
|
8
|
+
The module integrates with Apache Avro to provide native binary serialization with automatic schema generation and support for recursive data structures with cycle detection.
|
|
9
|
+
|
|
10
|
+
## Motivation
|
|
11
|
+
|
|
12
|
+
Avro is a powerful serialization format prevalent in distributed systems, messaging platforms, and data pipelines. Manually writing Avro encoders and decoders is error-prone and repetitive, especially for complex types with records, nested structures, and recursive definitions. `zio-blocks-schema-avro` eliminates this friction by deriving codec instances directly from your Scala types using ZIO Schema. You describe your data shape once, and the module handles:
|
|
13
|
+
- Full Avro type support (records, unions, arrays, maps, nested structures)
|
|
14
|
+
- Automatic Avro schema generation from Scala types
|
|
15
|
+
- Configurable sum type handling (union fields with discriminators)
|
|
16
|
+
- Precise error reporting with location traces showing the path to errors
|
|
17
|
+
- Recursive type support with automatic cycle detection
|
|
18
|
+
- Multiple encoding paths: ByteBuffer, byte arrays, and streams
|
|
19
|
+
- Multiple decoding paths: ByteBuffer, byte arrays, and streams
|
|
20
|
+
- JVM support (not available for Scala.js)
|
|
21
|
+
|
|
22
|
+
Rather than writing custom encoders or relying on string-based Avro schema configuration, you work with strongly-typed schemas that the compiler validates.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
Add the module to your `build.sbt` (JVM-only, not available for Scala.js):
|
|
27
|
+
|
|
28
|
+
```sbt
|
|
29
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-avro" % "0.0.55"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Supported Scala versions: 2.13.x and 3.x
|
|
33
|
+
|
|
34
|
+
## Introduction
|
|
35
|
+
|
|
36
|
+
The module provides a complete pipeline for Avro codec derivation and usage:
|
|
37
|
+
|
|
38
|
+
1. **Define your type** — Any Scala type with a `Schema` instance
|
|
39
|
+
2. **Derive a codec** — Use `Schema.derive(AvroFormat)` to obtain an `AvroCodec[A]`
|
|
40
|
+
3. **Encode or decode** — Call `codec.encode(value)` or `codec.decode(bytes)`
|
|
41
|
+
4. **Handle errors** — Catch `SchemaError` with location traces showing where the error occurred
|
|
42
|
+
|
|
43
|
+
The derivation process is automatic for all supported types (all 27 primitives, records, variants, sequences, maps). The module automatically generates Avro schemas and handles encoding/decoding without manual configuration.
|
|
44
|
+
|
|
45
|
+
## How They Work Together
|
|
46
|
+
|
|
47
|
+
The Avro codec pipeline flows through these layers:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
1. User defines Schema[A] for their type
|
|
51
|
+
↓
|
|
52
|
+
2. Schema[A].derive(AvroFormat) creates AvroCodec[A]
|
|
53
|
+
↓
|
|
54
|
+
3. AvroCodecDeriver derives Encoder and Decoder implementations
|
|
55
|
+
- For primitives: type-specific Avro encoders/decoders
|
|
56
|
+
- For records: field-by-field composition with Avro record schema
|
|
57
|
+
- For variants: union type encoding with discriminator support
|
|
58
|
+
- For sequences: array encoding/decoding
|
|
59
|
+
- For maps: map encoding/decoding
|
|
60
|
+
↓
|
|
61
|
+
4. AvroCodec provides multiple encoding paths
|
|
62
|
+
- encode(value) → Array[Byte]
|
|
63
|
+
- encode(value, output: OutputStream) → Unit
|
|
64
|
+
- encode(value, buffer: ByteBuffer) → Unit
|
|
65
|
+
↓
|
|
66
|
+
5. AvroCodec provides multiple decoding paths
|
|
67
|
+
- decode(bytes: Array[Byte]) → Either[SchemaError, A]
|
|
68
|
+
- decode(input: InputStream) → Either[SchemaError, A]
|
|
69
|
+
- decode(buffer: ByteBuffer) → Either[SchemaError, A]
|
|
70
|
+
↓
|
|
71
|
+
6. AvroCodec.avroSchema exposes generated Avro schema
|
|
72
|
+
Useful for compatibility checks and schema documentation
|
|
73
|
+
↓
|
|
74
|
+
7. Errors include location traces
|
|
75
|
+
Shows path (.field[index].nested) to error location
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Typical workflow:**
|
|
79
|
+
|
|
80
|
+
A user type flows through the derivation and encoding pipeline as follows:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
User type (e.g., case class Person)
|
|
84
|
+
↓
|
|
85
|
+
Schema.derived (automatic via macro)
|
|
86
|
+
↓
|
|
87
|
+
Schema[Person].derive(AvroFormat) → AvroCodec[Person]
|
|
88
|
+
↓
|
|
89
|
+
Use codec.encode(person) to serialize → Array[Byte]
|
|
90
|
+
Use codec.decode(bytes) to deserialize → Either[SchemaError, Person]
|
|
91
|
+
↓
|
|
92
|
+
Handle SchemaError with location trace on failure
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Type Relationships
|
|
96
|
+
|
|
97
|
+
- **`AvroCodec[A]`** — Main public API; contains encoder and decoder for bidirectional serialization
|
|
98
|
+
- **`AvroCodecDeriver`** — Configuration and derivation system; generates codecs from Schema
|
|
99
|
+
- **`AvroFormat`** — Integration with ZIO Schema format system; enables `Schema[A].derive(AvroFormat)`
|
|
100
|
+
- **`SchemaError`** — Error type with location traces; renders as paths like `.field[0].nested`
|
|
101
|
+
|
|
102
|
+
## Common Patterns
|
|
103
|
+
|
|
104
|
+
This section shows practical patterns for working with Avro codecs in real-world scenarios.
|
|
105
|
+
|
|
106
|
+
### Pattern 1: Derive and Encode a Simple Record
|
|
107
|
+
|
|
108
|
+
To derive and use an Avro codec for a record type:
|
|
109
|
+
|
|
110
|
+
```scala
|
|
111
|
+
import zio.blocks.schema._
|
|
112
|
+
import zio.blocks.schema.avro._
|
|
113
|
+
|
|
114
|
+
case class Person(name: String, age: Int, email: String)
|
|
115
|
+
|
|
116
|
+
object Person {
|
|
117
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
val codec = Person.schema.derive(AvroFormat)
|
|
121
|
+
val person = Person("Alice", 30, "alice@example.com")
|
|
122
|
+
val bytes = codec.encode(person)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Pattern 2: Decode Avro with Error Handling
|
|
126
|
+
|
|
127
|
+
When decoding Avro data, errors include location traces showing where the problem occurred.
|
|
128
|
+
|
|
129
|
+
To decode bytes and handle errors with location information:
|
|
130
|
+
|
|
131
|
+
```scala
|
|
132
|
+
import zio.blocks.schema._
|
|
133
|
+
import zio.blocks.schema.avro._
|
|
134
|
+
|
|
135
|
+
case class Employee(id: Int, name: String, salary: Double)
|
|
136
|
+
|
|
137
|
+
object Employee {
|
|
138
|
+
implicit val schema: Schema[Employee] = Schema.derived
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
val codec = Employee.schema.derive(AvroFormat)
|
|
142
|
+
val bytes = Array[Byte](1, 4, 6) // truncated data
|
|
143
|
+
|
|
144
|
+
val result = codec.decode(bytes)
|
|
145
|
+
|
|
146
|
+
result match {
|
|
147
|
+
case Right(employee) => println(s"Decoded: $employee")
|
|
148
|
+
case Left(error) =>
|
|
149
|
+
println(s"Error at ${error.getMessage}")
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Pattern 3: Inspect the Generated Avro Schema
|
|
154
|
+
|
|
155
|
+
Access the derived Avro schema to verify compatibility or document the serialization format.
|
|
156
|
+
|
|
157
|
+
To inspect the Avro schema for a type:
|
|
158
|
+
|
|
159
|
+
```scala
|
|
160
|
+
import zio.blocks.schema._
|
|
161
|
+
import zio.blocks.schema.avro._
|
|
162
|
+
|
|
163
|
+
case class Product(name: String, price: Double, inStock: Boolean)
|
|
164
|
+
|
|
165
|
+
object Product {
|
|
166
|
+
implicit val schema: Schema[Product] = Schema.derived
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
val codec = Product.schema.derive(AvroFormat)
|
|
170
|
+
val avroSchema = codec.avroSchema
|
|
171
|
+
println(avroSchema.toString)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Pattern 4: Handle Recursive Types
|
|
175
|
+
|
|
176
|
+
Recursive types (types that reference themselves) are fully supported with automatic cycle detection.
|
|
177
|
+
|
|
178
|
+
To define and encode a recursive data structure:
|
|
179
|
+
|
|
180
|
+
```scala
|
|
181
|
+
import zio.blocks.schema._
|
|
182
|
+
import zio.blocks.schema.avro._
|
|
183
|
+
|
|
184
|
+
sealed trait Tree
|
|
185
|
+
case class Leaf(value: Int) extends Tree
|
|
186
|
+
case class Branch(left: Tree, right: Tree) extends Tree
|
|
187
|
+
|
|
188
|
+
object Tree {
|
|
189
|
+
implicit val schema: Schema[Tree] = Schema.derived
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
val codec = Tree.schema.derive(AvroFormat)
|
|
193
|
+
val tree: Tree = Branch(Leaf(1), Branch(Leaf(2), Leaf(3)))
|
|
194
|
+
val bytes = codec.encode(tree)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## AvroCodec[A]
|
|
200
|
+
|
|
201
|
+
Main codec type for encoding and decoding values to and from Avro binary format. Contains encoder and decoder for bidirectional serialization.
|
|
202
|
+
|
|
203
|
+
### Overview
|
|
204
|
+
|
|
205
|
+
`AvroCodec[A]` holds both an encoder and decoder, providing a complete solution for serializing and deserializing values in Avro binary format. The codec is derived automatically from a `Schema[A]` using `AvroFormat`.
|
|
206
|
+
|
|
207
|
+
### Accessing the Avro Schema
|
|
208
|
+
|
|
209
|
+
To get the derived Avro schema from a codec:
|
|
210
|
+
|
|
211
|
+
```scala
|
|
212
|
+
import zio.blocks.schema._
|
|
213
|
+
import zio.blocks.schema.avro._
|
|
214
|
+
|
|
215
|
+
case class User(id: Int, name: String)
|
|
216
|
+
|
|
217
|
+
object User {
|
|
218
|
+
implicit val schema: Schema[User] = Schema.derived
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
val codec = User.schema.derive(AvroFormat)
|
|
222
|
+
val avroSchema = codec.avroSchema
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Encoding Values to Byte Array
|
|
226
|
+
|
|
227
|
+
Use the codec to convert values to byte arrays:
|
|
228
|
+
|
|
229
|
+
```scala
|
|
230
|
+
import zio.blocks.schema._
|
|
231
|
+
import zio.blocks.schema.avro._
|
|
232
|
+
|
|
233
|
+
case class Product(name: String, price: Double)
|
|
234
|
+
|
|
235
|
+
object Product {
|
|
236
|
+
implicit val schema: Schema[Product] = Schema.derived
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
val codec = Product.schema.derive(AvroFormat)
|
|
240
|
+
val product = Product("Widget", 9.99)
|
|
241
|
+
val bytes = codec.encode(product)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Encoding Values to OutputStream
|
|
245
|
+
|
|
246
|
+
Write encoded values directly to an output stream:
|
|
247
|
+
|
|
248
|
+
```scala
|
|
249
|
+
import zio.blocks.schema._
|
|
250
|
+
import zio.blocks.schema.avro._
|
|
251
|
+
import java.io.ByteArrayOutputStream
|
|
252
|
+
|
|
253
|
+
case class Item(name: String, quantity: Int)
|
|
254
|
+
|
|
255
|
+
object Item {
|
|
256
|
+
implicit val schema: Schema[Item] = Schema.derived
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
val codec = Item.schema.derive(AvroFormat)
|
|
260
|
+
val item = Item("Gadget", 42)
|
|
261
|
+
val output = new ByteArrayOutputStream()
|
|
262
|
+
codec.encode(item, output)
|
|
263
|
+
val bytes = output.toByteArray
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Decoding Values from Byte Array
|
|
267
|
+
|
|
268
|
+
Use the codec to convert byte arrays back to values:
|
|
269
|
+
|
|
270
|
+
```scala
|
|
271
|
+
import zio.blocks.schema._
|
|
272
|
+
import zio.blocks.schema.avro._
|
|
273
|
+
|
|
274
|
+
case class Record(id: Int, value: String)
|
|
275
|
+
|
|
276
|
+
object Record {
|
|
277
|
+
implicit val schema: Schema[Record] = Schema.derived
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
val codec = Record.schema.derive(AvroFormat)
|
|
281
|
+
// In real usage, bytes would come from a previous encoding or external source
|
|
282
|
+
val record = Record(123, "test")
|
|
283
|
+
val buffer = java.nio.ByteBuffer.allocate(256)
|
|
284
|
+
codec.encode(record, buffer)
|
|
285
|
+
buffer.flip()
|
|
286
|
+
val bytes = new Array[Byte](buffer.remaining())
|
|
287
|
+
buffer.get(bytes)
|
|
288
|
+
|
|
289
|
+
val result: Either[zio.blocks.schema.SchemaError, Record] = codec.decode(bytes)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Decoding Values from InputStream
|
|
293
|
+
|
|
294
|
+
Read and decode values from an input stream:
|
|
295
|
+
|
|
296
|
+
```scala
|
|
297
|
+
import zio.blocks.schema._
|
|
298
|
+
import zio.blocks.schema.avro._
|
|
299
|
+
import java.io.ByteArrayInputStream
|
|
300
|
+
|
|
301
|
+
case class Data(timestamp: Long, payload: String)
|
|
302
|
+
|
|
303
|
+
object Data {
|
|
304
|
+
implicit val schema: Schema[Data] = Schema.derived
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
val codec = Data.schema.derive(AvroFormat)
|
|
308
|
+
// Use encoded bytes from a previous encoding
|
|
309
|
+
val data = Data(System.currentTimeMillis(), "example payload")
|
|
310
|
+
val buffer = java.nio.ByteBuffer.allocate(256)
|
|
311
|
+
codec.encode(data, buffer)
|
|
312
|
+
buffer.flip()
|
|
313
|
+
val bytes = new Array[Byte](buffer.remaining())
|
|
314
|
+
buffer.get(bytes)
|
|
315
|
+
val input = new ByteArrayInputStream(bytes)
|
|
316
|
+
val result = codec.decode(input)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## AvroCodecDeriver
|
|
322
|
+
|
|
323
|
+
Configuration and derivation system for creating `AvroCodec[A]` instances from `Schema[A]`.
|
|
324
|
+
|
|
325
|
+
### Overview
|
|
326
|
+
|
|
327
|
+
`AvroCodecDeriver` implements the schema-driven derivation of Avro codecs. It automatically handles 27 primitive types and complex types (records, variants, sequences, maps), generating appropriate Avro schemas and encoder/decoder implementations.
|
|
328
|
+
|
|
329
|
+
### How Derivation Works
|
|
330
|
+
|
|
331
|
+
To create a codec from a schema:
|
|
332
|
+
|
|
333
|
+
```scala
|
|
334
|
+
import zio.blocks.schema._
|
|
335
|
+
import zio.blocks.schema.avro._
|
|
336
|
+
|
|
337
|
+
case class Person(name: String, age: Int)
|
|
338
|
+
|
|
339
|
+
object Person {
|
|
340
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
val codec = Person.schema.derive(AvroFormat)
|
|
344
|
+
// codec: AvroCodec[Person] = zio.blocks.schema.avro.AvroCodecDeriver$$anon$4@601650a
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Primitive Type Support
|
|
348
|
+
|
|
349
|
+
All 27 ZIO Schema primitives are supported:
|
|
350
|
+
- Numeric: `Byte`, `Short`, `Int`, `Long`, `Float`, `Double`, `BigInt`, `BigDecimal`
|
|
351
|
+
- Logical: `Boolean`, `Char`, `String`
|
|
352
|
+
- Temporal: `Instant`, `LocalDate`, `LocalDateTime`, `LocalTime`, `Duration`, `Period`, `Year`, `YearMonth`, `MonthDay`, `Month`, `DayOfWeek`, `ZonedDateTime`, `OffsetDateTime`, `OffsetTime`, `ZoneId`, `ZoneOffset`
|
|
353
|
+
- Special: `UUID`, `Currency`, `Unit`
|
|
354
|
+
|
|
355
|
+
### Record Type Support
|
|
356
|
+
|
|
357
|
+
Case classes (records) are fully supported. Each field becomes a named field in the Avro record schema:
|
|
358
|
+
|
|
359
|
+
```scala
|
|
360
|
+
import zio.blocks.schema._
|
|
361
|
+
import zio.blocks.schema.avro._
|
|
362
|
+
|
|
363
|
+
case class Address(street: String, city: String, zip: String)
|
|
364
|
+
|
|
365
|
+
object Address {
|
|
366
|
+
implicit val schema: Schema[Address] = Schema.derived
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
val codec = Address.schema.derive(AvroFormat)
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Variant Type Support
|
|
373
|
+
|
|
374
|
+
Sealed traits and sum types are encoded as Avro union types:
|
|
375
|
+
|
|
376
|
+
```scala
|
|
377
|
+
import zio.blocks.schema._
|
|
378
|
+
import zio.blocks.schema.avro._
|
|
379
|
+
|
|
380
|
+
sealed trait Status
|
|
381
|
+
case class Active(since: String) extends Status
|
|
382
|
+
case class Inactive(reason: String) extends Status
|
|
383
|
+
|
|
384
|
+
object Status {
|
|
385
|
+
implicit val schema: Schema[Status] = Schema.derived
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
val codec = Status.schema.derive(AvroFormat)
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## AvroFormat
|
|
394
|
+
|
|
395
|
+
Integration point with ZIO Schema's format system. Provides `BinaryFormat[AvroCodec]` to enable `Schema[A].derive(AvroFormat)` for any supported type.
|
|
396
|
+
|
|
397
|
+
### Using AvroFormat
|
|
398
|
+
|
|
399
|
+
To derive an Avro codec using the standard format:
|
|
400
|
+
|
|
401
|
+
```scala
|
|
402
|
+
import zio.blocks.schema._
|
|
403
|
+
import zio.blocks.schema.avro._
|
|
404
|
+
|
|
405
|
+
case class Sensor(id: Long, temperature: Double, humidity: Float)
|
|
406
|
+
|
|
407
|
+
object Sensor {
|
|
408
|
+
implicit val schema: Schema[Sensor] = Schema.derived
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
val codec = Sensor.schema.derive(AvroFormat)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
`AvroFormat` is a singleton object extending `BinaryFormat[AvroCodec]` with the MIME type `"application/avro"` and the `AvroCodecDeriver` as its derivation strategy.
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Error Handling
|
|
419
|
+
|
|
420
|
+
Avro decoding errors include location traces showing the path through nested structures where the error occurred.
|
|
421
|
+
|
|
422
|
+
### Understanding Error Traces
|
|
423
|
+
|
|
424
|
+
Errors render as paths like `.field[0].nested.value` showing exactly where decoding failed:
|
|
425
|
+
|
|
426
|
+
```scala
|
|
427
|
+
import zio.blocks.schema._
|
|
428
|
+
import zio.blocks.schema.avro._
|
|
429
|
+
|
|
430
|
+
case class Contact(emails: Seq[String])
|
|
431
|
+
|
|
432
|
+
object Contact {
|
|
433
|
+
implicit val schema: Schema[Contact] = Schema.derived
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
val codec = Contact.schema.derive(AvroFormat)
|
|
437
|
+
// Example invalid Avro bytes that will fail decoding
|
|
438
|
+
val invalidBytes: Array[Byte] = Array(0xFF.toByte, 0xFF.toByte)
|
|
439
|
+
|
|
440
|
+
val result = codec.decode(invalidBytes)
|
|
441
|
+
|
|
442
|
+
result match {
|
|
443
|
+
case Right(contact) => println(s"Success: $contact")
|
|
444
|
+
case Left(error) =>
|
|
445
|
+
println(s"Error: ${error.getMessage}")
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Zero-Overhead Error Handling
|
|
450
|
+
|
|
451
|
+
Errors use zero-overhead exceptions (no stack traces) for efficient error reporting in stream processing scenarios where errors are expected and handled inline.
|