@trevrpc/trevrpc-js 0.1.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/LICENSE +21 -0
- package/README.md +202 -0
- package/bin/protoc-gen-trevrpc-js.js +17 -0
- package/examples/greeter/README.md +35 -0
- package/examples/greeter/client.js +172 -0
- package/examples/greeter/greeter.node.trevrpc.d.ts +53 -0
- package/examples/greeter/greeter.node.trevrpc.js +9 -0
- package/examples/greeter/greeter.proto +18 -0
- package/examples/greeter/greeter.trevrpc.d.ts +55 -0
- package/examples/greeter/greeter.trevrpc.js +103 -0
- package/examples/greeter/index.html +140 -0
- package/examples/greeter/static-server.js +168 -0
- package/package.json +89 -0
- package/src/advanced.d.ts +29 -0
- package/src/advanced.js +1 -0
- package/src/browser-channel.js +45 -0
- package/src/channel.js +375 -0
- package/src/client.js +1397 -0
- package/src/connect.js +6 -0
- package/src/connect.node.js +6 -0
- package/src/framing.js +618 -0
- package/src/generator.js +868 -0
- package/src/index.d.ts +577 -0
- package/src/index.js +3 -0
- package/src/index.node.d.ts +10 -0
- package/src/index.node.js +3 -0
- package/src/metadata.js +112 -0
- package/src/native-loader.js +94 -0
- package/src/node-advanced.d.ts +27 -0
- package/src/node-advanced.js +1 -0
- package/src/node-generated.d.ts +24 -0
- package/src/node-generated.js +126 -0
- package/src/node-index.d.ts +1 -0
- package/src/node-index.js +7 -0
- package/src/node.d.ts +298 -0
- package/src/node.js +1456 -0
- package/src/runtime.js +66 -0
- package/src/server-response.js +49 -0
- package/src/status.js +145 -0
- package/src/timer.js +29 -0
- package/src/webtransport.js +624 -0
- package/src/wire.js +403 -0
package/src/runtime.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export {
|
|
2
|
+
Code,
|
|
3
|
+
FrameTooLargeError,
|
|
4
|
+
TrevRpcError,
|
|
5
|
+
cancelled,
|
|
6
|
+
codeFromNumber,
|
|
7
|
+
codeName,
|
|
8
|
+
deadlineExceeded,
|
|
9
|
+
internal,
|
|
10
|
+
invalidArgument,
|
|
11
|
+
isOkStatus,
|
|
12
|
+
resourceExhausted,
|
|
13
|
+
statusError,
|
|
14
|
+
statusFromResponse,
|
|
15
|
+
unavailable,
|
|
16
|
+
} from "./status.js";
|
|
17
|
+
export {
|
|
18
|
+
MaxMetadataEntries,
|
|
19
|
+
MaxMetadataKeyLen,
|
|
20
|
+
MaxMetadataTotalSize,
|
|
21
|
+
MaxMetadataValueLen,
|
|
22
|
+
ReservedMetadataPrefix,
|
|
23
|
+
metadataValueToBytes,
|
|
24
|
+
normalizeMetadata,
|
|
25
|
+
normalizeMetadataKey,
|
|
26
|
+
validateMetadata,
|
|
27
|
+
} from "./metadata.js";
|
|
28
|
+
export {
|
|
29
|
+
RpcKind,
|
|
30
|
+
RpcRequest,
|
|
31
|
+
RpcResponse,
|
|
32
|
+
RpcStreamFrame,
|
|
33
|
+
RpcStreamFrameKind,
|
|
34
|
+
WireVersion,
|
|
35
|
+
createRoot,
|
|
36
|
+
messageFrame,
|
|
37
|
+
protobuf,
|
|
38
|
+
wireRoot,
|
|
39
|
+
} from "./wire.js";
|
|
40
|
+
export {
|
|
41
|
+
DefaultMaxFrameSize,
|
|
42
|
+
FrameReader,
|
|
43
|
+
decodeFrame,
|
|
44
|
+
decodeStreamFrameBody,
|
|
45
|
+
encodeFrame,
|
|
46
|
+
encodeMessageStreamFrame,
|
|
47
|
+
encodeMessageStreamFrames,
|
|
48
|
+
frameBodyLength,
|
|
49
|
+
marshalMessage,
|
|
50
|
+
unmarshalMessage,
|
|
51
|
+
writeFrame,
|
|
52
|
+
writeMessageStreamFrames,
|
|
53
|
+
} from "./framing.js";
|
|
54
|
+
export {
|
|
55
|
+
BidirectionalStreamingCall,
|
|
56
|
+
ClientStreamingCall,
|
|
57
|
+
bidirectionalStreaming,
|
|
58
|
+
clientStreaming,
|
|
59
|
+
createServiceClient,
|
|
60
|
+
defaultCallOptions,
|
|
61
|
+
mergeCallOptions,
|
|
62
|
+
serverStreaming,
|
|
63
|
+
unary,
|
|
64
|
+
unaryWithResponse,
|
|
65
|
+
} from "./client.js";
|
|
66
|
+
export { createStreamingResponse, createUnaryResponse } from "./server-response.js";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { normalizeMetadata } from "./metadata.js";
|
|
2
|
+
import { Code, codeFromNumber } from "./status.js";
|
|
3
|
+
|
|
4
|
+
const UnaryResponseBrand = Symbol("trevrpc.unaryServerResponse");
|
|
5
|
+
const StreamingResponseBrand = Symbol("trevrpc.streamingServerResponse");
|
|
6
|
+
|
|
7
|
+
/** Creates an opaque unary generated-server response envelope. */
|
|
8
|
+
export function createUnaryResponse(message, metadata = {}) {
|
|
9
|
+
return Object.freeze({
|
|
10
|
+
[UnaryResponseBrand]: true,
|
|
11
|
+
message,
|
|
12
|
+
metadata: Object.freeze(normalizeMetadata(metadata)),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Creates an opaque streaming generated-server response envelope. */
|
|
17
|
+
export function createStreamingResponse(messages, status = {}) {
|
|
18
|
+
if (!isIterable(messages)) {
|
|
19
|
+
throw new TypeError("streaming response messages must be an iterable or async iterable");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
[StreamingResponseBrand]: true,
|
|
24
|
+
messages,
|
|
25
|
+
status: Object.freeze({
|
|
26
|
+
code: codeFromNumber(status.code ?? Code.Ok),
|
|
27
|
+
message: status.message ?? "",
|
|
28
|
+
metadata: Object.freeze(normalizeMetadata(status.metadata ?? {})),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Internal generated-dispatcher predicate. */
|
|
34
|
+
export function isUnaryServerResponse(value) {
|
|
35
|
+
return value?.[UnaryResponseBrand] === true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Internal generated-dispatcher predicate. */
|
|
39
|
+
export function isStreamingServerResponse(value) {
|
|
40
|
+
return value?.[StreamingResponseBrand] === true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isIterable(value) {
|
|
44
|
+
return (
|
|
45
|
+
value != null &&
|
|
46
|
+
(typeof value[Symbol.iterator] === "function" ||
|
|
47
|
+
typeof value[Symbol.asyncIterator] === "function")
|
|
48
|
+
);
|
|
49
|
+
}
|
package/src/status.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export const Code = Object.freeze({
|
|
2
|
+
Ok: 0,
|
|
3
|
+
Cancelled: 1,
|
|
4
|
+
Unknown: 2,
|
|
5
|
+
InvalidArgument: 3,
|
|
6
|
+
DeadlineExceeded: 4,
|
|
7
|
+
NotFound: 5,
|
|
8
|
+
AlreadyExists: 6,
|
|
9
|
+
PermissionDenied: 7,
|
|
10
|
+
ResourceExhausted: 8,
|
|
11
|
+
FailedPrecondition: 9,
|
|
12
|
+
Aborted: 10,
|
|
13
|
+
OutOfRange: 11,
|
|
14
|
+
Unimplemented: 12,
|
|
15
|
+
Internal: 13,
|
|
16
|
+
Unavailable: 14,
|
|
17
|
+
DataLoss: 15,
|
|
18
|
+
Unauthenticated: 16,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const CODE_NAMES = Object.freeze([
|
|
22
|
+
"Ok",
|
|
23
|
+
"Cancelled",
|
|
24
|
+
"Unknown",
|
|
25
|
+
"InvalidArgument",
|
|
26
|
+
"DeadlineExceeded",
|
|
27
|
+
"NotFound",
|
|
28
|
+
"AlreadyExists",
|
|
29
|
+
"PermissionDenied",
|
|
30
|
+
"ResourceExhausted",
|
|
31
|
+
"FailedPrecondition",
|
|
32
|
+
"Aborted",
|
|
33
|
+
"OutOfRange",
|
|
34
|
+
"Unimplemented",
|
|
35
|
+
"Internal",
|
|
36
|
+
"Unavailable",
|
|
37
|
+
"DataLoss",
|
|
38
|
+
"Unauthenticated",
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
/** Error carrying a TrevRPC status code, message, and metadata. */
|
|
42
|
+
export class TrevRpcError extends Error {
|
|
43
|
+
/** Creates a TrevRPC status error. */
|
|
44
|
+
constructor(code, message = "", metadata = {}, options = {}) {
|
|
45
|
+
const normalizedCode = codeFromNumber(code);
|
|
46
|
+
super(message === "" ? codeName(normalizedCode) : `${codeName(normalizedCode)}: ${message}`, {
|
|
47
|
+
cause: options.cause,
|
|
48
|
+
});
|
|
49
|
+
this.name = "TrevRpcError";
|
|
50
|
+
this.code = normalizedCode;
|
|
51
|
+
this.statusMessage = message;
|
|
52
|
+
this.metadata = metadata;
|
|
53
|
+
if (Number.isInteger(options.nativeCode)) {
|
|
54
|
+
this.nativeCode = options.nativeCode;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Resource-exhausted status reported when a frame exceeds the configured size limit. */
|
|
60
|
+
export class FrameTooLargeError extends TrevRpcError {
|
|
61
|
+
/** Creates a frame size error. */
|
|
62
|
+
constructor(length, max) {
|
|
63
|
+
super(Code.ResourceExhausted, `frame length ${length} exceeds maximum ${max}`);
|
|
64
|
+
this.name = "FrameTooLargeError";
|
|
65
|
+
this.length = length;
|
|
66
|
+
this.max = max;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Converts a number into a known status code, defaulting unknown values to Unknown. */
|
|
71
|
+
export function codeFromNumber(code) {
|
|
72
|
+
return Number.isInteger(code) && code >= 0 && code < CODE_NAMES.length ? code : Code.Unknown;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Returns the canonical status code name. */
|
|
76
|
+
export function codeName(code) {
|
|
77
|
+
return CODE_NAMES[codeFromNumber(code)];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Creates a TrevRPC status error. */
|
|
81
|
+
export function statusError(code, message = "", metadata = {}) {
|
|
82
|
+
return new TrevRpcError(code, message, metadata);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Builds a status error from an RPC response. */
|
|
86
|
+
export function statusFromResponse(response) {
|
|
87
|
+
if (response == null) {
|
|
88
|
+
return statusError(Code.Internal, "missing RPC response");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return statusError(response.status ?? Code.Ok, response.message ?? "", response.metadata ?? {});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Reports whether a status-like value is OK. */
|
|
95
|
+
export function isOkStatus(status) {
|
|
96
|
+
return status != null && codeFromNumber(status.code) === Code.Ok;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Creates an internal error status. */
|
|
100
|
+
export function internal(message) {
|
|
101
|
+
return statusError(Code.Internal, message);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Creates an invalid-argument status. */
|
|
105
|
+
export function invalidArgument(message) {
|
|
106
|
+
return statusError(Code.InvalidArgument, message);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Creates a deadline-exceeded status. */
|
|
110
|
+
export function deadlineExceeded(message) {
|
|
111
|
+
return statusError(Code.DeadlineExceeded, message);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Creates an unavailable status. */
|
|
115
|
+
export function unavailable(message) {
|
|
116
|
+
return statusError(Code.Unavailable, message);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Creates a resource-exhausted status. */
|
|
120
|
+
export function resourceExhausted(message) {
|
|
121
|
+
return statusError(Code.ResourceExhausted, message);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Creates a cancelled status. */
|
|
125
|
+
export function cancelled(message) {
|
|
126
|
+
return statusError(Code.Cancelled, message);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Converts a transport error into a TrevRPC status error. */
|
|
130
|
+
export function statusFromTransportError(error) {
|
|
131
|
+
if (error instanceof TrevRpcError) {
|
|
132
|
+
return error;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (error?.name === "AbortError") {
|
|
136
|
+
return new TrevRpcError(Code.Cancelled, "transport closed locally", {}, { cause: error });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return new TrevRpcError(
|
|
140
|
+
Code.Unavailable,
|
|
141
|
+
`transport unavailable: ${error?.message ?? String(error)}`,
|
|
142
|
+
{},
|
|
143
|
+
{ cause: error },
|
|
144
|
+
);
|
|
145
|
+
}
|
package/src/timer.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const MaxTimerDelayMs = 2_147_483_647;
|
|
2
|
+
|
|
3
|
+
/** Schedules a cancellable timeout without overflowing platform timer limits. */
|
|
4
|
+
export function scheduleTimeout(callback, delayMs) {
|
|
5
|
+
let remaining = delayMs;
|
|
6
|
+
let timer;
|
|
7
|
+
let cancelled = false;
|
|
8
|
+
|
|
9
|
+
const schedule = () => {
|
|
10
|
+
const chunk = Math.min(remaining, MaxTimerDelayMs);
|
|
11
|
+
timer = setTimeout(() => {
|
|
12
|
+
if (cancelled) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
remaining -= chunk;
|
|
16
|
+
if (remaining > 0) {
|
|
17
|
+
schedule();
|
|
18
|
+
} else {
|
|
19
|
+
callback();
|
|
20
|
+
}
|
|
21
|
+
}, chunk);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
schedule();
|
|
25
|
+
return () => {
|
|
26
|
+
cancelled = true;
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
};
|
|
29
|
+
}
|