@orpc/standard-server-peer 0.0.0-next.324fc97 → 0.0.0-next.325aa5d

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/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
- import { isAsyncIteratorObject, stringifyJSON, readAsBuffer, AsyncIteratorClass, isTypescriptObject, SequentialIdGenerator, AsyncIdQueue } from '@orpc/shared';
2
- import { generateContentDisposition, flattenHeader, getFilenameFromContentDisposition, withEventMeta, ErrorEvent, getEventMeta, isEventIteratorHeaders, experimental_HibernationEventIterator } from '@orpc/standard-server';
1
+ import { isAsyncIteratorObject, stringifyJSON, readAsBuffer, AsyncIteratorClass, startSpan, runInSpanContext, isTypescriptObject, setSpanError, runWithSpan, SequentialIdGenerator, AsyncIdQueue, getGlobalOtelConfig, clone, AbortError } from '@orpc/shared';
2
+ import { generateContentDisposition, flattenHeader, getFilenameFromContentDisposition, withEventMeta, ErrorEvent, getEventMeta, isEventIteratorHeaders, HibernationEventIterator } from '@orpc/standard-server';
3
3
 
4
+ const SHORTABLE_ORIGIN = "http://orpc";
5
+ const SHORTABLE_ORIGIN_MATCHER = /^http:\/\/orpc\//;
4
6
  var MessageType = /* @__PURE__ */ ((MessageType2) => {
5
7
  MessageType2[MessageType2["REQUEST"] = 1] = "REQUEST";
6
8
  MessageType2[MessageType2["RESPONSE"] = 2] = "RESPONSE";
@@ -8,7 +10,7 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
8
10
  MessageType2[MessageType2["ABORT_SIGNAL"] = 4] = "ABORT_SIGNAL";
9
11
  return MessageType2;
10
12
  })(MessageType || {});
11
- async function encodeRequestMessage(id, type, payload) {
13
+ function serializeRequestMessage(id, type, payload) {
12
14
  if (type === 3 /* EVENT_ITERATOR */) {
13
15
  const eventPayload = payload;
14
16
  const serializedPayload2 = {
@@ -16,35 +18,26 @@ async function encodeRequestMessage(id, type, payload) {
16
18
  d: eventPayload.data,
17
19
  m: eventPayload.meta
18
20
  };
19
- return encodeRawMessage({ i: id, t: type, p: serializedPayload2 });
21
+ return { i: id, t: type, p: serializedPayload2 };
20
22
  }
21
23
  if (type === 4 /* ABORT_SIGNAL */) {
22
- return encodeRawMessage({ i: id, t: type, p: payload });
24
+ return { i: id, t: type, p: payload };
23
25
  }
24
26
  const request = payload;
25
- const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
26
- request.body,
27
- request.headers
28
- );
29
27
  const serializedPayload = {
30
- u: request.url.toString().replace(/^orpc:\//, "/"),
31
- b: processedBody instanceof Blob ? void 0 : processedBody,
32
- h: Object.keys(processedHeaders).length > 0 ? processedHeaders : void 0,
28
+ u: request.url.toString().replace(SHORTABLE_ORIGIN_MATCHER, "/"),
29
+ b: request.body,
30
+ h: Object.keys(request.headers).length > 0 ? request.headers : void 0,
33
31
  m: request.method === "POST" ? void 0 : request.method
34
32
  };
35
- const baseMessage = {
33
+ return {
36
34
  i: id,
37
35
  p: serializedPayload
38
36
  };
39
- if (processedBody instanceof Blob) {
40
- return encodeRawMessage(baseMessage, processedBody);
41
- }
42
- return encodeRawMessage(baseMessage);
43
37
  }
44
- async function decodeRequestMessage(raw) {
45
- const { json: message, buffer } = await decodeRawMessage(raw);
38
+ function deserializeRequestMessage(message) {
46
39
  const id = message.i;
47
- const type = message.t;
40
+ const type = message.t ?? 1 /* REQUEST */;
48
41
  if (type === 3 /* EVENT_ITERATOR */) {
49
42
  const payload2 = message.p;
50
43
  return [id, type, { event: payload2.e, data: payload2.d, meta: payload2.m }];
@@ -53,11 +46,14 @@ async function decodeRequestMessage(raw) {
53
46
  return [id, type, message.p];
54
47
  }
55
48
  const payload = message.p;
56
- const headers = payload.h ?? {};
57
- const body = await deserializeBody(headers, payload.b, buffer);
58
- return [id, 1 /* REQUEST */, { url: new URL(payload.u, "orpc:/"), headers, method: payload.m ?? "POST", body }];
49
+ return [id, 1 /* REQUEST */, {
50
+ url: payload.u.startsWith("/") ? new URL(`${SHORTABLE_ORIGIN}${payload.u}`) : new URL(payload.u),
51
+ headers: payload.h ?? {},
52
+ method: payload.m ?? "POST",
53
+ body: payload.b
54
+ }];
59
55
  }
60
- async function encodeResponseMessage(id, type, payload) {
56
+ function serializeResponseMessage(id, type, payload) {
61
57
  if (type === 3 /* EVENT_ITERATOR */) {
62
58
  const eventPayload = payload;
63
59
  const serializedPayload2 = {
@@ -65,32 +61,23 @@ async function encodeResponseMessage(id, type, payload) {
65
61
  d: eventPayload.data,
66
62
  m: eventPayload.meta
67
63
  };
68
- return encodeRawMessage({ i: id, t: type, p: serializedPayload2 });
64
+ return { i: id, t: type, p: serializedPayload2 };
69
65
  }
70
66
  if (type === 4 /* ABORT_SIGNAL */) {
71
- return encodeRawMessage({ i: id, t: type, p: void 0 });
67
+ return { i: id, t: type, p: void 0 };
72
68
  }
73
69
  const response = payload;
74
- const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
75
- response.body,
76
- response.headers
77
- );
78
70
  const serializedPayload = {
79
71
  s: response.status === 200 ? void 0 : response.status,
80
- h: Object.keys(processedHeaders).length > 0 ? processedHeaders : void 0,
81
- b: processedBody instanceof Blob ? void 0 : processedBody
72
+ h: Object.keys(response.headers).length > 0 ? response.headers : void 0,
73
+ b: response.body
82
74
  };
83
- const baseMessage = {
75
+ return {
84
76
  i: id,
85
77
  p: serializedPayload
86
78
  };
87
- if (processedBody instanceof Blob) {
88
- return encodeRawMessage(baseMessage, processedBody);
89
- }
90
- return encodeRawMessage(baseMessage);
91
79
  }
92
- async function decodeResponseMessage(raw) {
93
- const { json: message, buffer } = await decodeRawMessage(raw);
80
+ function deserializeResponseMessage(message) {
94
81
  const id = message.i;
95
82
  const type = message.t;
96
83
  if (type === 3 /* EVENT_ITERATOR */) {
@@ -101,9 +88,71 @@ async function decodeResponseMessage(raw) {
101
88
  return [id, type, message.p];
102
89
  }
103
90
  const payload = message.p;
104
- const headers = payload.h ?? {};
105
- const body = await deserializeBody(headers, payload.b, buffer);
106
- return [id, 2 /* RESPONSE */, { status: payload.s ?? 200, headers, body }];
91
+ return [id, 2 /* RESPONSE */, {
92
+ status: payload.s ?? 200,
93
+ headers: payload.h ?? {},
94
+ body: payload.b
95
+ }];
96
+ }
97
+ async function encodeRequestMessage(id, type, payload) {
98
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
99
+ return encodeRawMessage(serializeRequestMessage(id, type, payload));
100
+ }
101
+ const request = payload;
102
+ const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
103
+ request.body,
104
+ request.headers
105
+ );
106
+ const modifiedRequest = {
107
+ ...request,
108
+ body: processedBody instanceof Blob ? void 0 : processedBody,
109
+ headers: processedHeaders
110
+ };
111
+ const baseMessage = serializeRequestMessage(id, 1 /* REQUEST */, modifiedRequest);
112
+ if (processedBody instanceof Blob) {
113
+ return encodeRawMessage(baseMessage, processedBody);
114
+ }
115
+ return encodeRawMessage(baseMessage);
116
+ }
117
+ async function decodeRequestMessage(raw) {
118
+ const { json: message, buffer } = await decodeRawMessage(raw);
119
+ const [id, type, payload] = deserializeRequestMessage(message);
120
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
121
+ return [id, type, payload];
122
+ }
123
+ const request = payload;
124
+ const body = await deserializeBody(request.headers, request.body, buffer);
125
+ return [id, type, { ...request, body }];
126
+ }
127
+ async function encodeResponseMessage(id, type, payload) {
128
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
129
+ return encodeRawMessage(serializeResponseMessage(id, type, payload));
130
+ }
131
+ const response = payload;
132
+ const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
133
+ response.body,
134
+ response.headers
135
+ );
136
+ const modifiedResponse = {
137
+ ...response,
138
+ body: processedBody instanceof Blob ? void 0 : processedBody,
139
+ headers: processedHeaders
140
+ };
141
+ const baseMessage = serializeResponseMessage(id, 2 /* RESPONSE */, modifiedResponse);
142
+ if (processedBody instanceof Blob) {
143
+ return encodeRawMessage(baseMessage, processedBody);
144
+ }
145
+ return encodeRawMessage(baseMessage);
146
+ }
147
+ async function decodeResponseMessage(raw) {
148
+ const { json: message, buffer } = await decodeRawMessage(raw);
149
+ const [id, type, payload] = deserializeResponseMessage(message);
150
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
151
+ return [id, type, payload];
152
+ }
153
+ const response = payload;
154
+ const body = await deserializeBody(response.headers, response.body, buffer);
155
+ return [id, type, { ...response, body }];
107
156
  }
108
157
  async function serializeBodyAndHeaders(body, originalHeaders) {
109
158
  const headers = { ...originalHeaders };
@@ -179,134 +228,252 @@ async function decodeRawMessage(raw) {
179
228
  };
180
229
  }
181
230
 
182
- function toEventIterator(queue, id, cleanup) {
231
+ function toEventIterator(queue, id, cleanup, options = {}) {
232
+ let span;
183
233
  return new AsyncIteratorClass(async () => {
184
- const item = await queue.pull(id);
185
- switch (item.event) {
186
- case "message": {
187
- let data = item.data;
188
- if (item.meta && isTypescriptObject(data)) {
189
- data = withEventMeta(data, item.meta);
234
+ span ??= startSpan("consume_event_iterator_stream");
235
+ try {
236
+ const item = await runInSpanContext(span, () => queue.pull(id));
237
+ switch (item.event) {
238
+ case "message": {
239
+ let data = item.data;
240
+ if (item.meta && isTypescriptObject(data)) {
241
+ data = withEventMeta(data, item.meta);
242
+ }
243
+ span?.addEvent("message");
244
+ return { value: data, done: false };
190
245
  }
191
- return { value: data, done: false };
192
- }
193
- case "error": {
194
- let error = new ErrorEvent({
195
- data: item.data
196
- });
197
- if (item.meta) {
198
- error = withEventMeta(error, item.meta);
246
+ case "error": {
247
+ let error = new ErrorEvent({
248
+ data: item.data
249
+ });
250
+ if (item.meta) {
251
+ error = withEventMeta(error, item.meta);
252
+ }
253
+ span?.addEvent("error");
254
+ throw error;
199
255
  }
200
- throw error;
201
- }
202
- case "done": {
203
- let data = item.data;
204
- if (item.meta && isTypescriptObject(data)) {
205
- data = withEventMeta(data, item.meta);
256
+ case "done": {
257
+ let data = item.data;
258
+ if (item.meta && isTypescriptObject(data)) {
259
+ data = withEventMeta(data, item.meta);
260
+ }
261
+ span?.addEvent("done");
262
+ return { value: data, done: true };
206
263
  }
207
- return { value: data, done: true };
208
264
  }
209
- }
210
- }, cleanup);
211
- }
212
- async function resolveEventIterator(iterator, callback) {
213
- while (true) {
214
- const payload = await (async () => {
215
- try {
216
- const { value, done } = await iterator.next();
217
- if (done) {
218
- return { event: "done", data: value, meta: getEventMeta(value) };
219
- }
220
- return { event: "message", data: value, meta: getEventMeta(value) };
221
- } catch (err) {
222
- return {
223
- meta: getEventMeta(err),
224
- event: "error",
225
- data: err instanceof ErrorEvent ? err.data : void 0
226
- };
265
+ } catch (e) {
266
+ if (!(e instanceof ErrorEvent)) {
267
+ setSpanError(span, e, options);
227
268
  }
228
- })();
269
+ throw e;
270
+ }
271
+ }, async (reason) => {
229
272
  try {
230
- const direction = await callback(payload);
231
- if (payload.event === "done" || payload.event === "error") {
232
- return;
273
+ if (reason !== "next") {
274
+ span?.addEvent("cancelled");
233
275
  }
234
- if (direction === "abort") {
276
+ await runInSpanContext(span, () => cleanup(reason));
277
+ } catch (e) {
278
+ setSpanError(span, e, options);
279
+ throw e;
280
+ } finally {
281
+ span?.end();
282
+ }
283
+ });
284
+ }
285
+ function resolveEventIterator(iterator, callback) {
286
+ return runWithSpan(
287
+ { name: "stream_event_iterator" },
288
+ async (span) => {
289
+ while (true) {
290
+ const payload = await (async () => {
291
+ try {
292
+ const { value, done } = await iterator.next();
293
+ if (done) {
294
+ span?.addEvent("done");
295
+ return { event: "done", data: value, meta: getEventMeta(value) };
296
+ }
297
+ span?.addEvent("message");
298
+ return { event: "message", data: value, meta: getEventMeta(value) };
299
+ } catch (err) {
300
+ if (err instanceof ErrorEvent) {
301
+ span?.addEvent("error");
302
+ return {
303
+ event: "error",
304
+ data: err.data,
305
+ meta: getEventMeta(err)
306
+ };
307
+ } else {
308
+ try {
309
+ await callback({ event: "error", data: void 0 });
310
+ } catch (err2) {
311
+ setSpanError(span, err);
312
+ throw err2;
313
+ }
314
+ throw err;
315
+ }
316
+ }
317
+ })();
318
+ let isInvokeCleanupFn = false;
235
319
  try {
236
- await iterator.return?.();
237
- } catch {
320
+ const direction = await callback(payload);
321
+ if (payload.event === "done" || payload.event === "error") {
322
+ return;
323
+ }
324
+ if (direction === "abort") {
325
+ isInvokeCleanupFn = true;
326
+ await iterator.return?.();
327
+ return;
328
+ }
329
+ } catch (err) {
330
+ if (!isInvokeCleanupFn) {
331
+ try {
332
+ await iterator.return?.();
333
+ } catch (err2) {
334
+ setSpanError(span, err);
335
+ throw err2;
336
+ }
337
+ }
338
+ throw err;
238
339
  }
239
- return;
240
- }
241
- } catch (err) {
242
- try {
243
- await iterator.return?.();
244
- } catch {
245
340
  }
246
- throw err;
247
341
  }
248
- }
342
+ );
249
343
  }
250
344
 
251
345
  class ClientPeer {
346
+ peer;
347
+ constructor(send) {
348
+ this.peer = new experimental_ClientPeerWithoutCodec(async ([id, type, payload]) => {
349
+ await send(await encodeRequestMessage(id, type, payload));
350
+ });
351
+ }
352
+ get length() {
353
+ return this.peer.length;
354
+ }
355
+ open(id) {
356
+ return this.peer.open(id);
357
+ }
358
+ async request(request) {
359
+ return this.peer.request(request);
360
+ }
361
+ async message(raw) {
362
+ return this.peer.message(await decodeResponseMessage(raw));
363
+ }
364
+ close(options = {}) {
365
+ return this.peer.close(options);
366
+ }
367
+ }
368
+ class experimental_ClientPeerWithoutCodec {
252
369
  idGenerator = new SequentialIdGenerator();
370
+ /**
371
+ * Queue of responses sent from server, awaiting consumption
372
+ */
253
373
  responseQueue = new AsyncIdQueue();
374
+ /**
375
+ * Queue of event iterator messages sent from server, awaiting consumption
376
+ */
254
377
  serverEventIteratorQueue = new AsyncIdQueue();
378
+ /**
379
+ * Controllers used to signal that the client should stop sending event iterator messages
380
+ */
255
381
  serverControllers = /* @__PURE__ */ new Map();
382
+ /**
383
+ * Cleanup functions invoked when the request/response is closed
384
+ */
385
+ cleanupFns = /* @__PURE__ */ new Map();
256
386
  send;
257
387
  constructor(send) {
258
- this.send = async (id, ...rest) => encodeRequestMessage(id, ...rest).then(async (raw) => {
388
+ this.send = async (message) => {
389
+ const id = message[0];
259
390
  if (this.serverControllers.has(id)) {
260
- await send(raw);
391
+ await send(message);
261
392
  }
262
- });
393
+ };
263
394
  }
264
395
  get length() {
265
- return (+this.responseQueue.length + this.serverEventIteratorQueue.length + this.serverControllers.size) / 3;
396
+ return (+this.responseQueue.length + this.serverEventIteratorQueue.length + this.serverControllers.size + this.cleanupFns.size) / 4;
266
397
  }
267
398
  open(id) {
268
399
  this.serverEventIteratorQueue.open(id);
269
400
  this.responseQueue.open(id);
270
401
  const controller = new AbortController();
271
402
  this.serverControllers.set(id, controller);
403
+ this.cleanupFns.set(id, []);
272
404
  return controller;
273
405
  }
274
406
  async request(request) {
275
407
  const signal = request.signal;
276
- if (signal?.aborted) {
277
- throw signal.reason;
278
- }
279
- const id = this.idGenerator.generate();
280
- const serverController = this.open(id);
281
- return new Promise((resolve, reject) => {
282
- this.send(id, MessageType.REQUEST, request).then(async () => {
408
+ return runWithSpan(
409
+ { name: "send_peer_request", signal },
410
+ async () => {
283
411
  if (signal?.aborted) {
284
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
285
- this.close({ id, reason: signal.reason });
286
- return;
412
+ throw signal.reason;
287
413
  }
288
- signal?.addEventListener("abort", async () => {
289
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
290
- this.close({ id, reason: signal.reason });
291
- }, { once: true });
292
- if (isAsyncIteratorObject(request.body)) {
293
- await resolveEventIterator(request.body, async (payload) => {
294
- if (serverController.signal.aborted) {
295
- return "abort";
296
- }
297
- await this.send(id, MessageType.EVENT_ITERATOR, payload);
298
- return "next";
414
+ const id = this.idGenerator.generate();
415
+ const serverController = this.open(id);
416
+ try {
417
+ const otelConfig = getGlobalOtelConfig();
418
+ if (otelConfig) {
419
+ const headers = clone(request.headers);
420
+ otelConfig.propagation.inject(otelConfig.context.active(), headers);
421
+ request = { ...request, headers };
422
+ }
423
+ await this.send([id, MessageType.REQUEST, request]);
424
+ if (signal?.aborted) {
425
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
426
+ throw signal.reason;
427
+ }
428
+ let abortListener;
429
+ signal?.addEventListener("abort", abortListener = async () => {
430
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
431
+ this.close({ id, reason: signal.reason });
432
+ }, { once: true });
433
+ this.cleanupFns.get(id)?.push(() => {
434
+ signal?.removeEventListener("abort", abortListener);
299
435
  });
436
+ if (isAsyncIteratorObject(request.body)) {
437
+ const iterator = request.body;
438
+ void resolveEventIterator(iterator, async (payload) => {
439
+ if (serverController.signal.aborted) {
440
+ return "abort";
441
+ }
442
+ await this.send([id, MessageType.EVENT_ITERATOR, payload]);
443
+ return "next";
444
+ });
445
+ }
446
+ const response = await this.responseQueue.pull(id);
447
+ if (isEventIteratorHeaders(response.headers)) {
448
+ const iterator = toEventIterator(
449
+ this.serverEventIteratorQueue,
450
+ id,
451
+ async (reason) => {
452
+ try {
453
+ if (reason !== "next") {
454
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
455
+ }
456
+ } finally {
457
+ this.close({ id });
458
+ }
459
+ },
460
+ { signal }
461
+ );
462
+ return {
463
+ ...response,
464
+ body: iterator
465
+ };
466
+ }
467
+ this.close({ id });
468
+ return response;
469
+ } catch (err) {
470
+ this.close({ id, reason: err });
471
+ throw err;
300
472
  }
301
- }).catch((err) => {
302
- this.close({ id, reason: err });
303
- reject(err);
304
- });
305
- this.responseQueue.pull(id).then(resolve).catch(reject);
306
- });
473
+ }
474
+ );
307
475
  }
308
- async message(raw) {
309
- const [id, type, payload] = await decodeResponseMessage(raw);
476
+ async message([id, type, payload]) {
310
477
  if (type === MessageType.ABORT_SIGNAL) {
311
478
  this.serverControllers.get(id)?.abort();
312
479
  return;
@@ -320,31 +487,19 @@ class ClientPeer {
320
487
  if (!this.responseQueue.isOpen(id)) {
321
488
  return;
322
489
  }
323
- if (isEventIteratorHeaders(payload.headers)) {
324
- this.responseQueue.push(id, {
325
- ...payload,
326
- body: toEventIterator(this.serverEventIteratorQueue, id, async (reason) => {
327
- try {
328
- if (reason !== "next") {
329
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
330
- }
331
- } finally {
332
- this.close({ id });
333
- }
334
- })
335
- });
336
- } else {
337
- this.responseQueue.push(id, payload);
338
- this.close({ id });
339
- }
490
+ this.responseQueue.push(id, payload);
340
491
  }
341
492
  close(options = {}) {
342
493
  if (options.id !== void 0) {
343
494
  this.serverControllers.get(options.id)?.abort(options.reason);
344
495
  this.serverControllers.delete(options.id);
496
+ this.cleanupFns.get(options.id)?.forEach((fn) => fn());
497
+ this.cleanupFns.delete(options.id);
345
498
  } else {
346
499
  this.serverControllers.forEach((c) => c.abort(options.reason));
347
500
  this.serverControllers.clear();
501
+ this.cleanupFns.forEach((fns) => fns.forEach((fn) => fn()));
502
+ this.cleanupFns.clear();
348
503
  }
349
504
  this.responseQueue.close(options);
350
505
  this.serverEventIteratorQueue.close(options);
@@ -352,15 +507,51 @@ class ClientPeer {
352
507
  }
353
508
 
354
509
  class ServerPeer {
510
+ peer;
511
+ constructor(send) {
512
+ this.peer = new experimental_ServerPeerWithoutCodec(async ([id, type, payload]) => {
513
+ await send(await encodeResponseMessage(id, type, payload));
514
+ });
515
+ }
516
+ get length() {
517
+ return this.peer.length;
518
+ }
519
+ open(id) {
520
+ return this.peer.open(id);
521
+ }
522
+ /**
523
+ * @todo This method will return Promise<void> in the next major version.
524
+ */
525
+ async message(raw, handleRequest) {
526
+ return this.peer.message(await decodeRequestMessage(raw), handleRequest);
527
+ }
528
+ /**
529
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
530
+ */
531
+ async response(id, response) {
532
+ return this.peer.response(id, response);
533
+ }
534
+ close({ abort = true, ...options } = {}) {
535
+ return this.peer.close({ ...options, abort });
536
+ }
537
+ }
538
+ class experimental_ServerPeerWithoutCodec {
539
+ /**
540
+ * Queue of event iterator messages sent from client, awaiting consumption
541
+ */
355
542
  clientEventIteratorQueue = new AsyncIdQueue();
543
+ /**
544
+ * Map of active client request controllers, should be synced to request signal
545
+ */
356
546
  clientControllers = /* @__PURE__ */ new Map();
357
547
  send;
358
548
  constructor(send) {
359
- this.send = (id, ...rest) => encodeResponseMessage(id, ...rest).then(async (raw) => {
549
+ this.send = async (message) => {
550
+ const id = message[0];
360
551
  if (this.clientControllers.has(id)) {
361
- await send(raw);
552
+ await send(message);
362
553
  }
363
- });
554
+ };
364
555
  }
365
556
  get length() {
366
557
  return (this.clientEventIteratorQueue.length + this.clientControllers.size) / 2;
@@ -371,10 +562,12 @@ class ServerPeer {
371
562
  this.clientControllers.set(id, controller);
372
563
  return controller;
373
564
  }
374
- async message(raw) {
375
- const [id, type, payload] = await decodeRequestMessage(raw);
565
+ /**
566
+ * @todo This method will return Promise<void> in the next major version.
567
+ */
568
+ async message([id, type, payload], handleRequest) {
376
569
  if (type === MessageType.ABORT_SIGNAL) {
377
- this.close({ id });
570
+ this.close({ id, reason: new AbortError("Client aborted the request") });
378
571
  return [id, void 0];
379
572
  }
380
573
  if (type === MessageType.EVENT_ITERATOR) {
@@ -383,52 +576,93 @@ class ServerPeer {
383
576
  }
384
577
  return [id, void 0];
385
578
  }
579
+ if (this.clientControllers.has(id)) {
580
+ return [id, void 0];
581
+ }
386
582
  const clientController = this.open(id);
583
+ const signal = clientController.signal;
387
584
  const request = {
388
585
  ...payload,
389
- signal: clientController.signal,
390
- body: isEventIteratorHeaders(payload.headers) ? toEventIterator(this.clientEventIteratorQueue, id, async (reason) => {
391
- if (reason !== "next") {
392
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
393
- }
394
- }) : payload.body
586
+ signal,
587
+ body: isEventIteratorHeaders(payload.headers) ? toEventIterator(
588
+ this.clientEventIteratorQueue,
589
+ id,
590
+ async (reason) => {
591
+ if (reason !== "next") {
592
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
593
+ }
594
+ },
595
+ { signal }
596
+ ) : payload.body
395
597
  };
598
+ if (handleRequest) {
599
+ let context;
600
+ const otelConfig = getGlobalOtelConfig();
601
+ if (otelConfig) {
602
+ context = otelConfig.propagation.extract(otelConfig.context.active(), request.headers);
603
+ }
604
+ await runWithSpan(
605
+ { name: "receive_peer_request", context },
606
+ async () => {
607
+ const response = await runWithSpan(
608
+ { name: "handle_request" },
609
+ async () => {
610
+ try {
611
+ return await handleRequest(request);
612
+ } catch (reason) {
613
+ this.close({ id, reason, abort: false });
614
+ throw reason;
615
+ }
616
+ }
617
+ );
618
+ await runWithSpan(
619
+ { name: "send_peer_response" },
620
+ () => this.response(id, response)
621
+ );
622
+ }
623
+ );
624
+ }
396
625
  return [id, request];
397
626
  }
627
+ /**
628
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
629
+ */
398
630
  async response(id, response) {
399
631
  const signal = this.clientControllers.get(id)?.signal;
400
632
  if (!signal || signal.aborted) {
401
633
  return;
402
634
  }
403
- await this.send(id, MessageType.RESPONSE, response).then(async () => {
635
+ try {
636
+ await this.send([id, MessageType.RESPONSE, response]);
404
637
  if (!signal.aborted && isAsyncIteratorObject(response.body)) {
405
- if (response.body instanceof experimental_HibernationEventIterator) {
638
+ if (response.body instanceof HibernationEventIterator) {
406
639
  response.body.hibernationCallback?.(id);
407
640
  } else {
408
- await resolveEventIterator(response.body, async (payload) => {
641
+ const iterator = response.body;
642
+ await resolveEventIterator(iterator, async (payload) => {
409
643
  if (signal.aborted) {
410
644
  return "abort";
411
645
  }
412
- await this.send(id, MessageType.EVENT_ITERATOR, payload);
646
+ await this.send([id, MessageType.EVENT_ITERATOR, payload]);
413
647
  return "next";
414
648
  });
415
649
  }
416
650
  }
417
651
  this.close({ id, abort: false });
418
- }).catch((reason) => {
652
+ } catch (reason) {
419
653
  this.close({ id, reason, abort: false });
420
654
  throw reason;
421
- });
655
+ }
422
656
  }
423
657
  close({ abort = true, ...options } = {}) {
424
658
  if (options.id === void 0) {
425
659
  if (abort) {
426
- this.clientControllers.forEach((c) => c.abort());
660
+ this.clientControllers.forEach((c) => c.abort(options.reason));
427
661
  }
428
662
  this.clientControllers.clear();
429
663
  } else {
430
664
  if (abort) {
431
- this.clientControllers.get(options.id)?.abort();
665
+ this.clientControllers.get(options.id)?.abort(options.reason);
432
666
  }
433
667
  this.clientControllers.delete(options.id);
434
668
  }
@@ -436,4 +670,4 @@ class ServerPeer {
436
670
  }
437
671
  }
438
672
 
439
- export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, resolveEventIterator, toEventIterator };
673
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, deserializeRequestMessage, deserializeResponseMessage, encodeRequestMessage, encodeResponseMessage, experimental_ClientPeerWithoutCodec, experimental_ServerPeerWithoutCodec, resolveEventIterator, serializeRequestMessage, serializeResponseMessage, toEventIterator };