@zio.dev/zio-blocks 0.0.33 → 0.0.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/adr/2026-07-18-data-migration.md +123 -0
  2. package/guides/async-getting-started.md +687 -0
  3. package/guides/compile-time-resource-safety-with-scope.md +21 -16
  4. package/guides/getting-started-with-mux.md +1395 -0
  5. package/guides/query-dsl-extending.md +161 -102
  6. package/guides/query-dsl-fluent-builder.md +217 -157
  7. package/guides/query-dsl-reified-optics.md +12 -10
  8. package/guides/query-dsl-sql.md +640 -165
  9. package/guides/sql-checked-interpolation.md +173 -0
  10. package/guides/sql-transactions.md +286 -0
  11. package/guides/telemetry-guide.md +1130 -0
  12. package/guides/zio-schema-migration.md +29 -22
  13. package/index.md +248 -389
  14. package/package.json +1 -1
  15. package/plans/config-follow-up-prs.md +188 -0
  16. package/plans/config-pr-assessment-roadmap.md +310 -0
  17. package/reference/MuxDataFlow.jsx +250 -0
  18. package/reference/async.md +1499 -0
  19. package/reference/chunk.md +3533 -308
  20. package/reference/codegen/case-class.md +436 -0
  21. package/reference/codegen/emitter-config.md +383 -0
  22. package/reference/codegen/examples.md +664 -0
  23. package/reference/codegen/field.md +316 -0
  24. package/reference/codegen/index.md +317 -0
  25. package/reference/codegen/scala-emitter.md +392 -0
  26. package/reference/codegen/scala-file.md +276 -0
  27. package/reference/codegen/sealed-trait.md +408 -0
  28. package/reference/codegen/type-definition.md +340 -0
  29. package/reference/codegen/type-ref.md +201 -0
  30. package/reference/combinators.md +347 -117
  31. package/reference/config/config-decoder.md +460 -0
  32. package/reference/config/config-source.md +489 -0
  33. package/reference/config/errors.md +278 -0
  34. package/reference/config/flags.md +369 -0
  35. package/reference/config/formats.md +314 -0
  36. package/reference/config/index.md +304 -0
  37. package/reference/config/rollout.md +336 -0
  38. package/reference/context.md +9 -52
  39. package/reference/data-migration.md +269 -0
  40. package/reference/datastar/attributes.md +302 -0
  41. package/reference/datastar/events.md +234 -0
  42. package/reference/datastar/index.md +256 -0
  43. package/reference/datastar/signals.md +230 -0
  44. package/reference/datastar/sse.md +295 -0
  45. package/reference/datastar.md +346 -0
  46. package/reference/docs.md +1461 -345
  47. package/reference/endpoint/auth-type.md +146 -0
  48. package/reference/endpoint/bulk-creation.md +96 -0
  49. package/reference/endpoint/endpoint.md +297 -0
  50. package/reference/endpoint/http-codec.md +249 -0
  51. package/reference/endpoint/index.md +745 -0
  52. package/reference/endpoint/path-codec.md +225 -0
  53. package/reference/endpoint/route-pattern.md +194 -0
  54. package/reference/endpoint/route-tree.md +111 -0
  55. package/reference/endpoint/segment-codec.md +199 -0
  56. package/reference/html.md +1424 -0
  57. package/reference/htmx/attribute-values.md +359 -0
  58. package/reference/htmx/hx-encoding.md +111 -0
  59. package/reference/htmx/hx-params.md +204 -0
  60. package/reference/htmx/hx-swap.md +276 -0
  61. package/reference/htmx/hx-sync.md +251 -0
  62. package/reference/htmx/hx-target.md +314 -0
  63. package/reference/htmx/hx-trigger.md +457 -0
  64. package/reference/htmx/hx-url-update.md +239 -0
  65. package/reference/htmx/index.md +807 -0
  66. package/reference/htmx/response-headers.md +240 -0
  67. package/reference/http-model/headers.md +735 -0
  68. package/reference/http-model/index.md +49 -0
  69. package/reference/http-model/model.md +1517 -0
  70. package/reference/http-model/schema-codecs.md +522 -0
  71. package/reference/http-model/schema.md +750 -0
  72. package/reference/http-model/server-sent-event.md +341 -0
  73. package/reference/jwt.md +195 -0
  74. package/reference/maybe.md +943 -0
  75. package/reference/media-type.md +2 -2
  76. package/reference/mux.md +254 -0
  77. package/reference/mux.mdx +828 -0
  78. package/reference/openapi.md +1351 -0
  79. package/reference/projection.md +654 -0
  80. package/reference/resource-management/defer-handle.md +1 -1
  81. package/reference/resource-management/resource.md +31 -98
  82. package/reference/resource-management/scope.md +28 -220
  83. package/reference/resource-management/wire.md +5 -55
  84. package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
  85. package/reference/ringbuffer/MpscDiagram.jsx +618 -0
  86. package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
  87. package/reference/ringbuffer/SpscDiagram.jsx +677 -0
  88. package/reference/ringbuffer/advanced.mdx +109 -0
  89. package/reference/ringbuffer/index.mdx +145 -0
  90. package/reference/ringbuffer/mpmc.mdx +185 -0
  91. package/reference/ringbuffer/mpsc.mdx +164 -0
  92. package/reference/ringbuffer/spmc.mdx +108 -0
  93. package/reference/ringbuffer/spsc.mdx +416 -0
  94. package/reference/{allows.md → schema/allows.md} +4 -100
  95. package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
  96. package/reference/{binding.md → schema/binding.md} +3 -4
  97. package/reference/schema/built-in-codecs/avro.md +451 -0
  98. package/reference/schema/built-in-codecs/bson.md +510 -0
  99. package/reference/schema/built-in-codecs/csv.md +564 -0
  100. package/reference/schema/built-in-codecs/index.md +77 -0
  101. package/reference/schema/built-in-codecs/json/index.md +295 -0
  102. package/reference/schema/built-in-codecs/json/json-config.md +217 -0
  103. package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
  104. package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
  105. package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
  106. package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
  107. package/reference/schema/built-in-codecs/messagepack.md +508 -0
  108. package/reference/schema/built-in-codecs/thrift.md +433 -0
  109. package/reference/schema/built-in-codecs/toon.md +1078 -0
  110. package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
  111. package/reference/schema/built-in-codecs/yaml.md +552 -0
  112. package/reference/{codec.md → schema/codec.md} +11 -11
  113. package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +196 -5
  114. package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
  115. package/reference/schema/format.md +92 -0
  116. package/reference/schema/index.md +52 -0
  117. package/reference/schema/migration.md +297 -0
  118. package/reference/{modifier.md → schema/modifier.md} +58 -7
  119. package/reference/{optics.md → schema/optics.md} +2 -2
  120. package/reference/{patch.md → schema/patch.md} +1 -1
  121. package/{path-interpolator.md → reference/schema/path-interpolator.md} +167 -72
  122. package/reference/schema/reflect-transformer.md +140 -0
  123. package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
  124. package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
  125. package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
  126. package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
  127. package/reference/schema/schema-search.md +263 -0
  128. package/reference/{schema.md → schema/schema.md} +22 -2
  129. package/reference/{structural-types.md → schema/structural-types.md} +1 -1
  130. package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
  131. package/reference/smithy.md +1032 -0
  132. package/reference/sql/db-codec-deriver.md +71 -0
  133. package/reference/sql/db-codec.md +687 -0
  134. package/reference/sql/db-con.md +271 -0
  135. package/reference/sql/db-connection.md +153 -0
  136. package/reference/sql/db-param-writer.md +77 -0
  137. package/reference/sql/db-param.md +66 -0
  138. package/reference/sql/db-result-reader.md +148 -0
  139. package/reference/sql/db-tx.md +114 -0
  140. package/reference/sql/db-value.md +41 -0
  141. package/reference/sql/ddl.md +85 -0
  142. package/reference/sql/frag.md +288 -0
  143. package/reference/sql/index.md +341 -0
  144. package/reference/sql/repo.md +600 -0
  145. package/reference/sql/sql-dialect.md +73 -0
  146. package/reference/sql/sql-logger.md +62 -0
  147. package/reference/sql/sql-name-mapper.md +70 -0
  148. package/reference/sql/table-metadata.md +134 -0
  149. package/reference/sql/table.md +448 -0
  150. package/reference/sql/transactor-zio.md +399 -0
  151. package/reference/sql/transactor.md +363 -0
  152. package/reference/sql-zio.md +112 -0
  153. package/reference/streams/core/index.md +32 -0
  154. package/reference/streams/core/pipeline.md +854 -0
  155. package/reference/streams/core/sink.md +1404 -0
  156. package/reference/streams/core/stream.md +3236 -0
  157. package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
  158. package/reference/streams/execution-and-compatibility/index.md +35 -0
  159. package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
  160. package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
  161. package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
  162. package/reference/streams/index.md +726 -0
  163. package/reference/streams/primitives/index.md +30 -0
  164. package/reference/streams/primitives/reader.md +1992 -0
  165. package/reference/streams/primitives/writer.md +1201 -0
  166. package/reference/telemetry/common/any-value.md +90 -0
  167. package/reference/telemetry/common/attribute-key.md +87 -0
  168. package/reference/telemetry/common/attributes.md +118 -0
  169. package/reference/telemetry/common/index.md +39 -0
  170. package/reference/telemetry/common/instrumentation-scope.md +24 -0
  171. package/reference/telemetry/common/resource.md +34 -0
  172. package/reference/telemetry/index.md +311 -0
  173. package/reference/telemetry/logging/index.md +197 -0
  174. package/reference/telemetry/logging/log-enrichment.md +72 -0
  175. package/reference/telemetry/logging/log-formatter.md +100 -0
  176. package/reference/telemetry/logging/log-record-processor.md +56 -0
  177. package/reference/telemetry/logging/log-record.md +44 -0
  178. package/reference/telemetry/logging/log-writer.md +64 -0
  179. package/reference/telemetry/logging/logger-provider.md +142 -0
  180. package/reference/telemetry/logging/logger.md +83 -0
  181. package/reference/telemetry/logging/severity.md +62 -0
  182. package/reference/telemetry/metrics/index.md +150 -0
  183. package/reference/telemetry/metrics/instruments.md +183 -0
  184. package/reference/telemetry/metrics/labeled-instruments.md +74 -0
  185. package/reference/telemetry/metrics/meter-provider.md +76 -0
  186. package/reference/telemetry/metrics/meter.md +98 -0
  187. package/reference/telemetry/metrics/metric-data.md +57 -0
  188. package/reference/telemetry/otel/custom-exporter.md +216 -0
  189. package/reference/telemetry/otel/index.md +212 -0
  190. package/reference/telemetry/tracing/index.md +155 -0
  191. package/reference/telemetry/tracing/sampler.md +89 -0
  192. package/reference/telemetry/tracing/span-builder.md +57 -0
  193. package/reference/telemetry/tracing/span-context.md +39 -0
  194. package/reference/telemetry/tracing/span-data.md +32 -0
  195. package/reference/telemetry/tracing/span-kind.md +55 -0
  196. package/reference/telemetry/tracing/span-processor.md +53 -0
  197. package/reference/telemetry/tracing/span-status.md +47 -0
  198. package/reference/telemetry/tracing/span.md +117 -0
  199. package/reference/telemetry/tracing/tracer-provider.md +91 -0
  200. package/reference/telemetry/tracing/tracer.md +52 -0
  201. package/reference/typeid.md +5 -83
  202. package/sidebars.js +376 -43
  203. package/undocumented-report.md +528 -270
  204. package/reference/formats.md +0 -694
  205. package/reference/http-model.md +0 -1716
  206. package/reference/streams.md +0 -989
  207. package/ringbuffer.md +0 -249
  208. /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
  209. /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
  210. /package/reference/{lazy.md → schema/lazy.md} +0 -0
  211. /package/reference/{reflect.md → schema/reflect.md} +0 -0
  212. /package/reference/{registers.md → schema/registers.md} +0 -0
  213. /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
  214. /package/reference/{syntax.md → schema/syntax.md} +0 -0
  215. /package/reference/{validation.md → schema/validation.md} +0 -0
@@ -0,0 +1,510 @@
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`, `BsonCodecDeriver`, and the compatibility facade `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.55"
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 `schema.derive(BsonCodecDeriver)` 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. Schema[A].derive(BsonCodecDeriver) creates BsonCodec[A]
56
+ ↓
57
+ 3. DerivationBuilder traverses the schema and BsonCodecDeriver composes 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. BsonCodecDeriver configuration methods customize 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
+ schema.derive(configuredBsonCodecDeriver) → 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 = Person.schema.derive(BsonCodecDeriver)
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
+ ## BsonCodecDeriver and BsonSchemaCodec
346
+
347
+ `BsonCodecDeriver` implements the shared `Deriver[BsonCodec]` contract. It supports direct derivation as well as `Schema.deriving` instance and modifier overrides by type, exact optic, or parent type and term name.
348
+
349
+ `BsonSchemaCodec` retains `bsonCodec`, `bsonEncoder`, `bsonDecoder`, and `Config` as compatibility and convenience APIs. These methods delegate to `BsonCodecDeriver`, so both entry points have the same BSON behavior.
350
+
351
+ ### Configuration
352
+
353
+ The `Config` class controls codec behavior:
354
+
355
+ ```scala
356
+ import zio.blocks.schema.bson._
357
+
358
+ val defaultConfig = BsonSchemaCodec.Config
359
+ val customConfig = defaultConfig
360
+ .withSumTypeHandling(BsonSchemaCodec.SumTypeHandling.DiscriminatorField("_type"))
361
+ .withClassNameMapping(_.toLowerCase)
362
+ .withIgnoreExtraFields(false)
363
+ .withNativeObjectId(true)
364
+ ```
365
+
366
+ ### Sum Type Handling Options
367
+
368
+ Choose how variants are encoded in BSON documents:
369
+
370
+ ```scala
371
+ import zio.blocks.schema.bson._
372
+
373
+ // Wrapper with class name field (default)
374
+ val wrapper = BsonSchemaCodec.SumTypeHandling.WrapperWithClassNameField
375
+
376
+ // Discriminator field approach
377
+ val discriminator = BsonSchemaCodec.SumTypeHandling.DiscriminatorField("type")
378
+
379
+ // No discriminator - encode variant directly
380
+ val none = BsonSchemaCodec.SumTypeHandling.NoDiscriminator
381
+ ```
382
+
383
+ ### Deriving Codecs
384
+
385
+ To create a codec from a schema:
386
+
387
+ ```scala
388
+ import zio.blocks.schema._
389
+ import zio.blocks.schema.bson._
390
+
391
+ case class Person(name: String, age: Int)
392
+
393
+ object Person {
394
+ implicit val schema: Schema[Person] = Schema.derived
395
+ }
396
+
397
+ val codec = Person.schema.derive(BsonCodecDeriver)
398
+ // codec: BsonCodec[Person] = BsonCodec(
399
+ // encoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$5@75f2c0f,
400
+ // decoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$6@5b87f051
401
+ // )
402
+ val configuredCodec = Person.schema.derive(BsonCodecDeriver.withIgnoreExtraFields(false))
403
+ // configuredCodec: BsonCodec[Person] = BsonCodec(
404
+ // encoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$5@117db32c,
405
+ // decoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$6@6fbcca58
406
+ // )
407
+
408
+ // Compatibility facade
409
+ val compatibleCodec = BsonSchemaCodec.bsonCodec(Person.schema)
410
+ // compatibleCodec: BsonCodec[Person] = BsonCodec(
411
+ // encoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$5@79d7f29,
412
+ // decoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$6@7b055825
413
+ // )
414
+ val configuredCompatibleCodec = BsonSchemaCodec.bsonCodec(Person.schema, BsonSchemaCodec.Config)
415
+ // configuredCompatibleCodec: BsonCodec[Person] = BsonCodec(
416
+ // encoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$5@148d2e57,
417
+ // decoder = zio.blocks.schema.bson.BsonCodecDeriver$$anon$6@78856fd8
418
+ // )
419
+ ```
420
+
421
+ ### Derivation overrides
422
+
423
+ Use `Schema.deriving` when part of a schema needs a custom codec or runtime modifier:
424
+
425
+ ```scala
426
+ val codec = Person.schema
427
+ .deriving(BsonCodecDeriver)
428
+ .instance(Person.schema.reflect.typeId, "age", customIntCodec)
429
+ .modifier(Person.schema.reflect.typeId, "name", Modifier.rename("fullName"))
430
+ .derive
431
+ ```
432
+
433
+ Type-level overrides affect every matching occurrence. Parent-type and term-name overloads are also available for fields and variant cases. String map keys remain BSON document field names; override map values or the whole map codec when custom map behavior is needed.
434
+
435
+ Record-level `Modifier.fieldNaming` and `Modifier.noExtraFields` annotations override the corresponding default BSON behavior. Variant-level `Modifier.caseNaming` and `Modifier.discriminator` annotations override class-name mapping and sum-type handling for the annotated variant.
436
+
437
+ ### Semantic Json values
438
+
439
+ `zio.blocks.schema.json.Json` objects, arrays, scalars, and nulls map directly to their semantic BSON equivalents. Finite BSON doubles other than signed zero retain their exact value when converted through `Json`; BSON signed zero is normalized to JSON zero because `Json.Number` does not retain its sign. Duplicate `Json.Object` field names are rejected because `BsonDocument` cannot represent them without data loss.
440
+
441
+ ---
442
+
443
+ ## BsonTrace
444
+
445
+ Error location information for BSON decoding errors. Shows the path to the error in the document.
446
+
447
+ ### Overview
448
+
449
+ `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`.
450
+
451
+ ### Trace Elements
452
+
453
+ The two types of trace elements:
454
+
455
+ ```scala
456
+ import zio.blocks.schema.bson._
457
+
458
+ sealed trait BsonTrace
459
+
460
+ case class Field(name: String) extends BsonTrace // Document field
461
+ case class Array(idx: Int) extends BsonTrace // Array index
462
+ ```
463
+
464
+ ### Rendering Traces
465
+
466
+ Convert a trace list to a human-readable path:
467
+
468
+ ```scala
469
+ import zio.blocks.schema.bson._
470
+
471
+ val trace = List(
472
+ BsonTrace.Field("user"),
473
+ BsonTrace.Array(0),
474
+ BsonTrace.Field("email")
475
+ )
476
+
477
+ val path = BsonTrace.render(trace) // ".user[0].email"
478
+ ```
479
+
480
+ ---
481
+
482
+ ## ObjectIdSupport
483
+
484
+ Special support for `org.bson.types.ObjectId` with automatic detection for native BSON ObjectId encoding.
485
+
486
+ ### Overview
487
+
488
+ `ObjectIdSupport` provides a Schema instance for ObjectId that enables native BSON ObjectId type encoding (12-byte format) when detected by BsonSchemaCodec.
489
+
490
+ ### Using ObjectId
491
+
492
+ To use ObjectId in your schema, import ObjectIdSupport:
493
+
494
+ ```scala
495
+ import zio.blocks.schema._
496
+ import zio.blocks.schema.bson.ObjectIdSupport._
497
+ import org.bson.types.ObjectId
498
+
499
+ case class MongoDocument(id: ObjectId, title: String)
500
+
501
+ object MongoDocument {
502
+ implicit val schema: Schema[MongoDocument] = Schema.derived
503
+ }
504
+
505
+ // ObjectId will automatically use native BSON ObjectId encoding
506
+ ```
507
+
508
+ ### ObjectId and Configuration
509
+
510
+ When ObjectIdSupport is imported, ObjectId automatically uses native BSON encoding regardless of the `useNativeObjectId` configuration setting.