@@ -63,9 +63,7 @@ Bootstrap a simple API specification.
63
63
64
64
``` typescript
65
65
import { Schema } from " @effect/schema" ;
66
- import { Effect , pipe } from " effect" ;
67
- import { Api , Client , RouterBuilder } from " effect-http" ;
68
- import { NodeServer } from " effect-http-node" ;
66
+ import { Api } from " effect-http" ;
69
67
70
68
const User = Schema .struct ({
71
69
name: Schema .string ,
@@ -84,6 +82,9 @@ const api = Api.api({ title: "Users API" }).pipe(
84
82
Create the app implementation.
85
83
86
84
``` typescript
85
+ import { Effect , pipe } from " effect" ;
86
+ import { RouterBuilder } from " effect-http" ;
87
+
87
88
const app = pipe (
88
89
RouterBuilder .make (api ),
89
90
RouterBuilder .handle (" getUser" , ({ query }) =>
@@ -96,21 +97,27 @@ const app = pipe(
96
97
Now, we can generate an object providing the HTTP client interface using ` Client.make ` .
97
98
98
99
``` typescript
100
+ import { Client } from " effect-http" ;
101
+
99
102
const client = Client .make (api , { baseUrl: " http://localhost:3000" });
100
103
```
101
104
102
105
Spawn the server on port 3000,
103
106
104
107
``` typescript
105
- app .pipe (NodeServer .listen ({ port: 3000 }), runMain );
108
+ import { NodeRuntime } from " @effect/platform-node"
109
+ import { NodeServer } from " effect-http-node" ;
110
+
111
+ app .pipe (NodeServer .listen ({ port: 3000 }), NodeRuntime .runMain );
106
112
```
107
113
108
114
and call it using the ` client ` .
109
115
110
116
``` ts
111
- const callServer = pipe (
117
+ const response = pipe (
112
118
client .getUser ({ query: { id: 12 } }),
113
119
Effect .flatMap ((user ) => Effect .log (` Got ${user .name }, nice! ` )),
120
+ Effect .scoped ,
114
121
);
115
122
```
116
123
@@ -193,7 +200,7 @@ a mapping from header names onto their schemas. The example below shows an API w
193
200
a single endpoint ` /hello ` which expects a header ` X-Client-Id ` to be present.
194
201
195
202
``` typescript
196
- import { runMain } from " @effect/platform-node/Runtime " ;
203
+ import { NodeRuntime } from " @effect/platform-node" ;
197
204
import { Schema } from " @effect/schema" ;
198
205
import { pipe } from " effect" ;
199
206
import { Api , ExampleServer , RouterBuilder } from " effect-http" ;
@@ -212,7 +219,7 @@ pipe(
212
219
ExampleServer .make (api ),
213
220
RouterBuilder .build ,
214
221
NodeServer .listen ({ port: 3000 }),
215
- runMain ,
222
+ NodeRuntime . runMain ,
216
223
);
217
224
```
218
225
@@ -403,6 +410,7 @@ import { NodeTesting } from 'effect-http-node';
403
410
test (" test /hello endpoint" , async () => {
404
411
const response = await NodeTesting .make (app , api ).pipe (
405
412
Effect .flatMap ((client ) => client .hello ({ query: { input: 12 } })),
413
+ Effect .scoped ,
406
414
Effect .runPromise ,
407
415
);
408
416
@@ -481,39 +489,35 @@ so we can see the failure behavior.
481
489
482
490
``` typescript
483
491
interface UserRepository {
484
- existsByName : (name : string ) => Effect .Effect <never , never , boolean >;
485
- store : (user : string ) => Effect .Effect <never , never , void >;
492
+ userExistsByName : (name : string ) => Effect .Effect <boolean >;
493
+ storeUser : (user : string ) => Effect .Effect <void >;
486
494
}
487
495
488
- const UserRepository = Context .Tag <UserRepository >();
496
+ const UserRepository = Context .GenericTag <UserRepository >(" UserRepository " );
489
497
490
498
const mockUserRepository = UserRepository .of ({
491
- existsByName : () => Effect .succeed (true ),
492
- store : () => Effect .unit ,
499
+ userExistsByName : () => Effect .succeed (true ),
500
+ storeUser : () => Effect .unit ,
493
501
});
502
+
503
+ const { userExistsByName, storeUser } = Effect .serviceFunctions (UserRepository );
494
504
```
495
505
496
506
And finally, we have the actual ` App ` implementation.
497
507
498
508
``` typescript
509
+
499
510
const app = RouterBuilder .make (api ).pipe (
500
511
RouterBuilder .handle (" storeUser" , ({ body }) =>
501
512
pipe (
502
- Effect .flatMap (UserRepository , (userRepository ) =>
503
- userRepository .existsByName (body .name ),
504
- ),
513
+ userExistsByName (body .name ),
505
514
Effect .filterOrFail (
506
515
(alreadyExists ) => ! alreadyExists ,
507
516
() => ServerError .conflictError (` User "${body .name }" already exists. ` ),
508
517
),
509
- Effect .flatMap (() =>
510
- Effect .flatMap (UserRepository , (repository ) =>
511
- repository .store (body .name ),
512
- ),
513
- ),
518
+ Effect .andThen (storeUser (body .name )),
514
519
Effect .map (() => ` User "${body .name }" stored. ` ),
515
- ),
516
- ),
520
+ )),
517
521
RouterBuilder .build ,
518
522
);
519
523
```
@@ -525,7 +529,7 @@ the `mockUserRepository` service.
525
529
app .pipe (
526
530
NodeServer .listen ({ port: 3000 }),
527
531
Effect .provideService (UserRepository , mockUserRepository ),
528
- Effect . runPromise ,
532
+ NodeRuntime . runMain
529
533
);
530
534
```
531
535
@@ -570,7 +574,7 @@ This enables separability of concers for big APIs and provides information for
570
574
generation of tags for the OpenAPI specification.
571
575
572
576
` ` ` typescript
573
- import { runMain } from " @effect/platform-node/Runtime " ;
577
+ import { NodeRuntime } from " @effect/platform-node" ;
574
578
import { Schema } from " @effect/schema" ;
575
579
import { Api, ExampleServer, RouterBuilder } from " effect-http" ;
576
580
import { NodeServer } from " effect-http-node" ;
@@ -604,7 +608,7 @@ const api = Api.api().pipe(
604
608
ExampleServer.make(api).pipe(
605
609
RouterBuilder.build,
606
610
NodeServer.listen({ port: 3000 }),
607
- runMain,
611
+ NodeRuntime. runMain,
608
612
);
609
613
` ` `
610
614
@@ -638,8 +642,8 @@ For an operation-level description, call the API endpoint method (`Api.get`,
638
642
desired description.
639
643
640
644
` ` ` ts
641
- import { runMain } from " @effect/platform-node/Runtime " ;
642
- import * as Schema from " @effect/schema/Schema " ;
645
+ import { NodeRuntime } from " @effect/platform-node" ;
646
+ import { Schema } from " @effect/schema" ;
643
647
import { Effect, pipe } from " effect" ;
644
648
import { Api, RouterBuilder } from " effect-http" ;
645
649
import { NodeServer } from " effect-http-node" ;
@@ -676,7 +680,7 @@ const app = RouterBuilder.make(api).pipe(
676
680
RouterBuilder.build,
677
681
);
678
682
679
- app.pipe(NodeServer.listen({ port: 3000 }), runMain);
683
+ app.pipe(NodeServer.listen({ port: 3000 }), NodeRuntime. runMain);
680
684
` ` `
681
685
682
686
# # Representations
@@ -716,7 +720,7 @@ be used, and if there is no representation matching the incomming `Accept` media
716
720
it will choose the first representation in the list.
717
721
718
722
` ` ` ts
719
- import { runMain } from " @effect/platform-node/Runtime " ;
723
+ import { NodeRuntime } from " @effect/platform-node" ;
720
724
import { Schema } from " @effect/schema" ;
721
725
import { Effect } from " effect" ;
722
726
import { Api, Representation, RouterBuilder } from " effect-http" ;
@@ -745,7 +749,7 @@ const program = app.pipe(
745
749
Effect.provide(PrettyLogger.layer ()),
746
750
);
747
751
748
- runMain(program);
752
+ NodeRuntime. runMain(program);
749
753
` ` `
750
754
751
755
Try running the server above and call the root path with different
@@ -790,7 +794,7 @@ helpful in the following and probably many more cases.
790
794
Use `ExampleServer.make` combinator to generate a `RouterBuilder` from an `Api`.
791
795
792
796
```typescript
793
- import { runMain } from "@effect/platform-node/Runtime ";
797
+ import { NodeRuntime } from "@effect/platform-node";
794
798
import { Schema } from "@effect/schema";
795
799
import { Effect, pipe } from "effect";
796
800
import { Api, ExampleServer, RouterBuilder } from "effect-http";
@@ -807,7 +811,7 @@ pipe(
807
811
ExampleServer.make(api),
808
812
RouterBuilder.build,
809
813
NodeServer.listen({ port: 3000 }),
810
- runMain,
814
+ NodeRuntime. runMain,
811
815
);
812
816
```
813
817
0 commit comments