starpc 0.1.7 → 0.2.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/Makefile +1 -0
- package/README.md +24 -5
- package/dist/echo/client-test.d.ts +2 -0
- package/dist/echo/client-test.js +35 -0
- package/dist/echo/echo.d.ts +124 -0
- package/dist/echo/echo.js +42 -0
- package/dist/echo/index.d.ts +3 -0
- package/dist/echo/index.js +3 -0
- package/dist/echo/server.d.ts +8 -0
- package/dist/echo/server.js +50 -0
- package/dist/echo/sever.d.ts +0 -0
- package/dist/echo/sever.js +1 -0
- package/dist/srpc/broadcast-channel.d.ts +3 -2
- package/dist/srpc/broadcast-channel.js +2 -2
- package/dist/srpc/client-rpc.d.ts +4 -28
- package/dist/srpc/client-rpc.js +9 -152
- package/dist/srpc/client.d.ts +2 -2
- package/dist/srpc/client.js +56 -84
- package/dist/srpc/common-rpc.d.ts +24 -0
- package/dist/srpc/common-rpc.js +140 -0
- package/dist/srpc/conn.d.ts +8 -3
- package/dist/srpc/conn.js +19 -3
- package/dist/srpc/definition.d.ts +15 -0
- package/dist/srpc/definition.js +1 -0
- package/dist/srpc/handler.d.ts +24 -0
- package/dist/srpc/handler.js +123 -0
- package/dist/srpc/index.d.ts +7 -3
- package/dist/srpc/index.js +6 -2
- package/dist/srpc/message.d.ts +11 -0
- package/dist/srpc/message.js +32 -0
- package/dist/srpc/mux.d.ts +11 -0
- package/dist/srpc/mux.js +36 -0
- package/dist/srpc/packet.d.ts +4 -4
- package/dist/srpc/packet.js +38 -27
- package/dist/srpc/rpcproto.d.ts +18 -43
- package/dist/srpc/rpcproto.js +37 -78
- package/dist/srpc/server-rpc.d.ts +11 -0
- package/dist/srpc/server-rpc.js +55 -0
- package/dist/srpc/server.d.ts +14 -0
- package/dist/srpc/server.js +31 -0
- package/dist/srpc/websocket.d.ts +3 -2
- package/dist/srpc/websocket.js +4 -4
- package/e2e/README.md +10 -0
- package/e2e/e2e.ts +27 -0
- package/echo/client-test.ts +41 -0
- package/echo/echo.ts +45 -0
- package/echo/index.ts +3 -0
- package/echo/server.ts +57 -0
- package/echo/sever.ts +0 -0
- package/integration/integration.bash +1 -1
- package/integration/integration.ts +10 -42
- package/package.json +18 -17
- package/srpc/broadcast-channel.ts +8 -3
- package/srpc/client-rpc.go +1 -9
- package/srpc/client-rpc.ts +11 -175
- package/srpc/client.ts +58 -99
- package/srpc/common-rpc.ts +171 -0
- package/srpc/conn.ts +33 -5
- package/srpc/definition.ts +30 -0
- package/srpc/handler.ts +174 -0
- package/srpc/index.ts +7 -3
- package/srpc/message.ts +60 -0
- package/srpc/mux.ts +56 -0
- package/srpc/packet.go +4 -11
- package/srpc/packet.ts +44 -30
- package/srpc/rpcproto.pb.go +54 -118
- package/srpc/rpcproto.proto +7 -12
- package/srpc/rpcproto.ts +38 -101
- package/srpc/rpcproto_vtproto.pb.go +58 -210
- package/srpc/server-rpc.go +5 -10
- package/srpc/server-rpc.ts +65 -0
- package/srpc/server.ts +56 -0
- package/srpc/websocket.ts +6 -4
package/Makefile
CHANGED
|
@@ -102,6 +102,7 @@ gents: $(PROTOWRAP) node_modules
|
|
|
102
102
|
--ts_proto_opt=forceLong=long \
|
|
103
103
|
--ts_proto_opt=oneof=unions \
|
|
104
104
|
--ts_proto_opt=esModuleInterop=true \
|
|
105
|
+
--ts_proto_opt=outputServices=default,outputServices=generic-definitions \
|
|
105
106
|
--proto_path $$(pwd)/vendor \
|
|
106
107
|
--print_structure \
|
|
107
108
|
--only_specified_files \
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ message EchoMsg {
|
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
## Go
|
|
59
|
+
## Go: Server & Client
|
|
60
60
|
|
|
61
61
|
A basic example can be found in the [e2e test]:
|
|
62
62
|
|
|
@@ -103,6 +103,29 @@ for WebSockets.
|
|
|
103
103
|
|
|
104
104
|
This repository uses protowrap, see the [Makefile](./Makefile).
|
|
105
105
|
|
|
106
|
+
`WebSocketConn` uses [js-libp2p-mplex] to multiplex streams over the WebSocket.
|
|
107
|
+
|
|
108
|
+
[js-libp2p-mplex]: https://github.com/libp2p/js-libp2p-mplex
|
|
109
|
+
|
|
110
|
+
### Server
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { WebSocketConn, Server, createMux } from '../srpc'
|
|
114
|
+
import { EchoerClientImpl } from '../echo/echo'
|
|
115
|
+
|
|
116
|
+
const mux = createMux()
|
|
117
|
+
mux.register(TODO)
|
|
118
|
+
const server = new Server(mux)
|
|
119
|
+
|
|
120
|
+
// TODO: accept a WebSocket-like object.
|
|
121
|
+
const ws = TODO
|
|
122
|
+
const channel = new WebSocketConn(ws, server)
|
|
123
|
+
// incoming streams will be handled by server.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
### Client
|
|
128
|
+
|
|
106
129
|
```typescript
|
|
107
130
|
import { WebSocketConn } from '../srpc'
|
|
108
131
|
import { EchoerClientImpl } from '../echo/echo'
|
|
@@ -127,10 +150,6 @@ result = await demoServiceClient.EchoClientStream(clientRequestStream)
|
|
|
127
150
|
console.log('success: output', result.body)
|
|
128
151
|
```
|
|
129
152
|
|
|
130
|
-
`WebSocketConn` uses [js-libp2p-mplex] to multiplex streams over the WebSocket.
|
|
131
|
-
|
|
132
|
-
[js-libp2p-mplex]: https://github.com/libp2p/js-libp2p-mplex
|
|
133
|
-
|
|
134
153
|
# Attribution
|
|
135
154
|
|
|
136
155
|
`protoc-gen-go-starpc` is a heavily modified version of `protoc-gen-go-drpc`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EchoerClientImpl } from './echo.js';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
export async function runClientTest(client) {
|
|
4
|
+
const demoServiceClient = new EchoerClientImpl(client);
|
|
5
|
+
console.log('Calling Echo: unary call...');
|
|
6
|
+
let result = await demoServiceClient.Echo({
|
|
7
|
+
body: 'Hello world!',
|
|
8
|
+
});
|
|
9
|
+
console.log('success: output', result.body);
|
|
10
|
+
// observable for client requests
|
|
11
|
+
const clientRequestStream = new Observable((subscriber) => {
|
|
12
|
+
subscriber.next({ body: 'Hello world from streaming request.' });
|
|
13
|
+
subscriber.complete();
|
|
14
|
+
});
|
|
15
|
+
console.log('Calling EchoClientStream: client -> server...');
|
|
16
|
+
result = await demoServiceClient.EchoClientStream(clientRequestStream);
|
|
17
|
+
console.log('success: output', result.body);
|
|
18
|
+
console.log('Calling EchoServerStream: server -> client...');
|
|
19
|
+
const serverStream = demoServiceClient.EchoServerStream({
|
|
20
|
+
body: 'Hello world from server to client streaming request.',
|
|
21
|
+
});
|
|
22
|
+
await new Promise((resolve, reject) => {
|
|
23
|
+
serverStream.subscribe({
|
|
24
|
+
next(result) {
|
|
25
|
+
console.log('server: output', result.body);
|
|
26
|
+
},
|
|
27
|
+
complete() {
|
|
28
|
+
resolve();
|
|
29
|
+
},
|
|
30
|
+
error(err) {
|
|
31
|
+
reject(err);
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
package/dist/echo/echo.d.ts
CHANGED
|
@@ -36,6 +36,130 @@ export declare class EchoerClientImpl implements Echoer {
|
|
|
36
36
|
EchoClientStream(request: Observable<EchoMsg>): Promise<EchoMsg>;
|
|
37
37
|
EchoBidiStream(request: Observable<EchoMsg>): Observable<EchoMsg>;
|
|
38
38
|
}
|
|
39
|
+
/** Echoer service returns the given message. */
|
|
40
|
+
export declare type EchoerDefinition = typeof EchoerDefinition;
|
|
41
|
+
export declare const EchoerDefinition: {
|
|
42
|
+
readonly name: "Echoer";
|
|
43
|
+
readonly fullName: "echo.Echoer";
|
|
44
|
+
readonly methods: {
|
|
45
|
+
/** Echo returns the given message. */
|
|
46
|
+
readonly echo: {
|
|
47
|
+
readonly name: "Echo";
|
|
48
|
+
readonly requestType: {
|
|
49
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
50
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
51
|
+
fromJSON(object: any): EchoMsg;
|
|
52
|
+
toJSON(message: EchoMsg): unknown;
|
|
53
|
+
fromPartial<I extends {
|
|
54
|
+
body?: string | undefined;
|
|
55
|
+
} & {
|
|
56
|
+
body?: string | undefined;
|
|
57
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
58
|
+
};
|
|
59
|
+
readonly requestStream: false;
|
|
60
|
+
readonly responseType: {
|
|
61
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
62
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
63
|
+
fromJSON(object: any): EchoMsg;
|
|
64
|
+
toJSON(message: EchoMsg): unknown;
|
|
65
|
+
fromPartial<I extends {
|
|
66
|
+
body?: string | undefined;
|
|
67
|
+
} & {
|
|
68
|
+
body?: string | undefined;
|
|
69
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
70
|
+
};
|
|
71
|
+
readonly responseStream: false;
|
|
72
|
+
readonly options: {};
|
|
73
|
+
};
|
|
74
|
+
/** EchoServerStream is an example of a server -> client one-way stream. */
|
|
75
|
+
readonly echoServerStream: {
|
|
76
|
+
readonly name: "EchoServerStream";
|
|
77
|
+
readonly requestType: {
|
|
78
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
79
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
80
|
+
fromJSON(object: any): EchoMsg;
|
|
81
|
+
toJSON(message: EchoMsg): unknown;
|
|
82
|
+
fromPartial<I extends {
|
|
83
|
+
body?: string | undefined;
|
|
84
|
+
} & {
|
|
85
|
+
body?: string | undefined;
|
|
86
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
87
|
+
};
|
|
88
|
+
readonly requestStream: false;
|
|
89
|
+
readonly responseType: {
|
|
90
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
91
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
92
|
+
fromJSON(object: any): EchoMsg;
|
|
93
|
+
toJSON(message: EchoMsg): unknown;
|
|
94
|
+
fromPartial<I extends {
|
|
95
|
+
body?: string | undefined;
|
|
96
|
+
} & {
|
|
97
|
+
body?: string | undefined;
|
|
98
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
99
|
+
};
|
|
100
|
+
readonly responseStream: true;
|
|
101
|
+
readonly options: {};
|
|
102
|
+
};
|
|
103
|
+
/** EchoClientStream is an example of client->server one-way stream. */
|
|
104
|
+
readonly echoClientStream: {
|
|
105
|
+
readonly name: "EchoClientStream";
|
|
106
|
+
readonly requestType: {
|
|
107
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
108
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
109
|
+
fromJSON(object: any): EchoMsg;
|
|
110
|
+
toJSON(message: EchoMsg): unknown;
|
|
111
|
+
fromPartial<I extends {
|
|
112
|
+
body?: string | undefined;
|
|
113
|
+
} & {
|
|
114
|
+
body?: string | undefined;
|
|
115
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
116
|
+
};
|
|
117
|
+
readonly requestStream: true;
|
|
118
|
+
readonly responseType: {
|
|
119
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
120
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
121
|
+
fromJSON(object: any): EchoMsg;
|
|
122
|
+
toJSON(message: EchoMsg): unknown;
|
|
123
|
+
fromPartial<I extends {
|
|
124
|
+
body?: string | undefined;
|
|
125
|
+
} & {
|
|
126
|
+
body?: string | undefined;
|
|
127
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
128
|
+
};
|
|
129
|
+
readonly responseStream: false;
|
|
130
|
+
readonly options: {};
|
|
131
|
+
};
|
|
132
|
+
/** EchoBidiStream is an example of a two-way stream. */
|
|
133
|
+
readonly echoBidiStream: {
|
|
134
|
+
readonly name: "EchoBidiStream";
|
|
135
|
+
readonly requestType: {
|
|
136
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
137
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
138
|
+
fromJSON(object: any): EchoMsg;
|
|
139
|
+
toJSON(message: EchoMsg): unknown;
|
|
140
|
+
fromPartial<I extends {
|
|
141
|
+
body?: string | undefined;
|
|
142
|
+
} & {
|
|
143
|
+
body?: string | undefined;
|
|
144
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
145
|
+
};
|
|
146
|
+
readonly requestStream: true;
|
|
147
|
+
readonly responseType: {
|
|
148
|
+
encode(message: EchoMsg, writer?: _m0.Writer): _m0.Writer;
|
|
149
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg;
|
|
150
|
+
fromJSON(object: any): EchoMsg;
|
|
151
|
+
toJSON(message: EchoMsg): unknown;
|
|
152
|
+
fromPartial<I extends {
|
|
153
|
+
body?: string | undefined;
|
|
154
|
+
} & {
|
|
155
|
+
body?: string | undefined;
|
|
156
|
+
} & Record<Exclude<keyof I, "body">, never>>(object: I): EchoMsg;
|
|
157
|
+
};
|
|
158
|
+
readonly responseStream: true;
|
|
159
|
+
readonly options: {};
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
};
|
|
39
163
|
interface Rpc {
|
|
40
164
|
request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
|
|
41
165
|
clientStreamingRequest(service: string, method: string, data: Observable<Uint8Array>): Promise<Uint8Array>;
|
package/dist/echo/echo.js
CHANGED
|
@@ -76,6 +76,48 @@ export class EchoerClientImpl {
|
|
|
76
76
|
return result.pipe(map((data) => EchoMsg.decode(new _m0.Reader(data))));
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
export const EchoerDefinition = {
|
|
80
|
+
name: 'Echoer',
|
|
81
|
+
fullName: 'echo.Echoer',
|
|
82
|
+
methods: {
|
|
83
|
+
/** Echo returns the given message. */
|
|
84
|
+
echo: {
|
|
85
|
+
name: 'Echo',
|
|
86
|
+
requestType: EchoMsg,
|
|
87
|
+
requestStream: false,
|
|
88
|
+
responseType: EchoMsg,
|
|
89
|
+
responseStream: false,
|
|
90
|
+
options: {},
|
|
91
|
+
},
|
|
92
|
+
/** EchoServerStream is an example of a server -> client one-way stream. */
|
|
93
|
+
echoServerStream: {
|
|
94
|
+
name: 'EchoServerStream',
|
|
95
|
+
requestType: EchoMsg,
|
|
96
|
+
requestStream: false,
|
|
97
|
+
responseType: EchoMsg,
|
|
98
|
+
responseStream: true,
|
|
99
|
+
options: {},
|
|
100
|
+
},
|
|
101
|
+
/** EchoClientStream is an example of client->server one-way stream. */
|
|
102
|
+
echoClientStream: {
|
|
103
|
+
name: 'EchoClientStream',
|
|
104
|
+
requestType: EchoMsg,
|
|
105
|
+
requestStream: true,
|
|
106
|
+
responseType: EchoMsg,
|
|
107
|
+
responseStream: false,
|
|
108
|
+
options: {},
|
|
109
|
+
},
|
|
110
|
+
/** EchoBidiStream is an example of a two-way stream. */
|
|
111
|
+
echoBidiStream: {
|
|
112
|
+
name: 'EchoBidiStream',
|
|
113
|
+
requestType: EchoMsg,
|
|
114
|
+
requestStream: true,
|
|
115
|
+
responseType: EchoMsg,
|
|
116
|
+
responseStream: true,
|
|
117
|
+
options: {},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
};
|
|
79
121
|
if (_m0.util.Long !== Long) {
|
|
80
122
|
_m0.util.Long = Long;
|
|
81
123
|
_m0.configure();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { Echoer, EchoMsg } from './echo';
|
|
3
|
+
export declare class EchoerServer implements Echoer {
|
|
4
|
+
Echo(request: EchoMsg): Promise<EchoMsg>;
|
|
5
|
+
EchoServerStream(request: EchoMsg): Observable<EchoMsg>;
|
|
6
|
+
EchoClientStream(request: Observable<EchoMsg>): Promise<EchoMsg>;
|
|
7
|
+
EchoBidiStream(request: Observable<EchoMsg>): Observable<EchoMsg>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { from as observableFrom } from 'rxjs';
|
|
2
|
+
import { pushable } from 'it-pushable';
|
|
3
|
+
// EchoServer implements the Echoer server.
|
|
4
|
+
export class EchoerServer {
|
|
5
|
+
async Echo(request) {
|
|
6
|
+
return request;
|
|
7
|
+
}
|
|
8
|
+
EchoServerStream(request) {
|
|
9
|
+
// send 5 responses, with a 200ms delay for each
|
|
10
|
+
return observableFrom((async function* response() {
|
|
11
|
+
for (let i = 0; i < 5; i++) {
|
|
12
|
+
yield request;
|
|
13
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
14
|
+
}
|
|
15
|
+
})());
|
|
16
|
+
}
|
|
17
|
+
EchoClientStream(request) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
request.subscribe({
|
|
20
|
+
next(msg) {
|
|
21
|
+
resolve(msg);
|
|
22
|
+
},
|
|
23
|
+
error(err) {
|
|
24
|
+
reject(err);
|
|
25
|
+
},
|
|
26
|
+
complete() {
|
|
27
|
+
reject(new Error('none received'));
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
EchoBidiStream(request) {
|
|
33
|
+
// build result observable
|
|
34
|
+
const pushResponse = pushable({ objectMode: true });
|
|
35
|
+
const response = observableFrom(pushResponse);
|
|
36
|
+
pushResponse.push({ body: 'hello from server' });
|
|
37
|
+
request.subscribe({
|
|
38
|
+
next(msg) {
|
|
39
|
+
pushResponse.push(msg);
|
|
40
|
+
},
|
|
41
|
+
error(err) {
|
|
42
|
+
pushResponse.throw(err);
|
|
43
|
+
},
|
|
44
|
+
complete() {
|
|
45
|
+
pushResponse.end();
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
return response;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Duplex, Sink } from 'it-stream-types';
|
|
2
|
-
import { Conn } from './conn';
|
|
2
|
+
import { Conn, ConnParams } from './conn';
|
|
3
|
+
import { Server } from './server';
|
|
3
4
|
export declare class BroadcastChannelIterable<T> implements Duplex<T> {
|
|
4
5
|
readonly channel: BroadcastChannel;
|
|
5
6
|
sink: Sink<T>;
|
|
@@ -11,6 +12,6 @@ export declare class BroadcastChannelIterable<T> implements Duplex<T> {
|
|
|
11
12
|
export declare function newBroadcastChannelIterable<T>(name: string): BroadcastChannelIterable<T>;
|
|
12
13
|
export declare class BroadcastChannelConn extends Conn {
|
|
13
14
|
private channel;
|
|
14
|
-
constructor(channel: BroadcastChannel);
|
|
15
|
+
constructor(channel: BroadcastChannel, server?: Server, connParams?: ConnParams);
|
|
15
16
|
getBroadcastChannel(): BroadcastChannel;
|
|
16
17
|
}
|
|
@@ -48,8 +48,8 @@ export function newBroadcastChannelIterable(name) {
|
|
|
48
48
|
export class BroadcastChannelConn extends Conn {
|
|
49
49
|
// channel is the broadcast channel iterable
|
|
50
50
|
channel;
|
|
51
|
-
constructor(channel) {
|
|
52
|
-
super();
|
|
51
|
+
constructor(channel, server, connParams) {
|
|
52
|
+
super(server, connParams);
|
|
53
53
|
this.channel = new BroadcastChannelIterable(channel);
|
|
54
54
|
pipe(this, this.channel, this);
|
|
55
55
|
}
|
|
@@ -1,31 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare class ClientRPC {
|
|
6
|
-
sink: Sink<Packet>;
|
|
7
|
-
source: AsyncIterable<Packet>;
|
|
8
|
-
private readonly _source;
|
|
9
|
-
private service;
|
|
10
|
-
private method;
|
|
11
|
-
private dataCb?;
|
|
12
|
-
private started;
|
|
13
|
-
private onStarted?;
|
|
14
|
-
private complete;
|
|
15
|
-
private onComplete?;
|
|
16
|
-
private closed;
|
|
17
|
-
constructor(service: string, method: string, dataCb: DataCb | null);
|
|
18
|
-
waitStarted(): Promise<void>;
|
|
19
|
-
waitComplete(): Promise<void>;
|
|
1
|
+
import type { CallStart } from './rpcproto.js';
|
|
2
|
+
import { CommonRPC } from './common-rpc.js';
|
|
3
|
+
export declare class ClientRPC extends CommonRPC {
|
|
4
|
+
constructor(service: string, method: string);
|
|
20
5
|
writeCallStart(data?: Uint8Array): Promise<void>;
|
|
21
|
-
writeCallData(data: Uint8Array, complete?: boolean, error?: string): Promise<void>;
|
|
22
|
-
private writePacket;
|
|
23
|
-
handleMessage(message: Uint8Array): Promise<void>;
|
|
24
|
-
handlePacket(packet: Partial<Packet>): Promise<void>;
|
|
25
6
|
handleCallStart(packet: Partial<CallStart>): Promise<void>;
|
|
26
|
-
handleCallStartResp(packet: Partial<CallStartResp>): Promise<void>;
|
|
27
|
-
handleCallData(packet: Partial<CallData>): Promise<void>;
|
|
28
|
-
close(err?: Error): Promise<void>;
|
|
29
|
-
private _createSink;
|
|
30
|
-
private _createSource;
|
|
31
7
|
}
|
package/dist/srpc/client-rpc.js
CHANGED
|
@@ -1,77 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { pushable } from 'it-pushable';
|
|
1
|
+
import { CommonRPC } from './common-rpc.js';
|
|
3
2
|
// ClientRPC is an ongoing RPC from the client side.
|
|
4
|
-
export class ClientRPC {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// source is the packet source for outgoing Packets.
|
|
8
|
-
source;
|
|
9
|
-
// _source is used to write to the source.
|
|
10
|
-
_source;
|
|
11
|
-
// service is the rpc service
|
|
12
|
-
service;
|
|
13
|
-
// method is the rpc method
|
|
14
|
-
method;
|
|
15
|
-
// dataCb is called with any incoming data.
|
|
16
|
-
dataCb;
|
|
17
|
-
// started is resolved when the request starts.
|
|
18
|
-
started;
|
|
19
|
-
// onStarted is called by the message handler when the request starts.
|
|
20
|
-
onStarted;
|
|
21
|
-
// complete is resolved when the request completes.
|
|
22
|
-
// rejected with an error if the call encountered any error.
|
|
23
|
-
complete;
|
|
24
|
-
// onComplete is called by the message handler when the call completes.
|
|
25
|
-
onComplete;
|
|
26
|
-
// closed indicates close has been called
|
|
27
|
-
closed;
|
|
28
|
-
constructor(service, method, dataCb) {
|
|
29
|
-
this.closed = false;
|
|
30
|
-
this.sink = this._createSink();
|
|
31
|
-
const sourcev = this._createSource();
|
|
32
|
-
this.source = sourcev;
|
|
33
|
-
this._source = sourcev;
|
|
3
|
+
export class ClientRPC extends CommonRPC {
|
|
4
|
+
constructor(service, method) {
|
|
5
|
+
super();
|
|
34
6
|
this.service = service;
|
|
35
7
|
this.method = method;
|
|
36
|
-
if (dataCb) {
|
|
37
|
-
this.dataCb = dataCb;
|
|
38
|
-
}
|
|
39
|
-
this.started = new Promise((resolveStarted, rejectStarted) => {
|
|
40
|
-
this.onStarted = (err) => {
|
|
41
|
-
if (err) {
|
|
42
|
-
rejectStarted(err);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
resolveStarted();
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
});
|
|
49
|
-
this.complete = new Promise((resolveComplete, rejectComplete) => {
|
|
50
|
-
this.onComplete = (err) => {
|
|
51
|
-
this.closed = true;
|
|
52
|
-
if (err) {
|
|
53
|
-
rejectComplete(err);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
resolveComplete();
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
// waitStarted returns the started promise.
|
|
62
|
-
waitStarted() {
|
|
63
|
-
return this.started;
|
|
64
|
-
}
|
|
65
|
-
// waitComplete returns the complete promise.
|
|
66
|
-
waitComplete() {
|
|
67
|
-
return this.complete;
|
|
68
8
|
}
|
|
69
9
|
// writeCallStart writes the call start packet.
|
|
10
|
+
// if data === undefined and data.length === 0 sends empty data packet.
|
|
70
11
|
async writeCallStart(data) {
|
|
12
|
+
if (!this.service || !this.method) {
|
|
13
|
+
throw new Error('service and method must be set');
|
|
14
|
+
}
|
|
71
15
|
const callStart = {
|
|
72
16
|
rpcService: this.service,
|
|
73
17
|
rpcMethod: this.method,
|
|
74
18
|
data: data || new Uint8Array(0),
|
|
19
|
+
dataIsZero: !!data && data.length === 0,
|
|
75
20
|
};
|
|
76
21
|
await this.writePacket({
|
|
77
22
|
body: {
|
|
@@ -80,97 +25,9 @@ export class ClientRPC {
|
|
|
80
25
|
},
|
|
81
26
|
});
|
|
82
27
|
}
|
|
83
|
-
// writeCallData writes the call data packet.
|
|
84
|
-
async writeCallData(data, complete, error) {
|
|
85
|
-
const callData = {
|
|
86
|
-
data,
|
|
87
|
-
complete: complete || false,
|
|
88
|
-
error: error || '',
|
|
89
|
-
};
|
|
90
|
-
await this.writePacket({
|
|
91
|
-
body: {
|
|
92
|
-
$case: 'callData',
|
|
93
|
-
callData,
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
// writePacket writes a packet to the stream.
|
|
98
|
-
async writePacket(packet) {
|
|
99
|
-
this._source.push(packet);
|
|
100
|
-
}
|
|
101
|
-
// handleMessage handles an incoming encoded Packet.
|
|
102
|
-
//
|
|
103
|
-
// note: may throw an error if the message was unexpected or invalid.
|
|
104
|
-
async handleMessage(message) {
|
|
105
|
-
return this.handlePacket(Packet.decode(message));
|
|
106
|
-
}
|
|
107
|
-
// handlePacket handles an incoming packet.
|
|
108
|
-
async handlePacket(packet) {
|
|
109
|
-
switch (packet?.body?.$case) {
|
|
110
|
-
case 'callStart':
|
|
111
|
-
return this.handleCallStart(packet.body.callStart);
|
|
112
|
-
case 'callStartResp':
|
|
113
|
-
return this.handleCallStartResp(packet.body.callStartResp);
|
|
114
|
-
case 'callData':
|
|
115
|
-
return this.handleCallData(packet.body.callData);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
28
|
// handleCallStart handles a CallStart packet.
|
|
119
29
|
async handleCallStart(packet) {
|
|
120
30
|
// we do not implement server -> client RPCs.
|
|
121
31
|
throw new Error(`unexpected server to client rpc: ${packet.rpcService}/${packet.rpcMethod}`);
|
|
122
32
|
}
|
|
123
|
-
// handleCallStartResp handles a CallStartResp packet.
|
|
124
|
-
async handleCallStartResp(packet) {
|
|
125
|
-
if (packet.error && packet.error.length) {
|
|
126
|
-
const err = new Error(packet.error);
|
|
127
|
-
this.onStarted(err);
|
|
128
|
-
this.onComplete(err);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// handleCallData handles a CallData packet.
|
|
132
|
-
async handleCallData(packet) {
|
|
133
|
-
const data = packet.data;
|
|
134
|
-
if (this.dataCb && data?.length) {
|
|
135
|
-
await this.dataCb(data);
|
|
136
|
-
}
|
|
137
|
-
if (packet.error && packet.error.length) {
|
|
138
|
-
this.onComplete(new Error(packet.error));
|
|
139
|
-
}
|
|
140
|
-
else if (packet.complete) {
|
|
141
|
-
this.onComplete();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// close closes the active call if not already completed.
|
|
145
|
-
async close(err) {
|
|
146
|
-
if (!this.closed) {
|
|
147
|
-
await this.writeCallData(new Uint8Array(0), true, err ? err.message : '');
|
|
148
|
-
}
|
|
149
|
-
if (!err) {
|
|
150
|
-
err = new Error('call closed');
|
|
151
|
-
}
|
|
152
|
-
this.onComplete(err);
|
|
153
|
-
}
|
|
154
|
-
// _createSink initializes the sink field.
|
|
155
|
-
_createSink() {
|
|
156
|
-
return async (source) => {
|
|
157
|
-
try {
|
|
158
|
-
for await (const msg of source) {
|
|
159
|
-
await this.handlePacket(msg);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
catch (err) {
|
|
163
|
-
this.close(err);
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
// _createSource initializes the source field.
|
|
168
|
-
_createSource() {
|
|
169
|
-
return pushable({
|
|
170
|
-
objectMode: true,
|
|
171
|
-
onEnd: (err) => {
|
|
172
|
-
this.onComplete(err);
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
33
|
}
|
package/dist/srpc/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
-
import type { TsProtoRpc } from './ts-proto-rpc';
|
|
3
|
-
import type { OpenStreamFunc } from './stream';
|
|
2
|
+
import type { TsProtoRpc } from './ts-proto-rpc.js';
|
|
3
|
+
import type { OpenStreamFunc } from './stream.js';
|
|
4
4
|
export declare class Client implements TsProtoRpc {
|
|
5
5
|
private openConnFn;
|
|
6
6
|
constructor(openConnFn: OpenStreamFunc);
|