@orpc/server 0.0.0-next.19c2a69 → 0.0.0-next.1a17b94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +9 -9
  2. package/dist/adapters/aws-lambda/index.d.mts +7 -6
  3. package/dist/adapters/aws-lambda/index.d.ts +7 -6
  4. package/dist/adapters/aws-lambda/index.mjs +7 -6
  5. package/dist/adapters/bun-ws/index.d.mts +12 -11
  6. package/dist/adapters/bun-ws/index.d.ts +12 -11
  7. package/dist/adapters/bun-ws/index.mjs +16 -20
  8. package/dist/adapters/crossws/index.d.mts +8 -5
  9. package/dist/adapters/crossws/index.d.ts +8 -5
  10. package/dist/adapters/crossws/index.mjs +11 -17
  11. package/dist/adapters/fetch/index.d.mts +54 -8
  12. package/dist/adapters/fetch/index.d.ts +54 -8
  13. package/dist/adapters/fetch/index.mjs +73 -4
  14. package/dist/adapters/message-port/index.d.mts +11 -8
  15. package/dist/adapters/message-port/index.d.ts +11 -8
  16. package/dist/adapters/message-port/index.mjs +14 -16
  17. package/dist/adapters/node/index.d.mts +30 -8
  18. package/dist/adapters/node/index.d.ts +30 -8
  19. package/dist/adapters/node/index.mjs +70 -13
  20. package/dist/adapters/standard/index.d.mts +8 -13
  21. package/dist/adapters/standard/index.d.ts +8 -13
  22. package/dist/adapters/standard/index.mjs +3 -2
  23. package/dist/adapters/standard-peer/index.d.mts +18 -0
  24. package/dist/adapters/standard-peer/index.d.ts +18 -0
  25. package/dist/adapters/standard-peer/index.mjs +7 -0
  26. package/dist/adapters/websocket/index.d.mts +36 -9
  27. package/dist/adapters/websocket/index.d.ts +36 -9
  28. package/dist/adapters/websocket/index.mjs +49 -20
  29. package/dist/adapters/ws/index.d.mts +11 -8
  30. package/dist/adapters/ws/index.d.ts +11 -8
  31. package/dist/adapters/ws/index.mjs +13 -14
  32. package/dist/helpers/index.d.mts +134 -0
  33. package/dist/helpers/index.d.ts +134 -0
  34. package/dist/helpers/index.mjs +188 -0
  35. package/dist/hibernation/index.d.mts +44 -0
  36. package/dist/hibernation/index.d.ts +44 -0
  37. package/dist/hibernation/index.mjs +65 -0
  38. package/dist/index.d.mts +21 -47
  39. package/dist/index.d.ts +21 -47
  40. package/dist/index.mjs +23 -9
  41. package/dist/plugins/index.d.mts +19 -6
  42. package/dist/plugins/index.d.ts +19 -6
  43. package/dist/plugins/index.mjs +94 -60
  44. package/dist/shared/{server.DG7Tamti.mjs → server.7jWaIryJ.mjs} +106 -57
  45. package/dist/shared/server.B7b2w3_i.d.ts +12 -0
  46. package/dist/shared/server.BEFBl-Cb.d.mts +12 -0
  47. package/dist/shared/{server.4FnxLwwr.mjs → server.BHZCyRuJ.mjs} +75 -42
  48. package/dist/shared/server.BU4WI18A.d.mts +32 -0
  49. package/dist/shared/{server.-ACo36I0.d.ts → server.Bmh5xd4n.d.ts} +3 -3
  50. package/dist/shared/{server.DD2C4ujN.d.mts → server.CYNGeoCm.d.mts} +6 -4
  51. package/dist/shared/{server.DD2C4ujN.d.ts → server.CYNGeoCm.d.ts} +6 -4
  52. package/dist/shared/server.D0H-iaY3.d.ts +32 -0
  53. package/dist/shared/{server.BVwwTHyO.mjs → server.DZ5BIITo.mjs} +1 -1
  54. package/dist/shared/server.DhJj-1X9.d.mts +42 -0
  55. package/dist/shared/server.UVMTOWrk.mjs +26 -0
  56. package/dist/shared/{server.Dq8xr7PQ.d.mts → server.gqRxT-yN.d.mts} +3 -3
  57. package/dist/shared/server.jMTkVNIb.d.ts +42 -0
  58. package/package.json +30 -13
  59. package/dist/shared/server.BPAWobQg.d.ts +0 -12
  60. package/dist/shared/server.Bd52nNaH.d.mts +0 -12
  61. package/dist/shared/server.BliFSTnG.d.mts +0 -10
  62. package/dist/shared/server.IG2MjhrD.d.ts +0 -10
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- import { mergeErrorMap, mergeMeta, mergeRoute, mergePrefix, mergeTags, isContractProcedure, getContractRouter } from '@orpc/contract';
1
+ import { mergeErrorMap, mergeMeta, mergeRoute, mergePrefix, mergeTags, isContractProcedure, getContractRouter, fallbackContractConfig } from '@orpc/contract';
2
2
  export { ValidationError, eventIterator, type } from '@orpc/contract';
3
- import { P as Procedure, b as addMiddleware, c as createProcedureClient, e as enhanceRouter, l as lazy, s as setHiddenRouterContract, i as isProcedure, d as isLazy, f as createAssertedLazyProcedure, g as getRouter } from './shared/server.DG7Tamti.mjs';
4
- export { L as LAZY_SYMBOL, p as call, r as createAccessibleLazyRouter, a as createContractedProcedure, h as createORPCErrorConstructorMap, q as getHiddenRouterContract, j as getLazyMeta, n as isStartWithMiddlewares, m as mergeCurrentContext, o as mergeMiddlewares, k as middlewareOutputFn, w as resolveContractProcedures, t as traverseContractProcedures, u as unlazy, x as unlazyRouter, v as validateORPCError } from './shared/server.DG7Tamti.mjs';
3
+ import { P as Procedure, b as addMiddleware, c as createProcedureClient, e as enhanceRouter, l as lazy, s as setHiddenRouterContract, u as unlazy, g as getRouter, i as isProcedure, d as isLazy, f as createAssertedLazyProcedure } from './shared/server.7jWaIryJ.mjs';
4
+ export { L as LAZY_SYMBOL, p as call, r as createAccessibleLazyRouter, a as createContractedProcedure, h as createORPCErrorConstructorMap, q as getHiddenRouterContract, j as getLazyMeta, n as isStartWithMiddlewares, m as mergeCurrentContext, o as mergeMiddlewares, k as middlewareOutputFn, w as resolveContractProcedures, t as traverseContractProcedures, x as unlazyRouter, v as validateORPCError } from './shared/server.7jWaIryJ.mjs';
5
5
  import { toORPCError } from '@orpc/client';
6
6
  export { ORPCError, isDefinedError, safe } from '@orpc/client';
7
7
  import { resolveMaybeOptionalOptions } from '@orpc/shared';
8
- export { onError, onFinish, onStart, onSuccess } from '@orpc/shared';
8
+ export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
9
9
  export { getEventMeta, withEventMeta } from '@orpc/standard-server';
10
10
 
11
11
  const DEFAULT_CONFIG = {
@@ -21,7 +21,7 @@ function fallbackConfig(key, value) {
21
21
  }
22
22
 
23
23
  function decorateMiddleware(middleware) {
24
- const decorated = (...args) => middleware(...args);
24
+ const decorated = ((...args) => middleware(...args));
25
25
  decorated.mapInput = (mapInput) => {
26
26
  const mapped = decorateMiddleware(
27
27
  (options, input, ...rest) => middleware(options, mapInput(input), ...rest)
@@ -151,7 +151,7 @@ class Builder {
151
151
  /**
152
152
  * Sets or overrides the config.
153
153
  *
154
- * @see {@link https://orpc.unnoq.com/docs/lifecycle#middlewares-order Middlewares Order Docs}
154
+ * @see {@link https://orpc.unnoq.com/docs/client/server-side#middlewares-order Middlewares Order Docs}
155
155
  * @see {@link https://orpc.unnoq.com/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
156
156
  */
157
157
  $config(config) {
@@ -448,12 +448,26 @@ function implement(contract, config = {}) {
448
448
  return impl;
449
449
  }
450
450
 
451
+ function inferRPCMethodFromRouter(router) {
452
+ return async (_, path) => {
453
+ const { default: procedure } = await unlazy(getRouter(router, path));
454
+ if (!isProcedure(procedure)) {
455
+ throw new Error(
456
+ `[inferRPCMethodFromRouter] No valid procedure found at path "${path.join(".")}". This may happen when the router is not properly configured.`
457
+ );
458
+ }
459
+ const method = fallbackContractConfig("defaultMethod", procedure["~orpc"].route.method);
460
+ return method === "HEAD" ? "GET" : method;
461
+ };
462
+ }
463
+
451
464
  function createRouterClient(router, ...rest) {
465
+ const options = resolveMaybeOptionalOptions(rest);
452
466
  if (isProcedure(router)) {
453
- const caller = createProcedureClient(router, resolveMaybeOptionalOptions(rest));
467
+ const caller = createProcedureClient(router, options);
454
468
  return caller;
455
469
  }
456
- const procedureCaller = isLazy(router) ? createProcedureClient(createAssertedLazyProcedure(router), resolveMaybeOptionalOptions(rest)) : {};
470
+ const procedureCaller = isLazy(router) ? createProcedureClient(createAssertedLazyProcedure(router), options) : {};
457
471
  const recursive = new Proxy(procedureCaller, {
458
472
  get(target, key) {
459
473
  if (typeof key !== "string") {
@@ -472,4 +486,4 @@ function createRouterClient(router, ...rest) {
472
486
  return recursive;
473
487
  }
474
488
 
475
- export { Builder, DecoratedProcedure, Procedure, addMiddleware, createActionableClient, createAssertedLazyProcedure, createProcedureClient, createRouterClient, decorateMiddleware, enhanceRouter, fallbackConfig, getRouter, implement, implementerInternal, isLazy, isProcedure, lazy, os, setHiddenRouterContract };
489
+ export { Builder, DecoratedProcedure, Procedure, addMiddleware, createActionableClient, createAssertedLazyProcedure, createProcedureClient, createRouterClient, decorateMiddleware, enhanceRouter, fallbackConfig, getRouter, implement, implementerInternal, inferRPCMethodFromRouter, isLazy, isProcedure, lazy, os, setHiddenRouterContract, unlazy };
@@ -1,8 +1,8 @@
1
1
  import { Value, Promisable } from '@orpc/shared';
2
2
  import { StandardRequest, StandardHeaders } from '@orpc/standard-server';
3
3
  import { BatchResponseBodyItem } from '@orpc/standard-server/batch';
4
- import { S as StandardHandlerInterceptorOptions, a as StandardHandlerPlugin, b as StandardHandlerOptions } from '../shared/server.Dq8xr7PQ.mjs';
5
- import { C as Context, F as ProcedureClientInterceptorOptions } from '../shared/server.DD2C4ujN.mjs';
4
+ import { d as StandardHandlerInterceptorOptions, g as StandardHandlerPlugin, e as StandardHandlerOptions } from '../shared/server.gqRxT-yN.mjs';
5
+ import { C as Context, d as ProcedureClientInterceptorOptions } from '../shared/server.CYNGeoCm.mjs';
6
6
  import { Meta, ORPCError as ORPCError$1 } from '@orpc/contract';
7
7
  import { ORPCError } from '@orpc/client';
8
8
 
@@ -33,10 +33,10 @@ interface BatchHandlerOptions<T extends Context> {
33
33
  headers?: Value<Promisable<StandardHeaders>, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
34
34
  }
35
35
  /**
36
- * The Batch Request/Response Plugin allows you to combine multiple requests and responses into a single batch,
36
+ * The Batch Requests Plugin allows you to combine multiple requests and responses into a single batch,
37
37
  * reducing the overhead of sending each one separately.
38
38
  *
39
- * @see {@link https://orpc.unnoq.com/docs/plugins/batch-request-response Batch Request/Response Plugin Docs}
39
+ * @see {@link https://orpc.unnoq.com/docs/plugins/batch-requests Batch Requests Plugin Docs}
40
40
  */
41
41
  declare class BatchHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
42
42
  private readonly maxSize;
@@ -69,6 +69,19 @@ declare class CORSPlugin<T extends Context> implements StandardHandlerPlugin<T>
69
69
  init(options: StandardHandlerOptions<T>): void;
70
70
  }
71
71
 
72
+ interface RequestHeadersPluginContext {
73
+ reqHeaders?: Headers;
74
+ }
75
+ /**
76
+ * The Request Headers Plugin injects a `reqHeaders` instance into the context,
77
+ * allowing access to request headers in oRPC.
78
+ *
79
+ * @see {@link https://orpc.unnoq.com/docs/plugins/request-headers Request Headers Plugin Docs}
80
+ */
81
+ declare class RequestHeadersPlugin<T extends RequestHeadersPluginContext> implements StandardHandlerPlugin<T> {
82
+ init(options: StandardHandlerOptions<T>): void;
83
+ }
84
+
72
85
  interface ResponseHeadersPluginContext {
73
86
  resHeaders?: Headers;
74
87
  }
@@ -152,5 +165,5 @@ declare class StrictGetMethodPlugin<T extends Context> implements StandardHandle
152
165
  init(options: StandardHandlerOptions<T>): void;
153
166
  }
154
167
 
155
- export { BatchHandlerPlugin, CORSPlugin, ResponseHeadersPlugin, SimpleCsrfProtectionHandlerPlugin, StrictGetMethodPlugin };
156
- export type { BatchHandlerOptions, CORSOptions, ResponseHeadersPluginContext, SimpleCsrfProtectionHandlerPluginOptions, StrictGetMethodPluginOptions };
168
+ export { BatchHandlerPlugin, CORSPlugin, RequestHeadersPlugin, ResponseHeadersPlugin, SimpleCsrfProtectionHandlerPlugin, StrictGetMethodPlugin };
169
+ export type { BatchHandlerOptions, CORSOptions, RequestHeadersPluginContext, ResponseHeadersPluginContext, SimpleCsrfProtectionHandlerPluginOptions, StrictGetMethodPluginOptions };
@@ -1,8 +1,8 @@
1
1
  import { Value, Promisable } from '@orpc/shared';
2
2
  import { StandardRequest, StandardHeaders } from '@orpc/standard-server';
3
3
  import { BatchResponseBodyItem } from '@orpc/standard-server/batch';
4
- import { S as StandardHandlerInterceptorOptions, a as StandardHandlerPlugin, b as StandardHandlerOptions } from '../shared/server.-ACo36I0.js';
5
- import { C as Context, F as ProcedureClientInterceptorOptions } from '../shared/server.DD2C4ujN.js';
4
+ import { d as StandardHandlerInterceptorOptions, g as StandardHandlerPlugin, e as StandardHandlerOptions } from '../shared/server.Bmh5xd4n.js';
5
+ import { C as Context, d as ProcedureClientInterceptorOptions } from '../shared/server.CYNGeoCm.js';
6
6
  import { Meta, ORPCError as ORPCError$1 } from '@orpc/contract';
7
7
  import { ORPCError } from '@orpc/client';
8
8
 
@@ -33,10 +33,10 @@ interface BatchHandlerOptions<T extends Context> {
33
33
  headers?: Value<Promisable<StandardHeaders>, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
34
34
  }
35
35
  /**
36
- * The Batch Request/Response Plugin allows you to combine multiple requests and responses into a single batch,
36
+ * The Batch Requests Plugin allows you to combine multiple requests and responses into a single batch,
37
37
  * reducing the overhead of sending each one separately.
38
38
  *
39
- * @see {@link https://orpc.unnoq.com/docs/plugins/batch-request-response Batch Request/Response Plugin Docs}
39
+ * @see {@link https://orpc.unnoq.com/docs/plugins/batch-requests Batch Requests Plugin Docs}
40
40
  */
41
41
  declare class BatchHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
42
42
  private readonly maxSize;
@@ -69,6 +69,19 @@ declare class CORSPlugin<T extends Context> implements StandardHandlerPlugin<T>
69
69
  init(options: StandardHandlerOptions<T>): void;
70
70
  }
71
71
 
72
+ interface RequestHeadersPluginContext {
73
+ reqHeaders?: Headers;
74
+ }
75
+ /**
76
+ * The Request Headers Plugin injects a `reqHeaders` instance into the context,
77
+ * allowing access to request headers in oRPC.
78
+ *
79
+ * @see {@link https://orpc.unnoq.com/docs/plugins/request-headers Request Headers Plugin Docs}
80
+ */
81
+ declare class RequestHeadersPlugin<T extends RequestHeadersPluginContext> implements StandardHandlerPlugin<T> {
82
+ init(options: StandardHandlerOptions<T>): void;
83
+ }
84
+
72
85
  interface ResponseHeadersPluginContext {
73
86
  resHeaders?: Headers;
74
87
  }
@@ -152,5 +165,5 @@ declare class StrictGetMethodPlugin<T extends Context> implements StandardHandle
152
165
  init(options: StandardHandlerOptions<T>): void;
153
166
  }
154
167
 
155
- export { BatchHandlerPlugin, CORSPlugin, ResponseHeadersPlugin, SimpleCsrfProtectionHandlerPlugin, StrictGetMethodPlugin };
156
- export type { BatchHandlerOptions, CORSOptions, ResponseHeadersPluginContext, SimpleCsrfProtectionHandlerPluginOptions, StrictGetMethodPluginOptions };
168
+ export { BatchHandlerPlugin, CORSPlugin, RequestHeadersPlugin, ResponseHeadersPlugin, SimpleCsrfProtectionHandlerPlugin, StrictGetMethodPlugin };
169
+ export type { BatchHandlerOptions, CORSOptions, RequestHeadersPluginContext, ResponseHeadersPluginContext, SimpleCsrfProtectionHandlerPluginOptions, StrictGetMethodPluginOptions };
@@ -1,6 +1,7 @@
1
- import { value, isAsyncIteratorObject } from '@orpc/shared';
2
- import { parseBatchRequest, toBatchResponse } from '@orpc/standard-server/batch';
1
+ import { runWithSpan, value, setSpanError, isAsyncIteratorObject, clone } from '@orpc/shared';
3
2
  import { flattenHeader } from '@orpc/standard-server';
3
+ import { parseBatchRequest, toBatchResponse } from '@orpc/standard-server/batch';
4
+ import { toFetchHeaders } from '@orpc/standard-server-fetch';
4
5
  import { ORPCError } from '@orpc/client';
5
6
  export { S as StrictGetMethodPlugin } from '../shared/server.BW-nUGgA.mjs';
6
7
  import '@orpc/contract';
@@ -26,69 +27,80 @@ class BatchHandlerPlugin {
26
27
  init(options) {
27
28
  options.rootInterceptors ??= [];
28
29
  options.rootInterceptors.unshift(async (options2) => {
29
- if (options2.request.headers["x-orpc-batch"] !== "1") {
30
+ const xHeader = flattenHeader(options2.request.headers["x-orpc-batch"]);
31
+ if (xHeader === void 0) {
30
32
  return options2.next();
31
33
  }
32
34
  let isParsing = false;
33
35
  try {
34
- isParsing = true;
35
- const parsed = parseBatchRequest({ ...options2.request, body: await options2.request.body() });
36
- isParsing = false;
37
- const maxSize = await value(this.maxSize, options2);
38
- if (parsed.length > maxSize) {
39
- return {
40
- matched: true,
41
- response: {
42
- status: 413,
43
- headers: {},
44
- body: "Batch request size exceeds the maximum allowed size"
45
- }
46
- };
47
- }
48
- const responses = parsed.map(
49
- (request, index) => {
50
- const mapped = this.mapRequestItem(request, options2);
51
- return options2.next({ ...options2, request: { ...mapped, body: () => Promise.resolve(mapped.body) } }).then(({ response: response2, matched }) => {
52
- if (matched) {
53
- if (response2.body instanceof Blob || response2.body instanceof FormData || isAsyncIteratorObject(response2.body)) {
54
- return {
55
- index,
56
- status: 500,
57
- headers: {},
58
- body: "Batch responses do not support file/blob, or event-iterator. Please call this procedure separately outside of the batch request."
59
- };
60
- }
61
- return { ...response2, index };
36
+ return await runWithSpan({ name: "handle_batch_request" }, async (span) => {
37
+ const mode = xHeader === "buffered" ? "buffered" : "streaming";
38
+ isParsing = true;
39
+ const parsed = parseBatchRequest({ ...options2.request, body: await options2.request.body() });
40
+ isParsing = false;
41
+ span?.setAttribute("batch.mode", mode);
42
+ span?.setAttribute("batch.size", parsed.length);
43
+ const maxSize = await value(this.maxSize, options2);
44
+ if (parsed.length > maxSize) {
45
+ const message = "Batch request size exceeds the maximum allowed size";
46
+ setSpanError(span, message);
47
+ return {
48
+ matched: true,
49
+ response: {
50
+ status: 413,
51
+ headers: {},
52
+ body: message
62
53
  }
63
- return { index, status: 404, headers: {}, body: "No procedure matched" };
64
- }).catch(() => {
65
- return { index, status: 500, headers: {}, body: "Internal server error" };
66
- });
54
+ };
67
55
  }
68
- );
69
- await Promise.race(responses);
70
- const status = await value(this.successStatus, responses, options2);
71
- const headers = await value(this.headers, responses, options2);
72
- const response = toBatchResponse({
73
- status,
74
- headers,
75
- body: async function* () {
76
- const promises = [...responses];
77
- while (true) {
78
- const handling = promises.filter((p) => p !== void 0);
79
- if (handling.length === 0) {
80
- return;
81
- }
82
- const result = await Promise.race(handling);
83
- promises[result.index] = void 0;
84
- yield result;
56
+ const responses = parsed.map(
57
+ (request, index) => {
58
+ const mapped = this.mapRequestItem(request, options2);
59
+ return options2.next({ ...options2, request: { ...mapped, body: () => Promise.resolve(mapped.body) } }).then(({ response: response2, matched }) => {
60
+ span?.addEvent(`response.${index}.${matched ? "success" : "not_matched"}`);
61
+ if (matched) {
62
+ if (response2.body instanceof Blob || response2.body instanceof FormData || isAsyncIteratorObject(response2.body)) {
63
+ return {
64
+ index,
65
+ status: 500,
66
+ headers: {},
67
+ body: "Batch responses do not support file/blob, or event-iterator. Please call this procedure separately outside of the batch request."
68
+ };
69
+ }
70
+ return { ...response2, index };
71
+ }
72
+ return { index, status: 404, headers: {}, body: "No procedure matched" };
73
+ }).catch((err) => {
74
+ Promise.reject(err);
75
+ return { index, status: 500, headers: {}, body: "Internal server error" };
76
+ });
85
77
  }
86
- }()
78
+ );
79
+ await Promise.race(responses);
80
+ const status = await value(this.successStatus, responses, options2);
81
+ const headers = await value(this.headers, responses, options2);
82
+ const response = await toBatchResponse({
83
+ status,
84
+ headers,
85
+ mode,
86
+ body: (async function* () {
87
+ const promises = [...responses];
88
+ while (true) {
89
+ const handling = promises.filter((p) => p !== void 0);
90
+ if (handling.length === 0) {
91
+ return;
92
+ }
93
+ const result = await Promise.race(handling);
94
+ promises[result.index] = void 0;
95
+ yield result;
96
+ }
97
+ })()
98
+ });
99
+ return {
100
+ matched: true,
101
+ response
102
+ };
87
103
  });
88
- return {
89
- matched: true,
90
- response
91
- };
92
104
  } catch (cause) {
93
105
  if (isParsing) {
94
106
  return {
@@ -175,6 +187,22 @@ class CORSPlugin {
175
187
  }
176
188
  }
177
189
 
190
+ class RequestHeadersPlugin {
191
+ init(options) {
192
+ options.rootInterceptors ??= [];
193
+ options.rootInterceptors.push((interceptorOptions) => {
194
+ const reqHeaders = interceptorOptions.context.reqHeaders ?? toFetchHeaders(interceptorOptions.request.headers);
195
+ return interceptorOptions.next({
196
+ ...interceptorOptions,
197
+ context: {
198
+ ...interceptorOptions.context,
199
+ reqHeaders
200
+ }
201
+ });
202
+ });
203
+ }
204
+ }
205
+
178
206
  class ResponseHeadersPlugin {
179
207
  init(options) {
180
208
  options.rootInterceptors ??= [];
@@ -190,7 +218,7 @@ class ResponseHeadersPlugin {
190
218
  if (!result.matched) {
191
219
  return result;
192
220
  }
193
- const responseHeaders = result.response.headers;
221
+ const responseHeaders = clone(result.response.headers);
194
222
  for (const [key, value] of resHeaders) {
195
223
  if (Array.isArray(responseHeaders[key])) {
196
224
  responseHeaders[key].push(value);
@@ -200,7 +228,13 @@ class ResponseHeadersPlugin {
200
228
  responseHeaders[key] = value;
201
229
  }
202
230
  }
203
- return result;
231
+ return {
232
+ ...result,
233
+ response: {
234
+ ...result.response,
235
+ headers: responseHeaders
236
+ }
237
+ };
204
238
  });
205
239
  }
206
240
  }
@@ -248,4 +282,4 @@ class SimpleCsrfProtectionHandlerPlugin {
248
282
  }
249
283
  }
250
284
 
251
- export { BatchHandlerPlugin, CORSPlugin, ResponseHeadersPlugin, SimpleCsrfProtectionHandlerPlugin };
285
+ export { BatchHandlerPlugin, CORSPlugin, RequestHeadersPlugin, ResponseHeadersPlugin, SimpleCsrfProtectionHandlerPlugin };
@@ -1,6 +1,7 @@
1
1
  import { isContractProcedure, ValidationError, mergePrefix, mergeErrorMap, enhanceRoute } from '@orpc/contract';
2
- import { fallbackORPCErrorStatus, ORPCError } from '@orpc/client';
3
- import { value, intercept } from '@orpc/shared';
2
+ import { resolveMaybeOptionalOptions, toArray, value, runWithSpan, intercept, isAsyncIteratorObject, asyncIteratorWithSpan } from '@orpc/shared';
3
+ import { ORPCError, fallbackORPCErrorStatus, mapEventIterator } from '@orpc/client';
4
+ import { HibernationEventIterator } from '@orpc/standard-server';
4
5
 
5
6
  const LAZY_SYMBOL = Symbol("ORPC_LAZY_SYMBOL");
6
7
  function lazy(loader, meta = {}) {
@@ -71,14 +72,15 @@ function createORPCErrorConstructorMap(errors) {
71
72
  if (typeof code !== "string") {
72
73
  return Reflect.get(target, code);
73
74
  }
74
- const item = (...[options]) => {
75
+ const item = (...rest) => {
76
+ const options = resolveMaybeOptionalOptions(rest);
75
77
  const config = errors[code];
76
78
  return new ORPCError(code, {
77
79
  defined: Boolean(config),
78
80
  status: config?.status,
79
- message: options?.message ?? config?.message,
80
- data: options?.data,
81
- cause: options?.cause
81
+ message: options.message ?? config?.message,
82
+ data: options.data,
83
+ cause: options.cause
82
84
  });
83
85
  };
84
86
  return item;
@@ -106,34 +108,59 @@ function middlewareOutputFn(output) {
106
108
  return { output, context: {} };
107
109
  }
108
110
 
109
- function createProcedureClient(lazyableProcedure, ...[options]) {
111
+ function createProcedureClient(lazyableProcedure, ...rest) {
112
+ const options = resolveMaybeOptionalOptions(rest);
110
113
  return async (...[input, callerOptions]) => {
111
- const path = options?.path ?? [];
114
+ const path = toArray(options.path);
112
115
  const { default: procedure } = await unlazy(lazyableProcedure);
113
116
  const clientContext = callerOptions?.context ?? {};
114
- const context = await value(options?.context ?? {}, clientContext);
117
+ const context = await value(options.context ?? {}, clientContext);
115
118
  const errors = createORPCErrorConstructorMap(procedure["~orpc"].errorMap);
119
+ const validateError = async (e) => {
120
+ if (e instanceof ORPCError) {
121
+ return await validateORPCError(procedure["~orpc"].errorMap, e);
122
+ }
123
+ return e;
124
+ };
116
125
  try {
117
- return await intercept(
118
- options?.interceptors ?? [],
119
- {
120
- context,
121
- input,
122
- // input only optional when it undefinable so we can safely cast it
123
- errors,
124
- path,
125
- procedure,
126
- signal: callerOptions?.signal,
127
- lastEventId: callerOptions?.lastEventId
128
- },
129
- (interceptorOptions) => executeProcedureInternal(interceptorOptions.procedure, interceptorOptions)
126
+ const output = await runWithSpan(
127
+ { name: "call_procedure", signal: callerOptions?.signal },
128
+ (span) => {
129
+ span?.setAttribute("procedure.path", [...path]);
130
+ return intercept(
131
+ toArray(options.interceptors),
132
+ {
133
+ context,
134
+ input,
135
+ // input only optional when it undefinable so we can safely cast it
136
+ errors,
137
+ path,
138
+ procedure,
139
+ signal: callerOptions?.signal,
140
+ lastEventId: callerOptions?.lastEventId
141
+ },
142
+ (interceptorOptions) => executeProcedureInternal(interceptorOptions.procedure, interceptorOptions)
143
+ );
144
+ }
130
145
  );
131
- } catch (e) {
132
- if (!(e instanceof ORPCError)) {
133
- throw e;
146
+ if (isAsyncIteratorObject(output)) {
147
+ if (output instanceof HibernationEventIterator) {
148
+ return output;
149
+ }
150
+ return mapEventIterator(
151
+ asyncIteratorWithSpan(
152
+ { name: "consume_event_iterator_output", signal: callerOptions?.signal },
153
+ output
154
+ ),
155
+ {
156
+ value: (v) => v,
157
+ error: (e) => validateError(e)
158
+ }
159
+ );
134
160
  }
135
- const validated = await validateORPCError(procedure["~orpc"].errorMap, e);
136
- throw validated;
161
+ return output;
162
+ } catch (e) {
163
+ throw await validateError(e);
137
164
  }
138
165
  };
139
166
  }
@@ -142,31 +169,41 @@ async function validateInput(procedure, input) {
142
169
  if (!schema) {
143
170
  return input;
144
171
  }
145
- const result = await schema["~standard"].validate(input);
146
- if (result.issues) {
147
- throw new ORPCError("BAD_REQUEST", {
148
- message: "Input validation failed",
149
- data: {
150
- issues: result.issues
151
- },
152
- cause: new ValidationError({ message: "Input validation failed", issues: result.issues })
153
- });
154
- }
155
- return result.value;
172
+ return runWithSpan(
173
+ { name: "validate_input" },
174
+ async () => {
175
+ const result = await schema["~standard"].validate(input);
176
+ if (result.issues) {
177
+ throw new ORPCError("BAD_REQUEST", {
178
+ message: "Input validation failed",
179
+ data: {
180
+ issues: result.issues
181
+ },
182
+ cause: new ValidationError({ message: "Input validation failed", issues: result.issues })
183
+ });
184
+ }
185
+ return result.value;
186
+ }
187
+ );
156
188
  }
157
189
  async function validateOutput(procedure, output) {
158
190
  const schema = procedure["~orpc"].outputSchema;
159
191
  if (!schema) {
160
192
  return output;
161
193
  }
162
- const result = await schema["~standard"].validate(output);
163
- if (result.issues) {
164
- throw new ORPCError("INTERNAL_SERVER_ERROR", {
165
- message: "Output validation failed",
166
- cause: new ValidationError({ message: "Output validation failed", issues: result.issues })
167
- });
168
- }
169
- return result.value;
194
+ return runWithSpan(
195
+ { name: "validate_output" },
196
+ async () => {
197
+ const result = await schema["~standard"].validate(output);
198
+ if (result.issues) {
199
+ throw new ORPCError("INTERNAL_SERVER_ERROR", {
200
+ message: "Output validation failed",
201
+ cause: new ValidationError({ message: "Output validation failed", issues: result.issues })
202
+ });
203
+ }
204
+ return result.value;
205
+ }
206
+ );
170
207
  }
171
208
  async function executeProcedureInternal(procedure, options) {
172
209
  const middlewares = procedure["~orpc"].middlewares;
@@ -178,17 +215,28 @@ async function executeProcedureInternal(procedure, options) {
178
215
  currentInput = await validateInput(procedure, currentInput);
179
216
  }
180
217
  const mid = middlewares[index];
181
- const output = mid ? (await mid({
182
- ...options,
183
- context,
184
- next: async (...[nextOptions]) => {
185
- const nextContext = nextOptions?.context ?? {};
186
- return {
187
- output: await next(index + 1, mergeCurrentContext(context, nextContext), currentInput),
188
- context: nextContext
189
- };
218
+ const output = mid ? await runWithSpan(
219
+ { name: `middleware.${mid.name}`, signal: options.signal },
220
+ async (span) => {
221
+ span?.setAttribute("middleware.index", index);
222
+ span?.setAttribute("middleware.name", mid.name);
223
+ const result = await mid({
224
+ ...options,
225
+ context,
226
+ next: async (...[nextOptions]) => {
227
+ const nextContext = nextOptions?.context ?? {};
228
+ return {
229
+ output: await next(index + 1, mergeCurrentContext(context, nextContext), currentInput),
230
+ context: nextContext
231
+ };
232
+ }
233
+ }, currentInput, middlewareOutputFn);
234
+ return result.output;
190
235
  }
191
- }, currentInput, middlewareOutputFn)).output : await procedure["~orpc"].handler({ ...options, context, input: currentInput });
236
+ ) : await runWithSpan(
237
+ { name: "handler", signal: options.signal },
238
+ () => procedure["~orpc"].handler({ ...options, context, input: currentInput })
239
+ );
192
240
  if (index === outputValidationIndex) {
193
241
  return await validateOutput(procedure, output);
194
242
  }
@@ -361,7 +409,8 @@ function createContractedProcedure(procedure, contract) {
361
409
  });
362
410
  }
363
411
  function call(procedure, input, ...rest) {
364
- return createProcedureClient(procedure, ...rest)(input);
412
+ const options = resolveMaybeOptionalOptions(rest);
413
+ return createProcedureClient(procedure, options)(input, options);
365
414
  }
366
415
 
367
416
  export { LAZY_SYMBOL as L, Procedure as P, createContractedProcedure as a, addMiddleware as b, createProcedureClient as c, isLazy as d, enhanceRouter as e, createAssertedLazyProcedure as f, getRouter as g, createORPCErrorConstructorMap as h, isProcedure as i, getLazyMeta as j, middlewareOutputFn as k, lazy as l, mergeCurrentContext as m, isStartWithMiddlewares as n, mergeMiddlewares as o, call as p, getHiddenRouterContract as q, createAccessibleLazyRouter as r, setHiddenRouterContract as s, traverseContractProcedures as t, unlazy as u, validateORPCError as v, resolveContractProcedures as w, unlazyRouter as x };
@@ -0,0 +1,12 @@
1
+ import { C as Context } from './server.CYNGeoCm.js';
2
+ import { b as StandardHandleOptions } from './server.Bmh5xd4n.js';
3
+
4
+ type FriendlyStandardHandleOptions<T extends Context> = Omit<StandardHandleOptions<T>, 'context'> & (Record<never, never> extends T ? {
5
+ context?: T;
6
+ } : {
7
+ context: T;
8
+ });
9
+ declare function resolveFriendlyStandardHandleOptions<T extends Context>(options: FriendlyStandardHandleOptions<T>): StandardHandleOptions<T>;
10
+
11
+ export { resolveFriendlyStandardHandleOptions as r };
12
+ export type { FriendlyStandardHandleOptions as F };
@@ -0,0 +1,12 @@
1
+ import { C as Context } from './server.CYNGeoCm.mjs';
2
+ import { b as StandardHandleOptions } from './server.gqRxT-yN.mjs';
3
+
4
+ type FriendlyStandardHandleOptions<T extends Context> = Omit<StandardHandleOptions<T>, 'context'> & (Record<never, never> extends T ? {
5
+ context?: T;
6
+ } : {
7
+ context: T;
8
+ });
9
+ declare function resolveFriendlyStandardHandleOptions<T extends Context>(options: FriendlyStandardHandleOptions<T>): StandardHandleOptions<T>;
10
+
11
+ export { resolveFriendlyStandardHandleOptions as r };
12
+ export type { FriendlyStandardHandleOptions as F };