@temporary-name/server 1.9.3-alpha.82e5e55517330d6049913c9b2f19e60239cd25d9 → 1.9.3-alpha.907c7c78d0193d34752279de92d699e50d6bc3a1

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 (42) hide show
  1. package/dist/adapters/aws-lambda/index.d.mts +4 -6
  2. package/dist/adapters/aws-lambda/index.d.ts +4 -6
  3. package/dist/adapters/aws-lambda/index.mjs +5 -7
  4. package/dist/adapters/fetch/index.d.mts +8 -86
  5. package/dist/adapters/fetch/index.d.ts +8 -86
  6. package/dist/adapters/fetch/index.mjs +17 -158
  7. package/dist/adapters/node/index.d.mts +8 -63
  8. package/dist/adapters/node/index.d.ts +8 -63
  9. package/dist/adapters/node/index.mjs +15 -123
  10. package/dist/adapters/standard/index.d.mts +20 -33
  11. package/dist/adapters/standard/index.d.ts +20 -33
  12. package/dist/adapters/standard/index.mjs +5 -7
  13. package/dist/helpers/index.mjs +3 -29
  14. package/dist/index.d.mts +121 -469
  15. package/dist/index.d.ts +121 -469
  16. package/dist/index.mjs +242 -445
  17. package/dist/openapi/index.d.mts +12 -28
  18. package/dist/openapi/index.d.ts +12 -28
  19. package/dist/openapi/index.mjs +66 -150
  20. package/dist/shared/server.Bj_UpI5O.d.mts +372 -0
  21. package/dist/shared/server.Bj_UpI5O.d.ts +372 -0
  22. package/dist/shared/server.C1RJffw4.mjs +30 -0
  23. package/dist/shared/server.C6VnFy4S.d.mts +41 -0
  24. package/dist/shared/server.CQIFwyhc.mjs +40 -0
  25. package/dist/shared/server.ChOv1yG3.mjs +319 -0
  26. package/dist/shared/server.CnzXkSjj.d.ts +41 -0
  27. package/dist/shared/server.DXzEGRE2.mjs +403 -0
  28. package/dist/shared/server.DgzAlPjF.mjs +160 -0
  29. package/dist/shared/server.YUvuxHty.mjs +48 -0
  30. package/package.json +10 -26
  31. package/dist/plugins/index.d.mts +0 -160
  32. package/dist/plugins/index.d.ts +0 -160
  33. package/dist/plugins/index.mjs +0 -288
  34. package/dist/shared/server.BEHw7Eyx.mjs +0 -247
  35. package/dist/shared/server.BKSOrA6h.d.mts +0 -192
  36. package/dist/shared/server.BKSOrA6h.d.ts +0 -192
  37. package/dist/shared/server.BKh8I1Ny.mjs +0 -239
  38. package/dist/shared/server.BeuTpcmO.d.mts +0 -23
  39. package/dist/shared/server.C1fnTLq0.d.mts +0 -57
  40. package/dist/shared/server.CQyYNJ1H.d.ts +0 -57
  41. package/dist/shared/server.DLsti1Pv.mjs +0 -293
  42. package/dist/shared/server.SLLuK6_v.d.ts +0 -23
package/dist/index.mjs CHANGED
@@ -1,334 +1,176 @@
1
- import { isContractProcedure, mergeErrorMap, mergeMeta, mergeRoute, mergePrefix, enhanceRoute, mergeTags, getContractRouter } from '@temporary-name/contract';
2
- export { ValidationError, eventIterator, type, validateORPCError } from '@temporary-name/contract';
3
- import { onError, resolveMaybeOptionalOptions } from '@temporary-name/shared';
4
- export { AsyncIteratorClass, EventPublisher, ORPCError, asyncIteratorToStream as eventIteratorToStream, isDefinedError, onError, onFinish, onStart, onSuccess, safe, streamToAsyncIteratorClass as streamToEventIterator } from '@temporary-name/shared';
5
- import { c as createProcedureClient, i as isLazy, g as getLazyMeta, l as lazy, u as unlazy, a as gatingContext } from './shared/server.BKh8I1Ny.mjs';
6
- export { L as LAZY_SYMBOL, b as createORPCErrorConstructorMap, m as mergeCurrentContext, d as middlewareOutputFn } from './shared/server.BKh8I1Ny.mjs';
1
+ import { assertNever, splitFirst, ORPCError, onError, resolveMaybeOptionalOptions, isTypescriptObject, isPropertyKey } from '@temporary-name/shared';
2
+ export { AsyncIteratorClass, EventPublisher, ORPCError, asyncIteratorToStream as eventIteratorToStream, isDefinedError, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@temporary-name/shared';
3
+ import * as z from '@temporary-name/zod';
4
+ import { SchemaClass, object, core, gatingContext } from '@temporary-name/zod';
5
+ import { g as getCookie } from './shared/server.C1RJffw4.mjs';
6
+ import { P as Procedure, m as mergePrefix, a as mergeTags, e as enhanceRouter, C as Contract, p as parseEndpointDefinition, b as mergeRoute, c as prefixRoute, d as addMiddleware, l as lazyInternal, f as getLazyMeta, u as unlazy, i as isProcedure, h as isLazy, j as getRouter } from './shared/server.ChOv1yG3.mjs';
7
+ export { L as LAZY_SYMBOL, V as ValidationError, q as createAccessibleLazyRouter, w as endpointRegex, g as getDynamicParams, n as isStartWithMiddlewares, k as lazy, o as mergeMiddlewares, r as resolveContractProcedures, s as standardizeHTTPPath, t as traverseContractProcedures, v as unlazyRouter } from './shared/server.ChOv1yG3.mjs';
8
+ import { c as createProcedureClient } from './shared/server.DgzAlPjF.mjs';
9
+ export { m as mergeCurrentContext, a as middlewareOutputFn } from './shared/server.DgzAlPjF.mjs';
10
+ export { e as eventIterator, g as getEventIteratorSchemaDetails } from './shared/server.YUvuxHty.mjs';
7
11
  export { getEventMeta, withEventMeta } from '@temporary-name/standard-server';
8
- import 'node:async_hooks';
9
- import 'zod';
10
- import 'zod/v4/core';
12
+ import 'cookie';
11
13
 
12
- function decorateMiddleware(middleware) {
13
- const decorated = ((...args) => middleware(...args));
14
- decorated.mapInput = (mapInput) => {
15
- const mapped = decorateMiddleware(
16
- (options, input, ...rest) => middleware(options, mapInput(input), ...rest)
17
- );
18
- return mapped;
19
- };
20
- decorated.concat = (concatMiddleware, mapInput) => {
21
- const mapped = mapInput ? decorateMiddleware(concatMiddleware).mapInput(mapInput) : concatMiddleware;
22
- const concatted = decorateMiddleware((options, input, output, ...rest) => {
23
- const merged = middleware(
24
- {
25
- ...options,
26
- next: (...[nextOptions1]) => mapped(
27
- {
28
- ...options,
29
- context: { ...options.context, ...nextOptions1?.context },
30
- next: (...[nextOptions2]) => options.next({ context: { ...nextOptions1?.context, ...nextOptions2?.context } })
31
- },
32
- input,
33
- output,
34
- ...rest
35
- )
36
- },
37
- input,
38
- output,
39
- ...rest
40
- );
41
- return merged;
42
- });
43
- return concatted;
44
- };
45
- return decorated;
46
- }
47
-
48
- function isStartWithMiddlewares(middlewares, compare) {
49
- if (compare.length > middlewares.length) {
50
- return false;
51
- }
52
- for (let i = 0; i < middlewares.length; i++) {
53
- if (compare[i] === void 0) {
54
- return true;
55
- }
56
- if (middlewares[i] !== compare[i]) {
57
- return false;
58
- }
14
+ function validateTokenPrefix(prefix, token) {
15
+ if (prefix && !token.startsWith(prefix)) {
16
+ throw new ORPCError("UNAUTHORIZED", { message: `Invalid auth token. It must start with "${prefix}"` });
59
17
  }
60
- return true;
61
18
  }
62
- function mergeMiddlewares(first, second, options) {
63
- if (options.dedupeLeading && isStartWithMiddlewares(second, first)) {
64
- return second;
65
- }
66
- return [...first, ...second];
19
+ function validateTokenAuth(config, token, options) {
20
+ const { tokenPrefix, validate } = config;
21
+ validateTokenPrefix(tokenPrefix, token);
22
+ return validate(token, options);
67
23
  }
68
- function addMiddleware(middlewares, addition) {
69
- return [...middlewares, addition];
24
+ function authByQuery(config, options) {
25
+ const { name, tokenPrefix, validate } = config;
26
+ const query = options.request.url.searchParams;
27
+ const token = query.get(name);
28
+ if (!token) return void 0;
29
+ validateTokenPrefix(tokenPrefix, token);
30
+ return validate(token, options);
70
31
  }
71
-
72
- class Procedure {
73
- /**
74
- * This property holds the defined options.
75
- */
76
- "~orpc";
77
- constructor(def) {
78
- this["~orpc"] = def;
79
- }
32
+ function authByHeader(config, options) {
33
+ const authHeader = options.request.headers.get(config.name);
34
+ return authHeader ? validateTokenAuth(config, authHeader, options) : void 0;
80
35
  }
81
- function isProcedure(item) {
82
- if (item instanceof Procedure) {
83
- return true;
84
- }
85
- return isContractProcedure(item) && "middlewares" in item["~orpc"] && "inputValidationIndex" in item["~orpc"] && "outputValidationIndex" in item["~orpc"] && "handler" in item["~orpc"];
36
+ function authByCookie(config, options) {
37
+ const cookie = getCookie(options.request.headers, config.name);
38
+ return cookie ? validateTokenAuth(config, cookie, options) : void 0;
39
+ }
40
+ function authByBearer(config, options) {
41
+ const authHeader = options.request.headers.get("Authorization");
42
+ if (!authHeader) return void 0;
43
+ const [authType, bearer] = splitFirst(authHeader, " ");
44
+ return authType === "Bearer" ? validateTokenAuth(config, bearer, options) : void 0;
45
+ }
46
+ function authByBasic(config, options) {
47
+ const authHeader = options.request.headers.get("Authorization");
48
+ if (!authHeader) return void 0;
49
+ const [authType, encoded] = splitFirst(authHeader, " ");
50
+ if (authType !== "Basic") return void 0;
51
+ const decoded = Buffer.from(encoded, "base64").toString("utf-8");
52
+ const [username, password] = splitFirst(decoded, ":");
53
+ validateTokenPrefix(config.tokenPrefix, password);
54
+ return config.validate(username, password, options);
55
+ }
56
+ function authByType(config, options) {
57
+ const { type } = config;
58
+ return type === "header" ? authByHeader(config, options) : type === "query" ? authByQuery(config, options) : type === "cookie" ? authByCookie(config, options) : type === "bearer" ? authByBearer(config, options) : type === "basic" ? authByBasic(config, options) : type === "none" ? false : assertNever(type);
59
+ }
60
+ function authDescription(config) {
61
+ const { type } = config;
62
+ return type === "basic" ? "a Basic Authentication header" : type === "bearer" ? "a Bearer Authentication header" : type === "header" ? `a header named "${config.name}"` : type === "query" ? `a query parameter named "${config.name}"` : type === "cookie" ? `a cookie named "${config.name}"` : type === "none" ? "no authentication" : assertNever(type);
63
+ }
64
+
65
+ function mergeMeta(meta1, meta2) {
66
+ return { ...meta1, ...meta2 };
86
67
  }
87
68
 
88
69
  class DecoratedProcedure extends Procedure {
89
70
  /**
90
- * Adds type-safe custom errors.
91
- * The provided errors are spared-merged with any existing errors.
71
+ * Make this procedure callable (works like a function while still being a procedure).
92
72
  *
93
- * @see {@link https://orpc.unnoq.com/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
73
+ * @see {@link https://orpc.unnoq.com/docs/client/server-side Server-side Client Docs}
94
74
  */
95
- errors(errors) {
96
- return new DecoratedProcedure({
97
- ...this["~orpc"],
98
- errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
75
+ callable(...rest) {
76
+ const client = createProcedureClient(this, ...rest);
77
+ return new Proxy(client, {
78
+ get: (target, key) => {
79
+ return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
80
+ },
81
+ has: (target, key) => {
82
+ return Reflect.has(this, key) || Reflect.has(target, key);
83
+ }
99
84
  });
100
85
  }
86
+ }
87
+
88
+ const initialSchemas = {
89
+ pathSchema: z.strictObject({}),
90
+ querySchema: z.strictObject({}),
91
+ bodySchema: z.strictObject({}),
92
+ outputSchema: z.unknown()
93
+ };
94
+
95
+ class ProcedureBuilder extends Contract {
96
+ z;
97
+ constructor(def) {
98
+ super(def);
99
+ this.z = new SchemaClass();
100
+ }
101
101
  /**
102
- * Sets or updates the metadata.
103
- * The provided metadata is spared-merged with any existing metadata.
102
+ * Sets or updates the metadata for the contract.
103
+ * The provided metadata is spared-merged with any existing metadata in the contract.
104
104
  *
105
105
  * @see {@link https://orpc.unnoq.com/docs/metadata Metadata Docs}
106
106
  */
107
107
  meta(meta) {
108
- return new DecoratedProcedure({
108
+ return new ProcedureBuilder({
109
109
  ...this["~orpc"],
110
110
  meta: mergeMeta(this["~orpc"].meta, meta)
111
111
  });
112
112
  }
113
+ endpoint(stringsOrEndpoint, ...values) {
114
+ const { method, path, pathSchema } = parseEndpointDefinition(stringsOrEndpoint, values);
115
+ const { prefix } = this["~orpc"];
116
+ const route = { method, path };
117
+ return new ProcedureBuilder({
118
+ ...this["~orpc"],
119
+ route: mergeRoute(this["~orpc"].route, prefix ? prefixRoute(route, prefix) : route),
120
+ schemas: {
121
+ ...this["~orpc"].schemas,
122
+ pathSchema
123
+ }
124
+ });
125
+ }
113
126
  /**
114
- * Sets or updates the route definition.
115
- * The provided route is spared-merged with any existing route.
127
+ * Sets or updates the route definition for the contract.
128
+ * The provided route is spared-merged with any existing route in the contract.
116
129
  * This option is typically relevant when integrating with OpenAPI.
117
130
  *
118
131
  * @see {@link https://orpc.unnoq.com/docs/openapi/routing OpenAPI Routing Docs}
119
132
  * @see {@link https://orpc.unnoq.com/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
120
133
  */
121
- route(route) {
122
- return new DecoratedProcedure({
134
+ endpointOpts(route) {
135
+ const { prefix } = this["~orpc"];
136
+ return new ProcedureBuilder({
123
137
  ...this["~orpc"],
124
- route: mergeRoute(this["~orpc"].route, route)
138
+ route: mergeRoute(this["~orpc"].route, prefix ? prefixRoute(route, prefix) : route)
125
139
  });
126
140
  }
127
- use(middleware, mapInput) {
128
- const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
129
- return new DecoratedProcedure({
141
+ query(schema) {
142
+ return new ProcedureBuilder({
130
143
  ...this["~orpc"],
131
- middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
132
- });
133
- }
134
- /**
135
- * Make this procedure callable (works like a function while still being a procedure).
136
- *
137
- * @see {@link https://orpc.unnoq.com/docs/client/server-side Server-side Client Docs}
138
- */
139
- callable(...rest) {
140
- const client = createProcedureClient(this, ...rest);
141
- return new Proxy(client, {
142
- get: (target, key) => {
143
- return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
144
+ schemas: {
145
+ ...this["~orpc"].schemas,
146
+ querySchema: schema instanceof core.$ZodType ? schema : object(schema)
144
147
  },
145
- has: (target, key) => {
146
- return Reflect.has(this, key) || Reflect.has(target, key);
147
- }
148
+ inputValidationIndex: this["~orpc"].middlewares.length
148
149
  });
149
150
  }
150
- }
151
-
152
- const HIDDEN_ROUTER_CONTRACT_SYMBOL = Symbol("ORPC_HIDDEN_ROUTER_CONTRACT");
153
- function setHiddenRouterContract(router, contract) {
154
- return new Proxy(router, {
155
- get(target, key) {
156
- if (key === HIDDEN_ROUTER_CONTRACT_SYMBOL) {
157
- return contract;
158
- }
159
- return Reflect.get(target, key);
160
- }
161
- });
162
- }
163
- function getHiddenRouterContract(router) {
164
- return router[HIDDEN_ROUTER_CONTRACT_SYMBOL];
165
- }
166
-
167
- function getRouter(router, path) {
168
- let current = router;
169
- for (let i = 0; i < path.length; i++) {
170
- const segment = path[i];
171
- if (!current) {
172
- return void 0;
173
- }
174
- if (isProcedure(current)) {
175
- return void 0;
176
- }
177
- if (!isLazy(current)) {
178
- current = current[segment];
179
- continue;
180
- }
181
- const lazied = current;
182
- const rest = path.slice(i);
183
- return lazy(async () => {
184
- const unwrapped = await unlazy(lazied);
185
- const next = getRouter(unwrapped.default, rest);
186
- return unlazy(next);
187
- }, getLazyMeta(lazied));
188
- }
189
- return current;
190
- }
191
- function createAccessibleLazyRouter(lazied) {
192
- const recursive = new Proxy(lazied, {
193
- get(target, key) {
194
- if (typeof key !== "string") {
195
- return Reflect.get(target, key);
196
- }
197
- const next = getRouter(lazied, [key]);
198
- return createAccessibleLazyRouter(next);
199
- }
200
- });
201
- return recursive;
202
- }
203
- function enhanceRouter(router, options) {
204
- if (isLazy(router)) {
205
- const laziedMeta = getLazyMeta(router);
206
- const enhancedPrefix = laziedMeta?.prefix ? mergePrefix(options.prefix, laziedMeta?.prefix) : options.prefix;
207
- const enhanced2 = lazy(
208
- async () => {
209
- const { default: unlaziedRouter } = await unlazy(router);
210
- const enhanced3 = enhanceRouter(unlaziedRouter, options);
211
- return unlazy(enhanced3);
151
+ body(schema) {
152
+ return new ProcedureBuilder({
153
+ ...this["~orpc"],
154
+ schemas: {
155
+ ...this["~orpc"].schemas,
156
+ bodySchema: schema instanceof core.$ZodType ? schema : object(schema)
212
157
  },
213
- {
214
- ...laziedMeta,
215
- prefix: enhancedPrefix
216
- }
217
- );
218
- const accessible = createAccessibleLazyRouter(enhanced2);
219
- return accessible;
220
- }
221
- if (isProcedure(router)) {
222
- const newMiddlewares = mergeMiddlewares(options.middlewares, router["~orpc"].middlewares, {
223
- dedupeLeading: options.dedupeLeadingMiddlewares
224
- });
225
- const newMiddlewareAdded = newMiddlewares.length - router["~orpc"].middlewares.length;
226
- const enhanced2 = new Procedure({
227
- ...router["~orpc"],
228
- route: enhanceRoute(router["~orpc"].route, options),
229
- errorMap: mergeErrorMap(options.errorMap, router["~orpc"].errorMap),
230
- middlewares: newMiddlewares,
231
- inputValidationIndex: router["~orpc"].inputValidationIndex + newMiddlewareAdded,
232
- outputValidationIndex: router["~orpc"].outputValidationIndex + newMiddlewareAdded
233
- });
234
- return enhanced2;
235
- }
236
- const enhanced = {};
237
- for (const key in router) {
238
- enhanced[key] = enhanceRouter(router[key], options);
239
- }
240
- return enhanced;
241
- }
242
- function traverseContractProcedures(options, callback, lazyOptions = []) {
243
- let currentRouter = options.router;
244
- const hiddenContract = getHiddenRouterContract(options.router);
245
- if (hiddenContract !== void 0) {
246
- currentRouter = hiddenContract;
247
- }
248
- if (isLazy(currentRouter)) {
249
- lazyOptions.push({
250
- router: currentRouter,
251
- path: options.path
252
- });
253
- } else if (isContractProcedure(currentRouter)) {
254
- callback({
255
- contract: currentRouter,
256
- path: options.path
158
+ inputValidationIndex: this["~orpc"].middlewares.length
257
159
  });
258
- } else {
259
- for (const key in currentRouter) {
260
- traverseContractProcedures(
261
- {
262
- router: currentRouter[key],
263
- path: [...options.path, key]
264
- },
265
- callback,
266
- lazyOptions
267
- );
268
- }
269
- }
270
- return lazyOptions;
271
- }
272
- async function resolveContractProcedures(options, callback) {
273
- const pending = [options];
274
- for (const options2 of pending) {
275
- const lazyOptions = traverseContractProcedures(options2, callback);
276
- for (const options3 of lazyOptions) {
277
- const { default: router } = await unlazy(options3.router);
278
- pending.push({
279
- router,
280
- path: options3.path
281
- });
282
- }
283
- }
284
- }
285
- async function unlazyRouter(router) {
286
- if (isProcedure(router)) {
287
- return router;
288
- }
289
- const unlazied = {};
290
- for (const key in router) {
291
- const item = router[key];
292
- const { default: unlaziedRouter } = await unlazy(item);
293
- unlazied[key] = await unlazyRouter(unlaziedRouter);
294
- }
295
- return unlazied;
296
- }
297
-
298
- class Builder {
299
- /**
300
- * This property holds the defined options.
301
- */
302
- "~orpc";
303
- constructor(def) {
304
- this["~orpc"] = def;
305
- }
306
- /**
307
- * Set or override the initial context.
308
- *
309
- * @see {@link https://orpc.unnoq.com/docs/context Context Docs}
310
- */
311
- $context() {
312
- return this;
313
160
  }
314
161
  /**
315
- * Creates a middleware.
316
- *
317
- * @see {@link https://orpc.unnoq.com/docs/middleware Middleware Docs}
318
- */
319
- middleware(middleware) {
320
- return decorateMiddleware(middleware);
321
- }
322
- /**
323
- * Adds type-safe custom errors.
324
- * The provided errors are spared-merged with any existing errors.
162
+ * Defines the output validation schema.
325
163
  *
326
- * @see {@link https://orpc.unnoq.com/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
164
+ * @see {@link https://orpc.unnoq.com/docs/procedure#input-output-validation Output Validation Docs}
327
165
  */
328
- errors(errors) {
329
- return new Builder({
166
+ output(schema) {
167
+ return new ProcedureBuilder({
330
168
  ...this["~orpc"],
331
- errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
169
+ schemas: {
170
+ ...this["~orpc"].schemas,
171
+ outputSchema: schema instanceof core.$ZodType ? schema : object(schema)
172
+ },
173
+ outputValidationIndex: this["~orpc"].middlewares.length
332
174
  });
333
175
  }
334
176
  /**
@@ -339,11 +181,41 @@ class Builder {
339
181
  * @see {@link https://orpc.unnoq.com/docs/middleware Middleware Docs}
340
182
  */
341
183
  use(middleware) {
342
- return new Builder({
184
+ return new this.constructor({
343
185
  ...this["~orpc"],
344
186
  middlewares: addMiddleware(this["~orpc"].middlewares, middleware)
345
187
  });
346
188
  }
189
+ // `& {}` is so AuthType will be expanded in parameter info tooltips.
190
+ // The default of false for ValidatedAuthContext is used when you pass in the type 'none'. We use false
191
+ // because we can't use null or undefined (see ValidatedAuthContext) but we still want it to be falsy.
192
+ useAuth(type, ...rest) {
193
+ const config = { type, ...rest[0] };
194
+ const middleware = os.$context().middleware(async (options) => {
195
+ const { next, context } = options;
196
+ if (context.auth) return next();
197
+ const auth = await authByType(config, options);
198
+ if (auth === void 0) {
199
+ const { authConfigs } = options.procedure["~orpc"];
200
+ if (context.auth !== false && config === authConfigs.at(-1)) {
201
+ let authDescriptions = authConfigs.map(authDescription).join(", ");
202
+ if (authConfigs.length > 1) {
203
+ authDescriptions = `one of: ${authDescriptions}`;
204
+ }
205
+ throw new ORPCError("UNAUTHORIZED", {
206
+ message: `Authentication required. You must provide ${authDescriptions}`
207
+ });
208
+ }
209
+ return next();
210
+ }
211
+ return next({ context: { auth } });
212
+ });
213
+ return new this.constructor({
214
+ ...this["~orpc"],
215
+ authConfigs: [...this["~orpc"].authConfigs, config],
216
+ middlewares: addMiddleware(this["~orpc"].middlewares, middleware)
217
+ });
218
+ }
347
219
  useGating(gates, isGateEnabled) {
348
220
  return this.use(({ next, context }) => {
349
221
  return gatingContext.run(
@@ -352,67 +224,22 @@ class Builder {
352
224
  );
353
225
  });
354
226
  }
355
- /**
356
- * Sets or updates the metadata.
357
- * The provided metadata is spared-merged with any existing metadata.
358
- *
359
- * @see {@link https://orpc.unnoq.com/docs/metadata Metadata Docs}
360
- */
361
- meta(meta) {
362
- return new Builder({
363
- ...this["~orpc"],
364
- meta: mergeMeta(this["~orpc"].meta, meta)
365
- });
366
- }
367
- /**
368
- * Sets or updates the route definition.
369
- * The provided route is spared-merged with any existing route.
370
- * This option is typically relevant when integrating with OpenAPI.
371
- *
372
- * @see {@link https://orpc.unnoq.com/docs/openapi/routing OpenAPI Routing Docs}
373
- * @see {@link https://orpc.unnoq.com/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
374
- */
375
- route(route) {
376
- return new Builder({
377
- ...this["~orpc"],
378
- route: mergeRoute(this["~orpc"].route, route)
379
- });
380
- }
381
- /**
382
- * Defines the input validation schema.
383
- *
384
- * @see {@link https://orpc.unnoq.com/docs/procedure#input-output-validation Input Validation Docs}
385
- */
386
- input(schema) {
387
- return new Builder({
388
- ...this["~orpc"],
389
- inputSchema: schema,
390
- inputValidationIndex: this["~orpc"].middlewares.length
391
- });
392
- }
393
- /**
394
- * Defines the output validation schema.
395
- *
396
- * @see {@link https://orpc.unnoq.com/docs/procedure#input-output-validation Output Validation Docs}
397
- */
398
- output(schema) {
399
- return new Builder({
400
- ...this["~orpc"],
401
- outputSchema: schema,
402
- outputValidationIndex: this["~orpc"].middlewares.length
403
- });
404
- }
405
227
  /**
406
228
  * Defines the handler of the procedure.
407
229
  *
408
230
  * @see {@link https://orpc.unnoq.com/docs/procedure Procedure Docs}
409
231
  */
410
232
  handler(handler) {
233
+ if (this["~orpc"].schemas.outputSchema === initialSchemas.outputSchema) {
234
+ throw new Error("You must call .output() before calling .handler()");
235
+ }
411
236
  return new DecoratedProcedure({
412
237
  ...this["~orpc"],
413
238
  handler
414
239
  });
415
240
  }
241
+ }
242
+ class BuilderWithMiddlewares extends ProcedureBuilder {
416
243
  /**
417
244
  * Prefixes all procedures in the router.
418
245
  * The provided prefix is post-appended to any existing router prefix.
@@ -422,7 +249,7 @@ class Builder {
422
249
  * @see {@link https://orpc.unnoq.com/docs/openapi/routing#route-prefixes OpenAPI Route Prefixes Docs}
423
250
  */
424
251
  prefix(prefix) {
425
- return new Builder({
252
+ return new this.constructor({
426
253
  ...this["~orpc"],
427
254
  prefix: mergePrefix(this["~orpc"].prefix, prefix)
428
255
  });
@@ -434,7 +261,7 @@ class Builder {
434
261
  * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification#operation-metadata OpenAPI Operation Metadata Docs}
435
262
  */
436
263
  tag(...tags) {
437
- return new Builder({
264
+ return new this.constructor({
438
265
  ...this["~orpc"],
439
266
  tags: mergeTags(this["~orpc"].tags, tags)
440
267
  });
@@ -447,123 +274,84 @@ class Builder {
447
274
  router(router) {
448
275
  return enhanceRouter(router, this["~orpc"]);
449
276
  }
277
+ }
278
+
279
+ function decorateMiddleware(middleware) {
280
+ const decorated = ((...args) => middleware(...args));
281
+ decorated.mapInput = (mapInput) => {
282
+ const mapped = decorateMiddleware(
283
+ (options, input, ...rest) => middleware(options, mapInput(input), ...rest)
284
+ );
285
+ return mapped;
286
+ };
287
+ decorated.concat = (concatMiddleware, mapInput) => {
288
+ const mapped = mapInput ? decorateMiddleware(concatMiddleware).mapInput(mapInput) : concatMiddleware;
289
+ const concatted = decorateMiddleware((options, input, output, ...rest) => {
290
+ const merged = middleware(
291
+ {
292
+ ...options,
293
+ next: (...[nextOptions1]) => mapped(
294
+ {
295
+ ...options,
296
+ context: { ...options.context, ...nextOptions1?.context },
297
+ next: (...[nextOptions2]) => options.next({ context: { ...nextOptions1?.context, ...nextOptions2?.context } })
298
+ },
299
+ input,
300
+ output,
301
+ ...rest
302
+ )
303
+ },
304
+ input,
305
+ output,
306
+ ...rest
307
+ );
308
+ return merged;
309
+ });
310
+ return concatted;
311
+ };
312
+ return decorated;
313
+ }
314
+
315
+ class Builder extends BuilderWithMiddlewares {
450
316
  /**
451
- * Create a lazy router
452
- * And applies all of the previously defined options to the specified router.
317
+ * Set or override the initial context.
453
318
  *
454
- * @see {@link https://orpc.unnoq.com/docs/router#extending-router Extending Router Docs}
319
+ * @see {@link https://orpc.unnoq.com/docs/context Context Docs}
455
320
  */
456
- lazyRoute(loader) {
457
- return enhanceRouter(lazy(loader), this["~orpc"]);
321
+ $context() {
322
+ return this;
323
+ }
324
+ /**
325
+ * Creates a middleware.
326
+ *
327
+ * @see {@link https://orpc.unnoq.com/docs/middleware Middleware Docs}
328
+ */
329
+ middleware(middleware) {
330
+ return decorateMiddleware(middleware);
458
331
  }
459
332
  }
460
333
  function createApiBuilder(opts = {}) {
461
- const base = new Builder({
334
+ return new Builder({
462
335
  route: {},
463
336
  meta: opts.meta ?? {},
464
- errorMap: {},
465
337
  inputValidationIndex: 0,
466
338
  outputValidationIndex: 0,
467
339
  middlewares: [
468
- onError((error, options) => {
340
+ onError((error, _options) => {
469
341
  console.dir(error, { depth: null });
470
342
  })
471
343
  ],
344
+ schemas: initialSchemas,
472
345
  // NB: this is a relic from orpc -- I'm not convinced there's a need for this (or if there is, that it's
473
346
  // the best solution). For now I've removed the interface to configure it externally.
474
- dedupeLeadingMiddlewares: true
347
+ dedupeLeadingMiddlewares: true,
348
+ authConfigs: []
475
349
  });
476
- return base;
477
350
  }
478
351
  const os = createApiBuilder();
479
352
 
480
- function implementerInternal(contract, middlewares) {
481
- if (isContractProcedure(contract)) {
482
- const impl2 = new Builder({
483
- ...contract["~orpc"],
484
- middlewares,
485
- inputValidationIndex: middlewares.length,
486
- outputValidationIndex: middlewares.length,
487
- dedupeLeadingMiddlewares: true
488
- });
489
- return impl2;
490
- }
491
- const impl = new Proxy(contract, {
492
- get: (target, key) => {
493
- if (typeof key !== "string") {
494
- return Reflect.get(target, key);
495
- }
496
- let method;
497
- if (key === "middleware") {
498
- method = (mid) => decorateMiddleware(mid);
499
- } else if (key === "use") {
500
- method = (mid) => {
501
- return implementerInternal(contract, addMiddleware(middlewares, mid));
502
- };
503
- } else if (key === "router") {
504
- method = (router) => {
505
- const adapted = enhanceRouter(router, {
506
- middlewares,
507
- errorMap: {},
508
- prefix: void 0,
509
- tags: void 0,
510
- dedupeLeadingMiddlewares: true
511
- });
512
- return setHiddenRouterContract(adapted, contract);
513
- };
514
- } else if (key === "lazyRoute") {
515
- method = (loader) => {
516
- const adapted = enhanceRouter(lazy(loader), {
517
- middlewares,
518
- errorMap: {},
519
- prefix: void 0,
520
- tags: void 0,
521
- dedupeLeadingMiddlewares: true
522
- });
523
- return setHiddenRouterContract(adapted, contract);
524
- };
525
- }
526
- const next = getContractRouter(target, [key]);
527
- if (!next) {
528
- return method ?? next;
529
- }
530
- const nextImpl = implementerInternal(next, middlewares);
531
- if (method) {
532
- return new Proxy(method, {
533
- get(_, key2) {
534
- return Reflect.get(nextImpl, key2);
535
- }
536
- });
537
- }
538
- return nextImpl;
539
- }
540
- });
541
- return impl;
542
- }
543
- function implement(contract) {
544
- const implInternal = implementerInternal(contract, []);
545
- const impl = new Proxy(implInternal, {
546
- get: (target, key) => {
547
- let method;
548
- if (key === "$context") {
549
- method = () => impl;
550
- }
551
- const next = Reflect.get(target, key);
552
- if (!method || !next || typeof next !== "function" && typeof next !== "object") {
553
- return method || next;
554
- }
555
- return new Proxy(method, {
556
- get(_, key2) {
557
- return Reflect.get(next, key2);
558
- }
559
- });
560
- }
561
- });
562
- return impl;
563
- }
564
-
565
353
  function createAssertedLazyProcedure(lazied) {
566
- const lazyProcedure = lazy(async () => {
354
+ const lazyProcedure = lazyInternal(async () => {
567
355
  const { default: maybeProcedure } = await unlazy(lazied);
568
356
  if (!isProcedure(maybeProcedure)) {
569
357
  throw new Error(`
@@ -576,14 +364,6 @@ function createAssertedLazyProcedure(lazied) {
576
364
  }, getLazyMeta(lazied));
577
365
  return lazyProcedure;
578
366
  }
579
- function createContractedProcedure(procedure, contract) {
580
- return new Procedure({
581
- ...procedure["~orpc"],
582
- errorMap: contract["~orpc"].errorMap,
583
- route: contract["~orpc"].route,
584
- meta: contract["~orpc"].meta
585
- });
586
- }
587
367
  function call(procedure, input, ...rest) {
588
368
  const options = resolveMaybeOptionalOptions(rest);
589
369
  return createProcedureClient(procedure, options)(input, options);
@@ -614,4 +394,21 @@ function createRouterClient(router, ...rest) {
614
394
  return recursive;
615
395
  }
616
396
 
617
- export { Builder, DecoratedProcedure, Procedure, addMiddleware, call, createAccessibleLazyRouter, createApiBuilder, createAssertedLazyProcedure, createContractedProcedure, createProcedureClient, createRouterClient, decorateMiddleware, enhanceRouter, getHiddenRouterContract, getLazyMeta, getRouter, implement, implementerInternal, isLazy, isProcedure, isStartWithMiddlewares, lazy, mergeMiddlewares, os, resolveContractProcedures, setHiddenRouterContract, traverseContractProcedures, unlazy, unlazyRouter };
397
+ function isSchemaIssue(issue) {
398
+ if (!isTypescriptObject(issue) || typeof issue.message !== "string") {
399
+ return false;
400
+ }
401
+ if (issue.path !== void 0) {
402
+ if (!Array.isArray(issue.path)) {
403
+ return false;
404
+ }
405
+ if (!issue.path.every(
406
+ (segment) => isPropertyKey(segment) || isTypescriptObject(segment) && isPropertyKey(segment.key)
407
+ )) {
408
+ return false;
409
+ }
410
+ }
411
+ return true;
412
+ }
413
+
414
+ export { Builder, BuilderWithMiddlewares, Contract, DecoratedProcedure, Procedure, ProcedureBuilder, addMiddleware, call, createApiBuilder, createAssertedLazyProcedure, createProcedureClient, createRouterClient, decorateMiddleware, enhanceRouter, getLazyMeta, getRouter, initialSchemas, isLazy, isProcedure, isSchemaIssue, lazyInternal, mergeMeta, os, parseEndpointDefinition, unlazy };