Created
March 24, 2025 10:01
-
-
Save titouancreach/b605ed4b2730b838c341d41c6d31a7aa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
FetchHttpClient, | |
HttpRouter, | |
HttpServer, | |
HttpServerResponse, | |
} from "@effect/platform"; | |
import { BunHttpServer, BunRuntime } from "@effect/platform-bun"; | |
import { | |
Rpc, | |
RpcClient, | |
RpcGroup, | |
RpcSerialization, | |
RpcServer, | |
} from "@effect/rpc"; | |
import { toWebHandler } from "@effect/rpc/RpcServer"; | |
import { Context, Effect, Layer, Schema as S } from "effect"; | |
class UserGroup extends RpcGroup.make( | |
Rpc.make("GetUser", { | |
error: S.Never, | |
payload: { | |
id: S.Number, | |
}, | |
success: S.Struct({ | |
name: S.String, | |
}), | |
}), | |
) {} | |
class AdminGroup extends RpcGroup.make( | |
Rpc.make("GetAdmin", { | |
error: S.Never, | |
payload: { | |
id: S.Number, | |
}, | |
success: S.Struct({ | |
name: S.String, | |
}), | |
}), | |
) {} | |
// implémentation | |
export const UserLive = UserGroup.toLayer( | |
Effect.gen(function* () { | |
return { | |
GetUser: Effect.fn("GetUser")(function* ({ id }) { | |
yield* Effect.log("Called GetUser"); | |
return { | |
name: "John Doe", | |
}; | |
}), | |
}; | |
}), | |
); | |
export const AdminLive = AdminGroup.toLayer( | |
Effect.gen(function* () { | |
return { | |
GetAdmin: Effect.fn("GetAdmin")(function* ({ id }) { | |
yield* Effect.log("Called GetAdmin"); | |
return { | |
name: "Admin", | |
}; | |
}), | |
}; | |
}), | |
); | |
export class UserClient extends Context.Tag("UserClient")< | |
UserClient, | |
RpcClient.RpcClient<RpcGroup.Rpcs<typeof UserGroup>> | |
>() { | |
static layer = Layer.scoped(UserClient, RpcClient.make(UserGroup)); | |
} | |
export class AdminClient extends Context.Tag("AdminClient")< | |
AdminClient, | |
RpcClient.RpcClient<RpcGroup.Rpcs<typeof AdminGroup>> | |
>() { | |
static layer = Layer.scoped(AdminClient, RpcClient.make(AdminGroup)); | |
} | |
const app = toWebHandler(AdminGroup.merge(UserGroup), { | |
layer: Layer.mergeAll(AdminLive, UserLive).pipe( | |
Layer.merge(RpcSerialization.layerJson), | |
Layer.merge(HttpServer.layerContext), | |
), | |
}); | |
const app2 = RpcServer.toHttpApp(AdminGroup.merge(UserGroup)).pipe( | |
Effect.provide(AdminLive), | |
Effect.provide(UserLive), | |
Effect.provide(RpcSerialization.layerJson), | |
); | |
const Router = Effect.gen(function* () { | |
const _app = yield* app2; | |
return HttpRouter.empty.pipe( | |
HttpRouter.mountApp("/rpc", _app), | |
HttpServer.serve(), | |
Layer.provide(BunHttpServer.layer({ port: 3000 })), | |
); | |
}); | |
const AllClients = Layer.mergeAll(UserClient.layer, AdminClient.layer); | |
const ClientRuntime = AllClients.pipe( | |
Layer.provide( | |
RpcClient.layerProtocolHttp({ | |
url: "http://localhost:3000/rpc", | |
}), | |
), | |
Layer.provide(RpcSerialization.layerJson), | |
Layer.provide(FetchHttpClient.layer), | |
); | |
const clientMain = Effect.gen(function* () { | |
const admin = yield* AdminClient; | |
const adminUser = yield* admin.GetAdmin({ id: 1 }); | |
console.log(adminUser); | |
const client = yield* UserClient; | |
const user = yield* client.GetUser({ id: 1 }); | |
console.log(user); | |
console.log("finished"); | |
}).pipe(Effect.provide(ClientRuntime), Effect.delay("500 millis")); | |
const clientServer = Effect.all( | |
[Layer.launch(Layer.unwrapScoped(Router)), clientMain], | |
{ | |
concurrency: 2, | |
}, | |
); | |
BunRuntime.runMain(clientServer); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment