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.
- package/dist/Schema.d.ts +6 -6
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +9 -13
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaAST.d.ts +5 -0
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js.map +1 -1
- package/dist/SchemaParser.d.ts.map +1 -1
- package/dist/SchemaParser.js +7 -2
- package/dist/SchemaParser.js.map +1 -1
- package/dist/unstable/cluster/EntityAddress.d.ts.map +1 -1
- package/dist/unstable/cluster/EntityAddress.js +1 -1
- package/dist/unstable/cluster/EntityAddress.js.map +1 -1
- package/dist/unstable/cluster/Runner.d.ts.map +1 -1
- package/dist/unstable/cluster/Runner.js +1 -1
- package/dist/unstable/cluster/Runner.js.map +1 -1
- package/dist/unstable/cluster/RunnerAddress.d.ts.map +1 -1
- package/dist/unstable/cluster/RunnerAddress.js +1 -1
- package/dist/unstable/cluster/RunnerAddress.js.map +1 -1
- package/dist/unstable/cluster/ShardId.js +3 -3
- package/dist/unstable/cluster/ShardId.js.map +1 -1
- package/dist/unstable/eventlog/EventJournal.js +2 -2
- package/dist/unstable/eventlog/EventJournal.js.map +1 -1
- package/dist/unstable/eventlog/EventLog.js +1 -1
- package/dist/unstable/eventlog/EventLog.js.map +1 -1
- package/dist/unstable/eventlog/SqlEventLogJournal.js +2 -2
- package/dist/unstable/eventlog/SqlEventLogJournal.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js +9 -8
- package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.d.ts +36 -20
- package/dist/unstable/httpapi/HttpApiClient.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.js +49 -18
- package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +186 -67
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.js +44 -29
- package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiSchema.d.ts +5 -0
- package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiSchema.js +20 -2
- package/dist/unstable/httpapi/HttpApiSchema.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +2 -5
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.d.ts +11 -7
- package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.js +6 -6
- package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Schema.ts +8 -12
- package/src/SchemaAST.ts +6 -0
- package/src/SchemaParser.ts +7 -2
- package/src/unstable/cluster/EntityAddress.ts +1 -1
- package/src/unstable/cluster/Runner.ts +1 -1
- package/src/unstable/cluster/RunnerAddress.ts +1 -1
- package/src/unstable/cluster/ShardId.ts +2 -2
- package/src/unstable/eventlog/EventJournal.ts +2 -2
- package/src/unstable/eventlog/EventLog.ts +1 -1
- package/src/unstable/eventlog/SqlEventLogJournal.ts +2 -2
- package/src/unstable/httpapi/HttpApiBuilder.ts +15 -9
- package/src/unstable/httpapi/HttpApiClient.ts +118 -55
- package/src/unstable/httpapi/HttpApiEndpoint.ts +164 -36
- package/src/unstable/httpapi/HttpApiSchema.ts +20 -2
- package/src/unstable/httpapi/OpenApi.ts +2 -6
- package/src/unstable/reactivity/AtomHttpApi.ts +22 -17
- 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
|
-
|
|
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
|
|
491
|
-
Req & { readonly
|
|
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:
|
|
946
|
-
query:
|
|
947
|
-
headers:
|
|
948
|
-
payload: getPayload(options?.payload),
|
|
949
|
-
success:
|
|
950
|
-
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
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
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
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
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
|
|
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
|
-
|
|
1113
|
+
const arr = Arr.ensure(success)
|
|
1114
|
+
return new Set(disableCodecs ? arr : arr.map(transformResponse))
|
|
1009
1115
|
}
|
|
1010
1116
|
|
|
1011
|
-
function
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
-
|
|
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
|
|
44
|
+
const ResponseMode extends HttpApiEndpoint.ClientResponseMode = HttpApiEndpoint.ClientResponseMode
|
|
45
45
|
>(
|
|
46
46
|
group: GroupName,
|
|
47
47
|
endpoint: Name,
|
|
48
48
|
options?: {
|
|
49
|
-
readonly
|
|
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,
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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 (
|
|
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
|
|
211
|
+
readonly responseMode?: HttpApiEndpoint.ClientResponseMode | undefined
|
|
212
212
|
}) =>
|
|
213
213
|
mutationFamily({
|
|
214
214
|
group,
|
|
215
215
|
endpoint,
|
|
216
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)}`
|