@vishalsharma7nov/react-native-proto 0.2.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.
- package/android/src/main/java/com/vishalsharma7nov/reactnativeproto/ReactNativeProtoNativeGrpcModule.java +142 -0
- package/app.plugin.js +63 -0
- package/bin/react-native-proto.js +956 -0
- package/ios/ReactNativeProtoNativeGrpc.m +129 -0
- package/lib/commonjs/auth.js +72 -0
- package/lib/commonjs/auth.js.map +1 -0
- package/lib/commonjs/client-factory.js +81 -0
- package/lib/commonjs/client-factory.js.map +1 -0
- package/lib/commonjs/codecs.js +41 -0
- package/lib/commonjs/codecs.js.map +1 -0
- package/lib/commonjs/connect/envelope.js +100 -0
- package/lib/commonjs/connect/envelope.js.map +1 -0
- package/lib/commonjs/connect/errors.js +71 -0
- package/lib/commonjs/connect/errors.js.map +1 -0
- package/lib/commonjs/errors.js +54 -0
- package/lib/commonjs/errors.js.map +1 -0
- package/lib/commonjs/generated/create-api.js +29 -0
- package/lib/commonjs/generated/create-api.js.map +1 -0
- package/lib/commonjs/generated/message-types.js +2 -0
- package/lib/commonjs/generated/message-types.js.map +1 -0
- package/lib/commonjs/generated/messages.js +47 -0
- package/lib/commonjs/generated/messages.js.map +1 -0
- package/lib/commonjs/generated/messages.pb.js +2787 -0
- package/lib/commonjs/generated/messages.pb.js.map +1 -0
- package/lib/commonjs/generated/method-map.js +68 -0
- package/lib/commonjs/generated/method-map.js.map +1 -0
- package/lib/commonjs/index.js +283 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/interceptors.js +19 -0
- package/lib/commonjs/interceptors.js.map +1 -0
- package/lib/commonjs/logging.js +54 -0
- package/lib/commonjs/logging.js.map +1 -0
- package/lib/commonjs/metro/index.js +35 -0
- package/lib/commonjs/metro/index.js.map +1 -0
- package/lib/commonjs/metro/transformer.js +33 -0
- package/lib/commonjs/metro/transformer.js.map +1 -0
- package/lib/commonjs/mock-server/index.js +125 -0
- package/lib/commonjs/mock-server/index.js.map +1 -0
- package/lib/commonjs/native-grpc/index.js +242 -0
- package/lib/commonjs/native-grpc/index.js.map +1 -0
- package/lib/commonjs/offline-queue.js +137 -0
- package/lib/commonjs/offline-queue.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/path-templates.js +44 -0
- package/lib/commonjs/path-templates.js.map +1 -0
- package/lib/commonjs/react-query/index.js +30 -0
- package/lib/commonjs/react-query/index.js.map +1 -0
- package/lib/commonjs/streaming.js +251 -0
- package/lib/commonjs/streaming.js.map +1 -0
- package/lib/commonjs/transport.js +323 -0
- package/lib/commonjs/transport.js.map +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/validation/zod.js +48 -0
- package/lib/commonjs/validation/zod.js.map +1 -0
- package/lib/commonjs/version-check.js +102 -0
- package/lib/commonjs/version-check.js.map +1 -0
- package/lib/module/auth.js +67 -0
- package/lib/module/auth.js.map +1 -0
- package/lib/module/client-factory.js +77 -0
- package/lib/module/client-factory.js.map +1 -0
- package/lib/module/codecs.js +36 -0
- package/lib/module/codecs.js.map +1 -0
- package/lib/module/connect/envelope.js +93 -0
- package/lib/module/connect/envelope.js.map +1 -0
- package/lib/module/connect/errors.js +65 -0
- package/lib/module/connect/errors.js.map +1 -0
- package/lib/module/errors.js +46 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/generated/create-api.js +13 -0
- package/lib/module/generated/create-api.js.map +1 -0
- package/lib/module/generated/message-types.js +2 -0
- package/lib/module/generated/message-types.js.map +1 -0
- package/lib/module/generated/messages.js +43 -0
- package/lib/module/generated/messages.js.map +1 -0
- package/lib/module/generated/messages.pb.js +2787 -0
- package/lib/module/generated/messages.pb.js.map +1 -0
- package/lib/module/generated/method-map.js +64 -0
- package/lib/module/generated/method-map.js.map +1 -0
- package/lib/module/index.js +53 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/interceptors.js +15 -0
- package/lib/module/interceptors.js.map +1 -0
- package/lib/module/logging.js +50 -0
- package/lib/module/logging.js.map +1 -0
- package/lib/module/metro/index.js +25 -0
- package/lib/module/metro/index.js.map +1 -0
- package/lib/module/metro/transformer.js +29 -0
- package/lib/module/metro/transformer.js.map +1 -0
- package/lib/module/mock-server/index.js +120 -0
- package/lib/module/mock-server/index.js.map +1 -0
- package/lib/module/native-grpc/index.js +233 -0
- package/lib/module/native-grpc/index.js.map +1 -0
- package/lib/module/offline-queue.js +132 -0
- package/lib/module/offline-queue.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/path-templates.js +39 -0
- package/lib/module/path-templates.js.map +1 -0
- package/lib/module/react-query/index.js +25 -0
- package/lib/module/react-query/index.js.map +1 -0
- package/lib/module/streaming.js +246 -0
- package/lib/module/streaming.js.map +1 -0
- package/lib/module/transport.js +316 -0
- package/lib/module/transport.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/validation/zod.js +43 -0
- package/lib/module/validation/zod.js.map +1 -0
- package/lib/module/version-check.js +93 -0
- package/lib/module/version-check.js.map +1 -0
- package/lib/typescript/src/auth.d.ts +26 -0
- package/lib/typescript/src/auth.d.ts.map +1 -0
- package/lib/typescript/src/client-factory.d.ts +7 -0
- package/lib/typescript/src/client-factory.d.ts.map +1 -0
- package/lib/typescript/src/codecs.d.ts +5 -0
- package/lib/typescript/src/codecs.d.ts.map +1 -0
- package/lib/typescript/src/connect/envelope.d.ts +18 -0
- package/lib/typescript/src/connect/envelope.d.ts.map +1 -0
- package/lib/typescript/src/connect/errors.d.ts +11 -0
- package/lib/typescript/src/connect/errors.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +21 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/generated/create-api.d.ts +34 -0
- package/lib/typescript/src/generated/create-api.d.ts.map +1 -0
- package/lib/typescript/src/generated/message-types.d.ts +54 -0
- package/lib/typescript/src/generated/message-types.d.ts.map +1 -0
- package/lib/typescript/src/generated/messages.d.ts +17 -0
- package/lib/typescript/src/generated/messages.d.ts.map +1 -0
- package/lib/typescript/src/generated/method-map.d.ts +7 -0
- package/lib/typescript/src/generated/method-map.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +53 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/interceptors.d.ts +17 -0
- package/lib/typescript/src/interceptors.d.ts.map +1 -0
- package/lib/typescript/src/logging.d.ts +16 -0
- package/lib/typescript/src/logging.d.ts.map +1 -0
- package/lib/typescript/src/metro/index.d.ts +15 -0
- package/lib/typescript/src/metro/index.d.ts.map +1 -0
- package/lib/typescript/src/metro/transformer.d.ts +16 -0
- package/lib/typescript/src/metro/transformer.d.ts.map +1 -0
- package/lib/typescript/src/mock-server/index.d.ts +27 -0
- package/lib/typescript/src/mock-server/index.d.ts.map +1 -0
- package/lib/typescript/src/native-grpc/index.d.ts +36 -0
- package/lib/typescript/src/native-grpc/index.d.ts.map +1 -0
- package/lib/typescript/src/offline-queue.d.ts +47 -0
- package/lib/typescript/src/offline-queue.d.ts.map +1 -0
- package/lib/typescript/src/path-templates.d.ts +17 -0
- package/lib/typescript/src/path-templates.d.ts.map +1 -0
- package/lib/typescript/src/react-query/index.d.ts +14 -0
- package/lib/typescript/src/react-query/index.d.ts.map +1 -0
- package/lib/typescript/src/streaming.d.ts +10 -0
- package/lib/typescript/src/streaming.d.ts.map +1 -0
- package/lib/typescript/src/transport.d.ts +19 -0
- package/lib/typescript/src/transport.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +78 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/validation/zod.d.ts +33 -0
- package/lib/typescript/src/validation/zod.d.ts.map +1 -0
- package/lib/typescript/src/version-check.d.ts +40 -0
- package/lib/typescript/src/version-check.d.ts.map +1 -0
- package/metro/index.js +23 -0
- package/metro/transformer.js +21 -0
- package/package.json +144 -0
- package/react-native-proto.podspec +15 -0
- package/src/auth.ts +97 -0
- package/src/client-factory.ts +109 -0
- package/src/codecs.ts +42 -0
- package/src/connect/envelope.ts +112 -0
- package/src/connect/errors.ts +86 -0
- package/src/errors.ts +81 -0
- package/src/generated/create-api.ts +40 -0
- package/src/generated/message-types.ts +63 -0
- package/src/generated/messages.pb.js +3207 -0
- package/src/generated/messages.ts +45 -0
- package/src/generated/method-map.ts +71 -0
- package/src/index.ts +113 -0
- package/src/interceptors.ts +32 -0
- package/src/logging.ts +67 -0
- package/src/metro/index.ts +27 -0
- package/src/metro/transformer.ts +38 -0
- package/src/mock-server/index.ts +164 -0
- package/src/native-grpc/index.ts +302 -0
- package/src/offline-queue.ts +160 -0
- package/src/path-templates.ts +65 -0
- package/src/react-query/index.ts +40 -0
- package/src/streaming.ts +326 -0
- package/src/transport.ts +427 -0
- package/src/types.ts +94 -0
- package/src/validation/zod.ts +75 -0
- package/src/version-check.ts +121 -0
package/src/streaming.ts
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CONNECT_FLAG_END_STREAM,
|
|
3
|
+
decodeConnectEnvelopes,
|
|
4
|
+
encodeConnectEnvelope,
|
|
5
|
+
readConnectEnvelopeStream,
|
|
6
|
+
} from './connect/envelope';
|
|
7
|
+
import {
|
|
8
|
+
bytesToUtf8,
|
|
9
|
+
connectErrorFromJson,
|
|
10
|
+
tryParseConnectError,
|
|
11
|
+
} from './connect/errors';
|
|
12
|
+
import { ProtoClientError } from './errors';
|
|
13
|
+
import { buildHeaders, unaryCall, type ResolvedTransportConfig } from './transport';
|
|
14
|
+
import type { CodecRegistry, MessageCodec, StreamCallInput } from './types';
|
|
15
|
+
|
|
16
|
+
async function collectRequests(
|
|
17
|
+
input: StreamCallInput
|
|
18
|
+
): Promise<Record<string, unknown>[]> {
|
|
19
|
+
if (input.requests) {
|
|
20
|
+
const list: Record<string, unknown>[] = [];
|
|
21
|
+
for await (const item of input.requests as AsyncIterable<
|
|
22
|
+
Record<string, unknown>
|
|
23
|
+
>) {
|
|
24
|
+
list.push(item);
|
|
25
|
+
}
|
|
26
|
+
return list;
|
|
27
|
+
}
|
|
28
|
+
return [input.request ?? {}];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function buildConnectRequestBody(
|
|
32
|
+
entryKind: string,
|
|
33
|
+
requests: Record<string, unknown>[],
|
|
34
|
+
requestCodec: MessageCodec
|
|
35
|
+
): Uint8Array {
|
|
36
|
+
const useEnvelopedRequest =
|
|
37
|
+
entryKind === 'clientStreaming' ||
|
|
38
|
+
entryKind === 'bidi' ||
|
|
39
|
+
requests.length > 1;
|
|
40
|
+
|
|
41
|
+
if (!useEnvelopedRequest) {
|
|
42
|
+
return requestCodec.encode(requests[0] ?? {});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const frames: Uint8Array[] = [];
|
|
46
|
+
for (let i = 0; i < requests.length; i += 1) {
|
|
47
|
+
frames.push(encodeConnectEnvelope(requestCodec.encode(requests[i] ?? {}), 0));
|
|
48
|
+
}
|
|
49
|
+
if (entryKind === 'clientStreaming' || entryKind === 'bidi') {
|
|
50
|
+
frames.push(encodeConnectEnvelope(new Uint8Array(0), CONNECT_FLAG_END_STREAM));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let bodyLength = 0;
|
|
54
|
+
for (let i = 0; i < frames.length; i += 1) {
|
|
55
|
+
bodyLength += frames[i]!.byteLength;
|
|
56
|
+
}
|
|
57
|
+
const body = new Uint8Array(bodyLength);
|
|
58
|
+
let offset = 0;
|
|
59
|
+
for (let i = 0; i < frames.length; i += 1) {
|
|
60
|
+
body.set(frames[i]!, offset);
|
|
61
|
+
offset += frames[i]!.byteLength;
|
|
62
|
+
}
|
|
63
|
+
return body;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function throwIfEndStreamError(
|
|
67
|
+
data: Uint8Array,
|
|
68
|
+
rpcPath: string,
|
|
69
|
+
status?: number
|
|
70
|
+
): void {
|
|
71
|
+
if (data.byteLength === 0) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const json = JSON.parse(bytesToUtf8(data)) as {
|
|
75
|
+
error?: { code?: string; message?: string };
|
|
76
|
+
code?: string;
|
|
77
|
+
message?: string;
|
|
78
|
+
};
|
|
79
|
+
const errBody = json.error ?? json;
|
|
80
|
+
if (errBody.code || errBody.message) {
|
|
81
|
+
throw connectErrorFromJson(errBody, rpcPath, status);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function* yieldConnectEnvelopes(
|
|
86
|
+
envelopes: { flags: number; data: Uint8Array }[],
|
|
87
|
+
responseCodec: MessageCodec,
|
|
88
|
+
input: StreamCallInput,
|
|
89
|
+
status?: number
|
|
90
|
+
): AsyncGenerator<Record<string, unknown>, void, undefined> {
|
|
91
|
+
for (let i = 0; i < envelopes.length; i += 1) {
|
|
92
|
+
const envelope = envelopes[i]!;
|
|
93
|
+
if (envelope.flags & CONNECT_FLAG_END_STREAM) {
|
|
94
|
+
throwIfEndStreamError(envelope.data, input.entry.rpcPath, status);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const message = responseCodec.decode(envelope.data);
|
|
98
|
+
if (input.onMessage) {
|
|
99
|
+
input.onMessage(message);
|
|
100
|
+
}
|
|
101
|
+
yield message;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function fetchConnectStreamResponse(
|
|
106
|
+
config: ResolvedTransportConfig,
|
|
107
|
+
input: StreamCallInput,
|
|
108
|
+
requestBody: Uint8Array
|
|
109
|
+
): Promise<Response> {
|
|
110
|
+
const path = config.pathForMethod(input.entry);
|
|
111
|
+
const url = `${config.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
|
112
|
+
const headers = await buildHeaders(
|
|
113
|
+
config,
|
|
114
|
+
'application/connect+proto',
|
|
115
|
+
input.entry.rpcPath,
|
|
116
|
+
input.headers
|
|
117
|
+
);
|
|
118
|
+
headers['Connect-Protocol-Version'] = '1';
|
|
119
|
+
headers.Accept = 'application/connect+proto';
|
|
120
|
+
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
const timeoutId = setTimeout(() => controller.abort(), config.timeoutMs);
|
|
123
|
+
const onAbort = () => controller.abort();
|
|
124
|
+
|
|
125
|
+
if (input.signal) {
|
|
126
|
+
if (input.signal.aborted) {
|
|
127
|
+
clearTimeout(timeoutId);
|
|
128
|
+
throw new ProtoClientError({
|
|
129
|
+
code: 'ABORTED',
|
|
130
|
+
message: 'Request was aborted before send',
|
|
131
|
+
rpcPath: input.entry.rpcPath,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
input.signal.addEventListener('abort', onAbort, { once: true });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
try {
|
|
139
|
+
return await config.fetchImpl(url, {
|
|
140
|
+
method: 'POST',
|
|
141
|
+
headers,
|
|
142
|
+
body: requestBody as unknown as BodyInit,
|
|
143
|
+
signal: controller.signal,
|
|
144
|
+
});
|
|
145
|
+
} catch (cause) {
|
|
146
|
+
if (controller.signal.aborted) {
|
|
147
|
+
throw new ProtoClientError({
|
|
148
|
+
code: input.signal?.aborted ? 'ABORTED' : 'TIMEOUT',
|
|
149
|
+
message: input.signal?.aborted
|
|
150
|
+
? 'Request was aborted'
|
|
151
|
+
: `Stream timed out after ${config.timeoutMs}ms`,
|
|
152
|
+
rpcPath: input.entry.rpcPath,
|
|
153
|
+
cause,
|
|
154
|
+
retryable: !input.signal?.aborted,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
throw new ProtoClientError({
|
|
158
|
+
code: 'NETWORK',
|
|
159
|
+
message: `Network error streaming ${input.entry.rpcPath}`,
|
|
160
|
+
rpcPath: input.entry.rpcPath,
|
|
161
|
+
cause,
|
|
162
|
+
retryable: true,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
} finally {
|
|
166
|
+
clearTimeout(timeoutId);
|
|
167
|
+
if (input.signal) {
|
|
168
|
+
input.signal.removeEventListener('abort', onAbort);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function assertOkConnectResponse(response: Response, rpcPath: string): void {
|
|
174
|
+
if (response.ok) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// Body already consumed by caller via text() if needed — here we only throw generic.
|
|
178
|
+
throw new ProtoClientError({
|
|
179
|
+
code: 'HTTP',
|
|
180
|
+
message: `HTTP ${response.status} for ${rpcPath}`,
|
|
181
|
+
status: response.status,
|
|
182
|
+
rpcPath,
|
|
183
|
+
retryable: response.status >= 500,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function* streamConnect(
|
|
188
|
+
config: ResolvedTransportConfig,
|
|
189
|
+
codecs: CodecRegistry,
|
|
190
|
+
input: StreamCallInput
|
|
191
|
+
): AsyncGenerator<Record<string, unknown>, void, undefined> {
|
|
192
|
+
const { entry } = input;
|
|
193
|
+
const requestCodec = codecs.get(entry.requestType);
|
|
194
|
+
const responseCodec = codecs.get(entry.responseType);
|
|
195
|
+
if (!requestCodec || !responseCodec) {
|
|
196
|
+
throw new ProtoClientError({
|
|
197
|
+
code: 'INVALID_ARGUMENT',
|
|
198
|
+
message: `Missing codec for ${entry.requestType} or ${entry.responseType}`,
|
|
199
|
+
rpcPath: entry.rpcPath,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const requests = await collectRequests(input);
|
|
204
|
+
if (
|
|
205
|
+
(entry.kind === 'clientStreaming' || entry.kind === 'bidi') &&
|
|
206
|
+
requests.length === 0
|
|
207
|
+
) {
|
|
208
|
+
throw new ProtoClientError({
|
|
209
|
+
code: 'INVALID_ARGUMENT',
|
|
210
|
+
message: 'Client streaming requires at least one request message',
|
|
211
|
+
rpcPath: entry.rpcPath,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const requestBody = buildConnectRequestBody(entry.kind, requests, requestCodec);
|
|
216
|
+
const response = await fetchConnectStreamResponse(config, input, requestBody);
|
|
217
|
+
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
let text = '';
|
|
220
|
+
try {
|
|
221
|
+
text = await response.text();
|
|
222
|
+
} catch {
|
|
223
|
+
text = '';
|
|
224
|
+
}
|
|
225
|
+
const connectErr = tryParseConnectError(text, entry.rpcPath, response.status);
|
|
226
|
+
if (connectErr) {
|
|
227
|
+
throw connectErr;
|
|
228
|
+
}
|
|
229
|
+
assertOkConnectResponse(response, entry.rpcPath);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const contentType = response.headers.get('content-type') || '';
|
|
233
|
+
|
|
234
|
+
if (response.body && typeof response.body.getReader === 'function') {
|
|
235
|
+
for await (const envelope of readConnectEnvelopeStream(
|
|
236
|
+
response.body,
|
|
237
|
+
config.maxResponseBytes
|
|
238
|
+
)) {
|
|
239
|
+
if (envelope.flags & CONNECT_FLAG_END_STREAM) {
|
|
240
|
+
throwIfEndStreamError(envelope.data, entry.rpcPath, response.status);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const message = responseCodec.decode(envelope.data);
|
|
244
|
+
if (input.onMessage) {
|
|
245
|
+
input.onMessage(message);
|
|
246
|
+
}
|
|
247
|
+
yield message;
|
|
248
|
+
}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
253
|
+
if (buffer.byteLength > config.maxResponseBytes) {
|
|
254
|
+
throw new ProtoClientError({
|
|
255
|
+
code: 'PAYLOAD_TOO_LARGE',
|
|
256
|
+
message: 'Stream response exceeds maxResponseBytes',
|
|
257
|
+
rpcPath: entry.rpcPath,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const looksLikeRawProto =
|
|
262
|
+
contentType.includes('proto') &&
|
|
263
|
+
!contentType.includes('connect') &&
|
|
264
|
+
buffer.byteLength > 0 &&
|
|
265
|
+
buffer[0]! > 2;
|
|
266
|
+
|
|
267
|
+
if (looksLikeRawProto) {
|
|
268
|
+
const message = await unaryCall(config, codecs, input);
|
|
269
|
+
if (input.onMessage) {
|
|
270
|
+
input.onMessage(message);
|
|
271
|
+
}
|
|
272
|
+
yield message;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const envelopes = decodeConnectEnvelopes(buffer);
|
|
277
|
+
if (envelopes.length === 0 && buffer.byteLength > 0) {
|
|
278
|
+
const message = responseCodec.decode(buffer);
|
|
279
|
+
if (input.onMessage) {
|
|
280
|
+
input.onMessage(message);
|
|
281
|
+
}
|
|
282
|
+
yield message;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
yield* yieldConnectEnvelopes(envelopes, responseCodec, input, response.status);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Streaming helpers.
|
|
291
|
+
* - HTTP+protobuf: unary only
|
|
292
|
+
* - Connect: server-streaming via envelope frames; client/bidi send enveloped requests
|
|
293
|
+
* - native-grpc: bridge streaming when available
|
|
294
|
+
*/
|
|
295
|
+
export async function* streamCall(
|
|
296
|
+
config: ResolvedTransportConfig,
|
|
297
|
+
codecs: CodecRegistry,
|
|
298
|
+
input: StreamCallInput
|
|
299
|
+
): AsyncGenerator<Record<string, unknown>, void, undefined> {
|
|
300
|
+
const { entry } = input;
|
|
301
|
+
|
|
302
|
+
if (entry.kind === 'unary') {
|
|
303
|
+
throw new ProtoClientError({
|
|
304
|
+
code: 'UNSUPPORTED',
|
|
305
|
+
message: `Method ${entry.rpcPath} is unary; use the promise API`,
|
|
306
|
+
rpcPath: entry.rpcPath,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (config.transport === 'http') {
|
|
311
|
+
throw new ProtoClientError({
|
|
312
|
+
code: 'UNSUPPORTED',
|
|
313
|
+
message:
|
|
314
|
+
'Streaming requires transport "connect" or "native-grpc". HTTP+protobuf is unary-only.',
|
|
315
|
+
rpcPath: entry.rpcPath,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (config.transport === 'native-grpc') {
|
|
320
|
+
const { nativeGrpcStream } = await import('./native-grpc');
|
|
321
|
+
yield* nativeGrpcStream(config, codecs, input);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
yield* streamConnect(config, codecs, input);
|
|
326
|
+
}
|