@zio.dev/zio-blocks 0.0.33 → 0.0.51
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/guides/compile-time-resource-safety-with-scope.md +16 -17
- package/guides/getting-started-with-mux.md +1507 -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 +246 -165
- package/guides/telemetry-guide.md +1069 -0
- package/guides/zio-schema-migration.md +29 -22
- package/index.md +292 -50
- 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 +651 -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.md +158 -0
- package/reference/context.md +4 -4
- package/reference/datastar.md +346 -0
- package/reference/docs.md +1461 -345
- package/reference/endpoint/auth-type.md +146 -0
- package/reference/endpoint/endpoint.md +297 -0
- package/reference/endpoint/http-codec.md +249 -0
- package/reference/endpoint/index.md +825 -0
- package/reference/endpoint/path-codec.md +237 -0
- package/reference/endpoint/route-pattern.md +196 -0
- package/reference/endpoint/route-tree.md +111 -0
- package/reference/endpoint/segment-codec.md +212 -0
- package/reference/html.md +1120 -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 +855 -0
- package/reference/http-model/index.md +47 -0
- package/reference/http-model/model.md +1481 -0
- package/reference/http-model/schema.md +747 -0
- package/reference/maybe.md +826 -0
- package/reference/media-type.md +2 -2
- package/reference/mux.mdx +823 -0
- package/reference/openapi.md +1351 -0
- package/reference/resource-management/defer-handle.md +1 -1
- package/reference/resource-management/resource.md +31 -2
- package/reference/resource-management/scope.md +28 -12
- package/reference/resource-management/wire.md +3 -7
- 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 +151 -0
- package/reference/ringbuffer/mpsc.mdx +132 -0
- package/reference/ringbuffer/spmc.mdx +108 -0
- package/reference/ringbuffer/spsc.mdx +344 -0
- package/reference/{allows.md → schema/allows.md} +4 -4
- package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
- package/reference/{binding.md → schema/binding.md} +2 -3
- package/reference/schema/built-in-codecs/avro.md +451 -0
- package/reference/schema/built-in-codecs/bson.md +480 -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} +10 -10
- package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +151 -5
- package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
- package/reference/schema/format.md +92 -0
- package/reference/schema/index.md +50 -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} +165 -72
- 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.md → schema/schema.md} +12 -0
- 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 +533 -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 +146 -0
- package/reference/sql/db-tx.md +82 -0
- package/reference/sql/db-value.md +41 -0
- package/reference/sql/ddl.md +85 -0
- package/reference/sql/frag.md +254 -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 +353 -0
- package/reference/sql-zio.md +112 -0
- package/reference/streams/concurrent-operators.md +106 -0
- package/reference/streams/index.md +653 -0
- package/reference/streams/pipeline.md +718 -0
- package/reference/streams/reader.md +1284 -0
- package/reference/streams/scala-2-compatibility.md +55 -0
- package/reference/streams/sink.md +1426 -0
- package/reference/streams/stream.md +2526 -0
- package/reference/streams/writer.md +1045 -0
- package/reference/streams/zero-boxing.md +275 -0
- package/reference/telemetry.md +693 -0
- package/reference/typeid.md +5 -19
- package/sidebars.js +238 -43
- 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,480 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: bson
|
|
3
|
+
title: "BSON Codec Module"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`zio-blocks-schema-bson` is a **schema-driven BSON codec module** for serializing and deserializing Scala types to and from BSON (Binary JSON) format. It provides comprehensive encoding and decoding with support for 27 primitive types, records, variants, sequences, maps, and recursive types.
|
|
7
|
+
|
|
8
|
+
Core types: `BsonCodec`, `BsonEncoder`, `BsonDecoder`, `BsonSchemaCodec`.
|
|
9
|
+
|
|
10
|
+
The module integrates with org.bson to provide native BSON type support including special handling for `ObjectId`, `Decimal128`, and other BSON-specific types.
|
|
11
|
+
|
|
12
|
+
## Motivation
|
|
13
|
+
|
|
14
|
+
BSON is the native wire format for MongoDB and appears widely across modern applications. Manually writing BSON encoders and decoders is error-prone and repetitive, especially for complex types with records, nested structures, and recursive definitions. `zio-blocks-schema-bson` 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:
|
|
15
|
+
- Full BSON type support (documents, arrays, strings, numbers, ObjectId, Decimal128, timestamps, etc.)
|
|
16
|
+
- Configurable sum type handling (discriminator fields, wrapper types, or no discriminator)
|
|
17
|
+
- Flexible field name mapping for compatibility with MongoDB conventions
|
|
18
|
+
- Native ObjectId support with automatic detection and encoding
|
|
19
|
+
- Precise error reporting with location traces showing the path to errors
|
|
20
|
+
- Recursive type support with automatic cycle detection
|
|
21
|
+
- JVM support (not available for Scala.js)
|
|
22
|
+
|
|
23
|
+
Rather than writing custom encoders or relying on string-based configuration, you work with strongly-typed schemas that the compiler validates.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
Add the module to your `build.sbt`:
|
|
28
|
+
|
|
29
|
+
```sbt
|
|
30
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema-bson" % "0.0.51"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Note:** This module is JVM-only and is not available for Scala.js.
|
|
34
|
+
|
|
35
|
+
Supported Scala versions: 2.13.x and 3.x
|
|
36
|
+
|
|
37
|
+
## Introduction
|
|
38
|
+
|
|
39
|
+
The module provides a complete pipeline for BSON codec derivation and usage:
|
|
40
|
+
|
|
41
|
+
1. **Define your type** — Any Scala type with a `Schema` instance
|
|
42
|
+
2. **Derive a codec** — Use `BsonSchemaCodec.bsonCodec(schema)` to obtain a `BsonCodec[A]`
|
|
43
|
+
3. **Encode or decode** — Call `codec.encoder.toBsonValue()` or `codec.decoder.fromBsonValue()`
|
|
44
|
+
4. **Handle errors** — Catch `BsonDecoder.Error` with location traces showing where the error occurred
|
|
45
|
+
|
|
46
|
+
The derivation process is automatic for all supported types (all 27 primitives, records, variants, sequences, maps). The module provides flexible configuration for sum type handling, field mapping, and ObjectId support.
|
|
47
|
+
|
|
48
|
+
## How They Work Together
|
|
49
|
+
|
|
50
|
+
The BSON codec pipeline flows through these layers:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
1. User defines Schema[A] for their type
|
|
54
|
+
↓
|
|
55
|
+
2. BsonSchemaCodec.bsonCodec(schema) creates BsonCodec[A]
|
|
56
|
+
↓
|
|
57
|
+
3. BsonSchemaCodec derives Encoder and Decoder implementations
|
|
58
|
+
- For primitives: type-specific BSON encoders/decoders
|
|
59
|
+
- For records: field-by-field composition
|
|
60
|
+
- For variants: discriminator-based selection
|
|
61
|
+
- For sequences: array encoding/decoding
|
|
62
|
+
- For maps: document/object encoding/decoding
|
|
63
|
+
↓
|
|
64
|
+
4. BsonEncoder writes values to BsonValue or BsonWriter
|
|
65
|
+
BsonDecoder reads BsonValue or BsonReader to values
|
|
66
|
+
↓
|
|
67
|
+
5. BsonSchemaCodec.Config customizes behavior
|
|
68
|
+
- Sum type handling (discriminator, wrapper, or none)
|
|
69
|
+
- Field name mapping for MongoDB conventions
|
|
70
|
+
- ObjectId detection and native BSON encoding
|
|
71
|
+
- Extra field handling (ignore or error)
|
|
72
|
+
↓
|
|
73
|
+
6. BsonTrace provides location information in errors
|
|
74
|
+
Shows the path (.field[index].nested) to error location
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Typical workflow:**
|
|
78
|
+
|
|
79
|
+
A user type flows through the derivation and encoding pipeline as follows:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
User type (e.g., case class Person)
|
|
83
|
+
↓
|
|
84
|
+
Schema.derived (automatic via macro)
|
|
85
|
+
↓
|
|
86
|
+
BsonSchemaCodec.bsonCodec(schema, config) → BsonCodec[Person]
|
|
87
|
+
↓
|
|
88
|
+
Use codec.encoder.toBsonValue(person) to serialize
|
|
89
|
+
Use codec.decoder.fromBsonValue(bsonValue) to deserialize
|
|
90
|
+
↓
|
|
91
|
+
Handle BsonDecoder.Error with location trace on failure
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Common Patterns
|
|
95
|
+
|
|
96
|
+
This section shows practical patterns for working with BSON codecs in real-world scenarios.
|
|
97
|
+
|
|
98
|
+
### Pattern 1: Derive and Encode a Simple Record
|
|
99
|
+
|
|
100
|
+
To derive and use a BSON codec for a record type:
|
|
101
|
+
|
|
102
|
+
```scala
|
|
103
|
+
import zio.blocks.schema._
|
|
104
|
+
import zio.blocks.schema.bson._
|
|
105
|
+
import org.bson.BsonDocument
|
|
106
|
+
|
|
107
|
+
case class Person(name: String, age: Int, email: String)
|
|
108
|
+
|
|
109
|
+
object Person {
|
|
110
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
val codec = BsonSchemaCodec.bsonCodec(Person.schema)
|
|
114
|
+
val person = Person("Alice", 30, "alice@example.com")
|
|
115
|
+
val bsonValue = codec.encoder.toBsonValue(person)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Pattern 2: Decode BSON with Error Handling
|
|
119
|
+
|
|
120
|
+
When decoding BSON, errors include location traces showing where the problem occurred.
|
|
121
|
+
|
|
122
|
+
To decode a BSON document and handle errors with location information:
|
|
123
|
+
|
|
124
|
+
```scala
|
|
125
|
+
import zio.blocks.schema._
|
|
126
|
+
import zio.blocks.schema.bson._
|
|
127
|
+
import org.bson.{BsonDocument, BsonString, BsonInt32}
|
|
128
|
+
|
|
129
|
+
case class Employee(id: Int, name: String, salary: Double)
|
|
130
|
+
|
|
131
|
+
object Employee {
|
|
132
|
+
implicit val schema: Schema[Employee] = Schema.derived
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
val codec = BsonSchemaCodec.bsonCodec(Employee.schema)
|
|
136
|
+
val doc = new BsonDocument()
|
|
137
|
+
doc.put("id", new BsonInt32(123))
|
|
138
|
+
doc.put("name", new BsonString("Bob"))
|
|
139
|
+
doc.put("salary", new BsonInt32(50000)) // Wrong type - should be number with decimal
|
|
140
|
+
|
|
141
|
+
val result = codec.decoder.fromBsonValue(doc)
|
|
142
|
+
|
|
143
|
+
result match {
|
|
144
|
+
case Right(employee) => println(s"Decoded: $employee")
|
|
145
|
+
case Left(error) =>
|
|
146
|
+
println(s"Error at ${error.trace}: ${error.message}")
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Pattern 3: Configure Sum Type Handling
|
|
151
|
+
|
|
152
|
+
Sum types (sealed traits with variants) can be encoded in different ways. Configure which approach you prefer.
|
|
153
|
+
|
|
154
|
+
To configure how variants are encoded in BSON documents:
|
|
155
|
+
|
|
156
|
+
```scala
|
|
157
|
+
import zio.blocks.schema._
|
|
158
|
+
import zio.blocks.schema.bson._
|
|
159
|
+
|
|
160
|
+
sealed trait Status
|
|
161
|
+
case class Active(since: String) extends Status
|
|
162
|
+
case class Inactive(reason: String) extends Status
|
|
163
|
+
|
|
164
|
+
object Status {
|
|
165
|
+
implicit val schema: Schema[Status] = Schema.derived
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
val discriminatorConfig = BsonSchemaCodec.Config
|
|
169
|
+
.withSumTypeHandling(BsonSchemaCodec.SumTypeHandling.DiscriminatorField("type"))
|
|
170
|
+
|
|
171
|
+
val codec = BsonSchemaCodec.bsonCodec(Status.schema, discriminatorConfig)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Pattern 4: Use ObjectId with Native BSON Encoding
|
|
175
|
+
|
|
176
|
+
ObjectId fields can be encoded using BSON's native ObjectId type for compatibility with MongoDB.
|
|
177
|
+
|
|
178
|
+
To enable native BSON ObjectId encoding:
|
|
179
|
+
|
|
180
|
+
```scala
|
|
181
|
+
import zio.blocks.schema._
|
|
182
|
+
import zio.blocks.schema.bson._
|
|
183
|
+
import zio.blocks.schema.bson.ObjectIdSupport._
|
|
184
|
+
import org.bson.types.ObjectId
|
|
185
|
+
|
|
186
|
+
case class Document(id: ObjectId, title: String)
|
|
187
|
+
|
|
188
|
+
object Document {
|
|
189
|
+
implicit val schema: Schema[Document] = Schema.derived
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
val config = BsonSchemaCodec.Config.withNativeObjectId(true)
|
|
193
|
+
val codec = BsonSchemaCodec.bsonCodec(Document.schema, config)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## BsonCodec[A]
|
|
197
|
+
|
|
198
|
+
Main codec type for encoding and decoding values to and from BSON format. Contains an encoder and decoder for bidirectional serialization.
|
|
199
|
+
|
|
200
|
+
### Overview
|
|
201
|
+
|
|
202
|
+
`BsonCodec[A]` holds both a `BsonEncoder[A]` and `BsonDecoder[A]`, providing a complete solution for serializing and deserializing values. The codec is derived automatically from a `Schema[A]` using `BsonSchemaCodec.bsonCodec()`.
|
|
203
|
+
|
|
204
|
+
### Access Encoder and Decoder
|
|
205
|
+
|
|
206
|
+
To access the encoder and decoder from a codec:
|
|
207
|
+
|
|
208
|
+
```scala
|
|
209
|
+
import zio.blocks.schema._
|
|
210
|
+
import zio.blocks.schema.bson._
|
|
211
|
+
|
|
212
|
+
case class User(id: Int, name: String)
|
|
213
|
+
|
|
214
|
+
object User {
|
|
215
|
+
implicit val schema: Schema[User] = Schema.derived
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
val codec = BsonSchemaCodec.bsonCodec(User.schema)
|
|
219
|
+
val encoder = codec.encoder
|
|
220
|
+
val decoder = codec.decoder
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Encoding Values
|
|
224
|
+
|
|
225
|
+
Use the encoder to convert values to BsonValue:
|
|
226
|
+
|
|
227
|
+
```scala
|
|
228
|
+
import zio.blocks.schema._
|
|
229
|
+
import zio.blocks.schema.bson._
|
|
230
|
+
|
|
231
|
+
case class Product(name: String, price: Double)
|
|
232
|
+
|
|
233
|
+
object Product {
|
|
234
|
+
implicit val schema: Schema[Product] = Schema.derived
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
val codec = BsonSchemaCodec.bsonCodec(Product.schema)
|
|
238
|
+
val product = Product("Widget", 9.99)
|
|
239
|
+
val bsonValue = codec.encoder.toBsonValue(product)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Decoding Values
|
|
243
|
+
|
|
244
|
+
Use the decoder to convert BsonValue back to values:
|
|
245
|
+
|
|
246
|
+
```scala
|
|
247
|
+
import zio.blocks.schema._
|
|
248
|
+
import zio.blocks.schema.bson._
|
|
249
|
+
import org.bson.BsonValue
|
|
250
|
+
|
|
251
|
+
case class Item(name: String, quantity: Int)
|
|
252
|
+
|
|
253
|
+
object Item {
|
|
254
|
+
implicit val schema: Schema[Item] = Schema.derived
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
val codec = BsonSchemaCodec.bsonCodec(Item.schema)
|
|
258
|
+
// Create a BsonValue from an encoded item
|
|
259
|
+
val item = Item("Widget", 42)
|
|
260
|
+
val bsonValue = codec.encoder.toBsonValue(item)
|
|
261
|
+
|
|
262
|
+
val result: Either[BsonDecoder.Error, Item] = codec.decoder.fromBsonValue(bsonValue)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## BsonEncoder[A]
|
|
268
|
+
|
|
269
|
+
Trait for encoding Scala values to BSON format. Provides methods for writing to BsonWriter or converting to BsonValue directly.
|
|
270
|
+
|
|
271
|
+
### Overview
|
|
272
|
+
|
|
273
|
+
`BsonEncoder[A]` is responsible for converting values of type `A` to BSON representation. It supports skipping absent values and provides two encoding paths: direct BsonValue conversion or streaming to a BsonWriter.
|
|
274
|
+
|
|
275
|
+
### Key Methods
|
|
276
|
+
|
|
277
|
+
To encode a value to BsonValue:
|
|
278
|
+
|
|
279
|
+
```scala
|
|
280
|
+
import zio.blocks.schema.bson._
|
|
281
|
+
|
|
282
|
+
trait BsonEncoder[A] {
|
|
283
|
+
def encode(writer: org.bson.BsonWriter, value: A, ctx: BsonEncoder.EncoderContext): Unit
|
|
284
|
+
def toBsonValue(value: A): org.bson.BsonValue
|
|
285
|
+
def isAbsent(value: A): Boolean = false
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Contramap for Transformations
|
|
290
|
+
|
|
291
|
+
Transform the input before encoding using contramap:
|
|
292
|
+
|
|
293
|
+
```scala
|
|
294
|
+
import zio.blocks.schema.bson._
|
|
295
|
+
import zio.blocks.schema._
|
|
296
|
+
|
|
297
|
+
case class WrappedInt(value: Int)
|
|
298
|
+
object WrappedInt {
|
|
299
|
+
implicit val schema: Schema[WrappedInt] = Schema.derived
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
val codec = BsonSchemaCodec.bsonCodec(WrappedInt.schema)
|
|
303
|
+
// The codec provides encoder and decoder for bidirectional serialization
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## BsonDecoder[A]
|
|
309
|
+
|
|
310
|
+
Trait for decoding BSON values to Scala types. Provides error handling with precise location information.
|
|
311
|
+
|
|
312
|
+
### Overview
|
|
313
|
+
|
|
314
|
+
`BsonDecoder[A]` converts BSON values back to Scala types. It provides two decoding paths: from BsonValue or streaming from a BsonReader. Errors include location traces showing the path where decoding failed.
|
|
315
|
+
|
|
316
|
+
### Key Methods
|
|
317
|
+
|
|
318
|
+
To decode a BsonValue:
|
|
319
|
+
|
|
320
|
+
```scala
|
|
321
|
+
import zio.blocks.schema.bson._
|
|
322
|
+
import org.bson.BsonValue
|
|
323
|
+
|
|
324
|
+
trait BsonDecoder[A] {
|
|
325
|
+
def decodeUnsafe(reader: org.bson.BsonReader, trace: List[BsonTrace], ctx: BsonDecoder.BsonDecoderContext): A
|
|
326
|
+
def fromBsonValueUnsafe(value: BsonValue, trace: List[BsonTrace], ctx: BsonDecoder.BsonDecoderContext): A
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Error Handling
|
|
331
|
+
|
|
332
|
+
Errors provide location information for debugging:
|
|
333
|
+
|
|
334
|
+
```scala
|
|
335
|
+
import zio.blocks.schema.bson._
|
|
336
|
+
|
|
337
|
+
case class BsonError(message: String, trace: List[BsonTrace])
|
|
338
|
+
|
|
339
|
+
val trace = List(BsonTrace.Field("user"), BsonTrace.Array(0), BsonTrace.Field("age"))
|
|
340
|
+
val rendered = BsonTrace.render(trace) // ".user[0].age"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## BsonSchemaCodec
|
|
346
|
+
|
|
347
|
+
Configuration and derivation system for creating `BsonCodec[A]` instances from `Schema[A]`.
|
|
348
|
+
|
|
349
|
+
### Overview
|
|
350
|
+
|
|
351
|
+
`BsonSchemaCodec` provides the `bsonCodec()` method to derive codecs, along with configurable behavior for sum types, field mapping, and ObjectId handling.
|
|
352
|
+
|
|
353
|
+
### Configuration
|
|
354
|
+
|
|
355
|
+
The `Config` class controls codec behavior:
|
|
356
|
+
|
|
357
|
+
```scala
|
|
358
|
+
import zio.blocks.schema.bson._
|
|
359
|
+
|
|
360
|
+
val defaultConfig = BsonSchemaCodec.Config
|
|
361
|
+
val customConfig = defaultConfig
|
|
362
|
+
.withSumTypeHandling(BsonSchemaCodec.SumTypeHandling.DiscriminatorField("_type"))
|
|
363
|
+
.withClassNameMapping(_.toLowerCase)
|
|
364
|
+
.withIgnoreExtraFields(false)
|
|
365
|
+
.withNativeObjectId(true)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Sum Type Handling Options
|
|
369
|
+
|
|
370
|
+
Choose how variants are encoded in BSON documents:
|
|
371
|
+
|
|
372
|
+
```scala
|
|
373
|
+
import zio.blocks.schema.bson._
|
|
374
|
+
|
|
375
|
+
// Wrapper with class name field (default)
|
|
376
|
+
val wrapper = BsonSchemaCodec.SumTypeHandling.WrapperWithClassNameField
|
|
377
|
+
|
|
378
|
+
// Discriminator field approach
|
|
379
|
+
val discriminator = BsonSchemaCodec.SumTypeHandling.DiscriminatorField("type")
|
|
380
|
+
|
|
381
|
+
// No discriminator - encode variant directly
|
|
382
|
+
val none = BsonSchemaCodec.SumTypeHandling.NoDiscriminator
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Deriving Codecs
|
|
386
|
+
|
|
387
|
+
To create a codec from a schema:
|
|
388
|
+
|
|
389
|
+
```scala
|
|
390
|
+
import zio.blocks.schema._
|
|
391
|
+
import zio.blocks.schema.bson._
|
|
392
|
+
|
|
393
|
+
case class Person(name: String, age: Int)
|
|
394
|
+
|
|
395
|
+
object Person {
|
|
396
|
+
implicit val schema: Schema[Person] = Schema.derived
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
val codec = BsonSchemaCodec.bsonCodec(Person.schema)
|
|
400
|
+
// codec: BsonCodec[Person] = BsonCodec(
|
|
401
|
+
// encoder = zio.blocks.schema.bson.BsonSchemaCodec$$anon$4@77dddeaa,
|
|
402
|
+
// decoder = zio.blocks.schema.bson.BsonSchemaCodec$$anon$5@1692f6db
|
|
403
|
+
// )
|
|
404
|
+
val customCodec = BsonSchemaCodec.bsonCodec(Person.schema, BsonSchemaCodec.Config)
|
|
405
|
+
// customCodec: BsonCodec[Person] = BsonCodec(
|
|
406
|
+
// encoder = zio.blocks.schema.bson.BsonSchemaCodec$$anon$4@3497a5ea,
|
|
407
|
+
// decoder = zio.blocks.schema.bson.BsonSchemaCodec$$anon$5@2d26055c
|
|
408
|
+
// )
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## BsonTrace
|
|
414
|
+
|
|
415
|
+
Error location information for BSON decoding errors. Shows the path to the error in the document.
|
|
416
|
+
|
|
417
|
+
### Overview
|
|
418
|
+
|
|
419
|
+
`BsonTrace` elements build up a path through nested documents and arrays. When an error occurs, the complete trace is rendered as a path like `.field[0].nested.value`.
|
|
420
|
+
|
|
421
|
+
### Trace Elements
|
|
422
|
+
|
|
423
|
+
The two types of trace elements:
|
|
424
|
+
|
|
425
|
+
```scala
|
|
426
|
+
import zio.blocks.schema.bson._
|
|
427
|
+
|
|
428
|
+
sealed trait BsonTrace
|
|
429
|
+
|
|
430
|
+
case class Field(name: String) extends BsonTrace // Document field
|
|
431
|
+
case class Array(idx: Int) extends BsonTrace // Array index
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Rendering Traces
|
|
435
|
+
|
|
436
|
+
Convert a trace list to a human-readable path:
|
|
437
|
+
|
|
438
|
+
```scala
|
|
439
|
+
import zio.blocks.schema.bson._
|
|
440
|
+
|
|
441
|
+
val trace = List(
|
|
442
|
+
BsonTrace.Field("user"),
|
|
443
|
+
BsonTrace.Array(0),
|
|
444
|
+
BsonTrace.Field("email")
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
val path = BsonTrace.render(trace) // ".user[0].email"
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## ObjectIdSupport
|
|
453
|
+
|
|
454
|
+
Special support for `org.bson.types.ObjectId` with automatic detection for native BSON ObjectId encoding.
|
|
455
|
+
|
|
456
|
+
### Overview
|
|
457
|
+
|
|
458
|
+
`ObjectIdSupport` provides a Schema instance for ObjectId that enables native BSON ObjectId type encoding (12-byte format) when detected by BsonSchemaCodec.
|
|
459
|
+
|
|
460
|
+
### Using ObjectId
|
|
461
|
+
|
|
462
|
+
To use ObjectId in your schema, import ObjectIdSupport:
|
|
463
|
+
|
|
464
|
+
```scala
|
|
465
|
+
import zio.blocks.schema._
|
|
466
|
+
import zio.blocks.schema.bson.ObjectIdSupport._
|
|
467
|
+
import org.bson.types.ObjectId
|
|
468
|
+
|
|
469
|
+
case class MongoDocument(id: ObjectId, title: String)
|
|
470
|
+
|
|
471
|
+
object MongoDocument {
|
|
472
|
+
implicit val schema: Schema[MongoDocument] = Schema.derived
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// ObjectId will automatically use native BSON ObjectId encoding
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### ObjectId and Configuration
|
|
479
|
+
|
|
480
|
+
When ObjectIdSupport is imported, ObjectId automatically uses native BSON encoding regardless of the `useNativeObjectId` configuration setting.
|