@trevrpc/effect 1.5.0 → 1.7.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/README.md +9 -5
- package/package.json +6 -3
- package/src/index.d.ts +42 -42
- package/src/index.js +19 -28
package/README.md
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# @trevrpc/effect
|
|
2
2
|
|
|
3
|
-
[Effect](https://effect.website) adapter for the TrevRPC browser client, [`@trevrpc/trevrpc-js`](https://www.npmjs.com/package/@trevrpc/trevrpc-js): it
|
|
3
|
+
[Effect](https://effect.website) adapter for the TrevRPC browser client, [`@trevrpc/trevrpc-js`](https://www.npmjs.com/package/@trevrpc/trevrpc-js): it makes clients whose calls are effects and streams.
|
|
4
|
+
|
|
5
|
+
> **Compatibility:** every TrevRPC package shares one version, and packages of the same version are compatible
|
|
6
|
+
> with each other: `trevrpc-rust` 1.7.0 works with `trevrpc-go` 1.7.0, `trevrpc-js` 1.7.0, and `trevrpc-kotlin`
|
|
7
|
+
> 1.7.0. Compatibility across different versions isn't guaranteed yet; that's a milestone for 2.0.
|
|
4
8
|
|
|
5
9
|
```sh
|
|
6
|
-
npm install @trevrpc/effect @trevrpc/trevrpc-js effect
|
|
10
|
+
npm install @trevrpc/effect @trevrpc/trevrpc-js @bufbuild/protobuf effect
|
|
7
11
|
```
|
|
8
12
|
|
|
9
13
|
```ts
|
|
@@ -11,10 +15,10 @@ import { createChannel } from "@trevrpc/trevrpc-js";
|
|
|
11
15
|
import { createEffectClient } from "@trevrpc/effect";
|
|
12
16
|
import { Stream } from "effect";
|
|
13
17
|
|
|
14
|
-
import {
|
|
18
|
+
import { Greeter } from "./gen/greeter/v1/greeter_pb.js";
|
|
15
19
|
|
|
16
20
|
const channel = createChannel("https://example.com/trevrpc");
|
|
17
|
-
const greeter = createEffectClient(
|
|
21
|
+
const greeter = createEffectClient(Greeter, channel);
|
|
18
22
|
|
|
19
23
|
// Effect<HelloReply, TrevRpcError>
|
|
20
24
|
const reply = greeter.sayHello({ name: "Ada" });
|
|
@@ -28,7 +32,7 @@ const replies = greeter.chat(
|
|
|
28
32
|
);
|
|
29
33
|
```
|
|
30
34
|
|
|
31
|
-
`createEffectClient(service,
|
|
35
|
+
`createEffectClient(service, transport, options?)` takes what `createClient` of `@trevrpc/trevrpc-js` takes: a service descriptor that [protobuf-es](https://github.com/bufbuild/protobuf-es)'s `protoc-gen-es` generates, a transport such as a channel, and default call options and interceptors. It returns a client with one method per RPC, named by its `localName`:
|
|
32
36
|
|
|
33
37
|
| RPC kind | Effect method |
|
|
34
38
|
| ----------------------- | --------------------------------------------------------------------------------------- |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trevrpc/effect",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Effect adapter for TrevRPC browser clients",
|
|
5
5
|
"homepage": "https://trev.zip/llc/TrevRPC",
|
|
6
6
|
"bugs": {
|
|
@@ -39,16 +39,19 @@
|
|
|
39
39
|
"check": "npm run format:check && npm run lint && npm run typecheck && npm test"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
+
"@bufbuild/protobuf": "^2.17.0",
|
|
43
|
+
"@bufbuild/protoc-gen-es": "^2.17.0",
|
|
42
44
|
"@trevrpc/trevrpc-js": "file:..",
|
|
43
45
|
"effect": "^4.1.2",
|
|
44
46
|
"typescript": "^7.0.2"
|
|
45
47
|
},
|
|
46
48
|
"peerDependencies": {
|
|
47
|
-
"@
|
|
49
|
+
"@bufbuild/protobuf": "^2.17.0",
|
|
50
|
+
"@trevrpc/trevrpc-js": "^1.7.0",
|
|
48
51
|
"effect": "^4.1.2"
|
|
49
52
|
},
|
|
50
53
|
"engines": {
|
|
51
54
|
"node": ">=24"
|
|
52
55
|
},
|
|
53
|
-
"packageManager": "npm@12.2.
|
|
56
|
+
"packageManager": "npm@12.2.2"
|
|
54
57
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,56 +1,55 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
CallOptions,
|
|
4
|
-
ClientStreamingCall,
|
|
5
|
-
ResponseStream,
|
|
6
|
-
RpcServiceDescriptor,
|
|
7
|
-
TrevRpcError,
|
|
8
|
-
} from "@trevrpc/trevrpc-js";
|
|
1
|
+
import type { DescMessage, DescService, MessageInitShape, MessageShape } from "@bufbuild/protobuf";
|
|
2
|
+
import type { CallOptions, ClientOptions, Transport, TrevRpcError } from "@trevrpc/trevrpc-js";
|
|
9
3
|
import type { Effect, Stream } from "effect";
|
|
10
4
|
|
|
11
5
|
/**
|
|
12
|
-
* The Effect form of a
|
|
6
|
+
* The Effect form of a method of a protobuf-es service descriptor:
|
|
13
7
|
*
|
|
14
8
|
* - unary: `(request, options?) => Effect<Response, TrevRpcError>`
|
|
15
9
|
* - server streaming: `(request, options?) => Stream<Response, TrevRpcError>`
|
|
16
10
|
* - client streaming: `(requests, options?) => Effect<Response, TrevRpcError | E, R>`
|
|
17
11
|
* - bidirectional streaming: `(requests, options?) => Stream<Response, TrevRpcError | E, R>`
|
|
18
12
|
*
|
|
19
|
-
* where
|
|
13
|
+
* where a request is a message or the init object `create()` takes, `requests` is a
|
|
14
|
+
* `Stream<Request, E, R>`, and a response is a message.
|
|
20
15
|
*/
|
|
21
|
-
export type EffectMethod<Method> = Method extends
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
export type EffectMethod<Method> = Method extends {
|
|
17
|
+
methodKind: infer Kind;
|
|
18
|
+
input: infer I extends DescMessage;
|
|
19
|
+
output: infer O extends DescMessage;
|
|
20
|
+
}
|
|
21
|
+
? Kind extends "unary"
|
|
22
|
+
? (
|
|
23
|
+
request: MessageInitShape<I>,
|
|
29
24
|
options?: CallOptions,
|
|
30
|
-
) =>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
) => Effect.Effect<Response, TrevRpcError | E, R>
|
|
35
|
-
: Method extends (
|
|
36
|
-
request: infer Request,
|
|
25
|
+
) => Effect.Effect<MessageShape<O>, TrevRpcError>
|
|
26
|
+
: Kind extends "server_streaming"
|
|
27
|
+
? (
|
|
28
|
+
request: MessageInitShape<I>,
|
|
37
29
|
options?: CallOptions,
|
|
38
|
-
) =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
) => Stream.Stream<MessageShape<O>, TrevRpcError>
|
|
31
|
+
: Kind extends "client_streaming"
|
|
32
|
+
? <E = never, R = never>(
|
|
33
|
+
requests: Stream.Stream<MessageInitShape<I>, E, R>,
|
|
34
|
+
options?: CallOptions,
|
|
35
|
+
) => Effect.Effect<MessageShape<O>, TrevRpcError | E, R>
|
|
36
|
+
: Kind extends "bidi_streaming"
|
|
37
|
+
? <E = never, R = never>(
|
|
38
|
+
requests: Stream.Stream<MessageInitShape<I>, E, R>,
|
|
39
|
+
options?: CallOptions,
|
|
40
|
+
) => Stream.Stream<MessageShape<O>, TrevRpcError | E, R>
|
|
41
|
+
: never
|
|
42
|
+
: never;
|
|
43
43
|
|
|
44
|
-
/**
|
|
45
|
-
export type EffectClient<
|
|
46
|
-
[Name in keyof
|
|
47
|
-
Client[Name]
|
|
48
|
-
>;
|
|
44
|
+
/** The Effect client of a service: one method per RPC, named by its `localName`. */
|
|
45
|
+
export type EffectClient<S extends DescService> = {
|
|
46
|
+
[Name in keyof S["method"]]: EffectMethod<S["method"][Name]>;
|
|
49
47
|
};
|
|
50
48
|
|
|
51
49
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* Creates a client for `service`, a service descriptor that protoc-gen-es generates (such as
|
|
51
|
+
* `Greeter` from `greeter_pb.js`), whose calls are Effect values. `transport` and `options` are
|
|
52
|
+
* those of `createClient` in `@trevrpc/trevrpc-js`.
|
|
54
53
|
*
|
|
55
54
|
* Interrupting an effect or stream cancels its call, which the server sees as `Code.Cancelled`.
|
|
56
55
|
* A `signal` in the call options cancels it too. Client-streaming and bidirectional calls pull
|
|
@@ -62,12 +61,13 @@ export type EffectClient<Client> = {
|
|
|
62
61
|
* Calls fail with a `TrevRpcError`; anything else a call rejects with becomes one with
|
|
63
62
|
* `Code.Unknown`, and with the original as `cause`.
|
|
64
63
|
*
|
|
65
|
-
* @throws
|
|
64
|
+
* @throws TrevRpcError with `Code.InvalidArgument` where `createClient` throws it.
|
|
66
65
|
*/
|
|
67
|
-
export function createEffectClient<
|
|
68
|
-
service:
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
export function createEffectClient<S extends DescService>(
|
|
67
|
+
service: S,
|
|
68
|
+
transport: Transport,
|
|
69
|
+
options?: ClientOptions,
|
|
70
|
+
): EffectClient<S>;
|
|
71
71
|
|
|
72
72
|
/** Returns a `TrevRpcError` as is, and wraps anything else in one with `Code.Unknown`. */
|
|
73
73
|
export function toTrevRpcError(error: unknown): TrevRpcError;
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Code, TrevRpcError } from "@trevrpc/trevrpc-js";
|
|
1
|
+
import { Code, TrevRpcError, createClient } from "@trevrpc/trevrpc-js";
|
|
2
2
|
import { Effect, Stream } from "effect";
|
|
3
3
|
|
|
4
4
|
/** Returns a `TrevRpcError` as is, and wraps anything else in one with `Code.Unknown`. */
|
|
@@ -11,39 +11,30 @@ export function toTrevRpcError(error) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
* calls
|
|
16
|
-
*
|
|
14
|
+
* Creates a client for `service`, a service descriptor that protoc-gen-es generates, whose calls
|
|
15
|
+
* are Effect values: unary calls return an `Effect`, server-streaming calls a `Stream`, and
|
|
16
|
+
* client-streaming and bidirectional calls take their requests as a `Stream`. Interrupting the
|
|
17
|
+
* effect or stream cancels the call. `transport` and `options` are those of `createClient`.
|
|
17
18
|
*/
|
|
18
|
-
export function createEffectClient(service,
|
|
19
|
+
export function createEffectClient(service, transport, options) {
|
|
20
|
+
const client = createClient(service, transport, options);
|
|
19
21
|
const result = {};
|
|
20
|
-
for (const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
const call = client[name].bind(client);
|
|
25
|
-
switch (method.kind) {
|
|
26
|
-
case "unary":
|
|
27
|
-
result[name] = liftUnary(call);
|
|
28
|
-
break;
|
|
29
|
-
case "serverStreaming":
|
|
30
|
-
result[name] = liftServerStreaming(call);
|
|
31
|
-
break;
|
|
32
|
-
case "clientStreaming":
|
|
33
|
-
result[name] = liftClientStreaming(call);
|
|
34
|
-
break;
|
|
35
|
-
case "bidirectionalStreaming":
|
|
36
|
-
result[name] = liftBidirectionalStreaming(call);
|
|
37
|
-
break;
|
|
38
|
-
default:
|
|
39
|
-
throw new TypeError(
|
|
40
|
-
`unknown kind ${String(method.kind)} of ${service.fullName}/${method.name}`,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
22
|
+
for (const method of service.methods) {
|
|
23
|
+
const call = client[method.localName];
|
|
24
|
+
result[method.localName] = Lifts[method.methodKind](call);
|
|
43
25
|
}
|
|
44
26
|
return result;
|
|
45
27
|
}
|
|
46
28
|
|
|
29
|
+
/** How each protobuf-es method kind's calls become Effect values. */
|
|
30
|
+
const Lifts = Object.freeze({
|
|
31
|
+
__proto__: null,
|
|
32
|
+
unary: liftUnary,
|
|
33
|
+
server_streaming: liftServerStreaming,
|
|
34
|
+
client_streaming: liftClientStreaming,
|
|
35
|
+
bidi_streaming: liftBidirectionalStreaming,
|
|
36
|
+
});
|
|
37
|
+
|
|
47
38
|
function liftUnary(call) {
|
|
48
39
|
return (request, options) =>
|
|
49
40
|
Effect.tryPromise({
|