@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
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: reflect-transformer
|
|
3
|
+
title: "ReflectTransformer"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`ReflectTransformer[F, G]` rewrites a `Reflect[F, A]` tree into a `Reflect[G, A]` tree, changing the binding-metadata type constructor from `F` to `G` at every node while leaving the shape — field names, type IDs, docs, modifiers, defaults, examples — untouched. `Reflect#transform` walks the tree and recurses into fields, cases, elements, and keys/values for you; a `ReflectTransformer` only has to say how to rebuild the metadata-bearing leaf of each node kind once its children are already transformed.
|
|
7
|
+
|
|
8
|
+
Three things in the codebase are built on it: stripping bindings to serialize a [`Schema`](./schema.md) as a [`DynamicSchema`](./dynamic-schema.md), attaching bindings back with `RebindTransformer`, and [type class derivation](./type-class-derivation.md), which pairs each node's binding with a derived instance. This page covers all three, plus `OnlyMetadata`, the base class most transformers use instead of implementing the full interface.
|
|
9
|
+
|
|
10
|
+
## Design & Structure
|
|
11
|
+
|
|
12
|
+
`ReflectTransformer` declares one method per [`Reflect`](./reflect.md) node kind — seven of the eight; `Deferred` is handled separately (see [Cycle Safety](#cycle-safety-and-the-transform-cache)) because it has no metadata of its own to transform. `transformRecord` is representative of all seven — each takes the node's already-transformed children plus its untouched shape fields, and returns a `Lazy` of the rebuilt node:
|
|
13
|
+
|
|
14
|
+
```scala
|
|
15
|
+
trait ReflectTransformer[-F[_, _], G[_, _]] {
|
|
16
|
+
def transformRecord[A](
|
|
17
|
+
path: DynamicOptic,
|
|
18
|
+
fields: IndexedSeq[Term[G, A, ?]],
|
|
19
|
+
typeId: TypeId[A],
|
|
20
|
+
metadata: F[BindingType.Record, A],
|
|
21
|
+
doc: Doc,
|
|
22
|
+
modifiers: Seq[Modifier.Reflect],
|
|
23
|
+
storedDefaultValue: Option[DynamicValue],
|
|
24
|
+
storedExamples: collection.immutable.Seq[DynamicValue]
|
|
25
|
+
): Lazy[Reflect.Record[G, A]]
|
|
26
|
+
|
|
27
|
+
// ...one more method per remaining node kind, same shape
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The other six follow the identical pattern — a `path`, the already-transformed children, the shape fields, and the still-untransformed `metadata: F[...]` — differing only in which children they carry and which `Reflect` node they return:
|
|
32
|
+
|
|
33
|
+
| Node kind | Method | Transformed children it receives |
|
|
34
|
+
| ---------- | -------- | ----------------------------------- |
|
|
35
|
+
| `Record` | `transformRecord` | `fields: IndexedSeq[Term[G, A, ?]]` |
|
|
36
|
+
| `Variant` | `transformVariant` | `cases: IndexedSeq[Term[G, A, ? <: A]]` |
|
|
37
|
+
| `Sequence` | `transformSequence` | `element: Reflect[G, A]` |
|
|
38
|
+
| `Map` | `transformMap` | `key: Reflect[G, Key]`, `value: Reflect[G, Value]` |
|
|
39
|
+
| `Dynamic` | `transformDynamic` | none — `DynamicValue` has no children |
|
|
40
|
+
| `Primitive` | `transformPrimitive` | none |
|
|
41
|
+
| `Wrapper` | `transformWrapper` | `wrapped: Reflect[G, B]` |
|
|
42
|
+
|
|
43
|
+
Every result is wrapped in [`Lazy`](./lazy.md) because a transformer built for a recursive schema must be able to build a node before its own children are fully forced.
|
|
44
|
+
|
|
45
|
+
## `OnlyMetadata` — The Common Case
|
|
46
|
+
|
|
47
|
+
Most transformers only need to change the metadata and leave every field, case, and element exactly as it already was. `ReflectTransformer.OnlyMetadata[F, G]` implements all seven `transformX` methods for you in terms of one method:
|
|
48
|
+
|
|
49
|
+
```scala
|
|
50
|
+
abstract class OnlyMetadata[F[_, _], G[_, _]] extends ReflectTransformer[F, G] {
|
|
51
|
+
def transformMetadata[K, A](f: F[K, A]): Lazy[G[K, A]]
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Each `transformX` implementation `OnlyMetadata` provides is one line: transform the metadata, then rebuild the same node with the same children and shape, swapping in the new metadata. `HasBinding[F]` — the type class that extracts a `Binding[T, A]` out of an arbitrary `F[T, A]` — is itself a `ReflectTransformer.OnlyMetadata[F, Binding]` whose `transformMetadata` calls the one method a `HasBinding[F]` instance supplies.
|
|
56
|
+
|
|
57
|
+
## Stripping Bindings: `ReflectTransformer.noBinding`
|
|
58
|
+
|
|
59
|
+
`ReflectTransformer.noBinding[F]()` is a predefined, stateless transformer that discards whatever metadata `F` holds and replaces it with the singleton `NoBinding` value, regardless of what `F` was. It is what `Reflect#noBinding` and, through it, `Schema#toDynamicSchema` use to turn a bound, operational schema into a pure-data one safe to serialize:
|
|
60
|
+
|
|
61
|
+
```scala
|
|
62
|
+
import zio.blocks.schema._
|
|
63
|
+
|
|
64
|
+
case class Person(name: String, age: Int)
|
|
65
|
+
object Person {
|
|
66
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Reflect.Bound[Person] -> Reflect.Unbound[Person], via ReflectTransformer.noBinding()
|
|
70
|
+
val unbound: Reflect.Unbound[Person] = Person.schema.reflect.noBinding
|
|
71
|
+
|
|
72
|
+
// The public entry point most code uses instead
|
|
73
|
+
val dynamicSchema: DynamicSchema = Person.schema.toDynamicSchema
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Because `ReflectTransformer.noBinding` never inspects the metadata it's replacing, one singleton instance (cast per call) serves every `F`, with no allocation per use.
|
|
77
|
+
|
|
78
|
+
## Attaching Bindings: `RebindTransformer`
|
|
79
|
+
|
|
80
|
+
`RebindTransformer` is the transformer in the opposite direction — `NoBinding` to `Binding` — that [`DynamicSchema#rebind`](./dynamic-schema.md) constructs internally to turn a deserialized, pure-data schema back into an operational one. It is `private[schema]`; the public surface is `DynamicSchema#rebind`, which builds one for you from a [`BindingResolver`](./binding-resolver.md):
|
|
81
|
+
|
|
82
|
+
```scala
|
|
83
|
+
import zio.blocks.schema._
|
|
84
|
+
import zio.blocks.schema.binding._
|
|
85
|
+
|
|
86
|
+
case class Person(name: String, age: Int)
|
|
87
|
+
object Person {
|
|
88
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
val dynamicSchema: DynamicSchema = Person.schema.toDynamicSchema
|
|
92
|
+
|
|
93
|
+
val resolver = BindingResolver.defaults.bind(Binding.of[Person])
|
|
94
|
+
val rebound: Schema[Person] = dynamicSchema.rebind[Person](resolver)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Unlike `ReflectTransformer.noBinding`, `RebindTransformer` implements every `transformX` method individually rather than extending `OnlyMetadata` — each one must call a different resolver lookup (`resolveRecord`, `resolveVariant`, `resolveSeqFor`, `resolveMapFor`, `resolveDynamic`, `resolvePrimitive`, `resolveWrapper`) and fail in a way that names which kind of binding was missing.
|
|
98
|
+
|
|
99
|
+
### `RebindException`
|
|
100
|
+
|
|
101
|
+
A resolver that's missing a binding for some type in the tree makes `DynamicSchema#rebind` throw `RebindException` rather than return quietly, since a `Schema` with an unresolved node isn't safe to hand back:
|
|
102
|
+
|
|
103
|
+
```scala
|
|
104
|
+
import zio.blocks.schema._
|
|
105
|
+
import zio.blocks.schema.binding._
|
|
106
|
+
|
|
107
|
+
case class Person(name: String, age: Int)
|
|
108
|
+
object Person {
|
|
109
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
val dynamicSchema = Person.schema.toDynamicSchema
|
|
113
|
+
|
|
114
|
+
try dynamicSchema.rebind[Person](BindingResolver.empty)
|
|
115
|
+
catch {
|
|
116
|
+
case e: RebindException =>
|
|
117
|
+
// path: the DynamicOptic where the lookup failed
|
|
118
|
+
// typeId: the missing type
|
|
119
|
+
// expectedKind: "Record", "Variant", "Sequence", "Map", "Dynamic", "Primitive", or "Wrapper"
|
|
120
|
+
println(s"${e.expectedKind} binding missing for ${e.typeId.fullName} at ${e.path}")
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Writing a Full `ReflectTransformer`: Type Class Derivation
|
|
125
|
+
|
|
126
|
+
`OnlyMetadata` covers every transformer described so far, but the interface exists in full for a reason: automatic type class derivation implements every `transformX` method directly, because deriving an instance for a `Record` needs the already-derived instances of its *fields*, not just a metadata swap. `DerivationBuilder.derive` walks a bound schema with a custom `ReflectTransformer[Binding, BindingInstance[TC, ?, ?]]` that, at each node, either substitutes a user-supplied override or invokes a [`Deriver[TC]`](./type-class-derivation.md) with the node's already-transformed children, then pairs the result with the original binding. This is the pattern to reach for when a transformation genuinely depends on more than the metadata at a single node.
|
|
127
|
+
|
|
128
|
+
## Cycle Safety and the Transform Cache
|
|
129
|
+
|
|
130
|
+
A recursive schema — one whose `Reflect` tree refers back to itself — reaches that self-reference through a `Reflect.Deferred` node. `Deferred#transform` doesn't call any `transformX` method; it looks up the pair `(this Deferred, this transformer)` in a per-thread memoization map first, and only builds a new deferred node on a miss. This is what makes `Reflect#transform` terminate on a recursive schema, and what lets a `Deferred` reached through multiple paths share one transformed result instead of being rebuilt repeatedly.
|
|
131
|
+
|
|
132
|
+
The two public entry points — `Reflect#noBinding` and `DynamicSchema#rebind` — wrap their call in an internal scope that clears this cache once the outermost `Reflect#transform` finishes, so a transformer's captured state (override maps, resolvers) doesn't stay pinned on the thread once its call returns. Reaching either entry point is enough to get this for free; it isn't something you configure.
|
|
133
|
+
|
|
134
|
+
## See Also
|
|
135
|
+
|
|
136
|
+
- [Reflect](./reflect.md) — the tree `ReflectTransformer` rewrites, and its eight node kinds
|
|
137
|
+
- [Binding](./binding.md) — what `F`/`G` are in practice: `Binding` and `NoBinding`
|
|
138
|
+
- [BindingResolver](./binding-resolver.md) — the lookup `RebindTransformer` delegates to
|
|
139
|
+
- [DynamicSchema](./dynamic-schema.md) — `Schema#toDynamicSchema` and `DynamicSchema#rebind`, the public entry points
|
|
140
|
+
- [Type Class Derivation](./type-class-derivation.md) — the fullest real use of the interface
|
|
@@ -39,13 +39,13 @@ The bidirectional data flow looks like this:
|
|
|
39
39
|
`As` is part of `zio-blocks-schema`:
|
|
40
40
|
|
|
41
41
|
```scala
|
|
42
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.
|
|
42
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.55"
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
For Scala.js and Scala Native, use `%%%`:
|
|
46
46
|
|
|
47
47
|
```scala
|
|
48
|
-
libraryDependencies += "dev.zio" %%% "zio-blocks-schema" % "0.0.
|
|
48
|
+
libraryDependencies += "dev.zio" %%% "zio-blocks-schema" % "0.0.55"
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Supported Scala versions: 2.13.x and 3.x.
|
|
@@ -89,7 +89,7 @@ manualAs.from(Long.MaxValue)
|
|
|
89
89
|
// SchemaError(
|
|
90
90
|
// List(
|
|
91
91
|
// ConversionFailed(
|
|
92
|
-
// source = DynamicOptic(
|
|
92
|
+
// source = DynamicOptic(ArraySeq()),
|
|
93
93
|
// details = "overflow",
|
|
94
94
|
// cause = None
|
|
95
95
|
// )
|
|
@@ -213,7 +213,7 @@ boxAs.from(LongBox(Long.MaxValue))
|
|
|
213
213
|
// SchemaError(
|
|
214
214
|
// List(
|
|
215
215
|
// ConversionFailed(
|
|
216
|
-
// source = DynamicOptic(
|
|
216
|
+
// source = DynamicOptic(ArraySeq()),
|
|
217
217
|
// details = "Value 9223372036854775807 is out of range for Int [-2147483648, 2147483647]",
|
|
218
218
|
// cause = None
|
|
219
219
|
// )
|
|
@@ -240,7 +240,7 @@ trait As[A, B] {
|
|
|
240
240
|
|
|
241
241
|
```scala
|
|
242
242
|
val revAs: As[LongBox, IntBox] = boxAs.reverse
|
|
243
|
-
// revAs: As[LongBox, IntBox] = zio.blocks.schema.As$$anon$1@
|
|
243
|
+
// revAs: As[LongBox, IntBox] = zio.blocks.schema.As$$anon$1@50968506
|
|
244
244
|
|
|
245
245
|
revAs.into(LongBox(5L))
|
|
246
246
|
// res11: Either[SchemaError, IntBox] = Right(IntBox(5))
|
|
@@ -302,7 +302,7 @@ We import `As.reverseInto` and use it to obtain the reverse `Into[Int, String]`:
|
|
|
302
302
|
import As.reverseInto
|
|
303
303
|
|
|
304
304
|
val intToStr: Into[Int, String] = reverseInto[String, Int]
|
|
305
|
-
// intToStr: Into[Int, String] = zio.blocks.schema.AsLowPriorityImplicits$$Lambda
|
|
305
|
+
// intToStr: Into[Int, String] = zio.blocks.schema.AsLowPriorityImplicits$$Lambda/0x0000000027f8bc38@794d4993
|
|
306
306
|
intToStr.into(42)
|
|
307
307
|
// res14: Either[SchemaError, String] = Right("42")
|
|
308
308
|
```
|
|
@@ -387,7 +387,7 @@ numericAs.from(LongModel(Long.MaxValue))
|
|
|
387
387
|
// SchemaError(
|
|
388
388
|
// List(
|
|
389
389
|
// ConversionFailed(
|
|
390
|
-
// source = DynamicOptic(
|
|
390
|
+
// source = DynamicOptic(ArraySeq()),
|
|
391
391
|
// details = "Value 9223372036854775807 is out of range for Int [-2147483648, 2147483647]",
|
|
392
392
|
// cause = None
|
|
393
393
|
// )
|
|
@@ -584,4 +584,4 @@ result
|
|
|
584
584
|
|
|
585
585
|
`As[A, B]` is defined in `zio.blocks.schema` alongside `Into[A, B]`. Because `As` is a subtype of `Into`, the two type classes compose naturally: you can derive an outer `As` from inner `As` instances, or mix `As` and custom `Into` instances when some fields need one-way or custom logic.
|
|
586
586
|
|
|
587
|
-
For a full reference on one-way conversions and the derivation rules that `As` builds on, see [Into](
|
|
587
|
+
For a full reference on one-way conversions and the derivation rules that `As` builds on, see [Into](into.md).
|
|
@@ -18,7 +18,7 @@ Schema evolution is the process of changing data structures over time while keep
|
|
|
18
18
|
|
|
19
19
|
## `Into[A, B]` — One-Way Conversion
|
|
20
20
|
|
|
21
|
-
[`Into[A, B]`](
|
|
21
|
+
[`Into[A, B]`](into.md) converts a value of type `A` to `Either[SchemaError, B]`. It is the right choice whenever the migration is asymmetric — for example, when adding a field with a default value, removing a field, or transforming data in a way that cannot be reversed.
|
|
22
22
|
|
|
23
23
|
Typical use cases:
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@ Typical use cases:
|
|
|
28
28
|
|
|
29
29
|
## `As[A, B]` — Bidirectional Round-Trip
|
|
30
30
|
|
|
31
|
-
[`As[A, B]`](
|
|
31
|
+
[`As[A, B]`](as.md) extends `Into[A, B]` with a `from(b: B): Either[SchemaError, A]` reverse direction. It guarantees that `A → B → A` restores the original value (within the constraints of numeric precision and optional fields). Use `As` when both sides of the conversion must remain in sync.
|
|
32
32
|
|
|
33
33
|
Typical use cases:
|
|
34
34
|
|
|
@@ -69,13 +69,13 @@ Compare this to a manual implementation:
|
|
|
69
69
|
`Into` is part of the `zio-blocks-schema` module:
|
|
70
70
|
|
|
71
71
|
```scala
|
|
72
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.
|
|
72
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.55"
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
For Scala.js:
|
|
76
76
|
|
|
77
77
|
```scala
|
|
78
|
-
libraryDependencies += "dev.zio" %%% "zio-blocks-schema" % "0.0.
|
|
78
|
+
libraryDependencies += "dev.zio" %%% "zio-blocks-schema" % "0.0.55"
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
Supported Scala versions: 2.13.x and 3.x.
|
|
@@ -241,7 +241,7 @@ Into[Long, Int].into(Long.MaxValue)
|
|
|
241
241
|
// SchemaError(
|
|
242
242
|
// List(
|
|
243
243
|
// ConversionFailed(
|
|
244
|
-
// source = DynamicOptic(
|
|
244
|
+
// source = DynamicOptic(ArraySeq()),
|
|
245
245
|
// details = "Value 9223372036854775807 is out of range for Int [-2147483648, 2147483647]",
|
|
246
246
|
// cause = None
|
|
247
247
|
// )
|
|
@@ -253,7 +253,7 @@ Into[Double, Int].into(3.14)
|
|
|
253
253
|
// SchemaError(
|
|
254
254
|
// List(
|
|
255
255
|
// ConversionFailed(
|
|
256
|
-
// source = DynamicOptic(
|
|
256
|
+
// source = DynamicOptic(ArraySeq()),
|
|
257
257
|
// details = "Value 3.14 cannot be precisely converted to Int",
|
|
258
258
|
// cause = None
|
|
259
259
|
// )
|
|
@@ -399,7 +399,7 @@ conv.into(Raw(Long.MaxValue))
|
|
|
399
399
|
// SchemaError(
|
|
400
400
|
// List(
|
|
401
401
|
// ConversionFailed(
|
|
402
|
-
// source = DynamicOptic(
|
|
402
|
+
// source = DynamicOptic(ArraySeq()),
|
|
403
403
|
// details = "Value 9223372036854775807 is out of range for Int [-2147483648, 2147483647]",
|
|
404
404
|
// cause = None
|
|
405
405
|
// )
|
|
@@ -623,7 +623,7 @@ validate.into(PersonRaw("Bob", 200))
|
|
|
623
623
|
// SchemaError(
|
|
624
624
|
// List(
|
|
625
625
|
// ConversionFailed(
|
|
626
|
-
// source = DynamicOptic(
|
|
626
|
+
// source = DynamicOptic(ArraySeq()),
|
|
627
627
|
// details = "Validation failed for field 'age': NonEmptyChunk(200 did not satisfy between(0, 150))",
|
|
628
628
|
// cause = None
|
|
629
629
|
// )
|
|
@@ -854,7 +854,7 @@ result
|
|
|
854
854
|
// SchemaError(
|
|
855
855
|
// List(
|
|
856
856
|
// ExpectationMismatch(
|
|
857
|
-
// source = DynamicOptic(
|
|
857
|
+
// source = DynamicOptic(ArraySeq()),
|
|
858
858
|
// expectation = "Expected a record"
|
|
859
859
|
// )
|
|
860
860
|
// )
|
|
@@ -915,7 +915,7 @@ backToMap
|
|
|
915
915
|
|
|
916
916
|
## Related Type: `As[A, B]`
|
|
917
917
|
|
|
918
|
-
`As[A, B]` extends `Into[A, B]` with a reverse direction, enabling round-trip safe bidirectional conversions. Because `As` must guarantee that `A → B → A` restores the original value, it applies stricter derivation constraints than `Into`. See [As](
|
|
918
|
+
`As[A, B]` extends `Into[A, B]` with a reverse direction, enabling round-trip safe bidirectional conversions. Because `As` must guarantee that `A → B → A` restores the original value, it applies stricter derivation constraints than `Into`. See [As](as.md) for the full reference.
|
|
919
919
|
|
|
920
920
|
## Best Practices
|
|
921
921
|
|