@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,212 @@
1
+ ---
2
+ id: segment-codec
3
+ title: "SegmentCodec"
4
+ ---
5
+
6
+ `SegmentCodec[A]` describes a single URL path segment. It supports basic typed segment kinds — `SegmentCodec.bool`, `SegmentCodec.int`, `SegmentCodec.long`, `SegmentCodec.string`, `SegmentCodec.uuid`, and `SegmentCodec.literal` — as well as intra-segment composition via `~`, which combines multiple typed parts within a single path segment (for example, `v42` as a literal prefix followed by an integer). Ambiguous combinations are rejected at compile time by a Scala 3 macro. Alongside the runtime decoded value type `A`, every segment codec also carries phantom metadata describing its boundary behavior and any declared path variable. The core type-level shape is:
7
+
8
+ ```scala
9
+ sealed trait SegmentCodec[A] {
10
+ type Prefix <: SegmentCodec.BoundaryTag
11
+ type Suffix <: SegmentCodec.BoundaryTag
12
+ type PathVars
13
+ }
14
+ ```
15
+
16
+ `PathVars` is purely type-level: it has zero runtime footprint. Capturing segments contribute one marker (for example `PathVar["id", Int]`), while non-capturing segments like `literal` and `Trailing` contribute none.
17
+
18
+ (The trait also includes additional members for documentation, examples, formatting, and rendering.)
19
+
20
+ ## Motivation
21
+
22
+ Standard routing libraries treat path segments as plain strings, deferring all parsing to handler code. `SegmentCodec` encodes the type of each segment statically, so the compiler knows whether a segment produces an `Int`, a `UUID`, or a custom domain type. This enables:
23
+
24
+ - **Type-safe path building**: `PathCodec.int("id")` produces a `PathCodec[Int]`, not `PathCodec[String]`.
25
+ - **Bidirectional conversion**: every `SegmentCodec` can both decode a string into `A` and format an `A` back to a string.
26
+ - **Compile-time combination validation**: the `~` operator is a macro that validates boundary constraints, rejecting combinations like `string ~ string` before the code compiles.
27
+
28
+ ## Segment Kinds
29
+
30
+ Each segment kind maps to a specific URL token type. Literal segments match a fixed string; the others capture and parse dynamic values.
31
+
32
+ ### Literal segments
33
+
34
+ A `Literal` segment matches exactly one fixed string value. Use `SegmentCodec.literal` with a compile-time string constant:
35
+
36
+ ```scala
37
+ import zio.blocks.endpoint._
38
+ import zio.blocks.endpoint.RoutePattern._
39
+
40
+ val usersLit: SegmentCodec.Literal = SegmentCodec.literal("users")
41
+ ```
42
+
43
+ `SegmentCodec.literal` is a macro: it validates that the value is a non-empty, URL-safe, single-segment string at compile time and rejects `""`, `"foo/bar"`, or strings requiring percent-encoding.
44
+
45
+ ### Typed dynamic segments
46
+
47
+ Standard typed segment constructors each accept a name string for documentation and OpenAPI path parameter labels:
48
+
49
+ ```scala
50
+ import zio.blocks.endpoint._
51
+ import zio.blocks.endpoint.RoutePattern._
52
+
53
+ val boolSeg: SegmentCodec[Boolean] = SegmentCodec.bool("flag")
54
+ val intSeg: SegmentCodec[Int] = SegmentCodec.int("id")
55
+ val longSeg: SegmentCodec[Long] = SegmentCodec.long("id")
56
+ val stringSeg: SegmentCodec[String] = SegmentCodec.string("slug")
57
+ val uuidSeg: SegmentCodec[java.util.UUID] = SegmentCodec.uuid("id")
58
+ ```
59
+
60
+ When the name is written as a literal string, that literal is preserved in the phantom `PathVars` marker. For example, `SegmentCodec.int("id")` contributes `PathVar["id", Int]`.
61
+
62
+ If a route should keep a captured segment for matching/formatting but explicitly mark it as intentionally unused for downstream tooling, the leaf dynamic segment codecs expose `.unused`:
63
+
64
+ ```scala
65
+ import zio.blocks.endpoint._
66
+ import zio.blocks.endpoint.RoutePattern._
67
+
68
+ val requiredId: SegmentCodec[Int] = SegmentCodec.int("id")
69
+ val ignoredId: SegmentCodec[Int] = SegmentCodec.int("id").unused
70
+ ```
71
+
72
+ `.unused` keeps decoding, formatting, rendering, and composition identical, but changes the phantom marker from `PathVar[Name, Type]` to `PathVar.Ignored[Name, Type]`.
73
+
74
+ The ordering of match priority in the routing trie follows the kind: `Literal` matches first, then `Int`, `Long`, `UUID`, `Bool`, `String`, `Combined`, and `Trailing` last.
75
+
76
+ ### Trailing segment
77
+
78
+ `SegmentCodec.Trailing` captures all remaining path segments as a `zio.http.Path`. Use it for wildcard routes; it always has the lowest priority in the trie:
79
+
80
+ ```scala
81
+ import zio.blocks.endpoint._
82
+ import zio.blocks.endpoint.RoutePattern._
83
+ import zio.http.Path
84
+
85
+ val rest: SegmentCodec[Path] = SegmentCodec.Trailing
86
+ ```
87
+
88
+ ## Intra-Segment Composition with `~`
89
+
90
+ The `~` operator combines two `SegmentCodec` values into a `Combined` codec that matches a single path segment containing both parts consecutively. This is useful for version strings like `v42` or prefixed identifiers like `usr-550e8400`:
91
+
92
+ ```scala
93
+ import zio.blocks.endpoint._
94
+ import zio.blocks.endpoint.RoutePattern._
95
+
96
+ val versionSeg: SegmentCodec[Int] =
97
+ SegmentCodec.literal("v") ~ SegmentCodec.int("major")
98
+ ```
99
+
100
+ The type is automatically flattened (eliminating `Unit` from the literal), so the resulting codec decodes `"v42"` into `42` and formats `42` back to `"v42"`.
101
+
102
+ ### Compile-time boundary validation
103
+
104
+ The `~` operator is a macro that checks `BoundaryTag` phantom types at compile time. Two categories of combination are always rejected:
105
+
106
+ - **Two string segments**: `SegmentCodec.string("a") ~ SegmentCodec.string("b")` — both are unbounded greedy matchers; the parser cannot know where one ends and the other begins.
107
+ - **Two numeric segments**: `SegmentCodec.int("a") ~ SegmentCodec.int("b")` — numeric segments are also ambiguously bounded.
108
+
109
+ Combinations that are safe compile successfully:
110
+
111
+ ```scala
112
+ import zio.blocks.endpoint._
113
+ import zio.blocks.endpoint.RoutePattern._
114
+
115
+ // Safe: literal delimiter separates two dynamic segments
116
+ val versionMajorMinor =
117
+ SegmentCodec.literal("v") ~ SegmentCodec.int("major") ~
118
+ SegmentCodec.literal("x") ~ SegmentCodec.int("minor")
119
+
120
+ // Safe: UUID in the middle, bounded by strings on both sides
121
+ val prefixedUuid =
122
+ SegmentCodec.string("prefix") ~ SegmentCodec.uuid("id") ~ SegmentCodec.string("suffix")
123
+ ```
124
+
125
+ Attempting an ambiguous combination like `string ~ string` produces a compiler error describing the constraint violation, not a runtime failure.
126
+
127
+ ## Type Transformations
128
+
129
+ Use these methods to remap the value a codec decodes or encodes without changing the underlying segment structure or its compile-time boundary tags.
130
+
131
+ ### `SegmentCodec#transform`
132
+
133
+ To map the decoded segment value to a different type, use `SegmentCodec#transform`. Both the decode and encode functions must be total:
134
+
135
+ ```scala
136
+ import zio.blocks.endpoint._
137
+ import zio.blocks.endpoint.RoutePattern._
138
+
139
+ final case class UserId(value: java.util.UUID)
140
+
141
+ val userIdSeg: SegmentCodec[UserId] =
142
+ SegmentCodec.uuid("id").transform[UserId](UserId(_), _.value)
143
+ ```
144
+
145
+ `SegmentCodec#transform` preserves the `BoundaryTag` types of the original codec, so transformed codecs still participate in compile-time `~` boundary validation.
146
+
147
+ It also preserves the original `PathVars` marker unchanged: transforming a captured `SegmentCodec.int("id")` into a domain type still records that the segment came from the declared `"id"` path variable.
148
+
149
+ ### `SegmentCodec#transformOrFail`
150
+
151
+ When decoding can fail, use `SegmentCodec#transformOrFail`. A `Left` result causes segment matching to fail for that candidate:
152
+
153
+ ```scala
154
+ import zio.blocks.endpoint._
155
+ import zio.blocks.endpoint.RoutePattern._
156
+
157
+ final case class PositiveInt(value: Int)
158
+
159
+ val positiveIntSeg: SegmentCodec[PositiveInt] =
160
+ SegmentCodec.int("count").transformOrFail[PositiveInt](
161
+ n => if (n > 0) Right(PositiveInt(n)) else Left(s"Expected positive, got $n"),
162
+ p => Right(p.value)
163
+ )
164
+ ```
165
+
166
+ ## Formatting and Rendering
167
+
168
+ These methods convert a typed value back to a string for use in URL construction and documentation output.
169
+
170
+ ### `SegmentCodec#format`
171
+
172
+ To format a typed value into a single-segment `Path`:
173
+
174
+ ```scala
175
+ import zio.blocks.endpoint._
176
+ import zio.blocks.endpoint.RoutePattern._
177
+ import zio.http.Path
178
+
179
+ val seg = SegmentCodec.int("id")
180
+ val path: Path = seg.format(42)
181
+ ```
182
+
183
+ ### `SegmentCodec#render`
184
+
185
+ To produce the human-readable representation of the segment for use in OpenAPI path parameters and documentation:
186
+
187
+ ```scala
188
+ import zio.blocks.endpoint._
189
+ import zio.blocks.endpoint.RoutePattern._
190
+
191
+ val intSeg = SegmentCodec.int("id")
192
+ val rendered: String = intSeg.render()
193
+ ```
194
+
195
+ By default, `SegmentCodec.render` produces `/{name}` for dynamic segments and `/{value}` for literal segments (including the leading slash in both cases). This leading slash is part of the segment's representation, not added by path composition. To customize the format, pass prefix and suffix arguments: `intSeg.render(":", "")` produces `/:id`. Both dynamic and literal segments always include this leading slash in their rendered form.
196
+
197
+ ## Priority Ordering
198
+
199
+ When `RouteTree` builds a routing trie, it uses `SegmentCodec.Kind` ordering to resolve ambiguous matches. Literals always win; within dynamic segments, more specific types take priority:
200
+
201
+ | Priority | Kind |
202
+ | -------- | ---------- |
203
+ | 1 | `Literal` |
204
+ | 2 | `Int` |
205
+ | 3 | `Long` |
206
+ | 4 | `UUID` |
207
+ | 5 | `Bool` |
208
+ | 6 | `String` |
209
+ | 7 | `Combined` |
210
+ | 8 | `Trailing` |
211
+
212
+ This ordering ensures that `/users/42` matches an `Int` route before a `String` route, and `/users/active` matches a `String` route because `"active"` is not a valid integer.