@orpc/server 1.14.9 → 1.14.11

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 (78) hide show
  1. package/README.md +52 -98
  2. package/dist/adapters/crossws/index.d.mts +45 -21
  3. package/dist/adapters/crossws/index.d.ts +45 -21
  4. package/dist/adapters/crossws/index.mjs +40 -18
  5. package/dist/adapters/fetch/index.d.mts +64 -96
  6. package/dist/adapters/fetch/index.d.ts +64 -96
  7. package/dist/adapters/fetch/index.mjs +34 -139
  8. package/dist/adapters/message-port/index.d.mts +49 -34
  9. package/dist/adapters/message-port/index.d.ts +49 -34
  10. package/dist/adapters/message-port/index.mjs +68 -37
  11. package/dist/adapters/node/index.d.mts +63 -71
  12. package/dist/adapters/node/index.d.ts +63 -71
  13. package/dist/adapters/node/index.mjs +36 -113
  14. package/dist/adapters/standard/index.d.mts +16 -18
  15. package/dist/adapters/standard/index.d.ts +16 -18
  16. package/dist/adapters/standard/index.mjs +5 -5
  17. package/dist/adapters/standard-peer/index.d.mts +12 -14
  18. package/dist/adapters/standard-peer/index.d.ts +12 -14
  19. package/dist/adapters/standard-peer/index.mjs +2 -21
  20. package/dist/adapters/websocket/index.d.mts +53 -38
  21. package/dist/adapters/websocket/index.d.ts +53 -38
  22. package/dist/adapters/websocket/index.mjs +59 -42
  23. package/dist/extensions/callable.d.mts +10 -0
  24. package/dist/extensions/callable.d.ts +10 -0
  25. package/dist/extensions/callable.mjs +11 -0
  26. package/dist/helpers/index.d.mts +4 -4
  27. package/dist/helpers/index.d.ts +4 -4
  28. package/dist/helpers/index.mjs +13 -5
  29. package/dist/index.d.mts +166 -770
  30. package/dist/index.d.ts +166 -770
  31. package/dist/index.mjs +306 -399
  32. package/dist/plugins/index.d.mts +214 -121
  33. package/dist/plugins/index.d.ts +214 -121
  34. package/dist/plugins/index.mjs +576 -214
  35. package/dist/shared/server.15O7oC1p.d.mts +61 -0
  36. package/dist/shared/server.B4BnEWWm.d.mts +67 -0
  37. package/dist/shared/server.BhsVw7m7.d.ts +104 -0
  38. package/dist/shared/server.BoiFpNT7.mjs +224 -0
  39. package/dist/shared/server.COPVXhDG.mjs +271 -0
  40. package/dist/shared/server.CX4vUnDk.mjs +11 -0
  41. package/dist/shared/server.CcR4kgje.d.mts +206 -0
  42. package/dist/shared/server.CcR4kgje.d.ts +206 -0
  43. package/dist/shared/server.CnN50DHH.d.ts +67 -0
  44. package/dist/shared/server.DBs0rrf9.mjs +41 -0
  45. package/dist/shared/server.DDFizwfU.d.mts +104 -0
  46. package/dist/shared/server.D_QauotT.mjs +30 -0
  47. package/dist/shared/server.DofEOwf-.mjs +237 -0
  48. package/dist/shared/{server.DZ5BIITo.mjs → server.W91HSRkE.mjs} +2 -2
  49. package/dist/shared/server.m3szVJGU.d.ts +61 -0
  50. package/package.json +26 -56
  51. package/dist/adapters/aws-lambda/index.d.mts +0 -46
  52. package/dist/adapters/aws-lambda/index.d.ts +0 -46
  53. package/dist/adapters/aws-lambda/index.mjs +0 -40
  54. package/dist/adapters/bun-ws/index.d.mts +0 -36
  55. package/dist/adapters/bun-ws/index.d.ts +0 -36
  56. package/dist/adapters/bun-ws/index.mjs +0 -47
  57. package/dist/adapters/fastify/index.d.mts +0 -53
  58. package/dist/adapters/fastify/index.d.ts +0 -53
  59. package/dist/adapters/fastify/index.mjs +0 -52
  60. package/dist/adapters/ws/index.d.mts +0 -31
  61. package/dist/adapters/ws/index.d.ts +0 -31
  62. package/dist/adapters/ws/index.mjs +0 -41
  63. package/dist/hibernation/index.d.mts +0 -44
  64. package/dist/hibernation/index.d.ts +0 -44
  65. package/dist/hibernation/index.mjs +0 -65
  66. package/dist/shared/server.7cEtMB30.d.ts +0 -74
  67. package/dist/shared/server.B8gYOD5g.d.mts +0 -12
  68. package/dist/shared/server.BqadksTP.d.mts +0 -74
  69. package/dist/shared/server.C8_sRzQB.d.mts +0 -42
  70. package/dist/shared/server.ChUyt5-i.d.mts +0 -32
  71. package/dist/shared/server.ChyoA9XY.d.ts +0 -42
  72. package/dist/shared/server.DEBcqOjg.mjs +0 -418
  73. package/dist/shared/server.EfTOZ2Q7.d.ts +0 -12
  74. package/dist/shared/server.TEVCLCFC.mjs +0 -39
  75. package/dist/shared/server.ZxHCEN1h.mjs +0 -226
  76. package/dist/shared/server.qKsRrdxW.d.mts +0 -193
  77. package/dist/shared/server.qKsRrdxW.d.ts +0 -193
  78. package/dist/shared/server.yoEB3Fx4.d.ts +0 -32
package/dist/index.mjs CHANGED
@@ -1,492 +1,399 @@
1
- import { mergeErrorMap, mergeMeta, mergeRoute, mergePrefix, mergeTags, isContractProcedure, getContractRouter, fallbackContractConfig } from '@orpc/contract';
2
- export { ValidationError, eventIterator, type, validateORPCError } from '@orpc/contract';
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.DEBcqOjg.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, v as resolveContractProcedures, t as traverseContractProcedures, w as unlazyRouter } from './shared/server.DEBcqOjg.mjs';
5
- import { toORPCError } from '@orpc/client';
6
- export { ORPCError, isDefinedError, safe } from '@orpc/client';
7
- import { isObject, resolveMaybeOptionalOptions } from '@orpc/shared';
8
- export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, asyncIteratorToUnproxiedDataStream as eventIteratorToUnproxiedDataStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
9
- export { ErrorEvent, getEventMeta, withEventMeta } from '@orpc/standard-server';
10
-
11
- const DEFAULT_CONFIG = {
12
- initialInputValidationIndex: 0,
13
- initialOutputValidationIndex: 0,
14
- dedupeLeadingMiddlewares: true
15
- };
16
- function fallbackConfig(key, value) {
17
- if (value === void 0) {
18
- return DEFAULT_CONFIG[key];
19
- }
20
- return value;
21
- }
1
+ import { mergeErrorMap, resolveMetaPlugins, getHiddenMetaPlugins, ProcedureContract } from '@orpc/contract';
2
+ export { ValidationError, asyncIteratorObject, defineMeta, eventIterator, reconcileORPCError, type } from '@orpc/contract';
3
+ import { toArray, bindMethods, getOrBind, isTypescriptObject, resolveMaybeOptionalOptions } from '@orpc/shared';
4
+ export { AsyncIteratorClass, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, asyncIteratorToStream as eventIteratorToStream, asyncIteratorToUnproxiedDataStream as eventIteratorToUnproxiedDataStream, onAsyncIteratorObjectError, onError, onFinish, onReadableStreamError, onStart, onSuccess, streamToAsyncIteratorObject, streamToAsyncIteratorObject as streamToEventIterator } from '@orpc/shared';
5
+ import { L as Lazy, P as Procedure, c as createProcedureClient } from './shared/server.DofEOwf-.mjs';
6
+ export { a as createORPCErrorConstructorMap, u as unlazy } from './shared/server.DofEOwf-.mjs';
7
+ import { D as DecoratedProcedure } from './shared/server.DBs0rrf9.mjs';
8
+ import { b as augmentRouter, d as augmentImplementedRouter, e as withHiddenRouterContract, f as createGuardedProcedureLazy, g as getRouter } from './shared/server.BoiFpNT7.mjs';
9
+ export { a as DEFAULT_ERROR_STATUS, D as DEFAULT_SUCCESS_STATUS, h as call, c as createContractProcedure, i as getHiddenRouterContract, u as unlazyRouter, j as walkProcedureContractsAsync, w as walkProcedureContractsSync } from './shared/server.BoiFpNT7.mjs';
10
+ import { RECURSIVE_CLIENT_UNWRAP_KEYS } from '@orpc/client';
11
+ export { COMMON_ERROR_STATUS_MAP, ORPCError, RPCJsonSerializer, RPCSerializer, cloneORPCError, isDefinedError, isInferableError, safe, toORPCError } from '@orpc/client';
12
+ export { ErrorEvent, getEventMeta, unwrapEvent, withEventMeta } from '@standardserver/core';
22
13
 
23
14
  function decorateMiddleware(middleware) {
24
15
  const decorated = ((...args) => middleware(...args));
25
- decorated.mapInput = (mapInput) => {
16
+ decorated["~orpc"] = middleware["~orpc"];
17
+ Object.defineProperty(decorated, "name", {
18
+ value: middleware.name
19
+ });
20
+ decorated.adaptInput = (adapt) => {
26
21
  const mapped = decorateMiddleware(
27
- (options, input, ...rest) => middleware(options, mapInput(input), ...rest)
22
+ (opts, input, ...args) => {
23
+ return middleware(opts, adapt(input), ...args);
24
+ }
28
25
  );
26
+ mapped["~orpc"] = middleware["~orpc"];
27
+ Object.defineProperty(mapped, "name", {
28
+ value: middleware.name
29
+ });
29
30
  return mapped;
30
31
  };
31
- decorated.concat = (concatMiddleware, mapInput) => {
32
- const mapped = mapInput ? decorateMiddleware(concatMiddleware).mapInput(mapInput) : concatMiddleware;
33
- const concatted = decorateMiddleware((options, input, output, ...rest) => {
34
- const merged = middleware({
35
- ...options,
36
- next: (...[nextOptions1]) => mapped({
37
- ...options,
38
- context: { ...options.context, ...nextOptions1?.context },
39
- next: (...[nextOptions2]) => options.next({ context: { ...nextOptions1?.context, ...nextOptions2?.context } })
40
- }, input, output, ...rest)
41
- }, input, output, ...rest);
42
- return merged;
43
- });
44
- return concatted;
32
+ decorated.errors = (errors) => {
33
+ const newMiddleware = decorateMiddleware(decorated);
34
+ newMiddleware["~orpc"] = {
35
+ ...decorated["~orpc"],
36
+ errorMap: mergeErrorMap(decorated["~orpc"]?.errorMap, errors)
37
+ };
38
+ return newMiddleware;
45
39
  };
46
- return decorated;
47
- }
48
-
49
- function createActionableClient(client) {
50
- const action = async (input) => {
51
- try {
52
- return [null, await client(input)];
53
- } catch (error) {
54
- if (error instanceof Error && "digest" in error && typeof error.digest === "string" && error.digest.startsWith("NEXT_")) {
55
- throw error;
56
- }
57
- if (error instanceof Response && "options" in error && isObject(error.options) || isObject(error) && error.isNotFound === true) {
58
- throw error;
59
- }
60
- return [toORPCError(error).toJSON(), void 0];
61
- }
62
- };
63
- return action;
64
- }
65
-
66
- class DecoratedProcedure extends Procedure {
67
- /**
68
- * Adds type-safe custom errors.
69
- * The provided errors are spared-merged with any existing errors.
70
- *
71
- * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
72
- */
73
- errors(errors) {
74
- return new DecoratedProcedure({
75
- ...this["~orpc"],
76
- errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
77
- });
78
- }
79
- /**
80
- * Sets or updates the metadata.
81
- * The provided metadata is spared-merged with any existing metadata.
82
- *
83
- * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
84
- */
85
- meta(meta) {
86
- return new DecoratedProcedure({
87
- ...this["~orpc"],
88
- meta: mergeMeta(this["~orpc"].meta, meta)
89
- });
90
- }
91
- /**
92
- * Sets or updates the route definition.
93
- * The provided route is spared-merged with any existing route.
94
- * This option is typically relevant when integrating with OpenAPI.
95
- *
96
- * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
97
- * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
98
- */
99
- route(route) {
100
- return new DecoratedProcedure({
101
- ...this["~orpc"],
102
- route: mergeRoute(this["~orpc"].route, route)
103
- });
104
- }
105
- use(middleware, mapInput) {
106
- const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
107
- return new DecoratedProcedure({
108
- ...this["~orpc"],
109
- middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
110
- });
111
- }
112
- /**
113
- * Make this procedure callable (works like a function while still being a procedure).
114
- *
115
- * @see {@link https://orpc.dev/docs/client/server-side Server-side Client Docs}
116
- */
117
- callable(...rest) {
118
- const client = createProcedureClient(this, ...rest);
119
- return new Proxy(client, {
120
- get: (target, key) => {
121
- return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
122
- },
123
- has: (target, key) => {
124
- return Reflect.has(this, key) || Reflect.has(target, key);
125
- }
40
+ decorated.use = (usedMiddleware) => {
41
+ const merged = decorateMiddleware((opts, ...args) => {
42
+ return middleware(
43
+ {
44
+ ...opts,
45
+ async next(nextOpts1) {
46
+ const result = await usedMiddleware({
47
+ ...opts,
48
+ context: { ...opts.context, ...nextOpts1?.context },
49
+ next(nextOpts2, ...args2) {
50
+ return opts.next({
51
+ ...opts,
52
+ context: {
53
+ ...nextOpts1?.context,
54
+ ...nextOpts2?.context
55
+ }
56
+ }, ...args2);
57
+ }
58
+ }, ...args);
59
+ return {
60
+ ...result,
61
+ context: {
62
+ ...nextOpts1?.context,
63
+ ...result.context
64
+ }
65
+ };
66
+ }
67
+ },
68
+ ...args
69
+ );
126
70
  });
127
- }
128
- /**
129
- * Make this procedure compatible with server action.
130
- *
131
- * @see {@link https://orpc.dev/docs/server-action Server Action Docs}
132
- */
133
- actionable(...rest) {
134
- const action = createActionableClient(createProcedureClient(this, ...rest));
135
- return new Proxy(action, {
136
- get: (target, key) => {
137
- return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
138
- },
139
- has: (target, key) => {
140
- return Reflect.has(this, key) || Reflect.has(target, key);
141
- }
71
+ merged["~orpc"] = {
72
+ ...decorated["~orpc"],
73
+ errorMap: mergeErrorMap(usedMiddleware["~orpc"]?.errorMap, decorated["~orpc"]?.errorMap),
74
+ metaPlugins: [
75
+ ...toArray(middleware["~orpc"]?.metaPlugins),
76
+ ...toArray(usedMiddleware["~orpc"]?.metaPlugins)
77
+ ]
78
+ };
79
+ Object.defineProperty(merged, "name", {
80
+ value: `${middleware.name} + ${usedMiddleware.name}`
142
81
  });
143
- }
82
+ return merged;
83
+ };
84
+ return decorated;
144
85
  }
145
86
 
146
87
  class Builder {
147
- /**
148
- * This property holds the defined options.
149
- */
150
88
  "~orpc";
151
- constructor(def) {
152
- this["~orpc"] = def;
89
+ constructor(definition) {
90
+ this["~orpc"] = definition;
153
91
  }
154
- /**
155
- * Sets or overrides the config.
156
- *
157
- * @see {@link https://orpc.dev/docs/client/server-side#middlewares-order Middlewares Order Docs}
158
- * @see {@link https://orpc.dev/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
159
- */
160
- $config(config) {
161
- const inputValidationCount = this["~orpc"].inputValidationIndex - fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex);
162
- const outputValidationCount = this["~orpc"].outputValidationIndex - fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex);
92
+ static create() {
163
93
  return new Builder({
164
- ...this["~orpc"],
165
- config,
166
- dedupeLeadingMiddlewares: fallbackConfig("dedupeLeadingMiddlewares", config.dedupeLeadingMiddlewares),
167
- inputValidationIndex: fallbackConfig("initialInputValidationIndex", config.initialInputValidationIndex) + inputValidationCount,
168
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex", config.initialOutputValidationIndex) + outputValidationCount
94
+ errorMap: {},
95
+ meta: {},
96
+ orderedMiddlewares: []
169
97
  });
170
98
  }
171
- /**
172
- * Set or override the initial context.
173
- *
174
- * @see {@link https://orpc.dev/docs/context Context Docs}
175
- */
176
99
  $context() {
100
+ return this;
101
+ }
102
+ $config(config) {
177
103
  return new Builder({
178
104
  ...this["~orpc"],
179
- middlewares: [],
180
- inputValidationIndex: fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex),
181
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex)
105
+ ...config
182
106
  });
183
107
  }
184
- /**
185
- * Sets or overrides the initial meta.
186
- *
187
- * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
188
- */
189
- $meta(initialMeta) {
108
+ meta(...plugins) {
109
+ const [meta, metaPlugins] = resolveMetaPlugins(
110
+ this["~orpc"].meta,
111
+ this["~orpc"].metaPlugins,
112
+ plugins
113
+ );
190
114
  return new Builder({
191
115
  ...this["~orpc"],
192
- meta: initialMeta
116
+ meta,
117
+ metaPlugins
193
118
  });
194
119
  }
195
- /**
196
- * Sets or overrides the initial route.
197
- * This option is typically relevant when integrating with OpenAPI.
198
- *
199
- * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
200
- * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
201
- */
202
- $route(initialRoute) {
203
- return new Builder({
120
+ errors(errors) {
121
+ let builder = new Builder({
204
122
  ...this["~orpc"],
205
- route: initialRoute
123
+ errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
206
124
  });
125
+ const plugins = getHiddenMetaPlugins(errors);
126
+ if (plugins) {
127
+ builder = builder.meta(...plugins);
128
+ }
129
+ return builder;
207
130
  }
208
- /**
209
- * Sets or overrides the initial input schema.
210
- *
211
- * @see {@link https://orpc.dev/docs/procedure#initial-configuration Initial Procedure Configuration Docs}
212
- */
213
- $input(initialInputSchema) {
214
- return new Builder({
131
+ use(middleware) {
132
+ let builder = new Builder({
215
133
  ...this["~orpc"],
216
- inputSchema: initialInputSchema
134
+ errorMap: mergeErrorMap(middleware["~orpc"]?.errorMap ?? {}, this["~orpc"].errorMap),
135
+ orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
136
+ middleware,
137
+ inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
138
+ outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
139
+ }]
217
140
  });
141
+ if (middleware["~orpc"]?.metaPlugins) {
142
+ builder = builder.meta(...middleware["~orpc"]?.metaPlugins);
143
+ }
144
+ return builder;
218
145
  }
219
- /**
220
- * Creates a middleware.
221
- *
222
- * @see {@link https://orpc.dev/docs/middleware Middleware Docs}
223
- */
224
146
  middleware(middleware) {
225
- return decorateMiddleware(middleware);
147
+ const allMiddlewares = [
148
+ ...this["~orpc"].orderedMiddlewares.map(({ middleware: middleware2 }) => middleware2),
149
+ middleware
150
+ ];
151
+ let current = decorateMiddleware(allMiddlewares.shift());
152
+ for (const mid of allMiddlewares) {
153
+ current = current.use(mid);
154
+ }
155
+ current["~orpc"] = {
156
+ ...current["~orpc"],
157
+ errorMap: this["~orpc"].errorMap,
158
+ metaPlugins: [
159
+ ...toArray(this["~orpc"].metaPlugins),
160
+ ...toArray(middleware["~orpc"]?.metaPlugins)
161
+ ]
162
+ };
163
+ return current;
226
164
  }
227
- /**
228
- * Adds type-safe custom errors.
229
- * The provided errors are spared-merged with any existing errors.
230
- *
231
- * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
232
- */
233
- errors(errors) {
234
- return new Builder({
165
+ input(schema) {
166
+ let builder = new Builder({
235
167
  ...this["~orpc"],
236
- errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
168
+ inputSchemas: [...toArray(this["~orpc"].inputSchemas), schema]
237
169
  });
170
+ const plugins = getHiddenMetaPlugins(schema);
171
+ if (plugins) {
172
+ builder = builder.meta(...plugins);
173
+ }
174
+ return builder;
238
175
  }
239
- use(middleware, mapInput) {
240
- const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
241
- return new Builder({
176
+ output(schema) {
177
+ let builder = new Builder({
242
178
  ...this["~orpc"],
243
- middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
179
+ outputSchemas: [...toArray(this["~orpc"].outputSchemas), schema]
244
180
  });
181
+ const plugins = getHiddenMetaPlugins(schema);
182
+ if (plugins) {
183
+ builder = builder.meta(...plugins);
184
+ }
185
+ return builder;
245
186
  }
246
- /**
247
- * Sets or updates the metadata.
248
- * The provided metadata is spared-merged with any existing metadata.
249
- *
250
- * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
251
- */
252
- meta(meta) {
253
- return new Builder({
187
+ handler(handler) {
188
+ let procedure = new DecoratedProcedure({
254
189
  ...this["~orpc"],
255
- meta: mergeMeta(this["~orpc"].meta, meta)
190
+ handler
256
191
  });
192
+ const plugins = getHiddenMetaPlugins(handler);
193
+ if (plugins) {
194
+ procedure = procedure.meta(...plugins);
195
+ }
196
+ return procedure;
257
197
  }
258
- /**
259
- * Sets or updates the route definition.
260
- * The provided route is spared-merged with any existing route.
261
- * This option is typically relevant when integrating with OpenAPI.
262
- *
263
- * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
264
- * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
265
- */
266
- route(route) {
267
- return new Builder({
198
+ router(router) {
199
+ return augmentRouter(router, {
268
200
  ...this["~orpc"],
269
- route: mergeRoute(this["~orpc"].route, route)
201
+ middlewares: this["~orpc"].orderedMiddlewares.map(({ middleware }) => middleware)
270
202
  });
271
203
  }
272
- /**
273
- * Defines the input validation schema.
274
- *
275
- * @see {@link https://orpc.dev/docs/procedure#input-output-validation Input Validation Docs}
276
- */
277
- input(schema) {
278
- return new Builder({
279
- ...this["~orpc"],
280
- inputSchema: schema,
281
- inputValidationIndex: fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex) + this["~orpc"].middlewares.length
204
+ lazy(loader) {
205
+ return new Lazy({
206
+ loader: async () => {
207
+ const { default: router } = await loader();
208
+ return {
209
+ default: this.router(router)
210
+ };
211
+ },
212
+ meta: this["~orpc"].meta,
213
+ metaPlugins: this["~orpc"].metaPlugins
282
214
  });
283
215
  }
284
- /**
285
- * Defines the output validation schema.
286
- *
287
- * @see {@link https://orpc.dev/docs/procedure#input-output-validation Output Validation Docs}
288
- */
289
- output(schema) {
290
- return new Builder({
291
- ...this["~orpc"],
292
- outputSchema: schema,
293
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex) + this["~orpc"].middlewares.length
294
- });
216
+ }
217
+ const os = Builder.create();
218
+
219
+ class ProcedureImplementer {
220
+ "~orpc";
221
+ constructor(definition) {
222
+ this["~orpc"] = definition;
295
223
  }
296
- /**
297
- * Defines the handler of the procedure.
298
- *
299
- * @see {@link https://orpc.dev/docs/procedure Procedure Docs}
300
- */
301
- handler(handler) {
302
- return new DecoratedProcedure({
224
+ "use"(middleware) {
225
+ return new ProcedureImplementer({
303
226
  ...this["~orpc"],
304
- handler
227
+ orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
228
+ middleware,
229
+ inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
230
+ outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
231
+ }]
305
232
  });
306
233
  }
307
- /**
308
- * Prefixes all procedures in the router.
309
- * The provided prefix is post-appended to any existing router prefix.
310
- *
311
- * @note This option does not affect procedures that do not define a path in their route definition.
312
- *
313
- * @see {@link https://orpc.dev/docs/openapi/routing#route-prefixes OpenAPI Route Prefixes Docs}
314
- */
315
- prefix(prefix) {
316
- return new Builder({
234
+ "handler"(handler) {
235
+ return new ImplementedProcedure({
317
236
  ...this["~orpc"],
318
- prefix: mergePrefix(this["~orpc"].prefix, prefix)
237
+ handler,
238
+ /**
239
+ * When enabled, errors returned (not thrown) by the handler are passed through as-is,
240
+ * rather than being transformed into inferrable errors.
241
+ *
242
+ * This is intended for the contract-first approach, where the procedure adheres to an
243
+ * external contract and returned errors should not affect the inferred contract types.
244
+ */
245
+ opaqueReturnedErrors: true
319
246
  });
320
247
  }
321
- /**
322
- * Adds tags to all procedures in the router.
323
- * This helpful when you want to group procedures together in the OpenAPI specification.
324
- *
325
- * @see {@link https://orpc.dev/docs/openapi/openapi-specification#operation-metadata OpenAPI Operation Metadata Docs}
326
- */
327
- tag(...tags) {
328
- return new Builder({
248
+ }
249
+ class ImplementedProcedure extends Procedure {
250
+ use(middleware) {
251
+ return new ImplementedProcedure({
329
252
  ...this["~orpc"],
330
- tags: mergeTags(this["~orpc"].tags, tags)
253
+ orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
254
+ middleware,
255
+ inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
256
+ outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
257
+ }]
331
258
  });
332
259
  }
333
- /**
334
- * Applies all of the previously defined options to the specified router.
335
- *
336
- * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
337
- */
260
+ }
261
+
262
+ class SharedRouterImplementer {
263
+ constructor(contract, config, middlewares) {
264
+ this.contract = contract;
265
+ this.config = config;
266
+ this.middlewares = middlewares;
267
+ }
268
+ static create(contract, config, middlewares = []) {
269
+ return new SharedRouterImplementer(
270
+ contract,
271
+ config,
272
+ middlewares
273
+ );
274
+ }
275
+ use(middleware) {
276
+ return createRouterImplementerInternal(this.contract, this.config, [...this.middlewares, middleware]);
277
+ }
278
+ middleware(middleware) {
279
+ const allMiddlewares = [
280
+ ...this.middlewares,
281
+ middleware
282
+ ];
283
+ let current = decorateMiddleware(allMiddlewares.shift());
284
+ for (const mid of allMiddlewares) {
285
+ current = current.use(mid);
286
+ }
287
+ return current;
288
+ }
338
289
  router(router) {
339
- return enhanceRouter(router, this["~orpc"]);
290
+ if (this.middlewares.length) {
291
+ router = augmentImplementedRouter(router, {
292
+ ...this.config,
293
+ middlewares: this.middlewares
294
+ });
295
+ }
296
+ return withHiddenRouterContract(router, this.contract);
340
297
  }
341
- /**
342
- * Create a lazy router
343
- * And applies all of the previously defined options to the specified router.
344
- *
345
- * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
346
- */
347
298
  lazy(loader) {
348
- return enhanceRouter(lazy(loader), this["~orpc"]);
299
+ if (this.middlewares.length) {
300
+ const originalLoader = loader;
301
+ loader = async () => {
302
+ const { default: router } = await originalLoader();
303
+ return {
304
+ default: augmentImplementedRouter(router, {
305
+ ...this.config,
306
+ middlewares: this.middlewares
307
+ })
308
+ };
309
+ };
310
+ }
311
+ return new Lazy({ loader, meta: {} });
349
312
  }
350
313
  }
351
- const os = new Builder({
352
- config: {},
353
- route: {},
354
- meta: {},
355
- errorMap: {},
356
- inputValidationIndex: fallbackConfig("initialInputValidationIndex"),
357
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex"),
358
- middlewares: [],
359
- dedupeLeadingMiddlewares: true
360
- });
361
-
362
- function implementerInternal(contract, config, middlewares) {
363
- if (isContractProcedure(contract)) {
364
- const impl2 = new Builder({
314
+ function createRouterImplementer(contract, config) {
315
+ return createRouterImplementerInternal(contract, config, []);
316
+ }
317
+ function createRouterImplementerInternal(contract, config, middlewares) {
318
+ if (contract instanceof ProcedureContract) {
319
+ return new ProcedureImplementer({
320
+ ...config,
365
321
  ...contract["~orpc"],
366
- config,
367
- middlewares,
368
- inputValidationIndex: fallbackConfig("initialInputValidationIndex", config?.initialInputValidationIndex) + middlewares.length,
369
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex", config?.initialOutputValidationIndex) + middlewares.length,
370
- dedupeLeadingMiddlewares: fallbackConfig("dedupeLeadingMiddlewares", config.dedupeLeadingMiddlewares)
322
+ orderedMiddlewares: middlewares.map((middleware) => ({ middleware }))
371
323
  });
372
- return impl2;
373
324
  }
374
- const impl = new Proxy(contract, {
375
- get: (target, key) => {
376
- if (typeof key !== "string") {
377
- return Reflect.get(target, key);
378
- }
325
+ const implementer = {};
326
+ for (const key in contract) {
327
+ const child = contract[key];
328
+ implementer[key] = createRouterImplementerInternal(child, config, middlewares);
329
+ }
330
+ const shared = bindMethods(SharedRouterImplementer.create(contract, config, middlewares));
331
+ for (const key in shared) {
332
+ const method = shared[key];
333
+ if (key in implementer) {
334
+ const child = implementer[key];
335
+ implementer[key] = new Proxy(method, {
336
+ get(_, p) {
337
+ return getOrBind(child, p);
338
+ }
339
+ });
340
+ } else {
341
+ implementer[key] = method;
342
+ }
343
+ }
344
+ return implementer;
345
+ }
346
+
347
+ function implement(contract, config = {}) {
348
+ const routerImplementer = createRouterImplementer(contract, config);
349
+ const implementer = new Proxy(routerImplementer, {
350
+ get(_, p) {
379
351
  let method;
380
- if (key === "middleware") {
381
- method = (mid) => decorateMiddleware(mid);
382
- } else if (key === "use") {
383
- method = (mid) => {
384
- return implementerInternal(
385
- contract,
386
- config,
387
- addMiddleware(middlewares, mid)
388
- );
389
- };
390
- } else if (key === "router") {
391
- method = (router) => {
392
- const adapted = enhanceRouter(router, {
393
- middlewares,
394
- errorMap: {},
395
- prefix: void 0,
396
- tags: void 0,
397
- dedupeLeadingMiddlewares: fallbackConfig("dedupeLeadingMiddlewares", config.dedupeLeadingMiddlewares)
398
- });
399
- return setHiddenRouterContract(adapted, contract);
400
- };
401
- } else if (key === "lazy") {
402
- method = (loader) => {
403
- const adapted = enhanceRouter(lazy(loader), {
404
- middlewares,
405
- errorMap: {},
406
- prefix: void 0,
407
- tags: void 0,
408
- dedupeLeadingMiddlewares: fallbackConfig("dedupeLeadingMiddlewares", config.dedupeLeadingMiddlewares)
409
- });
410
- return setHiddenRouterContract(adapted, contract);
411
- };
412
- }
413
- const next = getContractRouter(target, [key]);
414
- if (!next) {
415
- return method ?? next;
352
+ if (p === "$context") {
353
+ method = () => implementer;
354
+ } else if (p === "$config") {
355
+ method = (incoming) => implement(contract, { ...config, ...incoming });
416
356
  }
417
- const nextImpl = implementerInternal(next, config, middlewares);
357
+ const value = getOrBind(routerImplementer, p);
418
358
  if (method) {
359
+ if (!isTypescriptObject(value)) {
360
+ return method;
361
+ }
419
362
  return new Proxy(method, {
420
- get(_, key2) {
421
- return Reflect.get(nextImpl, key2);
363
+ get(_2, p2) {
364
+ return getOrBind(value, p2);
422
365
  }
423
366
  });
424
367
  }
425
- return nextImpl;
426
- }
427
- });
428
- return impl;
429
- }
430
- function implement(contract, config = {}) {
431
- const implInternal = implementerInternal(contract, config, []);
432
- const impl = new Proxy(implInternal, {
433
- get: (target, key) => {
434
- let method;
435
- if (key === "$context") {
436
- method = () => impl;
437
- } else if (key === "$config") {
438
- method = (config2) => implement(contract, config2);
439
- }
440
- const next = Reflect.get(target, key);
441
- if (!method || !next || typeof next !== "function" && typeof next !== "object") {
442
- return method || next;
443
- }
444
- return new Proxy(method, {
445
- get(_, key2) {
446
- return Reflect.get(next, key2);
447
- }
448
- });
368
+ return value;
449
369
  }
450
370
  });
451
- return impl;
452
- }
453
-
454
- function inferRPCMethodFromRouter(router) {
455
- return async (_, path) => {
456
- const { default: procedure } = await unlazy(getRouter(router, path));
457
- if (!isProcedure(procedure)) {
458
- throw new Error(
459
- `[inferRPCMethodFromRouter] No valid procedure found at path "${path.join(".")}". This may happen when the router is not properly configured.`
460
- );
461
- }
462
- const method = fallbackContractConfig("defaultMethod", procedure["~orpc"].route.method);
463
- return method === "HEAD" ? "GET" : method;
464
- };
371
+ return implementer;
465
372
  }
466
373
 
467
374
  function createRouterClient(router, ...rest) {
468
375
  const options = resolveMaybeOptionalOptions(rest);
469
- if (isProcedure(router)) {
470
- const caller = createProcedureClient(router, options);
471
- return caller;
376
+ if (router instanceof Procedure) {
377
+ return createProcedureClient(router, options);
472
378
  }
473
- const procedureCaller = isLazy(router) ? createProcedureClient(createAssertedLazyProcedure(router), options) : {};
379
+ const procedureCaller = router instanceof Lazy ? createProcedureClient(createGuardedProcedureLazy(router), options) : {};
474
380
  const recursive = new Proxy(procedureCaller, {
475
381
  get(target, key) {
476
- if (typeof key !== "string") {
477
- return Reflect.get(target, key);
382
+ if (typeof key !== "string" || router instanceof Lazy && RECURSIVE_CLIENT_UNWRAP_KEYS.has(key)) {
383
+ return getOrBind(target, key);
478
384
  }
479
385
  const next = getRouter(router, [key]);
480
386
  if (!next) {
481
- return Reflect.get(target, key);
387
+ return getOrBind(target, key);
482
388
  }
483
- return createRouterClient(next, {
484
- ...rest[0],
485
- path: [...rest[0]?.path ?? [], key]
389
+ const nextClient = createRouterClient(next, {
390
+ ...options,
391
+ path: [...toArray(options.path), key]
486
392
  });
393
+ return nextClient;
487
394
  }
488
395
  });
489
396
  return recursive;
490
397
  }
491
398
 
492
- export { Builder, DecoratedProcedure, Procedure, addMiddleware, createActionableClient, createAssertedLazyProcedure, createProcedureClient, createRouterClient, decorateMiddleware, enhanceRouter, fallbackConfig, getRouter, implement, implementerInternal, inferRPCMethodFromRouter, isLazy, isProcedure, lazy, os, setHiddenRouterContract, unlazy };
399
+ export { Builder, DecoratedProcedure, ImplementedProcedure, Lazy, Procedure, ProcedureImplementer, SharedRouterImplementer, augmentImplementedRouter, augmentRouter, createGuardedProcedureLazy, createProcedureClient, createRouterClient, createRouterImplementer, decorateMiddleware, getRouter, implement, os, withHiddenRouterContract };