-
-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrating an endpoint that uses a database. #1046
base: feat/add-tutorials
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@samwho is attempting to deploy a commit to the Effect Team on Vercel. A member of the Team first needs to authorize it. |
```ts twoslash {2-5} | ||
import { Effect } from "effect" | ||
// ---cut--- | ||
const promise = Effect.promise(async () => "Hello, world!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth renaming this from promise
to something else to avoid a user interpreting the variable as a Promise
instead of an Effect
.
NodeRuntime.runMain( | ||
Layer.launch( | ||
Layer.provide( | ||
HttpServer.serve(router), | ||
NodeHttpServer.layer(() => createServer(app), { port: 3000 }), | ||
), | ||
), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you've already taught folks about .pipe
, you could re-write this to make it flow sequentially:
HttpServer.server(router).pipe(
Layer.provide(NodeHttpServer.layer(() => createServer(app), { port: 3000 })),
Layer.launch,
NodeRuntime.runMain
)
$ bun index.ts | ||
``` | ||
|
||
And in other shell we can test the endpoint: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And in other shell we can test the endpoint: | |
And in another shell we can test the endpoint: |
const users = Effect.sync(() => { | ||
return { users: db.prepare("SELECT * FROM users").all() } | ||
}).pipe( | ||
(body) => HttpServerResponse.json(body) | ||
) | ||
|
||
const router = HttpRouter.empty.pipe( | ||
HttpRouter.get("/health", health), | ||
HttpRouter.get("/users", users), | ||
) | ||
``` | ||
|
||
This no longer gives us a type error. We've split our computation into two | ||
parts: fetching the data with `Effect.sync`, and serializing it with | ||
`HttpServerResponse.json`. The call to `pipe` takes the result of the first | ||
Effect and passes it to `HttpServerResponse.json`, flattening any nesting in | ||
the process. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct - body
in this case has the type Effect<{ users: Array<string> }>
, which we're now passing to HttpServerResponse.json
. Because HttpServerResponse.json
takes data of type unknown
, you're going to attempt to serialize an Effect
instead of the body
.
The reason you don't get a type error here is because the input to HttpServerResponse.json
is unknown
, which will allow any value.
At this point, you may choose to introduce the concept of sequencing Effect
s.
const users = Effect.sync(() => {
return { users: db.prepare("SELECT * FROM users").all() }
}).pipe(
// Similar to `Effect.map`, `Effect.flatMap` receives the value of the previous effect
// but instead of returning a new _value_, you return a new _Effect_
Effect.flatMap((body) => HttpServerResponse.json(body))
// Or alternatively `Effect.andThen((body) => ...)` if you prefer that naming
)
// `users` is type `Effect<HttpServerResponse, HttpBodyError>`
or you can introduce Effect.suspend
, which is the same as Effect.sync
, except instead of taking a side effect that returns a value, it takes a side effect that returns an Effect
:
const users = Effect.suspend(() => {
// Side effect
const body = { users: db.prepare("SELECT * FROM users").all() }
// return an effect
return HttpServerResponse.json(body)
})
// `users` is type `Effect<HttpServerResponse, HttpBodyError>`
Type
Description
Currently still a work in progress.