@replit/river 0.215.0 → 0.216.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/README.md +47 -0
- package/dist/adapter-BXCk-dmy.d.ts +29 -0
- package/dist/adapter-D5X11kmP.d.cts +29 -0
- package/dist/{chunk-VXRAFUA3.js → chunk-75ZMPCKC.js} +26 -6
- package/dist/{chunk-VXRAFUA3.js.map → chunk-75ZMPCKC.js.map} +1 -1
- package/dist/chunk-SHND2JG6.js +86 -0
- package/dist/chunk-SHND2JG6.js.map +1 -0
- package/dist/{chunk-RDTQZ7HO.js → chunk-ZLMQQI43.js} +12 -2
- package/dist/chunk-ZLMQQI43.js.map +1 -0
- package/dist/{client-BhwlY0-L.d.ts → client-BNc5Pj_4.d.ts} +2 -2
- package/dist/{client-Dk4H7qeg.d.cts → client-BZUvFL6B.d.cts} +2 -2
- package/dist/codec/index.cjs.map +1 -1
- package/dist/codec/index.d.cts +3 -3
- package/dist/codec/index.d.ts +3 -3
- package/dist/codec/index.js +2 -2
- package/dist/{connection-DU9v3y8a.d.ts → connection-ou9w2dSY.d.ts} +3 -3
- package/dist/{connection-CS00EWuS.d.cts → connection-xxgJHs2o.d.cts} +3 -3
- package/dist/{index-CHCzvZ9D.d.cts → index-BAGGleT3.d.cts} +1 -1
- package/dist/{index-uF0cBM7z.d.ts → index-ZWkoesQD.d.ts} +1 -1
- package/dist/logging/index.d.cts +2 -2
- package/dist/logging/index.d.ts +2 -2
- package/dist/{message-aABg0s5M.d.cts → message-CpXWqmJw.d.cts} +1 -1
- package/dist/{message-aABg0s5M.d.ts → message-CpXWqmJw.d.ts} +1 -1
- package/dist/protobuf/codec.cjs +107 -0
- package/dist/protobuf/codec.cjs.map +1 -0
- package/dist/protobuf/codec.d.cts +13 -0
- package/dist/protobuf/codec.d.ts +13 -0
- package/dist/protobuf/codec.js +7 -0
- package/dist/protobuf/codec.js.map +1 -0
- package/dist/protobuf/index.cjs +1877 -0
- package/dist/protobuf/index.cjs.map +1 -0
- package/dist/protobuf/index.d.cts +488 -0
- package/dist/protobuf/index.d.ts +488 -0
- package/dist/protobuf/index.js +1260 -0
- package/dist/protobuf/index.js.map +1 -0
- package/dist/router/index.cjs +1 -1
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +12 -11
- package/dist/router/index.d.ts +12 -11
- package/dist/router/index.js +1 -1
- package/dist/{server-uNzkzIRh.d.ts → server-BPu7Td80.d.ts} +4 -4
- package/dist/{server-BR0DZaWi.d.cts → server-JdnoVO11.d.cts} +4 -4
- package/dist/{services-B5SY771g.d.ts → services-BrTFTO5Q.d.ts} +104 -93
- package/dist/{services-DBv2nmly.d.cts → services-cwGAC2rB.d.cts} +104 -93
- package/dist/testUtil/index.cjs +25 -5
- package/dist/testUtil/index.cjs.map +1 -1
- package/dist/testUtil/index.d.cts +8 -7
- package/dist/testUtil/index.d.ts +8 -7
- package/dist/testUtil/index.js +2 -2
- package/dist/transport/impls/ws/client.cjs +5 -1
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +7 -6
- package/dist/transport/impls/ws/client.d.ts +7 -6
- package/dist/transport/impls/ws/client.js +2 -2
- package/dist/transport/impls/ws/server.cjs +21 -5
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +7 -6
- package/dist/transport/impls/ws/server.d.ts +7 -6
- package/dist/transport/impls/ws/server.js +2 -2
- package/dist/transport/index.cjs +25 -5
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +8 -7
- package/dist/transport/index.d.ts +8 -7
- package/dist/transport/index.js +2 -2
- package/dist/{transport-BOL2p5s-.d.ts → transport-B1MUtXL7.d.ts} +7 -5
- package/dist/{transport-D3jzhFSi.d.cts → transport-BnU3Zb0Q.d.cts} +7 -5
- package/dist/types-BGGvYIJM.d.cts +20 -0
- package/dist/types-BGGvYIJM.d.ts +20 -0
- package/package.json +12 -1
- package/dist/adapter-CgF7vQPu.d.ts +0 -47
- package/dist/adapter-IGrG4KLL.d.cts +0 -47
- package/dist/chunk-RDTQZ7HO.js.map +0 -1
|
@@ -0,0 +1,1877 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// protobuf/index.ts
|
|
21
|
+
var protobuf_exports = {};
|
|
22
|
+
__export(protobuf_exports, {
|
|
23
|
+
CANCEL_CODE: () => CANCEL_CODE,
|
|
24
|
+
Err: () => Err,
|
|
25
|
+
INVALID_REQUEST_CODE: () => INVALID_REQUEST_CODE,
|
|
26
|
+
Ok: () => Ok,
|
|
27
|
+
ProtoCodec: () => ProtoCodec,
|
|
28
|
+
ReadableBrokenError: () => ReadableBrokenError,
|
|
29
|
+
RiverErrorCode: () => RiverErrorCode,
|
|
30
|
+
UNCAUGHT_ERROR_CODE: () => UNCAUGHT_ERROR_CODE,
|
|
31
|
+
UNEXPECTED_DISCONNECT_CODE: () => UNEXPECTED_DISCONNECT_CODE,
|
|
32
|
+
createClient: () => createClient,
|
|
33
|
+
createClientHandshakeOptions: () => createClientHandshakeOptions2,
|
|
34
|
+
createProtoService: () => createProtoService,
|
|
35
|
+
createServer: () => createServer,
|
|
36
|
+
createServerHandshakeOptions: () => createServerHandshakeOptions2,
|
|
37
|
+
isClientError: () => isClientError,
|
|
38
|
+
isProtocolError: () => isProtocolError,
|
|
39
|
+
isRiverError: () => isRiverError,
|
|
40
|
+
isSerializedClientErrorResult: () => isSerializedClientErrorResult,
|
|
41
|
+
isSerializedProtocolErrorResult: () => isSerializedProtocolErrorResult
|
|
42
|
+
});
|
|
43
|
+
module.exports = __toCommonJS(protobuf_exports);
|
|
44
|
+
|
|
45
|
+
// protobuf/codec.ts
|
|
46
|
+
var import_protobuf = require("@bufbuild/protobuf");
|
|
47
|
+
var import_msgpack = require("@msgpack/msgpack");
|
|
48
|
+
|
|
49
|
+
// protobuf/gen/transport_pb.ts
|
|
50
|
+
var import_codegenv2 = require("@bufbuild/protobuf/codegenv2");
|
|
51
|
+
var file_transport = /* @__PURE__ */ (0, import_codegenv2.fileDesc)("Cg90cmFuc3BvcnQucHJvdG8SGHJlcGxpdC5yaXZlci5pbnRlcm5hbC52MSI9ChJQcm9wYWdhdGlvbkNvbnRleHQSEwoLdHJhY2VwYXJlbnQYASABKAkSEgoKdHJhY2VzdGF0ZRgCIAEoCSKuAgoRVHJhbnNwb3J0RW52ZWxvcGUSCgoCaWQYASABKAkSDAoEZnJvbRgCIAEoCRIKCgJ0bxgDIAEoCRILCgNzZXEYBCABKA0SCwoDYWNrGAUgASgNEhEKCXN0cmVhbV9pZBgGIAEoCRIVCg1jb250cm9sX2ZsYWdzGAcgASgNEhQKDHNlcnZpY2VfbmFtZRgIIAEoCRIWCg5wcm9jZWR1cmVfbmFtZRgJIAEoCRI9Cgd0cmFjaW5nGAogASgLMiwucmVwbGl0LnJpdmVyLmludGVybmFsLnYxLlByb3BhZ2F0aW9uQ29udGV4dBIXCg1wYXlsb2FkX2J5dGVzGAsgASgMSAASGQoPcGF5bG9hZF9tc2dwYWNrGAwgASgMSABCDgoMcGF5bG9hZF9raW5kYgZwcm90bzM");
|
|
52
|
+
var TransportEnvelopeSchema = /* @__PURE__ */ (0, import_codegenv2.messageDesc)(file_transport, 1);
|
|
53
|
+
|
|
54
|
+
// protobuf/codec.ts
|
|
55
|
+
var ProtoCodec = {
|
|
56
|
+
toBuffer(obj) {
|
|
57
|
+
const message = coerceTransportMessage(obj);
|
|
58
|
+
return (0, import_protobuf.toBinary)(
|
|
59
|
+
TransportEnvelopeSchema,
|
|
60
|
+
(0, import_protobuf.create)(TransportEnvelopeSchema, toEnvelopeInit(message))
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
fromBuffer(buff) {
|
|
64
|
+
const bytes = buff instanceof Uint8Array ? buff : new Uint8Array(buff);
|
|
65
|
+
return fromEnvelope((0, import_protobuf.fromBinary)(TransportEnvelopeSchema, bytes));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
function coerceTransportMessage(obj) {
|
|
69
|
+
const candidate = obj;
|
|
70
|
+
if (typeof candidate.id !== "string" || typeof candidate.from !== "string" || typeof candidate.to !== "string" || typeof candidate.seq !== "number" || typeof candidate.ack !== "number" || typeof candidate.streamId !== "string" || typeof candidate.controlFlags !== "number" || !("payload" in candidate)) {
|
|
71
|
+
throw new Error("ProtoCodec expects an opaque transport message");
|
|
72
|
+
}
|
|
73
|
+
return candidate;
|
|
74
|
+
}
|
|
75
|
+
function toEnvelopeInit(message) {
|
|
76
|
+
return {
|
|
77
|
+
id: message.id,
|
|
78
|
+
from: message.from,
|
|
79
|
+
to: message.to,
|
|
80
|
+
seq: message.seq,
|
|
81
|
+
ack: message.ack,
|
|
82
|
+
streamId: message.streamId,
|
|
83
|
+
controlFlags: message.controlFlags,
|
|
84
|
+
serviceName: message.serviceName ?? "",
|
|
85
|
+
procedureName: message.procedureName ?? "",
|
|
86
|
+
tracing: message.tracing ? {
|
|
87
|
+
traceparent: message.tracing.traceparent,
|
|
88
|
+
tracestate: message.tracing.tracestate
|
|
89
|
+
} : void 0,
|
|
90
|
+
payloadKind: message.payload instanceof Uint8Array ? { case: "payloadBytes", value: message.payload } : { case: "payloadMsgpack", value: (0, import_msgpack.encode)(message.payload) }
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function fromEnvelope(envelope) {
|
|
94
|
+
return {
|
|
95
|
+
id: envelope.id,
|
|
96
|
+
from: envelope.from,
|
|
97
|
+
to: envelope.to,
|
|
98
|
+
seq: envelope.seq,
|
|
99
|
+
ack: envelope.ack,
|
|
100
|
+
streamId: envelope.streamId,
|
|
101
|
+
controlFlags: envelope.controlFlags,
|
|
102
|
+
payload: decodePayloadKind(envelope),
|
|
103
|
+
...envelope.serviceName === "" ? {} : { serviceName: envelope.serviceName },
|
|
104
|
+
...envelope.procedureName === "" ? {} : { procedureName: envelope.procedureName },
|
|
105
|
+
...envelope.tracing ? {
|
|
106
|
+
tracing: {
|
|
107
|
+
traceparent: envelope.tracing.traceparent,
|
|
108
|
+
tracestate: envelope.tracing.tracestate
|
|
109
|
+
}
|
|
110
|
+
} : {}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function decodePayloadKind(envelope) {
|
|
114
|
+
switch (envelope.payloadKind.case) {
|
|
115
|
+
case "payloadBytes":
|
|
116
|
+
return envelope.payloadKind.value;
|
|
117
|
+
case "payloadMsgpack":
|
|
118
|
+
return (0, import_msgpack.decode)(envelope.payloadKind.value);
|
|
119
|
+
default:
|
|
120
|
+
throw new Error("invalid protobuf transport envelope: missing payload");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// protobuf/client.ts
|
|
125
|
+
var import_value = require("@sinclair/typebox/value");
|
|
126
|
+
|
|
127
|
+
// transport/message.ts
|
|
128
|
+
var import_typebox = require("@sinclair/typebox");
|
|
129
|
+
|
|
130
|
+
// transport/id.ts
|
|
131
|
+
var import_nanoid = require("nanoid");
|
|
132
|
+
var alphabet = (0, import_nanoid.customAlphabet)(
|
|
133
|
+
"1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"
|
|
134
|
+
);
|
|
135
|
+
var generateId = () => alphabet(12);
|
|
136
|
+
|
|
137
|
+
// transport/message.ts
|
|
138
|
+
var TransportMessageSchema = (t) => import_typebox.Type.Object({
|
|
139
|
+
id: import_typebox.Type.String(),
|
|
140
|
+
from: import_typebox.Type.String(),
|
|
141
|
+
to: import_typebox.Type.String(),
|
|
142
|
+
seq: import_typebox.Type.Integer(),
|
|
143
|
+
ack: import_typebox.Type.Integer(),
|
|
144
|
+
serviceName: import_typebox.Type.Optional(import_typebox.Type.String()),
|
|
145
|
+
procedureName: import_typebox.Type.Optional(import_typebox.Type.String()),
|
|
146
|
+
streamId: import_typebox.Type.String(),
|
|
147
|
+
controlFlags: import_typebox.Type.Integer(),
|
|
148
|
+
tracing: import_typebox.Type.Optional(
|
|
149
|
+
import_typebox.Type.Object({
|
|
150
|
+
traceparent: import_typebox.Type.String(),
|
|
151
|
+
tracestate: import_typebox.Type.String()
|
|
152
|
+
})
|
|
153
|
+
),
|
|
154
|
+
payload: t
|
|
155
|
+
});
|
|
156
|
+
var ControlMessageAckSchema = import_typebox.Type.Object({
|
|
157
|
+
type: import_typebox.Type.Literal("ACK")
|
|
158
|
+
});
|
|
159
|
+
var ControlMessageCloseSchema = import_typebox.Type.Object({
|
|
160
|
+
type: import_typebox.Type.Literal("CLOSE")
|
|
161
|
+
});
|
|
162
|
+
var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
|
|
163
|
+
type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
|
|
164
|
+
protocolVersion: import_typebox.Type.String(),
|
|
165
|
+
sessionId: import_typebox.Type.String(),
|
|
166
|
+
/**
|
|
167
|
+
* Specifies what the server's expected session state (from the pov of the client). This can be
|
|
168
|
+
* used by the server to know whether this is a new or a reestablished connection, and whether it
|
|
169
|
+
* is compatible with what it already has.
|
|
170
|
+
*/
|
|
171
|
+
expectedSessionState: import_typebox.Type.Object({
|
|
172
|
+
// what the client expects the server to send next
|
|
173
|
+
nextExpectedSeq: import_typebox.Type.Integer(),
|
|
174
|
+
nextSentSeq: import_typebox.Type.Integer()
|
|
175
|
+
}),
|
|
176
|
+
metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
|
|
177
|
+
});
|
|
178
|
+
var HandshakeErrorRetriableResponseCodes = import_typebox.Type.Union([
|
|
179
|
+
import_typebox.Type.Literal("SESSION_STATE_MISMATCH")
|
|
180
|
+
]);
|
|
181
|
+
var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox.Type.Union([
|
|
182
|
+
// The custom validation handler rejected the handler because the client is unsupported.
|
|
183
|
+
import_typebox.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
|
|
184
|
+
// The custom validation handler rejected the handshake.
|
|
185
|
+
import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
|
|
186
|
+
]);
|
|
187
|
+
var HandshakeErrorFatalResponseCodes = import_typebox.Type.Union([
|
|
188
|
+
HandshakeErrorCustomHandlerFatalResponseCodes,
|
|
189
|
+
// The ciient sent a handshake that doesn't comply with the extended handshake metadata.
|
|
190
|
+
import_typebox.Type.Literal("MALFORMED_HANDSHAKE_META"),
|
|
191
|
+
// The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
|
|
192
|
+
import_typebox.Type.Literal("MALFORMED_HANDSHAKE"),
|
|
193
|
+
// The client's protocol version does not match the server's.
|
|
194
|
+
import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH")
|
|
195
|
+
]);
|
|
196
|
+
var HandshakeErrorResponseCodes = import_typebox.Type.Union([
|
|
197
|
+
HandshakeErrorRetriableResponseCodes,
|
|
198
|
+
HandshakeErrorFatalResponseCodes
|
|
199
|
+
]);
|
|
200
|
+
var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
|
|
201
|
+
type: import_typebox.Type.Literal("HANDSHAKE_RESP"),
|
|
202
|
+
status: import_typebox.Type.Union([
|
|
203
|
+
import_typebox.Type.Object({
|
|
204
|
+
ok: import_typebox.Type.Literal(true),
|
|
205
|
+
sessionId: import_typebox.Type.String()
|
|
206
|
+
}),
|
|
207
|
+
import_typebox.Type.Object({
|
|
208
|
+
ok: import_typebox.Type.Literal(false),
|
|
209
|
+
reason: import_typebox.Type.String(),
|
|
210
|
+
code: HandshakeErrorResponseCodes
|
|
211
|
+
})
|
|
212
|
+
])
|
|
213
|
+
});
|
|
214
|
+
var ControlMessagePayloadSchema = import_typebox.Type.Union([
|
|
215
|
+
ControlMessageCloseSchema,
|
|
216
|
+
ControlMessageAckSchema,
|
|
217
|
+
ControlMessageHandshakeRequestSchema,
|
|
218
|
+
ControlMessageHandshakeResponseSchema
|
|
219
|
+
]);
|
|
220
|
+
var OpaqueTransportMessageSchema = TransportMessageSchema(
|
|
221
|
+
import_typebox.Type.Unknown()
|
|
222
|
+
);
|
|
223
|
+
function closeStreamMessage(streamId) {
|
|
224
|
+
return {
|
|
225
|
+
streamId,
|
|
226
|
+
controlFlags: 8 /* StreamClosedBit */,
|
|
227
|
+
payload: {
|
|
228
|
+
type: "CLOSE"
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function cancelMessage(streamId, payload) {
|
|
233
|
+
return {
|
|
234
|
+
streamId,
|
|
235
|
+
controlFlags: 4 /* StreamCancelBit */,
|
|
236
|
+
payload
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function isStreamOpen(controlFlag) {
|
|
240
|
+
return (
|
|
241
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
|
|
242
|
+
(controlFlag & 2 /* StreamOpenBit */) === 2 /* StreamOpenBit */
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
function isStreamClose(controlFlag) {
|
|
246
|
+
return (
|
|
247
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
|
|
248
|
+
(controlFlag & 8 /* StreamClosedBit */) === 8 /* StreamClosedBit */
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
function isStreamCancel(controlFlag) {
|
|
252
|
+
return (
|
|
253
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
|
|
254
|
+
(controlFlag & 4 /* StreamCancelBit */) === 4 /* StreamCancelBit */
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// router/result.ts
|
|
259
|
+
var import_typebox2 = require("@sinclair/typebox");
|
|
260
|
+
var AnyResultSchema = import_typebox2.Type.Union([
|
|
261
|
+
import_typebox2.Type.Object({
|
|
262
|
+
ok: import_typebox2.Type.Literal(false),
|
|
263
|
+
payload: import_typebox2.Type.Object({
|
|
264
|
+
code: import_typebox2.Type.String(),
|
|
265
|
+
message: import_typebox2.Type.String(),
|
|
266
|
+
extras: import_typebox2.Type.Optional(import_typebox2.Type.Unknown())
|
|
267
|
+
})
|
|
268
|
+
}),
|
|
269
|
+
import_typebox2.Type.Object({
|
|
270
|
+
ok: import_typebox2.Type.Literal(true),
|
|
271
|
+
payload: import_typebox2.Type.Unknown()
|
|
272
|
+
})
|
|
273
|
+
]);
|
|
274
|
+
function Ok(payload) {
|
|
275
|
+
return {
|
|
276
|
+
ok: true,
|
|
277
|
+
payload
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function Err(error) {
|
|
281
|
+
return {
|
|
282
|
+
ok: false,
|
|
283
|
+
payload: error
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// router/streams.ts
|
|
288
|
+
var ReadableBrokenError = {
|
|
289
|
+
code: "READABLE_BROKEN",
|
|
290
|
+
message: "Readable was broken before it is fully consumed"
|
|
291
|
+
};
|
|
292
|
+
function createPromiseWithResolvers() {
|
|
293
|
+
let resolve;
|
|
294
|
+
let reject;
|
|
295
|
+
const promise = new Promise((res, rej) => {
|
|
296
|
+
resolve = res;
|
|
297
|
+
reject = rej;
|
|
298
|
+
});
|
|
299
|
+
return {
|
|
300
|
+
promise,
|
|
301
|
+
// @ts-expect-error promise callbacks are sync
|
|
302
|
+
resolve,
|
|
303
|
+
// @ts-expect-error promise callbacks are sync
|
|
304
|
+
reject
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
var ReadableImpl = class {
|
|
308
|
+
/**
|
|
309
|
+
* Whether the {@link Readable} is closed.
|
|
310
|
+
*
|
|
311
|
+
* Closed {@link Readable}s are done receiving values, but that doesn't affect
|
|
312
|
+
* any other aspect of the {@link Readable} such as it's consumability.
|
|
313
|
+
*/
|
|
314
|
+
closed = false;
|
|
315
|
+
/**
|
|
316
|
+
* Whether the {@link Readable} is locked.
|
|
317
|
+
*
|
|
318
|
+
* @see {@link Readable}'s typedoc to understand locking
|
|
319
|
+
*/
|
|
320
|
+
locked = false;
|
|
321
|
+
/**
|
|
322
|
+
* Whether {@link break} was called.
|
|
323
|
+
*
|
|
324
|
+
* @see {@link break} for more information
|
|
325
|
+
*/
|
|
326
|
+
broken = false;
|
|
327
|
+
/**
|
|
328
|
+
* This flag allows us to avoid emitting a {@link ReadableBrokenError} after {@link break} was called
|
|
329
|
+
* in cases where the {@link queue} is fully consumed and {@link ReadableImpl} is {@link closed}. This is just an
|
|
330
|
+
* ergonomic feature to avoid emitting an error in our iteration when we don't have to.
|
|
331
|
+
*/
|
|
332
|
+
brokenWithValuesLeftToRead = false;
|
|
333
|
+
/**
|
|
334
|
+
* A list of values that have been pushed to the {@link ReadableImpl} but not yet emitted to the user.
|
|
335
|
+
*/
|
|
336
|
+
queue = [];
|
|
337
|
+
/**
|
|
338
|
+
* Used by methods in the class to signal to the iterator that it
|
|
339
|
+
* should check for the next value.
|
|
340
|
+
*/
|
|
341
|
+
next = null;
|
|
342
|
+
/**
|
|
343
|
+
* Consumes the {@link Readable} and returns an {@link AsyncIterator} that can be used
|
|
344
|
+
* to iterate over the values in the {@link Readable}.
|
|
345
|
+
*/
|
|
346
|
+
[Symbol.asyncIterator]() {
|
|
347
|
+
if (this.locked) {
|
|
348
|
+
throw new TypeError("Readable is already locked");
|
|
349
|
+
}
|
|
350
|
+
this.locked = true;
|
|
351
|
+
let didSignalBreak = false;
|
|
352
|
+
return {
|
|
353
|
+
next: async () => {
|
|
354
|
+
if (didSignalBreak) {
|
|
355
|
+
return {
|
|
356
|
+
done: true,
|
|
357
|
+
value: void 0
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
while (this.queue.length === 0) {
|
|
361
|
+
if (this.closed && !this.brokenWithValuesLeftToRead) {
|
|
362
|
+
return {
|
|
363
|
+
done: true,
|
|
364
|
+
value: void 0
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
if (this.broken) {
|
|
368
|
+
didSignalBreak = true;
|
|
369
|
+
return {
|
|
370
|
+
done: false,
|
|
371
|
+
value: Err(ReadableBrokenError)
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
if (!this.next) {
|
|
375
|
+
this.next = createPromiseWithResolvers();
|
|
376
|
+
}
|
|
377
|
+
await this.next.promise;
|
|
378
|
+
this.next = null;
|
|
379
|
+
}
|
|
380
|
+
const value = this.queue.shift();
|
|
381
|
+
return { done: false, value };
|
|
382
|
+
},
|
|
383
|
+
return: async () => {
|
|
384
|
+
this.break();
|
|
385
|
+
return { done: true, value: void 0 };
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Collects all the values from the {@link Readable} into an array.
|
|
391
|
+
*
|
|
392
|
+
* @see {@link Readable}'s typedoc for more information
|
|
393
|
+
*/
|
|
394
|
+
async collect() {
|
|
395
|
+
const array = [];
|
|
396
|
+
for await (const value of this) {
|
|
397
|
+
array.push(value);
|
|
398
|
+
}
|
|
399
|
+
return array;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Breaks the {@link Readable} and signals an error to any iterators waiting for the next value.
|
|
403
|
+
*
|
|
404
|
+
* @see {@link Readable}'s typedoc for more information
|
|
405
|
+
*/
|
|
406
|
+
break() {
|
|
407
|
+
if (this.broken) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
this.locked = true;
|
|
411
|
+
this.broken = true;
|
|
412
|
+
this.brokenWithValuesLeftToRead = this.queue.length > 0;
|
|
413
|
+
this.queue.length = 0;
|
|
414
|
+
this.next?.resolve();
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Whether the {@link Readable} is readable.
|
|
418
|
+
*
|
|
419
|
+
* @see {@link Readable}'s typedoc for more information
|
|
420
|
+
*/
|
|
421
|
+
isReadable() {
|
|
422
|
+
return !this.locked && !this.broken;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Pushes a value to be read.
|
|
426
|
+
*/
|
|
427
|
+
_pushValue(value) {
|
|
428
|
+
if (this.broken) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (this.closed) {
|
|
432
|
+
throw new Error("Cannot push to closed Readable");
|
|
433
|
+
}
|
|
434
|
+
this.queue.push(value);
|
|
435
|
+
this.next?.resolve();
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Triggers the close of the {@link Readable}. Make sure to push all remaining
|
|
439
|
+
* values before calling this method.
|
|
440
|
+
*/
|
|
441
|
+
_triggerClose() {
|
|
442
|
+
if (this.closed) {
|
|
443
|
+
throw new Error("Unexpected closing multiple times");
|
|
444
|
+
}
|
|
445
|
+
this.closed = true;
|
|
446
|
+
this.next?.resolve();
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* @internal meant for use within river, not exposed as a public API
|
|
450
|
+
*/
|
|
451
|
+
_hasValuesInQueue() {
|
|
452
|
+
return this.queue.length > 0;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Whether the {@link Readable} is closed.
|
|
456
|
+
*/
|
|
457
|
+
isClosed() {
|
|
458
|
+
return this.closed;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
var WritableImpl = class {
|
|
462
|
+
/**
|
|
463
|
+
* Passed via constructor to pass on calls to {@link write}
|
|
464
|
+
*/
|
|
465
|
+
writeCb;
|
|
466
|
+
/**
|
|
467
|
+
* Passed via constructor to pass on calls to {@link close}
|
|
468
|
+
*/
|
|
469
|
+
closeCb;
|
|
470
|
+
/**
|
|
471
|
+
* Whether {@link close} was called, and {@link Writable} is not writable anymore.
|
|
472
|
+
*/
|
|
473
|
+
closed = false;
|
|
474
|
+
constructor(callbacks) {
|
|
475
|
+
this.writeCb = callbacks.writeCb;
|
|
476
|
+
this.closeCb = callbacks.closeCb;
|
|
477
|
+
}
|
|
478
|
+
write(value) {
|
|
479
|
+
if (this.closed) {
|
|
480
|
+
throw new Error("Cannot write to closed Writable");
|
|
481
|
+
}
|
|
482
|
+
this.writeCb(value);
|
|
483
|
+
}
|
|
484
|
+
isWritable() {
|
|
485
|
+
return !this.closed;
|
|
486
|
+
}
|
|
487
|
+
close(value) {
|
|
488
|
+
if (this.closed) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (value !== void 0) {
|
|
492
|
+
this.writeCb(value);
|
|
493
|
+
}
|
|
494
|
+
this.closed = true;
|
|
495
|
+
this.writeCb = () => void 0;
|
|
496
|
+
this.closeCb();
|
|
497
|
+
this.closeCb = () => void 0;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* @internal meant for use within river, not exposed as a public API
|
|
501
|
+
*/
|
|
502
|
+
isClosed() {
|
|
503
|
+
return this.closed;
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// tracing/index.ts
|
|
508
|
+
var import_api = require("@opentelemetry/api");
|
|
509
|
+
|
|
510
|
+
// router/errors.ts
|
|
511
|
+
var import_typebox3 = require("@sinclair/typebox");
|
|
512
|
+
var UNCAUGHT_ERROR_CODE = "UNCAUGHT_ERROR";
|
|
513
|
+
var UNEXPECTED_DISCONNECT_CODE = "UNEXPECTED_DISCONNECT";
|
|
514
|
+
var INVALID_REQUEST_CODE = "INVALID_REQUEST";
|
|
515
|
+
var CANCEL_CODE = "CANCEL";
|
|
516
|
+
var ErrResultSchema = (t) => import_typebox3.Type.Object({
|
|
517
|
+
ok: import_typebox3.Type.Literal(false),
|
|
518
|
+
payload: t
|
|
519
|
+
});
|
|
520
|
+
var ValidationErrorDetails = import_typebox3.Type.Object({
|
|
521
|
+
path: import_typebox3.Type.String(),
|
|
522
|
+
message: import_typebox3.Type.String()
|
|
523
|
+
});
|
|
524
|
+
var ValidationErrors = import_typebox3.Type.Array(ValidationErrorDetails);
|
|
525
|
+
var CancelErrorSchema = import_typebox3.Type.Object({
|
|
526
|
+
code: import_typebox3.Type.Literal(CANCEL_CODE),
|
|
527
|
+
message: import_typebox3.Type.String()
|
|
528
|
+
});
|
|
529
|
+
var CancelResultSchema = ErrResultSchema(CancelErrorSchema);
|
|
530
|
+
var ReaderErrorSchema = import_typebox3.Type.Union([
|
|
531
|
+
import_typebox3.Type.Object({
|
|
532
|
+
code: import_typebox3.Type.Literal(UNCAUGHT_ERROR_CODE),
|
|
533
|
+
message: import_typebox3.Type.String()
|
|
534
|
+
}),
|
|
535
|
+
import_typebox3.Type.Object({
|
|
536
|
+
code: import_typebox3.Type.Literal(UNEXPECTED_DISCONNECT_CODE),
|
|
537
|
+
message: import_typebox3.Type.String()
|
|
538
|
+
}),
|
|
539
|
+
import_typebox3.Type.Object({
|
|
540
|
+
code: import_typebox3.Type.Literal(INVALID_REQUEST_CODE),
|
|
541
|
+
message: import_typebox3.Type.String(),
|
|
542
|
+
extras: import_typebox3.Type.Optional(
|
|
543
|
+
import_typebox3.Type.Object({
|
|
544
|
+
firstValidationErrors: import_typebox3.Type.Array(ValidationErrorDetails),
|
|
545
|
+
totalErrors: import_typebox3.Type.Number()
|
|
546
|
+
})
|
|
547
|
+
)
|
|
548
|
+
}),
|
|
549
|
+
CancelErrorSchema
|
|
550
|
+
]);
|
|
551
|
+
var ReaderErrorResultSchema = ErrResultSchema(ReaderErrorSchema);
|
|
552
|
+
|
|
553
|
+
// transport/stringifyError.ts
|
|
554
|
+
function coerceErrorString(err) {
|
|
555
|
+
if (err instanceof Error) {
|
|
556
|
+
return err.message || "unknown reason";
|
|
557
|
+
}
|
|
558
|
+
return `[coerced to error] ${String(err)}`;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// router/handshake.ts
|
|
562
|
+
function createClientHandshakeOptions(schema, construct) {
|
|
563
|
+
return { schema, construct };
|
|
564
|
+
}
|
|
565
|
+
function createServerHandshakeOptions(schema, validate) {
|
|
566
|
+
return { schema, validate };
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// package.json
|
|
570
|
+
var version = "0.216.0";
|
|
571
|
+
|
|
572
|
+
// tracing/index.ts
|
|
573
|
+
function getPropagationContext(ctx) {
|
|
574
|
+
const tracing = {
|
|
575
|
+
traceparent: "",
|
|
576
|
+
tracestate: ""
|
|
577
|
+
};
|
|
578
|
+
import_api.propagation.inject(ctx, tracing);
|
|
579
|
+
return tracing;
|
|
580
|
+
}
|
|
581
|
+
function createProcTelemetryInfo(tracer, session, kind, serviceName, procedureName, streamId) {
|
|
582
|
+
const baseCtx = import_api.context.active();
|
|
583
|
+
const span = tracer.startSpan(
|
|
584
|
+
`river.client.${serviceName}.${procedureName}`,
|
|
585
|
+
{
|
|
586
|
+
attributes: {
|
|
587
|
+
component: "river",
|
|
588
|
+
"river.method.kind": kind,
|
|
589
|
+
"river.method.service": serviceName,
|
|
590
|
+
"river.method.name": procedureName,
|
|
591
|
+
"river.streamId": streamId,
|
|
592
|
+
"span.kind": "client"
|
|
593
|
+
},
|
|
594
|
+
links: [{ context: session.telemetry.span.spanContext() }],
|
|
595
|
+
kind: import_api.SpanKind.CLIENT
|
|
596
|
+
},
|
|
597
|
+
baseCtx
|
|
598
|
+
);
|
|
599
|
+
const ctx = import_api.trace.setSpan(baseCtx, span);
|
|
600
|
+
const metadata = {
|
|
601
|
+
...session.loggingMetadata,
|
|
602
|
+
transportMessage: {
|
|
603
|
+
procedureName,
|
|
604
|
+
serviceName
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
if (span.isRecording()) {
|
|
608
|
+
metadata.telemetry = {
|
|
609
|
+
traceId: span.spanContext().traceId,
|
|
610
|
+
spanId: span.spanContext().spanId
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
session.log?.info(`invoked ${serviceName}.${procedureName}`, metadata);
|
|
614
|
+
return { span, ctx };
|
|
615
|
+
}
|
|
616
|
+
function createHandlerSpan(tracer, session, kind, serviceName, procedureName, streamId, tracing, fn) {
|
|
617
|
+
const ctx = tracing ? import_api.propagation.extract(import_api.context.active(), tracing) : import_api.context.active();
|
|
618
|
+
return tracer.startActiveSpan(
|
|
619
|
+
`river.server.${serviceName}.${procedureName}`,
|
|
620
|
+
{
|
|
621
|
+
attributes: {
|
|
622
|
+
component: "river",
|
|
623
|
+
"river.method.kind": kind,
|
|
624
|
+
"river.method.service": serviceName,
|
|
625
|
+
"river.method.name": procedureName,
|
|
626
|
+
"river.streamId": streamId,
|
|
627
|
+
"span.kind": "server"
|
|
628
|
+
},
|
|
629
|
+
links: [{ context: session.telemetry.span.spanContext() }],
|
|
630
|
+
kind: import_api.SpanKind.SERVER
|
|
631
|
+
},
|
|
632
|
+
ctx,
|
|
633
|
+
fn
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
function recordRiverError(span, error) {
|
|
637
|
+
span.setStatus({
|
|
638
|
+
code: import_api.SpanStatusCode.ERROR,
|
|
639
|
+
message: error.message
|
|
640
|
+
});
|
|
641
|
+
span.setAttributes({
|
|
642
|
+
"river.error_code": error.code,
|
|
643
|
+
"river.error_message": error.message
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
function getTracer() {
|
|
647
|
+
return import_api.trace.getTracer("river", version);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// protobuf/errors.ts
|
|
651
|
+
var RiverErrorCode = /* @__PURE__ */ ((RiverErrorCode2) => {
|
|
652
|
+
RiverErrorCode2["OK"] = "OK";
|
|
653
|
+
RiverErrorCode2["CANCELED"] = "CANCELED";
|
|
654
|
+
RiverErrorCode2["UNKNOWN"] = "UNKNOWN";
|
|
655
|
+
RiverErrorCode2["INVALID_ARGUMENT"] = "INVALID_ARGUMENT";
|
|
656
|
+
RiverErrorCode2["DEADLINE_EXCEEDED"] = "DEADLINE_EXCEEDED";
|
|
657
|
+
RiverErrorCode2["NOT_FOUND"] = "NOT_FOUND";
|
|
658
|
+
RiverErrorCode2["ALREADY_EXISTS"] = "ALREADY_EXISTS";
|
|
659
|
+
RiverErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
|
|
660
|
+
RiverErrorCode2["RESOURCE_EXHAUSTED"] = "RESOURCE_EXHAUSTED";
|
|
661
|
+
RiverErrorCode2["FAILED_PRECONDITION"] = "FAILED_PRECONDITION";
|
|
662
|
+
RiverErrorCode2["ABORTED"] = "ABORTED";
|
|
663
|
+
RiverErrorCode2["OUT_OF_RANGE"] = "OUT_OF_RANGE";
|
|
664
|
+
RiverErrorCode2["UNIMPLEMENTED"] = "UNIMPLEMENTED";
|
|
665
|
+
RiverErrorCode2["INTERNAL"] = "INTERNAL";
|
|
666
|
+
RiverErrorCode2["UNAVAILABLE"] = "UNAVAILABLE";
|
|
667
|
+
RiverErrorCode2["DATA_LOSS"] = "DATA_LOSS";
|
|
668
|
+
RiverErrorCode2["UNAUTHENTICATED"] = "UNAUTHENTICATED";
|
|
669
|
+
return RiverErrorCode2;
|
|
670
|
+
})(RiverErrorCode || {});
|
|
671
|
+
var riverErrorCodeSet = new Set(Object.values(RiverErrorCode));
|
|
672
|
+
var protocolErrorCodeSet = /* @__PURE__ */ new Set([
|
|
673
|
+
CANCEL_CODE,
|
|
674
|
+
INVALID_REQUEST_CODE,
|
|
675
|
+
UNCAUGHT_ERROR_CODE,
|
|
676
|
+
UNEXPECTED_DISCONNECT_CODE
|
|
677
|
+
]);
|
|
678
|
+
function isRiverError(value) {
|
|
679
|
+
if (!(typeof value === "object" && value !== null)) {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
const candidate = value;
|
|
683
|
+
return isRiverErrorCode(candidate.code) && typeof candidate.message === "string";
|
|
684
|
+
}
|
|
685
|
+
function isProtocolError(value) {
|
|
686
|
+
if (!(typeof value === "object" && value !== null)) {
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
const candidate = value;
|
|
690
|
+
return isProtocolErrorCode(candidate.code) && typeof candidate.message === "string";
|
|
691
|
+
}
|
|
692
|
+
function isClientError(value) {
|
|
693
|
+
return isRiverError(value) || isProtocolError(value);
|
|
694
|
+
}
|
|
695
|
+
function isSerializedClientErrorResult(value) {
|
|
696
|
+
return isErrResultWithPayload(value, isClientError);
|
|
697
|
+
}
|
|
698
|
+
function isSerializedProtocolErrorResult(value) {
|
|
699
|
+
return isErrResultWithPayload(value, isProtocolError);
|
|
700
|
+
}
|
|
701
|
+
function isRiverErrorCode(value) {
|
|
702
|
+
return typeof value === "string" && riverErrorCodeSet.has(value);
|
|
703
|
+
}
|
|
704
|
+
function isProtocolErrorCode(value) {
|
|
705
|
+
return typeof value === "string" && protocolErrorCodeSet.has(value);
|
|
706
|
+
}
|
|
707
|
+
function isErrResultWithPayload(value, predicate) {
|
|
708
|
+
if (!(typeof value === "object" && value !== null)) {
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
const candidate = value;
|
|
712
|
+
return candidate.ok === false && predicate(candidate.payload);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// protobuf/shared.ts
|
|
716
|
+
var import_protobuf2 = require("@bufbuild/protobuf");
|
|
717
|
+
var EMPTY_PROTO_BYTES = new Uint8Array(0);
|
|
718
|
+
function methodKindToProcType(methodKind) {
|
|
719
|
+
switch (methodKind) {
|
|
720
|
+
case "unary":
|
|
721
|
+
return "rpc";
|
|
722
|
+
case "server_streaming":
|
|
723
|
+
return "subscription";
|
|
724
|
+
case "client_streaming":
|
|
725
|
+
return "upload";
|
|
726
|
+
case "bidi_streaming":
|
|
727
|
+
return "stream";
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function methodKey(serviceName, methodName) {
|
|
731
|
+
return `${serviceName}/${methodName}`;
|
|
732
|
+
}
|
|
733
|
+
function encodeMessageBytes(schema, message) {
|
|
734
|
+
return (0, import_protobuf2.toBinary)(schema, (0, import_protobuf2.create)(schema, message));
|
|
735
|
+
}
|
|
736
|
+
function decodeMessageBytes(schema, payload) {
|
|
737
|
+
return (0, import_protobuf2.fromBinary)(schema, payload);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// protobuf/client.ts
|
|
741
|
+
var defaultClientOptions = {
|
|
742
|
+
connectOnInvoke: true,
|
|
743
|
+
eagerlyConnect: true
|
|
744
|
+
};
|
|
745
|
+
function createClient(service, transport, serverId, providedClientOptions = {}) {
|
|
746
|
+
if (providedClientOptions.handshakeOptions) {
|
|
747
|
+
transport.extendHandshake(providedClientOptions.handshakeOptions);
|
|
748
|
+
}
|
|
749
|
+
const clientOptions = { ...defaultClientOptions, ...providedClientOptions };
|
|
750
|
+
if (clientOptions.eagerlyConnect) {
|
|
751
|
+
transport.connect(serverId);
|
|
752
|
+
}
|
|
753
|
+
const client = {};
|
|
754
|
+
for (const methodName of Object.keys(service.method)) {
|
|
755
|
+
const method = service.method[methodName];
|
|
756
|
+
client[methodName] = createMethodCaller(
|
|
757
|
+
service,
|
|
758
|
+
method,
|
|
759
|
+
transport,
|
|
760
|
+
serverId,
|
|
761
|
+
clientOptions
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
return client;
|
|
765
|
+
}
|
|
766
|
+
function createMethodCaller(service, method, transport, serverId, clientOptions) {
|
|
767
|
+
switch (method.methodKind) {
|
|
768
|
+
case "unary":
|
|
769
|
+
return ((request, options) => {
|
|
770
|
+
if (transport.getStatus() === "closed") {
|
|
771
|
+
return Promise.resolve(
|
|
772
|
+
Err({
|
|
773
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
774
|
+
message: "transport is closed"
|
|
775
|
+
})
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
connectOnInvokeIfNeeded(clientOptions, transport, serverId);
|
|
779
|
+
const { resReadable } = startMethodCall(
|
|
780
|
+
service,
|
|
781
|
+
method,
|
|
782
|
+
transport,
|
|
783
|
+
serverId,
|
|
784
|
+
encodeMessageBytes(method.input, request),
|
|
785
|
+
true,
|
|
786
|
+
options?.signal
|
|
787
|
+
);
|
|
788
|
+
return getSingleMessage(resReadable, transport.log);
|
|
789
|
+
});
|
|
790
|
+
case "server_streaming":
|
|
791
|
+
return ((request, options) => {
|
|
792
|
+
if (transport.getStatus() === "closed") {
|
|
793
|
+
return createPreClosedReadable({
|
|
794
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
795
|
+
message: "transport is closed"
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
connectOnInvokeIfNeeded(clientOptions, transport, serverId);
|
|
799
|
+
return startMethodCall(
|
|
800
|
+
service,
|
|
801
|
+
method,
|
|
802
|
+
transport,
|
|
803
|
+
serverId,
|
|
804
|
+
encodeMessageBytes(method.input, request),
|
|
805
|
+
true,
|
|
806
|
+
options?.signal
|
|
807
|
+
).resReadable;
|
|
808
|
+
});
|
|
809
|
+
case "client_streaming":
|
|
810
|
+
return ((options) => {
|
|
811
|
+
if (transport.getStatus() === "closed") {
|
|
812
|
+
return createPreClosedClientStreamingCall();
|
|
813
|
+
}
|
|
814
|
+
connectOnInvokeIfNeeded(clientOptions, transport, serverId);
|
|
815
|
+
const { reqWritable, resReadable } = startMethodCall(
|
|
816
|
+
service,
|
|
817
|
+
method,
|
|
818
|
+
transport,
|
|
819
|
+
serverId,
|
|
820
|
+
EMPTY_PROTO_BYTES,
|
|
821
|
+
false,
|
|
822
|
+
options?.signal
|
|
823
|
+
);
|
|
824
|
+
let didFinalize = false;
|
|
825
|
+
return {
|
|
826
|
+
reqWritable,
|
|
827
|
+
finalize: () => {
|
|
828
|
+
if (didFinalize) {
|
|
829
|
+
throw new Error("client streaming call already finalized");
|
|
830
|
+
}
|
|
831
|
+
didFinalize = true;
|
|
832
|
+
if (!reqWritable.isClosed()) {
|
|
833
|
+
reqWritable.close();
|
|
834
|
+
}
|
|
835
|
+
return getSingleMessage(resReadable, transport.log);
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
});
|
|
839
|
+
case "bidi_streaming":
|
|
840
|
+
return ((options) => {
|
|
841
|
+
if (transport.getStatus() === "closed") {
|
|
842
|
+
return createPreClosedBiDiStreamingCall();
|
|
843
|
+
}
|
|
844
|
+
connectOnInvokeIfNeeded(clientOptions, transport, serverId);
|
|
845
|
+
return startMethodCall(
|
|
846
|
+
service,
|
|
847
|
+
method,
|
|
848
|
+
transport,
|
|
849
|
+
serverId,
|
|
850
|
+
EMPTY_PROTO_BYTES,
|
|
851
|
+
false,
|
|
852
|
+
options?.signal
|
|
853
|
+
);
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
function connectOnInvokeIfNeeded(clientOptions, transport, serverId) {
|
|
858
|
+
if (clientOptions.connectOnInvoke && !transport.sessions.has(serverId)) {
|
|
859
|
+
transport.connect(serverId);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
function startMethodCall(service, method, transport, serverId, initialPayload, procClosesWithInit, abortSignal) {
|
|
863
|
+
const session = transport.sessions.get(serverId) ?? transport.createUnconnectedSession(serverId);
|
|
864
|
+
const sessionScopedSend = transport.getSessionBoundSendFn(
|
|
865
|
+
serverId,
|
|
866
|
+
session.id
|
|
867
|
+
);
|
|
868
|
+
const streamId = generateId();
|
|
869
|
+
const { span, ctx } = createProcTelemetryInfo(
|
|
870
|
+
transport.tracer,
|
|
871
|
+
session,
|
|
872
|
+
methodKindToProcType(method.methodKind),
|
|
873
|
+
service.typeName,
|
|
874
|
+
method.name,
|
|
875
|
+
streamId
|
|
876
|
+
);
|
|
877
|
+
let cleanClose = true;
|
|
878
|
+
const reqWritable = new WritableImpl({
|
|
879
|
+
writeCb: (value) => {
|
|
880
|
+
sessionScopedSend({
|
|
881
|
+
streamId,
|
|
882
|
+
payload: encodeMessageBytes(method.input, value),
|
|
883
|
+
controlFlags: 0
|
|
884
|
+
});
|
|
885
|
+
},
|
|
886
|
+
closeCb: () => {
|
|
887
|
+
span.addEvent("reqWritable closed");
|
|
888
|
+
if (!procClosesWithInit && cleanClose) {
|
|
889
|
+
sessionScopedSend(closeStreamMessage(streamId));
|
|
890
|
+
}
|
|
891
|
+
if (resReadable.isClosed()) {
|
|
892
|
+
cleanup();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
const resReadable = new ReadableImpl();
|
|
897
|
+
const closeReadable = () => {
|
|
898
|
+
if (resReadable.isClosed()) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
resReadable._triggerClose();
|
|
902
|
+
span.addEvent("resReadable closed");
|
|
903
|
+
if (reqWritable.isClosed()) {
|
|
904
|
+
cleanup();
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
function cleanup() {
|
|
908
|
+
transport.removeEventListener("message", onMessage);
|
|
909
|
+
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
910
|
+
abortSignal?.removeEventListener("abort", onClientCancel);
|
|
911
|
+
span.end();
|
|
912
|
+
}
|
|
913
|
+
function pushResponseError(error) {
|
|
914
|
+
if (!resReadable.isClosed()) {
|
|
915
|
+
resReadable._pushValue(Err(error));
|
|
916
|
+
closeReadable();
|
|
917
|
+
}
|
|
918
|
+
reqWritable.close();
|
|
919
|
+
}
|
|
920
|
+
function onClientCancel() {
|
|
921
|
+
if (resReadable.isClosed() && reqWritable.isClosed()) {
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
span.addEvent("sending cancel");
|
|
925
|
+
cleanClose = false;
|
|
926
|
+
const error = {
|
|
927
|
+
code: CANCEL_CODE,
|
|
928
|
+
message: "cancelled by client"
|
|
929
|
+
};
|
|
930
|
+
pushResponseError(error);
|
|
931
|
+
sessionScopedSend(cancelMessage(streamId, Err(error)));
|
|
932
|
+
}
|
|
933
|
+
function onMessage(msg) {
|
|
934
|
+
if (msg.streamId !== streamId) {
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
if (msg.to !== transport.clientId) {
|
|
938
|
+
transport.log?.error("got stream message from unexpected client", {
|
|
939
|
+
clientId: transport.clientId,
|
|
940
|
+
transportMessage: msg
|
|
941
|
+
});
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
if (isStreamCancel(msg.controlFlags)) {
|
|
945
|
+
cleanClose = false;
|
|
946
|
+
span.addEvent("received cancel");
|
|
947
|
+
const error = isSerializedClientErrorResult(msg.payload) ? msg.payload.payload : {
|
|
948
|
+
code: CANCEL_CODE,
|
|
949
|
+
message: "stream cancelled with invalid payload"
|
|
950
|
+
};
|
|
951
|
+
pushResponseError(error);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
if (resReadable.isClosed()) {
|
|
955
|
+
transport.log?.error("received message after response stream is closed", {
|
|
956
|
+
clientId: transport.clientId,
|
|
957
|
+
transportMessage: msg
|
|
958
|
+
});
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
if (!import_value.Value.Check(ControlMessageCloseSchema, msg.payload)) {
|
|
962
|
+
if (msg.payload instanceof Uint8Array) {
|
|
963
|
+
try {
|
|
964
|
+
resReadable._pushValue(
|
|
965
|
+
Ok(
|
|
966
|
+
decodeMessageBytes(method.output, msg.payload)
|
|
967
|
+
)
|
|
968
|
+
);
|
|
969
|
+
} catch (err) {
|
|
970
|
+
pushResponseError({
|
|
971
|
+
code: INVALID_REQUEST_CODE,
|
|
972
|
+
message: "failed to decode protobuf response payload",
|
|
973
|
+
extras: { cause: err }
|
|
974
|
+
});
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
} else if (isSerializedClientErrorResult(msg.payload)) {
|
|
978
|
+
resReadable._pushValue(msg.payload);
|
|
979
|
+
} else {
|
|
980
|
+
pushResponseError({
|
|
981
|
+
code: INVALID_REQUEST_CODE,
|
|
982
|
+
message: "received invalid protobuf response payload"
|
|
983
|
+
});
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
if (isStreamClose(msg.controlFlags)) {
|
|
988
|
+
span.addEvent("received response close");
|
|
989
|
+
closeReadable();
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
function onSessionStatus(evt) {
|
|
993
|
+
if (evt.status !== "closing" || evt.session.to !== serverId || session.id !== evt.session.id) {
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
cleanClose = false;
|
|
997
|
+
pushResponseError({
|
|
998
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
999
|
+
message: `${serverId} unexpectedly disconnected`
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
abortSignal?.addEventListener("abort", onClientCancel);
|
|
1003
|
+
transport.addEventListener("message", onMessage);
|
|
1004
|
+
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
1005
|
+
try {
|
|
1006
|
+
sessionScopedSend({
|
|
1007
|
+
streamId,
|
|
1008
|
+
serviceName: service.typeName,
|
|
1009
|
+
procedureName: method.name,
|
|
1010
|
+
tracing: getPropagationContext(ctx),
|
|
1011
|
+
payload: initialPayload,
|
|
1012
|
+
controlFlags: procClosesWithInit ? 2 /* StreamOpenBit */ | 8 /* StreamClosedBit */ : 2 /* StreamOpenBit */
|
|
1013
|
+
});
|
|
1014
|
+
} catch (err) {
|
|
1015
|
+
cleanup();
|
|
1016
|
+
throw err;
|
|
1017
|
+
}
|
|
1018
|
+
if (procClosesWithInit) {
|
|
1019
|
+
reqWritable.close();
|
|
1020
|
+
}
|
|
1021
|
+
return { reqWritable, resReadable };
|
|
1022
|
+
}
|
|
1023
|
+
function createPreClosedReadable(error) {
|
|
1024
|
+
const readable = new ReadableImpl();
|
|
1025
|
+
readable._pushValue(Err(error));
|
|
1026
|
+
readable._triggerClose();
|
|
1027
|
+
return readable;
|
|
1028
|
+
}
|
|
1029
|
+
function createPreClosedWritable() {
|
|
1030
|
+
const writable = new WritableImpl({
|
|
1031
|
+
writeCb: () => void 0,
|
|
1032
|
+
closeCb: () => void 0
|
|
1033
|
+
});
|
|
1034
|
+
writable.close();
|
|
1035
|
+
return writable;
|
|
1036
|
+
}
|
|
1037
|
+
function createPreClosedClientStreamingCall() {
|
|
1038
|
+
return {
|
|
1039
|
+
reqWritable: createPreClosedWritable(),
|
|
1040
|
+
finalize: () => Promise.resolve(
|
|
1041
|
+
Err({
|
|
1042
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
1043
|
+
message: "transport is closed"
|
|
1044
|
+
})
|
|
1045
|
+
)
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
function createPreClosedBiDiStreamingCall() {
|
|
1049
|
+
return {
|
|
1050
|
+
reqWritable: createPreClosedWritable(),
|
|
1051
|
+
resReadable: createPreClosedReadable({
|
|
1052
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
1053
|
+
message: "transport is closed"
|
|
1054
|
+
})
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
async function getSingleMessage(resReadable, log) {
|
|
1058
|
+
const ret = await resReadable.collect();
|
|
1059
|
+
if (ret.length === 0) {
|
|
1060
|
+
return Err({
|
|
1061
|
+
code: INVALID_REQUEST_CODE,
|
|
1062
|
+
message: "expected single response from server, got none"
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
if (ret.length > 1) {
|
|
1066
|
+
log?.error("expected single protobuf response from server, got multiple");
|
|
1067
|
+
}
|
|
1068
|
+
const first = ret[0];
|
|
1069
|
+
if (!first.ok) {
|
|
1070
|
+
if (first.payload.code === ReadableBrokenError.code) {
|
|
1071
|
+
return Err({
|
|
1072
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
1073
|
+
message: first.payload.message
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
return Err(first.payload);
|
|
1077
|
+
}
|
|
1078
|
+
return first;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// protobuf/handshake.ts
|
|
1082
|
+
var import_typebox4 = require("@sinclair/typebox");
|
|
1083
|
+
var HandshakeBytesSchema = import_typebox4.Type.Uint8Array();
|
|
1084
|
+
function createClientHandshakeOptions2(schema, construct) {
|
|
1085
|
+
return createClientHandshakeOptions(
|
|
1086
|
+
HandshakeBytesSchema,
|
|
1087
|
+
async () => {
|
|
1088
|
+
const metadata = await construct();
|
|
1089
|
+
return encodeMessageBytes(schema, metadata);
|
|
1090
|
+
}
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
function createServerHandshakeOptions2(schema, validate) {
|
|
1094
|
+
return createServerHandshakeOptions(
|
|
1095
|
+
HandshakeBytesSchema,
|
|
1096
|
+
async (metadata, previousParsedMetadata) => {
|
|
1097
|
+
let decoded;
|
|
1098
|
+
try {
|
|
1099
|
+
decoded = decodeMessageBytes(schema, metadata);
|
|
1100
|
+
} catch {
|
|
1101
|
+
return "REJECTED_BY_CUSTOM_HANDLER";
|
|
1102
|
+
}
|
|
1103
|
+
return await validate(decoded, previousParsedMetadata);
|
|
1104
|
+
}
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// protobuf/service.ts
|
|
1109
|
+
function buildMethodMap(descriptor, handlers) {
|
|
1110
|
+
const methods = /* @__PURE__ */ new Map();
|
|
1111
|
+
const typedMethods = descriptor.method;
|
|
1112
|
+
for (const methodName of Object.keys(handlers)) {
|
|
1113
|
+
const handler = handlers[methodName];
|
|
1114
|
+
if (handler === void 0) {
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
1117
|
+
const method = typedMethods[methodName];
|
|
1118
|
+
if (!method) {
|
|
1119
|
+
throw new Error(`unknown method ${methodName} on ${descriptor.typeName}`);
|
|
1120
|
+
}
|
|
1121
|
+
methods.set(method.name, {
|
|
1122
|
+
service: descriptor,
|
|
1123
|
+
method,
|
|
1124
|
+
impl: handler
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
return methods;
|
|
1128
|
+
}
|
|
1129
|
+
var ProtoServiceScaffold = class {
|
|
1130
|
+
descriptor;
|
|
1131
|
+
config;
|
|
1132
|
+
constructor(descriptor, config) {
|
|
1133
|
+
this.descriptor = descriptor;
|
|
1134
|
+
this.config = config;
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Type-check a partial set of handler implementations against this
|
|
1138
|
+
* service's types. Returns the input unchanged -- this is purely a
|
|
1139
|
+
* type-level helper for splitting handlers across files.
|
|
1140
|
+
*
|
|
1141
|
+
* @param handlers - A partial set of method implementations.
|
|
1142
|
+
*/
|
|
1143
|
+
procedures(handlers) {
|
|
1144
|
+
return handlers;
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Finalize the scaffold into a service definition. Provide all handlers
|
|
1148
|
+
* here (or spread in handler objects from {@link procedures}).
|
|
1149
|
+
*
|
|
1150
|
+
* @param handlers - Method implementations (missing methods return
|
|
1151
|
+
* UNIMPLEMENTED at runtime).
|
|
1152
|
+
*/
|
|
1153
|
+
finalize(handlers) {
|
|
1154
|
+
return createProtoService().define(
|
|
1155
|
+
this.descriptor,
|
|
1156
|
+
this.config,
|
|
1157
|
+
handlers
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
function createProtoService() {
|
|
1162
|
+
return class ProtoServiceSchema {
|
|
1163
|
+
descriptor;
|
|
1164
|
+
methods;
|
|
1165
|
+
/** @internal */
|
|
1166
|
+
initializeStateFn;
|
|
1167
|
+
constructor(descriptor, initializeStateFn, methods) {
|
|
1168
|
+
this.descriptor = descriptor;
|
|
1169
|
+
this.initializeStateFn = initializeStateFn;
|
|
1170
|
+
this.methods = methods;
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Create a live service instance with initialized state.
|
|
1174
|
+
*
|
|
1175
|
+
* @param ctx - The user-provided context, passed to `initializeState`.
|
|
1176
|
+
*/
|
|
1177
|
+
instantiate(ctx) {
|
|
1178
|
+
const state = this.initializeStateFn ? this.initializeStateFn(ctx) : {};
|
|
1179
|
+
return Object.freeze({
|
|
1180
|
+
descriptor: this.descriptor,
|
|
1181
|
+
state,
|
|
1182
|
+
methods: this.methods,
|
|
1183
|
+
async [Symbol.asyncDispose]() {
|
|
1184
|
+
await state[Symbol.asyncDispose]?.();
|
|
1185
|
+
state[Symbol.dispose]?.();
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
static define(descriptor, configOrHandlers, maybeHandlers) {
|
|
1190
|
+
let initializeStateFn;
|
|
1191
|
+
let handlers;
|
|
1192
|
+
if ("initializeState" in configOrHandlers && typeof configOrHandlers.initializeState === "function") {
|
|
1193
|
+
if (!maybeHandlers) {
|
|
1194
|
+
throw new Error("expected handlers as third argument");
|
|
1195
|
+
}
|
|
1196
|
+
initializeStateFn = configOrHandlers.initializeState;
|
|
1197
|
+
handlers = maybeHandlers;
|
|
1198
|
+
} else {
|
|
1199
|
+
initializeStateFn = void 0;
|
|
1200
|
+
handlers = configOrHandlers;
|
|
1201
|
+
}
|
|
1202
|
+
return new ProtoServiceSchema(
|
|
1203
|
+
descriptor,
|
|
1204
|
+
initializeStateFn,
|
|
1205
|
+
buildMethodMap(descriptor, handlers)
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Create a scaffold for splitting handler implementations across files.
|
|
1210
|
+
*
|
|
1211
|
+
* @param descriptor - The generated protobuf service descriptor.
|
|
1212
|
+
* @param config - Service configuration including `initializeState`.
|
|
1213
|
+
*/
|
|
1214
|
+
static scaffold(descriptor, config) {
|
|
1215
|
+
return new ProtoServiceScaffold(
|
|
1216
|
+
descriptor,
|
|
1217
|
+
config
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// protobuf/server.ts
|
|
1224
|
+
var import_value2 = require("@sinclair/typebox/value");
|
|
1225
|
+
var import_api2 = require("@opentelemetry/api");
|
|
1226
|
+
var ProtobufServer = class {
|
|
1227
|
+
streams;
|
|
1228
|
+
transport;
|
|
1229
|
+
methods;
|
|
1230
|
+
serviceInstances;
|
|
1231
|
+
userContext;
|
|
1232
|
+
log;
|
|
1233
|
+
middlewares;
|
|
1234
|
+
serverCancelledStreams;
|
|
1235
|
+
maxCancelledStreamTombstonesPerSession;
|
|
1236
|
+
unregisterTransportListeners;
|
|
1237
|
+
constructor(transport, services, options = {}) {
|
|
1238
|
+
this.transport = transport;
|
|
1239
|
+
this.log = transport.log;
|
|
1240
|
+
this.middlewares = options.middlewares ?? [];
|
|
1241
|
+
this.maxCancelledStreamTombstonesPerSession = options.maxCancelledStreamTombstonesPerSession ?? 200;
|
|
1242
|
+
this.serverCancelledStreams = /* @__PURE__ */ new Map();
|
|
1243
|
+
this.streams = /* @__PURE__ */ new Map();
|
|
1244
|
+
this.userContext = options.extendedContext ?? {};
|
|
1245
|
+
this.methods = /* @__PURE__ */ new Map();
|
|
1246
|
+
this.serviceInstances = /* @__PURE__ */ new Map();
|
|
1247
|
+
for (const svc of services) {
|
|
1248
|
+
if (this.serviceInstances.has(svc.descriptor.typeName)) {
|
|
1249
|
+
throw new Error(
|
|
1250
|
+
`duplicate protobuf service registration for ${svc.descriptor.typeName}`
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
const instance = svc.instantiate(this.userContext);
|
|
1254
|
+
this.serviceInstances.set(svc.descriptor.typeName, instance);
|
|
1255
|
+
for (const [, reg] of instance.methods) {
|
|
1256
|
+
this.methods.set(
|
|
1257
|
+
methodKey(svc.descriptor.typeName, reg.method.name),
|
|
1258
|
+
reg
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
if (options.handshakeOptions) {
|
|
1263
|
+
transport.extendHandshake(options.handshakeOptions);
|
|
1264
|
+
}
|
|
1265
|
+
const handleCreatingNewStreams = (message) => {
|
|
1266
|
+
if (message.to !== this.transport.clientId) {
|
|
1267
|
+
this.log?.info(
|
|
1268
|
+
`got msg with destination that isn't this server, ignoring`,
|
|
1269
|
+
{
|
|
1270
|
+
clientId: this.transport.clientId,
|
|
1271
|
+
transportMessage: message
|
|
1272
|
+
}
|
|
1273
|
+
);
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
const stream = this.streams.get(message.streamId);
|
|
1277
|
+
if (stream) {
|
|
1278
|
+
stream.handleMsg(message);
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
if (this.serverCancelledStreams.get(message.from)?.has(message.streamId)) {
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
const newStreamProps = this.validateNewProcStream(message);
|
|
1285
|
+
if (!newStreamProps) {
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
createHandlerSpan(
|
|
1289
|
+
transport.tracer,
|
|
1290
|
+
newStreamProps.initialSession,
|
|
1291
|
+
methodKindToProcType(newStreamProps.method.methodKind),
|
|
1292
|
+
newStreamProps.service.typeName,
|
|
1293
|
+
newStreamProps.method.name,
|
|
1294
|
+
newStreamProps.streamId,
|
|
1295
|
+
newStreamProps.tracingCtx,
|
|
1296
|
+
(span) => {
|
|
1297
|
+
this.createNewProcStream(span, newStreamProps);
|
|
1298
|
+
}
|
|
1299
|
+
);
|
|
1300
|
+
};
|
|
1301
|
+
const handleSessionStatus = (evt) => {
|
|
1302
|
+
if (evt.status !== "closing") {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
const disconnectedClientId = evt.session.to;
|
|
1306
|
+
this.log?.info(
|
|
1307
|
+
`got session disconnect from ${disconnectedClientId}, cleaning up protobuf streams`,
|
|
1308
|
+
evt.session.loggingMetadata
|
|
1309
|
+
);
|
|
1310
|
+
for (const stream of this.streams.values()) {
|
|
1311
|
+
if (stream.from === disconnectedClientId) {
|
|
1312
|
+
stream.handleSessionDisconnect();
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
this.serverCancelledStreams.delete(disconnectedClientId);
|
|
1316
|
+
};
|
|
1317
|
+
const handleTransportStatus = (evt) => {
|
|
1318
|
+
if (evt.status === "closed") {
|
|
1319
|
+
this.unregisterTransportListeners();
|
|
1320
|
+
}
|
|
1321
|
+
};
|
|
1322
|
+
this.unregisterTransportListeners = () => {
|
|
1323
|
+
this.transport.removeEventListener("message", handleCreatingNewStreams);
|
|
1324
|
+
this.transport.removeEventListener("sessionStatus", handleSessionStatus);
|
|
1325
|
+
this.transport.removeEventListener(
|
|
1326
|
+
"transportStatus",
|
|
1327
|
+
handleTransportStatus
|
|
1328
|
+
);
|
|
1329
|
+
};
|
|
1330
|
+
this.transport.addEventListener("message", handleCreatingNewStreams);
|
|
1331
|
+
this.transport.addEventListener("sessionStatus", handleSessionStatus);
|
|
1332
|
+
this.transport.addEventListener("transportStatus", handleTransportStatus);
|
|
1333
|
+
}
|
|
1334
|
+
async close() {
|
|
1335
|
+
this.unregisterTransportListeners();
|
|
1336
|
+
for (const instance of this.serviceInstances.values()) {
|
|
1337
|
+
await instance[Symbol.asyncDispose]();
|
|
1338
|
+
}
|
|
1339
|
+
const ctx = this.userContext;
|
|
1340
|
+
if (ctx[Symbol.asyncDispose]) {
|
|
1341
|
+
await ctx[Symbol.asyncDispose]?.();
|
|
1342
|
+
} else if (ctx[Symbol.dispose]) {
|
|
1343
|
+
ctx[Symbol.dispose]?.();
|
|
1344
|
+
} else {
|
|
1345
|
+
for (const value of Object.values(ctx)) {
|
|
1346
|
+
if (value && typeof value === "object") {
|
|
1347
|
+
const v = value;
|
|
1348
|
+
if (v[Symbol.asyncDispose]) {
|
|
1349
|
+
await v[Symbol.asyncDispose]?.();
|
|
1350
|
+
} else if (v[Symbol.dispose]) {
|
|
1351
|
+
v[Symbol.dispose]?.();
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
createNewProcStream(span, props) {
|
|
1358
|
+
const {
|
|
1359
|
+
streamId,
|
|
1360
|
+
service,
|
|
1361
|
+
method,
|
|
1362
|
+
impl,
|
|
1363
|
+
serviceContext,
|
|
1364
|
+
serviceState,
|
|
1365
|
+
sessionMetadata,
|
|
1366
|
+
initialSession,
|
|
1367
|
+
initialRequest,
|
|
1368
|
+
closeRequestOnStart
|
|
1369
|
+
} = props;
|
|
1370
|
+
const { to: from, loggingMetadata, id: sessionId } = initialSession;
|
|
1371
|
+
loggingMetadata.telemetry = {
|
|
1372
|
+
traceId: span.spanContext().traceId,
|
|
1373
|
+
spanId: span.spanContext().spanId
|
|
1374
|
+
};
|
|
1375
|
+
let cleanClose = true;
|
|
1376
|
+
const finishedController = new AbortController();
|
|
1377
|
+
const sessionScopedSend = this.transport.getSessionBoundSendFn(
|
|
1378
|
+
from,
|
|
1379
|
+
sessionId
|
|
1380
|
+
);
|
|
1381
|
+
const deferredCleanups = [];
|
|
1382
|
+
let cleanupsHaveRun = false;
|
|
1383
|
+
const runCleanupSafe = async (fn) => {
|
|
1384
|
+
try {
|
|
1385
|
+
await fn();
|
|
1386
|
+
} catch (err) {
|
|
1387
|
+
span.recordException(
|
|
1388
|
+
err instanceof Error ? err : new Error(String(err))
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
const deferCleanup = (fn) => {
|
|
1393
|
+
if (cleanupsHaveRun) {
|
|
1394
|
+
void runCleanupSafe(fn);
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
deferredCleanups.push(fn);
|
|
1398
|
+
};
|
|
1399
|
+
const runDeferredCleanups = async () => {
|
|
1400
|
+
if (deferredCleanups.length === 0) {
|
|
1401
|
+
cleanupsHaveRun = true;
|
|
1402
|
+
span.end();
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
const cleanupSpan = getTracer().startSpan(
|
|
1406
|
+
"river.cleanup",
|
|
1407
|
+
{},
|
|
1408
|
+
import_api2.trace.setSpan(import_api2.context.active(), span)
|
|
1409
|
+
);
|
|
1410
|
+
try {
|
|
1411
|
+
for (let fn = deferredCleanups.pop(); fn; fn = deferredCleanups.pop()) {
|
|
1412
|
+
await runCleanupSafe(fn);
|
|
1413
|
+
}
|
|
1414
|
+
} finally {
|
|
1415
|
+
cleanupsHaveRun = true;
|
|
1416
|
+
cleanupSpan.end();
|
|
1417
|
+
span.end();
|
|
1418
|
+
}
|
|
1419
|
+
};
|
|
1420
|
+
const cleanup = () => {
|
|
1421
|
+
finishedController.abort();
|
|
1422
|
+
this.streams.delete(streamId);
|
|
1423
|
+
void runDeferredCleanups();
|
|
1424
|
+
};
|
|
1425
|
+
const reqReadable = new ReadableImpl();
|
|
1426
|
+
const closeReadable = () => {
|
|
1427
|
+
if (reqReadable.isClosed()) {
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
reqReadable._triggerClose();
|
|
1431
|
+
if (resWritable.isClosed()) {
|
|
1432
|
+
cleanup();
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
const procClosesWithResponse = method.methodKind === "unary" || method.methodKind === "client_streaming";
|
|
1436
|
+
const resWritable = new WritableImpl({
|
|
1437
|
+
writeCb: (response) => {
|
|
1438
|
+
const payload = response.ok ? encodeMessageBytes(method.output, response.payload) : Err(response.payload);
|
|
1439
|
+
if (!response.ok) {
|
|
1440
|
+
recordRiverError(span, response.payload);
|
|
1441
|
+
}
|
|
1442
|
+
sessionScopedSend({
|
|
1443
|
+
streamId,
|
|
1444
|
+
controlFlags: procClosesWithResponse ? 8 /* StreamClosedBit */ : 0,
|
|
1445
|
+
payload
|
|
1446
|
+
});
|
|
1447
|
+
if (procClosesWithResponse) {
|
|
1448
|
+
resWritable.close();
|
|
1449
|
+
}
|
|
1450
|
+
},
|
|
1451
|
+
closeCb: () => {
|
|
1452
|
+
if (!procClosesWithResponse && cleanClose) {
|
|
1453
|
+
sessionScopedSend(closeStreamMessage(streamId));
|
|
1454
|
+
}
|
|
1455
|
+
if (reqReadable.isClosed()) {
|
|
1456
|
+
cleanup();
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
const cancelStream = (error) => {
|
|
1461
|
+
this.cancelStream(from, sessionScopedSend, streamId, error);
|
|
1462
|
+
};
|
|
1463
|
+
const pushRequestError = (error) => {
|
|
1464
|
+
if (!reqReadable.isClosed()) {
|
|
1465
|
+
reqReadable._pushValue(Err(error));
|
|
1466
|
+
closeReadable();
|
|
1467
|
+
}
|
|
1468
|
+
resWritable.close();
|
|
1469
|
+
};
|
|
1470
|
+
const onServerCancel = (error) => {
|
|
1471
|
+
recordRiverError(span, error);
|
|
1472
|
+
if (reqReadable.isClosed() && resWritable.isClosed()) {
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
cleanClose = false;
|
|
1476
|
+
pushRequestError(error);
|
|
1477
|
+
cancelStream(error);
|
|
1478
|
+
};
|
|
1479
|
+
const onHandlerError = (err) => {
|
|
1480
|
+
const errorMsg = coerceErrorString(err);
|
|
1481
|
+
span.recordException(err instanceof Error ? err : new Error(errorMsg));
|
|
1482
|
+
this.log?.error(
|
|
1483
|
+
`${service.typeName}.${method.name} handler threw an uncaught error`,
|
|
1484
|
+
{
|
|
1485
|
+
...loggingMetadata,
|
|
1486
|
+
transportMessage: {
|
|
1487
|
+
procedureName: method.name,
|
|
1488
|
+
serviceName: service.typeName
|
|
1489
|
+
},
|
|
1490
|
+
extras: {
|
|
1491
|
+
error: errorMsg,
|
|
1492
|
+
originalException: err
|
|
1493
|
+
},
|
|
1494
|
+
tags: ["uncaught-handler-error"]
|
|
1495
|
+
}
|
|
1496
|
+
);
|
|
1497
|
+
const error = {
|
|
1498
|
+
code: UNCAUGHT_ERROR_CODE,
|
|
1499
|
+
message: errorMsg
|
|
1500
|
+
};
|
|
1501
|
+
recordRiverError(span, error);
|
|
1502
|
+
if (reqReadable.isClosed() && resWritable.isClosed()) {
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
if (!resWritable.isClosed()) {
|
|
1506
|
+
resWritable.write(Err(error));
|
|
1507
|
+
if (!procClosesWithResponse) {
|
|
1508
|
+
resWritable.close();
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
if (!reqReadable.isClosed()) {
|
|
1512
|
+
closeReadable();
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
const onMessage = (msg) => {
|
|
1516
|
+
if (msg.from !== from) {
|
|
1517
|
+
this.log?.error("got stream message from unexpected client", {
|
|
1518
|
+
...loggingMetadata,
|
|
1519
|
+
transportMessage: msg,
|
|
1520
|
+
tags: ["invariant-violation"]
|
|
1521
|
+
});
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
if (isStreamCancel(msg.controlFlags)) {
|
|
1525
|
+
const error = isSerializedProtocolErrorResult(
|
|
1526
|
+
msg.payload
|
|
1527
|
+
) ? msg.payload.payload : {
|
|
1528
|
+
code: CANCEL_CODE,
|
|
1529
|
+
message: "stream cancelled, client sent invalid payload"
|
|
1530
|
+
};
|
|
1531
|
+
pushRequestError(error);
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
if (reqReadable.isClosed()) {
|
|
1535
|
+
this.log?.warn("received message after request stream is closed", {
|
|
1536
|
+
...loggingMetadata,
|
|
1537
|
+
transportMessage: msg,
|
|
1538
|
+
tags: ["invalid-request"]
|
|
1539
|
+
});
|
|
1540
|
+
onServerCancel({
|
|
1541
|
+
code: INVALID_REQUEST_CODE,
|
|
1542
|
+
message: "received message after request stream is closed"
|
|
1543
|
+
});
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
if (msg.payload instanceof Uint8Array) {
|
|
1547
|
+
try {
|
|
1548
|
+
reqReadable._pushValue(
|
|
1549
|
+
Ok(decodeMessageBytes(method.input, msg.payload))
|
|
1550
|
+
);
|
|
1551
|
+
} catch {
|
|
1552
|
+
onServerCancel({
|
|
1553
|
+
code: INVALID_REQUEST_CODE,
|
|
1554
|
+
message: "failed to decode protobuf request payload"
|
|
1555
|
+
});
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
if (isStreamClose(msg.controlFlags)) {
|
|
1559
|
+
closeReadable();
|
|
1560
|
+
}
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (import_value2.Value.Check(ControlMessageCloseSchema, msg.payload) && isStreamClose(msg.controlFlags)) {
|
|
1564
|
+
closeReadable();
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
onServerCancel({
|
|
1568
|
+
code: INVALID_REQUEST_CODE,
|
|
1569
|
+
message: "received invalid protobuf request payload"
|
|
1570
|
+
});
|
|
1571
|
+
};
|
|
1572
|
+
const procStream = {
|
|
1573
|
+
from,
|
|
1574
|
+
streamId,
|
|
1575
|
+
service,
|
|
1576
|
+
method,
|
|
1577
|
+
handleMsg: onMessage,
|
|
1578
|
+
handleSessionDisconnect: () => {
|
|
1579
|
+
cleanClose = false;
|
|
1580
|
+
pushRequestError({
|
|
1581
|
+
code: UNEXPECTED_DISCONNECT_CODE,
|
|
1582
|
+
message: "client unexpectedly disconnected"
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
const handlerContext = {
|
|
1587
|
+
...serviceContext,
|
|
1588
|
+
state: serviceState,
|
|
1589
|
+
from,
|
|
1590
|
+
sessionId,
|
|
1591
|
+
metadata: sessionMetadata,
|
|
1592
|
+
span,
|
|
1593
|
+
service,
|
|
1594
|
+
method,
|
|
1595
|
+
deferCleanup,
|
|
1596
|
+
cancel: (message) => {
|
|
1597
|
+
const error = {
|
|
1598
|
+
code: CANCEL_CODE,
|
|
1599
|
+
message: message ?? "cancelled by server procedure handler"
|
|
1600
|
+
};
|
|
1601
|
+
onServerCancel(error);
|
|
1602
|
+
return Err(error);
|
|
1603
|
+
},
|
|
1604
|
+
signal: finishedController.signal
|
|
1605
|
+
};
|
|
1606
|
+
const middlewareContext = {
|
|
1607
|
+
...handlerContext,
|
|
1608
|
+
streamId,
|
|
1609
|
+
procedureName: method.name,
|
|
1610
|
+
serviceName: service.typeName
|
|
1611
|
+
};
|
|
1612
|
+
if (initialRequest !== null) {
|
|
1613
|
+
reqReadable._pushValue(Ok(initialRequest));
|
|
1614
|
+
}
|
|
1615
|
+
if (closeRequestOnStart) {
|
|
1616
|
+
closeReadable();
|
|
1617
|
+
}
|
|
1618
|
+
const handler = impl;
|
|
1619
|
+
const runProcedureHandler = async () => {
|
|
1620
|
+
try {
|
|
1621
|
+
switch (method.methodKind) {
|
|
1622
|
+
case "unary": {
|
|
1623
|
+
const response = await handler(
|
|
1624
|
+
requireInitialRequest(initialRequest, method),
|
|
1625
|
+
handlerContext
|
|
1626
|
+
);
|
|
1627
|
+
if (!resWritable.isClosed()) {
|
|
1628
|
+
resWritable.write(response);
|
|
1629
|
+
}
|
|
1630
|
+
break;
|
|
1631
|
+
}
|
|
1632
|
+
case "server_streaming":
|
|
1633
|
+
await handler({
|
|
1634
|
+
request: requireInitialRequest(initialRequest, method),
|
|
1635
|
+
ctx: handlerContext,
|
|
1636
|
+
resWritable
|
|
1637
|
+
});
|
|
1638
|
+
break;
|
|
1639
|
+
case "client_streaming": {
|
|
1640
|
+
const response = await handler({
|
|
1641
|
+
ctx: handlerContext,
|
|
1642
|
+
reqReadable
|
|
1643
|
+
});
|
|
1644
|
+
if (!resWritable.isClosed()) {
|
|
1645
|
+
resWritable.write(response);
|
|
1646
|
+
}
|
|
1647
|
+
break;
|
|
1648
|
+
}
|
|
1649
|
+
case "bidi_streaming":
|
|
1650
|
+
await handler({
|
|
1651
|
+
ctx: handlerContext,
|
|
1652
|
+
reqReadable,
|
|
1653
|
+
resWritable
|
|
1654
|
+
});
|
|
1655
|
+
break;
|
|
1656
|
+
}
|
|
1657
|
+
} catch (err) {
|
|
1658
|
+
onHandlerError(err);
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
this.middlewares.reduceRight(
|
|
1662
|
+
(next, middleware) => {
|
|
1663
|
+
return () => {
|
|
1664
|
+
middleware({
|
|
1665
|
+
ctx: middlewareContext,
|
|
1666
|
+
reqInit: initialRequest,
|
|
1667
|
+
next
|
|
1668
|
+
});
|
|
1669
|
+
};
|
|
1670
|
+
},
|
|
1671
|
+
() => {
|
|
1672
|
+
void runProcedureHandler();
|
|
1673
|
+
}
|
|
1674
|
+
)();
|
|
1675
|
+
if (!finishedController.signal.aborted) {
|
|
1676
|
+
this.streams.set(streamId, procStream);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
validateNewProcStream(initMessage) {
|
|
1680
|
+
const session = this.transport.sessions.get(initMessage.from);
|
|
1681
|
+
if (!session) {
|
|
1682
|
+
this.log?.error(`couldn't find session for ${initMessage.from}`, {
|
|
1683
|
+
clientId: this.transport.clientId,
|
|
1684
|
+
transportMessage: initMessage,
|
|
1685
|
+
tags: ["invariant-violation"]
|
|
1686
|
+
});
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1689
|
+
const sessionScopedSend = this.transport.getSessionBoundSendFn(
|
|
1690
|
+
initMessage.from,
|
|
1691
|
+
session.id
|
|
1692
|
+
);
|
|
1693
|
+
const sendCancel = (error) => {
|
|
1694
|
+
this.cancelStream(
|
|
1695
|
+
initMessage.from,
|
|
1696
|
+
sessionScopedSend,
|
|
1697
|
+
initMessage.streamId,
|
|
1698
|
+
error
|
|
1699
|
+
);
|
|
1700
|
+
};
|
|
1701
|
+
const sessionMetadata = this.transport.sessionHandshakeMetadata.get(
|
|
1702
|
+
session.to
|
|
1703
|
+
);
|
|
1704
|
+
if (!sessionMetadata) {
|
|
1705
|
+
sendCancel({
|
|
1706
|
+
code: UNCAUGHT_ERROR_CODE,
|
|
1707
|
+
message: `session doesn't have handshake metadata`
|
|
1708
|
+
});
|
|
1709
|
+
return null;
|
|
1710
|
+
}
|
|
1711
|
+
if (!isStreamOpen(initMessage.controlFlags)) {
|
|
1712
|
+
sendCancel({
|
|
1713
|
+
code: INVALID_REQUEST_CODE,
|
|
1714
|
+
message: `can't create a new procedure stream from a message without the stream open bit set`
|
|
1715
|
+
});
|
|
1716
|
+
return null;
|
|
1717
|
+
}
|
|
1718
|
+
if (!initMessage.serviceName) {
|
|
1719
|
+
sendCancel({
|
|
1720
|
+
code: INVALID_REQUEST_CODE,
|
|
1721
|
+
message: `missing service name in stream open message`
|
|
1722
|
+
});
|
|
1723
|
+
return null;
|
|
1724
|
+
}
|
|
1725
|
+
if (!initMessage.procedureName) {
|
|
1726
|
+
sendCancel({
|
|
1727
|
+
code: INVALID_REQUEST_CODE,
|
|
1728
|
+
message: `missing procedure name in stream open message`
|
|
1729
|
+
});
|
|
1730
|
+
return null;
|
|
1731
|
+
}
|
|
1732
|
+
const route = this.methods.get(
|
|
1733
|
+
methodKey(initMessage.serviceName, initMessage.procedureName)
|
|
1734
|
+
);
|
|
1735
|
+
if (!route) {
|
|
1736
|
+
sendCancel({
|
|
1737
|
+
code: "UNIMPLEMENTED" /* UNIMPLEMENTED */,
|
|
1738
|
+
message: `${initMessage.serviceName}.${initMessage.procedureName} is not implemented`
|
|
1739
|
+
});
|
|
1740
|
+
return null;
|
|
1741
|
+
}
|
|
1742
|
+
const serviceInstance = this.serviceInstances.get(initMessage.serviceName);
|
|
1743
|
+
let initialRequest = null;
|
|
1744
|
+
let closeRequestOnStart = false;
|
|
1745
|
+
if (route.method.methodKind === "unary" || route.method.methodKind === "server_streaming") {
|
|
1746
|
+
if (!(initMessage.payload instanceof Uint8Array)) {
|
|
1747
|
+
sendCancel({
|
|
1748
|
+
code: INVALID_REQUEST_CODE,
|
|
1749
|
+
message: "expected protobuf request payload in opening frame"
|
|
1750
|
+
});
|
|
1751
|
+
return null;
|
|
1752
|
+
}
|
|
1753
|
+
try {
|
|
1754
|
+
initialRequest = decodeMessageBytes(
|
|
1755
|
+
route.method.input,
|
|
1756
|
+
initMessage.payload
|
|
1757
|
+
);
|
|
1758
|
+
} catch {
|
|
1759
|
+
sendCancel({
|
|
1760
|
+
code: INVALID_REQUEST_CODE,
|
|
1761
|
+
message: "failed to decode protobuf request payload"
|
|
1762
|
+
});
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
if (!isStreamClose(initMessage.controlFlags)) {
|
|
1766
|
+
sendCancel({
|
|
1767
|
+
code: INVALID_REQUEST_CODE,
|
|
1768
|
+
message: "protobuf unary and server-streaming calls must close the request stream in the opening frame"
|
|
1769
|
+
});
|
|
1770
|
+
return null;
|
|
1771
|
+
}
|
|
1772
|
+
closeRequestOnStart = true;
|
|
1773
|
+
} else if (initMessage.payload instanceof Uint8Array) {
|
|
1774
|
+
if (initMessage.payload.byteLength > 0) {
|
|
1775
|
+
try {
|
|
1776
|
+
initialRequest = decodeMessageBytes(
|
|
1777
|
+
route.method.input,
|
|
1778
|
+
initMessage.payload
|
|
1779
|
+
);
|
|
1780
|
+
} catch {
|
|
1781
|
+
sendCancel({
|
|
1782
|
+
code: INVALID_REQUEST_CODE,
|
|
1783
|
+
message: "failed to decode protobuf request payload"
|
|
1784
|
+
});
|
|
1785
|
+
return null;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
closeRequestOnStart = isStreamClose(initMessage.controlFlags);
|
|
1789
|
+
} else if (import_value2.Value.Check(ControlMessageCloseSchema, initMessage.payload) && isStreamClose(initMessage.controlFlags)) {
|
|
1790
|
+
closeRequestOnStart = true;
|
|
1791
|
+
} else {
|
|
1792
|
+
sendCancel({
|
|
1793
|
+
code: INVALID_REQUEST_CODE,
|
|
1794
|
+
message: "received invalid protobuf request payload"
|
|
1795
|
+
});
|
|
1796
|
+
return null;
|
|
1797
|
+
}
|
|
1798
|
+
return {
|
|
1799
|
+
streamId: initMessage.streamId,
|
|
1800
|
+
service: route.service,
|
|
1801
|
+
method: route.method,
|
|
1802
|
+
impl: route.impl,
|
|
1803
|
+
serviceContext: this.userContext,
|
|
1804
|
+
serviceState: serviceInstance?.state ?? {},
|
|
1805
|
+
sessionMetadata,
|
|
1806
|
+
initialSession: session,
|
|
1807
|
+
initialRequest,
|
|
1808
|
+
closeRequestOnStart,
|
|
1809
|
+
tracingCtx: initMessage.tracing
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
cancelStream(to, sessionScopedSend, streamId, error) {
|
|
1813
|
+
let cancelledStreamsInSession = this.serverCancelledStreams.get(to);
|
|
1814
|
+
if (!cancelledStreamsInSession) {
|
|
1815
|
+
cancelledStreamsInSession = new LRUSet(
|
|
1816
|
+
this.maxCancelledStreamTombstonesPerSession
|
|
1817
|
+
);
|
|
1818
|
+
this.serverCancelledStreams.set(to, cancelledStreamsInSession);
|
|
1819
|
+
}
|
|
1820
|
+
cancelledStreamsInSession.add(streamId);
|
|
1821
|
+
sessionScopedSend(cancelMessage(streamId, Err(error)));
|
|
1822
|
+
}
|
|
1823
|
+
};
|
|
1824
|
+
function requireInitialRequest(initialRequest, method) {
|
|
1825
|
+
if (initialRequest === null) {
|
|
1826
|
+
throw new Error(
|
|
1827
|
+
`missing initial request for protobuf ${method.parent.typeName}.${method.name}`
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
return initialRequest;
|
|
1831
|
+
}
|
|
1832
|
+
var LRUSet = class {
|
|
1833
|
+
constructor(maxItems) {
|
|
1834
|
+
this.maxItems = maxItems;
|
|
1835
|
+
}
|
|
1836
|
+
items = /* @__PURE__ */ new Set();
|
|
1837
|
+
add(item) {
|
|
1838
|
+
if (this.items.has(item)) {
|
|
1839
|
+
this.items.delete(item);
|
|
1840
|
+
} else if (this.items.size >= this.maxItems) {
|
|
1841
|
+
const first = this.items.values().next();
|
|
1842
|
+
if (!first.done) {
|
|
1843
|
+
this.items.delete(first.value);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
this.items.add(item);
|
|
1847
|
+
}
|
|
1848
|
+
has(item) {
|
|
1849
|
+
return this.items.has(item);
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
function createServer(transport, services, options) {
|
|
1853
|
+
return new ProtobufServer(transport, services, options);
|
|
1854
|
+
}
|
|
1855
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1856
|
+
0 && (module.exports = {
|
|
1857
|
+
CANCEL_CODE,
|
|
1858
|
+
Err,
|
|
1859
|
+
INVALID_REQUEST_CODE,
|
|
1860
|
+
Ok,
|
|
1861
|
+
ProtoCodec,
|
|
1862
|
+
ReadableBrokenError,
|
|
1863
|
+
RiverErrorCode,
|
|
1864
|
+
UNCAUGHT_ERROR_CODE,
|
|
1865
|
+
UNEXPECTED_DISCONNECT_CODE,
|
|
1866
|
+
createClient,
|
|
1867
|
+
createClientHandshakeOptions,
|
|
1868
|
+
createProtoService,
|
|
1869
|
+
createServer,
|
|
1870
|
+
createServerHandshakeOptions,
|
|
1871
|
+
isClientError,
|
|
1872
|
+
isProtocolError,
|
|
1873
|
+
isRiverError,
|
|
1874
|
+
isSerializedClientErrorResult,
|
|
1875
|
+
isSerializedProtocolErrorResult
|
|
1876
|
+
});
|
|
1877
|
+
//# sourceMappingURL=index.cjs.map
|