@effect/platform 0.64.1 → 0.65.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/FetchHttpClient/package.json +6 -0
- package/README.md +173 -195
- package/dist/cjs/FetchHttpClient.js +32 -0
- package/dist/cjs/FetchHttpClient.js.map +1 -0
- package/dist/cjs/HttpApiClient.js +1 -1
- package/dist/cjs/HttpApiClient.js.map +1 -1
- package/dist/cjs/HttpClient.js +5 -36
- package/dist/cjs/HttpClient.js.map +1 -1
- package/dist/cjs/HttpClientRequest.js +11 -11
- package/dist/cjs/HttpClientRequest.js.map +1 -1
- package/dist/cjs/HttpClientResponse.js +2 -61
- package/dist/cjs/HttpClientResponse.js.map +1 -1
- package/dist/cjs/HttpIncomingMessage.js +2 -29
- package/dist/cjs/HttpIncomingMessage.js.map +1 -1
- package/dist/cjs/Runtime.js +1 -1
- package/dist/cjs/Runtime.js.map +1 -1
- package/dist/cjs/Socket.js +42 -53
- package/dist/cjs/Socket.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/internal/fetchHttpClient.js +52 -0
- package/dist/cjs/internal/fetchHttpClient.js.map +1 -0
- package/dist/cjs/internal/httpClient.js +82 -71
- package/dist/cjs/internal/httpClient.js.map +1 -1
- package/dist/cjs/internal/httpClientRequest.js +13 -13
- package/dist/cjs/internal/httpClientRequest.js.map +1 -1
- package/dist/cjs/internal/httpClientResponse.js +1 -33
- package/dist/cjs/internal/httpClientResponse.js.map +1 -1
- package/dist/cjs/internal/worker.js +21 -29
- package/dist/cjs/internal/worker.js.map +1 -1
- package/dist/dts/FetchHttpClient.d.ts +27 -0
- package/dist/dts/FetchHttpClient.d.ts.map +1 -0
- package/dist/dts/HttpApiClient.d.ts +2 -2
- package/dist/dts/HttpClient.d.ts +53 -61
- package/dist/dts/HttpClient.d.ts.map +1 -1
- package/dist/dts/HttpClientRequest.d.ts +11 -11
- package/dist/dts/HttpClientRequest.d.ts.map +1 -1
- package/dist/dts/HttpClientResponse.d.ts +4 -90
- package/dist/dts/HttpClientResponse.d.ts.map +1 -1
- package/dist/dts/HttpIncomingMessage.d.ts +0 -16
- package/dist/dts/HttpIncomingMessage.d.ts.map +1 -1
- package/dist/dts/HttpServer.d.ts +1 -1
- package/dist/dts/Socket.d.ts +3 -3
- package/dist/dts/Socket.d.ts.map +1 -1
- package/dist/dts/index.d.ts +4 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/fetchHttpClient.d.ts +2 -0
- package/dist/dts/internal/fetchHttpClient.d.ts.map +1 -0
- package/dist/esm/FetchHttpClient.js +21 -0
- package/dist/esm/FetchHttpClient.js.map +1 -0
- package/dist/esm/HttpApiClient.js +1 -1
- package/dist/esm/HttpApiClient.js.map +1 -1
- package/dist/esm/HttpClient.js +4 -35
- package/dist/esm/HttpClient.js.map +1 -1
- package/dist/esm/HttpClientRequest.js +10 -10
- package/dist/esm/HttpClientRequest.js.map +1 -1
- package/dist/esm/HttpClientResponse.js +1 -63
- package/dist/esm/HttpClientResponse.js.map +1 -1
- package/dist/esm/HttpIncomingMessage.js +0 -24
- package/dist/esm/HttpIncomingMessage.js.map +1 -1
- package/dist/esm/Runtime.js +1 -1
- package/dist/esm/Runtime.js.map +1 -1
- package/dist/esm/Socket.js +42 -53
- package/dist/esm/Socket.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/fetchHttpClient.js +44 -0
- package/dist/esm/internal/fetchHttpClient.js.map +1 -0
- package/dist/esm/internal/httpClient.js +79 -69
- package/dist/esm/internal/httpClient.js.map +1 -1
- package/dist/esm/internal/httpClientRequest.js +11 -11
- package/dist/esm/internal/httpClientRequest.js.map +1 -1
- package/dist/esm/internal/httpClientResponse.js +0 -24
- package/dist/esm/internal/httpClientResponse.js.map +1 -1
- package/dist/esm/internal/worker.js +21 -29
- package/dist/esm/internal/worker.js.map +1 -1
- package/package.json +11 -3
- package/src/FetchHttpClient.ts +25 -0
- package/src/HttpApiClient.ts +5 -5
- package/src/HttpClient.ts +79 -85
- package/src/HttpClientRequest.ts +21 -21
- package/src/HttpClientResponse.ts +4 -162
- package/src/HttpIncomingMessage.ts +0 -43
- package/src/HttpServer.ts +1 -1
- package/src/Runtime.ts +1 -1
- package/src/Socket.ts +42 -58
- package/src/index.ts +5 -0
- package/src/internal/fetchHttpClient.ts +53 -0
- package/src/internal/httpClient.ts +149 -125
- package/src/internal/httpClientRequest.ts +12 -12
- package/src/internal/httpClientResponse.ts +6 -96
- package/src/internal/worker.ts +40 -55
package/README.md
CHANGED
|
@@ -564,42 +564,46 @@ Effect.gen(function* () {
|
|
|
564
564
|
|
|
565
565
|
## Overview
|
|
566
566
|
|
|
567
|
-
|
|
567
|
+
The `@effect/platform/HttpClient*` modules provide a way to send HTTP requests,
|
|
568
|
+
handle responses, and abstract over the differences between platforms.
|
|
568
569
|
|
|
569
|
-
|
|
570
|
-
type HttpClient<A, E, R> = (request: HttpClientRequest): Effect<A, E, R>
|
|
571
|
-
```
|
|
570
|
+
The `HttpClient` interface has a set of methods for sending requests:
|
|
572
571
|
|
|
573
|
-
|
|
572
|
+
- `.execute` - takes a `HttpClientRequest` and returns a `HttpClientResponse`
|
|
573
|
+
- `.{get, post, ...}` - convenience methods for creating a request and
|
|
574
|
+
executing it in one step
|
|
574
575
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
The goal of `Default` is straightforward: transform a `HttpClientRequest` into a `HttpClientResponse`.
|
|
576
|
+
To access the `HttpClient`, you can use the `HttpClient.HttpClient` `Context.Tag`.
|
|
577
|
+
This will give you access to a `HttpClient.Service` instance, which is the default
|
|
578
|
+
type of the `HttpClient` interface.
|
|
580
579
|
|
|
581
580
|
### A First Example: Retrieving JSON Data (GET)
|
|
582
581
|
|
|
583
582
|
Here's a simple example demonstrating how to retrieve JSON data using `HttpClient` from `@effect/platform`.
|
|
584
583
|
|
|
585
584
|
```ts
|
|
586
|
-
import {
|
|
587
|
-
HttpClient,
|
|
588
|
-
HttpClientRequest,
|
|
589
|
-
HttpClientResponse
|
|
590
|
-
} from "@effect/platform"
|
|
585
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
591
586
|
import { Effect } from "effect"
|
|
592
587
|
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
588
|
+
const program = Effect.gen(function* () {
|
|
589
|
+
// access the HttpClient
|
|
590
|
+
const client = yield* HttpClient.HttpClient
|
|
596
591
|
|
|
597
|
-
|
|
598
|
-
|
|
592
|
+
const response = yield* client.get(
|
|
593
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
594
|
+
)
|
|
599
595
|
|
|
600
|
-
const json =
|
|
596
|
+
const json = yield* response.json
|
|
601
597
|
|
|
602
|
-
|
|
598
|
+
console.log(json)
|
|
599
|
+
}).pipe(
|
|
600
|
+
// ensure the request is aborted if the program is interrupted
|
|
601
|
+
Effect.scoped,
|
|
602
|
+
// provide the HttpClient
|
|
603
|
+
Effect.provide(FetchHttpClient.layer)
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
Effect.runPromise(program)
|
|
603
607
|
/*
|
|
604
608
|
Output:
|
|
605
609
|
{
|
|
@@ -614,29 +618,15 @@ Output:
|
|
|
614
618
|
*/
|
|
615
619
|
```
|
|
616
620
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
- `HttpClientRequest.get` creates a GET request to the specified URL.
|
|
620
|
-
- `HttpClient.fetch` executes the request.
|
|
621
|
-
- `HttpClientResponse.json` converts the response to JSON.
|
|
622
|
-
- `Effect.runPromise` runs the effect and logs the result.
|
|
623
|
-
|
|
624
|
-
### Built-in Defaults
|
|
621
|
+
### Custom `HttpClient.Service`'s
|
|
625
622
|
|
|
626
|
-
|
|
627
|
-
| -------------------- | ------------------------------------------------------------------------- |
|
|
628
|
-
| `HttpClient.fetch` | Execute the request using the global `fetch` function |
|
|
629
|
-
| `HttpClient.fetchOk` | Same as `fetch` but ensures only `2xx` responses are treated as successes |
|
|
630
|
-
|
|
631
|
-
### Custom Default
|
|
632
|
-
|
|
633
|
-
You can create your own `Default` using the `HttpClient.makeDefault` constructor.
|
|
623
|
+
You can create your own `HttpClient.Service` using the `HttpClient.makeService` constructor.
|
|
634
624
|
|
|
635
625
|
```ts
|
|
636
626
|
import { HttpClient, HttpClientResponse } from "@effect/platform"
|
|
637
627
|
import { Effect } from "effect"
|
|
638
628
|
|
|
639
|
-
const myClient = HttpClient.
|
|
629
|
+
const myClient = HttpClient.makeService((req) =>
|
|
640
630
|
Effect.succeed(
|
|
641
631
|
HttpClientResponse.fromWeb(
|
|
642
632
|
req,
|
|
@@ -657,27 +647,25 @@ const myClient = HttpClient.makeDefault((req) =>
|
|
|
657
647
|
## Tapping
|
|
658
648
|
|
|
659
649
|
```ts
|
|
660
|
-
import {
|
|
661
|
-
HttpClient,
|
|
662
|
-
HttpClientRequest,
|
|
663
|
-
HttpClientResponse
|
|
664
|
-
} from "@effect/platform"
|
|
650
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
665
651
|
import { Console, Effect } from "effect"
|
|
666
652
|
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
653
|
+
const program = Effect.gen(function* () {
|
|
654
|
+
const client = (yield* HttpClient.HttpClient).pipe(
|
|
655
|
+
// Log the request before fetching
|
|
656
|
+
HttpClient.tapRequest(Console.log)
|
|
657
|
+
)
|
|
670
658
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
)
|
|
659
|
+
const response = yield* client.get(
|
|
660
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
661
|
+
)
|
|
675
662
|
|
|
676
|
-
const
|
|
663
|
+
const json = yield* response.json
|
|
677
664
|
|
|
678
|
-
|
|
665
|
+
console.log(json)
|
|
666
|
+
}).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer))
|
|
679
667
|
|
|
680
|
-
Effect.runPromise(
|
|
668
|
+
Effect.runPromise(program)
|
|
681
669
|
/*
|
|
682
670
|
Output:
|
|
683
671
|
{
|
|
@@ -832,20 +820,21 @@ Output:
|
|
|
832
820
|
To convert a GET response to JSON:
|
|
833
821
|
|
|
834
822
|
```ts
|
|
835
|
-
import {
|
|
836
|
-
HttpClient,
|
|
837
|
-
HttpClientRequest,
|
|
838
|
-
HttpClientResponse
|
|
839
|
-
} from "@effect/platform"
|
|
823
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
840
824
|
import { NodeRuntime } from "@effect/platform-node"
|
|
841
825
|
import { Console, Effect } from "effect"
|
|
842
826
|
|
|
843
|
-
const getPostAsJson =
|
|
844
|
-
|
|
845
|
-
|
|
827
|
+
const getPostAsJson = Effect.gen(function* () {
|
|
828
|
+
const client = yield* HttpClient.HttpClient
|
|
829
|
+
const response = yield* client.get(
|
|
830
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
831
|
+
)
|
|
832
|
+
return yield* response.json
|
|
833
|
+
}).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer))
|
|
846
834
|
|
|
847
|
-
|
|
848
|
-
|
|
835
|
+
getPostAsJson.pipe(
|
|
836
|
+
Effect.andThen((post) => Console.log(typeof post, post)),
|
|
837
|
+
NodeRuntime.runMain
|
|
849
838
|
)
|
|
850
839
|
/*
|
|
851
840
|
Output:
|
|
@@ -866,20 +855,21 @@ object {
|
|
|
866
855
|
To convert a GET response to text:
|
|
867
856
|
|
|
868
857
|
```ts
|
|
869
|
-
import {
|
|
870
|
-
HttpClient,
|
|
871
|
-
HttpClientRequest,
|
|
872
|
-
HttpClientResponse
|
|
873
|
-
} from "@effect/platform"
|
|
858
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
874
859
|
import { NodeRuntime } from "@effect/platform-node"
|
|
875
860
|
import { Console, Effect } from "effect"
|
|
876
861
|
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
862
|
+
const getPostAsJson = Effect.gen(function* () {
|
|
863
|
+
const client = yield* HttpClient.HttpClient
|
|
864
|
+
const response = yield* client.get(
|
|
865
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
866
|
+
)
|
|
867
|
+
return yield* response.text
|
|
868
|
+
}).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer))
|
|
880
869
|
|
|
881
|
-
|
|
882
|
-
|
|
870
|
+
getPostAsJson.pipe(
|
|
871
|
+
Effect.andThen((post) => Console.log(typeof post, post)),
|
|
872
|
+
NodeRuntime.runMain
|
|
883
873
|
)
|
|
884
874
|
/*
|
|
885
875
|
Output:
|
|
@@ -899,14 +889,14 @@ string {
|
|
|
899
889
|
|
|
900
890
|
Here are some APIs you can use to convert the response:
|
|
901
891
|
|
|
902
|
-
| API
|
|
903
|
-
|
|
|
904
|
-
| `
|
|
905
|
-
| `
|
|
906
|
-
| `
|
|
907
|
-
| `
|
|
908
|
-
| `
|
|
909
|
-
| `
|
|
892
|
+
| API | Description |
|
|
893
|
+
| ------------------------ | ------------------------------------- |
|
|
894
|
+
| `response.arrayBuffer` | Convert to `ArrayBuffer` |
|
|
895
|
+
| `response.formData` | Convert to `FormData` |
|
|
896
|
+
| `response.json` | Convert to JSON |
|
|
897
|
+
| `response.stream` | Convert to a `Stream` of `Uint8Array` |
|
|
898
|
+
| `response.text` | Convert to text |
|
|
899
|
+
| `response.urlParamsBody` | Convert to `UrlParams` |
|
|
910
900
|
|
|
911
901
|
### Decoding Data with Schemas
|
|
912
902
|
|
|
@@ -914,8 +904,8 @@ A common use case when fetching data is to validate the received format. For thi
|
|
|
914
904
|
|
|
915
905
|
```ts
|
|
916
906
|
import {
|
|
907
|
+
FetchHttpClient,
|
|
917
908
|
HttpClient,
|
|
918
|
-
HttpClientRequest,
|
|
919
909
|
HttpClientResponse
|
|
920
910
|
} from "@effect/platform"
|
|
921
911
|
import { NodeRuntime } from "@effect/platform-node"
|
|
@@ -931,17 +921,17 @@ const Post = Schema.Struct({
|
|
|
931
921
|
const getPostAndValidate: Effect.Effect<{
|
|
932
922
|
readonly id: number;
|
|
933
923
|
readonly title: string;
|
|
934
|
-
},
|
|
924
|
+
}, HttpClientError | ParseError, never>
|
|
935
925
|
*/
|
|
936
|
-
const getPostAndValidate =
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
)
|
|
926
|
+
const getPostAndValidate = Effect.gen(function* () {
|
|
927
|
+
const client = yield* HttpClient.HttpClient
|
|
928
|
+
const response = yield* client.get(
|
|
929
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
930
|
+
)
|
|
931
|
+
return yield* HttpClientResponse.schemaBodyJson(Post)(response)
|
|
932
|
+
}).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer))
|
|
943
933
|
|
|
944
|
-
|
|
934
|
+
getPostAndValidate.pipe(Effect.andThen(Console.log), NodeRuntime.runMain)
|
|
945
935
|
/*
|
|
946
936
|
Output:
|
|
947
937
|
{
|
|
@@ -964,19 +954,19 @@ You can use `HttpClient.filterStatusOk`, or `HttpClient.fetchOk` to ensure only
|
|
|
964
954
|
In this example, we attempt to fetch a non-existent page and don't receive any error:
|
|
965
955
|
|
|
966
956
|
```ts
|
|
967
|
-
import {
|
|
968
|
-
HttpClient,
|
|
969
|
-
HttpClientRequest,
|
|
970
|
-
HttpClientResponse
|
|
971
|
-
} from "@effect/platform"
|
|
957
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
972
958
|
import { NodeRuntime } from "@effect/platform-node"
|
|
973
959
|
import { Console, Effect } from "effect"
|
|
974
960
|
|
|
975
|
-
const getText =
|
|
976
|
-
|
|
977
|
-
|
|
961
|
+
const getText = Effect.gen(function* () {
|
|
962
|
+
const client = yield* HttpClient.HttpClient
|
|
963
|
+
const response = yield* client.get(
|
|
964
|
+
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
965
|
+
)
|
|
966
|
+
return yield* response.text
|
|
967
|
+
}).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer))
|
|
978
968
|
|
|
979
|
-
|
|
969
|
+
getText.pipe(Effect.andThen(Console.log), NodeRuntime.runMain)
|
|
980
970
|
/*
|
|
981
971
|
Output:
|
|
982
972
|
{}
|
|
@@ -986,19 +976,19 @@ Output:
|
|
|
986
976
|
However, if we use `HttpClient.filterStatusOk`, an error is logged:
|
|
987
977
|
|
|
988
978
|
```ts
|
|
989
|
-
import {
|
|
990
|
-
HttpClient,
|
|
991
|
-
HttpClientRequest,
|
|
992
|
-
HttpClientResponse
|
|
993
|
-
} from "@effect/platform"
|
|
979
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
994
980
|
import { NodeRuntime } from "@effect/platform-node"
|
|
995
981
|
import { Console, Effect } from "effect"
|
|
996
982
|
|
|
997
|
-
const getText =
|
|
998
|
-
|
|
999
|
-
|
|
983
|
+
const getText = Effect.gen(function* () {
|
|
984
|
+
const client = (yield* HttpClient.HttpClient).pipe(HttpClient.filterStatusOk)
|
|
985
|
+
const response = yield* client.get(
|
|
986
|
+
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
987
|
+
)
|
|
988
|
+
return yield* response.text
|
|
989
|
+
}).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer))
|
|
1000
990
|
|
|
1001
|
-
|
|
991
|
+
getText.pipe(Effect.andThen(Console.log), NodeRuntime.runMain)
|
|
1002
992
|
/*
|
|
1003
993
|
Output:
|
|
1004
994
|
timestamp=... level=ERROR fiber=#0 cause="ResponseError: StatusCode error (404 GET https://jsonplaceholder.typicode.com/non-existing-page): non 2xx status code
|
|
@@ -1006,60 +996,36 @@ timestamp=... level=ERROR fiber=#0 cause="ResponseError: StatusCode error (404 G
|
|
|
1006
996
|
*/
|
|
1007
997
|
```
|
|
1008
998
|
|
|
1009
|
-
Note that you can use `HttpClient.fetchOk` as a shortcut for `HttpClient.filterStatusOk(HttpClient.fetch)`:
|
|
1010
|
-
|
|
1011
|
-
```ts
|
|
1012
|
-
const getText = HttpClientRequest.get(
|
|
1013
|
-
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
1014
|
-
).pipe(HttpClient.fetchOk, HttpClientResponse.text)
|
|
1015
|
-
```
|
|
1016
|
-
|
|
1017
|
-
You can also create your own status-based filters. In fact, `HttpClient.filterStatusOk` is just a shortcut for the following filter:
|
|
1018
|
-
|
|
1019
|
-
```ts
|
|
1020
|
-
const getText = HttpClientRequest.get(
|
|
1021
|
-
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
1022
|
-
).pipe(
|
|
1023
|
-
HttpClient.filterStatus(
|
|
1024
|
-
HttpClient.fetch,
|
|
1025
|
-
(status) => status >= 200 && status < 300
|
|
1026
|
-
),
|
|
1027
|
-
HttpClientResponse.text
|
|
1028
|
-
)
|
|
1029
|
-
|
|
1030
|
-
/*
|
|
1031
|
-
Output:
|
|
1032
|
-
timestamp=... level=ERROR fiber=#0 cause="ResponseError: StatusCode error (404 GET https://jsonplaceholder.typicode.com/non-existing-page): invalid status code
|
|
1033
|
-
... stack trace ...
|
|
1034
|
-
*/
|
|
1035
|
-
```
|
|
1036
|
-
|
|
1037
999
|
## POST
|
|
1038
1000
|
|
|
1039
|
-
To make a POST request, you can use the `HttpClientRequest.post` function provided by the `
|
|
1001
|
+
To make a POST request, you can use the `HttpClientRequest.post` function provided by the `HttpClientRequest` module. Here's an example of how to create and send a POST request:
|
|
1040
1002
|
|
|
1041
1003
|
```ts
|
|
1042
1004
|
import {
|
|
1005
|
+
FetchHttpClient,
|
|
1043
1006
|
HttpClient,
|
|
1044
|
-
HttpClientRequest
|
|
1045
|
-
HttpClientResponse
|
|
1007
|
+
HttpClientRequest
|
|
1046
1008
|
} from "@effect/platform"
|
|
1047
1009
|
import { NodeRuntime } from "@effect/platform-node"
|
|
1048
1010
|
import { Console, Effect } from "effect"
|
|
1049
1011
|
|
|
1050
|
-
const addPost =
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
)
|
|
1012
|
+
const addPost = Effect.gen(function* () {
|
|
1013
|
+
const client = yield* HttpClient.HttpClient
|
|
1014
|
+
return yield* HttpClientRequest.post(
|
|
1015
|
+
"https://jsonplaceholder.typicode.com/posts"
|
|
1016
|
+
).pipe(
|
|
1017
|
+
HttpClientRequest.bodyJson({
|
|
1018
|
+
title: "foo",
|
|
1019
|
+
body: "bar",
|
|
1020
|
+
userId: 1
|
|
1021
|
+
}),
|
|
1022
|
+
Effect.flatMap(client.execute),
|
|
1023
|
+
Effect.flatMap((res) => res.json),
|
|
1024
|
+
Effect.scoped
|
|
1025
|
+
)
|
|
1026
|
+
}).pipe(Effect.provide(FetchHttpClient.layer))
|
|
1061
1027
|
|
|
1062
|
-
|
|
1028
|
+
addPost.pipe(Effect.andThen(Console.log), NodeRuntime.runMain)
|
|
1063
1029
|
/*
|
|
1064
1030
|
Output:
|
|
1065
1031
|
{ title: 'foo', body: 'bar', userId: 1, id: 101 }
|
|
@@ -1072,29 +1038,33 @@ In the following example, we send the data as text:
|
|
|
1072
1038
|
|
|
1073
1039
|
```ts
|
|
1074
1040
|
import {
|
|
1041
|
+
FetchHttpClient,
|
|
1075
1042
|
HttpClient,
|
|
1076
|
-
HttpClientRequest
|
|
1077
|
-
HttpClientResponse
|
|
1043
|
+
HttpClientRequest
|
|
1078
1044
|
} from "@effect/platform"
|
|
1079
1045
|
import { NodeRuntime } from "@effect/platform-node"
|
|
1080
1046
|
import { Console, Effect } from "effect"
|
|
1081
1047
|
|
|
1082
|
-
const addPost =
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1048
|
+
const addPost = Effect.gen(function* () {
|
|
1049
|
+
const client = yield* HttpClient.HttpClient
|
|
1050
|
+
return yield* HttpClientRequest.post(
|
|
1051
|
+
"https://jsonplaceholder.typicode.com/posts"
|
|
1052
|
+
).pipe(
|
|
1053
|
+
HttpClientRequest.bodyText(
|
|
1054
|
+
JSON.stringify({
|
|
1055
|
+
title: "foo",
|
|
1056
|
+
body: "bar",
|
|
1057
|
+
userId: 1
|
|
1058
|
+
}),
|
|
1059
|
+
"application/json; charset=UTF-8"
|
|
1060
|
+
),
|
|
1061
|
+
client.execute,
|
|
1062
|
+
Effect.flatMap((res) => res.json),
|
|
1063
|
+
Effect.scoped
|
|
1064
|
+
)
|
|
1065
|
+
}).pipe(Effect.provide(FetchHttpClient.layer))
|
|
1096
1066
|
|
|
1097
|
-
|
|
1067
|
+
addPost.pipe(Effect.andThen(Console.log), NodeRuntime.runMain)
|
|
1098
1068
|
/*
|
|
1099
1069
|
Output:
|
|
1100
1070
|
{ title: 'foo', body: 'bar', userId: 1, id: 101 }
|
|
@@ -1107,6 +1077,7 @@ A common use case when fetching data is to validate the received format. For thi
|
|
|
1107
1077
|
|
|
1108
1078
|
```ts
|
|
1109
1079
|
import {
|
|
1080
|
+
FetchHttpClient,
|
|
1110
1081
|
HttpClient,
|
|
1111
1082
|
HttpClientRequest,
|
|
1112
1083
|
HttpClientResponse
|
|
@@ -1120,20 +1091,26 @@ const Post = Schema.Struct({
|
|
|
1120
1091
|
title: Schema.String
|
|
1121
1092
|
})
|
|
1122
1093
|
|
|
1123
|
-
const addPost =
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1094
|
+
const addPost = Effect.gen(function* () {
|
|
1095
|
+
const client = yield* HttpClient.HttpClient
|
|
1096
|
+
return yield* HttpClientRequest.post(
|
|
1097
|
+
"https://jsonplaceholder.typicode.com/posts"
|
|
1098
|
+
).pipe(
|
|
1099
|
+
HttpClientRequest.bodyText(
|
|
1100
|
+
JSON.stringify({
|
|
1101
|
+
title: "foo",
|
|
1102
|
+
body: "bar",
|
|
1103
|
+
userId: 1
|
|
1104
|
+
}),
|
|
1105
|
+
"application/json; charset=UTF-8"
|
|
1106
|
+
),
|
|
1107
|
+
client.execute,
|
|
1108
|
+
Effect.flatMap(HttpClientResponse.schemaBodyJson(Post)),
|
|
1109
|
+
Effect.scoped
|
|
1110
|
+
)
|
|
1111
|
+
}).pipe(Effect.provide(FetchHttpClient.layer))
|
|
1135
1112
|
|
|
1136
|
-
|
|
1113
|
+
addPost.pipe(Effect.andThen(Console.log), NodeRuntime.runMain)
|
|
1137
1114
|
/*
|
|
1138
1115
|
Output:
|
|
1139
1116
|
{ id: 101, title: 'foo' }
|
|
@@ -1147,30 +1124,31 @@ Output:
|
|
|
1147
1124
|
To test HTTP requests, you can inject a mock fetch implementation.
|
|
1148
1125
|
|
|
1149
1126
|
```ts
|
|
1150
|
-
import {
|
|
1151
|
-
HttpClient,
|
|
1152
|
-
HttpClientRequest,
|
|
1153
|
-
HttpClientResponse
|
|
1154
|
-
} from "@effect/platform"
|
|
1127
|
+
import { FetchHttpClient, HttpClient } from "@effect/platform"
|
|
1155
1128
|
import { Effect, Layer } from "effect"
|
|
1156
1129
|
import * as assert from "node:assert"
|
|
1157
1130
|
|
|
1158
1131
|
// Mock fetch implementation
|
|
1159
|
-
const FetchTest = Layer.succeed(
|
|
1132
|
+
const FetchTest = Layer.succeed(FetchHttpClient.Fetch, () =>
|
|
1160
1133
|
Promise.resolve(new Response("not found", { status: 404 }))
|
|
1161
1134
|
)
|
|
1162
1135
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1136
|
+
const TestLayer = FetchHttpClient.layer.pipe(Layer.provide(FetchTest))
|
|
1137
|
+
|
|
1138
|
+
const program = Effect.gen(function* () {
|
|
1139
|
+
const client = yield* HttpClient.HttpClient
|
|
1140
|
+
|
|
1141
|
+
return yield* client.get("https://www.google.com/").pipe(
|
|
1142
|
+
Effect.flatMap((res) => res.text),
|
|
1143
|
+
Effect.scoped
|
|
1144
|
+
)
|
|
1145
|
+
})
|
|
1168
1146
|
|
|
1169
1147
|
// Test
|
|
1170
1148
|
Effect.gen(function* () {
|
|
1171
1149
|
const response = yield* program
|
|
1172
1150
|
assert.equal(response, "not found")
|
|
1173
|
-
}).pipe(Effect.provide(
|
|
1151
|
+
}).pipe(Effect.provide(TestLayer), Effect.runPromise)
|
|
1174
1152
|
```
|
|
1175
1153
|
|
|
1176
1154
|
# HTTP Server
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.layer = exports.RequestInit = exports.Fetch = void 0;
|
|
7
|
+
var Context = _interopRequireWildcard(require("effect/Context"));
|
|
8
|
+
var internal = _interopRequireWildcard(require("./internal/fetchHttpClient.js"));
|
|
9
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
10
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
11
|
+
/**
|
|
12
|
+
* @since 1.0.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @since 1.0.0
|
|
17
|
+
* @category tags
|
|
18
|
+
*/
|
|
19
|
+
class Fetch extends /*#__PURE__*/Context.Tag(internal.fetchTagKey)() {}
|
|
20
|
+
/**
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
* @category tags
|
|
23
|
+
*/
|
|
24
|
+
exports.Fetch = Fetch;
|
|
25
|
+
class RequestInit extends /*#__PURE__*/Context.Tag(internal.requestInitTagKey)() {}
|
|
26
|
+
/**
|
|
27
|
+
* @since 1.0.0
|
|
28
|
+
* @category layers
|
|
29
|
+
*/
|
|
30
|
+
exports.RequestInit = RequestInit;
|
|
31
|
+
const layer = exports.layer = internal.layer;
|
|
32
|
+
//# sourceMappingURL=FetchHttpClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FetchHttpClient.js","names":["Context","_interopRequireWildcard","require","internal","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","Fetch","Tag","fetchTagKey","exports","RequestInit","requestInitTagKey","layer"],"sources":["../../src/FetchHttpClient.ts"],"sourcesContent":[null],"mappings":";;;;;;AAGA,IAAAA,OAAA,GAAAC,uBAAA,CAAAC,OAAA;AAGA,IAAAC,QAAA,GAAAF,uBAAA,CAAAC,OAAA;AAAyD,SAAAE,yBAAAC,CAAA,6BAAAC,OAAA,mBAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAJ,wBAAAI,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAI,UAAA,SAAAJ,CAAA,eAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,WAAAK,OAAA,EAAAL,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAG,GAAA,CAAAN,CAAA,UAAAG,CAAA,CAAAI,GAAA,CAAAP,CAAA,OAAAQ,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,CAAA,IAAAd,CAAA,oBAAAc,CAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAc,CAAA,SAAAG,CAAA,GAAAP,CAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAb,CAAA,EAAAc,CAAA,UAAAG,CAAA,KAAAA,CAAA,CAAAV,GAAA,IAAAU,CAAA,CAAAC,GAAA,IAAAP,MAAA,CAAAC,cAAA,CAAAJ,CAAA,EAAAM,CAAA,EAAAG,CAAA,IAAAT,CAAA,CAAAM,CAAA,IAAAd,CAAA,CAAAc,CAAA,YAAAN,CAAA,CAAAH,OAAA,GAAAL,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAe,GAAA,CAAAlB,CAAA,EAAAQ,CAAA,GAAAA,CAAA;AANzD;;;;AAQA;;;;AAIM,MAAOW,KAAM,sBAAQxB,OAAO,CAACyB,GAAG,CAACtB,QAAQ,CAACuB,WAAW,CAAC,EAAkC;AAE9F;;;;AAAAC,OAAA,CAAAH,KAAA,GAAAA,KAAA;AAIM,MAAOI,WAAY,sBAAQ5B,OAAO,CAACyB,GAAG,CAACtB,QAAQ,CAAC0B,iBAAiB,CAAC,EAAuC;AAE/G;;;;AAAAF,OAAA,CAAAC,WAAA,GAAAA,WAAA;AAIO,MAAME,KAAK,GAAAH,OAAA,CAAAG,KAAA,GAAoC3B,QAAQ,CAAC2B,KAAK","ignoreList":[]}
|
|
@@ -104,7 +104,7 @@ const make = (api, options) => Effect.gen(function* () {
|
|
|
104
104
|
client[group.identifier][endpoint.name] = request => {
|
|
105
105
|
const url = request && request.path ? makeUrl(request && request.path) : endpoint.path;
|
|
106
106
|
const baseRequest = HttpClientRequest.make(endpoint.method)(url);
|
|
107
|
-
return (isMultipart ? Effect.succeed(baseRequest.pipe(HttpClientRequest.
|
|
107
|
+
return (isMultipart ? Effect.succeed(baseRequest.pipe(HttpClientRequest.bodyFormData(request.payload))) : encodePayload._tag === "Some" ? encodePayload.value(request.payload).pipe(Effect.flatMap(payload => HttpMethod.hasBody(endpoint.method) ? HttpClientRequest.bodyJson(baseRequest, payload) : Effect.succeed(HttpClientRequest.setUrlParams(baseRequest, payload))), Effect.orDie) : Effect.succeed(baseRequest)).pipe(encodeHeaders._tag === "Some" ? Effect.flatMap(httpRequest => encodeHeaders.value(request.headers).pipe(Effect.orDie, Effect.map(headers => HttpClientRequest.setHeaders(httpRequest, headers)))) : _Function.identity, Effect.flatMap(request => Effect.flatMap(httpClient.execute(request), response => response.status !== successStatus ? handleError(request, response) : Effect.succeed(response))), successDecode._tag === "Some" ? Effect.flatMap(successDecode.value) : Effect.asVoid, Effect.scoped, Effect.catchIf(ParseResult.isParseError, Effect.die), Effect.mapInputContext(input => Context.merge(context, input)));
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpApiClient.js","names":["ParseResult","_interopRequireWildcard","require","Schema","Context","Effect","_Function","Option","HttpApi","HttpApiSchema","HttpClient","HttpClientError","HttpClientRequest","HttpClientResponse","HttpMethod","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","make","api","options","gen","context","httpClient","pipe","baseUrl","undefined","identity","mapRequest","prependUrl","transformClient","client","reflect","onGroup","group","identifier","onEndpoint","endpoint","errors","successAST","successEncoding","successStatus","makeUrl","compilePath","path","successDecode","map","ast","schema","kind","schemaBodyJson","schemaBodyUrlParams","response","arrayBuffer","buffer","Uint8Array","flatMap","decodeUnknown","text","handleError","request","error","status","die","ResponseError","reason","isNone","fail","decode","value","void","try","JSON","parse","catch","cause","json","mapError","isMultipart","payloadSchema","getMultipart","getOrElse","encodePayload","filter","encodeUnknown","encodeHeaders","headersSchema","name","url","baseRequest","method","succeed","
|
|
1
|
+
{"version":3,"file":"HttpApiClient.js","names":["ParseResult","_interopRequireWildcard","require","Schema","Context","Effect","_Function","Option","HttpApi","HttpApiSchema","HttpClient","HttpClientError","HttpClientRequest","HttpClientResponse","HttpMethod","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","make","api","options","gen","context","httpClient","pipe","baseUrl","undefined","identity","mapRequest","prependUrl","transformClient","client","reflect","onGroup","group","identifier","onEndpoint","endpoint","errors","successAST","successEncoding","successStatus","makeUrl","compilePath","path","successDecode","map","ast","schema","kind","schemaBodyJson","schemaBodyUrlParams","response","arrayBuffer","buffer","Uint8Array","flatMap","decodeUnknown","text","handleError","request","error","status","die","ResponseError","reason","isNone","fail","decode","value","void","try","JSON","parse","catch","cause","json","mapError","isMultipart","payloadSchema","getMultipart","getOrElse","encodePayload","filter","encodeUnknown","encodeHeaders","headersSchema","name","url","baseRequest","method","succeed","bodyFormData","payload","_tag","hasBody","bodyJson","setUrlParams","orDie","httpRequest","headers","setHeaders","execute","asVoid","scoped","catchIf","isParseError","mapInputContext","input","merge","exports","paramsRegex","segments","split","len","length","_","params"],"sources":["../../src/HttpApiClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|