| 1 | /** |
| 2 | * In-memory test harness for RPC groups. |
| 3 | * |
| 4 | * `RpcTest` connects a generated client directly to `RpcServer` handlers for |
| 5 | * the same `RpcGroup`. It uses the no-serialization path, so requests, |
| 6 | * responses, stream chunks, acknowledgements, interrupts, headers, and |
| 7 | * middleware metadata travel through the normal client/server machinery without |
| 8 | * opening HTTP, socket, worker, or serializer infrastructure. |
| 9 | * |
| 10 | * @stability unstable |
| 11 | * @since 4.0.0 |
| 12 | */ |
| 13 | import * as Effect from "../Effect.ts" |
| 14 | import type * as Scope from "../Scope.ts" |
| 15 | import type * as Rpc from "./Rpc.ts" |
| 16 | import * as RpcClient from "./RpcClient.ts" |
| 17 | import type * as RpcGroup from "./RpcGroup.ts" |
| 18 | import * as RpcServer from "./RpcServer.ts" |
| 19 | |
| 20 | /** |
| 21 | * Creates an in-memory RPC client for a group, backed by the group's handlers |
| 22 | * from the environment and using the no-serialization test transport. |
| 23 | * |
| 24 | * @stability unstable |
| 25 | * @category constructors |
| 26 | * @since 4.0.0 |
| 27 | */ |
| 28 | export const makeClient: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>( |
| 29 | group: RpcGroup.RpcGroup<Rpcs>, |
| 30 | options?: { |
| 31 | readonly flatten?: Flatten | undefined |
| 32 | } |
| 33 | ) => Effect.Effect< |
| 34 | Flatten extends true ? RpcClient.RpcClient.Flat<Rpcs> : RpcClient.RpcClient<Rpcs>, |
| 35 | never, |
| 36 | Scope.Scope | Rpc.ToHandler<Rpcs> | Rpc.Middleware<Rpcs> | Rpc.MiddlewareClient<Rpcs> |
| 37 | > = Effect.fnUntraced(function*<Rpcs extends Rpc.Any, const Flatten extends boolean = false>( |
| 38 | group: RpcGroup.RpcGroup<Rpcs>, |
| 39 | options?: { |
| 40 | readonly flatten?: Flatten | undefined |
| 41 | } |
| 42 | ) { |
| 43 | // oxlint-disable-next-line prefer-const |
| 44 | let client!: Effect.Success<ReturnType<typeof RpcClient.makeNoSerialization<Rpcs, never, Flatten>>> |
| 45 | const server = yield* RpcServer.makeNoSerialization(group, { |
| 46 | onFromServer(response) { |
| 47 | return client.write(response) |
| 48 | } |
| 49 | }) |
| 50 | client = yield* RpcClient.makeNoSerialization(group, { |
| 51 | supportsAck: true, |
| 52 | flatten: options?.flatten, |
| 53 | onFromClient({ message }) { |
| 54 | return server.write(0, message) |
| 55 | } |
| 56 | }) |
| 57 | return client.client |
| 58 | }) |