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.
Files changed (64) hide show
  1. package/Makefile +1 -0
  2. package/README.md +20 -10
  3. package/dist/echo/client-test.d.ts +1 -0
  4. package/dist/echo/client-test.js +20 -18
  5. package/dist/echo/echo.pb.d.ts +165 -12
  6. package/dist/echo/echo.pb.js +61 -17
  7. package/dist/echo/server.d.ts +8 -4
  8. package/dist/echo/server.js +29 -37
  9. package/dist/rpcstream/rpcstream.d.ts +6 -6
  10. package/dist/rpcstream/rpcstream.js +92 -51
  11. package/dist/rpcstream/rpcstream.pb.d.ts +46 -1
  12. package/dist/rpcstream/rpcstream.pb.js +157 -9
  13. package/dist/srpc/client.d.ts +3 -4
  14. package/dist/srpc/client.js +12 -46
  15. package/dist/srpc/common-rpc.d.ts +3 -2
  16. package/dist/srpc/common-rpc.js +12 -0
  17. package/dist/srpc/definition.d.ts +3 -3
  18. package/dist/srpc/handler.d.ts +2 -3
  19. package/dist/srpc/handler.js +5 -22
  20. package/dist/srpc/index.d.ts +1 -1
  21. package/dist/srpc/index.js +1 -1
  22. package/dist/srpc/packet.js +0 -32
  23. package/dist/srpc/pushable.d.ts +2 -0
  24. package/dist/srpc/pushable.js +13 -0
  25. package/dist/srpc/rpcproto.pb.d.ts +13 -6
  26. package/dist/srpc/rpcproto.pb.js +95 -10
  27. package/dist/srpc/server.d.ts +1 -0
  28. package/dist/srpc/server.js +7 -0
  29. package/dist/srpc/ts-proto-rpc.d.ts +3 -4
  30. package/e2e/e2e.ts +4 -3
  31. package/e2e/e2e_test.go +24 -1
  32. package/echo/client-test.ts +23 -18
  33. package/echo/echo.pb.go +33 -20
  34. package/echo/echo.pb.ts +90 -34
  35. package/echo/echo.proto +4 -0
  36. package/echo/echo_srpc.pb.go +77 -0
  37. package/echo/server.go +18 -0
  38. package/echo/server.ts +47 -41
  39. package/integration/integration.go +1 -2
  40. package/integration/integration.ts +5 -1
  41. package/integration/integration_srpc.pb.go +139 -0
  42. package/package.json +5 -3
  43. package/patches/ts-proto+1.115.5.patch +1339 -0
  44. package/srpc/client.ts +16 -50
  45. package/srpc/common-rpc.ts +14 -2
  46. package/srpc/definition.ts +3 -3
  47. package/srpc/handler.ts +17 -34
  48. package/srpc/index.ts +1 -1
  49. package/srpc/muxed-conn.go +2 -2
  50. package/srpc/packet-rw.go +4 -6
  51. package/srpc/packet.ts +0 -33
  52. package/srpc/pushable.ts +17 -0
  53. package/srpc/rpcproto.pb.ts +122 -12
  54. package/srpc/server-pipe.go +2 -2
  55. package/srpc/server.go +2 -2
  56. package/srpc/server.ts +8 -0
  57. package/srpc/ts-proto-rpc.ts +4 -6
  58. package/srpc/websocket.go +2 -2
  59. package/dist/echo/sever.d.ts +0 -0
  60. package/dist/echo/sever.js +0 -1
  61. package/dist/srpc/observable-source.d.ts +0 -9
  62. package/dist/srpc/observable-source.js +0 -25
  63. package/echo/sever.ts +0 -0
  64. package/srpc/observable-source.ts +0 -40
@@ -1,19 +1,19 @@
1
- import { Observable } from 'rxjs';
2
1
  import { RpcStreamPacket } from './rpcstream.pb.js';
3
2
  import { Server } from '../srpc/server.js';
4
3
  import { OpenStreamFunc, Stream } from '../srpc/stream.js';
5
4
  import { Pushable } from 'it-pushable';
6
5
  import { Source, Sink } from 'it-stream-types';
7
- export declare type RpcStreamCaller = (request: Observable<RpcStreamPacket>) => Observable<RpcStreamPacket>;
6
+ export declare type RpcStreamCaller = (request: AsyncIterable<RpcStreamPacket>) => AsyncIterable<RpcStreamPacket>;
7
+ export declare function openRpcStream(componentId: string, caller: RpcStreamCaller): Promise<Stream>;
8
8
  export declare function buildRpcStreamOpenStream(componentId: string, caller: RpcStreamCaller): OpenStreamFunc;
9
9
  export declare type RpcStreamGetter = (componentId: string) => Promise<Server>;
10
- export declare function handleRpcStream(stream: Observable<RpcStreamPacket>, getter: RpcStreamGetter): AsyncIterable<RpcStreamPacket>;
10
+ export declare function handleRpcStream(packetStream: AsyncIterator<RpcStreamPacket>, getter: RpcStreamGetter): AsyncIterable<RpcStreamPacket>;
11
11
  export declare class RpcStream implements Stream {
12
12
  readonly source: Source<Uint8Array>;
13
13
  readonly sink: Sink<Uint8Array>;
14
+ private readonly _packetStream;
14
15
  private readonly _packetSink;
15
- private readonly _source;
16
- constructor(packetSink: Pushable<RpcStreamPacket>, packetSource: Observable<RpcStreamPacket>);
16
+ constructor(packetSink: Pushable<RpcStreamPacket>, packetStream: AsyncIterator<RpcStreamPacket>);
17
17
  private _createSink;
18
- private _subscribeRpcStreamPacketSource;
18
+ private _createSource;
19
19
  }
@@ -1,50 +1,88 @@
1
- import { from as obsFrom } from 'rxjs';
2
1
  import { pushable } from 'it-pushable';
2
+ // openRpcStream attempts to open a stream over a RPC call.
3
+ // waits for the remote to ack the stream before returning.
4
+ export async function openRpcStream(componentId, caller) {
5
+ const packetSink = pushable({ objectMode: true });
6
+ const packetSource = caller(packetSink);
7
+ // write the component id
8
+ packetSink.push({
9
+ body: {
10
+ $case: 'init',
11
+ init: { componentId },
12
+ },
13
+ });
14
+ // wait for ack
15
+ const packetIt = packetSource[Symbol.asyncIterator]();
16
+ const ackPacketIt = await packetIt.next();
17
+ if (ackPacketIt.done) {
18
+ throw new Error(`rpcstream: closed before ack packet`);
19
+ }
20
+ const ackPacket = ackPacketIt.value;
21
+ const ackBody = ackPacket?.body;
22
+ if (!ackBody || ackBody.$case !== 'ack') {
23
+ const msgType = ackBody?.$case || 'none';
24
+ throw new Error(`rpcstream: expected ack packet but got ${msgType}`);
25
+ }
26
+ const errStr = ackBody.ack?.error;
27
+ if (errStr) {
28
+ throw new Error(`rpcstream: remote: ${errStr}`);
29
+ }
30
+ // build & return the data stream
31
+ return new RpcStream(packetSink, packetIt); // packetSource)
32
+ }
3
33
  // buildRpcStreamOpenStream builds a OpenStream func with a RpcStream.
4
34
  export function buildRpcStreamOpenStream(componentId, caller) {
5
35
  return async () => {
6
- const packetSink = pushable({ objectMode: true });
7
- const packetObs = obsFrom(packetSink);
8
- const packetSource = caller(packetObs);
9
- // write the component id
10
- packetSink.push({
11
- body: {
12
- $case: 'init',
13
- init: { componentId },
14
- },
15
- });
16
- // build & return the stream
17
- return new RpcStream(packetSink, packetSource);
36
+ return openRpcStream(componentId, caller);
18
37
  };
19
38
  }
20
39
  // handleRpcStream handles an incoming RPC stream (remote is the initiator).
21
- export async function* handleRpcStream(stream, getter) {
40
+ export async function* handleRpcStream(packetStream, getter) {
22
41
  // read the component id
23
- const initPromise = new Promise((resolve, reject) => {
24
- const subscription = stream.subscribe({
25
- next(value) {
26
- resolve(value);
27
- subscription.unsubscribe();
28
- },
29
- error(err) {
30
- reject(err);
31
- },
32
- complete() {
33
- reject(new Error('no packet received'));
34
- },
35
- });
36
- });
37
- // read the init packet
38
- const initRpcStreamPacket = await initPromise;
42
+ const initRpcStreamIt = await packetStream.next();
43
+ if (initRpcStreamIt.done) {
44
+ throw new Error('closed before init received');
45
+ }
46
+ const initRpcStreamPacket = initRpcStreamIt.value;
47
+ // ensure we received an init packet
39
48
  if (initRpcStreamPacket?.body?.$case !== 'init') {
40
49
  throw new Error('expected init packet');
41
50
  }
42
51
  // lookup the server for the component id.
43
- const server = await getter(initRpcStreamPacket.body.init.componentId);
52
+ let server;
53
+ let err;
54
+ try {
55
+ server = await getter(initRpcStreamPacket.body.init.componentId);
56
+ }
57
+ catch (errAny) {
58
+ err = errAny;
59
+ if (!err) {
60
+ err = new Error(`rpc getter failed`);
61
+ }
62
+ else if (!err.message) {
63
+ err = new Error(`rpc getter failed: ${err}`);
64
+ }
65
+ }
66
+ if (!server && !err) {
67
+ err = new Error('not implemented');
68
+ }
69
+ yield* [
70
+ {
71
+ body: {
72
+ $case: 'ack',
73
+ ack: {
74
+ error: err?.message || '',
75
+ },
76
+ },
77
+ },
78
+ ];
79
+ if (err) {
80
+ throw err;
81
+ }
44
82
  // build the outgoing packet sink & the packet source
45
83
  const packetSink = pushable({ objectMode: true });
46
84
  // handle the stream
47
- const rpcStream = new RpcStream(packetSink, stream);
85
+ const rpcStream = new RpcStream(packetSink, packetStream);
48
86
  server.handleDuplex(rpcStream);
49
87
  // process packets
50
88
  for await (const packet of packetSink) {
@@ -52,14 +90,15 @@ export async function* handleRpcStream(stream, getter) {
52
90
  }
53
91
  }
54
92
  // RpcStream implements the Stream on top of a RPC call.
93
+ // Note: expects the stream to already have been negotiated.
55
94
  export class RpcStream {
56
- constructor(packetSink, packetSource) {
95
+ // packetSink writes packets to the remote.
96
+ // packetSource receives packets from the remote.
97
+ constructor(packetSink, packetStream) {
57
98
  this._packetSink = packetSink;
99
+ this._packetStream = packetStream;
58
100
  this.sink = this._createSink();
59
- const source = pushable({ objectMode: true });
60
- this.source = source;
61
- this._source = source;
62
- this._subscribeRpcStreamPacketSource(packetSource);
101
+ this.source = this._createSource();
63
102
  }
64
103
  // _createSink initializes the sink field.
65
104
  _createSink() {
@@ -77,20 +116,22 @@ export class RpcStream {
77
116
  }
78
117
  };
79
118
  }
80
- // _subscribeRpcStreamPacketSource starts the subscription to the response data.
81
- _subscribeRpcStreamPacketSource(packetSource) {
82
- packetSource.subscribe({
83
- next: (value) => {
84
- if (value?.body?.$case === 'data') {
85
- this._source.push(value.body.data);
119
+ // _createSource initializes the source field.
120
+ _createSource() {
121
+ const packetSource = this._packetStream;
122
+ return (async function* packetDataSource() {
123
+ while (true) {
124
+ const msgIt = await packetSource.next();
125
+ if (msgIt.done) {
126
+ return;
86
127
  }
87
- },
88
- error: (err) => {
89
- this._source.end(err);
90
- },
91
- complete: () => {
92
- this._source.end();
93
- },
94
- });
128
+ const value = msgIt.value;
129
+ const body = value?.body;
130
+ if (!body || body.$case !== 'data') {
131
+ continue;
132
+ }
133
+ yield* [body.data];
134
+ }
135
+ })();
95
136
  }
96
137
  }
@@ -1,11 +1,15 @@
1
1
  import Long from 'long';
2
2
  import * as _m0 from 'protobufjs/minimal';
3
+ import { RpcStreamInit as RpcStreamInit1, RpcAck as RpcAck2 } from './rpcstream.pb.js';
3
4
  export declare const protobufPackage = "rpcstream";
4
5
  /** RpcStreamPacket is a packet encapsulating data for a RPC stream. */
5
6
  export interface RpcStreamPacket {
6
7
  body?: {
7
8
  $case: 'init';
8
- init: RpcStreamInit;
9
+ init: RpcStreamInit1;
10
+ } | {
11
+ $case: 'ack';
12
+ ack: RpcAck2;
9
13
  } | {
10
14
  $case: 'data';
11
15
  data: Uint8Array;
@@ -16,9 +20,16 @@ export interface RpcStreamInit {
16
20
  /** ComponentId is the identifier of the component making the request. */
17
21
  componentId: string;
18
22
  }
23
+ /** RpcAck is the ack message in a RPC stream. */
24
+ export interface RpcAck {
25
+ /** Error indicates there was some error setting up the stream. */
26
+ error: string;
27
+ }
19
28
  export declare const RpcStreamPacket: {
20
29
  encode(message: RpcStreamPacket, writer?: _m0.Writer): _m0.Writer;
21
30
  decode(input: _m0.Reader | Uint8Array, length?: number): RpcStreamPacket;
31
+ encodeTransform(source: AsyncIterable<RpcStreamPacket | RpcStreamPacket[]> | Iterable<RpcStreamPacket | RpcStreamPacket[]>): AsyncIterable<Uint8Array>;
32
+ decodeTransform(source: AsyncIterable<Uint8Array | Uint8Array[]> | Iterable<Uint8Array | Uint8Array[]>): AsyncIterable<RpcStreamPacket>;
22
33
  fromJSON(object: any): RpcStreamPacket;
23
34
  toJSON(message: RpcStreamPacket): unknown;
24
35
  fromPartial<I extends {
@@ -28,6 +39,12 @@ export declare const RpcStreamPacket: {
28
39
  } | undefined;
29
40
  } & {
30
41
  $case: "init";
42
+ }) | ({
43
+ ack?: {
44
+ error?: string | undefined;
45
+ } | undefined;
46
+ } & {
47
+ $case: "ack";
31
48
  }) | ({
32
49
  data?: Uint8Array | undefined;
33
50
  } & {
@@ -48,6 +65,19 @@ export declare const RpcStreamPacket: {
48
65
  } & Record<Exclude<keyof I["body"]["init"], "componentId">, never>) | undefined;
49
66
  $case: "init";
50
67
  } & Record<Exclude<keyof I["body"], "$case" | "init">, never>) | ({
68
+ ack?: {
69
+ error?: string | undefined;
70
+ } | undefined;
71
+ } & {
72
+ $case: "ack";
73
+ } & {
74
+ ack?: ({
75
+ error?: string | undefined;
76
+ } & {
77
+ error?: string | undefined;
78
+ } & Record<Exclude<keyof I["body"]["ack"], "error">, never>) | undefined;
79
+ $case: "ack";
80
+ } & Record<Exclude<keyof I["body"], "$case" | "ack">, never>) | ({
51
81
  data?: Uint8Array | undefined;
52
82
  } & {
53
83
  $case: "data";
@@ -60,6 +90,8 @@ export declare const RpcStreamPacket: {
60
90
  export declare const RpcStreamInit: {
61
91
  encode(message: RpcStreamInit, writer?: _m0.Writer): _m0.Writer;
62
92
  decode(input: _m0.Reader | Uint8Array, length?: number): RpcStreamInit;
93
+ encodeTransform(source: AsyncIterable<RpcStreamInit | RpcStreamInit[]> | Iterable<RpcStreamInit | RpcStreamInit[]>): AsyncIterable<Uint8Array>;
94
+ decodeTransform(source: AsyncIterable<Uint8Array | Uint8Array[]> | Iterable<Uint8Array | Uint8Array[]>): AsyncIterable<RpcStreamInit>;
63
95
  fromJSON(object: any): RpcStreamInit;
64
96
  toJSON(message: RpcStreamInit): unknown;
65
97
  fromPartial<I extends {
@@ -68,6 +100,19 @@ export declare const RpcStreamInit: {
68
100
  componentId?: string | undefined;
69
101
  } & Record<Exclude<keyof I, "componentId">, never>>(object: I): RpcStreamInit;
70
102
  };
103
+ export declare const RpcAck: {
104
+ encode(message: RpcAck, writer?: _m0.Writer): _m0.Writer;
105
+ decode(input: _m0.Reader | Uint8Array, length?: number): RpcAck;
106
+ encodeTransform(source: AsyncIterable<RpcAck | RpcAck[]> | Iterable<RpcAck | RpcAck[]>): AsyncIterable<Uint8Array>;
107
+ decodeTransform(source: AsyncIterable<Uint8Array | Uint8Array[]> | Iterable<Uint8Array | Uint8Array[]>): AsyncIterable<RpcAck>;
108
+ fromJSON(object: any): RpcAck;
109
+ toJSON(message: RpcAck): unknown;
110
+ fromPartial<I extends {
111
+ error?: string | undefined;
112
+ } & {
113
+ error?: string | undefined;
114
+ } & Record<Exclude<keyof I, "error">, never>>(object: I): RpcAck;
115
+ };
71
116
  declare type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
72
117
  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 {
73
118
  $case: string;
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable */
2
2
  import Long from 'long';
3
3
  import * as _m0 from 'protobufjs/minimal';
4
+ import { RpcStreamInit as RpcStreamInit1, RpcAck as RpcAck2, } from './rpcstream.pb.js';
4
5
  export const protobufPackage = 'rpcstream';
5
6
  function createBaseRpcStreamPacket() {
6
7
  return { body: undefined };
@@ -8,10 +9,13 @@ function createBaseRpcStreamPacket() {
8
9
  export const RpcStreamPacket = {
9
10
  encode(message, writer = _m0.Writer.create()) {
10
11
  if (message.body?.$case === 'init') {
11
- RpcStreamInit.encode(message.body.init, writer.uint32(10).fork()).ldelim();
12
+ RpcStreamInit1.encode(message.body.init, writer.uint32(10).fork()).ldelim();
13
+ }
14
+ if (message.body?.$case === 'ack') {
15
+ RpcAck2.encode(message.body.ack, writer.uint32(18).fork()).ldelim();
12
16
  }
13
17
  if (message.body?.$case === 'data') {
14
- writer.uint32(18).bytes(message.body.data);
18
+ writer.uint32(26).bytes(message.body.data);
15
19
  }
16
20
  return writer;
17
21
  },
@@ -25,10 +29,16 @@ export const RpcStreamPacket = {
25
29
  case 1:
26
30
  message.body = {
27
31
  $case: 'init',
28
- init: RpcStreamInit.decode(reader, reader.uint32()),
32
+ init: RpcStreamInit1.decode(reader, reader.uint32()),
29
33
  };
30
34
  break;
31
35
  case 2:
36
+ message.body = {
37
+ $case: 'ack',
38
+ ack: RpcAck2.decode(reader, reader.uint32()),
39
+ };
40
+ break;
41
+ case 3:
32
42
  message.body = { $case: 'data', data: reader.bytes() };
33
43
  break;
34
44
  default:
@@ -38,20 +48,54 @@ export const RpcStreamPacket = {
38
48
  }
39
49
  return message;
40
50
  },
51
+ // encodeTransform encodes a source of message objects.
52
+ // Transform<RpcStreamPacket, Uint8Array>
53
+ async *encodeTransform(source) {
54
+ for await (const pkt of source) {
55
+ if (Array.isArray(pkt)) {
56
+ for (const p of pkt) {
57
+ yield* [RpcStreamPacket.encode(p).finish()];
58
+ }
59
+ }
60
+ else {
61
+ yield* [RpcStreamPacket.encode(pkt).finish()];
62
+ }
63
+ }
64
+ },
65
+ // decodeTransform decodes a source of encoded messages.
66
+ // Transform<Uint8Array, RpcStreamPacket>
67
+ async *decodeTransform(source) {
68
+ for await (const pkt of source) {
69
+ if (Array.isArray(pkt)) {
70
+ for (const p of pkt) {
71
+ yield* [RpcStreamPacket.decode(p)];
72
+ }
73
+ }
74
+ else {
75
+ yield* [RpcStreamPacket.decode(pkt)];
76
+ }
77
+ }
78
+ },
41
79
  fromJSON(object) {
42
80
  return {
43
81
  body: isSet(object.init)
44
- ? { $case: 'init', init: RpcStreamInit.fromJSON(object.init) }
45
- : isSet(object.data)
46
- ? { $case: 'data', data: bytesFromBase64(object.data) }
47
- : undefined,
82
+ ? { $case: 'init', init: RpcStreamInit1.fromJSON(object.init) }
83
+ : isSet(object.ack)
84
+ ? { $case: 'ack', ack: RpcAck2.fromJSON(object.ack) }
85
+ : isSet(object.data)
86
+ ? { $case: 'data', data: bytesFromBase64(object.data) }
87
+ : undefined,
48
88
  };
49
89
  },
50
90
  toJSON(message) {
51
91
  const obj = {};
52
92
  message.body?.$case === 'init' &&
53
93
  (obj.init = message.body?.init
54
- ? RpcStreamInit.toJSON(message.body?.init)
94
+ ? RpcStreamInit1.toJSON(message.body?.init)
95
+ : undefined);
96
+ message.body?.$case === 'ack' &&
97
+ (obj.ack = message.body?.ack
98
+ ? RpcAck2.toJSON(message.body?.ack)
55
99
  : undefined);
56
100
  message.body?.$case === 'data' &&
57
101
  (obj.data =
@@ -67,9 +111,14 @@ export const RpcStreamPacket = {
67
111
  object.body?.init !== null) {
68
112
  message.body = {
69
113
  $case: 'init',
70
- init: RpcStreamInit.fromPartial(object.body.init),
114
+ init: RpcStreamInit1.fromPartial(object.body.init),
71
115
  };
72
116
  }
117
+ if (object.body?.$case === 'ack' &&
118
+ object.body?.ack !== undefined &&
119
+ object.body?.ack !== null) {
120
+ message.body = { $case: 'ack', ack: RpcAck2.fromPartial(object.body.ack) };
121
+ }
73
122
  if (object.body?.$case === 'data' &&
74
123
  object.body?.data !== undefined &&
75
124
  object.body?.data !== null) {
@@ -105,6 +154,34 @@ export const RpcStreamInit = {
105
154
  }
106
155
  return message;
107
156
  },
157
+ // encodeTransform encodes a source of message objects.
158
+ // Transform<RpcStreamInit, Uint8Array>
159
+ async *encodeTransform(source) {
160
+ for await (const pkt of source) {
161
+ if (Array.isArray(pkt)) {
162
+ for (const p of pkt) {
163
+ yield* [RpcStreamInit.encode(p).finish()];
164
+ }
165
+ }
166
+ else {
167
+ yield* [RpcStreamInit.encode(pkt).finish()];
168
+ }
169
+ }
170
+ },
171
+ // decodeTransform decodes a source of encoded messages.
172
+ // Transform<Uint8Array, RpcStreamInit>
173
+ async *decodeTransform(source) {
174
+ for await (const pkt of source) {
175
+ if (Array.isArray(pkt)) {
176
+ for (const p of pkt) {
177
+ yield* [RpcStreamInit.decode(p)];
178
+ }
179
+ }
180
+ else {
181
+ yield* [RpcStreamInit.decode(pkt)];
182
+ }
183
+ }
184
+ },
108
185
  fromJSON(object) {
109
186
  return {
110
187
  componentId: isSet(object.componentId) ? String(object.componentId) : '',
@@ -121,6 +198,77 @@ export const RpcStreamInit = {
121
198
  return message;
122
199
  },
123
200
  };
201
+ function createBaseRpcAck() {
202
+ return { error: '' };
203
+ }
204
+ export const RpcAck = {
205
+ encode(message, writer = _m0.Writer.create()) {
206
+ if (message.error !== '') {
207
+ writer.uint32(10).string(message.error);
208
+ }
209
+ return writer;
210
+ },
211
+ decode(input, length) {
212
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
213
+ let end = length === undefined ? reader.len : reader.pos + length;
214
+ const message = createBaseRpcAck();
215
+ while (reader.pos < end) {
216
+ const tag = reader.uint32();
217
+ switch (tag >>> 3) {
218
+ case 1:
219
+ message.error = reader.string();
220
+ break;
221
+ default:
222
+ reader.skipType(tag & 7);
223
+ break;
224
+ }
225
+ }
226
+ return message;
227
+ },
228
+ // encodeTransform encodes a source of message objects.
229
+ // Transform<RpcAck, Uint8Array>
230
+ async *encodeTransform(source) {
231
+ for await (const pkt of source) {
232
+ if (Array.isArray(pkt)) {
233
+ for (const p of pkt) {
234
+ yield* [RpcAck.encode(p).finish()];
235
+ }
236
+ }
237
+ else {
238
+ yield* [RpcAck.encode(pkt).finish()];
239
+ }
240
+ }
241
+ },
242
+ // decodeTransform decodes a source of encoded messages.
243
+ // Transform<Uint8Array, RpcAck>
244
+ async *decodeTransform(source) {
245
+ for await (const pkt of source) {
246
+ if (Array.isArray(pkt)) {
247
+ for (const p of pkt) {
248
+ yield* [RpcAck.decode(p)];
249
+ }
250
+ }
251
+ else {
252
+ yield* [RpcAck.decode(pkt)];
253
+ }
254
+ }
255
+ },
256
+ fromJSON(object) {
257
+ return {
258
+ error: isSet(object.error) ? String(object.error) : '',
259
+ };
260
+ },
261
+ toJSON(message) {
262
+ const obj = {};
263
+ message.error !== undefined && (obj.error = message.error);
264
+ return obj;
265
+ },
266
+ fromPartial(object) {
267
+ const message = createBaseRpcAck();
268
+ message.error = object.error ?? '';
269
+ return message;
270
+ },
271
+ };
124
272
  var globalThis = (() => {
125
273
  if (typeof globalThis !== 'undefined')
126
274
  return globalThis;
@@ -1,4 +1,3 @@
1
- import { Observable } from 'rxjs';
2
1
  import type { TsProtoRpc } from './ts-proto-rpc.js';
3
2
  import type { OpenStreamFunc } from './stream.js';
4
3
  export declare class Client implements TsProtoRpc {
@@ -8,8 +7,8 @@ export declare class Client implements TsProtoRpc {
8
7
  setOpenStreamFn(openStreamFn?: OpenStreamFunc): Promise<OpenStreamFunc>;
9
8
  private initOpenStreamFn;
10
9
  request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
11
- clientStreamingRequest(service: string, method: string, data: Observable<Uint8Array>): Promise<Uint8Array>;
12
- serverStreamingRequest(service: string, method: string, data: Uint8Array): Observable<Uint8Array>;
13
- bidirectionalStreamingRequest(service: string, method: string, data: Observable<Uint8Array>): Observable<Uint8Array>;
10
+ clientStreamingRequest(service: string, method: string, data: AsyncIterable<Uint8Array>): Promise<Uint8Array>;
11
+ serverStreamingRequest(service: string, method: string, data: Uint8Array): AsyncIterable<Uint8Array>;
12
+ bidirectionalStreamingRequest(service: string, method: string, data: AsyncIterable<Uint8Array>): AsyncIterable<Uint8Array>;
14
13
  private startRpc;
15
14
  }
@@ -1,22 +1,8 @@
1
1
  import { pipe } from 'it-pipe';
2
2
  import { pushable } from 'it-pushable';
3
- import { from as observableFrom } from 'rxjs';
4
3
  import { ClientRPC } from './client-rpc.js';
4
+ import { writeToPushable } from './pushable.js';
5
5
  import { decodePacketSource, encodePacketSource, parseLengthPrefixTransform, prependLengthPrefixTransform, } from './packet.js';
6
- // writeClientStream registers the subscriber to write the client data stream.
7
- function writeClientStream(call, data) {
8
- data.subscribe({
9
- next(value) {
10
- call.writeCallData(value);
11
- },
12
- error(err) {
13
- call.close(err);
14
- },
15
- complete() {
16
- call.writeCallData(undefined, true);
17
- },
18
- });
19
- }
20
6
  // Client implements the ts-proto Rpc interface with the drpcproto protocol.
21
7
  export class Client {
22
8
  constructor(openStreamFn) {
@@ -69,7 +55,7 @@ export class Client {
69
55
  // clientStreamingRequest starts a client side streaming request.
70
56
  async clientStreamingRequest(service, method, data) {
71
57
  const call = await this.startRpc(service, method, null);
72
- writeClientStream(call, data);
58
+ call.writeCallDataFromSource(data);
73
59
  for await (const data of call.rpcDataSource) {
74
60
  call.close();
75
61
  return data;
@@ -80,51 +66,31 @@ export class Client {
80
66
  }
81
67
  // serverStreamingRequest starts a server-side streaming request.
82
68
  serverStreamingRequest(service, method, data) {
83
- const pushServerData = pushable({ objectMode: true });
84
- const serverData = observableFrom(pushServerData);
69
+ const serverData = pushable({ objectMode: true });
85
70
  this.startRpc(service, method, data)
86
71
  .then(async (call) => {
87
- try {
88
- for await (const data of call.rpcDataSource) {
89
- pushServerData.push(data);
90
- }
91
- }
92
- catch (err) {
93
- pushServerData.throw(err);
94
- }
95
- pushServerData.end();
72
+ return writeToPushable(call.rpcDataSource, serverData);
96
73
  })
97
- .catch(pushServerData.throw.bind(pushServerData));
74
+ .catch(serverData.throw.bind(serverData));
98
75
  return serverData;
99
76
  }
100
77
  // bidirectionalStreamingRequest starts a two-way streaming request.
101
78
  bidirectionalStreamingRequest(service, method, data) {
102
- const pushServerData = pushable({ objectMode: true });
103
- const serverData = observableFrom(pushServerData);
79
+ const serverData = pushable({ objectMode: true });
104
80
  this.startRpc(service, method, null)
105
81
  .then(async (call) => {
82
+ call.writeCallDataFromSource(data);
106
83
  try {
107
- data.subscribe({
108
- next(value) {
109
- call.writeCallData(value);
110
- },
111
- error(err) {
112
- call.close(err);
113
- },
114
- complete() {
115
- call.close();
116
- },
117
- });
118
- for await (const data of call.rpcDataSource) {
119
- pushServerData.push(data);
84
+ for await (const message of call.rpcDataSource) {
85
+ serverData.push(message);
120
86
  }
121
87
  }
122
88
  catch (err) {
123
- pushServerData.throw(err);
89
+ serverData.throw(err);
124
90
  }
125
- pushServerData.end();
91
+ serverData.end();
126
92
  })
127
- .catch(pushServerData.throw.bind(pushServerData));
93
+ .catch(serverData.throw.bind(serverData));
128
94
  return serverData;
129
95
  }
130
96
  // startRpc is a common utility function to begin a rpc call.
@@ -1,16 +1,17 @@
1
- import type { Source, Sink } from 'it-stream-types';
1
+ import type { Sink } from 'it-stream-types';
2
2
  import type { CallData, CallStart } from './rpcproto.pb.js';
3
3
  import { Packet } from './rpcproto.pb.js';
4
4
  export declare class CommonRPC {
5
5
  sink: Sink<Packet>;
6
6
  source: AsyncIterable<Packet>;
7
7
  private readonly _source;
8
- readonly rpcDataSource: Source<Uint8Array>;
8
+ readonly rpcDataSource: AsyncIterable<Uint8Array>;
9
9
  private readonly _rpcDataSource;
10
10
  protected service?: string;
11
11
  protected method?: string;
12
12
  constructor();
13
13
  writeCallData(data?: Uint8Array, complete?: boolean, error?: string): Promise<void>;
14
+ writeCallDataFromSource(dataSource: AsyncIterable<Uint8Array>): Promise<void>;
14
15
  protected writePacket(packet: Packet): Promise<void>;
15
16
  handleMessage(message: Uint8Array): Promise<void>;
16
17
  handlePacket(packet: Partial<Packet>): Promise<void>;
@@ -26,6 +26,18 @@ export class CommonRPC {
26
26
  },
27
27
  });
28
28
  }
29
+ // writeCallDataFromSource writes all call data from the iterable.
30
+ async writeCallDataFromSource(dataSource) {
31
+ try {
32
+ for await (const data of dataSource) {
33
+ this.writeCallData(data);
34
+ }
35
+ this.writeCallData(undefined, true);
36
+ }
37
+ catch (err) {
38
+ this.close(err);
39
+ }
40
+ }
29
41
  // writePacket writes a packet to the stream.
30
42
  async writePacket(packet) {
31
43
  this._source.push(packet);