@orpc/server 1.14.6 → 2.0.0-beta.1

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 +74 -136
  2. package/dist/adapters/crossws/index.d.mts +42 -21
  3. package/dist/adapters/crossws/index.d.ts +42 -21
  4. package/dist/adapters/crossws/index.mjs +37 -18
  5. package/dist/adapters/fetch/index.d.mts +83 -67
  6. package/dist/adapters/fetch/index.d.ts +83 -67
  7. package/dist/adapters/fetch/index.mjs +131 -106
  8. package/dist/adapters/message-port/index.d.mts +51 -34
  9. package/dist/adapters/message-port/index.d.ts +51 -34
  10. package/dist/adapters/message-port/index.mjs +73 -38
  11. package/dist/adapters/node/index.d.mts +82 -60
  12. package/dist/adapters/node/index.d.ts +82 -60
  13. package/dist/adapters/node/index.mjs +127 -98
  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 +39 -34
  21. package/dist/adapters/websocket/index.d.ts +39 -34
  22. package/dist/adapters/websocket/index.mjs +42 -33
  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 +2 -2
  27. package/dist/helpers/index.d.ts +2 -2
  28. package/dist/helpers/index.mjs +1 -1
  29. package/dist/index.d.mts +163 -770
  30. package/dist/index.d.ts +163 -770
  31. package/dist/index.mjs +296 -403
  32. package/dist/plugins/index.d.mts +105 -143
  33. package/dist/plugins/index.d.ts +105 -143
  34. package/dist/plugins/index.mjs +232 -255
  35. package/dist/shared/server.BB_Ik9Ph.d.mts +104 -0
  36. package/dist/shared/server.BL22TloH.d.mts +184 -0
  37. package/dist/shared/server.BL22TloH.d.ts +184 -0
  38. package/dist/shared/server.B_U9y00a.d.mts +66 -0
  39. package/dist/shared/server.BsNNjG5J.d.mts +61 -0
  40. package/dist/shared/server.BwHnWUuN.mjs +222 -0
  41. package/dist/shared/server.CX4vUnDk.mjs +11 -0
  42. package/dist/shared/server.CjOb6ItT.mjs +41 -0
  43. package/dist/shared/server.CrlKQucM.mjs +233 -0
  44. package/dist/shared/server.D_QauotT.mjs +30 -0
  45. package/dist/shared/server.EOHJ3NJr.d.ts +104 -0
  46. package/dist/shared/server.GDpX6Df8.mjs +271 -0
  47. package/dist/shared/server.Pa0F03f_.d.ts +61 -0
  48. package/dist/shared/server.T9F3bzZx.d.ts +66 -0
  49. package/dist/shared/{server.DZ5BIITo.mjs → server.W91HSRkE.mjs} +2 -2
  50. package/package.json +26 -55
  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 -37
  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,385 @@
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, defineMeta, eventIterator, reconcileORPCError, type } from '@orpc/contract';
3
+ import { toArray, bindMethods, getOrBind, isTypescriptObject, resolveMaybeOptionalOptions } from '@orpc/shared';
4
+ export { AsyncIteratorClass, asyncIteratorToStream as eventIteratorToStream, asyncIteratorToUnproxiedDataStream as eventIteratorToUnproxiedDataStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
5
+ import { L as Lazy, P as Procedure, c as createProcedureClient } from './shared/server.CrlKQucM.mjs';
6
+ export { a as createORPCErrorConstructorMap, u as unlazy } from './shared/server.CrlKQucM.mjs';
7
+ import { D as DecoratedProcedure } from './shared/server.CjOb6ItT.mjs';
8
+ import { b as augmentRouter, d as augmentImplementedRouter, e as withHiddenRouterContract, f as createGuardedProcedureLazy, g as getRouter } from './shared/server.BwHnWUuN.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.BwHnWUuN.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
  );
29
- return mapped;
30
- };
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;
26
+ mapped["~orpc"] = middleware["~orpc"];
27
+ Object.defineProperty(mapped, "name", {
28
+ value: middleware.name
43
29
  });
44
- return concatted;
30
+ return mapped;
45
31
  };
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
- }
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;
62
39
  };
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() {
177
- return new Builder({
178
- ...this["~orpc"],
179
- middlewares: [],
180
- inputValidationIndex: fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex),
181
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex)
182
- });
100
+ return this;
183
101
  }
184
- /**
185
- * Sets or overrides the initial meta.
186
- *
187
- * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
188
- */
189
- $meta(initialMeta) {
102
+ meta(...plugins) {
103
+ const [meta, metaPlugins] = resolveMetaPlugins(
104
+ this["~orpc"].meta,
105
+ this["~orpc"].metaPlugins,
106
+ plugins
107
+ );
190
108
  return new Builder({
191
109
  ...this["~orpc"],
192
- meta: initialMeta
110
+ meta,
111
+ metaPlugins
193
112
  });
194
113
  }
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({
114
+ errors(errors) {
115
+ let builder = new Builder({
204
116
  ...this["~orpc"],
205
- route: initialRoute
117
+ errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
206
118
  });
119
+ const plugins = getHiddenMetaPlugins(errors);
120
+ if (plugins) {
121
+ builder = builder.meta(...plugins);
122
+ }
123
+ return builder;
207
124
  }
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({
125
+ use(middleware) {
126
+ let builder = new Builder({
215
127
  ...this["~orpc"],
216
- inputSchema: initialInputSchema
128
+ errorMap: mergeErrorMap(middleware["~orpc"]?.errorMap ?? {}, this["~orpc"].errorMap),
129
+ orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
130
+ middleware,
131
+ inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
132
+ outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
133
+ }]
217
134
  });
135
+ if (middleware["~orpc"]?.metaPlugins) {
136
+ builder = builder.meta(...middleware["~orpc"]?.metaPlugins);
137
+ }
138
+ return builder;
218
139
  }
219
- /**
220
- * Creates a middleware.
221
- *
222
- * @see {@link https://orpc.dev/docs/middleware Middleware Docs}
223
- */
224
140
  middleware(middleware) {
225
- return decorateMiddleware(middleware);
141
+ const allMiddlewares = [
142
+ ...this["~orpc"].orderedMiddlewares.map(({ middleware: middleware2 }) => middleware2),
143
+ middleware
144
+ ];
145
+ let current = decorateMiddleware(allMiddlewares.shift());
146
+ for (const mid of allMiddlewares) {
147
+ current = current.use(mid);
148
+ }
149
+ current["~orpc"] = {
150
+ ...current["~orpc"],
151
+ errorMap: this["~orpc"].errorMap,
152
+ metaPlugins: [
153
+ ...toArray(this["~orpc"].metaPlugins),
154
+ ...toArray(middleware["~orpc"]?.metaPlugins)
155
+ ]
156
+ };
157
+ return current;
226
158
  }
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({
159
+ input(schema) {
160
+ let builder = new Builder({
235
161
  ...this["~orpc"],
236
- errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
162
+ inputSchemas: [...toArray(this["~orpc"].inputSchemas), schema]
237
163
  });
164
+ const plugins = getHiddenMetaPlugins(schema);
165
+ if (plugins) {
166
+ builder = builder.meta(...plugins);
167
+ }
168
+ return builder;
238
169
  }
239
- use(middleware, mapInput) {
240
- const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
241
- return new Builder({
170
+ output(schema) {
171
+ let builder = new Builder({
242
172
  ...this["~orpc"],
243
- middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
173
+ outputSchemas: [...toArray(this["~orpc"].outputSchemas), schema]
244
174
  });
175
+ const plugins = getHiddenMetaPlugins(schema);
176
+ if (plugins) {
177
+ builder = builder.meta(...plugins);
178
+ }
179
+ return builder;
245
180
  }
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({
181
+ handler(handler) {
182
+ let procedure = new DecoratedProcedure({
254
183
  ...this["~orpc"],
255
- meta: mergeMeta(this["~orpc"].meta, meta)
184
+ handler
256
185
  });
186
+ const plugins = getHiddenMetaPlugins(handler);
187
+ if (plugins) {
188
+ procedure = procedure.meta(...plugins);
189
+ }
190
+ return procedure;
257
191
  }
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({
268
- ...this["~orpc"],
269
- route: mergeRoute(this["~orpc"].route, route)
192
+ router(router) {
193
+ return augmentRouter(router, {
194
+ middlewares: this["~orpc"].orderedMiddlewares.map(({ middleware }) => middleware),
195
+ meta: this["~orpc"].meta,
196
+ metaPlugins: this["~orpc"].metaPlugins,
197
+ errorMap: this["~orpc"].errorMap
270
198
  });
271
199
  }
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
200
+ lazy(loader) {
201
+ return new Lazy({
202
+ loader: async () => {
203
+ const { default: router } = await loader();
204
+ return {
205
+ default: this.router(router)
206
+ };
207
+ },
208
+ meta: this["~orpc"].meta,
209
+ metaPlugins: this["~orpc"].metaPlugins
282
210
  });
283
211
  }
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
- });
212
+ }
213
+ const os = Builder.create();
214
+
215
+ class ProcedureImplementer {
216
+ "~orpc";
217
+ constructor(definition) {
218
+ this["~orpc"] = definition;
295
219
  }
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({
220
+ "use"(middleware) {
221
+ return new ProcedureImplementer({
303
222
  ...this["~orpc"],
304
- handler
223
+ orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
224
+ middleware,
225
+ inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
226
+ outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
227
+ }]
305
228
  });
306
229
  }
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({
230
+ "handler"(handler) {
231
+ return new ImplementedProcedure({
317
232
  ...this["~orpc"],
318
- prefix: mergePrefix(this["~orpc"].prefix, prefix)
233
+ handler,
234
+ /**
235
+ * When enabled, errors returned (not thrown) by the handler are passed through as-is,
236
+ * rather than being transformed into inferrable errors.
237
+ *
238
+ * This is intended for the contract-first approach, where the procedure adheres to an
239
+ * external contract and returned errors should not affect the inferred contract types.
240
+ */
241
+ opaqueReturnedErrors: true
319
242
  });
320
243
  }
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({
244
+ }
245
+ class ImplementedProcedure extends Procedure {
246
+ use(middleware) {
247
+ return new ImplementedProcedure({
329
248
  ...this["~orpc"],
330
- tags: mergeTags(this["~orpc"].tags, tags)
249
+ orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
250
+ middleware,
251
+ inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
252
+ outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
253
+ }]
331
254
  });
332
255
  }
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
- */
256
+ }
257
+
258
+ class SharedRouterImplementer {
259
+ constructor(contract, middlewares) {
260
+ this.contract = contract;
261
+ this.middlewares = middlewares;
262
+ }
263
+ static create(contract, middlewares = []) {
264
+ return new SharedRouterImplementer(contract, middlewares);
265
+ }
266
+ use(middleware) {
267
+ return createRouterImplementerInternal(this.contract, [...this.middlewares, middleware]);
268
+ }
269
+ middleware(middleware) {
270
+ const allMiddlewares = [
271
+ ...this.middlewares,
272
+ middleware
273
+ ];
274
+ let current = decorateMiddleware(allMiddlewares.shift());
275
+ for (const mid of allMiddlewares) {
276
+ current = current.use(mid);
277
+ }
278
+ return current;
279
+ }
338
280
  router(router) {
339
- return enhanceRouter(router, this["~orpc"]);
281
+ if (this.middlewares.length) {
282
+ router = augmentImplementedRouter(router, {
283
+ middlewares: this.middlewares
284
+ });
285
+ }
286
+ return withHiddenRouterContract(router, this.contract);
340
287
  }
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
288
  lazy(loader) {
348
- return enhanceRouter(lazy(loader), this["~orpc"]);
289
+ if (this.middlewares.length) {
290
+ const originalLoader = loader;
291
+ loader = async () => {
292
+ const { default: router } = await originalLoader();
293
+ return {
294
+ default: augmentImplementedRouter(router, {
295
+ middlewares: this.middlewares
296
+ })
297
+ };
298
+ };
299
+ }
300
+ return new Lazy({ loader, meta: {} });
349
301
  }
350
302
  }
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({
303
+ function createRouterImplementer(contract) {
304
+ return createRouterImplementerInternal(contract, []);
305
+ }
306
+ function createRouterImplementerInternal(contract, middlewares) {
307
+ if (contract instanceof ProcedureContract) {
308
+ return new ProcedureImplementer({
365
309
  ...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)
310
+ orderedMiddlewares: middlewares.map((middleware) => ({ middleware }))
371
311
  });
372
- return impl2;
373
312
  }
374
- const impl = new Proxy(contract, {
375
- get: (target, key) => {
376
- if (typeof key !== "string") {
377
- return Reflect.get(target, key);
378
- }
313
+ const implementer = {};
314
+ for (const key in contract) {
315
+ const child = contract[key];
316
+ implementer[key] = createRouterImplementerInternal(child, middlewares);
317
+ }
318
+ const shared = bindMethods(SharedRouterImplementer.create(contract, middlewares));
319
+ for (const key in shared) {
320
+ const method = shared[key];
321
+ if (key in implementer) {
322
+ const child = implementer[key];
323
+ implementer[key] = new Proxy(method, {
324
+ get(_, p) {
325
+ return getOrBind(child, p);
326
+ }
327
+ });
328
+ } else {
329
+ implementer[key] = method;
330
+ }
331
+ }
332
+ return implementer;
333
+ }
334
+
335
+ function implement(contract) {
336
+ const routerImplementer = createRouterImplementer(contract);
337
+ const implementer = new Proxy(routerImplementer, {
338
+ get(_, p) {
379
339
  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;
340
+ if (p === "$context") {
341
+ method = () => implementer;
416
342
  }
417
- const nextImpl = implementerInternal(next, config, middlewares);
343
+ const value = getOrBind(routerImplementer, p);
418
344
  if (method) {
345
+ if (!isTypescriptObject(value)) {
346
+ return method;
347
+ }
419
348
  return new Proxy(method, {
420
- get(_, key2) {
421
- return Reflect.get(nextImpl, key2);
349
+ get(_2, p2) {
350
+ return getOrBind(value, p2);
422
351
  }
423
352
  });
424
353
  }
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
- });
354
+ return value;
449
355
  }
450
356
  });
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
- };
357
+ return implementer;
465
358
  }
466
359
 
467
360
  function createRouterClient(router, ...rest) {
468
361
  const options = resolveMaybeOptionalOptions(rest);
469
- if (isProcedure(router)) {
470
- const caller = createProcedureClient(router, options);
471
- return caller;
362
+ if (router instanceof Procedure) {
363
+ return createProcedureClient(router, options);
472
364
  }
473
- const procedureCaller = isLazy(router) ? createProcedureClient(createAssertedLazyProcedure(router), options) : {};
365
+ const procedureCaller = router instanceof Lazy ? createProcedureClient(createGuardedProcedureLazy(router), options) : {};
474
366
  const recursive = new Proxy(procedureCaller, {
475
367
  get(target, key) {
476
- if (typeof key !== "string") {
477
- return Reflect.get(target, key);
368
+ if (typeof key !== "string" || router instanceof Lazy && RECURSIVE_CLIENT_UNWRAP_KEYS.has(key)) {
369
+ return getOrBind(target, key);
478
370
  }
479
371
  const next = getRouter(router, [key]);
480
372
  if (!next) {
481
- return Reflect.get(target, key);
373
+ return getOrBind(target, key);
482
374
  }
483
- return createRouterClient(next, {
484
- ...rest[0],
485
- path: [...rest[0]?.path ?? [], key]
375
+ const nextClient = createRouterClient(next, {
376
+ ...options,
377
+ path: [...toArray(options.path), key]
486
378
  });
379
+ return nextClient;
487
380
  }
488
381
  });
489
382
  return recursive;
490
383
  }
491
384
 
492
- export { Builder, DecoratedProcedure, Procedure, addMiddleware, createActionableClient, createAssertedLazyProcedure, createProcedureClient, createRouterClient, decorateMiddleware, enhanceRouter, fallbackConfig, getRouter, implement, implementerInternal, inferRPCMethodFromRouter, isLazy, isProcedure, lazy, os, setHiddenRouterContract, unlazy };
385
+ export { Builder, DecoratedProcedure, ImplementedProcedure, Lazy, Procedure, ProcedureImplementer, SharedRouterImplementer, augmentImplementedRouter, augmentRouter, createGuardedProcedureLazy, createProcedureClient, createRouterClient, createRouterImplementer, decorateMiddleware, getRouter, implement, os, withHiddenRouterContract };