starpc 0.10.9 → 0.11.2

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.
@@ -34,7 +34,8 @@ export interface Echoer {
34
34
  }
35
35
  export declare class EchoerClientImpl implements Echoer {
36
36
  private readonly rpc;
37
- constructor(rpc: Rpc);
37
+ private readonly service;
38
+ constructor(rpc: Rpc, service?: string);
38
39
  Echo(request: EchoMsg): Promise<EchoMsg>;
39
40
  EchoServerStream(request: EchoMsg): AsyncIterable<EchoMsg>;
40
41
  EchoClientStream(request: AsyncIterable<EchoMsg>): Promise<EchoMsg>;
@@ -73,7 +73,8 @@ export const EchoMsg = {
73
73
  },
74
74
  };
75
75
  export class EchoerClientImpl {
76
- constructor(rpc) {
76
+ constructor(rpc, service) {
77
+ this.service = service || "echo.Echoer";
77
78
  this.rpc = rpc;
78
79
  this.Echo = this.Echo.bind(this);
79
80
  this.EchoServerStream = this.EchoServerStream.bind(this);
@@ -83,27 +84,27 @@ export class EchoerClientImpl {
83
84
  }
84
85
  Echo(request) {
85
86
  const data = EchoMsg.encode(request).finish();
86
- const promise = this.rpc.request("echo.Echoer", "Echo", data);
87
+ const promise = this.rpc.request(this.service, "Echo", data);
87
88
  return promise.then((data) => EchoMsg.decode(new _m0.Reader(data)));
88
89
  }
89
90
  EchoServerStream(request) {
90
91
  const data = EchoMsg.encode(request).finish();
91
- const result = this.rpc.serverStreamingRequest("echo.Echoer", "EchoServerStream", data);
92
+ const result = this.rpc.serverStreamingRequest(this.service, "EchoServerStream", data);
92
93
  return EchoMsg.decodeTransform(result);
93
94
  }
94
95
  EchoClientStream(request) {
95
96
  const data = EchoMsg.encodeTransform(request);
96
- const promise = this.rpc.clientStreamingRequest("echo.Echoer", "EchoClientStream", data);
97
+ const promise = this.rpc.clientStreamingRequest(this.service, "EchoClientStream", data);
97
98
  return promise.then((data) => EchoMsg.decode(new _m0.Reader(data)));
98
99
  }
99
100
  EchoBidiStream(request) {
100
101
  const data = EchoMsg.encodeTransform(request);
101
- const result = this.rpc.bidirectionalStreamingRequest("echo.Echoer", "EchoBidiStream", data);
102
+ const result = this.rpc.bidirectionalStreamingRequest(this.service, "EchoBidiStream", data);
102
103
  return EchoMsg.decodeTransform(result);
103
104
  }
104
105
  RpcStream(request) {
105
106
  const data = RpcStreamPacket.encodeTransform(request);
106
- const result = this.rpc.bidirectionalStreamingRequest("echo.Echoer", "RpcStream", data);
107
+ const result = this.rpc.bidirectionalStreamingRequest(this.service, "RpcStream", data);
107
108
  return RpcStreamPacket.decodeTransform(result);
108
109
  }
109
110
  }
@@ -32,7 +32,7 @@ export class EchoerServer {
32
32
  return result;
33
33
  }
34
34
  RpcStream(request) {
35
- return handleRpcStream(request[Symbol.asyncIterator](), async (_componentId) => {
35
+ return handleRpcStream(request[Symbol.asyncIterator](), async () => {
36
36
  if (!this.proxyServer) {
37
37
  throw new Error('rpc stream proxy server not set');
38
38
  }
package/dist/srpc/conn.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { pipe } from 'it-pipe';
2
2
  import { Mplex } from '@libp2p/mplex';
3
+ import isPromise from 'is-promise';
3
4
  import { Client } from './client.js';
4
5
  import { combineUint8ArrayListTransform } from './array-list.js';
5
6
  // streamToSRPCStream converts a Stream to a SRPCStream.
@@ -46,6 +47,9 @@ export class Conn {
46
47
  // openStream implements the client open stream function.
47
48
  async openStream() {
48
49
  const stream = this.muxer.newStream();
50
+ if (isPromise(stream)) {
51
+ return streamToSRPCStream(await stream);
52
+ }
49
53
  return streamToSRPCStream(stream);
50
54
  }
51
55
  // buildOpenStreamFunc returns openStream bound to this conn.
@@ -19,5 +19,5 @@ export declare class StaticHandler implements Handler {
19
19
  }
20
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
21
  export declare function createInvokeFn<R, O>(methodInfo: MethodDefinition<R, O>, methodProto: MethodProto<R, O>): InvokeFn;
22
- export declare function createHandler(definition: Definition, impl: any): Handler;
22
+ export declare function createHandler(definition: Definition, impl: any, serviceID?: string): Handler;
23
23
  export {};
@@ -89,7 +89,11 @@ export function createInvokeFn(methodInfo, methodProto) {
89
89
  };
90
90
  }
91
91
  // createHandler creates a handler from a definition and an implementation.
92
- export function createHandler(definition, impl) {
92
+ // if serviceID is not set, uses the fullName of the service as the identifier.
93
+ export function createHandler(definition, impl, serviceID) {
94
+ // serviceID defaults to the full name of the service from Protobuf.
95
+ serviceID = serviceID || definition.fullName;
96
+ // build map of method ID -> method prototype.
93
97
  const methodMap = {};
94
98
  for (const methodInfo of Object.values(definition.methods)) {
95
99
  const methodName = methodInfo.name;
@@ -100,5 +104,5 @@ export function createHandler(definition, impl) {
100
104
  methodProto = methodProto.bind(impl);
101
105
  methodMap[methodName] = createInvokeFn(methodInfo, methodProto);
102
106
  }
103
- return new StaticHandler(definition.fullName, methodMap);
107
+ return new StaticHandler(serviceID, methodMap);
104
108
  }
package/echo/echo.pb.ts CHANGED
@@ -105,7 +105,9 @@ export interface Echoer {
105
105
 
106
106
  export class EchoerClientImpl implements Echoer {
107
107
  private readonly rpc: Rpc;
108
- constructor(rpc: Rpc) {
108
+ private readonly service: string;
109
+ constructor(rpc: Rpc, service?: string) {
110
+ this.service = service || "echo.Echoer";
109
111
  this.rpc = rpc;
110
112
  this.Echo = this.Echo.bind(this);
111
113
  this.EchoServerStream = this.EchoServerStream.bind(this);
@@ -115,31 +117,31 @@ export class EchoerClientImpl implements Echoer {
115
117
  }
116
118
  Echo(request: EchoMsg): Promise<EchoMsg> {
117
119
  const data = EchoMsg.encode(request).finish();
118
- const promise = this.rpc.request("echo.Echoer", "Echo", data);
120
+ const promise = this.rpc.request(this.service, "Echo", data);
119
121
  return promise.then((data) => EchoMsg.decode(new _m0.Reader(data)));
120
122
  }
121
123
 
122
124
  EchoServerStream(request: EchoMsg): AsyncIterable<EchoMsg> {
123
125
  const data = EchoMsg.encode(request).finish();
124
- const result = this.rpc.serverStreamingRequest("echo.Echoer", "EchoServerStream", data);
126
+ const result = this.rpc.serverStreamingRequest(this.service, "EchoServerStream", data);
125
127
  return EchoMsg.decodeTransform(result);
126
128
  }
127
129
 
128
130
  EchoClientStream(request: AsyncIterable<EchoMsg>): Promise<EchoMsg> {
129
131
  const data = EchoMsg.encodeTransform(request);
130
- const promise = this.rpc.clientStreamingRequest("echo.Echoer", "EchoClientStream", data);
132
+ const promise = this.rpc.clientStreamingRequest(this.service, "EchoClientStream", data);
131
133
  return promise.then((data) => EchoMsg.decode(new _m0.Reader(data)));
132
134
  }
133
135
 
134
136
  EchoBidiStream(request: AsyncIterable<EchoMsg>): AsyncIterable<EchoMsg> {
135
137
  const data = EchoMsg.encodeTransform(request);
136
- const result = this.rpc.bidirectionalStreamingRequest("echo.Echoer", "EchoBidiStream", data);
138
+ const result = this.rpc.bidirectionalStreamingRequest(this.service, "EchoBidiStream", data);
137
139
  return EchoMsg.decodeTransform(result);
138
140
  }
139
141
 
140
142
  RpcStream(request: AsyncIterable<RpcStreamPacket>): AsyncIterable<RpcStreamPacket> {
141
143
  const data = RpcStreamPacket.encodeTransform(request);
142
- const result = this.rpc.bidirectionalStreamingRequest("echo.Echoer", "RpcStream", data);
144
+ const result = this.rpc.bidirectionalStreamingRequest(this.service, "RpcStream", data);
143
145
  return RpcStreamPacket.decodeTransform(result);
144
146
  }
145
147
  }
@@ -22,18 +22,26 @@ type SRPCEchoerClient interface {
22
22
  }
23
23
 
24
24
  type srpcEchoerClient struct {
25
- cc srpc.Client
25
+ cc srpc.Client
26
+ serviceID string
26
27
  }
27
28
 
28
29
  func NewSRPCEchoerClient(cc srpc.Client) SRPCEchoerClient {
29
- return &srpcEchoerClient{cc}
30
+ return &srpcEchoerClient{cc: cc, serviceID: SRPCEchoerServiceID}
31
+ }
32
+
33
+ func NewSRPCEchoerClientWithServiceID(cc srpc.Client, serviceID string) SRPCEchoerClient {
34
+ if serviceID == "" {
35
+ serviceID = SRPCEchoerServiceID
36
+ }
37
+ return &srpcEchoerClient{cc: cc, serviceID: serviceID}
30
38
  }
31
39
 
32
40
  func (c *srpcEchoerClient) SRPCClient() srpc.Client { return c.cc }
33
41
 
34
42
  func (c *srpcEchoerClient) Echo(ctx context.Context, in *EchoMsg) (*EchoMsg, error) {
35
43
  out := new(EchoMsg)
36
- err := c.cc.Invoke(ctx, "echo.Echoer", "Echo", in, out)
44
+ err := c.cc.Invoke(ctx, c.serviceID, "Echo", in, out)
37
45
  if err != nil {
38
46
  return nil, err
39
47
  }
@@ -41,7 +49,7 @@ func (c *srpcEchoerClient) Echo(ctx context.Context, in *EchoMsg) (*EchoMsg, err
41
49
  }
42
50
 
43
51
  func (c *srpcEchoerClient) EchoServerStream(ctx context.Context, in *EchoMsg) (SRPCEchoer_EchoServerStreamClient, error) {
44
- stream, err := c.cc.NewStream(ctx, "echo.Echoer", "EchoServerStream", in)
52
+ stream, err := c.cc.NewStream(ctx, c.serviceID, "EchoServerStream", in)
45
53
  if err != nil {
46
54
  return nil, err
47
55
  }
@@ -75,7 +83,7 @@ func (x *srpcEchoer_EchoServerStreamClient) RecvTo(m *EchoMsg) error {
75
83
  }
76
84
 
77
85
  func (c *srpcEchoerClient) EchoClientStream(ctx context.Context) (SRPCEchoer_EchoClientStreamClient, error) {
78
- stream, err := c.cc.NewStream(ctx, "echo.Echoer", "EchoClientStream", nil)
86
+ stream, err := c.cc.NewStream(ctx, c.serviceID, "EchoClientStream", nil)
79
87
  if err != nil {
80
88
  return nil, err
81
89
  }
@@ -116,7 +124,7 @@ func (x *srpcEchoer_EchoClientStreamClient) CloseAndMsgRecv(m *EchoMsg) error {
116
124
  }
117
125
 
118
126
  func (c *srpcEchoerClient) EchoBidiStream(ctx context.Context) (SRPCEchoer_EchoBidiStreamClient, error) {
119
- stream, err := c.cc.NewStream(ctx, "echo.Echoer", "EchoBidiStream", nil)
127
+ stream, err := c.cc.NewStream(ctx, c.serviceID, "EchoBidiStream", nil)
120
128
  if err != nil {
121
129
  return nil, err
122
130
  }
@@ -152,7 +160,7 @@ func (x *srpcEchoer_EchoBidiStreamClient) RecvTo(m *EchoMsg) error {
152
160
  }
153
161
 
154
162
  func (c *srpcEchoerClient) RpcStream(ctx context.Context) (SRPCEchoer_RpcStreamClient, error) {
155
- stream, err := c.cc.NewStream(ctx, "echo.Echoer", "RpcStream", nil)
163
+ stream, err := c.cc.NewStream(ctx, c.serviceID, "RpcStream", nil)
156
164
  if err != nil {
157
165
  return nil, err
158
166
  }
@@ -220,10 +228,26 @@ func (s *SRPCEchoerUnimplementedServer) RpcStream(SRPCEchoer_RpcStreamStream) er
220
228
  const SRPCEchoerServiceID = "echo.Echoer"
221
229
 
222
230
  type SRPCEchoerHandler struct {
223
- impl SRPCEchoerServer
231
+ serviceID string
232
+ impl SRPCEchoerServer
233
+ }
234
+
235
+ // NewSRPCEchoerHandler constructs a new RPC handler.
236
+ // serviceID: if empty, uses default: echo.Echoer
237
+ func NewSRPCEchoerHandler(impl SRPCEchoerServer, serviceID string) srpc.Handler {
238
+ if serviceID == "" {
239
+ serviceID = SRPCEchoerServiceID
240
+ }
241
+ return &SRPCEchoerHandler{impl: impl, serviceID: serviceID}
242
+ }
243
+
244
+ // SRPCRegisterEchoer registers the implementation with the mux.
245
+ // Uses the default serviceID: echo.Echoer
246
+ func SRPCRegisterEchoer(mux srpc.Mux, impl SRPCEchoerServer) error {
247
+ return mux.Register(NewSRPCEchoerHandler(impl, ""))
224
248
  }
225
249
 
226
- func (SRPCEchoerHandler) GetServiceID() string { return SRPCEchoerServiceID }
250
+ func (d *SRPCEchoerHandler) GetServiceID() string { return d.serviceID }
227
251
 
228
252
  func (SRPCEchoerHandler) GetMethodIDs() []string {
229
253
  return []string{
@@ -295,14 +319,6 @@ func (SRPCEchoerHandler) InvokeMethod_RpcStream(impl SRPCEchoerServer, strm srpc
295
319
  return impl.RpcStream(clientStrm)
296
320
  }
297
321
 
298
- func NewSRPCEchoerHandler(impl SRPCEchoerServer) srpc.Handler {
299
- return &SRPCEchoerHandler{impl: impl}
300
- }
301
-
302
- func SRPCRegisterEchoer(mux srpc.Mux, impl SRPCEchoerServer) error {
303
- return mux.Register(&SRPCEchoerHandler{impl: impl})
304
- }
305
-
306
322
  type SRPCEchoer_EchoStream interface {
307
323
  srpc.Stream
308
324
  SendAndClose(*EchoMsg) error
package/echo/server.ts CHANGED
@@ -52,7 +52,7 @@ export class EchoerServer implements Echoer {
52
52
  ): AsyncIterable<RpcStreamPacket> {
53
53
  return handleRpcStream(
54
54
  request[Symbol.asyncIterator](),
55
- async (_componentId: string): Promise<RpcStreamHandler> => {
55
+ async (): Promise<RpcStreamHandler> => {
56
56
  if (!this.proxyServer) {
57
57
  throw new Error('rpc stream proxy server not set')
58
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starpc",
3
- "version": "0.10.9",
3
+ "version": "0.11.2",
4
4
  "description": "Streaming protobuf RPC service protocol over any two-way channel.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -59,24 +59,25 @@
59
59
  "singleQuote": true
60
60
  },
61
61
  "devDependencies": {
62
- "@typescript-eslint/eslint-plugin": "^5.36.2",
63
- "@typescript-eslint/parser": "^5.36.2",
62
+ "@typescript-eslint/eslint-plugin": "^5.40.0",
63
+ "@typescript-eslint/parser": "^5.40.0",
64
64
  "bufferutil": "^4.0.6",
65
65
  "depcheck": "^1.4.3",
66
- "esbuild": "^0.15.7",
67
- "eslint": "^8.23.0",
66
+ "esbuild": "^0.15.10",
67
+ "eslint": "^8.25.0",
68
68
  "eslint-config-prettier": "^8.5.0",
69
69
  "prettier": "^2.7.1",
70
70
  "rimraf": "^3.0.2",
71
- "ts-proto": "^1.125.0",
72
- "typescript": "^4.8.2",
71
+ "ts-proto": "^1.126.1",
72
+ "typescript": "^4.8.4",
73
73
  "utf-8-validate": "^5.0.9"
74
74
  },
75
75
  "dependencies": {
76
- "@libp2p/interface-connection": "^3.0.1",
77
- "@libp2p/interface-stream-muxer": "^2.0.2",
78
- "@libp2p/mplex": "^5.1.1",
76
+ "@libp2p/interface-connection": "^3.0.2",
77
+ "@libp2p/interface-stream-muxer": "^3.0.0",
78
+ "@libp2p/mplex": "^6.0.2",
79
79
  "event-iterator": "^2.0.0",
80
+ "is-promise": "^4.0.0",
80
81
  "isomorphic-ws": "^5.0.0",
81
82
  "it-first": "^1.0.7",
82
83
  "it-length-prefixed": "^8.0.2",
@@ -86,8 +87,8 @@
86
87
  "it-ws": "^5.0.2",
87
88
  "long": "^5.2.0",
88
89
  "patch-package": "^6.4.7",
89
- "protobufjs": "^7.1.0",
90
+ "protobufjs": "^7.1.2",
90
91
  "uint8arraylist": "^2.3.2",
91
- "ws": "^8.8.1"
92
+ "ws": "^8.9.0"
92
93
  }
93
94
  }
@@ -0,0 +1,25 @@
1
+ diff --git a/node_modules/ts-proto/build/generate-services.js b/node_modules/ts-proto/build/generate-services.js
2
+ index 8ae7981..5ab6bf6 100644
3
+ --- a/node_modules/ts-proto/build/generate-services.js
4
+ +++ b/node_modules/ts-proto/build/generate-services.js
5
+ @@ -129,7 +129,7 @@ function generateRegularRpcMethod(ctx, fileDesc, serviceDesc, methodDesc) {
6
+ const data = ${encode};
7
+ const ${returnVariable} = this.rpc.${rpcMethod}(
8
+ ${maybeCtx}
9
+ - "${(0, utils_1.maybePrefixPackage)(fileDesc, serviceDesc.name)}",
10
+ + this.service,
11
+ "${methodDesc.name}",
12
+ data
13
+ );
14
+ @@ -148,7 +148,10 @@ function generateServiceClientImpl(ctx, fileDesc, serviceDesc) {
15
+ // Create the constructor(rpc: Rpc)
16
+ const rpcType = options.context ? "Rpc<Context>" : "Rpc";
17
+ chunks.push((0, ts_poet_1.code) `private readonly rpc: ${rpcType};`);
18
+ - chunks.push((0, ts_poet_1.code) `constructor(rpc: ${rpcType}) {`);
19
+ + chunks.push((0, ts_poet_1.code) `private readonly service: string;`);
20
+ + chunks.push((0, ts_poet_1.code) `constructor(rpc: ${rpcType}, service?: string) {`);
21
+ + const serviceID = (0, utils_1.maybePrefixPackage)(fileDesc, serviceDesc.name);
22
+ + chunks.push((0, ts_poet_1.code) `this.service = service || "${serviceID}";`);
23
+ chunks.push((0, ts_poet_1.code) `this.rpc = rpc;`);
24
+ // Bind each FooService method to the FooServiceImpl class
25
+ for (const methodDesc of serviceDesc.method) {
package/srpc/conn.ts CHANGED
@@ -7,6 +7,7 @@ import { pipe } from 'it-pipe'
7
7
  import type { Duplex } from 'it-stream-types'
8
8
  import { Mplex } from '@libp2p/mplex'
9
9
  import { Uint8ArrayList } from 'uint8arraylist'
10
+ import isPromise from 'is-promise'
10
11
 
11
12
  import type { OpenStreamFunc, Stream as SRPCStream } from './stream.js'
12
13
  import { Client } from './client.js'
@@ -29,7 +30,9 @@ export interface StreamHandler {
29
30
  }
30
31
 
31
32
  // streamToSRPCStream converts a Stream to a SRPCStream.
32
- export function streamToSRPCStream(stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>): SRPCStream {
33
+ export function streamToSRPCStream(
34
+ stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>
35
+ ): SRPCStream {
33
36
  return {
34
37
  source: pipe(stream, combineUint8ArrayListTransform()),
35
38
  sink: stream.sink,
@@ -83,6 +86,9 @@ export class Conn implements Duplex<Uint8Array> {
83
86
  // openStream implements the client open stream function.
84
87
  public async openStream(): Promise<SRPCStream> {
85
88
  const stream = this.muxer.newStream()
89
+ if (isPromise(stream)) {
90
+ return streamToSRPCStream(await stream)
91
+ }
86
92
  return streamToSRPCStream(stream)
87
93
  }
88
94
 
@@ -7,6 +7,7 @@ export interface Definition {
7
7
  // e.x.: Echo
8
8
  name: string
9
9
  // fullName is the fully qualified name of the service
10
+ // this is also referred to as the "service ID"
10
11
  // e.x.: echoer.Echoer
11
12
  fullName: string
12
13
  // methods is the set of RPC methods.
package/srpc/handler.ts CHANGED
@@ -145,7 +145,16 @@ export function createInvokeFn<R, O>(
145
145
  }
146
146
 
147
147
  // createHandler creates a handler from a definition and an implementation.
148
- export function createHandler(definition: Definition, impl: any): Handler {
148
+ // if serviceID is not set, uses the fullName of the service as the identifier.
149
+ export function createHandler(
150
+ definition: Definition,
151
+ impl: any,
152
+ serviceID?: string
153
+ ): Handler {
154
+ // serviceID defaults to the full name of the service from Protobuf.
155
+ serviceID = serviceID || definition.fullName
156
+
157
+ // build map of method ID -> method prototype.
149
158
  const methodMap: MethodMap = {}
150
159
  for (const methodInfo of Object.values(definition.methods)) {
151
160
  const methodName = methodInfo.name
@@ -157,5 +166,5 @@ export function createHandler(definition: Definition, impl: any): Handler {
157
166
  methodMap[methodName] = createInvokeFn(methodInfo, methodProto)
158
167
  }
159
168
 
160
- return new StaticHandler(definition.fullName, methodMap)
169
+ return new StaticHandler(serviceID, methodMap)
161
170
  }
package/srpc/server.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Duplex } from 'it-stream-types'
2
2
  import { pipe } from 'it-pipe'
3
- import { Uint8ArrayList } from 'uint8arraylist'
4
3
 
5
4
  import { LookupMethod } from './mux.js'
6
5
  import { ServerRPC } from './server-rpc.js'
@@ -42,9 +41,7 @@ export class Server implements StreamHandler {
42
41
  }
43
42
 
44
43
  // handleDuplex handles an incoming message duplex.
45
- public handleDuplex(
46
- stream: Duplex<Uint8Array, Uint8Array>
47
- ): ServerRPC {
44
+ public handleDuplex(stream: Duplex<Uint8Array, Uint8Array>): ServerRPC {
48
45
  const rpc = this.startRpc()
49
46
  pipe(
50
47
  stream,