effect 4.0.0-beta.97 → 4.0.0-beta.98

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 (166) hide show
  1. package/dist/LayerRef.d.ts +4 -6
  2. package/dist/LayerRef.d.ts.map +1 -1
  3. package/dist/LayerRef.js +4 -6
  4. package/dist/LayerRef.js.map +1 -1
  5. package/dist/Number.d.ts.map +1 -1
  6. package/dist/Number.js +28 -10
  7. package/dist/Number.js.map +1 -1
  8. package/dist/Schema.d.ts +22 -22
  9. package/dist/Schema.d.ts.map +1 -1
  10. package/dist/Schema.js +36 -33
  11. package/dist/Schema.js.map +1 -1
  12. package/dist/SchemaAST.d.ts.map +1 -1
  13. package/dist/SchemaAST.js +25 -10
  14. package/dist/SchemaAST.js.map +1 -1
  15. package/dist/SchemaError.d.ts +53 -0
  16. package/dist/SchemaError.d.ts.map +1 -0
  17. package/dist/SchemaError.js +61 -0
  18. package/dist/SchemaError.js.map +1 -0
  19. package/dist/SchemaGetter.d.ts.map +1 -1
  20. package/dist/SchemaGetter.js +17 -12
  21. package/dist/SchemaGetter.js.map +1 -1
  22. package/dist/SchemaRepresentation.d.ts.map +1 -1
  23. package/dist/SchemaRepresentation.js +186 -224
  24. package/dist/SchemaRepresentation.js.map +1 -1
  25. package/dist/index.d.ts +8 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +8 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/internal/effect.js +26 -8
  30. package/dist/internal/effect.js.map +1 -1
  31. package/dist/internal/schema/equivalence.js +1 -2
  32. package/dist/internal/schema/equivalence.js.map +1 -1
  33. package/dist/internal/schema/representation.js +1 -3
  34. package/dist/internal/schema/representation.js.map +1 -1
  35. package/dist/internal/schema/schema.d.ts +0 -13
  36. package/dist/internal/schema/schema.d.ts.map +1 -1
  37. package/dist/internal/schema/schema.js +4 -29
  38. package/dist/internal/schema/schema.js.map +1 -1
  39. package/dist/unstable/ai/McpSchema.d.ts +128 -128
  40. package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
  41. package/dist/unstable/cli/CliError.d.ts +8 -16
  42. package/dist/unstable/cli/CliError.d.ts.map +1 -1
  43. package/dist/unstable/cli/CliError.js +8 -16
  44. package/dist/unstable/cli/CliError.js.map +1 -1
  45. package/dist/unstable/cli/Command.d.ts +4 -3
  46. package/dist/unstable/cli/Command.d.ts.map +1 -1
  47. package/dist/unstable/cli/Command.js +3 -3
  48. package/dist/unstable/cli/Command.js.map +1 -1
  49. package/dist/unstable/cli/GlobalFlag.d.ts +6 -8
  50. package/dist/unstable/cli/GlobalFlag.d.ts.map +1 -1
  51. package/dist/unstable/cli/GlobalFlag.js +6 -6
  52. package/dist/unstable/cli/GlobalFlag.js.map +1 -1
  53. package/dist/unstable/cluster/EntityProxyServer.d.ts +1 -1
  54. package/dist/unstable/cluster/EntityProxyServer.d.ts.map +1 -1
  55. package/dist/unstable/cluster/EntityProxyServer.js +2 -4
  56. package/dist/unstable/cluster/EntityProxyServer.js.map +1 -1
  57. package/dist/unstable/cluster/internal/entityManager.js +15 -12
  58. package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
  59. package/dist/unstable/httpapi/HttpApi.d.ts +36 -15
  60. package/dist/unstable/httpapi/HttpApi.d.ts.map +1 -1
  61. package/dist/unstable/httpapi/HttpApi.js +19 -20
  62. package/dist/unstable/httpapi/HttpApi.js.map +1 -1
  63. package/dist/unstable/httpapi/HttpApiBuilder.d.ts +51 -62
  64. package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
  65. package/dist/unstable/httpapi/HttpApiBuilder.js +68 -58
  66. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  67. package/dist/unstable/httpapi/HttpApiClient.d.ts +53 -53
  68. package/dist/unstable/httpapi/HttpApiClient.d.ts.map +1 -1
  69. package/dist/unstable/httpapi/HttpApiClient.js +40 -30
  70. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  71. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +165 -164
  72. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
  73. package/dist/unstable/httpapi/HttpApiEndpoint.js +31 -19
  74. package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
  75. package/dist/unstable/httpapi/HttpApiError.d.ts +22 -0
  76. package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
  77. package/dist/unstable/httpapi/HttpApiError.js +31 -0
  78. package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
  79. package/dist/unstable/httpapi/HttpApiGroup.d.ts +55 -30
  80. package/dist/unstable/httpapi/HttpApiGroup.d.ts.map +1 -1
  81. package/dist/unstable/httpapi/HttpApiGroup.js +22 -29
  82. package/dist/unstable/httpapi/HttpApiGroup.js.map +1 -1
  83. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts +8 -8
  84. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts.map +1 -1
  85. package/dist/unstable/httpapi/HttpApiMiddleware.js.map +1 -1
  86. package/dist/unstable/httpapi/HttpApiScalar.d.ts +2 -2
  87. package/dist/unstable/httpapi/HttpApiScalar.d.ts.map +1 -1
  88. package/dist/unstable/httpapi/HttpApiScalar.js +4 -3
  89. package/dist/unstable/httpapi/HttpApiScalar.js.map +1 -1
  90. package/dist/unstable/httpapi/HttpApiSchema.d.ts +8 -0
  91. package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
  92. package/dist/unstable/httpapi/HttpApiSchema.js.map +1 -1
  93. package/dist/unstable/httpapi/HttpApiSwagger.d.ts +1 -1
  94. package/dist/unstable/httpapi/HttpApiSwagger.d.ts.map +1 -1
  95. package/dist/unstable/httpapi/HttpApiSwagger.js.map +1 -1
  96. package/dist/unstable/httpapi/HttpApiTest.d.ts +4 -4
  97. package/dist/unstable/httpapi/HttpApiTest.d.ts.map +1 -1
  98. package/dist/unstable/httpapi/HttpApiTest.js +9 -8
  99. package/dist/unstable/httpapi/HttpApiTest.js.map +1 -1
  100. package/dist/unstable/httpapi/OpenApi.d.ts +1 -1
  101. package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
  102. package/dist/unstable/httpapi/OpenApi.js +77 -37
  103. package/dist/unstable/httpapi/OpenApi.js.map +1 -1
  104. package/dist/unstable/httpapi/internal/html.js +6 -2
  105. package/dist/unstable/httpapi/internal/html.js.map +1 -1
  106. package/dist/unstable/httpapi/internal/mediaType.d.ts +2 -0
  107. package/dist/unstable/httpapi/internal/mediaType.d.ts.map +1 -0
  108. package/dist/unstable/httpapi/internal/mediaType.js +7 -0
  109. package/dist/unstable/httpapi/internal/mediaType.js.map +1 -0
  110. package/dist/unstable/persistence/PersistedQueue.d.ts.map +1 -1
  111. package/dist/unstable/persistence/PersistedQueue.js +16 -12
  112. package/dist/unstable/persistence/PersistedQueue.js.map +1 -1
  113. package/dist/unstable/reactivity/Atom.js +1 -1
  114. package/dist/unstable/reactivity/Atom.js.map +1 -1
  115. package/dist/unstable/reactivity/AtomHttpApi.d.ts +7 -7
  116. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  117. package/dist/unstable/reactivity/AtomHttpApi.js +3 -2
  118. package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
  119. package/dist/unstable/rpc/RpcServer.d.ts +3 -1
  120. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  121. package/dist/unstable/rpc/RpcServer.js +6 -3
  122. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  123. package/dist/unstable/workflow/DurableDeferred.js +1 -1
  124. package/dist/unstable/workflow/DurableDeferred.js.map +1 -1
  125. package/dist/unstable/workflow/WorkflowProxyServer.d.ts +1 -1
  126. package/dist/unstable/workflow/WorkflowProxyServer.d.ts.map +1 -1
  127. package/dist/unstable/workflow/WorkflowProxyServer.js +1 -2
  128. package/dist/unstable/workflow/WorkflowProxyServer.js.map +1 -1
  129. package/package.json +1 -1
  130. package/src/LayerRef.ts +4 -6
  131. package/src/Number.ts +29 -10
  132. package/src/Schema.ts +42 -34
  133. package/src/SchemaAST.ts +25 -13
  134. package/src/SchemaError.ts +64 -0
  135. package/src/SchemaGetter.ts +22 -16
  136. package/src/SchemaRepresentation.ts +165 -202
  137. package/src/index.ts +10 -0
  138. package/src/internal/effect.ts +39 -22
  139. package/src/internal/schema/equivalence.ts +1 -2
  140. package/src/internal/schema/representation.ts +4 -4
  141. package/src/internal/schema/schema.ts +4 -37
  142. package/src/unstable/cli/CliError.ts +24 -16
  143. package/src/unstable/cli/Command.ts +8 -8
  144. package/src/unstable/cli/GlobalFlag.ts +22 -33
  145. package/src/unstable/cluster/EntityProxyServer.ts +15 -17
  146. package/src/unstable/cluster/internal/entityManager.ts +48 -34
  147. package/src/unstable/httpapi/HttpApi.ts +72 -47
  148. package/src/unstable/httpapi/HttpApiBuilder.ts +320 -217
  149. package/src/unstable/httpapi/HttpApiClient.ts +196 -151
  150. package/src/unstable/httpapi/HttpApiEndpoint.ts +251 -447
  151. package/src/unstable/httpapi/HttpApiError.ts +33 -0
  152. package/src/unstable/httpapi/HttpApiGroup.ts +95 -74
  153. package/src/unstable/httpapi/HttpApiMiddleware.ts +10 -7
  154. package/src/unstable/httpapi/HttpApiScalar.ts +15 -12
  155. package/src/unstable/httpapi/HttpApiSchema.ts +8 -0
  156. package/src/unstable/httpapi/HttpApiSwagger.ts +2 -2
  157. package/src/unstable/httpapi/HttpApiTest.ts +15 -14
  158. package/src/unstable/httpapi/OpenApi.ts +74 -36
  159. package/src/unstable/httpapi/internal/html.ts +9 -2
  160. package/src/unstable/httpapi/internal/mediaType.ts +6 -0
  161. package/src/unstable/persistence/PersistedQueue.ts +16 -14
  162. package/src/unstable/reactivity/Atom.ts +1 -1
  163. package/src/unstable/reactivity/AtomHttpApi.ts +164 -162
  164. package/src/unstable/rpc/RpcServer.ts +10 -4
  165. package/src/unstable/workflow/DurableDeferred.ts +1 -1
  166. package/src/unstable/workflow/WorkflowProxyServer.ts +11 -12
@@ -30,7 +30,7 @@ import * as SchemaIssue from "../../SchemaIssue.ts"
30
30
  import * as SchemaTransformation from "../../SchemaTransformation.ts"
31
31
  import * as Scope from "../../Scope.ts"
32
32
  import * as Stream from "../../Stream.ts"
33
- import type { Covariant, NoInfer } from "../../Types.ts"
33
+ import type { NoInfer } from "../../Types.ts"
34
34
  import * as UndefinedOr from "../../UndefinedOr.ts"
35
35
  import * as Sse from "../encoding/Sse.ts"
36
36
  import type { Cookie } from "../http/Cookies.ts"
@@ -52,6 +52,7 @@ import type * as HttpApiGroup from "./HttpApiGroup.ts"
52
52
  import * as HttpApiMiddleware from "./HttpApiMiddleware.ts"
53
53
  import * as HttpApiSchema from "./HttpApiSchema.ts"
54
54
  import type * as HttpApiSecurity from "./HttpApiSecurity.ts"
55
+ import * as MediaType from "./internal/mediaType.ts"
55
56
  import * as OpenApi from "./OpenApi.ts"
56
57
 
57
58
  /**
@@ -60,7 +61,7 @@ import * as OpenApi from "./OpenApi.ts"
60
61
  * @category constructors
61
62
  * @since 4.0.0
62
63
  */
63
- export const layer = <Id extends string, Groups extends HttpApiGroup.Any>(
64
+ export const layer = <Id extends string, Groups extends HttpApiGroup.Constraint>(
64
65
  api: HttpApi.HttpApi<Id, Groups>,
65
66
  options?: {
66
67
  readonly openapiPath?: `/${string}` | undefined
@@ -87,7 +88,8 @@ export const layer = <Id extends string, Groups extends HttpApiGroup.Any>(
87
88
  const availableGroups = Array.from(services.mapUnsafe.keys()).filter((key) =>
88
89
  key.startsWith("effect/httpapi/HttpApiGroup/")
89
90
  )
90
- for (const group of Object.values(api.groups)) {
91
+ const groups = Object.values(api.groups) as ReadonlyArray<HttpApiGroup.Top>
92
+ for (const group of groups) {
91
93
  const groupRoutes = services.mapUnsafe.get(group.key)?.routes as Array<HttpRouter.Route<any, any>>
92
94
  if (groupRoutes === undefined) {
93
95
  const available = availableGroups.length === 0 ? "none" : availableGroups.join(", ")
@@ -118,17 +120,17 @@ export const layer = <Id extends string, Groups extends HttpApiGroup.Any>(
118
120
  */
119
121
  export const group = <
120
122
  ApiId extends string,
121
- Groups extends HttpApiGroup.Any,
122
- const Name extends HttpApiGroup.Name<Groups>,
123
+ Groups extends HttpApiGroup.Constraint,
124
+ const Identifier extends HttpApiGroup.Identifier<Groups>,
123
125
  Return
124
126
  >(
125
127
  api: HttpApi.HttpApi<ApiId, Groups>,
126
- groupName: Name,
128
+ groupIdentifier: Identifier,
127
129
  build: (
128
- handlers: Handlers.FromGroup<HttpApiGroup.WithName<Groups, Name>>
130
+ handlers: Handlers.FromGroup<HttpApiGroup.WithIdentifier<Groups, Identifier>>
129
131
  ) => Handlers.ValidateReturn<Return>
130
132
  ): Layer.Layer<
131
- HttpApiGroup.ApiGroup<ApiId, Name>,
133
+ HttpApiGroup.Service<ApiId, Identifier>,
132
134
  Handlers.Error<Return>,
133
135
  Exclude<Handlers.Context<Return>, Scope.Scope>
134
136
  > =>
@@ -136,9 +138,9 @@ export const group = <
136
138
  const services = (yield* Effect.context<any>()).pipe(
137
139
  Context.omit(Scope.Scope)
138
140
  )
139
- const group = api.groups[groupName]!
141
+ const group = api.groups[groupIdentifier] as HttpApiGroup.Constraint
140
142
  const result = build(makeHandlers(group))
141
- const handlers: Handlers<any, any> = Effect.isEffect(result)
143
+ const handlers: Handlers<any, any, any> = Effect.isEffect(result)
142
144
  ? (yield* result as Effect.Effect<any, any, any>)
143
145
  : result
144
146
  const routes: Array<HttpRouter.Route<any, any>> = []
@@ -153,21 +155,96 @@ export const group = <
153
155
  )
154
156
  })) as any
155
157
 
156
- /**
157
- * Type identifier symbol used to brand `Handlers` values.
158
- *
159
- * @category type IDs
160
- * @since 4.0.0
161
- */
162
- export const HandlersTypeId: unique symbol = Symbol.for("@effect/platform/HttpApiBuilder/Handlers")
158
+ const HandlersTypeId = "~effect/httpapi/HttpApiBuilder/Handlers"
163
159
 
164
- /**
165
- * Type of the `Handlers` type identifier symbol.
166
- *
167
- * @category type IDs
168
- * @since 4.0.0
169
- */
170
- export type HandlersTypeId = typeof HandlersTypeId
160
+ type EndpointMap<Endpoints extends HttpApiEndpoint.Constraint> = {
161
+ readonly [Endpoint in Endpoints as HttpApiEndpoint.Identifier<Endpoint>]: Endpoint
162
+ }
163
+
164
+ type HandlerRequirements<
165
+ Endpoint extends HttpApiEndpoint.Constraint,
166
+ R1,
167
+ R = HttpApiEndpoint.ExcludeProvided<
168
+ Endpoint,
169
+ R1 | HttpApiEndpoint.ServerServices<Endpoint>
170
+ >
171
+ > =
172
+ | HttpApiEndpoint.Middleware<Endpoint>
173
+ | HttpApiEndpoint.MiddlewareServices<Endpoint>
174
+ | ([R] extends [never] ? never : HttpRouter.Request<"Requires", R>)
175
+
176
+ interface HandlerOptions {
177
+ readonly uninterruptible?: boolean | undefined
178
+ }
179
+
180
+ /** @internal */
181
+ export interface HandlerRuntime {
182
+ readonly endpoint: HttpApiEndpoint.Top
183
+ readonly handler: HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, unknown, unknown>
184
+ readonly isRaw: boolean
185
+ readonly uninterruptible: boolean
186
+ }
187
+
188
+ type HandleAllEntry<Endpoint extends HttpApiEndpoint.Constraint> =
189
+ | HttpApiEndpoint.Handler<
190
+ Endpoint,
191
+ HttpApiEndpoint.MiddlewareError<Endpoint>,
192
+ unknown
193
+ >
194
+ | {
195
+ readonly handler: HttpApiEndpoint.Handler<
196
+ Endpoint,
197
+ HttpApiEndpoint.MiddlewareError<Endpoint>,
198
+ unknown
199
+ >
200
+ readonly options?: HandlerOptions | undefined
201
+ }
202
+
203
+ type HandleAllHandlers<EndpointsByIdentifier extends Record<string, HttpApiEndpoint.Constraint>> = {
204
+ readonly [Identifier in keyof EndpointsByIdentifier]?: HandleAllEntry<EndpointsByIdentifier[Identifier]>
205
+ }
206
+
207
+ type HandleAllExtraKeys<
208
+ EndpointsByIdentifier extends Record<string, HttpApiEndpoint.Constraint>,
209
+ HandlersByIdentifier
210
+ > = {
211
+ readonly [Identifier in Exclude<keyof HandlersByIdentifier, keyof EndpointsByIdentifier>]: never
212
+ }
213
+
214
+ type NotHandledIdentifier<Identifier extends PropertyKey, HandledIdentifiers extends PropertyKey> = Identifier extends
215
+ HandledIdentifiers ? never :
216
+ unknown
217
+
218
+ type HandleAllEntryHandler<Entry> = Entry extends { readonly handler: infer Handler } ? Handler : Entry
219
+
220
+ type HandleAllRequirements<
221
+ EndpointsByIdentifier extends Record<string, HttpApiEndpoint.Constraint>,
222
+ HandlersByIdentifier extends HandleAllHandlers<EndpointsByIdentifier>
223
+ > = {
224
+ readonly [Identifier in keyof HandlersByIdentifier & keyof EndpointsByIdentifier]: HandleAllEntryHandler<
225
+ HandlersByIdentifier[Identifier]
226
+ > extends HttpApiEndpoint.Handler<
227
+ EndpointsByIdentifier[Identifier],
228
+ HttpApiEndpoint.MiddlewareError<EndpointsByIdentifier[Identifier]>,
229
+ infer R1
230
+ > ? HandlerRequirements<EndpointsByIdentifier[Identifier], R1> :
231
+ never
232
+ }[keyof HandlersByIdentifier & keyof EndpointsByIdentifier]
233
+
234
+ type HandlersResult<A> = A extends Effect.Effect<infer H, any, any> ? H : A
235
+
236
+ type MissingHandlerNames<H extends Handlers<any, any, any>> = Exclude<
237
+ keyof H["~EndpointsByIdentifier"],
238
+ H["~HandledIdentifiers"]
239
+ >
240
+
241
+ type ValidateHandlersReturn<
242
+ A,
243
+ H = HandlersResult<A>,
244
+ Missing = H extends Handlers<any, any, any> ? MissingHandlerNames<H> : never
245
+ > = H extends Handlers<any, any, any> ? [Missing] extends [never] ? A
246
+ : `Endpoint not handled: ${Missing & string}`
247
+ : `Must return the implemented handlers`
171
248
 
172
249
  /**
173
250
  * Mutable handler collection for one `HttpApi` group.
@@ -175,59 +252,77 @@ export type HandlersTypeId = typeof HandlersTypeId
175
252
  * **Details**
176
253
  *
177
254
  * Each call to `handle` or `handleRaw` registers an endpoint implementation and
178
- * removes that endpoint from the type-level set of endpoints still requiring
179
- * handlers.
255
+ * adds that endpoint identifier to the type-level set of implemented endpoints.
256
+ * Endpoint identifiers that were already handled are rejected at the type level.
180
257
  *
181
258
  * @category handlers
182
259
  * @since 4.0.0
183
260
  */
184
261
  export interface Handlers<
185
262
  R,
186
- Endpoints extends HttpApiEndpoint.Any = never
263
+ EndpointsByIdentifier extends Record<string, HttpApiEndpoint.Constraint> = {},
264
+ HandledIdentifiers extends keyof EndpointsByIdentifier = never
187
265
  > extends Pipeable {
188
- readonly [HandlersTypeId]: {
189
- _Endpoints: Covariant<Endpoints>
190
- }
191
- readonly group: HttpApiGroup.AnyWithProps
192
- readonly handlers: Map<string, Handlers.Item<R>>
266
+ readonly [HandlersTypeId]: typeof HandlersTypeId
267
+ readonly "~EndpointsByIdentifier": EndpointsByIdentifier
268
+ readonly "~HandledIdentifiers": HandledIdentifiers
269
+ /** @internal */
270
+ readonly group: HttpApiGroup.Top
271
+ /** @internal */
272
+ readonly handlers: Map<string, HandlerRuntime>
193
273
 
194
274
  /**
195
- * Add the implementation for an `HttpApiEndpoint` to a `Handlers` group.
275
+ * Add the implementation for an unhandled `HttpApiEndpoint` to a `Handlers` group.
196
276
  */
197
- handle<Name extends HttpApiEndpoint.Name<Endpoints>, R1>(
198
- name: Name,
199
- handler: HttpApiEndpoint.HandlerWithName<Endpoints, Name, HttpApiEndpoint.ErrorsWithName<Endpoints, Name>, R1>,
277
+ handle<
278
+ Identifier extends keyof EndpointsByIdentifier,
279
+ R1
280
+ >(
281
+ identifier: Identifier & NotHandledIdentifier<Identifier, HandledIdentifiers>,
282
+ handler: HttpApiEndpoint.Handler<
283
+ EndpointsByIdentifier[Identifier],
284
+ HttpApiEndpoint.MiddlewareError<EndpointsByIdentifier[Identifier]>,
285
+ R1
286
+ >,
200
287
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
201
288
  ): Handlers<
202
- | R
203
- | HttpApiEndpoint.MiddlewareWithName<Endpoints, Name>
204
- | HttpApiEndpoint.MiddlewareServicesWithName<Endpoints, Name>
205
- | (HttpApiEndpoint.ExcludeProvidedWithName<
206
- Endpoints,
207
- Name,
208
- R1 | HttpApiEndpoint.ServerServicesWithName<Endpoints, Name>
209
- > extends infer _R ? _R extends never ? never : HttpRouter.Request<"Requires", _R> : never),
210
- HttpApiEndpoint.ExcludeName<Endpoints, Name>
289
+ R | HandlerRequirements<EndpointsByIdentifier[Identifier], R1>,
290
+ EndpointsByIdentifier,
291
+ HandledIdentifiers | Identifier
211
292
  >
212
293
 
213
294
  /**
214
- * Add the implementation for an `HttpApiEndpoint` to a `Handlers` group.
295
+ * Add implementations for unhandled `HttpApiEndpoint`s in a `Handlers` group.
296
+ */
297
+ handleAll<const HandlersByIdentifier extends HandleAllHandlers<Omit<EndpointsByIdentifier, HandledIdentifiers>>>(
298
+ handlers:
299
+ & HandlersByIdentifier
300
+ & HandleAllExtraKeys<Omit<EndpointsByIdentifier, HandledIdentifiers>, HandlersByIdentifier>
301
+ ): Handlers<
302
+ R | HandleAllRequirements<EndpointsByIdentifier, HandlersByIdentifier>,
303
+ EndpointsByIdentifier,
304
+ HandledIdentifiers | keyof HandlersByIdentifier & keyof EndpointsByIdentifier
305
+ >
306
+
307
+ /**
308
+ * Add the implementation for an unhandled `HttpApiEndpoint` to a `Handlers` group.
215
309
  * This version opts out of automatic payload decoding and provides the raw request.
216
310
  */
217
- handleRaw<Name extends HttpApiEndpoint.Name<Endpoints>, R1>(
218
- name: Name,
219
- handler: HttpApiEndpoint.HandlerRawWithName<Endpoints, Name, HttpApiEndpoint.ErrorsWithName<Endpoints, Name>, R1>,
311
+ handleRaw<
312
+ Identifier extends keyof EndpointsByIdentifier,
313
+ R1
314
+ >(
315
+ identifier: Identifier & NotHandledIdentifier<Identifier, HandledIdentifiers>,
316
+ handler: HttpApiEndpoint.HandlerRaw<
317
+ EndpointsByIdentifier[Identifier],
318
+ HttpApiEndpoint.MiddlewareError<EndpointsByIdentifier[Identifier]>,
319
+ R1
320
+ >,
220
321
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
221
322
  ): Handlers<
222
- | R
223
- | HttpApiEndpoint.MiddlewareWithName<Endpoints, Name>
224
- | HttpApiEndpoint.MiddlewareServicesWithName<Endpoints, Name>
225
- | (HttpApiEndpoint.ExcludeProvidedWithName<
226
- Endpoints,
227
- Name,
228
- R1 | HttpApiEndpoint.ServerServicesWithName<Endpoints, Name>
229
- > extends infer _R ? _R extends never ? never : HttpRouter.Request<"Requires", _R> : never),
230
- HttpApiEndpoint.ExcludeName<Endpoints, Name>
323
+ R | HandlerRequirements<EndpointsByIdentifier[Identifier], R1>,
324
+ EndpointsByIdentifier,
325
+ HandledIdentifiers | Identifier
231
326
  >
232
327
  }
233
328
 
@@ -237,34 +332,6 @@ export interface Handlers<
237
332
  * @since 4.0.0
238
333
  */
239
334
  export declare namespace Handlers {
240
- /**
241
- * A `Handlers` value with its context and endpoint types erased.
242
- *
243
- * @category handlers
244
- * @since 4.0.0
245
- */
246
- export interface Any {
247
- readonly [HandlersTypeId]: any
248
- }
249
-
250
- /**
251
- * Record stored for a registered endpoint handler.
252
- *
253
- * **Details**
254
- *
255
- * It keeps the endpoint metadata, handler function, whether raw request handling
256
- * is used, and whether the handler should run uninterruptibly.
257
- *
258
- * @category handlers
259
- * @since 4.0.0
260
- */
261
- export type Item<R> = {
262
- readonly endpoint: HttpApiEndpoint.AnyWithProps
263
- readonly handler: HttpApiEndpoint.Handler<any, any, R>
264
- readonly isRaw: boolean
265
- readonly uninterruptible: boolean
266
- }
267
-
268
335
  /**
269
336
  * Creates a handler collection for a group where every endpoint in the group is
270
337
  * still awaiting an implementation.
@@ -272,9 +339,9 @@ export declare namespace Handlers {
272
339
  * @category handlers
273
340
  * @since 4.0.0
274
341
  */
275
- export type FromGroup<Group extends HttpApiGroup.Any> = Handlers<
342
+ export type FromGroup<Group extends HttpApiGroup.Constraint> = Handlers<
276
343
  never,
277
- HttpApiGroup.Endpoints<Group>
344
+ Group["endpoints"]
278
345
  >
279
346
 
280
347
  /**
@@ -285,22 +352,7 @@ export declare namespace Handlers {
285
352
  * @category handlers
286
353
  * @since 4.0.0
287
354
  */
288
- export type ValidateReturn<A> = A extends (
289
- | Handlers<
290
- infer _R,
291
- infer _Endpoints
292
- >
293
- | Effect.Effect<
294
- Handlers<
295
- infer _R,
296
- infer _Endpoints
297
- >,
298
- infer _EX,
299
- infer _RX
300
- >
301
- ) ? [_Endpoints] extends [never] ? A
302
- : `Endpoint not handled: ${HttpApiEndpoint.Name<_Endpoints>}` :
303
- `Must return the implemented handlers`
355
+ export type ValidateReturn<A> = ValidateHandlersReturn<A>
304
356
 
305
357
  /**
306
358
  * Extracts the error channel from an effect that produces a `Handlers`
@@ -312,7 +364,8 @@ export declare namespace Handlers {
312
364
  export type Error<A> = A extends Effect.Effect<
313
365
  Handlers<
314
366
  infer _R,
315
- infer _Endpoints
367
+ infer _EndpointsByIdentifier,
368
+ infer _HandledIdentifiers
316
369
  >,
317
370
  infer _EX,
318
371
  infer _RX
@@ -328,12 +381,14 @@ export declare namespace Handlers {
328
381
  */
329
382
  export type Context<A> = A extends Handlers<
330
383
  infer _R,
331
- infer _Endpoints
384
+ infer _EndpointsByIdentifier,
385
+ infer _HandledIdentifiers
332
386
  > ? _R :
333
387
  A extends Effect.Effect<
334
388
  Handlers<
335
389
  infer _R,
336
- infer _Endpoints
390
+ infer _EndpointsByIdentifier,
391
+ infer _HandledIdentifiers
337
392
  >,
338
393
  infer _EX,
339
394
  infer _RX
@@ -341,34 +396,18 @@ export declare namespace Handlers {
341
396
  never
342
397
  }
343
398
 
344
- /**
345
- * Builds the server-side HTTP effect for a single endpoint in an API group using
346
- * the endpoint metadata, middleware, codecs, and supplied handler.
347
- *
348
- * @category handlers
349
- * @since 4.0.0
350
- */
351
- export const endpoint = <
352
- ApiId extends string,
353
- Groups extends HttpApiGroup.Any,
354
- const GroupName extends HttpApiGroup.Name<Groups>,
355
- const EndpointName extends HttpApiEndpoint.Name<HttpApiGroup.Endpoints<HttpApiGroup.WithName<Groups, GroupName>>>,
399
+ type EndpointReturn<
400
+ Groups extends HttpApiGroup.Constraint,
401
+ GroupIdentifier extends HttpApiGroup.Identifier<Groups>,
402
+ EndpointIdentifier extends HttpApiGroup.Endpoints<
403
+ HttpApiGroup.WithIdentifier<Groups, GroupIdentifier>
404
+ >["identifier"],
356
405
  R,
357
- Group extends HttpApiGroup.Any = HttpApiGroup.WithName<Groups, GroupName>,
358
- Endpoint extends HttpApiEndpoint.Any = HttpApiEndpoint.WithName<HttpApiGroup.Endpoints<Group>, EndpointName>
359
- >(
360
- api: HttpApi.HttpApi<ApiId, Groups>,
361
- groupName: GroupName,
362
- endpointName: EndpointName,
363
- handler: NoInfer<
364
- HttpApiEndpoint.HandlerWithName<
365
- HttpApiGroup.Endpoints<HttpApiGroup.WithName<Groups, GroupName>>,
366
- EndpointName,
367
- never,
368
- R
369
- >
406
+ Endpoint extends HttpApiEndpoint.Constraint = HttpApiEndpoint.WithIdentifier<
407
+ HttpApiGroup.Endpoints<HttpApiGroup.WithIdentifier<Groups, GroupIdentifier>>,
408
+ EndpointIdentifier
370
409
  >
371
- ): Effect.Effect<
410
+ > = Effect.Effect<
372
411
  Effect.Effect<
373
412
  HttpServerResponse,
374
413
  never,
@@ -385,10 +424,39 @@ export const endpoint = <
385
424
  | FileSystem
386
425
  | HttpPlatform
387
426
  | Path
388
- > =>
427
+ >
428
+
429
+ /**
430
+ * Builds the server-side HTTP effect for a single endpoint in an API group using
431
+ * the endpoint metadata, middleware, codecs, and supplied handler.
432
+ *
433
+ * @category handlers
434
+ * @since 4.0.0
435
+ */
436
+ export const endpoint = <
437
+ ApiId extends string,
438
+ Groups extends HttpApiGroup.Constraint,
439
+ const GroupIdentifier extends HttpApiGroup.Identifier<Groups>,
440
+ const EndpointIdentifier extends HttpApiGroup.Endpoints<
441
+ HttpApiGroup.WithIdentifier<Groups, GroupIdentifier>
442
+ >["identifier"],
443
+ R
444
+ >(
445
+ api: HttpApi.HttpApi<ApiId, Groups>,
446
+ groupIdentifier: GroupIdentifier,
447
+ endpointIdentifier: EndpointIdentifier,
448
+ handler: NoInfer<
449
+ HttpApiEndpoint.HandlerWithIdentifier<
450
+ HttpApiGroup.Endpoints<HttpApiGroup.WithIdentifier<Groups, GroupIdentifier>>,
451
+ EndpointIdentifier,
452
+ never,
453
+ R
454
+ >
455
+ >
456
+ ): EndpointReturn<Groups, GroupIdentifier, EndpointIdentifier, R> =>
389
457
  Effect.contextWith((context: Context.Context<any>) => {
390
- const group = api.groups[groupName] as unknown as HttpApiGroup.AnyWithProps
391
- const endpoint = group.endpoints[endpointName] as unknown as HttpApiEndpoint.AnyWithProps
458
+ const group = api.groups[groupIdentifier] as unknown as HttpApiGroup.Top
459
+ const endpoint = group.endpoints[endpointIdentifier]
392
460
  return Effect.succeed(handlerToHttpEffect(
393
461
  group,
394
462
  endpoint,
@@ -416,8 +484,10 @@ export const securityDecode = <Security extends HttpApiSecurity.HttpApiSecurity>
416
484
  case "Http": {
417
485
  return Effect.map(
418
486
  HttpServerRequest,
419
- // schemeLength + space
420
- (request) => Redacted.make((request.headers.authorization ?? "").slice(self.schemeLength + 1)) as any
487
+ (request) =>
488
+ Redacted.make(
489
+ getAuthorizationCredential(request.headers.authorization, self.scheme) ?? ""
490
+ ) as any
421
491
  )
422
492
  }
423
493
  case "ApiKey": {
@@ -444,24 +514,20 @@ export const securityDecode = <Security extends HttpApiSecurity.HttpApiSecurity>
444
514
  username: "",
445
515
  password: Redacted.make("")
446
516
  } as any
447
- return HttpServerRequest.pipe(
448
- Effect.flatMap((request) =>
449
- Effect.fromResult(Encoding.decodeBase64String((request.headers.authorization ?? "").slice(basicLen)))
450
- ),
451
- Effect.match({
452
- onFailure: () => empty,
453
- onSuccess: (header) => {
454
- const parts = header.split(":")
455
- if (parts.length !== 2) {
456
- return empty
457
- }
458
- return {
459
- username: parts[0],
460
- password: Redacted.make(parts[1])
461
- } as any
462
- }
463
- })
464
- )
517
+ return Effect.map(HttpServerRequest, (request) => {
518
+ const encoded = getAuthorizationCredential(request.headers.authorization, basicScheme)
519
+ if (encoded === undefined) return empty
520
+ const decoded = Result.getOrUndefined(Encoding.decodeBase64String(encoded))
521
+ if (decoded === undefined) return empty
522
+ // RFC 7617, Section 2: only the first colon separates the user-id from the password.
523
+ // https://www.rfc-editor.org/rfc/rfc7617.html#section-2
524
+ const separator = decoded.indexOf(":")
525
+ if (separator === -1) return empty
526
+ return {
527
+ username: decoded.slice(0, separator),
528
+ password: Redacted.make(decoded.slice(separator + 1))
529
+ } as any
530
+ })
465
531
  }
466
532
  }
467
533
  }
@@ -492,53 +558,101 @@ export const securitySetCookie = (
492
558
  // Internal
493
559
  // -----------------------------------------------------------------------------
494
560
 
495
- const basicLen = `Basic `.length
561
+ const basicScheme = "Basic"
562
+
563
+ function getAuthorizationCredential(
564
+ authorization: string | undefined,
565
+ scheme: string
566
+ ): string | undefined {
567
+ const schemeLength = scheme.length
568
+ // RFC 9110, Section 11.1: schemes are case-insensitive and credentials follow 1*SP.
569
+ // https://www.rfc-editor.org/rfc/rfc9110.html#section-11.1
570
+ if (
571
+ authorization === undefined ||
572
+ authorization.length <= schemeLength ||
573
+ authorization.charCodeAt(schemeLength) !== 32 ||
574
+ authorization.slice(0, schemeLength).toLowerCase() !== scheme.toLowerCase()
575
+ ) {
576
+ return undefined
577
+ }
578
+ let credentialStart = schemeLength + 1
579
+ while (authorization.charCodeAt(credentialStart) === 32) {
580
+ credentialStart++
581
+ }
582
+ return credentialStart === authorization.length ? undefined : authorization.slice(credentialStart)
583
+ }
584
+
585
+ const registerHandler = (
586
+ self: Handlers<any, any, any>,
587
+ identifier: string,
588
+ handler: HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, any, any>,
589
+ isRaw: boolean,
590
+ options?: HandlerOptions | undefined
591
+ ) => {
592
+ if (!Object.hasOwn(self.group.endpoints, identifier)) {
593
+ throw new Error(`HttpApiEndpoint "${identifier}" not found in HttpApiGroup "${self.group.identifier}"`)
594
+ }
595
+ if (self.handlers.has(identifier)) {
596
+ throw new Error(
597
+ `Handler for HttpApiEndpoint "${identifier}" is already registered in HttpApiGroup "${self.group.identifier}"`
598
+ )
599
+ }
600
+ const endpoint = self.group.endpoints[identifier]
601
+ self.handlers.set(identifier, {
602
+ endpoint,
603
+ handler,
604
+ isRaw,
605
+ uninterruptible: options?.uninterruptible ?? false
606
+ })
607
+ return self
608
+ }
496
609
 
497
610
  const HandlersProto = {
498
- [HandlersTypeId]: {
499
- _Endpoints: identity
500
- },
611
+ [HandlersTypeId]: HandlersTypeId,
501
612
  pipe() {
502
613
  return pipeArguments(this, arguments)
503
614
  },
504
615
  handle(
505
- this: Handlers<any, HttpApiEndpoint.Any>,
506
- name: string,
507
- handler: HttpApiEndpoint.Handler<any, any, any>,
616
+ this: Handlers<any, any, any>,
617
+ identifier: string,
618
+ handler: HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, any, any>,
508
619
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
509
620
  ) {
510
- const endpoint = this.group.endpoints[name]
511
- this.handlers.set(name, {
512
- endpoint,
513
- handler,
514
- isRaw: false,
515
- uninterruptible: options?.uninterruptible ?? false
516
- })
621
+ return registerHandler(this, identifier, handler, false, options)
622
+ },
623
+ handleAll(
624
+ this: Handlers<any, any, any>,
625
+ handlers: Record<
626
+ string,
627
+ HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, any, any> | {
628
+ readonly handler: HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, any, any>
629
+ readonly options?: HandlerOptions | undefined
630
+ }
631
+ >
632
+ ) {
633
+ for (const [identifier, entry] of Object.entries(handlers)) {
634
+ const handler = typeof entry === "function" ? entry : entry.handler
635
+ const options = typeof entry === "function" ? undefined : entry.options
636
+ registerHandler(this, identifier, handler, false, options)
637
+ }
517
638
  return this
518
639
  },
519
640
  handleRaw(
520
- this: Handlers<any, HttpApiEndpoint.Any>,
521
- name: string,
522
- handler: HttpApiEndpoint.Handler<any, any, any>,
641
+ this: Handlers<any, any, any>,
642
+ identifier: string,
643
+ handler: HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, any, any>,
523
644
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
524
645
  ) {
525
- const endpoint = this.group.endpoints[name]
526
- this.handlers.set(name, {
527
- endpoint,
528
- handler,
529
- isRaw: true,
530
- uninterruptible: options?.uninterruptible ?? false
531
- })
532
- return this
646
+ return registerHandler(this, identifier, handler, true, options)
533
647
  }
534
648
  }
535
649
 
536
- const makeHandlers = <R, Endpoints extends HttpApiEndpoint.Any>(
537
- group: HttpApiGroup.Any
538
- ): Handlers<R, Endpoints> => {
650
+ const makeHandlers = <R, Group extends HttpApiGroup.Constraint>(
651
+ group: Group
652
+ ): Handlers<R, EndpointMap<HttpApiGroup.Endpoints<Group>>> => {
539
653
  const self = Object.create(HandlersProto)
540
654
  self.group = group
541
- self.handlers = new Map<string, Handlers.Item<R>>()
655
+ self.handlers = new Map<string, HandlerRuntime>()
542
656
  return self
543
657
  }
544
658
 
@@ -581,7 +695,7 @@ function decodePayload(
581
695
  ): Effect.Effect<unknown, Schema.SchemaError, unknown> | HttpServerResponse | undefined {
582
696
  const hasBody = HttpMethod.hasBody(httpRequest.method)
583
697
  const contentType = hasBody
584
- ? getRequestMediaType(httpRequest)
698
+ ? MediaType.normalize(httpRequest.headers["content-type"] ?? "application/json")
585
699
  : "application/x-www-form-urlencoded"
586
700
  const existing = payloadBy.get(contentType)
587
701
  if (!existing) {
@@ -635,10 +749,10 @@ function decodePayload(
635
749
  }
636
750
 
637
751
  function handlerToHttpEffect(
638
- group: HttpApiGroup.AnyWithProps,
639
- endpoint: HttpApiEndpoint.AnyWithProps,
752
+ group: HttpApiGroup.Top,
753
+ endpoint: HttpApiEndpoint.Top,
640
754
  context: Context.Context<any>,
641
- handler: HttpApiEndpoint.Handler<any, any, any>,
755
+ handler: HttpApiEndpoint.Handler<HttpApiEndpoint.Constraint, any, any>,
642
756
  isRaw: boolean
643
757
  ) {
644
758
  const encodeSuccess = Schema.encodeUnknownEffect(makeSuccessSchema(endpoint))
@@ -706,8 +820,8 @@ function handlerToHttpEffect(
706
820
 
707
821
  /** @internal */
708
822
  export function handlerToRoute(
709
- group: HttpApiGroup.AnyWithProps,
710
- handler: Handlers.Item<any>,
823
+ group: HttpApiGroup.Top,
824
+ handler: HandlerRuntime,
711
825
  context: Context.Context<any>
712
826
  ): HttpRouter.Route<any, any> {
713
827
  const endpoint = handler.endpoint
@@ -719,31 +833,20 @@ export function handlerToRoute(
719
833
  )
720
834
  }
721
835
 
722
- const getRequestContentType = (request: HttpServerRequest): string =>
723
- request.headers["content-type"]
724
- ? request.headers["content-type"].toLowerCase().trim()
725
- : "application/json"
726
-
727
- const getRequestMediaType = (request: HttpServerRequest): string => {
728
- const contentType = getRequestContentType(request)
729
- const index = contentType.indexOf(";")
730
- return index === -1 ? contentType : contentType.slice(0, index).trim()
731
- }
732
-
733
- const applyMiddleware = <A extends Effect.Effect<any, any, any>>(
734
- group: HttpApiGroup.AnyWithProps,
735
- endpoint: HttpApiEndpoint.AnyWithProps,
836
+ const applyMiddleware = <Group extends HttpApiGroup.Constraint, A extends Effect.Effect<any, any, any>>(
837
+ group: Group,
838
+ endpoint: HttpApiEndpoint.Top,
736
839
  context: Context.Context<any>,
737
840
  handler: A
738
841
  ) => {
739
842
  const options = { group, endpoint }
740
843
  for (const key_ of endpoint.middlewares) {
741
- const key = key_ as any as HttpApiMiddleware.AnyService
742
- const service = Context.getUnsafe(context, key as any) as HttpApiMiddleware.HttpApiMiddleware<any, any, any>
844
+ const key = key_ as HttpApiMiddleware.AnyService
845
+ const service = Context.getUnsafe(context, key)
743
846
  const apply = HttpApiMiddleware.isSecurity(key)
744
- ? makeSecurityMiddleware(key, service as any)
847
+ ? makeSecurityMiddleware(key, service)
745
848
  : service
746
- handler = apply(handler, options) as A
849
+ handler = apply(handler, options)
747
850
  }
748
851
  return handler
749
852
  }
@@ -771,8 +874,8 @@ const makeSecurityMiddleware = (
771
874
  }
772
875
 
773
876
  const middleware = Effect.fnUntraced(function*(handler: Effect.Effect<any, any, any>, options: {
774
- readonly group: HttpApiGroup.AnyWithProps
775
- readonly endpoint: HttpApiEndpoint.AnyWithProps
877
+ readonly group: HttpApiGroup.Top
878
+ readonly endpoint: HttpApiEndpoint.Top
776
879
  }) {
777
880
  handler = Effect.mapError(handler, (error) => new HandlerError(error))
778
881
  let lastResult: Result.Result<any, any> | undefined
@@ -816,7 +919,7 @@ type StreamEncoder = (response: unknown, context: Context.Context<never>) =>
816
919
  | Effect.Effect<HttpServerResponse, Schema.SchemaError, unknown>
817
920
  | undefined
818
921
 
819
- function makeStreamEncoder(endpoint: HttpApiEndpoint.AnyWithProps): StreamEncoder | undefined {
922
+ function makeStreamEncoder(endpoint: HttpApiEndpoint.Top): StreamEncoder | undefined {
820
923
  const streamSchema = getStreamSuccessSchema(endpoint)
821
924
  if (streamSchema === undefined) {
822
925
  return undefined
@@ -863,7 +966,7 @@ function makeStreamEncoder(endpoint: HttpApiEndpoint.AnyWithProps): StreamEncode
863
966
  }
864
967
  }
865
968
 
866
- function getStreamSuccessSchema(endpoint: HttpApiEndpoint.AnyWithProps) {
969
+ function getStreamSuccessSchema(endpoint: HttpApiEndpoint.Top) {
867
970
  for (const schema of endpoint.success) {
868
971
  if (HttpApiSchema.isStreamSchema(schema)) {
869
972
  return schema
@@ -871,7 +974,7 @@ function getStreamSuccessSchema(endpoint: HttpApiEndpoint.AnyWithProps) {
871
974
  }
872
975
  }
873
976
 
874
- function hasBufferedSuccess(endpoint: HttpApiEndpoint.AnyWithProps): boolean {
977
+ function hasBufferedSuccess(endpoint: HttpApiEndpoint.Top): boolean {
875
978
  for (const schema of endpoint.success) {
876
979
  if (Schema.isSchema(schema) && !HttpApiSchema.isStreamSchema(schema)) return true
877
980
  }
@@ -942,14 +1045,14 @@ const toResponseSuccessSchema = toResponseSchema(HttpApiSchema.getStatusSuccess)
942
1045
  const toResponseErrorSchema = toResponseSchema(HttpApiSchema.getStatusError)
943
1046
 
944
1047
  function makeSuccessSchema(
945
- endpoint: HttpApiEndpoint.AnyWithProps
1048
+ endpoint: HttpApiEndpoint.Top
946
1049
  ): Schema.ConstraintEncoder<HttpServerResponse, unknown> {
947
1050
  const schemas = HttpApiEndpoint.getSuccessSchemas(endpoint).map(toResponseSuccessSchema)
948
1051
  return schemas.length === 1 ? schemas[0] : Schema.Union(schemas)
949
1052
  }
950
1053
 
951
1054
  function makeErrorSchema(
952
- endpoint: HttpApiEndpoint.AnyWithProps
1055
+ endpoint: HttpApiEndpoint.Top
953
1056
  ): Schema.ConstraintEncoder<HttpServerResponse, unknown> {
954
1057
  const schemas = HttpApiEndpoint.getErrorSchemas(endpoint).map(toResponseErrorSchema)
955
1058
  if (schemas.length === 0) return Schema.Never
@@ -967,7 +1070,7 @@ function toResponseSchema(getStatus: (ast: SchemaAST.AST) => number) {
967
1070
  const responseSchema = $HttpServerResponse.pipe(
968
1071
  Schema.decodeTo(schema, getResponseTransformation(getStatus, schema))
969
1072
  )
970
- cache.set(responseSchema.ast, responseSchema)
1073
+ cache.set(schema.ast, responseSchema)
971
1074
  return responseSchema
972
1075
  }
973
1076
  }