@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.
Files changed (123) hide show
  1. package/HttpApi/package.json +6 -0
  2. package/HttpApiBuilder/package.json +6 -0
  3. package/HttpApiClient/package.json +6 -0
  4. package/HttpApiEndpoint/package.json +6 -0
  5. package/HttpApiError/package.json +6 -0
  6. package/HttpApiGroup/package.json +6 -0
  7. package/HttpApiSchema/package.json +6 -0
  8. package/HttpApiSecurity/package.json +6 -0
  9. package/HttpApiSwagger/package.json +6 -0
  10. package/OpenApi/package.json +6 -0
  11. package/README.md +863 -302
  12. package/dist/cjs/HttpApi.js +168 -0
  13. package/dist/cjs/HttpApi.js.map +1 -0
  14. package/dist/cjs/HttpApiBuilder.js +471 -0
  15. package/dist/cjs/HttpApiBuilder.js.map +1 -0
  16. package/dist/cjs/HttpApiClient.js +134 -0
  17. package/dist/cjs/HttpApiClient.js.map +1 -0
  18. package/dist/cjs/HttpApiEndpoint.js +181 -0
  19. package/dist/cjs/HttpApiEndpoint.js.map +1 -0
  20. package/dist/cjs/HttpApiError.js +69 -0
  21. package/dist/cjs/HttpApiError.js.map +1 -0
  22. package/dist/cjs/HttpApiGroup.js +151 -0
  23. package/dist/cjs/HttpApiGroup.js.map +1 -0
  24. package/dist/cjs/HttpApiSchema.js +241 -0
  25. package/dist/cjs/HttpApiSchema.js.map +1 -0
  26. package/dist/cjs/HttpApiSecurity.js +83 -0
  27. package/dist/cjs/HttpApiSecurity.js.map +1 -0
  28. package/dist/cjs/HttpApiSwagger.js +50 -0
  29. package/dist/cjs/HttpApiSwagger.js.map +1 -0
  30. package/dist/cjs/HttpMethod.js +1 -1
  31. package/dist/cjs/HttpMethod.js.map +1 -1
  32. package/dist/cjs/HttpRouter.js +6 -1
  33. package/dist/cjs/HttpRouter.js.map +1 -1
  34. package/dist/cjs/OpenApi.js +317 -0
  35. package/dist/cjs/OpenApi.js.map +1 -0
  36. package/dist/cjs/index.js +21 -1
  37. package/dist/cjs/internal/apiSwagger.js +2 -0
  38. package/dist/cjs/internal/apiSwagger.js.map +1 -0
  39. package/dist/cjs/internal/httpRouter.js +6 -1
  40. package/dist/cjs/internal/httpRouter.js.map +1 -1
  41. package/dist/cjs/internal/multipart.js +5 -1
  42. package/dist/cjs/internal/multipart.js.map +1 -1
  43. package/dist/dts/HttpApi.d.ts +156 -0
  44. package/dist/dts/HttpApi.d.ts.map +1 -0
  45. package/dist/dts/HttpApiBuilder.d.ts +296 -0
  46. package/dist/dts/HttpApiBuilder.d.ts.map +1 -0
  47. package/dist/dts/HttpApiClient.d.ts +31 -0
  48. package/dist/dts/HttpApiClient.d.ts.map +1 -0
  49. package/dist/dts/HttpApiEndpoint.d.ts +350 -0
  50. package/dist/dts/HttpApiEndpoint.d.ts.map +1 -0
  51. package/dist/dts/HttpApiError.d.ts +70 -0
  52. package/dist/dts/HttpApiError.d.ts.map +1 -0
  53. package/dist/dts/HttpApiGroup.d.ts +196 -0
  54. package/dist/dts/HttpApiGroup.d.ts.map +1 -0
  55. package/dist/dts/HttpApiSchema.d.ts +223 -0
  56. package/dist/dts/HttpApiSchema.d.ts.map +1 -0
  57. package/dist/dts/HttpApiSecurity.d.ts +122 -0
  58. package/dist/dts/HttpApiSecurity.d.ts.map +1 -0
  59. package/dist/dts/HttpApiSwagger.d.ts +10 -0
  60. package/dist/dts/HttpApiSwagger.d.ts.map +1 -0
  61. package/dist/dts/HttpMethod.d.ts +16 -0
  62. package/dist/dts/HttpMethod.d.ts.map +1 -1
  63. package/dist/dts/HttpRouter.d.ts +8 -0
  64. package/dist/dts/HttpRouter.d.ts.map +1 -1
  65. package/dist/dts/HttpServerResponse.d.ts +3 -3
  66. package/dist/dts/HttpServerResponse.d.ts.map +1 -1
  67. package/dist/dts/OpenApi.d.ts +348 -0
  68. package/dist/dts/OpenApi.d.ts.map +1 -0
  69. package/dist/dts/index.d.ts +40 -0
  70. package/dist/dts/index.d.ts.map +1 -1
  71. package/dist/dts/internal/apiSwagger.d.ts +2 -0
  72. package/dist/dts/internal/apiSwagger.d.ts.map +1 -0
  73. package/dist/dts/internal/httpRouter.d.ts.map +1 -1
  74. package/dist/esm/HttpApi.js +157 -0
  75. package/dist/esm/HttpApi.js.map +1 -0
  76. package/dist/esm/HttpApiBuilder.js +447 -0
  77. package/dist/esm/HttpApiBuilder.js.map +1 -0
  78. package/dist/esm/HttpApiClient.js +124 -0
  79. package/dist/esm/HttpApiClient.js.map +1 -0
  80. package/dist/esm/HttpApiEndpoint.js +169 -0
  81. package/dist/esm/HttpApiEndpoint.js.map +1 -0
  82. package/dist/esm/HttpApiError.js +59 -0
  83. package/dist/esm/HttpApiError.js.map +1 -0
  84. package/dist/esm/HttpApiGroup.js +140 -0
  85. package/dist/esm/HttpApiGroup.js.map +1 -0
  86. package/dist/esm/HttpApiSchema.js +217 -0
  87. package/dist/esm/HttpApiSchema.js.map +1 -0
  88. package/dist/esm/HttpApiSecurity.js +73 -0
  89. package/dist/esm/HttpApiSecurity.js.map +1 -0
  90. package/dist/esm/HttpApiSwagger.js +40 -0
  91. package/dist/esm/HttpApiSwagger.js.map +1 -0
  92. package/dist/esm/HttpMethod.js +1 -1
  93. package/dist/esm/HttpMethod.js.map +1 -1
  94. package/dist/esm/HttpRouter.js +5 -0
  95. package/dist/esm/HttpRouter.js.map +1 -1
  96. package/dist/esm/OpenApi.js +299 -0
  97. package/dist/esm/OpenApi.js.map +1 -0
  98. package/dist/esm/index.js +40 -0
  99. package/dist/esm/index.js.map +1 -1
  100. package/dist/esm/internal/apiSwagger.js +2 -0
  101. package/dist/esm/internal/apiSwagger.js.map +1 -0
  102. package/dist/esm/internal/httpRouter.js +5 -0
  103. package/dist/esm/internal/httpRouter.js.map +1 -1
  104. package/dist/esm/internal/multipart.js +5 -1
  105. package/dist/esm/internal/multipart.js.map +1 -1
  106. package/package.json +83 -3
  107. package/src/HttpApi.ts +342 -0
  108. package/src/HttpApiBuilder.ts +869 -0
  109. package/src/HttpApiClient.ts +228 -0
  110. package/src/HttpApiEndpoint.ts +818 -0
  111. package/src/HttpApiError.ts +113 -0
  112. package/src/HttpApiGroup.ts +365 -0
  113. package/src/HttpApiSchema.ts +384 -0
  114. package/src/HttpApiSecurity.ts +169 -0
  115. package/src/HttpApiSwagger.ts +46 -0
  116. package/src/HttpMethod.ts +19 -1
  117. package/src/HttpRouter.ts +9 -0
  118. package/src/HttpServerResponse.ts +3 -3
  119. package/src/OpenApi.ts +665 -0
  120. package/src/index.ts +50 -0
  121. package/src/internal/apiSwagger.ts +7 -0
  122. package/src/internal/httpRouter.ts +9 -0
  123. 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
+ }