@trevrpc/trevrpc-js 0.2.3 → 1.0.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 (42) hide show
  1. package/README.md +89 -47
  2. package/bin/protoc-gen-trevrpc-js.js +1 -1
  3. package/package.json +11 -41
  4. package/src/bytes.js +10 -0
  5. package/src/call.js +287 -0
  6. package/src/channel.js +131 -296
  7. package/src/client.js +203 -1292
  8. package/src/framing.js +125 -519
  9. package/src/generator.js +26 -103
  10. package/src/index.d.ts +79 -452
  11. package/src/index.js +4 -3
  12. package/src/status.js +24 -70
  13. package/src/wire.js +4 -59
  14. package/examples/greeter/README.md +0 -35
  15. package/examples/greeter/client.js +0 -172
  16. package/examples/greeter/greeter.node.trevrpc.d.ts +0 -53
  17. package/examples/greeter/greeter.node.trevrpc.js +0 -9
  18. package/examples/greeter/greeter.proto +0 -18
  19. package/examples/greeter/greeter.trevrpc.d.ts +0 -55
  20. package/examples/greeter/greeter.trevrpc.js +0 -103
  21. package/examples/greeter/index.html +0 -140
  22. package/examples/greeter/static-server.js +0 -168
  23. package/src/advanced.d.ts +0 -29
  24. package/src/advanced.js +0 -1
  25. package/src/browser-channel.js +0 -49
  26. package/src/connect.js +0 -6
  27. package/src/connect.node.js +0 -6
  28. package/src/index.node.d.ts +0 -10
  29. package/src/index.node.js +0 -3
  30. package/src/native-loader.js +0 -118
  31. package/src/node-advanced.d.ts +0 -27
  32. package/src/node-advanced.js +0 -1
  33. package/src/node-generated.d.ts +0 -24
  34. package/src/node-generated.js +0 -126
  35. package/src/node-index.d.ts +0 -1
  36. package/src/node-index.js +0 -7
  37. package/src/node.d.ts +0 -298
  38. package/src/node.js +0 -1456
  39. package/src/runtime.js +0 -66
  40. package/src/server-response.js +0 -49
  41. package/src/timer.js +0 -29
  42. package/src/webtransport.js +0 -639
@@ -1,126 +0,0 @@
1
- import { marshalMessage, unmarshalMessage } from "./framing.js";
2
- import { isStreamingServerResponse, isUnaryServerResponse } from "./server-response.js";
3
- import { Code, statusError } from "./status.js";
4
- import { RpcStreamFrameKind } from "./wire.js";
5
-
6
- /** Registers typed generated handlers on a Node server. */
7
- export function registerTypedService(server, root, service, handlers) {
8
- for (const [jsName, method] of Object.entries(service.methods)) {
9
- const handler = handlers[jsName] ?? handlers[method.name];
10
- if (handler == null) {
11
- continue;
12
- }
13
- const requestType = root.lookupType(method.inputType);
14
- const responseType = root.lookupType(method.outputType);
15
- server.register(service.fullName, method.name, method.kind, async (call) => {
16
- await dispatchTypedNodeHandler(call, handler, method.kind, requestType, responseType);
17
- });
18
- }
19
- return server;
20
- }
21
-
22
- /** Dispatches one typed generated Node handler. */
23
- export async function dispatchTypedNodeHandler(call, handler, kind, requestType, responseType) {
24
- if (kind === "unary") {
25
- const request = unmarshalMessage(requestType, call.request.body ?? new Uint8Array(0));
26
- const response = await handler(request, call);
27
- const envelope = isUnaryServerResponse(response) ? response : null;
28
- await call.respond({
29
- body: marshalMessage(responseType, envelope == null ? response : envelope.message),
30
- metadata: envelope?.metadata ?? {},
31
- });
32
- return;
33
- }
34
-
35
- if (kind === "clientStreaming") {
36
- const response = await handler(decodeTypedNodeRequests(call, requestType), call);
37
- const envelope = isUnaryServerResponse(response) ? response : null;
38
- await call.sendMessage(
39
- marshalMessage(responseType, envelope == null ? response : envelope.message),
40
- );
41
- await call.finishStream(Code.Ok, "", envelope?.metadata ?? {});
42
- return;
43
- }
44
-
45
- const request =
46
- kind === "serverStreaming"
47
- ? unmarshalMessage(requestType, call.request.body ?? new Uint8Array(0))
48
- : decodeTypedNodeRequests(call, requestType);
49
- const response = await handler(request, call);
50
- const envelope = isStreamingServerResponse(response) ? response : null;
51
- await writeTypedResponseMessages(
52
- call,
53
- envelope == null ? response : envelope.messages,
54
- responseType,
55
- );
56
- const status = envelope?.status;
57
- await call.finishStream(status?.code ?? Code.Ok, status?.message ?? "", status?.metadata ?? {});
58
- }
59
-
60
- async function writeTypedResponseMessages(call, messages, responseType) {
61
- const iterator = responseIterator(messages ?? []);
62
- try {
63
- for (;;) {
64
- const result = await nextTypedResponseBatch(iterator, call.writeBatchMaxMessages ?? 16);
65
- if (result.done) {
66
- return;
67
- }
68
- await call.sendMany(result.value.map((message) => marshalMessage(responseType, message)));
69
- }
70
- } catch (error) {
71
- try {
72
- await iterator.return?.();
73
- } catch {
74
- // Preserve the send or iterator error, matching for-await cleanup behavior.
75
- }
76
- throw error;
77
- }
78
- }
79
-
80
- function responseIterator(messages) {
81
- if (typeof messages?.[Symbol.asyncIterator] === "function") {
82
- return messages[Symbol.asyncIterator]();
83
- }
84
- if (typeof messages?.[Symbol.iterator] === "function") {
85
- const iterator = messages[Symbol.iterator]();
86
- return {
87
- next: () => Promise.resolve(iterator.next()),
88
- return: () =>
89
- Promise.resolve(
90
- typeof iterator.return === "function"
91
- ? iterator.return()
92
- : { done: true, value: undefined },
93
- ),
94
- };
95
- }
96
- throw new TypeError("streaming handler must return an iterable or async iterable");
97
- }
98
-
99
- async function nextTypedResponseBatch(iterator, maxMessages) {
100
- if (typeof iterator.nextBatch === "function") {
101
- return await iterator.nextBatch(maxMessages);
102
- }
103
- const result = await iterator.next();
104
- return result.done ? result : { done: false, value: [result.value] };
105
- }
106
-
107
- async function* decodeTypedNodeRequests(call, requestType) {
108
- for (;;) {
109
- const frame = await call.recv();
110
- if (frame == null) {
111
- return;
112
- }
113
- if (frame.kind === RpcStreamFrameKind.Message) {
114
- yield unmarshalMessage(requestType, frame.body ?? new Uint8Array(0));
115
- continue;
116
- }
117
- if (frame.kind === RpcStreamFrameKind.Status) {
118
- const code = frame.status ?? Code.Ok;
119
- if (code !== Code.Ok) {
120
- throw statusError(code, frame.message ?? "", frame.metadata ?? {});
121
- }
122
- return;
123
- }
124
- throw statusError(Code.InvalidArgument, "request stream contained an unknown frame kind");
125
- }
126
- }
@@ -1 +0,0 @@
1
- export * from "./node.js";
package/src/node-index.js DELETED
@@ -1,7 +0,0 @@
1
- export {
2
- Channel,
3
- NodeServer,
4
- NodeServerCall,
5
- bearerAuthorizer,
6
- metadataValueAuthorizer,
7
- } from "./node.js";
package/src/node.d.ts DELETED
@@ -1,298 +0,0 @@
1
- import type {
2
- ChannelLifecycleEvent,
3
- ChannelLifecycleOptions,
4
- ChannelState,
5
- RpcChannel,
6
- MetadataInput,
7
- RpcKindValue,
8
- RpcMethodKind,
9
- RpcResponseMessage,
10
- RpcServiceDescriptor,
11
- RpcStreamFrameMessage,
12
- Transport,
13
- } from "./index.js";
14
-
15
- type TrevRpcEventListener = ((event: Event) => void) | { handleEvent(event: Event): void };
16
- interface TrevRpcEventListenerOptions {
17
- capture?: boolean;
18
- }
19
- interface TrevRpcAddEventListenerOptions extends TrevRpcEventListenerOptions {
20
- once?: boolean;
21
- passive?: boolean;
22
- signal?: AbortSignal;
23
- }
24
-
25
- export interface NodeEndpoint {
26
- host: string;
27
- port: number;
28
- }
29
-
30
- export interface NodeConnectOptions {
31
- caCertFile?: string;
32
- skipCertificateValidation?: boolean;
33
- maxStreamsPerSession?: number;
34
- idleTimeoutMs?: number;
35
- maxFrameSize?: number;
36
- maxPendingSendBytes?: number;
37
- maxPendingSendCount?: number;
38
- signal?: AbortSignal;
39
- }
40
-
41
- export interface NodeChannelOptions extends NodeConnectOptions, ChannelLifecycleOptions {
42
- /** Bounds initial readiness only. Later reconnects continue until close(). */
43
- timeoutMs?: number;
44
- }
45
-
46
- export interface NodeChannelTarget extends NodeChannelOptions {
47
- host: string;
48
- port?: number;
49
- }
50
-
51
- export interface NodeRpcStartedEvent {
52
- service: string;
53
- method: string;
54
- requestBodyLength: number;
55
- kind: RpcKindValue;
56
- }
57
-
58
- export interface NodeRpcFinishedEvent extends NodeRpcStartedEvent {
59
- responseBodyLength: number;
60
- status: number;
61
- elapsedMs?: number;
62
- }
63
-
64
- export interface NodeLogEvent {
65
- level: "debug" | "info" | "warn" | "error" | string;
66
- event: string;
67
- message?: string;
68
- service?: string;
69
- method?: string;
70
- status?: number;
71
- }
72
-
73
- export interface NodeServerMetrics {
74
- rpcStarted?(event: NodeRpcStartedEvent): void;
75
- rpcFinished?(event: NodeRpcFinishedEvent): void;
76
- started?(event: NodeRpcStartedEvent): void;
77
- finished?(event: NodeRpcFinishedEvent): void;
78
- }
79
-
80
- export interface NodeServerLogger {
81
- log?(event: NodeLogEvent): void;
82
- debug?(event: NodeLogEvent): void;
83
- info?(event: NodeLogEvent): void;
84
- warn?(event: NodeLogEvent): void;
85
- error?(event: NodeLogEvent): void;
86
- }
87
-
88
- export type NodeServerAuthorizationResult =
89
- | void
90
- | boolean
91
- | {
92
- code?: number;
93
- status?: number;
94
- message?: string;
95
- statusMessage?: string;
96
- metadata?: MetadataInput;
97
- };
98
-
99
- export type NodeServerAuthorizer = (
100
- call: NodeServerCall,
101
- ) => NodeServerAuthorizationResult | Promise<NodeServerAuthorizationResult>;
102
-
103
- export interface NodeHttp3AdmissionRequest {
104
- path: string;
105
- authority: string;
106
- secure: boolean;
107
- }
108
-
109
- export type NodeHttp3Admission = (request: NodeHttp3AdmissionRequest) => boolean;
110
-
111
- export interface NodeListenOptions extends NodeConnectOptions {
112
- host?: string;
113
- port?: number;
114
- path?: string;
115
- origin?: string;
116
- certFile?: string;
117
- keyFile?: string;
118
- maxSessionsPerConnection?: number;
119
- /** Enables ordinary HTTP/3 POST requests. Disabled by default. */
120
- enableHttp3?: boolean;
121
- /** HTTP/3 POST path. Defaults to /trevrpc. */
122
- http3Path?: string;
123
- /**
124
- * Synchronous request admission hook run before RPC framing is read. The
125
- * native wait is bounded by initialRequestTimeoutMs.
126
- */
127
- http3Admission?: NodeHttp3Admission;
128
- authorizer?: NodeServerAuthorizer;
129
- metrics?: NodeServerMetrics;
130
- logger?: NodeServerLogger | ((event: NodeLogEvent) => void);
131
- maxStreamMessages?: number;
132
- /** Initial HTTP/RPC request timeout. Defaults to 10000 ms. */
133
- initialRequestTimeoutMs?: number;
134
- streamIdleTimeoutMs?: number;
135
- }
136
-
137
- /** Native Node channel with background connection reconnection. */
138
- export class Channel extends EventTarget implements RpcChannel {
139
- readonly endpoint: Readonly<NodeEndpoint>;
140
- readonly options: Readonly<NodeChannelOptions>;
141
- readonly ready: boolean;
142
- readonly state: ChannelState;
143
- readonly generation: number;
144
-
145
- constructor(target: string | URL | NodeChannelTarget, options?: NodeChannelOptions);
146
-
147
- /** Creates a native channel and waits for its first ready generation. */
148
- static connect(
149
- target: string | URL | NodeChannelTarget,
150
- options?: NodeChannelOptions,
151
- ): Promise<Channel>;
152
- /** Waits for the current or next connection generation to become ready. */
153
- waitUntilReady(): Promise<void>;
154
- /** Sends a unary call on the current generation without replaying it. */
155
- call(
156
- request: Parameters<Transport["call"]>[0],
157
- options?: Parameters<Transport["call"]>[1],
158
- ): Promise<RpcResponseMessage>;
159
- /** Starts a streaming call on the current generation without resuming it later. */
160
- streamingCall(
161
- request: Parameters<Transport["streamingCall"]>[0],
162
- requestBody: AsyncIterable<Uint8Array>,
163
- options?: Parameters<Transport["streamingCall"]>[2],
164
- ): Promise<AsyncIterableIterator<RpcStreamFrameMessage>>;
165
- /** Stops reconnecting and closes the current generation. */
166
- close(): void;
167
- addEventListener(
168
- type: "statechange" | ChannelState,
169
- callback: (event: ChannelLifecycleEvent) => void,
170
- options?: boolean | TrevRpcAddEventListenerOptions,
171
- ): void;
172
- addEventListener(
173
- type: string,
174
- callback: TrevRpcEventListener | null,
175
- options?: boolean | TrevRpcAddEventListenerOptions,
176
- ): void;
177
- removeEventListener(
178
- type: "statechange" | ChannelState,
179
- callback: (event: ChannelLifecycleEvent) => void,
180
- options?: boolean | TrevRpcEventListenerOptions,
181
- ): void;
182
- removeEventListener(
183
- type: string,
184
- callback: TrevRpcEventListener | null,
185
- options?: boolean | TrevRpcEventListenerOptions,
186
- ): void;
187
- }
188
-
189
- export type NodeServerUnaryResult =
190
- | RpcResponseMessage
191
- | Uint8Array
192
- | ArrayBuffer
193
- | ArrayBufferView
194
- | readonly number[];
195
- export type NodeServerStreamingResult = AsyncIterable<
196
- Uint8Array | ArrayBuffer | ArrayBufferView | readonly number[]
197
- >;
198
-
199
- export type NodeServerHandler = (
200
- call: NodeServerCall,
201
- ) =>
202
- | void
203
- | NodeServerUnaryResult
204
- | NodeServerStreamingResult
205
- | Promise<void | NodeServerUnaryResult | NodeServerStreamingResult>;
206
-
207
- /** Raw server call passed to NodeServer handlers. */
208
- export class NodeServerCall {
209
- request: {
210
- service: string;
211
- method: string;
212
- body: Uint8Array;
213
- metadata: Record<string, Uint8Array>;
214
- kind: RpcKindValue;
215
- version: number;
216
- timeoutNanos?: string;
217
- };
218
- completed: boolean;
219
- deferred: boolean;
220
- responseBodyLength: number;
221
- finalStatus: number;
222
- startedAt: number;
223
- completedAt: number | null;
224
- /** Aborts when the deadline, cancellation, or server shutdown settles first. */
225
- readonly signal: AbortSignal;
226
- /** Absolute peer deadline captured from the native call context, or null when absent. */
227
- readonly deadline: Date | null;
228
-
229
- /** Keeps the call open after the handler returns. */
230
- defer(): this;
231
- /** Sends a unary response and completes the call. */
232
- respond(
233
- response?: RpcResponseMessage | Uint8Array | ArrayBuffer | ArrayBufferView | readonly number[],
234
- ): Promise<void>;
235
- /** Sends one streaming response message. */
236
- sendMessage(body: Uint8Array | ArrayBuffer | ArrayBufferView | readonly number[]): Promise<void>;
237
- /** Sends multiple streaming response messages. */
238
- sendMany(
239
- bodies: Iterable<Uint8Array | ArrayBuffer | ArrayBufferView | readonly number[]>,
240
- ): Promise<void>;
241
- /** Receives one streaming request frame, or null after EOF. */
242
- recv(): Promise<RpcStreamFrameMessage | null>;
243
- /** Sends the terminal streaming status and completes the call. */
244
- finishStream(status?: number, message?: string, metadata?: MetadataInput): Promise<void>;
245
- /** Cancels and closes the call. */
246
- close(reason?: unknown): void;
247
- }
248
-
249
- /** Native Node server backed by trevrpc-c and MsQuic. */
250
- export class NodeServer {
251
- port: number;
252
- maxFrameSize?: number;
253
- closed: Promise<void> | null;
254
-
255
- /** Creates a native QUIC and WebTransport TrevRPC server backed by trevrpc-c. */
256
- static listen(
257
- urlOrOptions: string | URL | NodeListenOptions,
258
- options?: NodeListenOptions,
259
- ): Promise<NodeServer>;
260
-
261
- /** Registers one raw RPC handler. */
262
- register(
263
- service: string,
264
- method: string,
265
- kind: RpcKindValue | RpcMethodKind,
266
- handler: NodeServerHandler,
267
- ): this;
268
-
269
- /** Registers handlers for a generated service descriptor. */
270
- registerService(service: RpcServiceDescriptor, handlers: Record<string, NodeServerHandler>): this;
271
-
272
- /** Sets an async authorizer that runs before registered handlers. */
273
- setAuthorizer(authorizer?: NodeServerAuthorizer | null): this;
274
- /** Clears the server authorizer. */
275
- clearAuthorizer(): this;
276
- /** Sets metrics callbacks. */
277
- setMetrics(metrics?: NodeServerMetrics | null): this;
278
- /** Clears metrics callbacks. */
279
- clearMetrics(): this;
280
- /** Sets a logger function or logger object. */
281
- setLogger(logger?: NodeServerLogger | ((event: NodeLogEvent) => void) | null): this;
282
- /** Clears the logger. */
283
- clearLogger(): this;
284
-
285
- /** Starts accepting RPCs. The returned promise resolves after close. */
286
- serve(): Promise<void>;
287
- /** Requests graceful server shutdown and drains already admitted calls. */
288
- close(): void;
289
- }
290
-
291
- /** Creates an authorizer requiring one metadata key/value pair. */
292
- export function metadataValueAuthorizer(
293
- key: string,
294
- value: string | Uint8Array | ArrayBuffer | ArrayBufferView | readonly number[],
295
- ): NodeServerAuthorizer;
296
-
297
- /** Creates an authorizer requiring an Authorization: Bearer token metadata value. */
298
- export function bearerAuthorizer(token: string): NodeServerAuthorizer;