@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.
Files changed (150) hide show
  1. package/guides/compile-time-resource-safety-with-scope.md +16 -17
  2. package/guides/getting-started-with-mux.md +1507 -0
  3. package/guides/query-dsl-extending.md +161 -102
  4. package/guides/query-dsl-fluent-builder.md +217 -157
  5. package/guides/query-dsl-reified-optics.md +12 -10
  6. package/guides/query-dsl-sql.md +246 -165
  7. package/guides/telemetry-guide.md +1069 -0
  8. package/guides/zio-schema-migration.md +29 -22
  9. package/index.md +292 -50
  10. package/package.json +1 -1
  11. package/plans/config-follow-up-prs.md +188 -0
  12. package/plans/config-pr-assessment-roadmap.md +310 -0
  13. package/reference/MuxDataFlow.jsx +250 -0
  14. package/reference/async.md +651 -0
  15. package/reference/chunk.md +3533 -308
  16. package/reference/codegen/case-class.md +436 -0
  17. package/reference/codegen/emitter-config.md +383 -0
  18. package/reference/codegen/examples.md +664 -0
  19. package/reference/codegen/field.md +316 -0
  20. package/reference/codegen/index.md +317 -0
  21. package/reference/codegen/scala-emitter.md +392 -0
  22. package/reference/codegen/scala-file.md +276 -0
  23. package/reference/codegen/sealed-trait.md +408 -0
  24. package/reference/codegen/type-definition.md +340 -0
  25. package/reference/codegen/type-ref.md +201 -0
  26. package/reference/combinators.md +347 -117
  27. package/reference/config.md +158 -0
  28. package/reference/context.md +4 -4
  29. package/reference/datastar.md +346 -0
  30. package/reference/docs.md +1461 -345
  31. package/reference/endpoint/auth-type.md +146 -0
  32. package/reference/endpoint/endpoint.md +297 -0
  33. package/reference/endpoint/http-codec.md +249 -0
  34. package/reference/endpoint/index.md +825 -0
  35. package/reference/endpoint/path-codec.md +237 -0
  36. package/reference/endpoint/route-pattern.md +196 -0
  37. package/reference/endpoint/route-tree.md +111 -0
  38. package/reference/endpoint/segment-codec.md +212 -0
  39. package/reference/html.md +1120 -0
  40. package/reference/htmx/attribute-values.md +359 -0
  41. package/reference/htmx/hx-encoding.md +111 -0
  42. package/reference/htmx/hx-params.md +204 -0
  43. package/reference/htmx/hx-swap.md +276 -0
  44. package/reference/htmx/hx-sync.md +251 -0
  45. package/reference/htmx/hx-target.md +314 -0
  46. package/reference/htmx/hx-trigger.md +457 -0
  47. package/reference/htmx/hx-url-update.md +239 -0
  48. package/reference/htmx/index.md +855 -0
  49. package/reference/http-model/index.md +47 -0
  50. package/reference/http-model/model.md +1481 -0
  51. package/reference/http-model/schema.md +747 -0
  52. package/reference/maybe.md +826 -0
  53. package/reference/media-type.md +2 -2
  54. package/reference/mux.mdx +823 -0
  55. package/reference/openapi.md +1351 -0
  56. package/reference/resource-management/defer-handle.md +1 -1
  57. package/reference/resource-management/resource.md +31 -2
  58. package/reference/resource-management/scope.md +28 -12
  59. package/reference/resource-management/wire.md +3 -7
  60. package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
  61. package/reference/ringbuffer/MpscDiagram.jsx +618 -0
  62. package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
  63. package/reference/ringbuffer/SpscDiagram.jsx +677 -0
  64. package/reference/ringbuffer/advanced.mdx +109 -0
  65. package/reference/ringbuffer/index.mdx +145 -0
  66. package/reference/ringbuffer/mpmc.mdx +151 -0
  67. package/reference/ringbuffer/mpsc.mdx +132 -0
  68. package/reference/ringbuffer/spmc.mdx +108 -0
  69. package/reference/ringbuffer/spsc.mdx +344 -0
  70. package/reference/{allows.md → schema/allows.md} +4 -4
  71. package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
  72. package/reference/{binding.md → schema/binding.md} +2 -3
  73. package/reference/schema/built-in-codecs/avro.md +451 -0
  74. package/reference/schema/built-in-codecs/bson.md +480 -0
  75. package/reference/schema/built-in-codecs/csv.md +564 -0
  76. package/reference/schema/built-in-codecs/index.md +77 -0
  77. package/reference/schema/built-in-codecs/json/index.md +295 -0
  78. package/reference/schema/built-in-codecs/json/json-config.md +217 -0
  79. package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
  80. package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
  81. package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
  82. package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
  83. package/reference/schema/built-in-codecs/messagepack.md +508 -0
  84. package/reference/schema/built-in-codecs/thrift.md +433 -0
  85. package/reference/schema/built-in-codecs/toon.md +1078 -0
  86. package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
  87. package/reference/schema/built-in-codecs/yaml.md +552 -0
  88. package/reference/{codec.md → schema/codec.md} +10 -10
  89. package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +151 -5
  90. package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
  91. package/reference/schema/format.md +92 -0
  92. package/reference/schema/index.md +50 -0
  93. package/reference/schema/migration.md +297 -0
  94. package/reference/{modifier.md → schema/modifier.md} +58 -7
  95. package/reference/{optics.md → schema/optics.md} +2 -2
  96. package/reference/{patch.md → schema/patch.md} +1 -1
  97. package/{path-interpolator.md → reference/schema/path-interpolator.md} +165 -72
  98. package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
  99. package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
  100. package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
  101. package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
  102. package/reference/{schema.md → schema/schema.md} +12 -0
  103. package/reference/{structural-types.md → schema/structural-types.md} +1 -1
  104. package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
  105. package/reference/smithy.md +533 -0
  106. package/reference/sql/db-codec-deriver.md +71 -0
  107. package/reference/sql/db-codec.md +687 -0
  108. package/reference/sql/db-con.md +271 -0
  109. package/reference/sql/db-connection.md +153 -0
  110. package/reference/sql/db-param-writer.md +77 -0
  111. package/reference/sql/db-param.md +66 -0
  112. package/reference/sql/db-result-reader.md +146 -0
  113. package/reference/sql/db-tx.md +82 -0
  114. package/reference/sql/db-value.md +41 -0
  115. package/reference/sql/ddl.md +85 -0
  116. package/reference/sql/frag.md +254 -0
  117. package/reference/sql/index.md +341 -0
  118. package/reference/sql/repo.md +600 -0
  119. package/reference/sql/sql-dialect.md +73 -0
  120. package/reference/sql/sql-logger.md +62 -0
  121. package/reference/sql/sql-name-mapper.md +70 -0
  122. package/reference/sql/table-metadata.md +134 -0
  123. package/reference/sql/table.md +448 -0
  124. package/reference/sql/transactor-zio.md +399 -0
  125. package/reference/sql/transactor.md +353 -0
  126. package/reference/sql-zio.md +112 -0
  127. package/reference/streams/concurrent-operators.md +106 -0
  128. package/reference/streams/index.md +653 -0
  129. package/reference/streams/pipeline.md +718 -0
  130. package/reference/streams/reader.md +1284 -0
  131. package/reference/streams/scala-2-compatibility.md +55 -0
  132. package/reference/streams/sink.md +1426 -0
  133. package/reference/streams/stream.md +2526 -0
  134. package/reference/streams/writer.md +1045 -0
  135. package/reference/streams/zero-boxing.md +275 -0
  136. package/reference/telemetry.md +693 -0
  137. package/reference/typeid.md +5 -19
  138. package/sidebars.js +238 -43
  139. package/reference/formats.md +0 -694
  140. package/reference/http-model.md +0 -1716
  141. package/reference/streams.md +0 -989
  142. package/ringbuffer.md +0 -249
  143. /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
  144. /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
  145. /package/reference/{lazy.md → schema/lazy.md} +0 -0
  146. /package/reference/{reflect.md → schema/reflect.md} +0 -0
  147. /package/reference/{registers.md → schema/registers.md} +0 -0
  148. /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
  149. /package/reference/{syntax.md → schema/syntax.md} +0 -0
  150. /package/reference/{validation.md → schema/validation.md} +0 -0
@@ -0,0 +1,664 @@
1
+ ---
2
+ id: examples
3
+ title: "Complete Examples"
4
+ ---
5
+
6
+ This page shows complete, runnable examples demonstrating realistic code generation workflows. Each example builds IR models from scratch and emits formatted Scala code.
7
+
8
+ ## Example 1: Simple Domain Model
9
+
10
+ Build a complete domain model with a case class and sealed trait:
11
+
12
+ ```scala
13
+ import zio.blocks.codegen.ir._
14
+ import zio.blocks.codegen.emit._
15
+
16
+ // Define error types
17
+ val error = SealedTrait(
18
+ name = "Error",
19
+ cases = List(
20
+ SealedTraitCase.CaseObjectCase("NotFound"),
21
+ SealedTraitCase.CaseObjectCase("Unauthorized"),
22
+ SealedTraitCase.CaseClassCase(
23
+ CaseClass("ValidationError", List(
24
+ Field("field", TypeRef.String),
25
+ Field("message", TypeRef.String)
26
+ ))
27
+ )
28
+ )
29
+ )
30
+
31
+ // Define a user
32
+ val user = CaseClass(
33
+ name = "User",
34
+ fields = List(
35
+ Field("id", TypeRef.Long),
36
+ Field("email", TypeRef.String),
37
+ Field("name", TypeRef.String),
38
+ Field("active", TypeRef.Boolean, defaultValue = Some("true"))
39
+ )
40
+ )
41
+
42
+ // Assemble into a file
43
+ val file = ScalaFile(
44
+ packageDecl = PackageDecl("com.example.domain"),
45
+ imports = List(
46
+ Import.WildcardImport("zio")
47
+ ),
48
+ types = List(error, user)
49
+ )
50
+
51
+ val config = EmitterConfig(indentWidth = 2)
52
+ ```
53
+
54
+ This generates:
55
+
56
+ ```scala
57
+ import zio.blocks.codegen.emit._
58
+ val code = ScalaEmitter.emit(file, config)
59
+ // code: String = """package com.example.domain
60
+ //
61
+ // import zio.*
62
+ //
63
+ // sealed trait Error
64
+ //
65
+ // object Error {
66
+ // case object NotFound extends Error
67
+ // case object Unauthorized extends Error
68
+ // case class ValidationError(
69
+ // field: String,
70
+ // message: String,
71
+ // ) extends Error
72
+ // }
73
+ //
74
+ // case class User(
75
+ // id: Long,
76
+ // email: String,
77
+ // name: String,
78
+ // active: Boolean = true,
79
+ // )
80
+ // """
81
+ ```
82
+
83
+ ## Example 2: Generic Container Types
84
+
85
+ Build polymorphic types with type parameters:
86
+
87
+ ```scala
88
+ import zio.blocks.codegen.ir._
89
+ import zio.blocks.codegen.emit._
90
+
91
+ // A generic wrapper
92
+ val container = CaseClass(
93
+ name = "Container",
94
+ fields = List(
95
+ Field("value", TypeRef("T")),
96
+ Field("metadata", TypeRef("Map", List(TypeRef.String, TypeRef.String)))
97
+ ),
98
+ typeParams = List(TypeParam("T")),
99
+ derives = List("Show")
100
+ )
101
+
102
+ // A generic result type
103
+ val result = SealedTrait(
104
+ name = "Result",
105
+ typeParams = List(TypeParam("A")),
106
+ cases = List(
107
+ SealedTraitCase.CaseClassCase(
108
+ CaseClass("Success", List(
109
+ Field("value", TypeRef("A"))
110
+ ), typeParams = List(TypeParam("A")))
111
+ ),
112
+ SealedTraitCase.CaseClassCase(
113
+ CaseClass("Failure", List(
114
+ Field("error", TypeRef.String)
115
+ ))
116
+ )
117
+ )
118
+ )
119
+
120
+ val file = ScalaFile(
121
+ packageDecl = PackageDecl("com.example.types"),
122
+ types = List(container, result)
123
+ )
124
+ ```
125
+
126
+ Generates:
127
+
128
+ ```scala
129
+ import zio.blocks.codegen.emit._
130
+ ScalaEmitter.emit(file, EmitterConfig())
131
+ // res1: String = """package com.example.types
132
+ //
133
+ // case class Container[T](
134
+ // value: T,
135
+ // metadata: Map[String, String],
136
+ // ) derives Show
137
+ //
138
+ // sealed trait Result[A]
139
+ //
140
+ // object Result {
141
+ // case class Success[A](
142
+ // value: A,
143
+ // ) extends Result[A]
144
+ // case class Failure(
145
+ // error: String,
146
+ // ) extends Result[A]
147
+ // }
148
+ // """
149
+ ```
150
+
151
+ ## Example 3: API Request/Response Models
152
+
153
+ Generate HTTP API models from scratch:
154
+
155
+ ```scala
156
+ import zio.blocks.codegen.ir._
157
+ import zio.blocks.codegen.emit._
158
+
159
+ // Request model
160
+ val createUserReq = CaseClass(
161
+ name = "CreateUserRequest",
162
+ fields = List(
163
+ Field("email", TypeRef.String),
164
+ Field("name", TypeRef.String),
165
+ Field("password", TypeRef.String)
166
+ )
167
+ )
168
+
169
+ // Response model
170
+ val user = CaseClass(
171
+ name = "User",
172
+ fields = List(
173
+ Field("id", TypeRef.Long),
174
+ Field("email", TypeRef.String),
175
+ Field("name", TypeRef.String),
176
+ Field("createdAt", TypeRef.String)
177
+ )
178
+ )
179
+
180
+ // Error responses
181
+ val apiError = SealedTrait(
182
+ name = "ApiError",
183
+ cases = List(
184
+ SealedTraitCase.CaseClassCase(
185
+ CaseClass("BadRequest", List(
186
+ Field("message", TypeRef.String)
187
+ ))
188
+ ),
189
+ SealedTraitCase.CaseClassCase(
190
+ CaseClass("Conflict", List(
191
+ Field("resource", TypeRef.String),
192
+ Field("details", TypeRef.String)
193
+ ))
194
+ ),
195
+ SealedTraitCase.CaseObjectCase("InternalServerError")
196
+ )
197
+ )
198
+
199
+ val file = ScalaFile(
200
+ packageDecl = PackageDecl("com.example.api.models"),
201
+ types = List(createUserReq, user, apiError)
202
+ )
203
+ ```
204
+
205
+ Generates:
206
+
207
+ ```scala
208
+ import zio.blocks.codegen.emit._
209
+ ScalaEmitter.emit(file, EmitterConfig())
210
+ // res3: String = """package com.example.api.models
211
+ //
212
+ // case class CreateUserRequest(
213
+ // email: String,
214
+ // name: String,
215
+ // password: String,
216
+ // )
217
+ //
218
+ // case class User(
219
+ // id: Long,
220
+ // email: String,
221
+ // name: String,
222
+ // createdAt: String,
223
+ // )
224
+ //
225
+ // sealed trait ApiError
226
+ //
227
+ // object ApiError {
228
+ // case class BadRequest(
229
+ // message: String,
230
+ // ) extends ApiError
231
+ // case class Conflict(
232
+ // resource: String,
233
+ // details: String,
234
+ // ) extends ApiError
235
+ // case object InternalServerError extends ApiError
236
+ // }
237
+ // """
238
+ ```
239
+
240
+ ## Example 4: Cross-Scala Version Generation
241
+
242
+ Emit code for both Scala 3 and Scala 2:
243
+
244
+ ```scala
245
+ import zio.blocks.codegen.ir._
246
+ import zio.blocks.codegen.emit._
247
+
248
+ // An enum type
249
+ val status = Enum(
250
+ name = "OrderStatus",
251
+ cases = List(
252
+ EnumCase.SimpleCase("Pending"),
253
+ EnumCase.SimpleCase("Shipped"),
254
+ EnumCase.SimpleCase("Delivered"),
255
+ EnumCase.SimpleCase("Cancelled")
256
+ )
257
+ )
258
+
259
+ val file = ScalaFile(
260
+ packageDecl = PackageDecl("com.shop.models"),
261
+ types = List(status)
262
+ )
263
+
264
+ // Generate for Scala 3
265
+ val scala3Code = ScalaEmitter.emit(
266
+ file,
267
+ EmitterConfig(scala3Syntax = true)
268
+ )
269
+
270
+ // Generate for Scala 2
271
+ val scala2Code = ScalaEmitter.emit(
272
+ file,
273
+ EmitterConfig(scala3Syntax = false)
274
+ )
275
+ ```
276
+
277
+ Scala 3 output:
278
+
279
+ ```scala
280
+ import zio.blocks.codegen.emit._
281
+ scala3Code
282
+ // res5: String = """package com.shop.models
283
+ //
284
+ // enum OrderStatus {
285
+ // case Pending, Shipped, Delivered, Cancelled
286
+ // }
287
+ // """
288
+ ```
289
+
290
+ Scala 2 output:
291
+
292
+ ```scala
293
+ import zio.blocks.codegen.emit._
294
+ scala2Code
295
+ // res6: String = """package com.shop.models
296
+ //
297
+ // sealed trait OrderStatus
298
+ //
299
+ // object OrderStatus {
300
+ // case object Pending extends OrderStatus
301
+ // case object Shipped extends OrderStatus
302
+ // case object Delivered extends OrderStatus
303
+ // case object Cancelled extends OrderStatus
304
+ // }
305
+ // """
306
+ ```
307
+
308
+ ## Example 5: Object with Static Methods and Values
309
+
310
+ Generate a companion object with utility methods:
311
+
312
+ ```scala
313
+ import zio.blocks.codegen.ir._
314
+ import zio.blocks.codegen.emit._
315
+
316
+ val config = CaseClass(
317
+ name = "AppConfig",
318
+ fields = List(
319
+ Field("host", TypeRef.String),
320
+ Field("port", TypeRef.Int),
321
+ Field("timeout", TypeRef.Long)
322
+ ),
323
+ companion = Some(
324
+ CompanionObject(
325
+ members = List(
326
+ ObjectMember.ValMember(
327
+ "Default",
328
+ TypeRef("AppConfig"),
329
+ "AppConfig(\"localhost\", 8080, 30000L)"
330
+ ),
331
+ ObjectMember.ValMember(
332
+ "Production",
333
+ TypeRef("AppConfig"),
334
+ "AppConfig(\"api.example.com\", 443, 60000L)"
335
+ )
336
+ )
337
+ )
338
+ ),
339
+ derives = List("Show")
340
+ )
341
+
342
+ val file = ScalaFile(
343
+ packageDecl = PackageDecl("com.example.config"),
344
+ types = List(config)
345
+ )
346
+ ```
347
+
348
+ Generates:
349
+
350
+ ```scala
351
+ import zio.blocks.codegen.emit._
352
+ ScalaEmitter.emit(file, EmitterConfig())
353
+ // res8: String = """package com.example.config
354
+ //
355
+ // case class AppConfig(
356
+ // host: String,
357
+ // port: Int,
358
+ // timeout: Long,
359
+ // ) derives Show
360
+ //
361
+ // object AppConfig {
362
+ // val Default: AppConfig = AppConfig("localhost", 8080, 30000L)
363
+ // val Production: AppConfig = AppConfig("api.example.com", 443, 60000L)
364
+ // }
365
+ // """
366
+ ```
367
+
368
+ ## Example 6: Complex Nested Types
369
+
370
+ Model deeply nested generic structures:
371
+
372
+ ```scala
373
+ import zio.blocks.codegen.ir._
374
+ import zio.blocks.codegen.emit._
375
+
376
+ // Pagination wrapper
377
+ val page = CaseClass(
378
+ name = "Page",
379
+ fields = List(
380
+ Field(
381
+ "items",
382
+ TypeRef("List", List(TypeRef("T")))
383
+ ),
384
+ Field("total", TypeRef.Long),
385
+ Field("page", TypeRef.Int),
386
+ Field("pageSize", TypeRef.Int),
387
+ Field(
388
+ "errors",
389
+ TypeRef("List", List(
390
+ TypeRef("Map", List(
391
+ TypeRef.String,
392
+ TypeRef.String
393
+ ))
394
+ ))
395
+ )
396
+ ),
397
+ typeParams = List(TypeParam("T"))
398
+ )
399
+
400
+ val file = ScalaFile(
401
+ packageDecl = PackageDecl("com.example.pagination"),
402
+ imports = List(
403
+ Import.WildcardImport("scala.collection")
404
+ ),
405
+ types = List(page)
406
+ )
407
+ ```
408
+
409
+ Generates:
410
+
411
+ ```scala
412
+ import zio.blocks.codegen.emit._
413
+ ScalaEmitter.emit(file, EmitterConfig(indentWidth = 2))
414
+ // res10: String = """package com.example.pagination
415
+ //
416
+ // import scala.collection.*
417
+ //
418
+ // case class Page[T](
419
+ // items: List[T],
420
+ // total: Long,
421
+ // page: Int,
422
+ // pageSize: Int,
423
+ // errors: List[Map[String, String]],
424
+ // )
425
+ // """
426
+ ```
427
+
428
+ ## Example 7: Building Files Incrementally
429
+
430
+ Add types to a file step by step:
431
+
432
+ ```scala
433
+ import zio.blocks.codegen.ir._
434
+ import zio.blocks.codegen.emit._
435
+
436
+ // Build types
437
+ val user = CaseClass("User", List(Field("id", TypeRef.Long)))
438
+ val order = CaseClass("Order", List(
439
+ Field("id", TypeRef.Long),
440
+ Field("userId", TypeRef.Long)
441
+ ))
442
+ val status = Enum(
443
+ "OrderStatus",
444
+ cases = List(
445
+ EnumCase.SimpleCase("Pending"),
446
+ EnumCase.SimpleCase("Complete")
447
+ )
448
+ )
449
+
450
+ // Assemble into a file
451
+ val file = ScalaFile(
452
+ packageDecl = PackageDecl("com.example"),
453
+ imports = List(Import.WildcardImport("zio")),
454
+ types = List(user, order, status)
455
+ )
456
+ ```
457
+
458
+ Generates:
459
+
460
+ ```scala
461
+ import zio.blocks.codegen.emit._
462
+ ScalaEmitter.emit(file, EmitterConfig())
463
+ // res12: String = """package com.example
464
+ //
465
+ // import zio.*
466
+ //
467
+ // case class User(
468
+ // id: Long,
469
+ // )
470
+ //
471
+ // case class Order(
472
+ // id: Long,
473
+ // userId: Long,
474
+ // )
475
+ //
476
+ // enum OrderStatus {
477
+ // case Pending, Complete
478
+ // }
479
+ // """
480
+ ```
481
+
482
+ ## Example 8: Multi-File Generation
483
+
484
+ Generate multiple files from a single data model:
485
+
486
+ ```scala
487
+ import zio.blocks.codegen.ir._
488
+ import zio.blocks.codegen.emit._
489
+
490
+ val config = EmitterConfig()
491
+
492
+ // Models file
493
+ val modelsFile = ScalaFile(
494
+ packageDecl = PackageDecl("com.example.models"),
495
+ types = List(
496
+ CaseClass("User", List(
497
+ Field("id", TypeRef.Long),
498
+ Field("name", TypeRef.String)
499
+ )),
500
+ CaseClass("Product", List(
501
+ Field("id", TypeRef.Long),
502
+ Field("price", TypeRef("BigDecimal"))
503
+ ))
504
+ )
505
+ )
506
+
507
+ // Errors file
508
+ val errorsFile = ScalaFile(
509
+ packageDecl = PackageDecl("com.example.errors"),
510
+ types = List(
511
+ SealedTrait(
512
+ "DomainError",
513
+ cases = List(
514
+ SealedTraitCase.CaseObjectCase("NotFound"),
515
+ SealedTraitCase.CaseObjectCase("Unauthorized")
516
+ )
517
+ )
518
+ )
519
+ )
520
+
521
+ // Emit both
522
+ val modelsCode = ScalaEmitter.emit(modelsFile, config)
523
+ val errorsCode = ScalaEmitter.emit(errorsFile, config)
524
+ ```
525
+
526
+ Models output:
527
+
528
+ ```scala
529
+ import zio.blocks.codegen.emit._
530
+ modelsCode
531
+ // res14: String = """package com.example.models
532
+ //
533
+ // case class User(
534
+ // id: Long,
535
+ // name: String,
536
+ // )
537
+ //
538
+ // case class Product(
539
+ // id: Long,
540
+ // price: BigDecimal,
541
+ // )
542
+ // """
543
+ ```
544
+
545
+ Errors output:
546
+
547
+ ```scala
548
+ import zio.blocks.codegen.emit._
549
+ errorsCode
550
+ // res15: String = """package com.example.errors
551
+ //
552
+ // sealed trait DomainError
553
+ //
554
+ // object DomainError {
555
+ // case object NotFound extends DomainError
556
+ // case object Unauthorized extends DomainError
557
+ // }
558
+ // """
559
+ ```
560
+
561
+ ## Key Patterns
562
+
563
+ These patterns recur across all code generation workflows:
564
+
565
+ ### Building Incrementally
566
+
567
+ When generating code, you'll often build types incrementally:
568
+
569
+ ```scala
570
+ import zio.blocks.codegen.ir._
571
+
572
+ val types = List(
573
+ CaseClass("User", List()),
574
+ CaseClass("Product", List())
575
+ )
576
+
577
+ // Create file with all types
578
+ val file = ScalaFile(
579
+ packageDecl = PackageDecl("com.example"),
580
+ types = types
581
+ )
582
+ ```
583
+
584
+ ### Reusing Type Definitions
585
+
586
+ Define common types once and compose them:
587
+
588
+ ```scala
589
+ import zio.blocks.codegen.ir._
590
+
591
+ // Common error type
592
+ val baseError = SealedTrait(
593
+ "Error",
594
+ cases = List(
595
+ SealedTraitCase.CaseObjectCase("NotFound")
596
+ )
597
+ )
598
+
599
+ // File 1
600
+ val file1 = ScalaFile(
601
+ packageDecl = PackageDecl("com.module1"),
602
+ types = List(baseError)
603
+ )
604
+
605
+ // File 2 (same error, different package)
606
+ val file2 = ScalaFile(
607
+ packageDecl = PackageDecl("com.module2"),
608
+ types = List(baseError)
609
+ )
610
+ ```
611
+
612
+ ### Configuration Strategies
613
+
614
+ Choose configuration once and apply to all files:
615
+
616
+ ```scala
617
+ import zio.blocks.codegen.emit._
618
+
619
+ // Your project's standard config
620
+ val projectConfig = EmitterConfig(
621
+ indentWidth = 2,
622
+ trailingCommas = true,
623
+ sortImports = true,
624
+ scala3Syntax = true
625
+ )
626
+
627
+ // Apply to all generated files
628
+ // ScalaEmitter.emit(file1, projectConfig)
629
+ // ScalaEmitter.emit(file2, projectConfig)
630
+ // ScalaEmitter.emit(file3, projectConfig)
631
+ ```
632
+
633
+ ## Integration with Generators
634
+
635
+ In a real code generator, you'd:
636
+
637
+ 1. **Parse** your source format (OpenAPI, Smithy, Protobuf, etc.)
638
+ 2. **Build IR** models from parsed data
639
+ 3. **Configure** the emitter once
640
+ 4. **Emit** files in a loop
641
+ 5. **Write** strings to disk
642
+
643
+ Example structure:
644
+
645
+ ```scala
646
+ // Pseudocode: real generators follow this pattern
647
+
648
+ // def generateFromOpenAPI(spec: OpenAPI): Unit = {
649
+ // val config = EmitterConfig(...)
650
+ //
651
+ // for (schema <- spec.schemas) {
652
+ // val irType = openAPISchemaToIR(schema) // Parse → IR
653
+ // val file = ScalaFile(
654
+ // packageDecl = PackageDecl("com.generated"),
655
+ // types = List(irType)
656
+ // )
657
+ // val code = ScalaEmitter.emit(file, config) // IR → Scala
658
+ // writeFile(s"generated/${schema.name}.scala", code) // Write
659
+ // }
660
+ // }
661
+ ```
662
+
663
+ This separation of concerns (format-specific parsing → generic IR → emission) is the core value of `zio-blocks-codegen`.
664
+