@effect/platform 0.10.4 → 0.11.1

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 (125) hide show
  1. package/Effectify.d.ts.map +1 -1
  2. package/Http/Body.d.ts +129 -0
  3. package/Http/Body.d.ts.map +1 -0
  4. package/Http/Body.js +70 -0
  5. package/Http/Body.js.map +1 -0
  6. package/Http/Client.d.ts +213 -0
  7. package/Http/Client.d.ts.map +1 -0
  8. package/Http/Client.js +124 -0
  9. package/Http/Client.js.map +1 -0
  10. package/Http/ClientError.d.ts +70 -0
  11. package/Http/ClientError.d.ts.map +1 -0
  12. package/Http/ClientError.js +28 -0
  13. package/Http/ClientError.js.map +1 -0
  14. package/Http/ClientRequest.d.ts +317 -0
  15. package/Http/ClientRequest.d.ts.map +1 -0
  16. package/Http/ClientRequest.js +202 -0
  17. package/Http/ClientRequest.js.map +1 -0
  18. package/Http/ClientResponse.d.ts +36 -0
  19. package/Http/ClientResponse.d.ts.map +1 -0
  20. package/Http/ClientResponse.js +29 -0
  21. package/Http/ClientResponse.js.map +1 -0
  22. package/Http/FormData.d.ts +56 -0
  23. package/Http/FormData.d.ts.map +1 -0
  24. package/Http/FormData.js +13 -0
  25. package/Http/FormData.js.map +1 -0
  26. package/Http/Headers.d.ts +38 -0
  27. package/Http/Headers.d.ts.map +1 -0
  28. package/Http/Headers.js +54 -0
  29. package/Http/Headers.js.map +1 -0
  30. package/Http/IncomingMessage.d.ts +37 -0
  31. package/Http/IncomingMessage.d.ts.map +1 -0
  32. package/Http/IncomingMessage.js +30 -0
  33. package/Http/IncomingMessage.js.map +1 -0
  34. package/Http/Method.d.ts +10 -0
  35. package/Http/Method.d.ts.map +1 -0
  36. package/Http/Method.js +12 -0
  37. package/Http/Method.js.map +1 -0
  38. package/Http/UrlParams.d.ts +56 -0
  39. package/Http/UrlParams.d.ts.map +1 -0
  40. package/Http/UrlParams.js +74 -0
  41. package/Http/UrlParams.js.map +1 -0
  42. package/HttpClient.d.ts +32 -0
  43. package/HttpClient.d.ts.map +1 -0
  44. package/HttpClient.js +23 -0
  45. package/HttpClient.js.map +1 -0
  46. package/README.md +3 -0
  47. package/internal/console.js.map +1 -1
  48. package/internal/effectify.js.map +1 -1
  49. package/internal/error.js.map +1 -1
  50. package/internal/http/body.d.ts +2 -0
  51. package/internal/http/body.d.ts.map +1 -0
  52. package/internal/http/body.js +101 -0
  53. package/internal/http/body.js.map +1 -0
  54. package/internal/http/client.d.ts +3 -0
  55. package/internal/http/client.d.ts.map +1 -0
  56. package/internal/http/client.js +147 -0
  57. package/internal/http/client.js.map +1 -0
  58. package/internal/http/clientError.d.ts +2 -0
  59. package/internal/http/clientError.d.ts.map +1 -0
  60. package/internal/http/clientError.js +24 -0
  61. package/internal/http/clientError.js.map +1 -0
  62. package/internal/http/clientRequest.d.ts +2 -0
  63. package/internal/http/clientRequest.d.ts.map +1 -0
  64. package/internal/http/clientRequest.js +180 -0
  65. package/internal/http/clientRequest.js.map +1 -0
  66. package/internal/http/clientResponse.d.ts +2 -0
  67. package/internal/http/clientResponse.d.ts.map +1 -0
  68. package/internal/http/clientResponse.js +101 -0
  69. package/internal/http/clientResponse.js.map +1 -0
  70. package/mjs/Http/Body.mjs +52 -0
  71. package/mjs/Http/Body.mjs.map +1 -0
  72. package/mjs/Http/Client.mjs +97 -0
  73. package/mjs/Http/Client.mjs.map +1 -0
  74. package/mjs/Http/ClientError.mjs +17 -0
  75. package/mjs/Http/ClientError.mjs.map +1 -0
  76. package/mjs/Http/ClientRequest.mjs +162 -0
  77. package/mjs/Http/ClientRequest.mjs.map +1 -0
  78. package/mjs/Http/ClientResponse.mjs +18 -0
  79. package/mjs/Http/ClientResponse.mjs.map +1 -0
  80. package/mjs/Http/FormData.mjs +6 -0
  81. package/mjs/Http/FormData.mjs.map +1 -0
  82. package/mjs/Http/Headers.mjs +40 -0
  83. package/mjs/Http/Headers.mjs.map +1 -0
  84. package/mjs/Http/IncomingMessage.mjs +19 -0
  85. package/mjs/Http/IncomingMessage.mjs.map +1 -0
  86. package/mjs/Http/Method.mjs +5 -0
  87. package/mjs/Http/Method.mjs.map +1 -0
  88. package/mjs/Http/UrlParams.mjs +57 -0
  89. package/mjs/Http/UrlParams.mjs.map +1 -0
  90. package/mjs/HttpClient.mjs +18 -0
  91. package/mjs/HttpClient.mjs.map +1 -0
  92. package/mjs/internal/console.mjs.map +1 -1
  93. package/mjs/internal/effectify.mjs.map +1 -1
  94. package/mjs/internal/error.mjs.map +1 -1
  95. package/mjs/internal/http/body.mjs +83 -0
  96. package/mjs/internal/http/body.mjs.map +1 -0
  97. package/mjs/internal/http/client.mjs +120 -0
  98. package/mjs/internal/http/client.mjs.map +1 -0
  99. package/mjs/internal/http/clientError.mjs +13 -0
  100. package/mjs/internal/http/clientError.mjs.map +1 -0
  101. package/mjs/internal/http/clientRequest.mjs +138 -0
  102. package/mjs/internal/http/clientRequest.mjs.map +1 -0
  103. package/mjs/internal/http/clientResponse.mjs +91 -0
  104. package/mjs/internal/http/clientResponse.mjs.map +1 -0
  105. package/package.json +13 -8
  106. package/src/Effectify.ts +65 -65
  107. package/src/Http/Body.ts +148 -0
  108. package/src/Http/Client.ts +280 -0
  109. package/src/Http/ClientError.ts +80 -0
  110. package/src/Http/ClientRequest.ts +383 -0
  111. package/src/Http/ClientResponse.ts +42 -0
  112. package/src/Http/FormData.ts +61 -0
  113. package/src/Http/Headers.ts +69 -0
  114. package/src/Http/IncomingMessage.ts +45 -0
  115. package/src/Http/Method.ts +17 -0
  116. package/src/Http/UrlParams.ts +106 -0
  117. package/src/HttpClient.ts +32 -0
  118. package/src/internal/console.ts +6 -6
  119. package/src/internal/effectify.ts +14 -14
  120. package/src/internal/error.ts +2 -2
  121. package/src/internal/http/body.ts +113 -0
  122. package/src/internal/http/client.ts +437 -0
  123. package/src/internal/http/clientError.ts +20 -0
  124. package/src/internal/http/clientRequest.ts +390 -0
  125. package/src/internal/http/clientResponse.ts +114 -0
@@ -0,0 +1,437 @@
1
+ import * as Chunk from "@effect/data/Chunk"
2
+ import * as Context from "@effect/data/Context"
3
+ import { dual } from "@effect/data/Function"
4
+ import type * as Predicate from "@effect/data/Predicate"
5
+ import * as Effect from "@effect/io/Effect"
6
+ import * as Layer from "@effect/io/Layer"
7
+ import type * as Schedule from "@effect/io/Schedule"
8
+ import type * as Body from "@effect/platform/Http/Body"
9
+ import type * as Client from "@effect/platform/Http/Client"
10
+ import type * as Error from "@effect/platform/Http/ClientError"
11
+ import type * as ClientRequest from "@effect/platform/Http/ClientRequest"
12
+ import * as Method from "@effect/platform/Http/Method"
13
+ import * as internalBody from "@effect/platform/internal/http/body"
14
+ import * as internalError from "@effect/platform/internal/http/clientError"
15
+ import * as internalRequest from "@effect/platform/internal/http/clientRequest"
16
+ import * as internalResponse from "@effect/platform/internal/http/clientResponse"
17
+ import type * as ParseResult from "@effect/schema/ParseResult"
18
+ import * as Schema from "@effect/schema/Schema"
19
+ import * as Stream from "@effect/stream/Stream"
20
+
21
+ /** @internal */
22
+ export const tag = Context.Tag<Client.Client.Default>("@effect/platform/Http/Client")
23
+
24
+ const baseUrl = (): string | undefined => {
25
+ if ("location" in globalThis) {
26
+ return location.origin + location.pathname
27
+ }
28
+ return undefined
29
+ }
30
+
31
+ /** @internal */
32
+ export const fetch = (
33
+ options: RequestInit = {}
34
+ ): Client.Client.Default =>
35
+ (request) =>
36
+ Effect.flatMap(
37
+ Effect.try({
38
+ try: () => new URL(request.url, baseUrl()),
39
+ catch: (_) =>
40
+ internalError.requestError({
41
+ request,
42
+ reason: "Encode",
43
+ error: _
44
+ })
45
+ }),
46
+ (url) =>
47
+ Effect.suspend(() => {
48
+ Chunk.forEach(request.urlParams, ([key, value]) => {
49
+ if (value === undefined) return
50
+ url.searchParams.append(key, value)
51
+ })
52
+
53
+ const headers = new Headers([...request.headers] as any)
54
+ const send = (body: BodyInit | undefined) =>
55
+ Effect.map(
56
+ Effect.tryPromise({
57
+ try: (signal) =>
58
+ globalThis.fetch(url, {
59
+ ...options,
60
+ method: request.method,
61
+ headers,
62
+ body,
63
+ signal
64
+ }),
65
+ catch: (_) =>
66
+ internalError.requestError({
67
+ request,
68
+ reason: "Transport",
69
+ error: _
70
+ })
71
+ }),
72
+ (_) => internalResponse.fromWeb(request, _)
73
+ )
74
+ if (Method.hasBody(request.method)) {
75
+ return request.body._tag === "BytesEffect" ?
76
+ Effect.flatMap(
77
+ Effect.mapError(request.body.body, (error) =>
78
+ internalError.requestError({
79
+ reason: "Encode",
80
+ request,
81
+ error
82
+ })),
83
+ (body) => send(body)
84
+ ) :
85
+ send(convertBody(request.body))
86
+ }
87
+ return send(undefined)
88
+ })
89
+ )
90
+
91
+ const convertBody = (body: Exclude<Body.Body, Body.BytesEffect>): BodyInit | undefined => {
92
+ switch (body._tag) {
93
+ case "Empty":
94
+ return undefined
95
+ case "Raw":
96
+ return body.body as any
97
+ case "Bytes":
98
+ return body.body
99
+ case "FormData":
100
+ return body.formData
101
+ case "Stream":
102
+ return Stream.toReadableStream(body.stream)
103
+ }
104
+ }
105
+
106
+ export const fetchOk = (
107
+ options: RequestInit = {}
108
+ ): Client.Client.Default => filterStatusOk(fetch(options))
109
+
110
+ /** @internal */
111
+ export const fetchLayer = Layer.succeed(tag, fetch())
112
+
113
+ /** @internal */
114
+ export const catchTag: {
115
+ <E extends { _tag: string }, K extends E["_tag"] & string, R1, E1, A1>(
116
+ tag: K,
117
+ f: (e: Extract<E, { _tag: K }>) => Effect.Effect<R1, E1, A1>
118
+ ): <R, A>(
119
+ self: Client.Client<R, E, A>
120
+ ) => Client.Client<R1 | R, E1 | Exclude<E, { _tag: K }>, A1 | A>
121
+ <R, E extends { _tag: string }, A, K extends E["_tag"] & string, E1, R1, A1>(
122
+ self: Client.Client<R, E, A>,
123
+ tag: K,
124
+ f: (e: Extract<E, { _tag: K }>) => Effect.Effect<R1, E1, A1>
125
+ ): Client.Client<R1 | R, E1 | Exclude<E, { _tag: K }>, A1 | A>
126
+ } = dual(
127
+ 3,
128
+ <R, E extends { _tag: string }, A, K extends E["_tag"] & string, E1, R1, A1>(
129
+ self: Client.Client<R, E, A>,
130
+ tag: K,
131
+ f: (e: Extract<E, { _tag: K }>) => Effect.Effect<R1, E1, A1>
132
+ ): Client.Client<R1 | R, E1 | Exclude<E, { _tag: K }>, A1 | A> =>
133
+ (request) => Effect.catchTag(self(request), tag, f)
134
+ )
135
+
136
+ /** @internal */
137
+ export const catchTags: {
138
+ <
139
+ E extends { _tag: string },
140
+ Cases extends {
141
+ [K in E["_tag"]]+?:
142
+ | ((error: Extract<E, { _tag: K }>) => Effect.Effect<any, any, any>)
143
+ | undefined
144
+ }
145
+ >(
146
+ cases: Cases
147
+ ): <R, A>(
148
+ self: Client.Client<R, E, A>
149
+ ) => Client.Client<
150
+ | R
151
+ | {
152
+ [K in keyof Cases]: Cases[K] extends (
153
+ ...args: Array<any>
154
+ ) => Effect.Effect<infer R, any, any> ? R
155
+ : never
156
+ }[keyof Cases],
157
+ | Exclude<E, { _tag: keyof Cases }>
158
+ | {
159
+ [K in keyof Cases]: Cases[K] extends (
160
+ ...args: Array<any>
161
+ ) => Effect.Effect<any, infer E, any> ? E
162
+ : never
163
+ }[keyof Cases],
164
+ | A
165
+ | {
166
+ [K in keyof Cases]: Cases[K] extends (
167
+ ...args: Array<any>
168
+ ) => Effect.Effect<any, any, infer A> ? A
169
+ : never
170
+ }[keyof Cases]
171
+ >
172
+ <
173
+ R,
174
+ E extends { _tag: string },
175
+ A,
176
+ Cases extends {
177
+ [K in E["_tag"]]+?:
178
+ | ((error: Extract<E, { _tag: K }>) => Effect.Effect<any, any, any>)
179
+ | undefined
180
+ }
181
+ >(
182
+ self: Client.Client<R, E, A>,
183
+ cases: Cases
184
+ ): Client.Client<
185
+ | R
186
+ | {
187
+ [K in keyof Cases]: Cases[K] extends (
188
+ ...args: Array<any>
189
+ ) => Effect.Effect<infer R, any, any> ? R
190
+ : never
191
+ }[keyof Cases],
192
+ | Exclude<E, { _tag: keyof Cases }>
193
+ | {
194
+ [K in keyof Cases]: Cases[K] extends (
195
+ ...args: Array<any>
196
+ ) => Effect.Effect<any, infer E, any> ? E
197
+ : never
198
+ }[keyof Cases],
199
+ | A
200
+ | {
201
+ [K in keyof Cases]: Cases[K] extends (
202
+ ...args: Array<any>
203
+ ) => Effect.Effect<any, any, infer A> ? A
204
+ : never
205
+ }[keyof Cases]
206
+ >
207
+ } = dual(
208
+ 2,
209
+ <
210
+ R,
211
+ E extends { _tag: string },
212
+ A,
213
+ Cases extends {
214
+ [K in E["_tag"]]+?:
215
+ | ((error: Extract<E, { _tag: K }>) => Effect.Effect<any, any, any>)
216
+ | undefined
217
+ }
218
+ >(
219
+ self: Client.Client<R, E, A>,
220
+ cases: Cases
221
+ ): Client.Client<
222
+ | R
223
+ | {
224
+ [K in keyof Cases]: Cases[K] extends (
225
+ ...args: Array<any>
226
+ ) => Effect.Effect<infer R, any, any> ? R
227
+ : never
228
+ }[keyof Cases],
229
+ | Exclude<E, { _tag: keyof Cases }>
230
+ | {
231
+ [K in keyof Cases]: Cases[K] extends (
232
+ ...args: Array<any>
233
+ ) => Effect.Effect<any, infer E, any> ? E
234
+ : never
235
+ }[keyof Cases],
236
+ | A
237
+ | {
238
+ [K in keyof Cases]: Cases[K] extends (
239
+ ...args: Array<any>
240
+ ) => Effect.Effect<any, any, infer A> ? A
241
+ : never
242
+ }[keyof Cases]
243
+ > =>
244
+ (request) => Effect.catchTags(self(request), cases)
245
+ )
246
+
247
+ /** @internal */
248
+ export const catchAll: {
249
+ <E, R2, E2, A2>(f: (e: E) => Effect.Effect<R2, E2, A2>): <R, A>(
250
+ self: Client.Client<R, E, A>
251
+ ) => Client.Client<R | R2, E2, A2 | A>
252
+ <R, E, A, R2, E2, A2>(
253
+ self: Client.Client<R, E, A>,
254
+ f: (e: E) => Effect.Effect<R2, E2, A2>
255
+ ): Client.Client<R | R2, E2, A2 | A>
256
+ } = dual(
257
+ 2,
258
+ <R, E, A, R2, E2, A2>(
259
+ self: Client.Client<R, E, A>,
260
+ f: (e: E) => Effect.Effect<R2, E2, A2>
261
+ ): Client.Client<R | R2, E2, A2 | A> =>
262
+ (request) => Effect.catchAll(self(request), f)
263
+ )
264
+
265
+ /** @internal */
266
+ export const filterOrElse = dual<
267
+ <A, R2, E2, B>(f: Predicate.Predicate<A>, orElse: (a: A) => Effect.Effect<R2, E2, B>) => <R, E>(
268
+ self: Client.Client<R, E, A>
269
+ ) => Client.Client<R2 | R, E2 | E, A | B>,
270
+ <R, E, A, R2, E2, B>(
271
+ self: Client.Client<R, E, A>,
272
+ f: Predicate.Predicate<A>,
273
+ orElse: (a: A) => Effect.Effect<R2, E2, B>
274
+ ) => Client.Client<R2 | R, E2 | E, A | B>
275
+ >(3, (self, f, orElse) => (request) => Effect.filterOrElse(self(request), f, orElse))
276
+
277
+ /** @internal */
278
+ export const filterOrFail = dual<
279
+ <A, E2>(f: Predicate.Predicate<A>, orFailWith: (a: A) => E2) => <R, E>(
280
+ self: Client.Client<R, E, A>
281
+ ) => Client.Client<R, E2 | E, A>,
282
+ <R, E, A, E2>(
283
+ self: Client.Client<R, E, A>,
284
+ f: Predicate.Predicate<A>,
285
+ orFailWith: (a: A) => E2
286
+ ) => Client.Client<R, E2 | E, A>
287
+ >(3, (self, f, orFailWith) => (request) => Effect.filterOrFail(self(request), f, orFailWith))
288
+
289
+ /** @internal */
290
+ export const filterStatus = dual<
291
+ (f: (status: number) => boolean) => <R, E>(
292
+ self: Client.Client.WithResponse<R, E>
293
+ ) => Client.Client.WithResponse<R, E | Error.ResponseError>,
294
+ <R, E>(
295
+ self: Client.Client.WithResponse<R, E>,
296
+ f: (status: number) => boolean
297
+ ) => Client.Client.WithResponse<R, E | Error.ResponseError>
298
+ >(
299
+ 2,
300
+ (self, f) => (request) =>
301
+ Effect.filterOrFail(
302
+ self(request),
303
+ (response) => f(response.status),
304
+ (response) =>
305
+ internalError.responseError({
306
+ request,
307
+ response,
308
+ reason: "StatusCode",
309
+ error: "non 2xx status code"
310
+ })
311
+ )
312
+ )
313
+
314
+ /** @internal */
315
+ export const filterStatusOk: <R, E>(
316
+ self: Client.Client.WithResponse<R, E>
317
+ ) => Client.Client.WithResponse<R, E | Error.ResponseError> = filterStatus((status) => status >= 200 && status < 300)
318
+
319
+ /** @internal */
320
+ export const map = dual<
321
+ <A, B>(f: (a: A) => B) => <R, E>(
322
+ self: Client.Client<R, E, A>
323
+ ) => Client.Client<R, E, B>,
324
+ <R, E, A, B>(
325
+ self: Client.Client<R, E, A>,
326
+ f: (a: A) => B
327
+ ) => Client.Client<R, E, B>
328
+ >(2, (self, f) => (request) => Effect.map(self(request), f))
329
+
330
+ /** @internal */
331
+ export const mapEffect = dual<
332
+ <A, R2, E2, B>(f: (a: A) => Effect.Effect<R2, E2, B>) => <R, E>(
333
+ self: Client.Client<R, E, A>
334
+ ) => Client.Client<R | R2, E | E2, B>,
335
+ <R, E, A, R2, E2, B>(
336
+ self: Client.Client<R, E, A>,
337
+ f: (a: A) => Effect.Effect<R2, E2, B>
338
+ ) => Client.Client<R | R2, E | E2, B>
339
+ >(2, (self, f) => (request) => Effect.flatMap(self(request), f))
340
+
341
+ /** @internal */
342
+ export const mapRequest = dual<
343
+ (f: (a: ClientRequest.ClientRequest) => ClientRequest.ClientRequest) => <R, E, A>(
344
+ self: Client.Client<R, E, A>
345
+ ) => Client.Client<R, E, A>,
346
+ <R, E, A>(
347
+ self: Client.Client<R, E, A>,
348
+ f: (a: ClientRequest.ClientRequest) => ClientRequest.ClientRequest
349
+ ) => Client.Client<R, E, A>
350
+ >(2, (self, f) => (request) => self(f(request)))
351
+
352
+ /** @internal */
353
+ export const mapRequestEffect = dual<
354
+ <R2, E2>(f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, ClientRequest.ClientRequest>) => <R, E, A>(
355
+ self: Client.Client<R, E, A>
356
+ ) => Client.Client<R | R2, E | E2, A>,
357
+ <R, E, A, R2, E2>(
358
+ self: Client.Client<R, E, A>,
359
+ f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, ClientRequest.ClientRequest>
360
+ ) => Client.Client<R | R2, E | E2, A>
361
+ >(2, (self, f) => (request) => Effect.flatMap(f(request), self))
362
+
363
+ /** @internal */
364
+ export const retry: {
365
+ <R1, E extends E0, E0, B>(policy: Schedule.Schedule<R1, E0, B>): <R, A>(
366
+ self: Client.Client<R, E, A>
367
+ ) => Client.Client<R1 | R, E, A>
368
+ <R, E extends E0, E0, A, R1, B>(
369
+ self: Client.Client<R, E, A>,
370
+ policy: Schedule.Schedule<R1, E0, B>
371
+ ): Client.Client<R | R1, E, A>
372
+ } = dual(
373
+ 2,
374
+ <R, E extends E0, E0, A, R1, B>(
375
+ self: Client.Client<R, E, A>,
376
+ policy: Schedule.Schedule<R1, E0, B>
377
+ ): Client.Client<R | R1, E, A> =>
378
+ (request) => Effect.retry(self(request), policy)
379
+ )
380
+
381
+ /** @internal */
382
+ export const schemaFunction = dual<
383
+ <SI, SA>(
384
+ schema: Schema.Schema<SI, SA>
385
+ ) => <R, E, A>(
386
+ self: Client.Client<R, E, A>
387
+ ) => (
388
+ request: ClientRequest.ClientRequest
389
+ ) => (a: SA) => Effect.Effect<R, E | ParseResult.ParseError | Error.RequestError, A>,
390
+ <R, E, A, SI, SA>(
391
+ self: Client.Client<R, E, A>,
392
+ schema: Schema.Schema<SI, SA>
393
+ ) => (
394
+ request: ClientRequest.ClientRequest
395
+ ) => (a: SA) => Effect.Effect<R, E | ParseResult.ParseError | Error.RequestError, A>
396
+ >(2, (self, schema) => {
397
+ const encode = Schema.encode(schema)
398
+ return (request) => (a) =>
399
+ Effect.flatMap(
400
+ Effect.tryMap(encode(a), {
401
+ try: (body) => new TextEncoder().encode(JSON.stringify(body)),
402
+ catch: (error) =>
403
+ internalError.requestError({
404
+ request,
405
+ reason: "Encode",
406
+ error
407
+ })
408
+ }),
409
+ (body) =>
410
+ self(internalRequest.setBody(
411
+ request,
412
+ internalBody.bytes(body, "application/json")
413
+ ))
414
+ )
415
+ })
416
+
417
+ /** @internal */
418
+ export const tap = dual<
419
+ <A, R2, E2, _>(f: (a: A) => Effect.Effect<R2, E2, _>) => <R, E>(
420
+ self: Client.Client<R, E, A>
421
+ ) => Client.Client<R | R2, E | E2, A>,
422
+ <R, E, A, R2, E2, _>(
423
+ self: Client.Client<R, E, A>,
424
+ f: (a: A) => Effect.Effect<R2, E2, _>
425
+ ) => Client.Client<R | R2, E | E2, A>
426
+ >(2, (self, f) => (request) => Effect.tap(self(request), f))
427
+
428
+ /** @internal */
429
+ export const tapRequest = dual<
430
+ <R2, E2, _>(f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, _>) => <R, E, A>(
431
+ self: Client.Client<R, E, A>
432
+ ) => Client.Client<R | R2, E | E2, A>,
433
+ <R, E, A, R2, E2, _>(
434
+ self: Client.Client<R, E, A>,
435
+ f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, _>
436
+ ) => Client.Client<R | R2, E | E2, A>
437
+ >(2, (self, f) => (request) => Effect.zipRight(f(request), self(request)))
@@ -0,0 +1,20 @@
1
+ import * as Data from "@effect/data/Data"
2
+ import type * as Error from "@effect/platform/Http/ClientError"
3
+
4
+ /** @internal */
5
+ export const TypeId: Error.TypeId = Symbol.for(
6
+ "@effect/platform/Http/Error"
7
+ ) as Error.TypeId
8
+
9
+ const make = <A extends Error.HttpClientError>(tag: A["_tag"]) => (props: Omit<A, Error.HttpError.ProvidedFields>): A =>
10
+ Data.struct({
11
+ [TypeId]: TypeId,
12
+ _tag: tag,
13
+ ...props
14
+ } as A)
15
+
16
+ /** @internal */
17
+ export const requestError = make<Error.RequestError>("RequestError")
18
+
19
+ /** @internal */
20
+ export const responseError = make<Error.ResponseError>("ResponseError")