@replit/river 0.23.16 → 0.200.0-rc.1
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/dist/chunk-45HIR2AS.js +1993 -0
- package/dist/chunk-45HIR2AS.js.map +1 -0
- package/dist/{chunk-YXDAOVP7.js → chunk-75B5D7MR.js} +2 -2
- package/dist/{chunk-WN77AT67.js → chunk-AJBZUHSI.js} +22 -6
- package/dist/chunk-AJBZUHSI.js.map +1 -0
- package/dist/{chunk-R47IZD67.js → chunk-EMIERCU7.js} +2 -2
- package/dist/{chunk-MQCGG6KL.js → chunk-LH2VHMQM.js} +4 -4
- package/dist/{chunk-6LCL2ZZF.js → chunk-QMM35C3H.js} +1 -1
- package/dist/chunk-QMM35C3H.js.map +1 -0
- package/dist/{chunk-JA7XGTAL.js → chunk-W75HU4F6.js} +4 -4
- package/dist/{chunk-UDXM64QK.js → chunk-WQVOMUNR.js} +2 -2
- package/dist/{chunk-TXSQRTZB.js → chunk-XLXRFSRB.js} +25 -10
- package/dist/chunk-XLXRFSRB.js.map +1 -0
- package/dist/{connection-d738cc08.d.ts → connection-0638316b.d.ts} +1 -1
- package/dist/{connection-99a67d3e.d.ts → connection-c6521735.d.ts} +1 -1
- package/dist/{index-ea74cdbb.d.ts → index-10ebd26a.d.ts} +33 -33
- package/dist/logging/index.cjs.map +1 -1
- package/dist/logging/index.d.cts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +1 -1
- package/dist/router/index.cjs +1109 -968
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +19 -23
- package/dist/router/index.d.ts +19 -23
- package/dist/router/index.js +12 -6
- package/dist/services-34d97070.d.ts +1366 -0
- package/dist/transport/impls/uds/client.cjs +20 -4
- package/dist/transport/impls/uds/client.cjs.map +1 -1
- package/dist/transport/impls/uds/client.d.cts +3 -4
- package/dist/transport/impls/uds/client.d.ts +3 -4
- package/dist/transport/impls/uds/client.js +6 -6
- package/dist/transport/impls/uds/server.cjs +20 -4
- package/dist/transport/impls/uds/server.cjs.map +1 -1
- package/dist/transport/impls/uds/server.d.cts +4 -4
- package/dist/transport/impls/uds/server.d.ts +4 -4
- package/dist/transport/impls/uds/server.js +6 -6
- package/dist/transport/impls/ws/client.cjs +20 -4
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +5 -6
- package/dist/transport/impls/ws/client.d.ts +5 -6
- package/dist/transport/impls/ws/client.js +6 -6
- package/dist/transport/impls/ws/server.cjs +20 -4
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +4 -4
- package/dist/transport/impls/ws/server.d.ts +4 -4
- package/dist/transport/impls/ws/server.js +6 -6
- package/dist/transport/index.cjs +20 -4
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +27 -5
- package/dist/transport/index.d.ts +27 -5
- package/dist/transport/index.js +6 -6
- package/dist/util/testHelpers.cjs +354 -310
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +32 -21
- package/dist/util/testHelpers.d.ts +32 -21
- package/dist/util/testHelpers.js +76 -42
- package/dist/util/testHelpers.js.map +1 -1
- package/package.json +2 -3
- package/dist/chunk-6LCL2ZZF.js.map +0 -1
- package/dist/chunk-LTSLICON.js +0 -1865
- package/dist/chunk-LTSLICON.js.map +0 -1
- package/dist/chunk-TXSQRTZB.js.map +0 -1
- package/dist/chunk-WN77AT67.js.map +0 -1
- package/dist/client-0926d3d6.d.ts +0 -52
- package/dist/handshake-75d0124f.d.ts +0 -516
- package/dist/server-3740c5d9.d.ts +0 -24
- package/dist/services-75e84a9f.d.ts +0 -709
- /package/dist/{chunk-YXDAOVP7.js.map → chunk-75B5D7MR.js.map} +0 -0
- /package/dist/{chunk-R47IZD67.js.map → chunk-EMIERCU7.js.map} +0 -0
- /package/dist/{chunk-MQCGG6KL.js.map → chunk-LH2VHMQM.js.map} +0 -0
- /package/dist/{chunk-JA7XGTAL.js.map → chunk-W75HU4F6.js.map} +0 -0
- /package/dist/{chunk-UDXM64QK.js.map → chunk-WQVOMUNR.js.map} +0 -0
package/dist/chunk-LTSLICON.js
DELETED
|
@@ -1,1865 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ControlMessagePayloadSchema,
|
|
3
|
-
coerceErrorString,
|
|
4
|
-
createHandlerSpan,
|
|
5
|
-
createProcTelemetryInfo,
|
|
6
|
-
getPropagationContext,
|
|
7
|
-
isStreamClose,
|
|
8
|
-
isStreamOpen
|
|
9
|
-
} from "./chunk-TXSQRTZB.js";
|
|
10
|
-
|
|
11
|
-
// router/services.ts
|
|
12
|
-
import { Type } from "@sinclair/typebox";
|
|
13
|
-
function serializeSchema(services, handshakeSchema) {
|
|
14
|
-
const serializedServiceObject = Object.entries(services).reduce((acc, [name, value]) => {
|
|
15
|
-
acc[name] = value.serialize();
|
|
16
|
-
return acc;
|
|
17
|
-
}, {});
|
|
18
|
-
const schema = {
|
|
19
|
-
services: serializedServiceObject
|
|
20
|
-
};
|
|
21
|
-
if (handshakeSchema) {
|
|
22
|
-
schema.handshakeSchema = Type.Strict(handshakeSchema);
|
|
23
|
-
}
|
|
24
|
-
return schema;
|
|
25
|
-
}
|
|
26
|
-
var ServiceSchema = class _ServiceSchema {
|
|
27
|
-
/**
|
|
28
|
-
* Factory function for creating a fresh state.
|
|
29
|
-
*/
|
|
30
|
-
initializeState;
|
|
31
|
-
/**
|
|
32
|
-
* The procedures for this service.
|
|
33
|
-
*/
|
|
34
|
-
procedures;
|
|
35
|
-
/**
|
|
36
|
-
* @param config - The configuration for this service.
|
|
37
|
-
* @param procedures - The procedures for this service.
|
|
38
|
-
*/
|
|
39
|
-
constructor(config, procedures) {
|
|
40
|
-
this.initializeState = config.initializeState;
|
|
41
|
-
this.procedures = procedures;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Creates a {@link ServiceScaffold}, which can be used to define procedures
|
|
45
|
-
* that can then be merged into a {@link ServiceSchema}, via the scaffold's
|
|
46
|
-
* `finalize` method.
|
|
47
|
-
*
|
|
48
|
-
* There are two patterns that work well with this method. The first is using
|
|
49
|
-
* it to separate the definition of procedures from the definition of the
|
|
50
|
-
* service's configuration:
|
|
51
|
-
* ```ts
|
|
52
|
-
* const MyServiceScaffold = ServiceSchema.scaffold({
|
|
53
|
-
* initializeState: () => ({ count: 0 }),
|
|
54
|
-
* });
|
|
55
|
-
*
|
|
56
|
-
* const incrementProcedures = MyServiceScaffold.procedures({
|
|
57
|
-
* increment: Procedure.rpc({
|
|
58
|
-
* input: Type.Object({ amount: Type.Number() }),
|
|
59
|
-
* output: Type.Object({ current: Type.Number() }),
|
|
60
|
-
* async handler(ctx, input) {
|
|
61
|
-
* ctx.state.count += input.amount;
|
|
62
|
-
* return Ok({ current: ctx.state.count });
|
|
63
|
-
* }
|
|
64
|
-
* }),
|
|
65
|
-
* })
|
|
66
|
-
*
|
|
67
|
-
* const MyService = MyServiceScaffold.finalize({
|
|
68
|
-
* ...incrementProcedures,
|
|
69
|
-
* // you can also directly define procedures here
|
|
70
|
-
* });
|
|
71
|
-
* ```
|
|
72
|
-
* This might be really handy if you have a very large service and you're
|
|
73
|
-
* wanting to split it over multiple files. You can define the scaffold
|
|
74
|
-
* in one file, and then import that scaffold in other files where you
|
|
75
|
-
* define procedures - and then finally import the scaffolds and your
|
|
76
|
-
* procedure objects in a final file where you finalize the scaffold into
|
|
77
|
-
* a service schema.
|
|
78
|
-
*
|
|
79
|
-
* The other way is to use it like in a builder pattern:
|
|
80
|
-
* ```ts
|
|
81
|
-
* const MyService = ServiceSchema
|
|
82
|
-
* .scaffold({ initializeState: () => ({ count: 0 }) })
|
|
83
|
-
* .finalize({
|
|
84
|
-
* increment: Procedure.rpc({
|
|
85
|
-
* input: Type.Object({ amount: Type.Number() }),
|
|
86
|
-
* output: Type.Object({ current: Type.Number() }),
|
|
87
|
-
* async handler(ctx, input) {
|
|
88
|
-
* ctx.state.count += input.amount;
|
|
89
|
-
* return Ok({ current: ctx.state.count });
|
|
90
|
-
* }
|
|
91
|
-
* }),
|
|
92
|
-
* })
|
|
93
|
-
* ```
|
|
94
|
-
* Depending on your preferences, this may be a more appealing way to define
|
|
95
|
-
* a schema versus using the {@link ServiceSchema.define} method.
|
|
96
|
-
*/
|
|
97
|
-
static scaffold(config) {
|
|
98
|
-
return new ServiceScaffold(config);
|
|
99
|
-
}
|
|
100
|
-
// actual implementation
|
|
101
|
-
static define(configOrProcedures, maybeProcedures) {
|
|
102
|
-
let config;
|
|
103
|
-
let procedures;
|
|
104
|
-
if ("initializeState" in configOrProcedures && typeof configOrProcedures.initializeState === "function") {
|
|
105
|
-
if (!maybeProcedures) {
|
|
106
|
-
throw new Error("Expected procedures to be defined");
|
|
107
|
-
}
|
|
108
|
-
config = configOrProcedures;
|
|
109
|
-
procedures = maybeProcedures;
|
|
110
|
-
} else {
|
|
111
|
-
config = { initializeState: () => ({}) };
|
|
112
|
-
procedures = configOrProcedures;
|
|
113
|
-
}
|
|
114
|
-
return new _ServiceSchema(config, procedures);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Serializes this schema's procedures into a plain object that is JSON compatible.
|
|
118
|
-
*/
|
|
119
|
-
serialize() {
|
|
120
|
-
return {
|
|
121
|
-
procedures: Object.fromEntries(
|
|
122
|
-
Object.entries(this.procedures).map(([procName, procDef]) => [
|
|
123
|
-
procName,
|
|
124
|
-
{
|
|
125
|
-
input: Type.Strict(procDef.input),
|
|
126
|
-
output: Type.Strict(procDef.output),
|
|
127
|
-
// Only add `description` field if the type declares it.
|
|
128
|
-
..."description" in procDef ? { description: procDef.description } : {},
|
|
129
|
-
// Only add the `errors` field if the type declares it.
|
|
130
|
-
..."errors" in procDef ? {
|
|
131
|
-
errors: Type.Strict(procDef.errors)
|
|
132
|
-
} : {},
|
|
133
|
-
type: procDef.type,
|
|
134
|
-
// Only add the `init` field if the type declares it.
|
|
135
|
-
..."init" in procDef ? {
|
|
136
|
-
init: Type.Strict(procDef.init)
|
|
137
|
-
} : {}
|
|
138
|
-
}
|
|
139
|
-
])
|
|
140
|
-
)
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Instantiates this schema into a {@link Service} object.
|
|
145
|
-
*
|
|
146
|
-
* You probably don't need this, usually the River server will handle this
|
|
147
|
-
* for you.
|
|
148
|
-
*/
|
|
149
|
-
instantiate() {
|
|
150
|
-
return Object.freeze({
|
|
151
|
-
state: this.initializeState(),
|
|
152
|
-
procedures: this.procedures
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
var ServiceScaffold = class {
|
|
157
|
-
/**
|
|
158
|
-
* The configuration for this service.
|
|
159
|
-
*/
|
|
160
|
-
config;
|
|
161
|
-
/**
|
|
162
|
-
* @param config - The configuration for this service.
|
|
163
|
-
*/
|
|
164
|
-
constructor(config) {
|
|
165
|
-
this.config = config;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Define procedures for this service. Use the {@link Procedure} constructors
|
|
169
|
-
* to create them. This returns the procedures object, which can then be
|
|
170
|
-
* passed to {@link ServiceSchema.finalize} to create a {@link ServiceSchema}.
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* ```
|
|
174
|
-
* const myProcedures = MyServiceScaffold.procedures({
|
|
175
|
-
* myRPC: Procedure.rpc({
|
|
176
|
-
* // ...
|
|
177
|
-
* }),
|
|
178
|
-
* });
|
|
179
|
-
*
|
|
180
|
-
* const MyService = MyServiceScaffold.finalize({
|
|
181
|
-
* ...myProcedures,
|
|
182
|
-
* });
|
|
183
|
-
* ```
|
|
184
|
-
*
|
|
185
|
-
* @param procedures - The procedures for this service.
|
|
186
|
-
*/
|
|
187
|
-
procedures(procedures) {
|
|
188
|
-
return procedures;
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Finalizes the scaffold into a {@link ServiceSchema}. This is where you
|
|
192
|
-
* provide the service's procedures and get a {@link ServiceSchema} in return.
|
|
193
|
-
*
|
|
194
|
-
* You can directly define procedures here, or you can define them separately
|
|
195
|
-
* with the {@link ServiceScaffold.procedures} method, and then pass them here.
|
|
196
|
-
*
|
|
197
|
-
* @example
|
|
198
|
-
* ```
|
|
199
|
-
* const MyService = MyServiceScaffold.finalize({
|
|
200
|
-
* myRPC: Procedure.rpc({
|
|
201
|
-
* // ...
|
|
202
|
-
* }),
|
|
203
|
-
* // e.g. from the procedures method
|
|
204
|
-
* ...myOtherProcedures,
|
|
205
|
-
* });
|
|
206
|
-
* ```
|
|
207
|
-
*/
|
|
208
|
-
finalize(procedures) {
|
|
209
|
-
return ServiceSchema.define(this.config, procedures);
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// router/diff.ts
|
|
214
|
-
function diffServerSchema(oldServer, newServer, options) {
|
|
215
|
-
const allServices = /* @__PURE__ */ new Set([
|
|
216
|
-
...Object.keys(oldServer.services),
|
|
217
|
-
...Object.keys(newServer.services)
|
|
218
|
-
]);
|
|
219
|
-
const breakages = {};
|
|
220
|
-
for (const serviceName of allServices) {
|
|
221
|
-
const oldService = oldServer.services[serviceName];
|
|
222
|
-
const newService = newServer.services[serviceName];
|
|
223
|
-
const breakage = diffService(oldService, newService, options);
|
|
224
|
-
if (breakage) {
|
|
225
|
-
breakages[serviceName] = breakage;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
if (Object.keys(breakages).length) {
|
|
229
|
-
return { serviceBreakages: breakages };
|
|
230
|
-
}
|
|
231
|
-
return null;
|
|
232
|
-
}
|
|
233
|
-
function diffService(oldService, newService, options) {
|
|
234
|
-
if (!newService) {
|
|
235
|
-
return options?.allowServiceRemoval ? null : { reason: "removed" };
|
|
236
|
-
}
|
|
237
|
-
if (!oldService) {
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
const allProcedures = /* @__PURE__ */ new Set([
|
|
241
|
-
...Object.keys(oldService.procedures),
|
|
242
|
-
...Object.keys(newService.procedures)
|
|
243
|
-
]);
|
|
244
|
-
const breakages = {};
|
|
245
|
-
for (const procedureName of allProcedures) {
|
|
246
|
-
const aProcedure = oldService.procedures[procedureName];
|
|
247
|
-
const bProcedure = newService.procedures[procedureName];
|
|
248
|
-
const breakage = diffProcedure(aProcedure, bProcedure, options);
|
|
249
|
-
if (breakage) {
|
|
250
|
-
breakages[procedureName] = breakage;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (Object.keys(breakages).length) {
|
|
254
|
-
return { reason: "modified", procedureBreakages: breakages };
|
|
255
|
-
}
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
function diffProcedure(oldProcedure, newProcedure, options) {
|
|
259
|
-
if (!newProcedure) {
|
|
260
|
-
return options?.allowProcedureRemoval ? null : { reason: "removed" };
|
|
261
|
-
}
|
|
262
|
-
if (!oldProcedure) {
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
if (oldProcedure.type !== newProcedure.type) {
|
|
266
|
-
return {
|
|
267
|
-
reason: "type-changed",
|
|
268
|
-
oldType: oldProcedure.type,
|
|
269
|
-
newType: newProcedure.type
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
const inputBreakage = diffProcedureField(
|
|
273
|
-
oldProcedure.input,
|
|
274
|
-
newProcedure.input,
|
|
275
|
-
"client"
|
|
276
|
-
);
|
|
277
|
-
const initBreakage = diffProcedureField(
|
|
278
|
-
oldProcedure.init,
|
|
279
|
-
newProcedure.init,
|
|
280
|
-
"client"
|
|
281
|
-
);
|
|
282
|
-
const outputBreakage = diffProcedureField(
|
|
283
|
-
oldProcedure.output,
|
|
284
|
-
newProcedure.output,
|
|
285
|
-
"server"
|
|
286
|
-
);
|
|
287
|
-
if (inputBreakage ?? initBreakage ?? outputBreakage) {
|
|
288
|
-
const result = {
|
|
289
|
-
reason: "modified"
|
|
290
|
-
};
|
|
291
|
-
if (inputBreakage) {
|
|
292
|
-
result.input = inputBreakage;
|
|
293
|
-
}
|
|
294
|
-
if (initBreakage) {
|
|
295
|
-
result.init = initBreakage;
|
|
296
|
-
}
|
|
297
|
-
if (outputBreakage) {
|
|
298
|
-
result.output = outputBreakage;
|
|
299
|
-
}
|
|
300
|
-
return result;
|
|
301
|
-
}
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
304
|
-
function diffProcedureField(oldSchema, newSchema, origin) {
|
|
305
|
-
if (!oldSchema && !newSchema) {
|
|
306
|
-
return null;
|
|
307
|
-
}
|
|
308
|
-
const diffBreakage = diffRequired(oldSchema, newSchema, origin, false, false);
|
|
309
|
-
if (diffBreakage) {
|
|
310
|
-
return diffBreakage;
|
|
311
|
-
}
|
|
312
|
-
if (!oldSchema || !newSchema) {
|
|
313
|
-
throw new Error("Appease typescript, this should never happen");
|
|
314
|
-
}
|
|
315
|
-
return diffJSONSchema(oldSchema, newSchema, origin);
|
|
316
|
-
}
|
|
317
|
-
function diffRequired(oldSchema, newSchema, origin, oldRequired, newRequired) {
|
|
318
|
-
if (!newSchema && !oldSchema) {
|
|
319
|
-
throw new Error("Both old and new schema are undefined");
|
|
320
|
-
}
|
|
321
|
-
if (!newSchema) {
|
|
322
|
-
if (!oldRequired && origin == "server") {
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
return { reason: "removed-required" };
|
|
326
|
-
}
|
|
327
|
-
if (!oldSchema) {
|
|
328
|
-
if (newRequired && origin === "client") {
|
|
329
|
-
return { reason: "new-required" };
|
|
330
|
-
}
|
|
331
|
-
return null;
|
|
332
|
-
}
|
|
333
|
-
if (origin === "client" && !oldRequired && newRequired) {
|
|
334
|
-
return { reason: "new-required" };
|
|
335
|
-
}
|
|
336
|
-
if (origin === "server" && oldRequired && !newRequired) {
|
|
337
|
-
return { reason: "removed-required" };
|
|
338
|
-
}
|
|
339
|
-
return null;
|
|
340
|
-
}
|
|
341
|
-
function diffJSONSchema(oldSchema, newSchema, origin) {
|
|
342
|
-
if (oldSchema.type !== newSchema.type) {
|
|
343
|
-
return {
|
|
344
|
-
reason: "type-changed",
|
|
345
|
-
oldType: getReportingType(oldSchema),
|
|
346
|
-
newType: getReportingType(newSchema)
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
if (getReportingType(oldSchema) !== getReportingType(newSchema)) {
|
|
350
|
-
return {
|
|
351
|
-
reason: "type-changed",
|
|
352
|
-
oldType: getReportingType(oldSchema),
|
|
353
|
-
newType: getReportingType(newSchema)
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
if ("const" in oldSchema && "const" in newSchema && oldSchema.const !== newSchema.const) {
|
|
357
|
-
return {
|
|
358
|
-
reason: "type-changed",
|
|
359
|
-
oldType: `${getReportingType(oldSchema)}-const-${oldSchema.const}`,
|
|
360
|
-
newType: `${getReportingType(newSchema)}-const-${newSchema.const}`
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
if ("const" in oldSchema && !("const" in newSchema) && origin === "server") {
|
|
364
|
-
return {
|
|
365
|
-
reason: "type-changed",
|
|
366
|
-
oldType: `${getReportingType(oldSchema)}-const-${oldSchema.const}`,
|
|
367
|
-
newType: getReportingType(newSchema)
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
if ("const" in newSchema && !("const" in oldSchema) && origin === "client") {
|
|
371
|
-
return {
|
|
372
|
-
reason: "type-changed",
|
|
373
|
-
oldType: getReportingType(oldSchema),
|
|
374
|
-
newType: `${getReportingType(newSchema)}-const-${newSchema.const}`
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
const breakages = {};
|
|
378
|
-
if ("$ref" in newSchema) {
|
|
379
|
-
if (newSchema.$ref !== oldSchema.$ref) {
|
|
380
|
-
return {
|
|
381
|
-
reason: "type-changed",
|
|
382
|
-
oldType: getReportingType(oldSchema),
|
|
383
|
-
newType: getReportingType(newSchema)
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
} else if ("not" in newSchema) {
|
|
387
|
-
const notBreakage = diffJSONSchema(
|
|
388
|
-
oldSchema.not,
|
|
389
|
-
newSchema.not,
|
|
390
|
-
origin
|
|
391
|
-
);
|
|
392
|
-
if (notBreakage) {
|
|
393
|
-
breakages.not = notBreakage;
|
|
394
|
-
}
|
|
395
|
-
} else if ("anyOf" in newSchema) {
|
|
396
|
-
const oldAnyOfStringified = oldSchema.anyOf.map((el) => JSON.stringify(el)).sort();
|
|
397
|
-
const newAnyOfStringified = newSchema.anyOf.map((el) => JSON.stringify(el)).sort();
|
|
398
|
-
const anyOfBreakages = {};
|
|
399
|
-
for (let i = 0; i < oldAnyOfStringified.length; i++) {
|
|
400
|
-
if (newAnyOfStringified.includes(oldAnyOfStringified[i])) {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
if (!newAnyOfStringified[i]) {
|
|
404
|
-
if (origin === "server") {
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
anyOfBreakages[`old-${i}`] = { reason: "removed-required" };
|
|
408
|
-
} else {
|
|
409
|
-
const breakage = diffJSONSchema(
|
|
410
|
-
JSON.parse(oldAnyOfStringified[i]),
|
|
411
|
-
JSON.parse(newAnyOfStringified[i]),
|
|
412
|
-
origin
|
|
413
|
-
);
|
|
414
|
-
if (breakage) {
|
|
415
|
-
anyOfBreakages[`old-${i}`] = breakage;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
for (let i = 0; i < newAnyOfStringified.length; i++) {
|
|
420
|
-
if (oldAnyOfStringified.includes(newAnyOfStringified[i])) {
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
if (!oldAnyOfStringified[i]) {
|
|
424
|
-
if (origin === "client") {
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
anyOfBreakages[`new-${i}`] = { reason: "new-required" };
|
|
428
|
-
} else {
|
|
429
|
-
const breakage = diffJSONSchema(
|
|
430
|
-
JSON.parse(oldAnyOfStringified[i]),
|
|
431
|
-
JSON.parse(newAnyOfStringified[i]),
|
|
432
|
-
origin
|
|
433
|
-
);
|
|
434
|
-
if (breakage) {
|
|
435
|
-
anyOfBreakages[`new-${i}`] = breakage;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
if (Object.keys(anyOfBreakages).length > 0) {
|
|
440
|
-
breakages.anyOf = {
|
|
441
|
-
reason: "field-breakage",
|
|
442
|
-
fieldBreakages: anyOfBreakages
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
} else if ("oneOf" in newSchema) {
|
|
446
|
-
throw new Error("oneOf is not supported, typebox does not emit it");
|
|
447
|
-
} else if ("allOf" in newSchema) {
|
|
448
|
-
if (newSchema.allOf.length !== oldSchema.allOf.length) {
|
|
449
|
-
breakages.allOf = {
|
|
450
|
-
reason: "type-changed",
|
|
451
|
-
oldType: `${oldSchema.allOf}`,
|
|
452
|
-
newType: `${newSchema.allOf}`
|
|
453
|
-
};
|
|
454
|
-
} else {
|
|
455
|
-
for (let i = 0; i < newSchema.allOf.length; i++) {
|
|
456
|
-
const breakage = diffJSONSchema(
|
|
457
|
-
oldSchema.allOf[i],
|
|
458
|
-
newSchema.allOf[i],
|
|
459
|
-
origin
|
|
460
|
-
);
|
|
461
|
-
if (breakage) {
|
|
462
|
-
breakages.allOf = breakage;
|
|
463
|
-
break;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
} else if (newSchema.type === "array") {
|
|
468
|
-
const itemsBreakages = diffJSONSchema(
|
|
469
|
-
oldSchema.items,
|
|
470
|
-
newSchema.items,
|
|
471
|
-
origin
|
|
472
|
-
);
|
|
473
|
-
if (itemsBreakages) {
|
|
474
|
-
breakages.items = itemsBreakages;
|
|
475
|
-
}
|
|
476
|
-
if (oldSchema.minItems < newSchema.minItems) {
|
|
477
|
-
if (origin === "client") {
|
|
478
|
-
breakages.minItems = {
|
|
479
|
-
reason: "type-changed",
|
|
480
|
-
oldType: `${oldSchema.minItems}`,
|
|
481
|
-
newType: `${newSchema.minItems}`
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
} else if (oldSchema.minItems > newSchema.minItems) {
|
|
485
|
-
if (origin === "server") {
|
|
486
|
-
breakages.minItems = {
|
|
487
|
-
reason: "type-changed",
|
|
488
|
-
oldType: `${oldSchema.minItems}`,
|
|
489
|
-
newType: `${newSchema.minItems}`
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
if (oldSchema.maxItems < newSchema.maxItems) {
|
|
494
|
-
if (origin === "server") {
|
|
495
|
-
breakages.maxItems = {
|
|
496
|
-
reason: "type-changed",
|
|
497
|
-
oldType: `${oldSchema.maxItems}`,
|
|
498
|
-
newType: `${newSchema.maxItems}`
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
} else if (oldSchema.maxItems > newSchema.maxItems) {
|
|
502
|
-
if (origin === "client") {
|
|
503
|
-
breakages.maxItems = {
|
|
504
|
-
reason: "type-changed",
|
|
505
|
-
oldType: `${oldSchema.maxItems}`,
|
|
506
|
-
newType: `${newSchema.maxItems}`
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
if (!oldSchema.uniqueItems && newSchema.uniqueItems && origin === "client") {
|
|
511
|
-
breakages.uniqueItems = {
|
|
512
|
-
reason: "type-changed",
|
|
513
|
-
oldType: `${!!oldSchema.uniqueItems}`,
|
|
514
|
-
newType: `${!!newSchema.uniqueItems}`
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
if ("contains" in newSchema !== "contains" in oldSchema) {
|
|
518
|
-
if ("contains" in newSchema && !("contains" in oldSchema) && origin === "client") {
|
|
519
|
-
breakages.contains = {
|
|
520
|
-
reason: "type-changed",
|
|
521
|
-
oldType: "no-contains",
|
|
522
|
-
newType: "contains"
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
} else if ("contains" in newSchema) {
|
|
526
|
-
const containsBreakage = diffJSONSchema(
|
|
527
|
-
oldSchema.contains,
|
|
528
|
-
newSchema.contains,
|
|
529
|
-
origin
|
|
530
|
-
);
|
|
531
|
-
if (containsBreakage) {
|
|
532
|
-
breakages.contains = containsBreakage;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
if (oldSchema.minContains < newSchema.minContains) {
|
|
536
|
-
if (origin === "client") {
|
|
537
|
-
breakages.minContains = {
|
|
538
|
-
reason: "type-changed",
|
|
539
|
-
oldType: `${oldSchema.minContains}`,
|
|
540
|
-
newType: `${newSchema.minContains}`
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
} else if (oldSchema.minContains > newSchema.minContains) {
|
|
544
|
-
if (origin === "server") {
|
|
545
|
-
breakages.minContains = {
|
|
546
|
-
reason: "type-changed",
|
|
547
|
-
oldType: `${oldSchema.minContains}`,
|
|
548
|
-
newType: `${newSchema.minContains}`
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
if (oldSchema.maxContains < newSchema.maxContains) {
|
|
553
|
-
if (origin === "server") {
|
|
554
|
-
breakages.maxContains = {
|
|
555
|
-
reason: "type-changed",
|
|
556
|
-
oldType: `${oldSchema.maxContains}`,
|
|
557
|
-
newType: `${newSchema.maxContains}`
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
} else if (oldSchema.maxContains > newSchema.maxContains) {
|
|
561
|
-
if (origin === "client") {
|
|
562
|
-
breakages.maxContains = {
|
|
563
|
-
reason: "type-changed",
|
|
564
|
-
oldType: `${oldSchema.maxContains}`,
|
|
565
|
-
newType: `${newSchema.maxContains}`
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
} else if (newSchema.type === "object") {
|
|
570
|
-
if ("properties" in newSchema !== "properties" in oldSchema) {
|
|
571
|
-
return {
|
|
572
|
-
reason: "type-changed",
|
|
573
|
-
oldType: "properties" in oldSchema ? "probably-object" : "probably-record",
|
|
574
|
-
newType: "properties" in newSchema ? "probably-object" : "probably-record"
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
if ("properties" in newSchema) {
|
|
578
|
-
const propertiesBreakages = diffObjectProperties(
|
|
579
|
-
oldSchema.properties,
|
|
580
|
-
newSchema.properties,
|
|
581
|
-
origin,
|
|
582
|
-
oldSchema.required,
|
|
583
|
-
newSchema.required
|
|
584
|
-
);
|
|
585
|
-
if (Object.keys(propertiesBreakages).length) {
|
|
586
|
-
breakages.properties = {
|
|
587
|
-
reason: "field-breakage",
|
|
588
|
-
fieldBreakages: propertiesBreakages
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
if ("patternProperties" in newSchema) {
|
|
593
|
-
const patternPropertiesBreakages = diffObjectProperties(
|
|
594
|
-
oldSchema.patternProperties,
|
|
595
|
-
newSchema.patternProperties,
|
|
596
|
-
origin,
|
|
597
|
-
oldSchema.required,
|
|
598
|
-
newSchema.required
|
|
599
|
-
);
|
|
600
|
-
if (Object.keys(patternPropertiesBreakages).length) {
|
|
601
|
-
breakages.patternProperties = {
|
|
602
|
-
reason: "field-breakage",
|
|
603
|
-
fieldBreakages: patternPropertiesBreakages
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
if ("additionalProperties" in newSchema || "additionalProperties" in oldSchema) {
|
|
608
|
-
throw new Error("additionalProperties is not supported");
|
|
609
|
-
}
|
|
610
|
-
if ("minProperties" in newSchema || "minProperties" in oldSchema) {
|
|
611
|
-
throw new Error("minProperties is not supported");
|
|
612
|
-
}
|
|
613
|
-
if ("maxProperties" in newSchema || "maxProperties" in oldSchema) {
|
|
614
|
-
throw new Error("maxProperties is not supported");
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
if (Object.keys(breakages).length) {
|
|
618
|
-
return {
|
|
619
|
-
reason: "field-breakage",
|
|
620
|
-
fieldBreakages: breakages
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
return null;
|
|
624
|
-
}
|
|
625
|
-
function diffObjectProperties(oldProperties, newProperties, origin, oldRequiredProperties = [], newRequiredProperties = []) {
|
|
626
|
-
const allProperties = /* @__PURE__ */ new Set([
|
|
627
|
-
...Object.keys(oldProperties),
|
|
628
|
-
...Object.keys(newProperties)
|
|
629
|
-
]);
|
|
630
|
-
const breakages = {};
|
|
631
|
-
for (const propertyName of allProperties) {
|
|
632
|
-
const requiredBreakage = diffRequired(
|
|
633
|
-
oldProperties[propertyName],
|
|
634
|
-
newProperties[propertyName],
|
|
635
|
-
origin,
|
|
636
|
-
oldRequiredProperties.includes(propertyName),
|
|
637
|
-
newRequiredProperties.includes(propertyName)
|
|
638
|
-
);
|
|
639
|
-
if (requiredBreakage) {
|
|
640
|
-
breakages[propertyName] = requiredBreakage;
|
|
641
|
-
} else if (oldProperties[propertyName] && newProperties[propertyName]) {
|
|
642
|
-
const propertyBreakage = diffJSONSchema(
|
|
643
|
-
oldProperties[propertyName],
|
|
644
|
-
newProperties[propertyName],
|
|
645
|
-
origin
|
|
646
|
-
);
|
|
647
|
-
if (propertyBreakage) {
|
|
648
|
-
breakages[propertyName] = propertyBreakage;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
return breakages;
|
|
653
|
-
}
|
|
654
|
-
function getReportingType(schema) {
|
|
655
|
-
if ("not" in schema) {
|
|
656
|
-
return "not";
|
|
657
|
-
}
|
|
658
|
-
if ("anyOf" in schema) {
|
|
659
|
-
return "anyOf";
|
|
660
|
-
}
|
|
661
|
-
if ("allOf" in schema) {
|
|
662
|
-
return "allOf";
|
|
663
|
-
}
|
|
664
|
-
if ("$ref" in schema) {
|
|
665
|
-
return "$ref";
|
|
666
|
-
}
|
|
667
|
-
if (schema.type && typeof schema.type === "string") {
|
|
668
|
-
return schema.type;
|
|
669
|
-
}
|
|
670
|
-
throw new Error(
|
|
671
|
-
"Subschema not supported, probably a conditional subschema. Check logs."
|
|
672
|
-
);
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
// router/procedures.ts
|
|
676
|
-
import { Type as Type2 } from "@sinclair/typebox";
|
|
677
|
-
function rpc({
|
|
678
|
-
input,
|
|
679
|
-
output,
|
|
680
|
-
errors = Type2.Never(),
|
|
681
|
-
description,
|
|
682
|
-
handler
|
|
683
|
-
}) {
|
|
684
|
-
return {
|
|
685
|
-
...description ? { description } : {},
|
|
686
|
-
type: "rpc",
|
|
687
|
-
input,
|
|
688
|
-
output,
|
|
689
|
-
errors,
|
|
690
|
-
handler
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
function upload({
|
|
694
|
-
init,
|
|
695
|
-
input,
|
|
696
|
-
output,
|
|
697
|
-
errors = Type2.Never(),
|
|
698
|
-
description,
|
|
699
|
-
handler
|
|
700
|
-
}) {
|
|
701
|
-
return init !== void 0 && init !== null ? {
|
|
702
|
-
type: "upload",
|
|
703
|
-
...description ? { description } : {},
|
|
704
|
-
init,
|
|
705
|
-
input,
|
|
706
|
-
output,
|
|
707
|
-
errors,
|
|
708
|
-
handler
|
|
709
|
-
} : {
|
|
710
|
-
type: "upload",
|
|
711
|
-
...description ? { description } : {},
|
|
712
|
-
input,
|
|
713
|
-
output,
|
|
714
|
-
errors,
|
|
715
|
-
handler
|
|
716
|
-
};
|
|
717
|
-
}
|
|
718
|
-
function subscription({
|
|
719
|
-
input,
|
|
720
|
-
output,
|
|
721
|
-
errors = Type2.Never(),
|
|
722
|
-
description,
|
|
723
|
-
handler
|
|
724
|
-
}) {
|
|
725
|
-
return {
|
|
726
|
-
type: "subscription",
|
|
727
|
-
...description ? { description } : {},
|
|
728
|
-
input,
|
|
729
|
-
output,
|
|
730
|
-
errors,
|
|
731
|
-
handler
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
function stream({
|
|
735
|
-
init,
|
|
736
|
-
input,
|
|
737
|
-
output,
|
|
738
|
-
errors = Type2.Never(),
|
|
739
|
-
description,
|
|
740
|
-
handler
|
|
741
|
-
}) {
|
|
742
|
-
return init !== void 0 && init !== null ? {
|
|
743
|
-
type: "stream",
|
|
744
|
-
...description ? { description } : {},
|
|
745
|
-
init,
|
|
746
|
-
input,
|
|
747
|
-
output,
|
|
748
|
-
errors,
|
|
749
|
-
handler
|
|
750
|
-
} : {
|
|
751
|
-
type: "stream",
|
|
752
|
-
...description ? { description } : {},
|
|
753
|
-
input,
|
|
754
|
-
output,
|
|
755
|
-
errors,
|
|
756
|
-
handler
|
|
757
|
-
};
|
|
758
|
-
}
|
|
759
|
-
var Procedure = {
|
|
760
|
-
rpc,
|
|
761
|
-
upload,
|
|
762
|
-
subscription,
|
|
763
|
-
stream
|
|
764
|
-
};
|
|
765
|
-
|
|
766
|
-
// node_modules/p-defer/index.js
|
|
767
|
-
function pDefer() {
|
|
768
|
-
const deferred = {};
|
|
769
|
-
deferred.promise = new Promise((resolve, reject) => {
|
|
770
|
-
deferred.resolve = resolve;
|
|
771
|
-
deferred.reject = reject;
|
|
772
|
-
});
|
|
773
|
-
return deferred;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
// node_modules/it-pushable/dist/src/fifo.js
|
|
777
|
-
var FixedFIFO = class {
|
|
778
|
-
buffer;
|
|
779
|
-
mask;
|
|
780
|
-
top;
|
|
781
|
-
btm;
|
|
782
|
-
next;
|
|
783
|
-
constructor(hwm) {
|
|
784
|
-
if (!(hwm > 0) || (hwm - 1 & hwm) !== 0) {
|
|
785
|
-
throw new Error("Max size for a FixedFIFO should be a power of two");
|
|
786
|
-
}
|
|
787
|
-
this.buffer = new Array(hwm);
|
|
788
|
-
this.mask = hwm - 1;
|
|
789
|
-
this.top = 0;
|
|
790
|
-
this.btm = 0;
|
|
791
|
-
this.next = null;
|
|
792
|
-
}
|
|
793
|
-
push(data) {
|
|
794
|
-
if (this.buffer[this.top] !== void 0) {
|
|
795
|
-
return false;
|
|
796
|
-
}
|
|
797
|
-
this.buffer[this.top] = data;
|
|
798
|
-
this.top = this.top + 1 & this.mask;
|
|
799
|
-
return true;
|
|
800
|
-
}
|
|
801
|
-
shift() {
|
|
802
|
-
const last = this.buffer[this.btm];
|
|
803
|
-
if (last === void 0) {
|
|
804
|
-
return void 0;
|
|
805
|
-
}
|
|
806
|
-
this.buffer[this.btm] = void 0;
|
|
807
|
-
this.btm = this.btm + 1 & this.mask;
|
|
808
|
-
return last;
|
|
809
|
-
}
|
|
810
|
-
isEmpty() {
|
|
811
|
-
return this.buffer[this.btm] === void 0;
|
|
812
|
-
}
|
|
813
|
-
};
|
|
814
|
-
var FIFO = class {
|
|
815
|
-
size;
|
|
816
|
-
hwm;
|
|
817
|
-
head;
|
|
818
|
-
tail;
|
|
819
|
-
constructor(options = {}) {
|
|
820
|
-
this.hwm = options.splitLimit ?? 16;
|
|
821
|
-
this.head = new FixedFIFO(this.hwm);
|
|
822
|
-
this.tail = this.head;
|
|
823
|
-
this.size = 0;
|
|
824
|
-
}
|
|
825
|
-
calculateSize(obj) {
|
|
826
|
-
if (obj?.byteLength != null) {
|
|
827
|
-
return obj.byteLength;
|
|
828
|
-
}
|
|
829
|
-
return 1;
|
|
830
|
-
}
|
|
831
|
-
push(val) {
|
|
832
|
-
if (val?.value != null) {
|
|
833
|
-
this.size += this.calculateSize(val.value);
|
|
834
|
-
}
|
|
835
|
-
if (!this.head.push(val)) {
|
|
836
|
-
const prev = this.head;
|
|
837
|
-
this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length);
|
|
838
|
-
this.head.push(val);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
shift() {
|
|
842
|
-
let val = this.tail.shift();
|
|
843
|
-
if (val === void 0 && this.tail.next != null) {
|
|
844
|
-
const next = this.tail.next;
|
|
845
|
-
this.tail.next = null;
|
|
846
|
-
this.tail = next;
|
|
847
|
-
val = this.tail.shift();
|
|
848
|
-
}
|
|
849
|
-
if (val?.value != null) {
|
|
850
|
-
this.size -= this.calculateSize(val.value);
|
|
851
|
-
}
|
|
852
|
-
return val;
|
|
853
|
-
}
|
|
854
|
-
isEmpty() {
|
|
855
|
-
return this.head.isEmpty();
|
|
856
|
-
}
|
|
857
|
-
};
|
|
858
|
-
|
|
859
|
-
// node_modules/it-pushable/dist/src/index.js
|
|
860
|
-
var AbortError = class extends Error {
|
|
861
|
-
type;
|
|
862
|
-
code;
|
|
863
|
-
constructor(message, code) {
|
|
864
|
-
super(message ?? "The operation was aborted");
|
|
865
|
-
this.type = "aborted";
|
|
866
|
-
this.code = code ?? "ABORT_ERR";
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
function pushable(options = {}) {
|
|
870
|
-
const getNext = (buffer) => {
|
|
871
|
-
const next = buffer.shift();
|
|
872
|
-
if (next == null) {
|
|
873
|
-
return { done: true };
|
|
874
|
-
}
|
|
875
|
-
if (next.error != null) {
|
|
876
|
-
throw next.error;
|
|
877
|
-
}
|
|
878
|
-
return {
|
|
879
|
-
done: next.done === true,
|
|
880
|
-
// @ts-expect-error if done is false, value will be present
|
|
881
|
-
value: next.value
|
|
882
|
-
};
|
|
883
|
-
};
|
|
884
|
-
return _pushable(getNext, options);
|
|
885
|
-
}
|
|
886
|
-
function _pushable(getNext, options) {
|
|
887
|
-
options = options ?? {};
|
|
888
|
-
let onEnd = options.onEnd;
|
|
889
|
-
let buffer = new FIFO();
|
|
890
|
-
let pushable2;
|
|
891
|
-
let onNext;
|
|
892
|
-
let ended;
|
|
893
|
-
let drain = pDefer();
|
|
894
|
-
const waitNext = async () => {
|
|
895
|
-
try {
|
|
896
|
-
if (!buffer.isEmpty()) {
|
|
897
|
-
return getNext(buffer);
|
|
898
|
-
}
|
|
899
|
-
if (ended) {
|
|
900
|
-
return { done: true };
|
|
901
|
-
}
|
|
902
|
-
return await new Promise((resolve, reject) => {
|
|
903
|
-
onNext = (next) => {
|
|
904
|
-
onNext = null;
|
|
905
|
-
buffer.push(next);
|
|
906
|
-
try {
|
|
907
|
-
resolve(getNext(buffer));
|
|
908
|
-
} catch (err) {
|
|
909
|
-
reject(err);
|
|
910
|
-
}
|
|
911
|
-
return pushable2;
|
|
912
|
-
};
|
|
913
|
-
});
|
|
914
|
-
} finally {
|
|
915
|
-
if (buffer.isEmpty()) {
|
|
916
|
-
queueMicrotask(() => {
|
|
917
|
-
drain.resolve();
|
|
918
|
-
drain = pDefer();
|
|
919
|
-
});
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
};
|
|
923
|
-
const bufferNext = (next) => {
|
|
924
|
-
if (onNext != null) {
|
|
925
|
-
return onNext(next);
|
|
926
|
-
}
|
|
927
|
-
buffer.push(next);
|
|
928
|
-
return pushable2;
|
|
929
|
-
};
|
|
930
|
-
const bufferError = (err) => {
|
|
931
|
-
buffer = new FIFO();
|
|
932
|
-
if (onNext != null) {
|
|
933
|
-
return onNext({ error: err });
|
|
934
|
-
}
|
|
935
|
-
buffer.push({ error: err });
|
|
936
|
-
return pushable2;
|
|
937
|
-
};
|
|
938
|
-
const push = (value) => {
|
|
939
|
-
if (ended) {
|
|
940
|
-
return pushable2;
|
|
941
|
-
}
|
|
942
|
-
if (options?.objectMode !== true && value?.byteLength == null) {
|
|
943
|
-
throw new Error("objectMode was not true but tried to push non-Uint8Array value");
|
|
944
|
-
}
|
|
945
|
-
return bufferNext({ done: false, value });
|
|
946
|
-
};
|
|
947
|
-
const end = (err) => {
|
|
948
|
-
if (ended)
|
|
949
|
-
return pushable2;
|
|
950
|
-
ended = true;
|
|
951
|
-
return err != null ? bufferError(err) : bufferNext({ done: true });
|
|
952
|
-
};
|
|
953
|
-
const _return = () => {
|
|
954
|
-
buffer = new FIFO();
|
|
955
|
-
end();
|
|
956
|
-
return { done: true };
|
|
957
|
-
};
|
|
958
|
-
const _throw = (err) => {
|
|
959
|
-
end(err);
|
|
960
|
-
return { done: true };
|
|
961
|
-
};
|
|
962
|
-
pushable2 = {
|
|
963
|
-
[Symbol.asyncIterator]() {
|
|
964
|
-
return this;
|
|
965
|
-
},
|
|
966
|
-
next: waitNext,
|
|
967
|
-
return: _return,
|
|
968
|
-
throw: _throw,
|
|
969
|
-
push,
|
|
970
|
-
end,
|
|
971
|
-
get readableLength() {
|
|
972
|
-
return buffer.size;
|
|
973
|
-
},
|
|
974
|
-
onEmpty: async (options2) => {
|
|
975
|
-
const signal = options2?.signal;
|
|
976
|
-
signal?.throwIfAborted();
|
|
977
|
-
if (buffer.isEmpty()) {
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
|
-
let cancel;
|
|
981
|
-
let listener;
|
|
982
|
-
if (signal != null) {
|
|
983
|
-
cancel = new Promise((resolve, reject) => {
|
|
984
|
-
listener = () => {
|
|
985
|
-
reject(new AbortError());
|
|
986
|
-
};
|
|
987
|
-
signal.addEventListener("abort", listener);
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
try {
|
|
991
|
-
await Promise.race([
|
|
992
|
-
drain.promise,
|
|
993
|
-
cancel
|
|
994
|
-
]);
|
|
995
|
-
} finally {
|
|
996
|
-
if (listener != null && signal != null) {
|
|
997
|
-
signal?.removeEventListener("abort", listener);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
};
|
|
1002
|
-
if (onEnd == null) {
|
|
1003
|
-
return pushable2;
|
|
1004
|
-
}
|
|
1005
|
-
const _pushable2 = pushable2;
|
|
1006
|
-
pushable2 = {
|
|
1007
|
-
[Symbol.asyncIterator]() {
|
|
1008
|
-
return this;
|
|
1009
|
-
},
|
|
1010
|
-
next() {
|
|
1011
|
-
return _pushable2.next();
|
|
1012
|
-
},
|
|
1013
|
-
throw(err) {
|
|
1014
|
-
_pushable2.throw(err);
|
|
1015
|
-
if (onEnd != null) {
|
|
1016
|
-
onEnd(err);
|
|
1017
|
-
onEnd = void 0;
|
|
1018
|
-
}
|
|
1019
|
-
return { done: true };
|
|
1020
|
-
},
|
|
1021
|
-
return() {
|
|
1022
|
-
_pushable2.return();
|
|
1023
|
-
if (onEnd != null) {
|
|
1024
|
-
onEnd();
|
|
1025
|
-
onEnd = void 0;
|
|
1026
|
-
}
|
|
1027
|
-
return { done: true };
|
|
1028
|
-
},
|
|
1029
|
-
push,
|
|
1030
|
-
end(err) {
|
|
1031
|
-
_pushable2.end(err);
|
|
1032
|
-
if (onEnd != null) {
|
|
1033
|
-
onEnd(err);
|
|
1034
|
-
onEnd = void 0;
|
|
1035
|
-
}
|
|
1036
|
-
return pushable2;
|
|
1037
|
-
},
|
|
1038
|
-
get readableLength() {
|
|
1039
|
-
return _pushable2.readableLength;
|
|
1040
|
-
},
|
|
1041
|
-
onEmpty: (opts) => {
|
|
1042
|
-
return _pushable2.onEmpty(opts);
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
return pushable2;
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
// router/client.ts
|
|
1049
|
-
import { nanoid } from "nanoid";
|
|
1050
|
-
|
|
1051
|
-
// router/result.ts
|
|
1052
|
-
import {
|
|
1053
|
-
Type as Type3
|
|
1054
|
-
} from "@sinclair/typebox";
|
|
1055
|
-
var UNCAUGHT_ERROR = "UNCAUGHT_ERROR";
|
|
1056
|
-
var UNEXPECTED_DISCONNECT = "UNEXPECTED_DISCONNECT";
|
|
1057
|
-
var RiverUncaughtSchema = Type3.Object({
|
|
1058
|
-
code: Type3.Union([
|
|
1059
|
-
Type3.Literal(UNCAUGHT_ERROR),
|
|
1060
|
-
Type3.Literal(UNEXPECTED_DISCONNECT)
|
|
1061
|
-
]),
|
|
1062
|
-
message: Type3.String()
|
|
1063
|
-
});
|
|
1064
|
-
function Ok(payload) {
|
|
1065
|
-
return {
|
|
1066
|
-
ok: true,
|
|
1067
|
-
payload
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
|
-
function Err(error) {
|
|
1071
|
-
return {
|
|
1072
|
-
ok: false,
|
|
1073
|
-
payload: error
|
|
1074
|
-
};
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
// router/client.ts
|
|
1078
|
-
var noop = () => {
|
|
1079
|
-
};
|
|
1080
|
-
function _createRecursiveProxy(callback, path) {
|
|
1081
|
-
const proxy = new Proxy(noop, {
|
|
1082
|
-
// property access, recurse and add field to path
|
|
1083
|
-
get(_obj, key) {
|
|
1084
|
-
if (typeof key !== "string")
|
|
1085
|
-
return void 0;
|
|
1086
|
-
return _createRecursiveProxy(callback, [...path, key]);
|
|
1087
|
-
},
|
|
1088
|
-
// hit the end, let's invoke the handler
|
|
1089
|
-
apply(_target, _this, args) {
|
|
1090
|
-
return callback({
|
|
1091
|
-
path,
|
|
1092
|
-
args
|
|
1093
|
-
});
|
|
1094
|
-
}
|
|
1095
|
-
});
|
|
1096
|
-
return proxy;
|
|
1097
|
-
}
|
|
1098
|
-
var defaultClientOptions = {
|
|
1099
|
-
connectOnInvoke: true,
|
|
1100
|
-
eagerlyConnect: true
|
|
1101
|
-
};
|
|
1102
|
-
function createClient(transport, serverId, providedClientOptions = {}) {
|
|
1103
|
-
if (providedClientOptions.handshakeOptions) {
|
|
1104
|
-
transport.extendHandshake(providedClientOptions.handshakeOptions);
|
|
1105
|
-
}
|
|
1106
|
-
const options = { ...defaultClientOptions, ...providedClientOptions };
|
|
1107
|
-
if (options.eagerlyConnect) {
|
|
1108
|
-
void transport.connect(serverId);
|
|
1109
|
-
}
|
|
1110
|
-
return _createRecursiveProxy(async (opts) => {
|
|
1111
|
-
const [serviceName, procName, procType] = [...opts.path];
|
|
1112
|
-
if (!(serviceName && procName && procType)) {
|
|
1113
|
-
throw new Error(
|
|
1114
|
-
"invalid river call, ensure the service and procedure you are calling exists"
|
|
1115
|
-
);
|
|
1116
|
-
}
|
|
1117
|
-
const [input] = opts.args;
|
|
1118
|
-
if (options.connectOnInvoke && !transport.connections.has(serverId)) {
|
|
1119
|
-
void transport.connect(serverId);
|
|
1120
|
-
}
|
|
1121
|
-
if (procType === "rpc") {
|
|
1122
|
-
return handleRpc(transport, serverId, input, serviceName, procName);
|
|
1123
|
-
} else if (procType === "stream") {
|
|
1124
|
-
return handleStream(transport, serverId, input, serviceName, procName);
|
|
1125
|
-
} else if (procType === "subscribe") {
|
|
1126
|
-
return handleSubscribe(transport, serverId, input, serviceName, procName);
|
|
1127
|
-
} else if (procType === "upload") {
|
|
1128
|
-
return handleUpload(transport, serverId, input, serviceName, procName);
|
|
1129
|
-
} else {
|
|
1130
|
-
throw new Error(`invalid river call, unknown procedure type ${procType}`);
|
|
1131
|
-
}
|
|
1132
|
-
}, []);
|
|
1133
|
-
}
|
|
1134
|
-
function createSessionDisconnectHandler(from, cb) {
|
|
1135
|
-
return (evt) => {
|
|
1136
|
-
if (evt.status === "disconnect" && evt.session.to === from) {
|
|
1137
|
-
cb();
|
|
1138
|
-
}
|
|
1139
|
-
};
|
|
1140
|
-
}
|
|
1141
|
-
function handleRpc(transport, serverId, input, serviceName, procedureName) {
|
|
1142
|
-
const streamId = nanoid();
|
|
1143
|
-
const { span, ctx } = createProcTelemetryInfo(
|
|
1144
|
-
transport,
|
|
1145
|
-
"rpc",
|
|
1146
|
-
serviceName,
|
|
1147
|
-
procedureName,
|
|
1148
|
-
streamId
|
|
1149
|
-
);
|
|
1150
|
-
transport.send(serverId, {
|
|
1151
|
-
streamId,
|
|
1152
|
-
serviceName,
|
|
1153
|
-
procedureName,
|
|
1154
|
-
payload: input,
|
|
1155
|
-
tracing: getPropagationContext(ctx),
|
|
1156
|
-
controlFlags: 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */
|
|
1157
|
-
});
|
|
1158
|
-
const responsePromise = new Promise((resolve) => {
|
|
1159
|
-
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
1160
|
-
cleanup();
|
|
1161
|
-
resolve(
|
|
1162
|
-
Err({
|
|
1163
|
-
code: UNEXPECTED_DISCONNECT,
|
|
1164
|
-
message: `${serverId} unexpectedly disconnected`
|
|
1165
|
-
})
|
|
1166
|
-
);
|
|
1167
|
-
});
|
|
1168
|
-
function cleanup() {
|
|
1169
|
-
transport.removeEventListener("message", onMessage);
|
|
1170
|
-
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
1171
|
-
span.end();
|
|
1172
|
-
}
|
|
1173
|
-
function onMessage(msg) {
|
|
1174
|
-
if (msg.streamId !== streamId)
|
|
1175
|
-
return;
|
|
1176
|
-
if (msg.to !== transport.clientId)
|
|
1177
|
-
return;
|
|
1178
|
-
cleanup();
|
|
1179
|
-
resolve(msg.payload);
|
|
1180
|
-
}
|
|
1181
|
-
transport.addEventListener("message", onMessage);
|
|
1182
|
-
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
1183
|
-
});
|
|
1184
|
-
return responsePromise;
|
|
1185
|
-
}
|
|
1186
|
-
function handleStream(transport, serverId, init, serviceName, procedureName) {
|
|
1187
|
-
const streamId = nanoid();
|
|
1188
|
-
const { span, ctx } = createProcTelemetryInfo(
|
|
1189
|
-
transport,
|
|
1190
|
-
"stream",
|
|
1191
|
-
serviceName,
|
|
1192
|
-
procedureName,
|
|
1193
|
-
streamId
|
|
1194
|
-
);
|
|
1195
|
-
const inputStream = pushable({ objectMode: true });
|
|
1196
|
-
const outputStream = pushable({ objectMode: true });
|
|
1197
|
-
let firstMessage = true;
|
|
1198
|
-
let healthyClose = true;
|
|
1199
|
-
if (init) {
|
|
1200
|
-
transport.send(serverId, {
|
|
1201
|
-
streamId,
|
|
1202
|
-
serviceName,
|
|
1203
|
-
procedureName,
|
|
1204
|
-
payload: init,
|
|
1205
|
-
tracing: getPropagationContext(ctx),
|
|
1206
|
-
controlFlags: 2 /* StreamOpenBit */
|
|
1207
|
-
});
|
|
1208
|
-
firstMessage = false;
|
|
1209
|
-
}
|
|
1210
|
-
const pipeInputToTransport = async () => {
|
|
1211
|
-
for await (const rawIn of inputStream) {
|
|
1212
|
-
const m = {
|
|
1213
|
-
streamId,
|
|
1214
|
-
payload: rawIn,
|
|
1215
|
-
controlFlags: 0
|
|
1216
|
-
};
|
|
1217
|
-
if (firstMessage) {
|
|
1218
|
-
m.serviceName = serviceName;
|
|
1219
|
-
m.procedureName = procedureName;
|
|
1220
|
-
m.tracing = getPropagationContext(ctx);
|
|
1221
|
-
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
1222
|
-
firstMessage = false;
|
|
1223
|
-
}
|
|
1224
|
-
transport.send(serverId, m);
|
|
1225
|
-
}
|
|
1226
|
-
if (!healthyClose)
|
|
1227
|
-
return;
|
|
1228
|
-
transport.sendCloseStream(serverId, streamId);
|
|
1229
|
-
};
|
|
1230
|
-
void pipeInputToTransport();
|
|
1231
|
-
function onMessage(msg) {
|
|
1232
|
-
if (msg.streamId !== streamId)
|
|
1233
|
-
return;
|
|
1234
|
-
if (msg.to !== transport.clientId)
|
|
1235
|
-
return;
|
|
1236
|
-
if (isStreamClose(msg.controlFlags)) {
|
|
1237
|
-
cleanup();
|
|
1238
|
-
} else {
|
|
1239
|
-
outputStream.push(msg.payload);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
function cleanup() {
|
|
1243
|
-
inputStream.end();
|
|
1244
|
-
outputStream.end();
|
|
1245
|
-
transport.removeEventListener("message", onMessage);
|
|
1246
|
-
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
1247
|
-
span.end();
|
|
1248
|
-
}
|
|
1249
|
-
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
1250
|
-
outputStream.push(
|
|
1251
|
-
Err({
|
|
1252
|
-
code: UNEXPECTED_DISCONNECT,
|
|
1253
|
-
message: `${serverId} unexpectedly disconnected`
|
|
1254
|
-
})
|
|
1255
|
-
);
|
|
1256
|
-
healthyClose = false;
|
|
1257
|
-
cleanup();
|
|
1258
|
-
});
|
|
1259
|
-
transport.addEventListener("message", onMessage);
|
|
1260
|
-
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
1261
|
-
return [inputStream, outputStream, cleanup];
|
|
1262
|
-
}
|
|
1263
|
-
function handleSubscribe(transport, serverId, input, serviceName, procedureName) {
|
|
1264
|
-
const streamId = nanoid();
|
|
1265
|
-
const { span, ctx } = createProcTelemetryInfo(
|
|
1266
|
-
transport,
|
|
1267
|
-
"subscription",
|
|
1268
|
-
serviceName,
|
|
1269
|
-
procedureName,
|
|
1270
|
-
streamId
|
|
1271
|
-
);
|
|
1272
|
-
transport.send(serverId, {
|
|
1273
|
-
streamId,
|
|
1274
|
-
serviceName,
|
|
1275
|
-
procedureName,
|
|
1276
|
-
payload: input,
|
|
1277
|
-
tracing: getPropagationContext(ctx),
|
|
1278
|
-
controlFlags: 2 /* StreamOpenBit */
|
|
1279
|
-
});
|
|
1280
|
-
let healthyClose = true;
|
|
1281
|
-
const outputStream = pushable({ objectMode: true });
|
|
1282
|
-
function onMessage(msg) {
|
|
1283
|
-
if (msg.streamId !== streamId)
|
|
1284
|
-
return;
|
|
1285
|
-
if (msg.to !== transport.clientId)
|
|
1286
|
-
return;
|
|
1287
|
-
if (isStreamClose(msg.controlFlags)) {
|
|
1288
|
-
cleanup();
|
|
1289
|
-
} else {
|
|
1290
|
-
outputStream.push(msg.payload);
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
function cleanup() {
|
|
1294
|
-
outputStream.end();
|
|
1295
|
-
transport.removeEventListener("message", onMessage);
|
|
1296
|
-
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
1297
|
-
span.end();
|
|
1298
|
-
}
|
|
1299
|
-
const closeHandler = () => {
|
|
1300
|
-
cleanup();
|
|
1301
|
-
if (!healthyClose)
|
|
1302
|
-
return;
|
|
1303
|
-
transport.sendCloseStream(serverId, streamId);
|
|
1304
|
-
};
|
|
1305
|
-
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
1306
|
-
outputStream.push(
|
|
1307
|
-
Err({
|
|
1308
|
-
code: UNEXPECTED_DISCONNECT,
|
|
1309
|
-
message: `${serverId} unexpectedly disconnected`
|
|
1310
|
-
})
|
|
1311
|
-
);
|
|
1312
|
-
healthyClose = false;
|
|
1313
|
-
cleanup();
|
|
1314
|
-
});
|
|
1315
|
-
transport.addEventListener("message", onMessage);
|
|
1316
|
-
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
1317
|
-
return [outputStream, closeHandler];
|
|
1318
|
-
}
|
|
1319
|
-
function handleUpload(transport, serverId, init, serviceName, procedureName) {
|
|
1320
|
-
const streamId = nanoid();
|
|
1321
|
-
const { span, ctx } = createProcTelemetryInfo(
|
|
1322
|
-
transport,
|
|
1323
|
-
"upload",
|
|
1324
|
-
serviceName,
|
|
1325
|
-
procedureName,
|
|
1326
|
-
streamId
|
|
1327
|
-
);
|
|
1328
|
-
const inputStream = pushable({ objectMode: true });
|
|
1329
|
-
let firstMessage = true;
|
|
1330
|
-
let healthyClose = true;
|
|
1331
|
-
if (init) {
|
|
1332
|
-
transport.send(serverId, {
|
|
1333
|
-
streamId,
|
|
1334
|
-
serviceName,
|
|
1335
|
-
procedureName,
|
|
1336
|
-
payload: init,
|
|
1337
|
-
tracing: getPropagationContext(ctx),
|
|
1338
|
-
controlFlags: 2 /* StreamOpenBit */
|
|
1339
|
-
});
|
|
1340
|
-
firstMessage = false;
|
|
1341
|
-
}
|
|
1342
|
-
const pipeInputToTransport = async () => {
|
|
1343
|
-
for await (const rawIn of inputStream) {
|
|
1344
|
-
const m = {
|
|
1345
|
-
streamId,
|
|
1346
|
-
payload: rawIn,
|
|
1347
|
-
controlFlags: 0
|
|
1348
|
-
};
|
|
1349
|
-
if (firstMessage) {
|
|
1350
|
-
m.serviceName = serviceName;
|
|
1351
|
-
m.procedureName = procedureName;
|
|
1352
|
-
m.tracing = getPropagationContext(ctx);
|
|
1353
|
-
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
1354
|
-
firstMessage = false;
|
|
1355
|
-
}
|
|
1356
|
-
transport.send(serverId, m);
|
|
1357
|
-
}
|
|
1358
|
-
if (!healthyClose)
|
|
1359
|
-
return;
|
|
1360
|
-
transport.sendCloseStream(serverId, streamId);
|
|
1361
|
-
};
|
|
1362
|
-
void pipeInputToTransport();
|
|
1363
|
-
const responsePromise = new Promise((resolve) => {
|
|
1364
|
-
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
1365
|
-
healthyClose = false;
|
|
1366
|
-
cleanup();
|
|
1367
|
-
resolve(
|
|
1368
|
-
Err({
|
|
1369
|
-
code: UNEXPECTED_DISCONNECT,
|
|
1370
|
-
message: `${serverId} unexpectedly disconnected`
|
|
1371
|
-
})
|
|
1372
|
-
);
|
|
1373
|
-
});
|
|
1374
|
-
function cleanup() {
|
|
1375
|
-
inputStream.end();
|
|
1376
|
-
transport.removeEventListener("message", onMessage);
|
|
1377
|
-
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
1378
|
-
span.end();
|
|
1379
|
-
}
|
|
1380
|
-
function onMessage(msg) {
|
|
1381
|
-
if (msg.streamId !== streamId)
|
|
1382
|
-
return;
|
|
1383
|
-
if (msg.to !== transport.clientId)
|
|
1384
|
-
return;
|
|
1385
|
-
cleanup();
|
|
1386
|
-
resolve(msg.payload);
|
|
1387
|
-
}
|
|
1388
|
-
transport.addEventListener("message", onMessage);
|
|
1389
|
-
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
1390
|
-
});
|
|
1391
|
-
return [inputStream, responsePromise];
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
// router/server.ts
|
|
1395
|
-
import { Value } from "@sinclair/typebox/value";
|
|
1396
|
-
import { SpanStatusCode } from "@opentelemetry/api";
|
|
1397
|
-
var RiverServer = class {
|
|
1398
|
-
transport;
|
|
1399
|
-
services;
|
|
1400
|
-
contextMap;
|
|
1401
|
-
// map of streamId to ProcStream
|
|
1402
|
-
streamMap;
|
|
1403
|
-
// map of client to their open streams by streamId
|
|
1404
|
-
clientStreams;
|
|
1405
|
-
disconnectedSessions;
|
|
1406
|
-
log;
|
|
1407
|
-
constructor(transport, services, handshakeOptions, extendedContext) {
|
|
1408
|
-
const instances = {};
|
|
1409
|
-
this.services = instances;
|
|
1410
|
-
this.contextMap = /* @__PURE__ */ new Map();
|
|
1411
|
-
for (const [name, service] of Object.entries(services)) {
|
|
1412
|
-
const instance = service.instantiate();
|
|
1413
|
-
instances[name] = instance;
|
|
1414
|
-
this.contextMap.set(instance, {
|
|
1415
|
-
...extendedContext,
|
|
1416
|
-
state: instance.state
|
|
1417
|
-
});
|
|
1418
|
-
}
|
|
1419
|
-
if (handshakeOptions) {
|
|
1420
|
-
transport.extendHandshake(handshakeOptions);
|
|
1421
|
-
}
|
|
1422
|
-
this.transport = transport;
|
|
1423
|
-
this.disconnectedSessions = /* @__PURE__ */ new Set();
|
|
1424
|
-
this.streamMap = /* @__PURE__ */ new Map();
|
|
1425
|
-
this.clientStreams = /* @__PURE__ */ new Map();
|
|
1426
|
-
this.transport.addEventListener("message", this.onMessage);
|
|
1427
|
-
this.transport.addEventListener("sessionStatus", this.onSessionStatus);
|
|
1428
|
-
this.log = transport.log;
|
|
1429
|
-
this.transport.addEventListener("transportStatus", async ({ status }) => {
|
|
1430
|
-
if (status !== "closed") {
|
|
1431
|
-
return;
|
|
1432
|
-
}
|
|
1433
|
-
this.transport.removeEventListener("message", this.onMessage);
|
|
1434
|
-
this.transport.removeEventListener("sessionStatus", this.onSessionStatus);
|
|
1435
|
-
await Promise.all([...this.streamMap.keys()].map(this.cleanupStream));
|
|
1436
|
-
});
|
|
1437
|
-
}
|
|
1438
|
-
get streams() {
|
|
1439
|
-
return this.streamMap;
|
|
1440
|
-
}
|
|
1441
|
-
onMessage = async (message) => {
|
|
1442
|
-
if (message.to !== this.transport.clientId) {
|
|
1443
|
-
this.log?.info(
|
|
1444
|
-
`got msg with destination that isn't this server, ignoring`,
|
|
1445
|
-
{
|
|
1446
|
-
clientId: this.transport.clientId,
|
|
1447
|
-
transportMessage: message
|
|
1448
|
-
}
|
|
1449
|
-
);
|
|
1450
|
-
return;
|
|
1451
|
-
}
|
|
1452
|
-
let procStream = this.streamMap.get(message.streamId);
|
|
1453
|
-
const isInitMessage = !procStream;
|
|
1454
|
-
procStream ||= this.createNewProcStream(message);
|
|
1455
|
-
if (!procStream) {
|
|
1456
|
-
return;
|
|
1457
|
-
}
|
|
1458
|
-
await this.pushToStream(procStream, message, isInitMessage);
|
|
1459
|
-
};
|
|
1460
|
-
// cleanup streams on session close
|
|
1461
|
-
onSessionStatus = async (evt) => {
|
|
1462
|
-
if (evt.status !== "disconnect")
|
|
1463
|
-
return;
|
|
1464
|
-
const disconnectedClientId = evt.session.to;
|
|
1465
|
-
this.log?.info(
|
|
1466
|
-
`got session disconnect from ${disconnectedClientId}, cleaning up streams`,
|
|
1467
|
-
evt.session.loggingMetadata
|
|
1468
|
-
);
|
|
1469
|
-
const streamsFromThisClient = this.clientStreams.get(disconnectedClientId);
|
|
1470
|
-
if (!streamsFromThisClient)
|
|
1471
|
-
return;
|
|
1472
|
-
this.disconnectedSessions.add(disconnectedClientId);
|
|
1473
|
-
await Promise.all(
|
|
1474
|
-
Array.from(streamsFromThisClient).map(this.cleanupStream)
|
|
1475
|
-
);
|
|
1476
|
-
this.disconnectedSessions.delete(disconnectedClientId);
|
|
1477
|
-
this.clientStreams.delete(disconnectedClientId);
|
|
1478
|
-
};
|
|
1479
|
-
createNewProcStream(message) {
|
|
1480
|
-
if (!isStreamOpen(message.controlFlags)) {
|
|
1481
|
-
this.log?.error(
|
|
1482
|
-
`can't create a new procedure stream from a message that doesn't have the stream open bit set`,
|
|
1483
|
-
{
|
|
1484
|
-
clientId: this.transport.clientId,
|
|
1485
|
-
transportMessage: message,
|
|
1486
|
-
tags: ["invariant-violation"]
|
|
1487
|
-
}
|
|
1488
|
-
);
|
|
1489
|
-
return;
|
|
1490
|
-
}
|
|
1491
|
-
if (!message.procedureName || !message.serviceName) {
|
|
1492
|
-
this.log?.warn(
|
|
1493
|
-
`missing procedure or service name in stream open message`,
|
|
1494
|
-
{
|
|
1495
|
-
clientId: this.transport.clientId,
|
|
1496
|
-
transportMessage: message
|
|
1497
|
-
}
|
|
1498
|
-
);
|
|
1499
|
-
return;
|
|
1500
|
-
}
|
|
1501
|
-
if (!(message.serviceName in this.services)) {
|
|
1502
|
-
this.log?.warn(`couldn't find service ${message.serviceName}`, {
|
|
1503
|
-
clientId: this.transport.clientId,
|
|
1504
|
-
transportMessage: message
|
|
1505
|
-
});
|
|
1506
|
-
return;
|
|
1507
|
-
}
|
|
1508
|
-
const service = this.services[message.serviceName];
|
|
1509
|
-
const serviceContext = this.getContext(service, message.serviceName);
|
|
1510
|
-
if (!(message.procedureName in service.procedures)) {
|
|
1511
|
-
this.log?.warn(
|
|
1512
|
-
`couldn't find a matching procedure for ${message.serviceName}.${message.procedureName}`,
|
|
1513
|
-
{
|
|
1514
|
-
clientId: this.transport.clientId,
|
|
1515
|
-
transportMessage: message
|
|
1516
|
-
}
|
|
1517
|
-
);
|
|
1518
|
-
return;
|
|
1519
|
-
}
|
|
1520
|
-
const session = this.transport.sessions.get(message.from);
|
|
1521
|
-
if (!session) {
|
|
1522
|
-
this.log?.warn(`couldn't find session for ${message.from}`, {
|
|
1523
|
-
clientId: this.transport.clientId,
|
|
1524
|
-
transportMessage: message
|
|
1525
|
-
});
|
|
1526
|
-
return;
|
|
1527
|
-
}
|
|
1528
|
-
const procedure = service.procedures[message.procedureName];
|
|
1529
|
-
const incoming = pushable({ objectMode: true });
|
|
1530
|
-
const outgoing = pushable({ objectMode: true });
|
|
1531
|
-
const needsClose = procedure.type === "subscription" || procedure.type === "stream";
|
|
1532
|
-
const disposables = [];
|
|
1533
|
-
const outputHandler = (
|
|
1534
|
-
// sending outgoing messages back to client
|
|
1535
|
-
needsClose ? (
|
|
1536
|
-
// subscription and stream case, we need to send a close bit after the response stream
|
|
1537
|
-
(async () => {
|
|
1538
|
-
for await (const response of outgoing) {
|
|
1539
|
-
this.transport.send(session.to, {
|
|
1540
|
-
streamId: message.streamId,
|
|
1541
|
-
controlFlags: 0,
|
|
1542
|
-
payload: response
|
|
1543
|
-
});
|
|
1544
|
-
}
|
|
1545
|
-
if (!this.disconnectedSessions.has(message.from)) {
|
|
1546
|
-
this.transport.sendCloseStream(session.to, message.streamId);
|
|
1547
|
-
}
|
|
1548
|
-
disposables.forEach((d) => d());
|
|
1549
|
-
})()
|
|
1550
|
-
) : (
|
|
1551
|
-
// rpc and upload case, we just send the response back with close bit
|
|
1552
|
-
(async () => {
|
|
1553
|
-
const response = await outgoing.next().then((res) => res.value);
|
|
1554
|
-
if (response) {
|
|
1555
|
-
this.transport.send(session.to, {
|
|
1556
|
-
streamId: message.streamId,
|
|
1557
|
-
controlFlags: 4 /* StreamClosedBit */,
|
|
1558
|
-
payload: response
|
|
1559
|
-
});
|
|
1560
|
-
disposables.forEach((d) => d());
|
|
1561
|
-
}
|
|
1562
|
-
})()
|
|
1563
|
-
)
|
|
1564
|
-
);
|
|
1565
|
-
const errorHandler = (err, span) => {
|
|
1566
|
-
const errorMsg = coerceErrorString(err);
|
|
1567
|
-
this.log?.error(
|
|
1568
|
-
`procedure ${message.serviceName}.${message.procedureName} threw an uncaught error: ${errorMsg}`,
|
|
1569
|
-
session.loggingMetadata
|
|
1570
|
-
);
|
|
1571
|
-
span.recordException(err instanceof Error ? err : new Error(errorMsg));
|
|
1572
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1573
|
-
outgoing.push(
|
|
1574
|
-
Err({
|
|
1575
|
-
code: UNCAUGHT_ERROR,
|
|
1576
|
-
message: errorMsg
|
|
1577
|
-
})
|
|
1578
|
-
);
|
|
1579
|
-
};
|
|
1580
|
-
const sessionMeta = this.transport.sessionHandshakeMetadata.get(session);
|
|
1581
|
-
if (!sessionMeta) {
|
|
1582
|
-
this.log?.error(`session doesn't have handshake metadata`, {
|
|
1583
|
-
...session.loggingMetadata,
|
|
1584
|
-
tags: ["invariant-violation"]
|
|
1585
|
-
});
|
|
1586
|
-
return;
|
|
1587
|
-
}
|
|
1588
|
-
let inputHandler;
|
|
1589
|
-
const procHasInitMessage = "init" in procedure;
|
|
1590
|
-
const serviceContextWithTransportInfo = {
|
|
1591
|
-
...serviceContext,
|
|
1592
|
-
to: message.to,
|
|
1593
|
-
from: message.from,
|
|
1594
|
-
streamId: message.streamId,
|
|
1595
|
-
session,
|
|
1596
|
-
metadata: sessionMeta
|
|
1597
|
-
};
|
|
1598
|
-
switch (procedure.type) {
|
|
1599
|
-
case "rpc":
|
|
1600
|
-
inputHandler = createHandlerSpan(
|
|
1601
|
-
procedure.type,
|
|
1602
|
-
message,
|
|
1603
|
-
async (span) => {
|
|
1604
|
-
const inputMessage = await incoming.next();
|
|
1605
|
-
if (inputMessage.done) {
|
|
1606
|
-
return;
|
|
1607
|
-
}
|
|
1608
|
-
try {
|
|
1609
|
-
const outputMessage = await procedure.handler(
|
|
1610
|
-
serviceContextWithTransportInfo,
|
|
1611
|
-
inputMessage.value
|
|
1612
|
-
);
|
|
1613
|
-
outgoing.push(outputMessage);
|
|
1614
|
-
} catch (err) {
|
|
1615
|
-
errorHandler(err, span);
|
|
1616
|
-
} finally {
|
|
1617
|
-
span.end();
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
);
|
|
1621
|
-
break;
|
|
1622
|
-
case "stream":
|
|
1623
|
-
if (procHasInitMessage) {
|
|
1624
|
-
inputHandler = createHandlerSpan(
|
|
1625
|
-
procedure.type,
|
|
1626
|
-
message,
|
|
1627
|
-
async (span) => {
|
|
1628
|
-
const initMessage = await incoming.next();
|
|
1629
|
-
if (initMessage.done) {
|
|
1630
|
-
return;
|
|
1631
|
-
}
|
|
1632
|
-
try {
|
|
1633
|
-
const dispose = await procedure.handler(
|
|
1634
|
-
serviceContextWithTransportInfo,
|
|
1635
|
-
initMessage.value,
|
|
1636
|
-
incoming,
|
|
1637
|
-
outgoing
|
|
1638
|
-
);
|
|
1639
|
-
if (dispose) {
|
|
1640
|
-
disposables.push(dispose);
|
|
1641
|
-
}
|
|
1642
|
-
} catch (err) {
|
|
1643
|
-
errorHandler(err, span);
|
|
1644
|
-
} finally {
|
|
1645
|
-
span.end();
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
);
|
|
1649
|
-
} else {
|
|
1650
|
-
inputHandler = createHandlerSpan(
|
|
1651
|
-
procedure.type,
|
|
1652
|
-
message,
|
|
1653
|
-
async (span) => {
|
|
1654
|
-
try {
|
|
1655
|
-
const dispose = await procedure.handler(
|
|
1656
|
-
serviceContextWithTransportInfo,
|
|
1657
|
-
incoming,
|
|
1658
|
-
outgoing
|
|
1659
|
-
);
|
|
1660
|
-
if (dispose) {
|
|
1661
|
-
disposables.push(dispose);
|
|
1662
|
-
}
|
|
1663
|
-
} catch (err) {
|
|
1664
|
-
errorHandler(err, span);
|
|
1665
|
-
} finally {
|
|
1666
|
-
span.end();
|
|
1667
|
-
}
|
|
1668
|
-
}
|
|
1669
|
-
);
|
|
1670
|
-
}
|
|
1671
|
-
break;
|
|
1672
|
-
case "subscription":
|
|
1673
|
-
inputHandler = createHandlerSpan(
|
|
1674
|
-
procedure.type,
|
|
1675
|
-
message,
|
|
1676
|
-
async (span) => {
|
|
1677
|
-
const inputMessage = await incoming.next();
|
|
1678
|
-
if (inputMessage.done) {
|
|
1679
|
-
return;
|
|
1680
|
-
}
|
|
1681
|
-
try {
|
|
1682
|
-
const dispose = await procedure.handler(
|
|
1683
|
-
serviceContextWithTransportInfo,
|
|
1684
|
-
inputMessage.value,
|
|
1685
|
-
outgoing
|
|
1686
|
-
);
|
|
1687
|
-
if (dispose) {
|
|
1688
|
-
disposables.push(dispose);
|
|
1689
|
-
}
|
|
1690
|
-
} catch (err) {
|
|
1691
|
-
errorHandler(err, span);
|
|
1692
|
-
} finally {
|
|
1693
|
-
span.end();
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
);
|
|
1697
|
-
break;
|
|
1698
|
-
case "upload":
|
|
1699
|
-
if (procHasInitMessage) {
|
|
1700
|
-
inputHandler = createHandlerSpan(
|
|
1701
|
-
procedure.type,
|
|
1702
|
-
message,
|
|
1703
|
-
async (span) => {
|
|
1704
|
-
const initMessage = await incoming.next();
|
|
1705
|
-
if (initMessage.done) {
|
|
1706
|
-
return;
|
|
1707
|
-
}
|
|
1708
|
-
try {
|
|
1709
|
-
const outputMessage = await procedure.handler(
|
|
1710
|
-
serviceContextWithTransportInfo,
|
|
1711
|
-
initMessage.value,
|
|
1712
|
-
incoming
|
|
1713
|
-
);
|
|
1714
|
-
if (!this.disconnectedSessions.has(message.from)) {
|
|
1715
|
-
outgoing.push(outputMessage);
|
|
1716
|
-
}
|
|
1717
|
-
} catch (err) {
|
|
1718
|
-
errorHandler(err, span);
|
|
1719
|
-
} finally {
|
|
1720
|
-
span.end();
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
);
|
|
1724
|
-
} else {
|
|
1725
|
-
inputHandler = createHandlerSpan(
|
|
1726
|
-
procedure.type,
|
|
1727
|
-
message,
|
|
1728
|
-
async (span) => {
|
|
1729
|
-
try {
|
|
1730
|
-
const outputMessage = await procedure.handler(
|
|
1731
|
-
serviceContextWithTransportInfo,
|
|
1732
|
-
incoming
|
|
1733
|
-
);
|
|
1734
|
-
if (!this.disconnectedSessions.has(message.from)) {
|
|
1735
|
-
outgoing.push(outputMessage);
|
|
1736
|
-
}
|
|
1737
|
-
} catch (err) {
|
|
1738
|
-
errorHandler(err, span);
|
|
1739
|
-
} finally {
|
|
1740
|
-
span.end();
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
);
|
|
1744
|
-
}
|
|
1745
|
-
break;
|
|
1746
|
-
default:
|
|
1747
|
-
this.log?.warn(
|
|
1748
|
-
`got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`,
|
|
1749
|
-
{ ...session.loggingMetadata, transportMessage: message }
|
|
1750
|
-
);
|
|
1751
|
-
return;
|
|
1752
|
-
}
|
|
1753
|
-
const procStream = {
|
|
1754
|
-
id: message.streamId,
|
|
1755
|
-
incoming,
|
|
1756
|
-
outgoing,
|
|
1757
|
-
serviceName: message.serviceName,
|
|
1758
|
-
procedureName: message.procedureName,
|
|
1759
|
-
promises: { inputHandler, outputHandler }
|
|
1760
|
-
};
|
|
1761
|
-
this.streamMap.set(message.streamId, procStream);
|
|
1762
|
-
const streamsFromThisClient = this.clientStreams.get(message.from) ?? /* @__PURE__ */ new Set();
|
|
1763
|
-
streamsFromThisClient.add(message.streamId);
|
|
1764
|
-
this.clientStreams.set(message.from, streamsFromThisClient);
|
|
1765
|
-
return procStream;
|
|
1766
|
-
}
|
|
1767
|
-
async pushToStream(procStream, message, isInit) {
|
|
1768
|
-
const { serviceName, procedureName } = procStream;
|
|
1769
|
-
const procedure = this.services[serviceName].procedures[procedureName];
|
|
1770
|
-
const procHasInitMessage = "init" in procedure;
|
|
1771
|
-
if (isInit && procHasInitMessage) {
|
|
1772
|
-
if (Value.Check(procedure.init, message.payload)) {
|
|
1773
|
-
procStream.incoming.push(message.payload);
|
|
1774
|
-
} else {
|
|
1775
|
-
this.log?.error(
|
|
1776
|
-
`procedure ${serviceName}.${procedureName} received invalid init payload`,
|
|
1777
|
-
{
|
|
1778
|
-
clientId: this.transport.clientId,
|
|
1779
|
-
transportMessage: message,
|
|
1780
|
-
validationErrors: [
|
|
1781
|
-
...Value.Errors(procedure.init, message.payload)
|
|
1782
|
-
]
|
|
1783
|
-
}
|
|
1784
|
-
);
|
|
1785
|
-
}
|
|
1786
|
-
} else if (Value.Check(procedure.input, message.payload)) {
|
|
1787
|
-
procStream.incoming.push(message.payload);
|
|
1788
|
-
} else if (!Value.Check(ControlMessagePayloadSchema, message.payload)) {
|
|
1789
|
-
this.log?.error(
|
|
1790
|
-
`procedure ${serviceName}.${procedureName} received invalid payload`,
|
|
1791
|
-
{
|
|
1792
|
-
clientId: this.transport.clientId,
|
|
1793
|
-
transportMessage: message,
|
|
1794
|
-
validationErrors: [...Value.Errors(procedure.input, message.payload)]
|
|
1795
|
-
}
|
|
1796
|
-
);
|
|
1797
|
-
}
|
|
1798
|
-
if (isStreamClose(message.controlFlags)) {
|
|
1799
|
-
await this.cleanupStream(message.streamId);
|
|
1800
|
-
const streamsFromThisClient = this.clientStreams.get(message.from);
|
|
1801
|
-
if (streamsFromThisClient) {
|
|
1802
|
-
streamsFromThisClient.delete(message.streamId);
|
|
1803
|
-
if (streamsFromThisClient.size === 0) {
|
|
1804
|
-
this.clientStreams.delete(message.from);
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
getContext(service, serviceName) {
|
|
1810
|
-
const context = this.contextMap.get(service);
|
|
1811
|
-
if (!context) {
|
|
1812
|
-
const err = `no context found for ${serviceName}`;
|
|
1813
|
-
this.log?.error(err, {
|
|
1814
|
-
clientId: this.transport.clientId,
|
|
1815
|
-
tags: ["invariant-violation"]
|
|
1816
|
-
});
|
|
1817
|
-
throw new Error(err);
|
|
1818
|
-
}
|
|
1819
|
-
return context;
|
|
1820
|
-
}
|
|
1821
|
-
cleanupStream = async (id) => {
|
|
1822
|
-
const stream2 = this.streamMap.get(id);
|
|
1823
|
-
if (!stream2) {
|
|
1824
|
-
return;
|
|
1825
|
-
}
|
|
1826
|
-
stream2.incoming.end();
|
|
1827
|
-
await stream2.promises.inputHandler;
|
|
1828
|
-
stream2.outgoing.end();
|
|
1829
|
-
await stream2.promises.outputHandler;
|
|
1830
|
-
this.streamMap.delete(id);
|
|
1831
|
-
};
|
|
1832
|
-
};
|
|
1833
|
-
function createServer(transport, services, providedServerOptions) {
|
|
1834
|
-
return new RiverServer(
|
|
1835
|
-
transport,
|
|
1836
|
-
services,
|
|
1837
|
-
providedServerOptions?.handshakeOptions,
|
|
1838
|
-
providedServerOptions?.extendedContext
|
|
1839
|
-
);
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1842
|
-
// router/handshake.ts
|
|
1843
|
-
function createClientHandshakeOptions(schema, construct) {
|
|
1844
|
-
return { schema, construct };
|
|
1845
|
-
}
|
|
1846
|
-
function createServerHandshakeOptions(schema, validate) {
|
|
1847
|
-
return { schema, validate };
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
export {
|
|
1851
|
-
serializeSchema,
|
|
1852
|
-
ServiceSchema,
|
|
1853
|
-
diffServerSchema,
|
|
1854
|
-
Procedure,
|
|
1855
|
-
pushable,
|
|
1856
|
-
UNCAUGHT_ERROR,
|
|
1857
|
-
RiverUncaughtSchema,
|
|
1858
|
-
Ok,
|
|
1859
|
-
Err,
|
|
1860
|
-
createClient,
|
|
1861
|
-
createServer,
|
|
1862
|
-
createClientHandshakeOptions,
|
|
1863
|
-
createServerHandshakeOptions
|
|
1864
|
-
};
|
|
1865
|
-
//# sourceMappingURL=chunk-LTSLICON.js.map
|