@orpc/server 2.0.0-beta.4 → 2.0.0-beta.41

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 (60) hide show
  1. package/README.md +97 -94
  2. package/dist/adapters/aws-lambda/index.d.mts +50 -0
  3. package/dist/adapters/aws-lambda/index.d.ts +50 -0
  4. package/dist/adapters/aws-lambda/index.mjs +39 -0
  5. package/dist/adapters/crossws/index.d.mts +21 -12
  6. package/dist/adapters/crossws/index.d.ts +21 -12
  7. package/dist/adapters/crossws/index.mjs +14 -10
  8. package/dist/adapters/fastify/index.d.mts +42 -0
  9. package/dist/adapters/fastify/index.d.ts +42 -0
  10. package/dist/adapters/fastify/index.mjs +39 -0
  11. package/dist/adapters/fetch/index.d.mts +21 -114
  12. package/dist/adapters/fetch/index.d.ts +21 -114
  13. package/dist/adapters/fetch/index.mjs +20 -182
  14. package/dist/adapters/message-port/index.d.mts +23 -20
  15. package/dist/adapters/message-port/index.d.ts +23 -20
  16. package/dist/adapters/message-port/index.mjs +31 -34
  17. package/dist/adapters/node/index.d.mts +19 -96
  18. package/dist/adapters/node/index.d.ts +19 -96
  19. package/dist/adapters/node/index.mjs +19 -157
  20. package/dist/adapters/standard/index.d.mts +91 -17
  21. package/dist/adapters/standard/index.d.ts +91 -17
  22. package/dist/adapters/standard/index.mjs +4 -4
  23. package/dist/adapters/standard-peer/index.d.mts +6 -11
  24. package/dist/adapters/standard-peer/index.d.ts +6 -11
  25. package/dist/adapters/standard-peer/index.mjs +10 -2
  26. package/dist/adapters/websocket/index.d.mts +45 -29
  27. package/dist/adapters/websocket/index.d.ts +45 -29
  28. package/dist/adapters/websocket/index.mjs +39 -28
  29. package/dist/extensions/callable.d.mts +5 -5
  30. package/dist/extensions/callable.d.ts +5 -5
  31. package/dist/extensions/callable.mjs +2 -2
  32. package/dist/helpers/index.d.mts +23 -6
  33. package/dist/helpers/index.d.ts +23 -6
  34. package/dist/helpers/index.mjs +13 -5
  35. package/dist/index.d.mts +332 -37
  36. package/dist/index.d.ts +332 -37
  37. package/dist/index.mjs +141 -65
  38. package/dist/plugins/index.d.mts +255 -31
  39. package/dist/plugins/index.d.ts +255 -31
  40. package/dist/plugins/index.mjs +559 -38
  41. package/dist/shared/server.1ExWFMze.mjs +69 -0
  42. package/dist/shared/{server.CjOb6ItT.mjs → server.AVQWL-DI.mjs} +1 -1
  43. package/dist/shared/{server.BL22TloH.d.mts → server.BEdOJs6S.d.mts} +41 -62
  44. package/dist/shared/{server.BL22TloH.d.ts → server.BEdOJs6S.d.ts} +41 -62
  45. package/dist/shared/{server.GDpX6Df8.mjs → server.BFEVk-EI.mjs} +164 -70
  46. package/dist/shared/{server.BwHnWUuN.mjs → server.BgvqVW_v.mjs} +25 -20
  47. package/dist/shared/server.BllfVJLm.d.mts +34 -0
  48. package/dist/shared/server.COfbQ0D8.d.ts +34 -0
  49. package/dist/shared/{server.DBANIheG.d.ts → server.CVO0hWyj.d.mts} +24 -13
  50. package/dist/shared/{server.BsNNjG5J.d.mts → server.DD1roZl9.d.mts} +32 -20
  51. package/dist/shared/server.DFEuNUt4.d.ts +14 -0
  52. package/dist/shared/{server.DJIkub_t.d.mts → server.DJNkZPfD.d.ts} +24 -13
  53. package/dist/shared/{server.Pa0F03f_.d.ts → server.DZeVx8K9.d.ts} +32 -20
  54. package/dist/shared/{server.CrlKQucM.mjs → server.FEqy7Hrj.mjs} +25 -53
  55. package/dist/shared/server.UG_xdTub.d.mts +14 -0
  56. package/package.json +48 -14
  57. package/dist/shared/server.CX4vUnDk.mjs +0 -11
  58. package/dist/shared/server.Cj5lgPuG.d.mts +0 -66
  59. package/dist/shared/server.D_QauotT.mjs +0 -30
  60. package/dist/shared/server.d_2NS3g5.d.ts +0 -66
@@ -1,8 +1,8 @@
1
1
  import { ORPCError, toORPCError, RPCSerializer, COMMON_ERROR_STATUS_MAP } from '@orpc/client';
2
- import { sortPlugins, getOpenTelemetryConfig, runWithSpan, toArray, matchesHttpPathPrefix, intercept, ORPC_NAME, isAsyncIteratorObject, override, traceAsyncIterator, recordSpanError, pathToHttpPath, normalizeHttpPath, value, parseEmptyableJSON } from '@orpc/shared';
3
- import { flattenStandardHeader, parseStandardUrl } from '@standardserver/core';
4
- import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.CrlKQucM.mjs';
5
- import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.BwHnWUuN.mjs';
2
+ import { sortPlugins, toArray, matchesHttpPathPrefix, value, intercept, getTracer, runWithSpan, ORPC_NAME, isAsyncIteratorObject, override, traceAsyncIterator, traceReadableStream, recordSpanError, wrapAsyncIterator, toTracingException, wrapReadableStream, pathToHttpPath, normalizeHttpPath, parseEmptyableJSON, getOwn } from '@orpc/shared';
3
+ import { flattenStandardHeader, parseStandardUrl, ErrorEvent } from '@standard-server/core';
4
+ import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.FEqy7Hrj.mjs';
5
+ import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.BgvqVW_v.mjs';
6
6
 
7
7
  class CompositeStandardHandlerPlugin {
8
8
  name = "~composite";
@@ -24,8 +24,8 @@ class StandardHandler {
24
24
  constructor(codec, options) {
25
25
  this.codec = codec;
26
26
  options = new CompositeStandardHandlerPlugin([
27
- new OtelHandlerPlugin(),
28
- ...toArray(options.plugins)
27
+ ...toArray(options.plugins),
28
+ new TracingHandlerPlugin()
29
29
  ]).init(options);
30
30
  this.routingInterceptors = options.routingInterceptors;
31
31
  this.interceptors = options.interceptors;
@@ -34,15 +34,17 @@ class StandardHandler {
34
34
  routingInterceptors;
35
35
  interceptors;
36
36
  clientInterceptors;
37
- async handle(request, { context, prefix }) {
37
+ async handle(request, options) {
38
+ const { prefix } = options;
38
39
  if (prefix && !matchesHttpPathPrefix(request.url, prefix)) {
39
40
  return { matched: false, response: void 0 };
40
41
  }
42
+ const context = await value(options.context, request);
41
43
  return intercept(
42
44
  this.routingInterceptors,
43
45
  { context, prefix, request },
44
46
  async ({ context: context2, prefix: prefix2, request: request2 }) => {
45
- const span = getOpenTelemetryConfig()?.trace.getActiveSpan();
47
+ const span = getTracer()?.getActiveSpan();
46
48
  let step;
47
49
  const matchedOrNot = await runWithSpan("find_procedure", () => this.codec.resolveProcedure(request2, { context: context2, prefix: prefix2 }));
48
50
  if (!matchedOrNot) {
@@ -63,8 +65,10 @@ class StandardHandler {
63
65
  step = "decode_input";
64
66
  let input = await runWithSpan("decode_input", decodeInput2);
65
67
  step = void 0;
66
- if (isAsyncIteratorObject(input)) {
67
- input = override(input, traceAsyncIterator("consume_event_iterator_input", input));
68
+ if (getTracer() && isAsyncIteratorObject(input)) {
69
+ input = override(input, traceAsyncIterator("consume_async_iterator_object_input", input));
70
+ } else if (getTracer() && input instanceof ReadableStream) {
71
+ input = override(input, traceReadableStream("consume_octet_stream_input", input));
68
72
  }
69
73
  const client = createProcedureClient(procedure2, {
70
74
  context: context3,
@@ -97,23 +101,80 @@ class StandardHandler {
97
101
  );
98
102
  }
99
103
  }
100
- class OtelHandlerPlugin {
101
- name = "~opentelemetry";
104
+ class TracingHandlerPlugin {
105
+ name = "~tracing";
102
106
  init(options) {
103
107
  return {
104
108
  ...options,
105
109
  routingInterceptors: [
106
- // Should be placed before user-provided interceptors to help them access the current active context.
110
+ // Should be placed before user-provided interceptors to help them access the current active span.
107
111
  async ({ next, request }) => {
108
- const otelConfig = getOpenTelemetryConfig();
109
- let propagationContext;
110
- if (otelConfig?.propagation) {
111
- propagationContext = otelConfig.propagation.extract(otelConfig.context.active(), request.headers);
112
+ const tracer = getTracer();
113
+ if (!tracer) {
114
+ return next();
112
115
  }
113
- return runWithSpan(
114
- { name: `${request.method} ${request.url}`, context: propagationContext },
115
- () => next()
116
- );
116
+ const parent = tracer.extract?.(request.headers);
117
+ const [pathname] = parseStandardUrl(request.url);
118
+ return tracer.startActiveSpan(`${request.method} ${pathname}`, parent, async (span) => {
119
+ try {
120
+ const result = await next();
121
+ if (!result.matched) {
122
+ span.end();
123
+ return result;
124
+ }
125
+ const body = result.response.body;
126
+ if (isAsyncIteratorObject(body)) {
127
+ return {
128
+ ...result,
129
+ response: {
130
+ ...result.response,
131
+ /**
132
+ * @remarks
133
+ * **Warning**: Remember use `override` for remaining special properties
134
+ */
135
+ body: override(body, wrapAsyncIterator(body, {
136
+ runWith: (fn) => tracer.withActiveSpan(span, fn),
137
+ onError(error) {
138
+ if (!(error instanceof ErrorEvent)) {
139
+ span.recordException("error", toTracingException(error));
140
+ }
141
+ },
142
+ onFinish() {
143
+ span.end();
144
+ }
145
+ }))
146
+ }
147
+ };
148
+ }
149
+ if (body instanceof ReadableStream) {
150
+ return {
151
+ ...result,
152
+ response: {
153
+ ...result.response,
154
+ /**
155
+ * @remarks
156
+ * **Warning**: Remember use `override` for remaining special properties
157
+ */
158
+ body: override(body, wrapReadableStream(body, {
159
+ runWith: (fn) => tracer.withActiveSpan(span, fn),
160
+ onError(error) {
161
+ span.recordException("error", toTracingException(error));
162
+ },
163
+ onFinish() {
164
+ span.end();
165
+ }
166
+ }))
167
+ }
168
+ };
169
+ }
170
+ span.end();
171
+ return result;
172
+ } catch (e) {
173
+ span.recordException("error", toTracingException(e));
174
+ span.end();
175
+ throw e;
176
+ }
177
+ });
117
178
  },
118
179
  ...toArray(options.routingInterceptors)
119
180
  ]
@@ -121,13 +182,22 @@ class OtelHandlerPlugin {
121
182
  }
122
183
  }
123
184
 
185
+ const RPC_DEFAULT_ALLOW_METHODS = ["POST", "PUT", "PATCH", "DELETE"];
124
186
  class RPCMatcher {
125
187
  filter;
188
+ allowMethodsSet;
189
+ allowMethodsFn;
126
190
  rootRouter;
127
191
  tree = /* @__PURE__ */ new Map();
128
- pendingLazyRouters = [];
192
+ pendingLazyRouters = /* @__PURE__ */ new Map();
129
193
  constructor(router, options = {}) {
130
194
  this.filter = options.filter ?? true;
195
+ const allowMethods = options.allowMethods ?? RPC_DEFAULT_ALLOW_METHODS;
196
+ if (typeof allowMethods !== "function") {
197
+ this.allowMethodsSet = new Set(allowMethods);
198
+ } else {
199
+ this.allowMethodsFn = allowMethods;
200
+ }
131
201
  this.rootRouter = router;
132
202
  this.index(router);
133
203
  }
@@ -136,30 +206,20 @@ class RPCMatcher {
136
206
  if (!value(this.filter, procedure, procedurePath)) {
137
207
  return;
138
208
  }
139
- const httpPath = pathToHttpPath(procedurePath);
140
- if (procedure instanceof Procedure) {
141
- this.tree.set(httpPath, {
142
- path: procedurePath,
143
- contract: procedure,
144
- procedure
145
- });
146
- } else {
147
- this.tree.set(httpPath, {
148
- path: procedurePath,
149
- contract: procedure
150
- });
151
- }
209
+ this.tree.set(pathToHttpPath(procedurePath), {
210
+ path: procedurePath,
211
+ contract: procedure,
212
+ // contract-first entries have no implementation yet, resolveProcedure fills it in on demand
213
+ procedure: procedure instanceof Procedure ? procedure : void 0
214
+ });
152
215
  }, path);
153
- this.pendingLazyRouters.push(
154
- ...lazyResults.map((result) => ({
155
- ...result,
156
- httpPathPrefix: pathToHttpPath(result.path)
157
- }))
158
- );
216
+ for (const result of lazyResults) {
217
+ this.pendingLazyRouters.set(pathToHttpPath(result.path), result);
218
+ }
159
219
  }
160
- async match(_method, pathname, prefix) {
161
- if (pathname.length > 1 && pathname.endsWith("/")) {
162
- pathname = pathname.slice(0, -1);
220
+ async match(method, pathname, prefix) {
221
+ if (this.allowMethodsSet && !this.allowMethodsSet.has(method)) {
222
+ return void 0;
163
223
  }
164
224
  if (prefix) {
165
225
  if (!pathname.startsWith(prefix)) {
@@ -176,40 +236,74 @@ class RPCMatcher {
176
236
  return void 0;
177
237
  }
178
238
  }
179
- const result = await this.matchPathname(pathname);
180
- if (!result && pathname.includes("%")) {
181
- return this.matchPathname(normalizeHttpPath(pathname));
239
+ if (pathname.length > 1 && pathname.endsWith("/")) {
240
+ pathname = pathname.slice(0, -1);
182
241
  }
183
- return result;
184
- }
185
- async matchPathname(pathname) {
186
- await this.resolvePendingLazyRouters(pathname);
187
- const entry = this.tree.get(pathname);
188
- if (!entry) {
242
+ const loading = this.resolvePendingLazyRouters(pathname);
243
+ if (loading !== void 0) {
244
+ await loading;
245
+ }
246
+ let entry = this.tree.get(pathname);
247
+ if (entry === void 0 && pathname.includes("%")) {
248
+ const normalizedPathname = normalizeHttpPath(pathname);
249
+ const normalizedLoading = this.resolvePendingLazyRouters(normalizedPathname);
250
+ if (normalizedLoading !== void 0) {
251
+ await normalizedLoading;
252
+ }
253
+ entry = this.tree.get(normalizedPathname);
254
+ }
255
+ if (entry === void 0) {
256
+ return void 0;
257
+ }
258
+ const procedure = entry.procedure ?? await this.resolveProcedure(entry);
259
+ if (this.allowMethodsFn && !this.allowMethodsFn(method, procedure, entry.path)) {
189
260
  return void 0;
190
261
  }
191
- const procedure = await this.resolveProcedure(entry);
192
- return { path: entry.path, procedure };
262
+ return {
263
+ path: entry.path,
264
+ procedure
265
+ };
193
266
  }
194
- async resolvePendingLazyRouters(pathname) {
195
- if (!this.pendingLazyRouters.length) {
267
+ resolvePendingLazyRouters(pathname) {
268
+ if (this.pendingLazyRouters.size === 0) {
196
269
  return;
197
270
  }
198
- const stillPending = [];
199
- for (const pending of this.pendingLazyRouters) {
200
- if (pathname.startsWith(pending.httpPathPrefix)) {
201
- const { default: router } = await unlazy(pending.router);
202
- this.index(router, pending.path);
203
- } else {
204
- stillPending.push(pending);
271
+ let slashIndex = 0;
272
+ while (slashIndex !== -1) {
273
+ const nextSlashIndex = pathname.indexOf("/", slashIndex + 1);
274
+ const httpPathPrefix = nextSlashIndex === -1 ? pathname : pathname.slice(0, nextSlashIndex);
275
+ if (this.pendingLazyRouters.has(httpPathPrefix)) {
276
+ return this.loadPendingLazyRouters(pathname, slashIndex);
205
277
  }
278
+ slashIndex = nextSlashIndex;
206
279
  }
207
- this.pendingLazyRouters = stillPending;
208
280
  }
209
- async resolveProcedure(entry) {
210
- if (entry.procedure) {
211
- return entry.procedure;
281
+ async loadPendingLazyRouters(pathname, slashIndex) {
282
+ while (slashIndex !== -1) {
283
+ const nextSlashIndex = pathname.indexOf("/", slashIndex + 1);
284
+ const httpPathPrefix = nextSlashIndex === -1 ? pathname : pathname.slice(0, nextSlashIndex);
285
+ const pending = this.pendingLazyRouters.get(httpPathPrefix);
286
+ if (pending !== void 0) {
287
+ await this.loadPendingLazyRouter(httpPathPrefix, pending);
288
+ }
289
+ slashIndex = nextSlashIndex;
290
+ }
291
+ }
292
+ loadPendingLazyRouter(httpPathPrefix, pending) {
293
+ if (pending.loading === void 0) {
294
+ pending.loading = this.indexPendingLazyRouter(httpPathPrefix, pending).catch((error) => {
295
+ pending.loading = void 0;
296
+ throw error;
297
+ });
212
298
  }
299
+ return pending.loading;
300
+ }
301
+ async indexPendingLazyRouter(httpPathPrefix, pending) {
302
+ const { default: router } = await unlazy(pending.router);
303
+ this.index(router, pending.path);
304
+ this.pendingLazyRouters.delete(httpPathPrefix);
305
+ }
306
+ async resolveProcedure(entry) {
213
307
  const { default: maybeProcedure } = await unlazy(getRouter(this.rootRouter, entry.path));
214
308
  if (!(maybeProcedure instanceof Procedure)) {
215
309
  throw new TypeError(
@@ -259,7 +353,7 @@ class RPCHandlerCodec {
259
353
  };
260
354
  }
261
355
  encodeError(error, _procedure, _path, _options) {
262
- const status = this.errorStatusMap[error.code] ?? DEFAULT_ERROR_STATUS;
356
+ const status = getOwn(this.errorStatusMap, error.code) ?? DEFAULT_ERROR_STATUS;
263
357
  return {
264
358
  headers: {},
265
359
  status,
@@ -268,4 +362,4 @@ class RPCHandlerCodec {
268
362
  }
269
363
  }
270
364
 
271
- export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, RPCHandlerCodec as R, StandardHandler as S, RPCMatcher as a };
365
+ export { CompositeStandardHandlerPlugin as C, RPCHandlerCodec as R, StandardHandler as S, TracingHandlerPlugin as T, RPCMatcher as a, RPC_DEFAULT_ALLOW_METHODS as b };
@@ -1,6 +1,6 @@
1
- import { c as createProcedureClient, P as Procedure, L as Lazy, u as unlazy } from './server.CrlKQucM.mjs';
1
+ import { c as createProcedureClient, P as Procedure, L as Lazy, u as unlazy } from './server.FEqy7Hrj.mjs';
2
2
  import { resolveMetaPlugins, mergeErrorMap, ProcedureContract } from '@orpc/contract';
3
- import { getOrBind, isTypescriptObject } from '@orpc/shared';
3
+ import { omit, isTypescriptObject, getOwn } from '@orpc/shared';
4
4
 
5
5
  const DEFAULT_SUCCESS_STATUS = 200;
6
6
  const DEFAULT_ERROR_STATUS = 500;
@@ -44,7 +44,7 @@ function withHiddenRouterContract(router, contract) {
44
44
  if (key === HIDDEN_ROUTER_CONTRACT_SYMBOL) {
45
45
  return contract;
46
46
  }
47
- return getOrBind(target, key);
47
+ return Reflect.get(target, key);
48
48
  }
49
49
  });
50
50
  }
@@ -77,6 +77,7 @@ function augmentRouter(router, options) {
77
77
  router["~orpc"].metaPlugins
78
78
  );
79
79
  const enhanced2 = new Procedure({
80
+ ...omit(options, ["middlewares", "errorMap", "meta", "metaPlugins"]),
80
81
  ...router["~orpc"],
81
82
  meta,
82
83
  metaPlugins,
@@ -92,8 +93,8 @@ function augmentRouter(router, options) {
92
93
  return router;
93
94
  }
94
95
  const enhanced = {};
95
- for (const key in router) {
96
- enhanced[key] = augmentRouter(router[key], options);
96
+ for (const [key, child] of Object.entries(router)) {
97
+ enhanced[key] = augmentRouter(child, options);
97
98
  }
98
99
  return enhanced;
99
100
  }
@@ -111,6 +112,7 @@ function augmentImplementedRouter(router, options) {
111
112
  }
112
113
  if (router instanceof Procedure) {
113
114
  const enhanced2 = new Procedure({
115
+ ...omit(options, ["middlewares"]),
114
116
  ...router["~orpc"],
115
117
  orderedMiddlewares: [
116
118
  ...options.middlewares.map((middleware) => ({ middleware, inputSchemasLengthAtUse: 0, outputSchemasLengthAtUse: 0 })),
@@ -123,8 +125,8 @@ function augmentImplementedRouter(router, options) {
123
125
  return router;
124
126
  }
125
127
  const enhanced = {};
126
- for (const key in router) {
127
- enhanced[key] = augmentImplementedRouter(router[key], options);
128
+ for (const [key, child] of Object.entries(router)) {
129
+ enhanced[key] = augmentImplementedRouter(child, options);
128
130
  }
129
131
  return enhanced;
130
132
  }
@@ -139,7 +141,7 @@ function getRouter(router, path) {
139
141
  return void 0;
140
142
  }
141
143
  if (!(current instanceof Lazy)) {
142
- current = current[segment];
144
+ current = getOwn(current, segment);
143
145
  continue;
144
146
  }
145
147
  const lazied = current;
@@ -159,27 +161,31 @@ function getRouter(router, path) {
159
161
  return current;
160
162
  }
161
163
  function walkProcedureContractsSync(router, callback, path = []) {
164
+ const lazyResults = [];
165
+ walkProcedureContractsSyncInternal(router, callback, path.slice(), lazyResults);
166
+ return lazyResults;
167
+ }
168
+ function walkProcedureContractsSyncInternal(router, callback, path, lazyResults) {
162
169
  const hiddenContract = getHiddenRouterContract(router);
163
170
  if (hiddenContract !== void 0) {
164
171
  router = hiddenContract;
165
172
  }
166
173
  if (router instanceof ProcedureContract) {
167
- callback(router, path);
168
- return [];
174
+ callback(router, path.slice());
175
+ return;
169
176
  }
170
177
  if (!isTypescriptObject(router)) {
171
- return [];
178
+ return;
172
179
  }
173
- const lazyResults = [];
174
- for (const key in router) {
175
- const value = router[key];
180
+ for (const [key, value] of Object.entries(router)) {
181
+ path.push(key);
176
182
  if (value instanceof Lazy) {
177
- lazyResults.push({ router: value, path: [...path, key] });
183
+ lazyResults.push({ router: value, path: path.slice() });
178
184
  } else {
179
- lazyResults.push(...walkProcedureContractsSync(value, callback, [...path, key]));
185
+ walkProcedureContractsSyncInternal(value, callback, path, lazyResults);
180
186
  }
187
+ path.pop();
181
188
  }
182
- return lazyResults;
183
189
  }
184
190
  async function walkProcedureContractsAsync(router, callback, path = []) {
185
191
  const hiddenContract = getHiddenRouterContract(router);
@@ -193,8 +199,7 @@ async function walkProcedureContractsAsync(router, callback, path = []) {
193
199
  if (!isTypescriptObject(router)) {
194
200
  return;
195
201
  }
196
- for (const key in router) {
197
- const value = router[key];
202
+ for (const [key, value] of Object.entries(router)) {
198
203
  if (value instanceof Lazy) {
199
204
  const { default: router2 } = await unlazy(value);
200
205
  await walkProcedureContractsAsync(router2, callback, [...path, key]);
@@ -211,7 +216,7 @@ async function unlazyRouter(router) {
211
216
  return router;
212
217
  }
213
218
  const unlazied = {};
214
- for (const key in router) {
219
+ for (const key of Object.keys(router)) {
215
220
  const item = router[key];
216
221
  const { default: unlaziedRouter } = await unlazy(item);
217
222
  unlazied[key] = await unlazyRouter(unlaziedRouter);
@@ -0,0 +1,34 @@
1
+ import { C as Context } from './server.BEdOJs6S.mjs';
2
+ import { b as StandardHandlerPlugin, c as StandardHandlerOptions } from './server.CVO0hWyj.mjs';
3
+
4
+ interface RequestLimitHandlerPluginOptions {
5
+ /**
6
+ * The maximum allowed request body size in bytes.
7
+ */
8
+ maxBodySize: number;
9
+ }
10
+ /**
11
+ * Rejects requests whose body exceeds `maxBodySize`.
12
+ *
13
+ * When used with the request compression plugin, the limit applies to the
14
+ * decompressed payload rather than the compressed wire size.
15
+ *
16
+ * @see {@link https://orpc.dev/docs/plugins/request-limit | Request Limit Plugin}
17
+ */
18
+ declare class RequestLimitHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
19
+ name: string;
20
+ /**
21
+ * Should limit the original batch request body instead of sub-requests.
22
+ */
23
+ after: string[];
24
+ /**
25
+ * Should limit the final body size instead of the compressed one.
26
+ */
27
+ before: string[];
28
+ private readonly maxBodySize;
29
+ constructor(options: RequestLimitHandlerPluginOptions);
30
+ init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
31
+ }
32
+
33
+ export { RequestLimitHandlerPlugin as R };
34
+ export type { RequestLimitHandlerPluginOptions as a };
@@ -0,0 +1,34 @@
1
+ import { C as Context } from './server.BEdOJs6S.js';
2
+ import { b as StandardHandlerPlugin, c as StandardHandlerOptions } from './server.DJNkZPfD.js';
3
+
4
+ interface RequestLimitHandlerPluginOptions {
5
+ /**
6
+ * The maximum allowed request body size in bytes.
7
+ */
8
+ maxBodySize: number;
9
+ }
10
+ /**
11
+ * Rejects requests whose body exceeds `maxBodySize`.
12
+ *
13
+ * When used with the request compression plugin, the limit applies to the
14
+ * decompressed payload rather than the compressed wire size.
15
+ *
16
+ * @see {@link https://orpc.dev/docs/plugins/request-limit | Request Limit Plugin}
17
+ */
18
+ declare class RequestLimitHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
19
+ name: string;
20
+ /**
21
+ * Should limit the original batch request body instead of sub-requests.
22
+ */
23
+ after: string[];
24
+ /**
25
+ * Should limit the final body size instead of the compressed one.
26
+ */
27
+ before: string[];
28
+ private readonly maxBodySize;
29
+ constructor(options: RequestLimitHandlerPluginOptions);
30
+ init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
31
+ }
32
+
33
+ export { RequestLimitHandlerPlugin as R };
34
+ export type { RequestLimitHandlerPluginOptions as a };
@@ -1,7 +1,7 @@
1
1
  import { AnyORPCError } from '@orpc/client';
2
- import { OrderablePlugin, Interceptor, Promisable } from '@orpc/shared';
3
- import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
4
- import { C as Context, c as ProcedureClientInterceptor, A as AnyProcedure } from './server.BL22TloH.js';
2
+ import { OrderablePlugin, Value, Promisable, Interceptor } from '@orpc/shared';
3
+ import { StandardLazyRequest, StandardResponse } from '@standard-server/core';
4
+ import { C as Context, c as ProcedureClientInterceptor, A as AnyProcedure } from './server.BEdOJs6S.mjs';
5
5
  import { Schema, ErrorMap } from '@orpc/contract';
6
6
 
7
7
  interface StandardHandlerPlugin<T extends Context> extends OrderablePlugin {
@@ -36,6 +36,17 @@ declare class CompositeStandardHandlerPlugin<T extends Context> implements Stand
36
36
 
37
37
  interface StandardHandlerHandleOptions<T extends Context> {
38
38
  prefix?: `/${string}` | undefined;
39
+ /**
40
+ * The initial context, or a function (sync or async) that receives the request and returns it.
41
+ * The function only runs once the request passes the prefix check.
42
+ */
43
+ context: Value<Promisable<T>, [request: StandardLazyRequest]>;
44
+ }
45
+ /**
46
+ * `StandardHandlerHandleOptions` after the context has been resolved,
47
+ * this is what interceptors and codecs receive.
48
+ */
49
+ interface ResolvedStandardHandlerHandleOptions<T extends Context> extends Omit<StandardHandlerHandleOptions<T>, 'context'> {
39
50
  context: T;
40
51
  }
41
52
  type StandardHandlerHandleResult = {
@@ -45,11 +56,11 @@ type StandardHandlerHandleResult = {
45
56
  matched: false;
46
57
  response?: undefined;
47
58
  };
48
- interface StandardHandlerInterceptorOptions<T extends Context> extends StandardHandlerCodecResolvedProcedure, StandardHandlerHandleOptions<T> {
59
+ interface StandardHandlerInterceptorOptions<T extends Context> extends StandardHandlerCodecResolvedProcedure, ResolvedStandardHandlerHandleOptions<T> {
49
60
  request: StandardLazyRequest;
50
61
  }
51
62
  type StandardHandlerInterceptor<T extends Context> = Interceptor<StandardHandlerInterceptorOptions<T>, Promise<StandardResponse>>;
52
- interface StandardHandlerRoutingInterceptorOptions<T extends Context> extends StandardHandlerHandleOptions<T> {
63
+ interface StandardHandlerRoutingInterceptorOptions<T extends Context> extends ResolvedStandardHandlerHandleOptions<T> {
53
64
  request: StandardLazyRequest;
54
65
  }
55
66
  type StandardHandlerRoutingInterceptor<T extends Context> = Interceptor<StandardHandlerRoutingInterceptorOptions<T>, Promise<StandardHandlerHandleResult>>;
@@ -73,7 +84,7 @@ interface StandardHandlerOptions<TContext extends Context> {
73
84
  * ClientInterceptor equivalent with createRouterClient.interceptors / createProcedure.interceptors
74
85
  * useful for error handling, logging, metrics, etc. (not counting encoding/decoding)
75
86
  */
76
- clientInterceptors?: ProcedureClientInterceptor<TContext, Schema<unknown>, ErrorMap, any>[];
87
+ clientInterceptors?: ProcedureClientInterceptor<TContext, Schema<unknown>, ErrorMap>[];
77
88
  plugins?: StandardHandlerPlugin<TContext>[];
78
89
  }
79
90
  declare class StandardHandler<T extends Context> {
@@ -82,9 +93,9 @@ declare class StandardHandler<T extends Context> {
82
93
  private readonly interceptors;
83
94
  private readonly clientInterceptors;
84
95
  constructor(codec: StandardHandlerCodec<T>, options: StandardHandlerOptions<T>);
85
- handle(request: StandardLazyRequest, { context, prefix }: StandardHandlerHandleOptions<T>): Promise<StandardHandlerHandleResult>;
96
+ handle(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerHandleResult>;
86
97
  }
87
- declare class OtelHandlerPlugin implements StandardHandlerPlugin<any> {
98
+ declare class TracingHandlerPlugin implements StandardHandlerPlugin<any> {
88
99
  name: string;
89
100
  init(options: StandardHandlerOptions<any>): StandardHandlerOptions<any>;
90
101
  }
@@ -95,10 +106,10 @@ interface StandardHandlerCodecResolvedProcedure {
95
106
  decodeInput: () => Promise<unknown>;
96
107
  }
97
108
  interface StandardHandlerCodec<T extends Context> {
98
- resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promisable<StandardHandlerCodecResolvedProcedure | undefined>;
99
- encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
100
- encodeError(error: AnyORPCError, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
109
+ resolveProcedure(request: StandardLazyRequest, options: ResolvedStandardHandlerHandleOptions<T>): Promisable<StandardHandlerCodecResolvedProcedure | undefined>;
110
+ encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], options: ResolvedStandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
111
+ encodeError(error: AnyORPCError, procedure: AnyProcedure, path: string[], options: ResolvedStandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
101
112
  }
102
113
 
103
- export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, StandardHandler as S };
104
- export type { StandardHandlerOptions as a, StandardHandlerHandleOptions as b, StandardHandlerCodec as c, StandardHandlerCodecResolvedProcedure as d, StandardHandlerPlugin as e, StandardHandlerRoutingInterceptorOptions as f, StandardHandlerInterceptorOptions as g, StandardHandlerHandleResult as h, StandardHandlerInterceptor as i, StandardHandlerRoutingInterceptor as j };
114
+ export { CompositeStandardHandlerPlugin as C, StandardHandler as S, TracingHandlerPlugin as T };
115
+ export type { ResolvedStandardHandlerHandleOptions as R, StandardHandlerHandleOptions as a, StandardHandlerPlugin as b, StandardHandlerOptions as c, StandardHandlerRoutingInterceptorOptions as d, StandardHandlerInterceptorOptions as e, StandardHandlerCodec as f, StandardHandlerCodecResolvedProcedure as g, StandardHandlerHandleResult as h, StandardHandlerInterceptor as i, StandardHandlerRoutingInterceptor as j };