effect 4.0.0-beta.80 → 4.0.0-beta.82

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 (48) hide show
  1. package/dist/Config.d.ts.map +1 -1
  2. package/dist/Config.js +5 -2
  3. package/dist/Config.js.map +1 -1
  4. package/dist/Schema.d.ts +1 -1
  5. package/dist/Schema.d.ts.map +1 -1
  6. package/dist/unstable/encoding/Sse.d.ts +18 -14
  7. package/dist/unstable/encoding/Sse.d.ts.map +1 -1
  8. package/dist/unstable/encoding/Sse.js +7 -4
  9. package/dist/unstable/encoding/Sse.js.map +1 -1
  10. package/dist/unstable/httpapi/HttpApi.d.ts +1 -1
  11. package/dist/unstable/httpapi/HttpApi.d.ts.map +1 -1
  12. package/dist/unstable/httpapi/HttpApi.js +1 -0
  13. package/dist/unstable/httpapi/HttpApi.js.map +1 -1
  14. package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
  15. package/dist/unstable/httpapi/HttpApiBuilder.js +92 -11
  16. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  17. package/dist/unstable/httpapi/HttpApiClient.d.ts +6 -1
  18. package/dist/unstable/httpapi/HttpApiClient.d.ts.map +1 -1
  19. package/dist/unstable/httpapi/HttpApiClient.js +114 -3
  20. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  21. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +60 -50
  22. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
  23. package/dist/unstable/httpapi/HttpApiEndpoint.js +116 -5
  24. package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
  25. package/dist/unstable/httpapi/HttpApiGroup.d.ts +1 -1
  26. package/dist/unstable/httpapi/HttpApiGroup.d.ts.map +1 -1
  27. package/dist/unstable/httpapi/HttpApiSchema.d.ts +116 -2
  28. package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
  29. package/dist/unstable/httpapi/HttpApiSchema.js +75 -5
  30. package/dist/unstable/httpapi/HttpApiSchema.js.map +1 -1
  31. package/dist/unstable/httpapi/OpenApi.d.ts +15 -0
  32. package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
  33. package/dist/unstable/httpapi/OpenApi.js +82 -13
  34. package/dist/unstable/httpapi/OpenApi.js.map +1 -1
  35. package/dist/unstable/reactivity/AtomHttpApi.d.ts +2 -2
  36. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/Config.ts +5 -2
  39. package/src/Schema.ts +1 -1
  40. package/src/unstable/encoding/Sse.ts +34 -20
  41. package/src/unstable/httpapi/HttpApi.ts +2 -1
  42. package/src/unstable/httpapi/HttpApiBuilder.ts +148 -3
  43. package/src/unstable/httpapi/HttpApiClient.ts +196 -5
  44. package/src/unstable/httpapi/HttpApiEndpoint.ts +209 -18
  45. package/src/unstable/httpapi/HttpApiGroup.ts +1 -1
  46. package/src/unstable/httpapi/HttpApiSchema.ts +249 -5
  47. package/src/unstable/httpapi/OpenApi.ts +130 -17
  48. package/src/unstable/reactivity/AtomHttpApi.ts +2 -2
@@ -10,9 +10,12 @@
10
10
  * @since 4.0.0
11
11
  */
12
12
  import { constVoid, type LazyArg } from "../../Function.ts"
13
+ import * as Predicate from "../../Predicate.ts"
13
14
  import * as Schema from "../../Schema.ts"
14
15
  import * as SchemaAST from "../../SchemaAST.ts"
15
16
  import * as SchemaTransformation from "../../SchemaTransformation.ts"
17
+ import * as Stream from "../../Stream.ts"
18
+ import type * as Sse from "../encoding/Sse.ts"
16
19
  import { hasBody, type HttpMethod } from "../http/HttpMethod.ts"
17
20
  import type * as Multipart_ from "../http/Multipart.ts"
18
21
 
@@ -125,6 +128,8 @@ const statusCodeByLiteral = {
125
128
  NetworkAuthenticationRequired: 511
126
129
  } as const
127
130
 
131
+ const StreamSchemaTypeId = "~effect/httpapi/HttpApiSchema/Stream"
132
+
128
133
  /**
129
134
  * Common HTTP status code literals accepted by {@link status}.
130
135
  *
@@ -145,13 +150,15 @@ export type StatusLiteral = keyof typeof statusCodeByLiteral
145
150
  * @category status
146
151
  * @since 4.0.0
147
152
  */
148
- export function status(code: number): <S extends Schema.Top>(self: S) => S["Rebuild"]
149
- export function status(code: StatusLiteral): <S extends Schema.Top>(self: S) => S["Rebuild"]
153
+ export function status(code: number): {
154
+ <S extends Schema.Top>(self: S): S["Rebuild"]
155
+ }
156
+ export function status(code: StatusLiteral): {
157
+ <S extends Schema.Top>(self: S): S["Rebuild"]
158
+ }
150
159
  export function status(code: number | StatusLiteral) {
151
160
  const statusCode = typeof code === "string" ? statusCodeByLiteral[code] : code
152
- return <S extends Schema.Top>(self: S): S["Rebuild"] => {
153
- return self.annotate({ httpApiStatus: statusCode })
154
- }
161
+ return <S extends Schema.Top>(self: S): S["Rebuild"] => self.annotate({ httpApiStatus: statusCode })
155
162
  }
156
163
 
157
164
  /**
@@ -251,6 +258,238 @@ export function asNoContent<S extends Schema.Top>(options: {
251
258
  }
252
259
  }
253
260
 
261
+ type StreamMode = "sse" | "uint8array"
262
+
263
+ /**
264
+ * Mode describing whether an SSE stream emits full events or raw data values.
265
+ *
266
+ * @category models
267
+ * @since 4.0.0
268
+ */
269
+ export type StreamSseMode = "events" | "data"
270
+
271
+ /**
272
+ * Schema for a Server-Sent Events success response.
273
+ *
274
+ * **Details**
275
+ *
276
+ * `events` describes successful application events emitted by the stream, and
277
+ * `error` describes typed stream failures that will be encoded by later
278
+ * endpoint/server/client integrations using the reserved failure event. If
279
+ * `error` is omitted, it defaults to `Schema.Never`. When `StreamSse` is
280
+ * constructed from `data`, handlers and clients expose raw data values while
281
+ * the server and client still use an SSE event schema internally.
282
+ *
283
+ * @category models
284
+ * @since 4.0.0
285
+ */
286
+ export interface StreamSse<
287
+ Events extends Sse.EventCodec,
288
+ Error extends Schema.Top,
289
+ Value = Events["Type"]
290
+ > extends
291
+ Schema.Bottom<
292
+ Stream.Stream<Value, Error["Type"], never>,
293
+ Stream.Stream<Value, Error["Type"], never>,
294
+ Events["DecodingServices"] | Error["DecodingServices"],
295
+ Events["EncodingServices"] | Error["EncodingServices"],
296
+ SchemaAST.Declaration,
297
+ StreamSse<Events, Error, Value>
298
+ >
299
+ {
300
+ readonly "Rebuild": StreamSse<Events, Error, Value>
301
+ readonly [StreamSchemaTypeId]: typeof StreamSchemaTypeId
302
+ readonly _tag: "StreamSse"
303
+ readonly mode: "sse"
304
+ readonly sseMode: StreamSseMode
305
+ readonly contentType: string
306
+ readonly events: Events
307
+ readonly error: Error
308
+ readonly "~Value"?: Value | undefined
309
+ }
310
+
311
+ /**
312
+ * Event schema produced when {@link StreamSse} is constructed from a JSON data schema.
313
+ *
314
+ * @category models
315
+ * @since 4.0.0
316
+ */
317
+ export interface SseEventFromData<Data extends Schema.Top> extends
318
+ Schema.Codec<
319
+ {
320
+ readonly id: string | undefined
321
+ readonly event: string
322
+ readonly data: Data["Type"]
323
+ },
324
+ {
325
+ readonly id?: string | undefined
326
+ readonly event?: string | undefined
327
+ readonly data: string
328
+ },
329
+ Data["DecodingServices"],
330
+ Data["EncodingServices"]
331
+ >
332
+ {}
333
+
334
+ /**
335
+ * Schema for a streaming `Uint8Array` success response.
336
+ *
337
+ * **Details**
338
+ *
339
+ * This declaration stores the response content type for later endpoint,
340
+ * server, client, and OpenAPI integrations. It is intentionally separate from
341
+ * the buffered `asUint8Array` response encoding.
342
+ *
343
+ * @category models
344
+ * @since 4.0.0
345
+ */
346
+ export interface StreamUint8Array extends
347
+ Schema.Bottom<
348
+ Stream.Stream<Uint8Array, unknown, never>,
349
+ Stream.Stream<Uint8Array, unknown, never>,
350
+ never,
351
+ never,
352
+ SchemaAST.Declaration,
353
+ StreamUint8Array
354
+ >
355
+ {
356
+ readonly "Rebuild": StreamUint8Array
357
+ readonly [StreamSchemaTypeId]: typeof StreamSchemaTypeId
358
+ readonly _tag: "StreamUint8Array"
359
+ readonly mode: "uint8array"
360
+ readonly contentType: string
361
+ }
362
+
363
+ /** @internal */
364
+ export type StreamSchema = StreamSse<Sse.EventCodec, Schema.Top, unknown> | StreamUint8Array
365
+
366
+ /** @internal */
367
+ export type StreamMetadata =
368
+ | {
369
+ readonly mode: "sse"
370
+ readonly sseMode: StreamSseMode
371
+ readonly contentType: string
372
+ readonly events: Sse.EventCodec
373
+ readonly error: Schema.Top
374
+ }
375
+ | {
376
+ readonly mode: "uint8array"
377
+ readonly contentType: string
378
+ }
379
+
380
+ const streamSchema = Schema.declare(Stream.isStream)
381
+
382
+ /**
383
+ * Creates a Server-Sent Events streaming success response schema.
384
+ *
385
+ * @category constructors
386
+ * @since 4.0.0
387
+ */
388
+ export const StreamSse: {
389
+ /**
390
+ * Creates a Server-Sent Events streaming success response schema.
391
+ *
392
+ * @category constructors
393
+ * @since 4.0.0
394
+ */
395
+ <Events extends Sse.EventCodec, Error extends Schema.Top = Schema.Never>(
396
+ options: {
397
+ readonly contentType?: string | undefined
398
+ readonly events: Events
399
+ readonly error?: Error | undefined
400
+ }
401
+ ): StreamSse<Events, Error, Events["Type"]>
402
+ /**
403
+ * Creates a Server-Sent Events streaming success response schema.
404
+ *
405
+ * @category constructors
406
+ * @since 4.0.0
407
+ */
408
+ <Data extends Schema.Top, Error extends Schema.Top = Schema.Never>(
409
+ options: {
410
+ readonly contentType?: string | undefined
411
+ readonly data: Data
412
+ readonly error?: Error | undefined
413
+ }
414
+ ): StreamSse<SseEventFromData<Data>, Error, Data["Type"]>
415
+ } = (options: {
416
+ readonly contentType?: string | undefined
417
+ readonly events?: Sse.EventCodec | undefined
418
+ readonly data?: Schema.Top | undefined
419
+ readonly error?: Schema.Top | undefined
420
+ }): StreamSse<Sse.EventCodec, Schema.Top, unknown> => {
421
+ const events = options.events ?? (options.data === undefined ? undefined : Schema.Struct({
422
+ id: Schema.UndefinedOr(Schema.String),
423
+ event: Schema.String,
424
+ data: Schema.fromJsonString(options.data)
425
+ }))
426
+ if (events === undefined) {
427
+ throw new Error("StreamSse requires either an events schema or a data schema")
428
+ }
429
+ return Schema.make<StreamSse<Sse.EventCodec, Schema.Top, unknown>>(streamSchema.ast, {
430
+ [StreamSchemaTypeId]: StreamSchemaTypeId,
431
+ _tag: "StreamSse",
432
+ mode: "sse",
433
+ sseMode: options.events === undefined ? "data" : "events",
434
+ contentType: options.contentType ?? defaultStreamContentType("sse"),
435
+ events,
436
+ error: options.error ?? Schema.Never
437
+ })
438
+ }
439
+
440
+ /**
441
+ * Creates a streaming `Uint8Array` success response schema.
442
+ *
443
+ * @category constructors
444
+ * @since 4.0.0
445
+ */
446
+ export const StreamUint8Array = (options?: {
447
+ readonly contentType?: string | undefined
448
+ }): StreamUint8Array =>
449
+ Schema.make<StreamUint8Array>(streamSchema.ast, {
450
+ [StreamSchemaTypeId]: StreamSchemaTypeId,
451
+ _tag: "StreamUint8Array",
452
+ mode: "uint8array",
453
+ contentType: options?.contentType ?? defaultStreamContentType("uint8array")
454
+ })
455
+
456
+ /** @internal */
457
+ export const isStreamSchema = (u: unknown): u is StreamSchema =>
458
+ Schema.isSchema(u) && Predicate.hasProperty(u, StreamSchemaTypeId)
459
+
460
+ /** @internal */
461
+ export const isStreamSse = (u: unknown): u is StreamSse<Sse.EventCodec, Schema.Top, unknown> =>
462
+ isStreamSchema(u) && u._tag === "StreamSse"
463
+
464
+ /** @internal */
465
+ export const isStreamUint8Array = (u: unknown): u is StreamUint8Array =>
466
+ isStreamSchema(u) && u._tag === "StreamUint8Array"
467
+
468
+ /** @internal */
469
+ export function getStreamMetadata(self: StreamSchema): StreamMetadata {
470
+ return self._tag === "StreamSse" ?
471
+ {
472
+ mode: self.mode,
473
+ sseMode: self.sseMode,
474
+ contentType: self.contentType,
475
+ events: self.events,
476
+ error: self.error
477
+ } :
478
+ {
479
+ mode: self.mode,
480
+ contentType: self.contentType
481
+ }
482
+ }
483
+
484
+ function defaultStreamContentType(mode: StreamMode): string {
485
+ switch (mode) {
486
+ case "sse":
487
+ return "text/event-stream"
488
+ case "uint8array":
489
+ return "application/octet-stream"
490
+ }
491
+ }
492
+
254
493
  /**
255
494
  * Runtime brand key used to mark schemas as buffered multipart payloads.
256
495
  *
@@ -487,6 +726,11 @@ export function getStatusSuccess(self: SchemaAST.AST): number {
487
726
  return resolveHttpApiStatus(self) ?? 200
488
727
  }
489
728
 
729
+ /** @internal */
730
+ export function getStatusStream(self: StreamSchema): number {
731
+ return getStatusSuccess(self.ast)
732
+ }
733
+
490
734
  /** @internal */
491
735
  export function getStatusError(self: SchemaAST.AST): number {
492
736
  return resolveHttpApiStatus(self) ?? 500
@@ -367,7 +367,7 @@ export function fromApi<Id extends string, Groups extends HttpApiGroup.Any>(
367
367
  }
368
368
 
369
369
  function processResponseBodies(bodies: ResponseBodies, defaultDescription: () => string) {
370
- for (const [status, { content, descriptions }] of bodies) {
370
+ for (const [status, { content, descriptions, streamContent }] of bodies) {
371
371
  const description = descriptions.size > 0 ? Array.from(descriptions).join(" | ") : defaultDescription()
372
372
  op.responses[status] = {
373
373
  description
@@ -390,6 +390,67 @@ export function fromApi<Id extends string, Groups extends HttpApiGroup.Any>(
390
390
  })
391
391
  })
392
392
  }
393
+ if (streamContent !== undefined) {
394
+ streamContent.forEach((stream, contentType) => {
395
+ op.responses[status].content ??= {}
396
+ if (HttpApiSchema.isStreamSse(stream)) {
397
+ pathOps.push({
398
+ _tag: "schema",
399
+ ast: SchemaAST.getAST(stream.events),
400
+ path: ["paths", path, method, "responses", String(status), "content", contentType, "schema"]
401
+ })
402
+ pathOps.push({
403
+ _tag: "schema",
404
+ ast: SchemaAST.getAST(Schema.toCodecJson(Schema.Cause(stream.error, Schema.Defect()))),
405
+ path: [
406
+ "paths",
407
+ path,
408
+ method,
409
+ "responses",
410
+ String(status),
411
+ "content",
412
+ contentType,
413
+ "x-effect-stream",
414
+ "causeSchema"
415
+ ]
416
+ })
417
+ pathOps.push({
418
+ _tag: "schema",
419
+ ast: SchemaAST.getAST(stream.error),
420
+ path: [
421
+ "paths",
422
+ path,
423
+ method,
424
+ "responses",
425
+ String(status),
426
+ "content",
427
+ contentType,
428
+ "x-effect-stream",
429
+ "errorSchema"
430
+ ]
431
+ })
432
+ op.responses[status].content[contentType] = {
433
+ schema: {},
434
+ "x-effect-stream": {
435
+ encoding: "sse",
436
+ causeSchema: {},
437
+ errorSchema: {},
438
+ failureEvent: reservedStreamFailureEvent
439
+ }
440
+ }
441
+ } else {
442
+ op.responses[status].content[contentType] = {
443
+ schema: {
444
+ type: "string",
445
+ format: "binary"
446
+ },
447
+ "x-effect-stream": {
448
+ encoding: "uint8array"
449
+ }
450
+ }
451
+ }
452
+ })
453
+ }
393
454
  }
394
455
  }
395
456
 
@@ -461,11 +522,7 @@ export function fromApi<Id extends string, Groups extends HttpApiGroup.Any>(
461
522
  processParameters(endpoint.query, "query")
462
523
 
463
524
  processResponseBodies(
464
- extractResponseBodies(
465
- HttpApiEndpoint.getSuccessSchemas(endpoint),
466
- HttpApiSchema.getStatusSuccess,
467
- resolveDescriptionOrIdentifier
468
- ),
525
+ extractSuccessResponseBodies(endpoint),
469
526
  () => "Success"
470
527
  )
471
528
  processResponseBodies(
@@ -564,9 +621,20 @@ type ResponseBodies = Map<
564
621
  {
565
622
  descriptions: Set<string>
566
623
  content: Content | undefined // undefined means no content
624
+ streamContent: StreamContent | undefined
567
625
  }
568
626
  >
569
627
 
628
+ const reservedStreamFailureEvent = "effect/httpapi/stream/failure"
629
+
630
+ function extractSuccessResponseBodies(endpoint: HttpApiEndpoint.AnyWithProps): ResponseBodies {
631
+ return extractResponseBodies(
632
+ HttpApiEndpoint.getSuccessSchemas(endpoint),
633
+ HttpApiSchema.getStatusSuccess,
634
+ resolveDescriptionOrIdentifier
635
+ )
636
+ }
637
+
570
638
  function extractResponseBodies(
571
639
  schemas: Array<Schema.Top>,
572
640
  getStatus: (ast: SchemaAST.AST) => number,
@@ -575,6 +643,7 @@ function extractResponseBodies(
575
643
  const map = new Map<number, {
576
644
  descriptions: Set<string>
577
645
  content: Content | undefined
646
+ streamContent: StreamContent | undefined
578
647
  }>()
579
648
 
580
649
  schemas.forEach(process)
@@ -582,6 +651,10 @@ function extractResponseBodies(
582
651
  return map
583
652
 
584
653
  function process(schema: Schema.Top) {
654
+ if (HttpApiSchema.isStreamSchema(schema)) {
655
+ addStreamContent(schema)
656
+ return
657
+ }
585
658
  const ast = schema.ast
586
659
  const status = getStatus(ast)
587
660
  if (HttpApiSchema.isNoContent(ast)) {
@@ -596,7 +669,8 @@ function extractResponseBodies(
596
669
  if (statusMap === undefined) {
597
670
  map.set(status, {
598
671
  descriptions: new Set([description]),
599
- content: undefined
672
+ content: undefined,
673
+ streamContent: undefined
600
674
  })
601
675
  } else {
602
676
  if (description !== undefined) {
@@ -612,22 +686,25 @@ function extractResponseBodies(
612
686
  if (statusMap === undefined) {
613
687
  map.set(status, {
614
688
  descriptions: new Set(description !== undefined ? [description] : []),
615
- content: new Map([[_tag, new Map([[contentType, new Set([schema])]])]])
689
+ content: new Map([[_tag, new Map([[contentType, new Set([schema])]])]]),
690
+ streamContent: undefined
616
691
  })
617
692
  } else {
618
- if (statusMap.content !== undefined) {
619
- // concat descriptions
620
- if (description !== undefined) {
621
- statusMap.descriptions.add(description)
622
- }
693
+ // concat descriptions
694
+ if (description !== undefined) {
695
+ statusMap.descriptions.add(description)
696
+ }
623
697
 
624
- const contentTypeMap = statusMap.content.get(_tag)
625
- if (contentTypeMap === undefined) {
698
+ if (statusMap.content === undefined) {
699
+ statusMap.content = new Map([[_tag, new Map([[contentType, new Set([schema])]])]])
700
+ } else {
701
+ const schemasByContentType = statusMap.content.get(_tag)
702
+ if (schemasByContentType === undefined) {
626
703
  statusMap.content.set(_tag, new Map([[contentType, new Set([schema])]]))
627
704
  } else {
628
- const set = contentTypeMap.get(contentType)
705
+ const set = schemasByContentType.get(contentType)
629
706
  if (set === undefined) {
630
- contentTypeMap.set(contentType, new Set([schema]))
707
+ schemasByContentType.set(contentType, new Set([schema]))
631
708
  } else {
632
709
  set.add(schema)
633
710
  }
@@ -635,6 +712,22 @@ function extractResponseBodies(
635
712
  }
636
713
  }
637
714
  }
715
+
716
+ function addStreamContent(stream: HttpApiSchema.StreamSchema) {
717
+ const status = HttpApiSchema.getStatusStream(stream)
718
+ const statusMap = map.get(status)
719
+ if (statusMap === undefined) {
720
+ map.set(status, {
721
+ descriptions: new Set(),
722
+ content: undefined,
723
+ streamContent: new Map([[stream.contentType, stream]])
724
+ })
725
+ } else if (statusMap.streamContent === undefined) {
726
+ statusMap.streamContent = new Map([[stream.contentType, stream]])
727
+ } else {
728
+ statusMap.streamContent.set(stream.contentType, stream)
729
+ }
730
+ }
638
731
  }
639
732
 
640
733
  function resolveDescriptionOrIdentifier(ast: SchemaAST.AST): string | undefined {
@@ -649,6 +742,8 @@ type Content = Map<
649
742
  >
650
743
  >
651
744
 
745
+ type StreamContent = Map<string, HttpApiSchema.StreamSchema>
746
+
652
747
  const Uint8ArrayEncoding = Schema.String.annotate({
653
748
  format: "binary"
654
749
  })
@@ -895,8 +990,26 @@ export interface OpenApiSpecResponse {
895
990
  */
896
991
  export interface OpenApiSpecMediaType {
897
992
  schema: JsonSchema.JsonSchema
993
+ "x-effect-stream"?: OpenApiSpecEffectStream
898
994
  }
899
995
 
996
+ /**
997
+ * Effect-specific metadata for generated streaming response media types.
998
+ *
999
+ * @category models
1000
+ * @since 4.0.0
1001
+ */
1002
+ export type OpenApiSpecEffectStream =
1003
+ | {
1004
+ encoding: "sse"
1005
+ causeSchema: JsonSchema.JsonSchema
1006
+ errorSchema: JsonSchema.JsonSchema
1007
+ failureEvent: "effect/httpapi/stream/failure"
1008
+ }
1009
+ | {
1010
+ encoding: "uint8array"
1011
+ }
1012
+
900
1013
  /**
901
1014
  * Generated OpenAPI request body object for endpoint payloads.
902
1015
  *
@@ -82,7 +82,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
82
82
  readonly reactivityKeys?: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
83
83
  }
84
84
  >,
85
- ResponseByMode<_Success["Type"], ResponseMode>,
85
+ ResponseByMode<Extract<_Success, Schema.Top>["Type"], ResponseMode>,
86
86
  ErrorByMode<_Error, _Middleware, ResponseMode>
87
87
  >
88
88
  : never
@@ -140,7 +140,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
140
140
  >
141
141
  ] ? Atom.Atom<
142
142
  AsyncResult.AsyncResult<
143
- ResponseByMode<_Success["Type"], ResponseMode>,
143
+ ResponseByMode<Extract<_Success, Schema.Top>["Type"], ResponseMode>,
144
144
  ErrorByMode<_Error, _Middleware, ResponseMode>
145
145
  >
146
146
  >