@orpc/server 0.0.0-next.4a7a06a → 0.0.0-next.4b3a4c5

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 +46 -0
  3. package/dist/adapters/aws-lambda/index.d.ts +46 -0
  4. package/dist/adapters/aws-lambda/index.mjs +42 -0
  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 +56 -10
  12. package/dist/adapters/fetch/index.d.ts +56 -10
  13. package/dist/adapters/fetch/index.mjs +74 -4
  14. package/dist/adapters/message-port/index.d.mts +31 -0
  15. package/dist/adapters/message-port/index.d.ts +31 -0
  16. package/dist/adapters/message-port/index.mjs +39 -0
  17. package/dist/adapters/node/index.d.mts +32 -10
  18. package/dist/adapters/node/index.d.ts +32 -10
  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 +24 -9
  41. package/dist/plugins/index.d.mts +28 -15
  42. package/dist/plugins/index.d.ts +28 -15
  43. package/dist/plugins/index.mjs +94 -60
  44. package/dist/shared/{server.4FnxLwwr.mjs → server.2SSWGLDL.mjs} +75 -42
  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.BU4WI18A.d.mts +32 -0
  48. package/dist/shared/{server.YZzrREz9.d.ts → server.Bmh5xd4n.d.ts} +8 -8
  49. package/dist/shared/{server.DPWk5pjW.d.mts → server.CYNGeoCm.d.mts} +10 -8
  50. package/dist/shared/{server.DPWk5pjW.d.ts → server.CYNGeoCm.d.ts} +10 -8
  51. package/dist/shared/server.D0H-iaY3.d.ts +32 -0
  52. package/dist/shared/{server.BVwwTHyO.mjs → server.DZ5BIITo.mjs} +1 -1
  53. package/dist/shared/server.DhJj-1X9.d.mts +42 -0
  54. package/dist/shared/{server.DG7Tamti.mjs → server.Dp6pyBjF.mjs} +114 -57
  55. package/dist/shared/server.UVMTOWrk.mjs +26 -0
  56. package/dist/shared/{server.eWLxY3lq.d.mts → server.gqRxT-yN.d.mts} +8 -8
  57. package/dist/shared/server.jMTkVNIb.d.ts +42 -0
  58. package/package.json +40 -12
  59. package/dist/shared/server.BRoxSiSC.d.mts +0 -12
  60. package/dist/shared/server.BjiJH9Vo.d.ts +0 -10
  61. package/dist/shared/server.Cy1vfSiG.d.ts +0 -12
  62. package/dist/shared/server.QUe9N8P4.d.mts +0 -10
package/dist/index.mjs CHANGED
@@ -1,10 +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.Dp6pyBjF.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.Dp6pyBjF.mjs';
5
5
  import { toORPCError } from '@orpc/client';
6
6
  export { ORPCError, isDefinedError, safe } from '@orpc/client';
7
- export { onError, onFinish, onStart, onSuccess } from '@orpc/shared';
7
+ import { resolveMaybeOptionalOptions } from '@orpc/shared';
8
+ export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
8
9
  export { getEventMeta, withEventMeta } from '@orpc/standard-server';
9
10
 
10
11
  const DEFAULT_CONFIG = {
@@ -20,7 +21,7 @@ function fallbackConfig(key, value) {
20
21
  }
21
22
 
22
23
  function decorateMiddleware(middleware) {
23
- const decorated = (...args) => middleware(...args);
24
+ const decorated = ((...args) => middleware(...args));
24
25
  decorated.mapInput = (mapInput) => {
25
26
  const mapped = decorateMiddleware(
26
27
  (options, input, ...rest) => middleware(options, mapInput(input), ...rest)
@@ -150,7 +151,7 @@ class Builder {
150
151
  /**
151
152
  * Sets or overrides the config.
152
153
  *
153
- * @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}
154
155
  * @see {@link https://orpc.unnoq.com/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
155
156
  */
156
157
  $config(config) {
@@ -447,12 +448,26 @@ function implement(contract, config = {}) {
447
448
  return impl;
448
449
  }
449
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
+
450
464
  function createRouterClient(router, ...rest) {
465
+ const options = resolveMaybeOptionalOptions(rest);
451
466
  if (isProcedure(router)) {
452
- const caller = createProcedureClient(router, ...rest);
467
+ const caller = createProcedureClient(router, options);
453
468
  return caller;
454
469
  }
455
- const procedureCaller = isLazy(router) ? createProcedureClient(createAssertedLazyProcedure(router), ...rest) : {};
470
+ const procedureCaller = isLazy(router) ? createProcedureClient(createAssertedLazyProcedure(router), options) : {};
456
471
  const recursive = new Proxy(procedureCaller, {
457
472
  get(target, key) {
458
473
  if (typeof key !== "string") {
@@ -471,4 +486,4 @@ function createRouterClient(router, ...rest) {
471
486
  return recursive;
472
487
  }
473
488
 
474
- 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
- import { Value } from '@orpc/shared';
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.eWLxY3lq.mjs';
5
- import { C as Context, F as ProcedureClientInterceptorOptions } from '../shared/server.DPWk5pjW.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
 
@@ -12,7 +12,7 @@ interface BatchHandlerOptions<T extends Context> {
12
12
  *
13
13
  * @default 10
14
14
  */
15
- maxSize?: Value<number, [StandardHandlerInterceptorOptions<T>]>;
15
+ maxSize?: Value<Promisable<number>, [StandardHandlerInterceptorOptions<T>]>;
16
16
  /**
17
17
  * Map the request before processing it.
18
18
  *
@@ -24,19 +24,19 @@ interface BatchHandlerOptions<T extends Context> {
24
24
  *
25
25
  * @default 207
26
26
  */
27
- successStatus?: Value<number, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
27
+ successStatus?: Value<Promisable<number>, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
28
28
  /**
29
29
  * success batch response headers.
30
30
  *
31
31
  * @default {}
32
32
  */
33
- headers?: Value<StandardHeaders, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
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;
@@ -49,8 +49,8 @@ declare class BatchHandlerPlugin<T extends Context> implements StandardHandlerPl
49
49
  }
50
50
 
51
51
  interface CORSOptions<T extends Context> {
52
- origin?: Value<string | readonly string[] | null | undefined, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
53
- timingOrigin?: Value<string | readonly string[] | null | undefined, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
52
+ origin?: Value<Promisable<string | readonly string[] | null | undefined>, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
53
+ timingOrigin?: Value<Promisable<string | readonly string[] | null | undefined>, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
54
54
  allowMethods?: readonly string[];
55
55
  allowHeaders?: readonly string[];
56
56
  maxAge?: number;
@@ -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
  }
@@ -88,21 +101,21 @@ interface SimpleCsrfProtectionHandlerPluginOptions<T extends Context> {
88
101
  *
89
102
  * @default 'x-csrf-token'
90
103
  */
91
- headerName?: Value<string, [options: StandardHandlerInterceptorOptions<T>]>;
104
+ headerName?: Value<Promisable<string>, [options: StandardHandlerInterceptorOptions<T>]>;
92
105
  /**
93
106
  * The value of the header to check.
94
107
  *
95
108
  * @default 'orpc'
96
109
  *
97
110
  */
98
- headerValue?: Value<string, [options: StandardHandlerInterceptorOptions<T>]>;
111
+ headerValue?: Value<Promisable<string>, [options: StandardHandlerInterceptorOptions<T>]>;
99
112
  /**
100
113
  * Exclude a procedure from the plugin.
101
114
  *
102
115
  * @default false
103
116
  *
104
117
  */
105
- exclude?: Value<boolean, [options: ProcedureClientInterceptorOptions<T, Record<never, never>, Meta>]>;
118
+ exclude?: Value<Promisable<boolean>, [options: ProcedureClientInterceptorOptions<T, Record<never, never>, Meta>]>;
106
119
  /**
107
120
  * The error thrown when the CSRF token is invalid.
108
121
  *
@@ -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
- import { Value } from '@orpc/shared';
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.YZzrREz9.js';
5
- import { C as Context, F as ProcedureClientInterceptorOptions } from '../shared/server.DPWk5pjW.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
 
@@ -12,7 +12,7 @@ interface BatchHandlerOptions<T extends Context> {
12
12
  *
13
13
  * @default 10
14
14
  */
15
- maxSize?: Value<number, [StandardHandlerInterceptorOptions<T>]>;
15
+ maxSize?: Value<Promisable<number>, [StandardHandlerInterceptorOptions<T>]>;
16
16
  /**
17
17
  * Map the request before processing it.
18
18
  *
@@ -24,19 +24,19 @@ interface BatchHandlerOptions<T extends Context> {
24
24
  *
25
25
  * @default 207
26
26
  */
27
- successStatus?: Value<number, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
27
+ successStatus?: Value<Promisable<number>, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
28
28
  /**
29
29
  * success batch response headers.
30
30
  *
31
31
  * @default {}
32
32
  */
33
- headers?: Value<StandardHeaders, [responses: Promise<BatchResponseBodyItem>[], batchOptions: StandardHandlerInterceptorOptions<T>]>;
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;
@@ -49,8 +49,8 @@ declare class BatchHandlerPlugin<T extends Context> implements StandardHandlerPl
49
49
  }
50
50
 
51
51
  interface CORSOptions<T extends Context> {
52
- origin?: Value<string | readonly string[] | null | undefined, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
53
- timingOrigin?: Value<string | readonly string[] | null | undefined, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
52
+ origin?: Value<Promisable<string | readonly string[] | null | undefined>, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
53
+ timingOrigin?: Value<Promisable<string | readonly string[] | null | undefined>, [origin: string, options: StandardHandlerInterceptorOptions<T>]>;
54
54
  allowMethods?: readonly string[];
55
55
  allowHeaders?: readonly string[];
56
56
  maxAge?: number;
@@ -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
  }
@@ -88,21 +101,21 @@ interface SimpleCsrfProtectionHandlerPluginOptions<T extends Context> {
88
101
  *
89
102
  * @default 'x-csrf-token'
90
103
  */
91
- headerName?: Value<string, [options: StandardHandlerInterceptorOptions<T>]>;
104
+ headerName?: Value<Promisable<string>, [options: StandardHandlerInterceptorOptions<T>]>;
92
105
  /**
93
106
  * The value of the header to check.
94
107
  *
95
108
  * @default 'orpc'
96
109
  *
97
110
  */
98
- headerValue?: Value<string, [options: StandardHandlerInterceptorOptions<T>]>;
111
+ headerValue?: Value<Promisable<string>, [options: StandardHandlerInterceptorOptions<T>]>;
99
112
  /**
100
113
  * Exclude a procedure from the plugin.
101
114
  *
102
115
  * @default false
103
116
  *
104
117
  */
105
- exclude?: Value<boolean, [options: ProcedureClientInterceptorOptions<T, Record<never, never>, Meta>]>;
118
+ exclude?: Value<Promisable<boolean>, [options: ProcedureClientInterceptorOptions<T, Record<never, never>, Meta>]>;
106
119
  /**
107
120
  * The error thrown when the CSRF token is invalid.
108
121
  *
@@ -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,8 +1,8 @@
1
1
  import { toHttpPath, StandardRPCJsonSerializer, StandardRPCSerializer } from '@orpc/client/standard';
2
2
  import { ORPCError, toORPCError } from '@orpc/client';
3
- import { toArray, intercept, parseEmptyableJSON } from '@orpc/shared';
3
+ import { toArray, intercept, runWithSpan, ORPC_NAME, isAsyncIteratorObject, asyncIteratorWithSpan, setSpanError, parseEmptyableJSON, NullProtoObj, value } from '@orpc/shared';
4
4
  import { flattenHeader } from '@orpc/standard-server';
5
- import { c as createProcedureClient, t as traverseContractProcedures, i as isProcedure, u as unlazy, g as getRouter, a as createContractedProcedure } from './server.DG7Tamti.mjs';
5
+ import { c as createProcedureClient, t as traverseContractProcedures, i as isProcedure, u as unlazy, g as getRouter, a as createContractedProcedure } from './server.Dp6pyBjF.mjs';
6
6
 
7
7
  class CompositeStandardHandlerPlugin {
8
8
  plugins;
@@ -39,49 +39,74 @@ class StandardHandler {
39
39
  this.rootInterceptors,
40
40
  { ...options, request, prefix },
41
41
  async (interceptorOptions) => {
42
- let isDecoding = false;
43
- try {
44
- return await intercept(
45
- this.interceptors,
46
- interceptorOptions,
47
- async ({ request: request2, context, prefix: prefix2 }) => {
48
- const method = request2.method;
49
- const url = request2.url;
50
- const pathname = prefix2 ? url.pathname.replace(prefix2, "") : url.pathname;
51
- const match = await this.matcher.match(method, `/${pathname.replace(/^\/|\/$/g, "")}`);
52
- if (!match) {
53
- return { matched: false, response: void 0 };
42
+ return runWithSpan(
43
+ { name: `${request.method} ${request.url.pathname}` },
44
+ async (span) => {
45
+ let step;
46
+ try {
47
+ return await intercept(
48
+ this.interceptors,
49
+ interceptorOptions,
50
+ async ({ request: request2, context, prefix: prefix2 }) => {
51
+ const method = request2.method;
52
+ const url = request2.url;
53
+ const pathname = prefix2 ? url.pathname.replace(prefix2, "") : url.pathname;
54
+ const match = await runWithSpan(
55
+ { name: "find_procedure" },
56
+ () => this.matcher.match(method, `/${pathname.replace(/^\/|\/$/g, "")}`)
57
+ );
58
+ if (!match) {
59
+ return { matched: false, response: void 0 };
60
+ }
61
+ span?.updateName(`${ORPC_NAME}.${match.path.join("/")}`);
62
+ span?.setAttribute("rpc.system", ORPC_NAME);
63
+ span?.setAttribute("rpc.method", match.path.join("."));
64
+ step = "decode_input";
65
+ let input = await runWithSpan(
66
+ { name: "decode_input" },
67
+ () => this.codec.decode(request2, match.params, match.procedure)
68
+ );
69
+ step = void 0;
70
+ if (isAsyncIteratorObject(input)) {
71
+ input = asyncIteratorWithSpan(
72
+ { name: "consume_event_iterator_input", signal: request2.signal },
73
+ input
74
+ );
75
+ }
76
+ const client = createProcedureClient(match.procedure, {
77
+ context,
78
+ path: match.path,
79
+ interceptors: this.clientInterceptors
80
+ });
81
+ step = "call_procedure";
82
+ const output = await client(input, {
83
+ signal: request2.signal,
84
+ lastEventId: flattenHeader(request2.headers["last-event-id"])
85
+ });
86
+ step = void 0;
87
+ const response = this.codec.encode(output, match.procedure);
88
+ return {
89
+ matched: true,
90
+ response
91
+ };
92
+ }
93
+ );
94
+ } catch (e) {
95
+ if (step !== "call_procedure") {
96
+ setSpanError(span, e);
54
97
  }
55
- const client = createProcedureClient(match.procedure, {
56
- context,
57
- path: match.path,
58
- interceptors: this.clientInterceptors
59
- });
60
- isDecoding = true;
61
- const input = await this.codec.decode(request2, match.params, match.procedure);
62
- isDecoding = false;
63
- const output = await client(input, {
64
- signal: request2.signal,
65
- lastEventId: flattenHeader(request2.headers["last-event-id"])
66
- });
67
- const response = this.codec.encode(output, match.procedure);
98
+ const error = step === "decode_input" && !(e instanceof ORPCError) ? new ORPCError("BAD_REQUEST", {
99
+ message: `Malformed request. Ensure the request body is properly formatted and the 'Content-Type' header is set correctly.`,
100
+ cause: e
101
+ }) : toORPCError(e);
102
+ const response = this.codec.encodeError(error);
68
103
  return {
69
104
  matched: true,
70
105
  response
71
106
  };
72
107
  }
73
- );
74
- } catch (e) {
75
- const error = isDecoding && !(e instanceof ORPCError) ? new ORPCError("BAD_REQUEST", {
76
- message: `Malformed request. Ensure the request body is properly formatted and the 'Content-Type' header is set correctly.`,
77
- cause: e
78
- }) : toORPCError(e);
79
- const response = this.codec.encodeError(error);
80
- return {
81
- matched: true,
82
- response
83
- };
84
- }
108
+ }
109
+ );
85
110
  }
86
111
  );
87
112
  }
@@ -112,10 +137,18 @@ class StandardRPCCodec {
112
137
  }
113
138
 
114
139
  class StandardRPCMatcher {
115
- tree = {};
140
+ filter;
141
+ tree = new NullProtoObj();
116
142
  pendingRouters = [];
143
+ constructor(options = {}) {
144
+ this.filter = options.filter ?? true;
145
+ }
117
146
  init(router, path = []) {
118
- const laziedOptions = traverseContractProcedures({ router, path }, ({ path: path2, contract }) => {
147
+ const laziedOptions = traverseContractProcedures({ router, path }, (traverseOptions) => {
148
+ if (!value(this.filter, traverseOptions)) {
149
+ return;
150
+ }
151
+ const { path: path2, contract } = traverseOptions;
119
152
  const httpPath = toHttpPath(path2);
120
153
  if (isProcedure(contract)) {
121
154
  this.tree[httpPath] = {
@@ -177,7 +210,7 @@ class StandardRPCHandler extends StandardHandler {
177
210
  constructor(router, options = {}) {
178
211
  const jsonSerializer = new StandardRPCJsonSerializer(options);
179
212
  const serializer = new StandardRPCSerializer(jsonSerializer);
180
- const matcher = new StandardRPCMatcher();
213
+ const matcher = new StandardRPCMatcher(options);
181
214
  const codec = new StandardRPCCodec(serializer);
182
215
  super(router, matcher, codec, options);
183
216
  }
@@ -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 };