effect 4.0.0-beta.37 → 4.0.0-beta.38

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 (68) hide show
  1. package/dist/Schema.d.ts +6 -6
  2. package/dist/Schema.d.ts.map +1 -1
  3. package/dist/Schema.js +9 -13
  4. package/dist/Schema.js.map +1 -1
  5. package/dist/SchemaAST.d.ts +5 -0
  6. package/dist/SchemaAST.d.ts.map +1 -1
  7. package/dist/SchemaAST.js.map +1 -1
  8. package/dist/SchemaParser.d.ts.map +1 -1
  9. package/dist/SchemaParser.js +7 -2
  10. package/dist/SchemaParser.js.map +1 -1
  11. package/dist/unstable/cluster/EntityAddress.d.ts.map +1 -1
  12. package/dist/unstable/cluster/EntityAddress.js +1 -1
  13. package/dist/unstable/cluster/EntityAddress.js.map +1 -1
  14. package/dist/unstable/cluster/Runner.d.ts.map +1 -1
  15. package/dist/unstable/cluster/Runner.js +1 -1
  16. package/dist/unstable/cluster/Runner.js.map +1 -1
  17. package/dist/unstable/cluster/RunnerAddress.d.ts.map +1 -1
  18. package/dist/unstable/cluster/RunnerAddress.js +1 -1
  19. package/dist/unstable/cluster/RunnerAddress.js.map +1 -1
  20. package/dist/unstable/cluster/ShardId.js +3 -3
  21. package/dist/unstable/cluster/ShardId.js.map +1 -1
  22. package/dist/unstable/eventlog/EventJournal.js +2 -2
  23. package/dist/unstable/eventlog/EventJournal.js.map +1 -1
  24. package/dist/unstable/eventlog/EventLog.js +1 -1
  25. package/dist/unstable/eventlog/EventLog.js.map +1 -1
  26. package/dist/unstable/eventlog/SqlEventLogJournal.js +2 -2
  27. package/dist/unstable/eventlog/SqlEventLogJournal.js.map +1 -1
  28. package/dist/unstable/httpapi/HttpApiBuilder.js +9 -8
  29. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  30. package/dist/unstable/httpapi/HttpApiClient.d.ts +36 -20
  31. package/dist/unstable/httpapi/HttpApiClient.d.ts.map +1 -1
  32. package/dist/unstable/httpapi/HttpApiClient.js +49 -18
  33. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  34. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +186 -67
  35. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
  36. package/dist/unstable/httpapi/HttpApiEndpoint.js +44 -29
  37. package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
  38. package/dist/unstable/httpapi/HttpApiSchema.d.ts +5 -0
  39. package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
  40. package/dist/unstable/httpapi/HttpApiSchema.js +20 -2
  41. package/dist/unstable/httpapi/HttpApiSchema.js.map +1 -1
  42. package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
  43. package/dist/unstable/httpapi/OpenApi.js +2 -5
  44. package/dist/unstable/httpapi/OpenApi.js.map +1 -1
  45. package/dist/unstable/reactivity/AtomHttpApi.d.ts +11 -7
  46. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  47. package/dist/unstable/reactivity/AtomHttpApi.js +6 -6
  48. package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
  49. package/dist/unstable/schema/VariantSchema.d.ts +1 -1
  50. package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
  51. package/package.json +1 -1
  52. package/src/Schema.ts +8 -12
  53. package/src/SchemaAST.ts +6 -0
  54. package/src/SchemaParser.ts +7 -2
  55. package/src/unstable/cluster/EntityAddress.ts +1 -1
  56. package/src/unstable/cluster/Runner.ts +1 -1
  57. package/src/unstable/cluster/RunnerAddress.ts +1 -1
  58. package/src/unstable/cluster/ShardId.ts +2 -2
  59. package/src/unstable/eventlog/EventJournal.ts +2 -2
  60. package/src/unstable/eventlog/EventLog.ts +1 -1
  61. package/src/unstable/eventlog/SqlEventLogJournal.ts +2 -2
  62. package/src/unstable/httpapi/HttpApiBuilder.ts +15 -9
  63. package/src/unstable/httpapi/HttpApiClient.ts +118 -55
  64. package/src/unstable/httpapi/HttpApiEndpoint.ts +164 -36
  65. package/src/unstable/httpapi/HttpApiSchema.ts +20 -2
  66. package/src/unstable/httpapi/OpenApi.ts +2 -6
  67. package/src/unstable/reactivity/AtomHttpApi.ts +22 -17
  68. package/src/unstable/schema/VariantSchema.ts +1 -1
@@ -4,6 +4,7 @@
4
4
  import * as Arr from "../../Array.ts"
5
5
  import type { Brand } from "../../Brand.ts"
6
6
  import type { Effect } from "../../Effect.ts"
7
+ import { identity } from "../../Function.ts"
7
8
  import { type Pipeable, pipeArguments } from "../../Pipeable.ts"
8
9
  import * as Predicate from "../../Predicate.ts"
9
10
  import * as Schema from "../../Schema.ts"
@@ -476,7 +477,7 @@ export type ClientRequest<
476
477
  Query extends Schema.Top,
477
478
  Payload extends Schema.Top,
478
479
  Headers extends Schema.Top,
479
- WithResponse extends boolean
480
+ ResponseMode extends ClientResponseMode
480
481
  > = (
481
482
  & ([Params["Type"]] extends [never] ? {} : { readonly params: Params["Type"] })
482
483
  & ([Query["Type"]] extends [never] ? {} : { readonly query: Query["Type"] })
@@ -487,10 +488,16 @@ export type ClientRequest<
487
488
  ? { readonly payload: FormData }
488
489
  : { readonly payload: Payload["Type"] }
489
490
  : { readonly payload: Payload["Type"] })
490
- ) extends infer Req ? keyof Req extends never ? (void | { readonly withResponse?: WithResponse }) :
491
- Req & { readonly withResponse?: WithResponse } :
491
+ ) extends infer Req ? keyof Req extends never ? (void | { readonly responseMode?: ResponseMode }) :
492
+ Req & { readonly responseMode?: ResponseMode } :
492
493
  void
493
494
 
495
+ /**
496
+ * @since 4.0.0
497
+ * @category models
498
+ */
499
+ export type ClientResponseMode = "decoded-only" | "decoded-and-response" | "response-only"
500
+
494
501
  /**
495
502
  * @since 4.0.0
496
503
  * @category models
@@ -888,6 +895,14 @@ export type PayloadConstraint<Method extends HttpMethod> = Method extends HttpMe
888
895
  > :
889
896
  SuccessConstraint
890
897
 
898
+ /**
899
+ * @since 4.0.0
900
+ * @category constraints
901
+ */
902
+ export type PayloadConstraintCodecs<Method extends HttpMethod> = Method extends HttpMethod.NoBody ?
903
+ Record<string, Schema.Top> :
904
+ Schema.Top | ReadonlyArray<Schema.Top>
905
+
891
906
  /**
892
907
  * @since 4.0.0
893
908
  * @category constraints
@@ -904,7 +919,73 @@ export type ErrorConstraint = Schema.Top | ReadonlyArray<Schema.Top>
904
919
  * @since 4.0.0
905
920
  * @category constructors
906
921
  */
907
- export const make = <Method extends HttpMethod>(method: Method) =>
922
+ export const make = <Method extends HttpMethod>(method: Method): {
923
+ <
924
+ const Name extends string,
925
+ const Path extends HttpRouter.PathInput,
926
+ Params extends Schema.Top | Schema.Struct.Fields = never,
927
+ Query extends Schema.Top | Schema.Struct.Fields = never,
928
+ Payload extends PayloadConstraintCodecs<Method> = never,
929
+ Headers extends Schema.Top | Schema.Struct.Fields = never,
930
+ const Success extends Schema.Top | ReadonlyArray<Schema.Top> = HttpApiSchema.NoContent,
931
+ const Error extends Schema.Top | ReadonlyArray<Schema.Top> = never
932
+ >(
933
+ name: Name,
934
+ path: Path,
935
+ options?: {
936
+ readonly disableCodecs?: false | undefined
937
+ readonly params?: Params | undefined
938
+ readonly query?: Query | undefined
939
+ readonly headers?: Headers | undefined
940
+ readonly payload?: Payload | undefined
941
+ readonly success?: Success | undefined
942
+ readonly error?: Error | undefined
943
+ }
944
+ ): HttpApiEndpoint<
945
+ Name,
946
+ Method,
947
+ Path,
948
+ StringTree<Params extends Schema.Struct.Fields ? Schema.Struct<Params> : Params>,
949
+ StringTree<Query extends Schema.Struct.Fields ? Schema.Struct<Query> : Query>,
950
+ Method extends HttpMethod.WithBody ? Json<ExtractSchemaOrArray<Payload>>
951
+ : StringTree<ExtractSchemaOrArray<Payload>>,
952
+ StringTree<Headers extends Schema.Struct.Fields ? Schema.Struct<Headers> : Headers>,
953
+ Json<Success extends ReadonlyArray<Schema.Top> ? Success[number] : Success>,
954
+ Json<(Error extends ReadonlyArray<Schema.Top> ? Error[number] : Error) | typeof BadRequestNoContent>
955
+ >
956
+ <
957
+ const Name extends string,
958
+ const Path extends HttpRouter.PathInput,
959
+ Params extends ParamsConstraint = never,
960
+ Query extends QueryConstraint = never,
961
+ Payload extends PayloadConstraint<Method> = never,
962
+ Headers extends HeadersConstraint = never,
963
+ const Success extends SuccessConstraint = HttpApiSchema.NoContent,
964
+ const Error extends ErrorConstraint = never
965
+ >(
966
+ name: Name,
967
+ path: Path,
968
+ options?: {
969
+ readonly disableCodecs: true
970
+ readonly params?: Params | undefined
971
+ readonly query?: Query | undefined
972
+ readonly headers?: Headers | undefined
973
+ readonly payload?: Payload | undefined
974
+ readonly success?: Success | undefined
975
+ readonly error?: Error | undefined
976
+ }
977
+ ): HttpApiEndpoint<
978
+ Name,
979
+ Method,
980
+ Path,
981
+ Params extends Schema.Struct.Fields ? Schema.Struct<Params> : Params,
982
+ Query extends Schema.Struct.Fields ? Schema.Struct<Query> : Query,
983
+ ExtractSchemaOrArray<Payload>,
984
+ ExtractSchemaOrArray<Headers>,
985
+ Success extends ReadonlyArray<Schema.Top> ? Success[number] : Success,
986
+ (Error extends ReadonlyArray<Schema.Top> ? Error[number] : Error) | typeof BadRequestNoContent
987
+ >
988
+ } =>
908
989
  <
909
990
  const Name extends string,
910
991
  const Path extends HttpRouter.PathInput,
@@ -918,6 +999,7 @@ export const make = <Method extends HttpMethod>(method: Method) =>
918
999
  name: Name,
919
1000
  path: Path,
920
1001
  options?: {
1002
+ readonly disableCodecs?: boolean | undefined
921
1003
  readonly params?: Params | undefined
922
1004
  readonly query?: Query | undefined
923
1005
  readonly headers?: Headers | undefined
@@ -938,42 +1020,62 @@ export const make = <Method extends HttpMethod>(method: Method) =>
938
1020
  Success extends ReadonlyArray<Schema.Top> ? Success[number] : Success,
939
1021
  (Error extends ReadonlyArray<Schema.Top> ? Error[number] : Error) | typeof BadRequestNoContent
940
1022
  > => {
1023
+ const disableCodecs = options?.disableCodecs ?? false
1024
+ const transformStringTree = disableCodecs ? identity : Schema.toCodecStringTree
941
1025
  return makeProto({
942
1026
  name,
943
1027
  path,
944
1028
  method,
945
- params: getParams(options?.params),
946
- query: getQuery(options?.query),
947
- headers: getHeaders(options?.headers),
948
- payload: getPayload(options?.payload),
949
- success: getSuccess(options?.success),
950
- error: getError(options?.error),
1029
+ params: ensureStruct(options?.params, transformStringTree),
1030
+ query: ensureStruct(options?.query, transformStringTree),
1031
+ headers: ensureStruct(options?.headers, transformStringTree),
1032
+ payload: getPayload(options?.payload, method, disableCodecs),
1033
+ success: getResponse(options?.success, disableCodecs),
1034
+ error: getResponse(options?.error, disableCodecs),
951
1035
  annotations: ServiceMap.empty(),
952
1036
  middlewares: new Set()
953
1037
  })
954
1038
  }
955
1039
 
956
- function getParams(params: ParamsConstraint | undefined): Schema.Top | undefined {
957
- if (params === undefined) return undefined
958
- if (Schema.isSchema(params)) return params
959
- return Schema.Struct(params)
960
- }
1040
+ type ExtractSchemaOrArray<S extends Schema.Struct.Fields | Schema.Top | ReadonlyArray<Schema.Top>> = S extends
1041
+ Schema.Struct.Fields ? Schema.Struct<S>
1042
+ : S extends ReadonlyArray<Schema.Top> ? S[number]
1043
+ : S
961
1044
 
962
- function getQuery(query: QueryConstraint | undefined): Schema.Top | undefined {
963
- if (query === undefined) return undefined
964
- if (Schema.isSchema(query)) return query
965
- return Schema.Struct(query)
966
- }
1045
+ /**
1046
+ * @since 4.0.0
1047
+ * @category Codecs
1048
+ */
1049
+ export interface Json<S extends Schema.Top>
1050
+ extends Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
1051
+ {}
1052
+
1053
+ /**
1054
+ * @since 4.0.0
1055
+ * @category Codecs
1056
+ */
1057
+ export interface StringTree<S extends Schema.Top> extends
1058
+ Schema.Codec<
1059
+ S["Type"],
1060
+ Schema.StringTree,
1061
+ S["DecodingServices"],
1062
+ S["EncodingServices"]
1063
+ >
1064
+ {}
967
1065
 
968
- // all keys should be lowercase
969
- function getHeaders(headers: HeadersConstraint | undefined): Schema.Top | undefined {
970
- if (headers === undefined) return undefined
971
- if (Schema.isSchema(headers)) return headers
972
- return Schema.Struct(headers)
1066
+ function ensureStruct(
1067
+ params: Schema.Struct.Fields | Schema.Top | undefined,
1068
+ transform: typeof Schema.toCodecJson | typeof Schema.toCodecStringTree
1069
+ ): Schema.Top | undefined {
1070
+ if (params === undefined) return undefined
1071
+ if (Schema.isSchema(params)) return transform(params)
1072
+ return transform(Schema.Struct(params))
973
1073
  }
974
1074
 
975
1075
  function getPayload(
976
- payload: Schema.Top | ReadonlyArray<Schema.Top> | Schema.Struct.Fields | undefined
1076
+ payload: Schema.Top | ReadonlyArray<Schema.Top> | Schema.Struct.Fields | undefined,
1077
+ method: HttpMethod,
1078
+ disableCodecs: boolean
977
1079
  ): PayloadMap {
978
1080
  const result: Map<string, { encoding: HttpApiSchema.PayloadEncoding; schemas: [Schema.Top, ...Array<Schema.Top>] }> =
979
1081
  new Map()
@@ -982,9 +1084,11 @@ function getPayload(
982
1084
  ? payload
983
1085
  : Schema.isSchema(payload)
984
1086
  ? [payload]
985
- : [Schema.Struct(payload as any).pipe(HttpApiSchema.asFormUrlEncoded())]
1087
+ : [(Schema.Struct(payload as any)).pipe(HttpApiSchema.asFormUrlEncoded())]
1088
+ const transform = disableCodecs ? identity : transformPayload
1089
+
986
1090
  for (const schema of schemas) {
987
- const encoding = HttpApiSchema.getPayloadEncoding(schema.ast)
1091
+ const encoding = HttpApiSchema.getPayloadEncoding(schema.ast, method)
988
1092
  const existing = result.get(encoding.contentType)
989
1093
  if (existing) {
990
1094
  if (existing.encoding._tag !== encoding._tag) {
@@ -993,24 +1097,48 @@ function getPayload(
993
1097
  if (existing.encoding._tag === "Multipart") {
994
1098
  throw new Error(`Multiple multipart payloads for content-type: ${encoding.contentType}`)
995
1099
  }
996
- existing.schemas.push(schema)
1100
+ existing.schemas.push(transform(schema, method))
997
1101
  } else {
998
- result.set(encoding.contentType, { encoding, schemas: [schema] })
1102
+ result.set(encoding.contentType, { encoding, schemas: [transform(schema, method)] })
999
1103
  }
1000
1104
  }
1001
1105
  return result
1002
1106
  }
1003
1107
 
1004
- function getSuccess(
1005
- success: Schema.Top | ReadonlyArray<Schema.Top> | undefined
1108
+ function getResponse(
1109
+ success: Schema.Top | ReadonlyArray<Schema.Top> | undefined,
1110
+ disableCodecs: boolean
1006
1111
  ): Set<Schema.Top> {
1007
1112
  if (success === undefined) return new Set()
1008
- return new Set(Array.isArray(success) ? success : [success])
1113
+ const arr = Arr.ensure(success)
1114
+ return new Set(disableCodecs ? arr : arr.map(transformResponse))
1009
1115
  }
1010
1116
 
1011
- function getError(error: Schema.Top | ReadonlyArray<Schema.Top> | undefined): Set<Schema.Top> {
1012
- if (error === undefined) return new Set()
1013
- return new Set(Array.isArray(error) ? error : [error])
1117
+ function transformResponse(schema: Schema.Top): Schema.Top {
1118
+ const encoding = HttpApiSchema.getResponseEncoding(schema.ast)
1119
+ switch (encoding._tag) {
1120
+ case "Json":
1121
+ return Schema.toCodecJson(schema)
1122
+ case "FormUrlEncoded":
1123
+ return Schema.toCodecStringTree(schema)
1124
+ case "Text":
1125
+ case "Uint8Array":
1126
+ return schema
1127
+ }
1128
+ }
1129
+
1130
+ function transformPayload(schema: Schema.Top, method: HttpMethod): Schema.Top {
1131
+ const encoding = HttpApiSchema.getPayloadEncoding(schema.ast, method)
1132
+ switch (encoding._tag) {
1133
+ case "Json":
1134
+ return Schema.toCodecJson(schema)
1135
+ case "FormUrlEncoded":
1136
+ return Schema.toCodecStringTree(schema)
1137
+ case "Text":
1138
+ case "Uint8Array":
1139
+ case "Multipart":
1140
+ return schema
1141
+ }
1014
1142
  }
1015
1143
 
1016
1144
  /**
@@ -31,6 +31,7 @@ import { constVoid, type LazyArg } from "../../Function.ts"
31
31
  import * as Schema from "../../Schema.ts"
32
32
  import * as AST from "../../SchemaAST.ts"
33
33
  import * as Transformation from "../../SchemaTransformation.ts"
34
+ import { hasBody, type HttpMethod } from "../http/HttpMethod.ts"
34
35
  import type * as Multipart_ from "../http/Multipart.ts"
35
36
 
36
37
  declare module "../../Schema.ts" {
@@ -332,6 +333,17 @@ export function asUint8Array(options?: {
332
333
  return <S extends Schema.Top & { readonly Encoded: Uint8Array }>(self: S) =>
333
334
  asNonMultipartEncoding(self, { _tag: "Uint8Array", ...options })
334
335
  }
336
+ /**
337
+ * @since 4.0.0
338
+ */
339
+ export const isNoContent = (ast: AST.AST): boolean => {
340
+ if (AST.isVoid(ast)) return true
341
+ const encoded = AST.toEncoded(ast)
342
+ if (AST.isVoid(encoded)) return true
343
+ const target = ast.encoding?.[0].to
344
+ if (target === undefined) return false
345
+ return AST.isVoid(target)
346
+ }
335
347
 
336
348
  const resolveHttpApiEncoding = AST.resolveAt<Encoding>("~httpApiEncoding")
337
349
 
@@ -341,14 +353,20 @@ const defaultJsonEncoding: Encoding = {
341
353
  _tag: "Json",
342
354
  contentType: "application/json"
343
355
  }
356
+ const defaultUrlEncodedEncoding: Encoding = {
357
+ _tag: "FormUrlEncoded",
358
+ contentType: "application/x-www-form-urlencoded"
359
+ }
344
360
 
345
361
  function getEncoding(ast: AST.AST): Encoding {
346
362
  return resolveHttpApiEncoding(ast) ?? defaultJsonEncoding
347
363
  }
348
364
 
349
365
  /** @internal */
350
- export function getPayloadEncoding(ast: AST.AST): PayloadEncoding {
351
- return getEncoding(ast)
366
+ export function getPayloadEncoding(ast: AST.AST, method: HttpMethod): PayloadEncoding {
367
+ const encoding = resolveHttpApiEncoding(ast)
368
+ if (encoding) return encoding
369
+ return hasBody(method) ? defaultJsonEncoding : defaultUrlEncodedEncoding
352
370
  }
353
371
 
354
372
  /** @internal */
@@ -314,7 +314,7 @@ export function fromApi<Id extends string, Groups extends HttpApiGroup.Any>(
314
314
  const c: OpenApiSpecContent = {}
315
315
  let hasContent = false
316
316
  payloadMap.forEach(({ encoding, schemas }, contentType) => {
317
- const filtered = schemas.filter((s) => !isNoContent(s.ast))
317
+ const filtered = schemas.filter((s) => !HttpApiSchema.isNoContent(s.ast))
318
318
  if (filtered.length === 0) return
319
319
  hasContent = true
320
320
  const asts = filtered.map(AST.getAST)
@@ -529,10 +529,6 @@ export function fromApi<Id extends string, Groups extends HttpApiGroup.Any>(
529
529
  return spec
530
530
  }
531
531
 
532
- function isNoContent(ast: AST.AST): boolean {
533
- return AST.isVoid(AST.toEncoded(ast))
534
- }
535
-
536
532
  type ResponseBodies = Map<
537
533
  number, // status
538
534
  {
@@ -558,7 +554,7 @@ function extractResponseBodies(
558
554
  function process(schema: Schema.Top) {
559
555
  const ast = schema.ast
560
556
  const status = getStatus(ast)
561
- if (isNoContent(ast)) {
557
+ if (HttpApiSchema.isNoContent(ast)) {
562
558
  addNoContent(status, getDescription(schema.ast) ?? "<No Content>")
563
559
  } else {
564
560
  addContent(schema, status, HttpApiSchema.getResponseEncoding(ast))
@@ -41,12 +41,12 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
41
41
  HttpApiGroup.Endpoints<Group>,
42
42
  Name
43
43
  >,
44
- const WithResponse extends boolean = false
44
+ const ResponseMode extends HttpApiEndpoint.ClientResponseMode = HttpApiEndpoint.ClientResponseMode
45
45
  >(
46
46
  group: GroupName,
47
47
  endpoint: Name,
48
48
  options?: {
49
- readonly withResponse?: WithResponse | undefined
49
+ readonly responseMode?: ResponseMode | undefined
50
50
  }
51
51
  ) => [Endpoint] extends [
52
52
  HttpApiEndpoint.HttpApiEndpoint<
@@ -64,11 +64,11 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
64
64
  >
65
65
  ] ? Atom.AtomResultFn<
66
66
  Simplify<
67
- HttpApiEndpoint.ClientRequest<_Params, _Query, _Payload, _Headers, false> & {
67
+ HttpApiEndpoint.ClientRequest<_Params, _Query, _Payload, _Headers, "decoded-only"> & {
68
68
  readonly reactivityKeys?: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
69
69
  }
70
70
  >,
71
- WithResponse extends true ? [_Success["Type"], HttpClientResponse] : _Success["Type"],
71
+ ResponseByMode<_Success["Type"], ResponseMode>,
72
72
  _Error["Type"]
73
73
  >
74
74
  : never
@@ -81,7 +81,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
81
81
  HttpApiGroup.Endpoints<Group>,
82
82
  Name
83
83
  >,
84
- const WithResponse extends boolean = false
84
+ const ResponseMode extends HttpApiEndpoint.ClientResponseMode = "decoded-only"
85
85
  >(
86
86
  group: GroupName,
87
87
  endpoint: Name,
@@ -100,7 +100,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
100
100
  infer _RE
101
101
  >
102
102
  ] ? Simplify<
103
- HttpApiEndpoint.ClientRequest<_Params, _Query, _Payload, _Headers, WithResponse> & {
103
+ HttpApiEndpoint.ClientRequest<_Params, _Query, _Payload, _Headers, ResponseMode> & {
104
104
  readonly reactivityKeys?:
105
105
  | ReadonlyArray<unknown>
106
106
  | ReadonlyRecord<string, ReadonlyArray<unknown>>
@@ -125,7 +125,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
125
125
  >
126
126
  ] ? Atom.Atom<
127
127
  AsyncResult.AsyncResult<
128
- WithResponse extends true ? [_Success["Type"], HttpClientResponse] : _Success["Type"],
128
+ ResponseByMode<_Success["Type"], ResponseMode>,
129
129
  _Error["Type"]
130
130
  >
131
131
  >
@@ -175,7 +175,7 @@ export const Service = <Self>() =>
175
175
  Schema.isSchemaError(e) || HttpClientError.isHttpClientError(e) ? Effect.die(e) : Effect.fail(e)
176
176
  )
177
177
 
178
- const mutationFamily = Atom.family(({ endpoint, group, withResponse }: MutationKey) => {
178
+ const mutationFamily = Atom.family(({ endpoint, group, responseMode }: MutationKey) => {
179
179
  const atom = self.runtime.fn<{
180
180
  params: any
181
181
  query: any
@@ -187,14 +187,14 @@ export const Service = <Self>() =>
187
187
  const client = (yield* self) as any
188
188
  const effect = catchErrors(client[group][endpoint]({
189
189
  ...opts,
190
- withResponse
190
+ responseMode
191
191
  }) as Effect.Effect<any>)
192
192
  return yield* opts.reactivityKeys
193
193
  ? Reactivity.mutation(effect, opts.reactivityKeys)
194
194
  : effect
195
195
  })
196
196
  )
197
- if (withResponse === false) {
197
+ if (responseMode === "decoded-only") {
198
198
  const definition = options.api.groups[group]!.endpoints[endpoint]! as HttpApiEndpoint.AnyWithProps
199
199
  return Atom.serializable(atom, {
200
200
  key: `AtomHttpApi:mutation:${group}:${endpoint}`,
@@ -208,12 +208,12 @@ export const Service = <Self>() =>
208
208
  }) as any
209
209
 
210
210
  self.mutation = ((group: string, endpoint: string, options?: {
211
- readonly withResponse?: boolean | undefined
211
+ readonly responseMode?: HttpApiEndpoint.ClientResponseMode | undefined
212
212
  }) =>
213
213
  mutationFamily({
214
214
  group,
215
215
  endpoint,
216
- withResponse: options?.withResponse ?? false
216
+ responseMode: options?.responseMode ?? "decoded-only"
217
217
  })) as any
218
218
 
219
219
  const queryFamily = Atom.family((opts: QueryKey) => {
@@ -224,7 +224,7 @@ export const Service = <Self>() =>
224
224
  HttpClientError.HttpClientError | SchemaError
225
225
  >)
226
226
  }))
227
- if (opts.withResponse === false) {
227
+ if (opts.responseMode === "decoded-only") {
228
228
  const endpoint = options.api.groups[opts.group]!.endpoints[opts.endpoint]! as HttpApiEndpoint.AnyWithProps
229
229
  atom = Atom.serializable(atom, {
230
230
  key: makeSerializableKey(opts),
@@ -252,7 +252,7 @@ export const Service = <Self>() =>
252
252
  readonly query?: any
253
253
  readonly payload?: any
254
254
  readonly headers?: any
255
- readonly withResponse?: boolean
255
+ readonly responseMode?: HttpApiEndpoint.ClientResponseMode
256
256
  readonly reactivityKeys?: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
257
257
  readonly timeToLive?: Duration.Input | undefined
258
258
  }
@@ -264,7 +264,7 @@ export const Service = <Self>() =>
264
264
  query: request.query,
265
265
  payload: request.payload,
266
266
  headers: request.headers,
267
- withResponse: request.withResponse ?? false,
267
+ responseMode: request.responseMode ?? "decoded-only",
268
268
  reactivityKeys: request.reactivityKeys,
269
269
  timeToLive: request.timeToLive
270
270
  ? Duration.fromInputUnsafe(request.timeToLive)
@@ -277,7 +277,7 @@ export const Service = <Self>() =>
277
277
  interface MutationKey {
278
278
  group: string
279
279
  endpoint: string
280
- withResponse: boolean
280
+ responseMode: HttpApiEndpoint.ClientResponseMode
281
281
  }
282
282
 
283
283
  interface QueryKey {
@@ -287,11 +287,16 @@ interface QueryKey {
287
287
  query: any
288
288
  headers: any
289
289
  payload: any
290
- withResponse: boolean
290
+ responseMode: HttpApiEndpoint.ClientResponseMode
291
291
  reactivityKeys?: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
292
292
  timeToLive?: Duration.Duration | undefined
293
293
  }
294
294
 
295
+ type ResponseByMode<Success, ResponseMode extends HttpApiEndpoint.ClientResponseMode> = [ResponseMode] extends
296
+ ["decoded-and-response"] ? [Success, HttpClientResponse]
297
+ : [ResponseMode] extends ["response-only"] ? HttpClientResponse
298
+ : Success
299
+
295
300
  const makeSerializableKey = (
296
301
  key: QueryKey
297
302
  ): string => `AtomHttpApi:${key.group}:${key.endpoint}:${Hash.hash(key)}`
@@ -238,7 +238,7 @@ export interface Class<
238
238
  new(
239
239
  props: S["~type.make.in"],
240
240
  options?: {
241
- readonly disableValidation?: boolean
241
+ readonly disableChecks?: boolean
242
242
  } | undefined
243
243
  ): S["Type"]
244
244