starpc 0.4.9 → 0.5.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 +20 -10
- package/dist/echo/client-test.d.ts +1 -0
- package/dist/echo/client-test.js +20 -18
- package/dist/echo/echo.pb.d.ts +165 -12
- package/dist/echo/echo.pb.js +61 -17
- package/dist/echo/server.d.ts +8 -4
- package/dist/echo/server.js +29 -37
- package/dist/rpcstream/rpcstream.d.ts +6 -6
- package/dist/rpcstream/rpcstream.js +92 -51
- package/dist/rpcstream/rpcstream.pb.d.ts +46 -1
- package/dist/rpcstream/rpcstream.pb.js +157 -9
- package/dist/srpc/client.d.ts +3 -4
- package/dist/srpc/client.js +12 -46
- package/dist/srpc/common-rpc.d.ts +3 -2
- package/dist/srpc/common-rpc.js +12 -0
- package/dist/srpc/definition.d.ts +3 -3
- package/dist/srpc/handler.d.ts +2 -3
- package/dist/srpc/handler.js +5 -22
- package/dist/srpc/index.d.ts +1 -1
- package/dist/srpc/index.js +1 -1
- package/dist/srpc/packet.js +0 -32
- package/dist/srpc/pushable.d.ts +2 -0
- package/dist/srpc/pushable.js +13 -0
- package/dist/srpc/rpcproto.pb.d.ts +13 -6
- package/dist/srpc/rpcproto.pb.js +95 -10
- package/dist/srpc/server.d.ts +1 -0
- package/dist/srpc/server.js +7 -0
- package/dist/srpc/ts-proto-rpc.d.ts +3 -4
- package/e2e/e2e.ts +4 -3
- package/e2e/e2e_test.go +24 -1
- package/echo/client-test.ts +23 -18
- package/echo/echo.pb.go +33 -20
- package/echo/echo.pb.ts +90 -34
- package/echo/echo.proto +4 -0
- package/echo/echo_srpc.pb.go +77 -0
- package/echo/server.go +18 -0
- package/echo/server.ts +47 -41
- package/integration/integration.go +1 -2
- package/integration/integration.ts +5 -1
- package/integration/integration_srpc.pb.go +139 -0
- package/package.json +5 -3
- package/patches/ts-proto+1.115.5.patch +1339 -0
- package/srpc/client.ts +16 -50
- package/srpc/common-rpc.ts +14 -2
- package/srpc/definition.ts +3 -3
- package/srpc/handler.ts +17 -34
- package/srpc/index.ts +1 -1
- package/srpc/muxed-conn.go +2 -2
- package/srpc/packet-rw.go +4 -6
- package/srpc/packet.ts +0 -33
- package/srpc/pushable.ts +17 -0
- package/srpc/rpcproto.pb.ts +122 -12
- package/srpc/server-pipe.go +2 -2
- package/srpc/server.go +2 -2
- package/srpc/server.ts +8 -0
- package/srpc/ts-proto-rpc.ts +4 -6
- package/srpc/websocket.go +2 -2
- package/dist/echo/sever.d.ts +0 -0
- package/dist/echo/sever.js +0 -1
- package/dist/srpc/observable-source.d.ts +0 -9
- package/dist/srpc/observable-source.js +0 -25
- package/echo/sever.ts +0 -0
- package/srpc/observable-source.ts +0 -40
|
@@ -6,10 +6,10 @@ export interface Definition {
|
|
|
6
6
|
[id: string]: MethodDefinition<unknown, unknown>;
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
export interface MethodDefinition<
|
|
9
|
+
export interface MethodDefinition<RequestT, ResponseT> {
|
|
10
10
|
name: string;
|
|
11
|
-
requestType: MessageDefinition<
|
|
11
|
+
requestType: MessageDefinition<RequestT>;
|
|
12
12
|
requestStream: boolean;
|
|
13
|
-
responseType: MessageDefinition<
|
|
13
|
+
responseType: MessageDefinition<ResponseT>;
|
|
14
14
|
responseStream: boolean;
|
|
15
15
|
}
|
package/dist/srpc/handler.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Sink, Source } from 'it-stream-types';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
2
|
import { Definition, MethodDefinition } from './definition.js';
|
|
4
3
|
export declare type InvokeFn = (dataSource: Source<Uint8Array>, dataSink: Sink<Uint8Array>) => Promise<void>;
|
|
5
4
|
export interface Handler {
|
|
@@ -18,7 +17,7 @@ export declare class StaticHandler implements Handler {
|
|
|
18
17
|
getMethodIDs(): string[];
|
|
19
18
|
lookupMethod(serviceID: string, methodID: string): Promise<InvokeFn | null>;
|
|
20
19
|
}
|
|
21
|
-
declare type MethodProto = ((request:
|
|
22
|
-
export declare function createInvokeFn(methodInfo: MethodDefinition<
|
|
20
|
+
declare type MethodProto<R, O> = ((request: R) => Promise<O>) | ((request: R) => AsyncIterable<O>) | ((request: AsyncIterable<R>) => Promise<O>) | ((request: AsyncIterable<R>) => AsyncIterable<O>);
|
|
21
|
+
export declare function createInvokeFn<R, O>(methodInfo: MethodDefinition<R, O>, methodProto: MethodProto<R, O>): InvokeFn;
|
|
23
22
|
export declare function createHandler(definition: Definition, impl: any): Handler;
|
|
24
23
|
export {};
|
package/dist/srpc/handler.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pipe } from 'it-pipe';
|
|
2
2
|
import { pushable } from 'it-pushable';
|
|
3
|
-
import { from as observableFrom } from 'rxjs';
|
|
4
3
|
import { buildDecodeMessageTransform, buildEncodeMessageTransform, } from './message.js';
|
|
4
|
+
import { writeToPushable } from './pushable.js';
|
|
5
5
|
// StaticHandler is a handler with a definition and implementation.
|
|
6
6
|
export class StaticHandler {
|
|
7
7
|
constructor(serviceID, methods) {
|
|
@@ -40,8 +40,8 @@ export function createInvokeFn(methodInfo, methodProto) {
|
|
|
40
40
|
// build the request argument.
|
|
41
41
|
let requestArg;
|
|
42
42
|
if (methodInfo.requestStream) {
|
|
43
|
-
//
|
|
44
|
-
requestArg =
|
|
43
|
+
// use the request source as the argument.
|
|
44
|
+
requestArg = requestSource;
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
47
|
// receive a single message for the argument.
|
|
@@ -62,25 +62,8 @@ export function createInvokeFn(methodInfo, methodProto) {
|
|
|
62
62
|
throw new Error('return value was undefined');
|
|
63
63
|
}
|
|
64
64
|
if (methodInfo.responseStream) {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
throw new Error('expected return value to be an Observable');
|
|
68
|
-
}
|
|
69
|
-
return new Promise((resolve, reject) => {
|
|
70
|
-
responseObs.subscribe({
|
|
71
|
-
next(value) {
|
|
72
|
-
responseSink.push(value);
|
|
73
|
-
},
|
|
74
|
-
error: (err) => {
|
|
75
|
-
responseSink.throw(err);
|
|
76
|
-
reject(err);
|
|
77
|
-
},
|
|
78
|
-
complete: () => {
|
|
79
|
-
responseSink.end();
|
|
80
|
-
resolve();
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
});
|
|
65
|
+
const response = responseObj;
|
|
66
|
+
return writeToPushable(response, responseSink);
|
|
84
67
|
}
|
|
85
68
|
else {
|
|
86
69
|
const responsePromise = responseObj;
|
package/dist/srpc/index.d.ts
CHANGED
|
@@ -7,4 +7,4 @@ export { Packet, CallStart, CallData } from './rpcproto.pb.js';
|
|
|
7
7
|
export { Mux, createMux } from './mux.js';
|
|
8
8
|
export { BroadcastChannelDuplex, newBroadcastChannelDuplex, BroadcastChannelConn, } from './broadcast-channel.js';
|
|
9
9
|
export { MessagePortIterable, newMessagePortIterable, MessagePortConn, } from './message-port.js';
|
|
10
|
-
export {
|
|
10
|
+
export { writeToPushable } from './pushable';
|
package/dist/srpc/index.js
CHANGED
|
@@ -6,4 +6,4 @@ export { Packet, CallStart, CallData } from './rpcproto.pb.js';
|
|
|
6
6
|
export { createMux } from './mux.js';
|
|
7
7
|
export { BroadcastChannelDuplex, newBroadcastChannelDuplex, BroadcastChannelConn, } from './broadcast-channel.js';
|
|
8
8
|
export { MessagePortIterable, newMessagePortIterable, MessagePortConn, } from './message-port.js';
|
|
9
|
-
export {
|
|
9
|
+
export { writeToPushable } from './pushable';
|
package/dist/srpc/packet.js
CHANGED
|
@@ -66,35 +66,3 @@ export function prependPacketLen(msgData) {
|
|
|
66
66
|
merged.set(msgData, msgLenData.length);
|
|
67
67
|
return merged;
|
|
68
68
|
}
|
|
69
|
-
/*
|
|
70
|
-
// buildCallDataPacket builds a CallData packet.
|
|
71
|
-
function buildCallDataPacket(data: Uint8Array): Packet {
|
|
72
|
-
const callData: CallData = {
|
|
73
|
-
data: p,
|
|
74
|
-
complete: false,
|
|
75
|
-
error: '',
|
|
76
|
-
}
|
|
77
|
-
const pkt: Packet = {
|
|
78
|
-
body: {
|
|
79
|
-
$case: 'callData',
|
|
80
|
-
callData: callData,
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return pkt
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// wrapCallDataTransform is a transformer that wraps call data into a Packet.
|
|
87
|
-
export async function* wrapCallDataTransform(
|
|
88
|
-
source: Source<Uint8Array | Uint8Array>
|
|
89
|
-
): AsyncIterable<Packet> {
|
|
90
|
-
for await (const pkt of source) {
|
|
91
|
-
if (Array.isArray(pkt)) {
|
|
92
|
-
for (const p of pkt) {
|
|
93
|
-
yield* [buildCallDataPacket(p)]
|
|
94
|
-
}
|
|
95
|
-
} else {
|
|
96
|
-
yield* [buildCallDataPacket(pkt)]
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
*/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// writeToPushable writes the incoming server data to the pushable.
|
|
2
|
+
export async function writeToPushable(dataSource, out) {
|
|
3
|
+
try {
|
|
4
|
+
for await (const data of dataSource) {
|
|
5
|
+
out.push(data);
|
|
6
|
+
}
|
|
7
|
+
out.end();
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
out.end(err);
|
|
11
|
+
throw err;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import Long from 'long';
|
|
2
2
|
import * as _m0 from 'protobufjs/minimal';
|
|
3
|
+
import { CallStart as CallStart1, CallData as CallData2 } from './rpcproto.pb.js';
|
|
3
4
|
export declare const protobufPackage = "srpc";
|
|
4
5
|
/** Packet is a message sent over a srpc packet connection. */
|
|
5
6
|
export interface Packet {
|
|
6
7
|
body?: {
|
|
7
8
|
$case: 'callStart';
|
|
8
|
-
callStart:
|
|
9
|
+
callStart: CallStart1;
|
|
9
10
|
} | {
|
|
10
11
|
$case: 'callData';
|
|
11
|
-
callData:
|
|
12
|
+
callData: CallData2;
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
15
|
/** CallStart requests starting a new RPC call. */
|
|
@@ -48,6 +49,8 @@ export interface CallData {
|
|
|
48
49
|
export declare const Packet: {
|
|
49
50
|
encode(message: Packet, writer?: _m0.Writer): _m0.Writer;
|
|
50
51
|
decode(input: _m0.Reader | Uint8Array, length?: number): Packet;
|
|
52
|
+
encodeTransform(source: AsyncIterable<Packet | Packet[]> | Iterable<Packet | Packet[]>): AsyncIterable<Uint8Array>;
|
|
53
|
+
decodeTransform(source: AsyncIterable<Uint8Array | Uint8Array[]> | Iterable<Uint8Array | Uint8Array[]>): AsyncIterable<Packet>;
|
|
51
54
|
fromJSON(object: any): Packet;
|
|
52
55
|
toJSON(message: Packet): unknown;
|
|
53
56
|
fromPartial<I extends {
|
|
@@ -91,7 +94,7 @@ export declare const Packet: {
|
|
|
91
94
|
rpcMethod?: string | undefined;
|
|
92
95
|
data?: Uint8Array | undefined;
|
|
93
96
|
dataIsZero?: boolean | undefined;
|
|
94
|
-
} & Record<Exclude<keyof I["body"]["callStart"], keyof
|
|
97
|
+
} & Record<Exclude<keyof I["body"]["callStart"], keyof CallStart1>, never>) | undefined;
|
|
95
98
|
$case: "callStart";
|
|
96
99
|
} & Record<Exclude<keyof I["body"], "callStart" | "$case">, never>) | ({
|
|
97
100
|
callData?: {
|
|
@@ -113,7 +116,7 @@ export declare const Packet: {
|
|
|
113
116
|
dataIsZero?: boolean | undefined;
|
|
114
117
|
complete?: boolean | undefined;
|
|
115
118
|
error?: string | undefined;
|
|
116
|
-
} & Record<Exclude<keyof I["body"]["callData"], keyof
|
|
119
|
+
} & Record<Exclude<keyof I["body"]["callData"], keyof CallData2>, never>) | undefined;
|
|
117
120
|
$case: "callData";
|
|
118
121
|
} & Record<Exclude<keyof I["body"], "callData" | "$case">, never>) | undefined;
|
|
119
122
|
} & Record<Exclude<keyof I, "body">, never>>(object: I): Packet;
|
|
@@ -121,6 +124,8 @@ export declare const Packet: {
|
|
|
121
124
|
export declare const CallStart: {
|
|
122
125
|
encode(message: CallStart, writer?: _m0.Writer): _m0.Writer;
|
|
123
126
|
decode(input: _m0.Reader | Uint8Array, length?: number): CallStart;
|
|
127
|
+
encodeTransform(source: AsyncIterable<CallStart | CallStart[]> | Iterable<CallStart | CallStart[]>): AsyncIterable<Uint8Array>;
|
|
128
|
+
decodeTransform(source: AsyncIterable<Uint8Array | Uint8Array[]> | Iterable<Uint8Array | Uint8Array[]>): AsyncIterable<CallStart>;
|
|
124
129
|
fromJSON(object: any): CallStart;
|
|
125
130
|
toJSON(message: CallStart): unknown;
|
|
126
131
|
fromPartial<I extends {
|
|
@@ -133,11 +138,13 @@ export declare const CallStart: {
|
|
|
133
138
|
rpcMethod?: string | undefined;
|
|
134
139
|
data?: Uint8Array | undefined;
|
|
135
140
|
dataIsZero?: boolean | undefined;
|
|
136
|
-
} & Record<Exclude<keyof I, keyof
|
|
141
|
+
} & Record<Exclude<keyof I, keyof CallStart1>, never>>(object: I): CallStart;
|
|
137
142
|
};
|
|
138
143
|
export declare const CallData: {
|
|
139
144
|
encode(message: CallData, writer?: _m0.Writer): _m0.Writer;
|
|
140
145
|
decode(input: _m0.Reader | Uint8Array, length?: number): CallData;
|
|
146
|
+
encodeTransform(source: AsyncIterable<CallData | CallData[]> | Iterable<CallData | CallData[]>): AsyncIterable<Uint8Array>;
|
|
147
|
+
decodeTransform(source: AsyncIterable<Uint8Array | Uint8Array[]> | Iterable<Uint8Array | Uint8Array[]>): AsyncIterable<CallData>;
|
|
141
148
|
fromJSON(object: any): CallData;
|
|
142
149
|
toJSON(message: CallData): unknown;
|
|
143
150
|
fromPartial<I extends {
|
|
@@ -150,7 +157,7 @@ export declare const CallData: {
|
|
|
150
157
|
dataIsZero?: boolean | undefined;
|
|
151
158
|
complete?: boolean | undefined;
|
|
152
159
|
error?: string | undefined;
|
|
153
|
-
} & Record<Exclude<keyof I, keyof
|
|
160
|
+
} & Record<Exclude<keyof I, keyof CallData2>, never>>(object: I): CallData;
|
|
154
161
|
};
|
|
155
162
|
declare type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
156
163
|
export declare type DeepPartial<T> = T extends Builtin ? T : T extends Long ? string | number | Long : T extends Array<infer U> ? Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {
|
package/dist/srpc/rpcproto.pb.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import Long from 'long';
|
|
3
3
|
import * as _m0 from 'protobufjs/minimal';
|
|
4
|
+
import { CallStart as CallStart1, CallData as CallData2, } from './rpcproto.pb.js';
|
|
4
5
|
export const protobufPackage = 'srpc';
|
|
5
6
|
function createBasePacket() {
|
|
6
7
|
return { body: undefined };
|
|
@@ -8,10 +9,10 @@ function createBasePacket() {
|
|
|
8
9
|
export const Packet = {
|
|
9
10
|
encode(message, writer = _m0.Writer.create()) {
|
|
10
11
|
if (message.body?.$case === 'callStart') {
|
|
11
|
-
|
|
12
|
+
CallStart1.encode(message.body.callStart, writer.uint32(10).fork()).ldelim();
|
|
12
13
|
}
|
|
13
14
|
if (message.body?.$case === 'callData') {
|
|
14
|
-
|
|
15
|
+
CallData2.encode(message.body.callData, writer.uint32(18).fork()).ldelim();
|
|
15
16
|
}
|
|
16
17
|
return writer;
|
|
17
18
|
},
|
|
@@ -25,13 +26,13 @@ export const Packet = {
|
|
|
25
26
|
case 1:
|
|
26
27
|
message.body = {
|
|
27
28
|
$case: 'callStart',
|
|
28
|
-
callStart:
|
|
29
|
+
callStart: CallStart1.decode(reader, reader.uint32()),
|
|
29
30
|
};
|
|
30
31
|
break;
|
|
31
32
|
case 2:
|
|
32
33
|
message.body = {
|
|
33
34
|
$case: 'callData',
|
|
34
|
-
callData:
|
|
35
|
+
callData: CallData2.decode(reader, reader.uint32()),
|
|
35
36
|
};
|
|
36
37
|
break;
|
|
37
38
|
default:
|
|
@@ -41,15 +42,43 @@ export const Packet = {
|
|
|
41
42
|
}
|
|
42
43
|
return message;
|
|
43
44
|
},
|
|
45
|
+
// encodeTransform encodes a source of message objects.
|
|
46
|
+
// Transform<Packet, Uint8Array>
|
|
47
|
+
async *encodeTransform(source) {
|
|
48
|
+
for await (const pkt of source) {
|
|
49
|
+
if (Array.isArray(pkt)) {
|
|
50
|
+
for (const p of pkt) {
|
|
51
|
+
yield* [Packet.encode(p).finish()];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
yield* [Packet.encode(pkt).finish()];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
// decodeTransform decodes a source of encoded messages.
|
|
60
|
+
// Transform<Uint8Array, Packet>
|
|
61
|
+
async *decodeTransform(source) {
|
|
62
|
+
for await (const pkt of source) {
|
|
63
|
+
if (Array.isArray(pkt)) {
|
|
64
|
+
for (const p of pkt) {
|
|
65
|
+
yield* [Packet.decode(p)];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
yield* [Packet.decode(pkt)];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
44
73
|
fromJSON(object) {
|
|
45
74
|
return {
|
|
46
75
|
body: isSet(object.callStart)
|
|
47
76
|
? {
|
|
48
77
|
$case: 'callStart',
|
|
49
|
-
callStart:
|
|
78
|
+
callStart: CallStart1.fromJSON(object.callStart),
|
|
50
79
|
}
|
|
51
80
|
: isSet(object.callData)
|
|
52
|
-
? { $case: 'callData', callData:
|
|
81
|
+
? { $case: 'callData', callData: CallData2.fromJSON(object.callData) }
|
|
53
82
|
: undefined,
|
|
54
83
|
};
|
|
55
84
|
},
|
|
@@ -57,11 +86,11 @@ export const Packet = {
|
|
|
57
86
|
const obj = {};
|
|
58
87
|
message.body?.$case === 'callStart' &&
|
|
59
88
|
(obj.callStart = message.body?.callStart
|
|
60
|
-
?
|
|
89
|
+
? CallStart1.toJSON(message.body?.callStart)
|
|
61
90
|
: undefined);
|
|
62
91
|
message.body?.$case === 'callData' &&
|
|
63
92
|
(obj.callData = message.body?.callData
|
|
64
|
-
?
|
|
93
|
+
? CallData2.toJSON(message.body?.callData)
|
|
65
94
|
: undefined);
|
|
66
95
|
return obj;
|
|
67
96
|
},
|
|
@@ -72,7 +101,7 @@ export const Packet = {
|
|
|
72
101
|
object.body?.callStart !== null) {
|
|
73
102
|
message.body = {
|
|
74
103
|
$case: 'callStart',
|
|
75
|
-
callStart:
|
|
104
|
+
callStart: CallStart1.fromPartial(object.body.callStart),
|
|
76
105
|
};
|
|
77
106
|
}
|
|
78
107
|
if (object.body?.$case === 'callData' &&
|
|
@@ -80,7 +109,7 @@ export const Packet = {
|
|
|
80
109
|
object.body?.callData !== null) {
|
|
81
110
|
message.body = {
|
|
82
111
|
$case: 'callData',
|
|
83
|
-
callData:
|
|
112
|
+
callData: CallData2.fromPartial(object.body.callData),
|
|
84
113
|
};
|
|
85
114
|
}
|
|
86
115
|
return message;
|
|
@@ -136,6 +165,34 @@ export const CallStart = {
|
|
|
136
165
|
}
|
|
137
166
|
return message;
|
|
138
167
|
},
|
|
168
|
+
// encodeTransform encodes a source of message objects.
|
|
169
|
+
// Transform<CallStart, Uint8Array>
|
|
170
|
+
async *encodeTransform(source) {
|
|
171
|
+
for await (const pkt of source) {
|
|
172
|
+
if (Array.isArray(pkt)) {
|
|
173
|
+
for (const p of pkt) {
|
|
174
|
+
yield* [CallStart.encode(p).finish()];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
yield* [CallStart.encode(pkt).finish()];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
// decodeTransform decodes a source of encoded messages.
|
|
183
|
+
// Transform<Uint8Array, CallStart>
|
|
184
|
+
async *decodeTransform(source) {
|
|
185
|
+
for await (const pkt of source) {
|
|
186
|
+
if (Array.isArray(pkt)) {
|
|
187
|
+
for (const p of pkt) {
|
|
188
|
+
yield* [CallStart.decode(p)];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
yield* [CallStart.decode(pkt)];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
139
196
|
fromJSON(object) {
|
|
140
197
|
return {
|
|
141
198
|
rpcService: isSet(object.rpcService) ? String(object.rpcService) : '',
|
|
@@ -214,6 +271,34 @@ export const CallData = {
|
|
|
214
271
|
}
|
|
215
272
|
return message;
|
|
216
273
|
},
|
|
274
|
+
// encodeTransform encodes a source of message objects.
|
|
275
|
+
// Transform<CallData, Uint8Array>
|
|
276
|
+
async *encodeTransform(source) {
|
|
277
|
+
for await (const pkt of source) {
|
|
278
|
+
if (Array.isArray(pkt)) {
|
|
279
|
+
for (const p of pkt) {
|
|
280
|
+
yield* [CallData.encode(p).finish()];
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
yield* [CallData.encode(pkt).finish()];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
// decodeTransform decodes a source of encoded messages.
|
|
289
|
+
// Transform<Uint8Array, CallData>
|
|
290
|
+
async *decodeTransform(source) {
|
|
291
|
+
for await (const pkt of source) {
|
|
292
|
+
if (Array.isArray(pkt)) {
|
|
293
|
+
for (const p of pkt) {
|
|
294
|
+
yield* [CallData.decode(p)];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
yield* [CallData.decode(pkt)];
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
},
|
|
217
302
|
fromJSON(object) {
|
|
218
303
|
return {
|
|
219
304
|
data: isSet(object.data)
|
package/dist/srpc/server.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export declare class Server implements StreamHandler {
|
|
|
10
10
|
startRpc(): ServerRPC;
|
|
11
11
|
handleStream(stream: Stream): ServerRPC;
|
|
12
12
|
handleDuplex(stream: Duplex<Uint8Array>): ServerRPC;
|
|
13
|
+
handlePacketDuplex(stream: Duplex<Uint8Array>): ServerRPC;
|
|
13
14
|
handlePacketStream(stream: Duplex<Packet>): ServerRPC;
|
|
14
15
|
}
|
package/dist/srpc/server.js
CHANGED
|
@@ -21,6 +21,13 @@ export class Server {
|
|
|
21
21
|
pipe(stream, parseLengthPrefixTransform(), decodePacketSource, rpc, encodePacketSource, prependLengthPrefixTransform(), stream);
|
|
22
22
|
return rpc;
|
|
23
23
|
}
|
|
24
|
+
// handlePacketDuplex handles an incoming Uint8Array duplex.
|
|
25
|
+
// skips the packet length prefix transform.
|
|
26
|
+
handlePacketDuplex(stream) {
|
|
27
|
+
const rpc = this.startRpc();
|
|
28
|
+
pipe(stream, decodePacketSource, rpc, encodePacketSource, stream);
|
|
29
|
+
return rpc;
|
|
30
|
+
}
|
|
24
31
|
// handlePacketStream handles an incoming Packet duplex.
|
|
25
32
|
handlePacketStream(stream) {
|
|
26
33
|
const rpc = this.startRpc();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Observable } from 'rxjs';
|
|
2
1
|
export interface TsProtoRpc {
|
|
3
2
|
request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
|
|
4
|
-
clientStreamingRequest(service: string, method: string, data:
|
|
5
|
-
serverStreamingRequest(service: string, method: string, data: Uint8Array):
|
|
6
|
-
bidirectionalStreamingRequest(service: string, method: string, data:
|
|
3
|
+
clientStreamingRequest(service: string, method: string, data: AsyncIterable<Uint8Array>): Promise<Uint8Array>;
|
|
4
|
+
serverStreamingRequest(service: string, method: string, data: Uint8Array): AsyncIterable<Uint8Array>;
|
|
5
|
+
bidirectionalStreamingRequest(service: string, method: string, data: AsyncIterable<Uint8Array>): AsyncIterable<Uint8Array>;
|
|
7
6
|
}
|
package/e2e/e2e.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { pipe } from 'it-pipe'
|
|
2
2
|
import { createHandler, createMux, Server, Client, Conn } from '../srpc'
|
|
3
3
|
import { EchoerDefinition, EchoerServer, runClientTest } from '../echo'
|
|
4
|
+
import { runRpcStreamTest } from '../echo/client-test'
|
|
4
5
|
|
|
5
6
|
async function runRPC() {
|
|
6
7
|
const mux = createMux()
|
|
7
|
-
const echoer = new EchoerServer()
|
|
8
|
-
mux.register(createHandler(EchoerDefinition, echoer))
|
|
9
8
|
const server = new Server(mux)
|
|
9
|
+
const echoer = new EchoerServer(server)
|
|
10
|
+
mux.register(createHandler(EchoerDefinition, echoer))
|
|
10
11
|
|
|
11
12
|
const clientConn = new Conn()
|
|
12
13
|
const serverConn = new Conn(server)
|
|
13
14
|
pipe(clientConn, serverConn, clientConn)
|
|
14
15
|
const client = new Client(clientConn.buildOpenStreamFunc())
|
|
15
16
|
|
|
17
|
+
await runRpcStreamTest(client)
|
|
16
18
|
await runClientTest(client)
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -21,7 +23,6 @@ runRPC()
|
|
|
21
23
|
console.log('finished successfully')
|
|
22
24
|
})
|
|
23
25
|
.catch((err) => {
|
|
24
|
-
console.log('failed')
|
|
25
26
|
console.error(err)
|
|
26
27
|
process.exit(1)
|
|
27
28
|
})
|
package/e2e/e2e_test.go
CHANGED
|
@@ -8,6 +8,7 @@ import (
|
|
|
8
8
|
"time"
|
|
9
9
|
|
|
10
10
|
"github.com/aperturerobotics/starpc/echo"
|
|
11
|
+
"github.com/aperturerobotics/starpc/rpcstream"
|
|
11
12
|
"github.com/aperturerobotics/starpc/srpc"
|
|
12
13
|
"github.com/libp2p/go-libp2p/p2p/muxer/mplex"
|
|
13
14
|
mp "github.com/libp2p/go-mplex"
|
|
@@ -17,8 +18,8 @@ import (
|
|
|
17
18
|
// RunE2E runs an end to end test with a callback.
|
|
18
19
|
func RunE2E(t *testing.T, cb func(client echo.SRPCEchoerClient) error) {
|
|
19
20
|
// construct the server
|
|
20
|
-
echoServer := &echo.EchoServer{}
|
|
21
21
|
mux := srpc.NewMux()
|
|
22
|
+
echoServer := echo.NewEchoServer(mux)
|
|
22
23
|
if err := echo.SRPCRegisterEchoer(mux, echoServer); err != nil {
|
|
23
24
|
t.Fatal(err.Error())
|
|
24
25
|
}
|
|
@@ -179,3 +180,25 @@ func TestE2E_BidiStream(t *testing.T) {
|
|
|
179
180
|
return strm.Close()
|
|
180
181
|
})
|
|
181
182
|
}
|
|
183
|
+
|
|
184
|
+
func TestE2E_RpcStream(t *testing.T) {
|
|
185
|
+
ctx := context.Background()
|
|
186
|
+
RunE2E(t, func(client echo.SRPCEchoerClient) error {
|
|
187
|
+
openStreamFn := rpcstream.NewRpcStreamOpenStream(func(ctx context.Context) (rpcstream.RpcStream, error) {
|
|
188
|
+
return client.RpcStream(ctx)
|
|
189
|
+
}, "test")
|
|
190
|
+
proxiedClient := srpc.NewClient(openStreamFn)
|
|
191
|
+
proxiedSvc := echo.NewSRPCEchoerClient(proxiedClient)
|
|
192
|
+
|
|
193
|
+
// run a RPC proxied over another RPC
|
|
194
|
+
resp, err := proxiedSvc.Echo(ctx, &echo.EchoMsg{Body: "hello world"})
|
|
195
|
+
if err != nil {
|
|
196
|
+
return err
|
|
197
|
+
}
|
|
198
|
+
if resp.GetBody() != "hello world" {
|
|
199
|
+
return errors.Errorf("response body incorrect: %q", resp.GetBody())
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return nil
|
|
203
|
+
})
|
|
204
|
+
}
|
package/echo/client-test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Client } from '../srpc/index.js'
|
|
2
2
|
import { EchoerClientImpl, EchoMsg } from './echo.pb.js'
|
|
3
|
-
import {
|
|
3
|
+
import { pushable } from 'it-pushable'
|
|
4
|
+
import { buildRpcStreamOpenStream } from '../rpcstream/rpcstream.js'
|
|
4
5
|
|
|
5
6
|
export async function runClientTest(client: Client) {
|
|
6
7
|
const demoServiceClient = new EchoerClientImpl(client)
|
|
@@ -12,10 +13,9 @@ export async function runClientTest(client: Client) {
|
|
|
12
13
|
console.log('success: output', result.body)
|
|
13
14
|
|
|
14
15
|
// observable for client requests
|
|
15
|
-
const clientRequestStream =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
})
|
|
16
|
+
const clientRequestStream = pushable<EchoMsg>({ objectMode: true })
|
|
17
|
+
clientRequestStream.push({ body: 'Hello world from streaming request.' })
|
|
18
|
+
clientRequestStream.end()
|
|
19
19
|
|
|
20
20
|
console.log('Calling EchoClientStream: client -> server...')
|
|
21
21
|
result = await demoServiceClient.EchoClientStream(clientRequestStream)
|
|
@@ -25,17 +25,22 @@ export async function runClientTest(client: Client) {
|
|
|
25
25
|
const serverStream = demoServiceClient.EchoServerStream({
|
|
26
26
|
body: 'Hello world from server to client streaming request.',
|
|
27
27
|
})
|
|
28
|
-
await
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
for await (const msg of serverStream) {
|
|
29
|
+
console.log('server: output', msg.body)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// runRpcStreamTest tests a RPCStream.
|
|
34
|
+
export async function runRpcStreamTest(client: Client) {
|
|
35
|
+
console.log('Calling RpcStream to open a RPC stream client...')
|
|
36
|
+
const service = new EchoerClientImpl(client)
|
|
37
|
+
const openStreamFn = buildRpcStreamOpenStream(
|
|
38
|
+
'test',
|
|
39
|
+
service.RpcStream.bind(service)
|
|
40
|
+
)
|
|
41
|
+
const proxiedClient = new Client(openStreamFn)
|
|
42
|
+
const proxiedService = new EchoerClientImpl(proxiedClient)
|
|
43
|
+
console.log('Calling Echo via RPC stream...')
|
|
44
|
+
const resp = await proxiedService.Echo({ body: 'hello world via proxy' })
|
|
45
|
+
console.log('rpc stream test: succeeded: response: ' + resp.body)
|
|
41
46
|
}
|