@effect/platform 0.62.4 → 0.63.0
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/HttpApi/package.json +6 -0
- package/HttpApiBuilder/package.json +6 -0
- package/HttpApiClient/package.json +6 -0
- package/HttpApiEndpoint/package.json +6 -0
- package/HttpApiError/package.json +6 -0
- package/HttpApiGroup/package.json +6 -0
- package/HttpApiSchema/package.json +6 -0
- package/HttpApiSecurity/package.json +6 -0
- package/HttpApiSwagger/package.json +6 -0
- package/OpenApi/package.json +6 -0
- package/README.md +863 -302
- package/dist/cjs/HttpApi.js +168 -0
- package/dist/cjs/HttpApi.js.map +1 -0
- package/dist/cjs/HttpApiBuilder.js +471 -0
- package/dist/cjs/HttpApiBuilder.js.map +1 -0
- package/dist/cjs/HttpApiClient.js +134 -0
- package/dist/cjs/HttpApiClient.js.map +1 -0
- package/dist/cjs/HttpApiEndpoint.js +181 -0
- package/dist/cjs/HttpApiEndpoint.js.map +1 -0
- package/dist/cjs/HttpApiError.js +69 -0
- package/dist/cjs/HttpApiError.js.map +1 -0
- package/dist/cjs/HttpApiGroup.js +151 -0
- package/dist/cjs/HttpApiGroup.js.map +1 -0
- package/dist/cjs/HttpApiSchema.js +241 -0
- package/dist/cjs/HttpApiSchema.js.map +1 -0
- package/dist/cjs/HttpApiSecurity.js +83 -0
- package/dist/cjs/HttpApiSecurity.js.map +1 -0
- package/dist/cjs/HttpApiSwagger.js +50 -0
- package/dist/cjs/HttpApiSwagger.js.map +1 -0
- package/dist/cjs/HttpMethod.js +1 -1
- package/dist/cjs/HttpMethod.js.map +1 -1
- package/dist/cjs/HttpRouter.js +6 -1
- package/dist/cjs/HttpRouter.js.map +1 -1
- package/dist/cjs/OpenApi.js +317 -0
- package/dist/cjs/OpenApi.js.map +1 -0
- package/dist/cjs/index.js +21 -1
- package/dist/cjs/internal/apiSwagger.js +2 -0
- package/dist/cjs/internal/apiSwagger.js.map +1 -0
- package/dist/cjs/internal/httpRouter.js +6 -1
- package/dist/cjs/internal/httpRouter.js.map +1 -1
- package/dist/cjs/internal/multipart.js +5 -1
- package/dist/cjs/internal/multipart.js.map +1 -1
- package/dist/dts/HttpApi.d.ts +156 -0
- package/dist/dts/HttpApi.d.ts.map +1 -0
- package/dist/dts/HttpApiBuilder.d.ts +296 -0
- package/dist/dts/HttpApiBuilder.d.ts.map +1 -0
- package/dist/dts/HttpApiClient.d.ts +31 -0
- package/dist/dts/HttpApiClient.d.ts.map +1 -0
- package/dist/dts/HttpApiEndpoint.d.ts +350 -0
- package/dist/dts/HttpApiEndpoint.d.ts.map +1 -0
- package/dist/dts/HttpApiError.d.ts +70 -0
- package/dist/dts/HttpApiError.d.ts.map +1 -0
- package/dist/dts/HttpApiGroup.d.ts +196 -0
- package/dist/dts/HttpApiGroup.d.ts.map +1 -0
- package/dist/dts/HttpApiSchema.d.ts +223 -0
- package/dist/dts/HttpApiSchema.d.ts.map +1 -0
- package/dist/dts/HttpApiSecurity.d.ts +122 -0
- package/dist/dts/HttpApiSecurity.d.ts.map +1 -0
- package/dist/dts/HttpApiSwagger.d.ts +10 -0
- package/dist/dts/HttpApiSwagger.d.ts.map +1 -0
- package/dist/dts/HttpMethod.d.ts +16 -0
- package/dist/dts/HttpMethod.d.ts.map +1 -1
- package/dist/dts/HttpRouter.d.ts +8 -0
- package/dist/dts/HttpRouter.d.ts.map +1 -1
- package/dist/dts/HttpServerResponse.d.ts +3 -3
- package/dist/dts/HttpServerResponse.d.ts.map +1 -1
- package/dist/dts/OpenApi.d.ts +348 -0
- package/dist/dts/OpenApi.d.ts.map +1 -0
- package/dist/dts/index.d.ts +40 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/apiSwagger.d.ts +2 -0
- package/dist/dts/internal/apiSwagger.d.ts.map +1 -0
- package/dist/dts/internal/httpRouter.d.ts.map +1 -1
- package/dist/esm/HttpApi.js +157 -0
- package/dist/esm/HttpApi.js.map +1 -0
- package/dist/esm/HttpApiBuilder.js +447 -0
- package/dist/esm/HttpApiBuilder.js.map +1 -0
- package/dist/esm/HttpApiClient.js +124 -0
- package/dist/esm/HttpApiClient.js.map +1 -0
- package/dist/esm/HttpApiEndpoint.js +169 -0
- package/dist/esm/HttpApiEndpoint.js.map +1 -0
- package/dist/esm/HttpApiError.js +59 -0
- package/dist/esm/HttpApiError.js.map +1 -0
- package/dist/esm/HttpApiGroup.js +140 -0
- package/dist/esm/HttpApiGroup.js.map +1 -0
- package/dist/esm/HttpApiSchema.js +217 -0
- package/dist/esm/HttpApiSchema.js.map +1 -0
- package/dist/esm/HttpApiSecurity.js +73 -0
- package/dist/esm/HttpApiSecurity.js.map +1 -0
- package/dist/esm/HttpApiSwagger.js +40 -0
- package/dist/esm/HttpApiSwagger.js.map +1 -0
- package/dist/esm/HttpMethod.js +1 -1
- package/dist/esm/HttpMethod.js.map +1 -1
- package/dist/esm/HttpRouter.js +5 -0
- package/dist/esm/HttpRouter.js.map +1 -1
- package/dist/esm/OpenApi.js +299 -0
- package/dist/esm/OpenApi.js.map +1 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/apiSwagger.js +2 -0
- package/dist/esm/internal/apiSwagger.js.map +1 -0
- package/dist/esm/internal/httpRouter.js +5 -0
- package/dist/esm/internal/httpRouter.js.map +1 -1
- package/dist/esm/internal/multipart.js +5 -1
- package/dist/esm/internal/multipart.js.map +1 -1
- package/package.json +83 -3
- package/src/HttpApi.ts +342 -0
- package/src/HttpApiBuilder.ts +869 -0
- package/src/HttpApiClient.ts +228 -0
- package/src/HttpApiEndpoint.ts +818 -0
- package/src/HttpApiError.ts +113 -0
- package/src/HttpApiGroup.ts +365 -0
- package/src/HttpApiSchema.ts +384 -0
- package/src/HttpApiSecurity.ts +169 -0
- package/src/HttpApiSwagger.ts +46 -0
- package/src/HttpMethod.ts +19 -1
- package/src/HttpRouter.ts +9 -0
- package/src/HttpServerResponse.ts +3 -3
- package/src/OpenApi.ts +665 -0
- package/src/index.ts +50 -0
- package/src/internal/apiSwagger.ts +7 -0
- package/src/internal/httpRouter.ts +9 -0
- package/src/internal/multipart.ts +5 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as ParseResult from "@effect/schema/ParseResult"
|
|
5
|
+
import * as Schema from "@effect/schema/Schema"
|
|
6
|
+
import * as Context from "effect/Context"
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import { identity } from "effect/Function"
|
|
9
|
+
import * as Option from "effect/Option"
|
|
10
|
+
import type { Simplify } from "effect/Types"
|
|
11
|
+
import * as HttpApi from "./HttpApi.js"
|
|
12
|
+
import type { HttpApiEndpoint } from "./HttpApiEndpoint.js"
|
|
13
|
+
import type { HttpApiGroup } from "./HttpApiGroup.js"
|
|
14
|
+
import * as HttpApiSchema from "./HttpApiSchema.js"
|
|
15
|
+
import * as HttpClient from "./HttpClient.js"
|
|
16
|
+
import * as HttpClientError from "./HttpClientError.js"
|
|
17
|
+
import * as HttpClientRequest from "./HttpClientRequest.js"
|
|
18
|
+
import * as HttpClientResponse from "./HttpClientResponse.js"
|
|
19
|
+
import * as HttpMethod from "./HttpMethod.js"
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @since 1.0.0
|
|
23
|
+
* @category models
|
|
24
|
+
*/
|
|
25
|
+
export type Client<A extends HttpApi.HttpApi.Any> = [A] extends
|
|
26
|
+
[HttpApi.HttpApi<infer _Groups, infer _ApiError, infer _ApiErrorR>] ? {
|
|
27
|
+
readonly [GroupName in _Groups["identifier"]]: [HttpApiGroup.WithName<_Groups, GroupName>] extends
|
|
28
|
+
[HttpApiGroup<GroupName, infer _Endpoints, infer _GroupError, infer _GroupErrorR>] ? {
|
|
29
|
+
readonly [Name in _Endpoints["name"]]: [HttpApiEndpoint.WithName<_Endpoints, Name>] extends [
|
|
30
|
+
HttpApiEndpoint<
|
|
31
|
+
Name,
|
|
32
|
+
infer _Method,
|
|
33
|
+
infer _Path,
|
|
34
|
+
infer _Payload,
|
|
35
|
+
infer _Headers,
|
|
36
|
+
infer _Success,
|
|
37
|
+
infer _Error,
|
|
38
|
+
infer _R
|
|
39
|
+
>
|
|
40
|
+
] ? (
|
|
41
|
+
request: Simplify<HttpApiEndpoint.ClientRequest<_Path, _Payload, _Headers>>
|
|
42
|
+
) => Effect.Effect<
|
|
43
|
+
_Success,
|
|
44
|
+
_Error | _GroupError | _ApiError | HttpClientError.HttpClientError
|
|
45
|
+
> :
|
|
46
|
+
never
|
|
47
|
+
} :
|
|
48
|
+
never
|
|
49
|
+
} :
|
|
50
|
+
never
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @since 1.0.0
|
|
54
|
+
* @category constructors
|
|
55
|
+
*/
|
|
56
|
+
export const make = <A extends HttpApi.HttpApi.Any>(
|
|
57
|
+
api: A,
|
|
58
|
+
options?: {
|
|
59
|
+
readonly transformClient?: ((client: HttpClient.HttpClient.Default) => HttpClient.HttpClient.Default) | undefined
|
|
60
|
+
readonly baseUrl?: string | undefined
|
|
61
|
+
}
|
|
62
|
+
): Effect.Effect<Simplify<Client<A>>, never, HttpApi.HttpApi.Context<A> | HttpClient.HttpClient.Default> =>
|
|
63
|
+
Effect.gen(function*() {
|
|
64
|
+
const context = yield* Effect.context<any>()
|
|
65
|
+
const httpClient = (yield* HttpClient.HttpClient).pipe(
|
|
66
|
+
options?.baseUrl === undefined ? identity : HttpClient.mapRequest(HttpClientRequest.prependUrl(options.baseUrl)),
|
|
67
|
+
options?.transformClient === undefined ? identity : options.transformClient
|
|
68
|
+
)
|
|
69
|
+
const client: Record<string, Record<string, any>> = {}
|
|
70
|
+
HttpApi.reflect(api as any, {
|
|
71
|
+
onGroup({ group }) {
|
|
72
|
+
client[group.identifier] = {}
|
|
73
|
+
},
|
|
74
|
+
onEndpoint({ endpoint, errors, group, successAST, successEncoding, successStatus }) {
|
|
75
|
+
const makeUrl = compilePath(endpoint.path)
|
|
76
|
+
const successDecode = successAST.pipe(
|
|
77
|
+
Option.map((ast) => {
|
|
78
|
+
const schema = Schema.make(ast)
|
|
79
|
+
switch (successEncoding.kind) {
|
|
80
|
+
case "Json": {
|
|
81
|
+
return HttpClientResponse.schemaBodyJson(schema)
|
|
82
|
+
}
|
|
83
|
+
case "UrlParams": {
|
|
84
|
+
return HttpClientResponse.schemaBodyUrlParams(schema as any)
|
|
85
|
+
}
|
|
86
|
+
case "Uint8Array": {
|
|
87
|
+
return (response: HttpClientResponse.HttpClientResponse) =>
|
|
88
|
+
response.arrayBuffer.pipe(
|
|
89
|
+
Effect.map((buffer) => new Uint8Array(buffer)),
|
|
90
|
+
Effect.flatMap(Schema.decodeUnknown(schema))
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
case "Text": {
|
|
94
|
+
return (response: HttpClientResponse.HttpClientResponse) =>
|
|
95
|
+
Effect.flatMap(response.text, Schema.decodeUnknown(schema))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
)
|
|
100
|
+
const handleError = (
|
|
101
|
+
request: HttpClientRequest.HttpClientRequest,
|
|
102
|
+
response: HttpClientResponse.HttpClientResponse
|
|
103
|
+
) => {
|
|
104
|
+
const error = errors.get(response.status)
|
|
105
|
+
if (error === undefined) {
|
|
106
|
+
return Effect.die(
|
|
107
|
+
new HttpClientError.ResponseError({
|
|
108
|
+
reason: "Decode",
|
|
109
|
+
request,
|
|
110
|
+
response
|
|
111
|
+
})
|
|
112
|
+
)
|
|
113
|
+
} else if (Option.isNone(error)) {
|
|
114
|
+
return Effect.fail(
|
|
115
|
+
new HttpClientError.ResponseError({
|
|
116
|
+
reason: "StatusCode",
|
|
117
|
+
request,
|
|
118
|
+
response
|
|
119
|
+
})
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
const decode = Schema.decodeUnknown(Schema.make(error.value))
|
|
123
|
+
return response.text.pipe(
|
|
124
|
+
Effect.flatMap((text) =>
|
|
125
|
+
text === "" ? Effect.void : Effect.try({
|
|
126
|
+
try: () => JSON.parse(text),
|
|
127
|
+
catch: (cause) =>
|
|
128
|
+
new HttpClientError.ResponseError({
|
|
129
|
+
reason: "Decode",
|
|
130
|
+
request,
|
|
131
|
+
response,
|
|
132
|
+
cause
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
),
|
|
136
|
+
Effect.flatMap((json) =>
|
|
137
|
+
Effect.mapError(decode(json), (cause) =>
|
|
138
|
+
new HttpClientError.ResponseError({
|
|
139
|
+
reason: "Decode",
|
|
140
|
+
request,
|
|
141
|
+
response,
|
|
142
|
+
cause
|
|
143
|
+
}))
|
|
144
|
+
),
|
|
145
|
+
Effect.flatMap(Effect.fail)
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
const isMultipart = endpoint.payloadSchema.pipe(
|
|
149
|
+
Option.map((schema) => HttpApiSchema.getMultipart(schema.ast)),
|
|
150
|
+
Option.getOrElse(() => false)
|
|
151
|
+
)
|
|
152
|
+
const encodePayload = endpoint.payloadSchema.pipe(
|
|
153
|
+
Option.filter(() => !isMultipart),
|
|
154
|
+
Option.map(Schema.encodeUnknown)
|
|
155
|
+
)
|
|
156
|
+
const encodeHeaders = endpoint.headersSchema.pipe(
|
|
157
|
+
Option.map(Schema.encodeUnknown)
|
|
158
|
+
)
|
|
159
|
+
client[group.identifier][endpoint.name] = (request: {
|
|
160
|
+
readonly path: any
|
|
161
|
+
readonly payload: any
|
|
162
|
+
readonly headers: any
|
|
163
|
+
}) => {
|
|
164
|
+
const url = request && request.path ? makeUrl(request && request.path) : endpoint.path
|
|
165
|
+
const baseRequest = HttpClientRequest.make(endpoint.method)(url)
|
|
166
|
+
return (isMultipart ?
|
|
167
|
+
Effect.succeed(baseRequest.pipe(
|
|
168
|
+
HttpClientRequest.formDataBody(request.payload)
|
|
169
|
+
))
|
|
170
|
+
: encodePayload._tag === "Some"
|
|
171
|
+
? encodePayload.value(request.payload).pipe(
|
|
172
|
+
Effect.flatMap((payload) =>
|
|
173
|
+
HttpMethod.hasBody(endpoint.method)
|
|
174
|
+
? HttpClientRequest.jsonBody(baseRequest, payload)
|
|
175
|
+
: Effect.succeed(HttpClientRequest.setUrlParams(baseRequest, payload as any))
|
|
176
|
+
),
|
|
177
|
+
Effect.orDie
|
|
178
|
+
)
|
|
179
|
+
: Effect.succeed(baseRequest)).pipe(
|
|
180
|
+
encodeHeaders._tag === "Some"
|
|
181
|
+
? Effect.flatMap((httpRequest) =>
|
|
182
|
+
encodeHeaders.value(request.headers).pipe(
|
|
183
|
+
Effect.orDie,
|
|
184
|
+
Effect.map((headers) => HttpClientRequest.setHeaders(httpRequest, headers as any))
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
: identity,
|
|
188
|
+
Effect.flatMap((request) =>
|
|
189
|
+
Effect.flatMap(httpClient(request), (response) =>
|
|
190
|
+
response.status !== successStatus
|
|
191
|
+
? handleError(request, response)
|
|
192
|
+
: Effect.succeed(response))
|
|
193
|
+
),
|
|
194
|
+
successDecode._tag === "Some"
|
|
195
|
+
? Effect.flatMap(successDecode.value)
|
|
196
|
+
: Effect.asVoid,
|
|
197
|
+
Effect.scoped,
|
|
198
|
+
Effect.catchIf(ParseResult.isParseError, Effect.die),
|
|
199
|
+
Effect.mapInputContext((input) => Context.merge(context, input))
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
return client as any
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// ----------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
const paramsRegex = /:(\w+)[^/]*/g
|
|
210
|
+
|
|
211
|
+
const compilePath = (path: string) => {
|
|
212
|
+
const segments = path.split(paramsRegex)
|
|
213
|
+
const len = segments.length
|
|
214
|
+
if (len === 1) {
|
|
215
|
+
return (_: any) => path
|
|
216
|
+
}
|
|
217
|
+
return (params: Record<string, string>) => {
|
|
218
|
+
let url = segments[0]
|
|
219
|
+
for (let i = 1; i < len; i++) {
|
|
220
|
+
if (i % 2 === 0) {
|
|
221
|
+
url += segments[i]
|
|
222
|
+
} else {
|
|
223
|
+
url += params[segments[i]]
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return url
|
|
227
|
+
}
|
|
228
|
+
}
|