@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
@@ -3,13 +3,20 @@ id: path-interpolator
3
3
  title: "Path Interpolator"
4
4
  ---
5
5
 
6
+ :::note
7
+ To use the path interpolator `p"..."`, you must import the schema package: `import zio.blocks.schema._`
8
+ :::
9
+
6
10
  The path interpolator `p"..."` is a compile-time string interpolator for constructing `DynamicOptic` instances in ZIO Blocks. It provides a clean, concise syntax for building optic paths that navigate through complex data structures, with all parsing and validation happening at compile time for zero runtime overhead.
7
11
 
8
12
  **Why use the path interpolator?**
9
13
 
10
14
  Instead of manually constructing optics like this:
11
15
 
16
+
12
17
  ```scala
18
+ import zio.blocks.schema._
19
+
13
20
  DynamicOptic(Vector(
14
21
  DynamicOptic.Node.Field("users"),
15
22
  DynamicOptic.Node.Elements,
@@ -20,6 +27,8 @@ DynamicOptic(Vector(
20
27
  You can write:
21
28
 
22
29
  ```scala
30
+ import zio.blocks.schema._
31
+
23
32
  p".users[*].email"
24
33
  ```
25
34
 
@@ -46,9 +55,11 @@ val path = p".users[0].name"
46
55
 
47
56
  ## Syntax Reference
48
57
 
58
+ This section documents the complete path syntax with examples for each component type.
59
+
49
60
  ### Field Access
50
61
 
51
- Access fields in records using dot notation. The leading dot is optional.
62
+ Access fields in records using dot notation. The leading dot is optional:
52
63
 
53
64
  ```scala
54
65
  // With leading dot
@@ -64,7 +75,7 @@ p".user.address.street"
64
75
  // Equivalent to: Field("user") → Field("address") → Field("street")
65
76
  ```
66
77
 
67
- **Special cases:**
78
+ Field names can also include special characters and keywords:
68
79
 
69
80
  ```scala
70
81
  p"._private" // Fields starting with underscore
@@ -77,7 +88,7 @@ p".true" // Keywords as field names (true, false, null)
77
88
 
78
89
  Access sequence elements by index, multiple indices, or ranges.
79
90
 
80
- **Single index:**
91
+ To access a single element by index:
81
92
 
82
93
  ```scala
83
94
  p"[0]" // AtIndex(0)
@@ -85,7 +96,7 @@ p"[42]" // AtIndex(42)
85
96
  p"[2147483647]" // AtIndex(Int.MaxValue)
86
97
  ```
87
98
 
88
- **Multiple indices:**
99
+ To access multiple elements at specific indices:
89
100
 
90
101
  ```scala
91
102
  p"[0,1,2]" // AtIndices(Seq(0, 1, 2))
@@ -93,7 +104,7 @@ p"[0, 2, 5]" // AtIndices(Seq(0, 2, 5)) - spaces allowed
93
104
  p"[5,2,8,1]" // Order preserved
94
105
  ```
95
106
 
96
- **Ranges:**
107
+ To select a range of consecutive elements:
97
108
 
98
109
  ```scala
99
110
  p"[0:5]" // AtIndices(Seq(0, 1, 2, 3, 4))
@@ -105,14 +116,14 @@ p"[10:5]" // AtIndices(Seq.empty) - inverted range
105
116
 
106
117
  ### Element Selectors
107
118
 
108
- Select all elements in a sequence using wildcard syntax.
119
+ Select all elements in a sequence using wildcard syntax:
109
120
 
110
121
  ```scala
111
122
  p"[*]" // Elements - all elements
112
123
  p"[:*]" // Elements - alternative syntax
113
124
  ```
114
125
 
115
- **Chained selectors:**
126
+ To navigate nested sequences:
116
127
 
117
128
  ```scala
118
129
  p"[*][*]" // Nested sequences: all elements of all elements
@@ -123,7 +134,7 @@ p"[*][0]" // First element of each sequence
123
134
 
124
135
  Access map values by key, where keys can be strings, integers, booleans, or characters.
125
136
 
126
- **String keys:**
137
+ To use string keys:
127
138
 
128
139
  ```scala
129
140
  p"""{"host"}""" // AtMapKey(String("host"))
@@ -133,7 +144,7 @@ p"""{"🎉"}""" // Emoji keys
133
144
  p"""{""}""" // Empty string key
134
145
  ```
135
146
 
136
- **Integer keys:**
147
+ To use integer keys:
137
148
 
138
149
  ```scala
139
150
  p"{42}" // AtMapKey(Int(42))
@@ -143,14 +154,14 @@ p"{2147483647}" // AtMapKey(Int.MaxValue)
143
154
  p"{-2147483648}" // AtMapKey(Int.MinValue)
144
155
  ```
145
156
 
146
- **Boolean keys:**
157
+ To use boolean keys:
147
158
 
148
159
  ```scala
149
160
  p"{true}" // AtMapKey(Boolean(true))
150
161
  p"{false}" // AtMapKey(Boolean(false))
151
162
  ```
152
163
 
153
- **Char keys:**
164
+ To use character keys:
154
165
 
155
166
  ```scala
156
167
  p"{'a'}" // AtMapKey(Char('a'))
@@ -158,7 +169,7 @@ p"{' '}" // AtMapKey(Char(' '))
158
169
  p"{'9'}" // AtMapKey(Char('9'))
159
170
  ```
160
171
 
161
- **Multiple keys:**
172
+ To use multiple keys of the same or mixed types:
162
173
 
163
174
  ```scala
164
175
  p"""{"foo", "bar", "baz"}""" // AtMapKeys(Seq(...))
@@ -172,7 +183,7 @@ p"""{"s", 'c', 42, true}""" // All supported types
172
183
 
173
184
  ### Map Selectors
174
185
 
175
- Select all keys or all values in a map.
186
+ Select all keys or all values in a map:
176
187
 
177
188
  ```scala
178
189
  p"{*}" // MapValues - all values
@@ -180,7 +191,7 @@ p"{:*}" // MapValues - alternative syntax
180
191
  p"{*:}" // MapKeys - all keys
181
192
  ```
182
193
 
183
- **Examples:**
194
+ To apply map selectors to nested maps:
184
195
 
185
196
  ```scala
186
197
  p"{*}{*}" // Nested maps: all values of all values
@@ -189,7 +200,7 @@ p"{*:}{*:}" // All keys of all keys
189
200
 
190
201
  ### Variant Case Access
191
202
 
192
- Navigate into a specific variant case using angle brackets.
203
+ Navigate into a specific variant case using angle brackets:
193
204
 
194
205
  ```scala
195
206
  p"<Left>" // Case("Left")
@@ -198,7 +209,7 @@ p"<Some>" // Case("Some")
198
209
  p"<None>" // Case("None")
199
210
  ```
200
211
 
201
- **Special cases:**
212
+ Variant case names can include special characters and keywords:
202
213
 
203
214
  ```scala
204
215
  p"<_Empty>" // Cases starting with underscore
@@ -206,7 +217,7 @@ p"<Case1>" // Cases with digits
206
217
  p"<café>" // Unicode case names
207
218
  ```
208
219
 
209
- **Chained cases:**
220
+ To navigate nested variant cases:
210
221
 
211
222
  ```scala
212
223
  p"<A><B><C>" // Nested variants
@@ -216,7 +227,7 @@ p"<A><B><C>" // Nested variants
216
227
 
217
228
  Search for values matching a schema pattern anywhere in a data structure using the `#` prefix.
218
229
 
219
- **Nominal types:**
230
+ To search for nominal types by name:
220
231
 
221
232
  ```scala
222
233
  p"#Person" // Find all values of type Person
@@ -224,7 +235,7 @@ p"#User" // Find all values of type User
224
235
  p"#Address" // Find all values of type Address
225
236
  ```
226
237
 
227
- **Primitive types:**
238
+ To search for primitive types:
228
239
 
229
240
  ```scala
230
241
  p"#string" // Find all string values
@@ -233,7 +244,7 @@ p"#boolean" // Find all boolean values
233
244
  p"#uuid" // Find all UUID values
234
245
  ```
235
246
 
236
- **Structural records:**
247
+ To search for records with specific field structures:
237
248
 
238
249
  ```scala
239
250
  p"#record { name: string }" // Find records with a string 'name' field
@@ -241,13 +252,13 @@ p"#record { name: string, age: int }" // Find records with both fields
241
252
  p"#record { items: list(Person) }" // Nested schema
242
253
  ```
243
254
 
244
- **Structural variants:**
255
+ To search for variants with specific case structures:
245
256
 
246
257
  ```scala
247
258
  p"#variant { Left: int, Right: string }" // Find Either-like variants
248
259
  ```
249
260
 
250
- **Collections:**
261
+ To search for collection types:
251
262
 
252
263
  ```scala
253
264
  p"#list(string)" // Find lists of strings
@@ -256,13 +267,13 @@ p"#map(string, int)" // Find maps from string to int
256
267
  p"#option(Person)" // Find optional Person values
257
268
  ```
258
269
 
259
- **Wildcard:**
270
+ To match any value regardless of type:
260
271
 
261
272
  ```scala
262
273
  p"#_" // Find any value (matches everything)
263
274
  ```
264
275
 
265
- **Combined paths with search:**
276
+ To combine path navigation with schema search:
266
277
 
267
278
  ```scala
268
279
  p".users#Person" // Search for Person in users field
@@ -284,7 +295,7 @@ String and character literals support standard escape sequences:
284
295
  | `\"` | `"` | Double quote |
285
296
  | `\\` | `\` | Backslash |
286
297
 
287
- **Examples:**
298
+ Here are some examples of escape sequences in use:
288
299
 
289
300
  ```scala
290
301
  p"""{"foo\nbar"}""" // String key with newline
@@ -300,6 +311,8 @@ Combine different path elements to navigate complex nested structures.
300
311
 
301
312
  ### Field → Sequence
302
313
 
314
+ Access sequence elements by index or range through a field:
315
+
303
316
  ```scala
304
317
  p".items[0]" // First item
305
318
  p".items[*]" // All items
@@ -309,6 +322,8 @@ p".items[0:5]" // Items 0 through 4
309
322
 
310
323
  ### Field → Map
311
324
 
325
+ Access map values by key through a field:
326
+
312
327
  ```scala
313
328
  p""".config{"host"}""" // Map lookup
314
329
  p".settings{42}" // Integer key
@@ -318,6 +333,8 @@ p".lookup{*:}" // All map keys
318
333
 
319
334
  ### Field → Variant
320
335
 
336
+ Navigate into variant cases through a field:
337
+
321
338
  ```scala
322
339
  p".result<Success>" // Variant case
323
340
  p".response<Ok>" // HTTP response variant
@@ -325,6 +342,8 @@ p".response<Ok>" // HTTP response variant
325
342
 
326
343
  ### Nested Structures
327
344
 
345
+ Combine different path elements to build complex navigation through nested data:
346
+
328
347
  ```scala
329
348
  // Record in sequence
330
349
  p".users[0].name"
@@ -345,6 +364,8 @@ p".response<Ok>.body"
345
364
 
346
365
  ### Deeply Nested Paths
347
366
 
367
+ Chain multiple path operators for deeply nested data structures:
368
+
348
369
  ```scala
349
370
  // Complex nested navigation
350
371
  p""".root.children[*].metadata{"tags"}[0]"""
@@ -359,35 +380,47 @@ p""".a[0]{"k"}<V>.b[*]{*}.c{*:}"""
359
380
 
360
381
  ## Root and Empty Paths
361
382
 
383
+ An empty path refers to the root of the data structure:
384
+
362
385
  ```scala
363
386
  p"" // Empty path = root
364
- // Equivalent to: DynamicOptic.root
365
- // Equivalent to: DynamicOptic(Vector.empty)
366
387
  ```
367
388
 
368
389
  ## Compile-Time Safety
369
390
 
370
391
  The path interpolator **rejects runtime interpolation** to prevent unsafe dynamic path construction.
371
392
 
372
- **❌ This will fail to compile:**
393
+ ### Examples of Safety Checks
394
+
395
+ Runtime interpolation will fail to compile:
373
396
 
374
397
  ```scala
398
+ import zio.blocks.schema._
399
+
375
400
  val fieldName = "email"
376
401
  val path = p".$fieldName"
377
402
  // Error: Path interpolator does not support runtime arguments.
378
- // Use only literal strings like p".field[0]"
403
+ // error:
404
+ // Path interpolator does not support runtime arguments. Use only literal strings like p".field[0]"
405
+ // val path = p".$fieldName"
406
+ // ^^^^^^^^^^^^^
379
407
  ```
380
408
 
381
- **❌ This will also fail:**
409
+ Array indices also cannot be interpolated at runtime:
382
410
 
383
411
  ```scala
412
+ import zio.blocks.schema._
413
+
384
414
  val idx = 5
385
415
  val path = p"[$idx]"
386
416
  // Error: Path interpolator does not support runtime arguments.
387
- // Use only literal strings like p".field[0]"
417
+ // error:
418
+ // Path interpolator does not support runtime arguments. Use only literal strings like p".field[0]"
419
+ // val path = p"[$idx]"
420
+ // ^^^^^^^^^
388
421
  ```
389
422
 
390
- **✅ Use only literal strings:**
423
+ Instead, use only literal strings at compile time:
391
424
 
392
425
  ```scala
393
426
  val path = p".users[0].email" // ✓ Works
@@ -395,31 +428,46 @@ val path = p".users[0].email" // ✓ Works
395
428
 
396
429
  ### Parse Error Examples
397
430
 
398
- Invalid syntax is caught at compile time:
431
+ Invalid syntax is caught at compile time. Here are examples of common errors:
399
432
 
400
433
  ```scala
434
+ import zio.blocks.schema._
435
+
401
436
  // Unterminated string
402
437
  p"""{"foo"""
403
- // Error: Unterminated string literal starting at position 1
438
+ // Error: Unterminated string literal
404
439
 
405
- // Invalid escape sequence
440
+ // Invalid escape sequence
406
441
  p"""{"foo\x"}"""
407
- // Error: Invalid escape sequence '\x' at position 6
442
+ // Error: Invalid escape sequence
408
443
 
409
444
  // Unexpected character
410
445
  p".field@"
411
- // Error: Unexpected character '@' at position 6
446
+ // Error: Unexpected character '@'
412
447
 
413
448
  // Invalid identifier
414
449
  p"."
415
- // Error: Invalid identifier at position 1
450
+ // Error: Invalid identifier
451
+ // error:
452
+ // Unterminated string literal starting at position 1
453
+ // error:
454
+ // Invalid escape sequence '\x' at position 6
455
+ // error:
456
+ // Unexpected character '@' at position 6. Expected field, index, map, or variant accessor
457
+ // error:
458
+ // Invalid identifier at position 1
459
+ // error:
460
+ // Conflicting definitions:
461
+ // val path: zio.blocks.schema.DynamicOptic in object MdocApp at line 14 and
462
+ // val path: zio.blocks.schema.DynamicOptic in object MdocApp at line 114
463
+ //
416
464
  ```
417
465
 
418
466
  ## Performance
419
467
 
420
468
  **Zero Runtime Overhead**
421
469
 
422
- All path parsing and validation occurs at **compile time**. The interpolator generates the exact same bytecode as manual `DynamicOptic` construction:
470
+ All path parsing and validation occurs at **compile time**. The interpolator generates the exact same bytecode as manual `DynamicOptic` construction. Here's the comparison:
423
471
 
424
472
  ```scala
425
473
  // These produce identical bytecode:
@@ -436,8 +484,12 @@ There is **no runtime parsing**, **no reflection**, and **no performance penalty
436
484
 
437
485
  ## Examples
438
486
 
487
+ This section shows practical examples of using the path interpolator with realistic data structures.
488
+
439
489
  ### Accessing Nested Fields
440
490
 
491
+ To access deeply nested fields in a data structure:
492
+
441
493
  ```scala
442
494
  import zio.blocks.schema._
443
495
 
@@ -447,14 +499,18 @@ case class Person(name: String, age: Int, address: Address)
447
499
  // Access nested street field
448
500
  val streetPath = p".address.street"
449
501
 
450
- // Use with DynamicValue
451
- val person = DynamicValue.fromPerson(...)
502
+ // Use with DynamicValue - example (requires actual DynamicValue instance)
503
+ val person: DynamicValue = ???
452
504
  val street = person.get(streetPath)
453
505
  ```
454
506
 
455
507
  ### Working with Collections
456
508
 
509
+ To work with sequences and access elements by index or range:
510
+
457
511
  ```scala
512
+ import zio.blocks.schema._
513
+
458
514
  case class User(id: Int, email: String, tags: Seq[String])
459
515
  case class Company(name: String, users: Seq[User])
460
516
 
@@ -470,7 +526,11 @@ val specificUsersPath = p".users[0,2,5]"
470
526
 
471
527
  ### Map Lookups
472
528
 
529
+ To work with map data structures and access values by key:
530
+
473
531
  ```scala
532
+ import zio.blocks.schema._
533
+
474
534
  case class Config(
475
535
  settings: Map[String, String],
476
536
  ports: Map[Int, String]
@@ -491,13 +551,21 @@ val allPortsPath = p"ports{*:}"
491
551
 
492
552
  ### Variant Case Handling
493
553
 
554
+ To navigate variant cases in your data structures:
555
+
494
556
  ```scala
557
+ import zio.blocks.schema._
558
+
495
559
  sealed trait Result[+A]
496
560
  case class Success[A](value: A) extends Result[A]
497
561
  case class Failure(error: String) extends Result[Nothing]
498
562
 
499
563
  case class Response(result: Result[User])
564
+ ```
565
+
566
+ Use paths to navigate into specific cases:
500
567
 
568
+ ```scala
501
569
  // Navigate into Success case
502
570
  val successValuePath = p".result<Success>.value"
503
571
 
@@ -507,7 +575,11 @@ val errorPath = p".result<Failure>.error"
507
575
 
508
576
  ### Real-World Example: API Response
509
577
 
578
+ To extract specific data from complex nested API response structures:
579
+
510
580
  ```scala
581
+ import zio.blocks.schema._
582
+
511
583
  case class Metadata(tags: Seq[String], version: Int)
512
584
  case class Item(id: String, data: String, metadata: Metadata)
513
585
  case class ApiResponse(
@@ -531,8 +603,12 @@ val apiKeyPath = p"""config{"api_key"}"""
531
603
 
532
604
  ## Before & After Comparison
533
605
 
606
+ This comparison shows how the path interpolator simplifies optic path construction compared to manual approaches.
607
+
534
608
  ### Manual Construction (Before)
535
609
 
610
+ Manual path construction requires verbose imports and careful construction:
611
+
536
612
  ```scala
537
613
  import zio.blocks.schema.DynamicOptic
538
614
  import zio.blocks.schema.DynamicOptic.Node
@@ -582,7 +658,7 @@ val path2 = p""".root.children[*].metadata{"tags"}[0]"""
582
658
  val path3 = p"""data{"foo", "bar", 42}"""
583
659
  ```
584
660
 
585
- **Benefits:**
661
+ The path interpolator provides significant benefits:
586
662
 
587
663
  - **90% less code** for typical paths
588
664
  - **Easier to read** and understand intent
@@ -592,9 +668,15 @@ val path3 = p"""data{"foo", "bar", 42}"""
592
668
 
593
669
  ## Practical Usage Patterns
594
670
 
671
+ These patterns demonstrate effective ways to use the path interpolator in real-world scenarios.
672
+
595
673
  ### Building Paths Dynamically (at Compile Time)
596
674
 
675
+ While runtime variables are not supported, you can compose literal paths at compile time:
676
+
597
677
  ```scala
678
+ import zio.blocks.schema._
679
+
598
680
  // You can't use runtime variables, but you can compose literal paths:
599
681
  val basePath = p".data.items"
600
682
  val emailPath = basePath(p"[*].email")
@@ -603,26 +685,31 @@ val emailPath = basePath(p"[*].email")
603
685
 
604
686
  ### Working with DynamicValue
605
687
 
688
+ To navigate and extract values from dynamic data:
689
+
606
690
  ```scala
607
691
  import zio.blocks.schema._
608
692
 
609
- val data: DynamicValue = ...
693
+ val data: DynamicValue = ???
610
694
 
611
695
  // Navigate and extract
612
696
  val value = data.get(p".users[0].email")
613
697
 
614
- // Update at path
615
- val updated = data.set(p".users[0].age", DynamicValue.fromInt(30))
698
+ // Update at path (using appropriate constructor)
699
+ val ageValue: DynamicValue = ???
700
+ val updated = data.set(p".users[0].age", ageValue)
616
701
  ```
617
702
 
618
703
  ### Integration with Schema Optics
619
704
 
705
+ To use path interpolators with schema-based optics:
706
+
620
707
  ```scala
621
708
  import zio.blocks.schema._
622
709
 
623
- case class User(name: String, email: String)
624
- object User extends CompanionOptics[User] {
625
- implicit val schema: Schema[User] = Schema.derived
710
+ case class UserRecord(name: String, email: String)
711
+ object UserRecord extends CompanionOptics[UserRecord] {
712
+ implicit val schema: Schema[UserRecord] = Schema.derived
626
713
 
627
714
  // Use path interpolator for complex lenses
628
715
  val email = $(_.email)
@@ -634,23 +721,22 @@ val dynamicPath = p".email"
634
721
 
635
722
  ## Tips and Best Practices
636
723
 
637
- 1. **Use the leading dot for clarity**: While optional, `p".field"` is more explicit than `p"field"`
724
+ 1. **Use the leading dot for clarity**: While optional, `p".field"` is more explicit than `p"field"`:
638
725
 
639
- 2. **Leverage compile-time validation**: Let the compiler catch typos and syntax errors early
640
-
641
- 3. **Compose paths when needed**: Break complex paths into reusable components
642
- ```scala
726
+ ```scala mdoc:compile-only
643
727
  val userPath = p".users[0]"
644
728
  val emailPath = userPath(p".email")
645
729
  ```
646
730
 
647
- 4. **Use raw strings for map keys**: Triple-quoted strings avoid escape hell
648
- ```scala
731
+ 4. **Use raw strings for map keys**: Triple-quoted strings avoid escape hell:
732
+
733
+ ```scala mdoc:compile-only
649
734
  p"""config{"api.key"}""" // Better than p"config{\"api.key\"}"
650
735
  ```
651
736
 
652
- 5. **Document complex paths**: Add comments explaining what nested paths navigate
653
- ```scala
737
+ 5. **Document complex paths**: Add comments explaining what nested paths navigate:
738
+
739
+ ```scala mdoc:compile-only
654
740
  // Get the first tag from each user's metadata
655
741
  val tagsPath = p".users[*].metadata.tags[0]"
656
742
  ```
@@ -670,29 +756,36 @@ These limitations ensure compile-time safety and zero runtime overhead.
670
756
 
671
757
  ```scala
672
758
  val optic = DynamicOptic.root.field("users").elements.field("email")
759
+ // optic: DynamicOptic = DynamicOptic(
760
+ // IndexedSeq(Field("users"), Elements, Field("email"))
761
+ // )
673
762
  println(optic) // Output: .users[*].email
763
+ // .users[*].email
674
764
 
675
765
  // The output can be copy-pasted into p"..."
676
766
  val same = p".users[*].email"
767
+ // same: DynamicOptic = DynamicOptic(
768
+ // Vector(Field("users"), Elements, Field("email"))
769
+ // )
677
770
  ```
678
771
 
679
772
  **Examples:**
680
773
 
681
- | DynamicOptic Construction | toString Output |
682
- |------------------------------------------------------|-------------------|
683
- | `DynamicOptic.root.field("name")` | `.name` |
684
- | `DynamicOptic.root.field("address").field("street")` | `.address.street` |
685
- | `DynamicOptic.root.caseOf("Some")` | `<Some>` |
686
- | `DynamicOptic.root.at(0)` | `[0]` |
687
- | `DynamicOptic.root.atIndices(0, 2, 5)` | `[0,2,5]` |
688
- | `DynamicOptic.elements` | `[*]` |
689
- | `DynamicOptic.root.atKey("host")` | `{"host"}` |
690
- | `DynamicOptic.root.atKey(80)` | `{80}` |
691
- | `DynamicOptic.mapValues` | `{*}` |
692
- | `DynamicOptic.mapKeys` | `{*:}` |
693
- | `DynamicOptic.wrapped` | `.~` |
694
- | `DynamicOptic.root.searchSchema(SchemaRepr.Nominal("Person"))` | `#Person` |
695
- | `DynamicOptic.root.searchSchema(SchemaRepr.Primitive("string"))` | `#string` |
774
+ | DynamicOptic Construction | Interpolator Syntax |
775
+ |------------------------------------------------------|---------------------|
776
+ | `DynamicOptic.root.field("name")` | `p".name"` |
777
+ | `DynamicOptic.root.field("address").field("street")` | `p".address.street"` |
778
+ | `DynamicOptic.root.caseOf("Some")` | `p"<Some>"` |
779
+ | `DynamicOptic.root.at(0)` | `p"[0]"` |
780
+ | `DynamicOptic.root.atIndices(0, 2, 5)` | `p"[0,2,5]"` |
781
+ | `DynamicOptic.elements` | `p"[*]"` |
782
+ | `DynamicOptic.root.atKey("host")` | `p"{"host"}"` |
783
+ | `DynamicOptic.root.atKey(80)` | `p"{80}"` |
784
+ | `DynamicOptic.mapValues` | `p"{*}"` |
785
+ | `DynamicOptic.mapKeys` | `p"{*:}"` |
786
+ | `DynamicOptic.wrapped` | `p".~"` |
787
+ | `DynamicOptic.root.searchSchema(SchemaRepr.Nominal("Person"))` | `p"#Person"` |
788
+ | `DynamicOptic.root.searchSchema(SchemaRepr.Primitive("string"))` | `p"#string"` |
696
789
 
697
790
  ## Summary
698
791