@orpc/openapi 2.0.0-beta.2 → 2.0.0-beta.20

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 (29) hide show
  1. package/README.md +32 -21
  2. package/dist/adapters/fetch/index.d.mts +2 -2
  3. package/dist/adapters/fetch/index.d.ts +2 -2
  4. package/dist/adapters/fetch/index.mjs +3 -3
  5. package/dist/adapters/node/index.d.mts +2 -2
  6. package/dist/adapters/node/index.d.ts +2 -2
  7. package/dist/adapters/node/index.mjs +2 -2
  8. package/dist/adapters/standard/index.d.mts +2 -2
  9. package/dist/adapters/standard/index.d.ts +2 -2
  10. package/dist/adapters/standard/index.mjs +3 -3
  11. package/dist/extensions/route.d.mts +2 -2
  12. package/dist/extensions/route.d.ts +2 -2
  13. package/dist/index.d.mts +55 -34
  14. package/dist/index.d.ts +55 -34
  15. package/dist/index.mjs +682 -661
  16. package/dist/plugins/index.d.mts +1 -1
  17. package/dist/plugins/index.d.ts +1 -1
  18. package/dist/shared/{openapi.BYcWgK1j.d.ts → openapi.B6hEbRyF.d.ts} +18 -14
  19. package/dist/shared/{openapi.C7m7NAmH.d.mts → openapi.BOOA-bde.d.mts} +1 -1
  20. package/dist/shared/{openapi.C7m7NAmH.d.ts → openapi.BOOA-bde.d.ts} +1 -1
  21. package/dist/shared/{openapi.XeW6_5tm.d.mts → openapi.BafbB3uM.d.mts} +18 -14
  22. package/dist/shared/{openapi.CYgMBSUF.d.mts → openapi.ByT4oUeY.d.mts} +2 -2
  23. package/dist/shared/{openapi.CYgMBSUF.d.ts → openapi.ByT4oUeY.d.ts} +2 -2
  24. package/dist/shared/{openapi.B2SK0ZAr.mjs → openapi.C-p_Q2lb.mjs} +4 -4
  25. package/dist/shared/{openapi.DR-y5p-D.mjs → openapi.CVgUshDP.mjs} +28 -25
  26. package/dist/shared/{openapi.BQzzr4-4.d.ts → openapi.DNNo0V-l.d.ts} +23 -9
  27. package/dist/shared/{openapi.BcEtAxQj.d.mts → openapi.hg_rhZ4x.d.mts} +23 -9
  28. package/dist/shared/{openapi.DmAa7YPO.mjs → openapi.zZH_UksW.mjs} +7 -4
  29. package/package.json +28 -12
@@ -4,7 +4,7 @@ import { Value, Promisable } from '@orpc/shared';
4
4
  import { ApiReferenceConfiguration } from '@scalar/api-reference';
5
5
  import { StandardUrl } from '@standardserver/core';
6
6
  import { SwaggerUIOptions } from 'swagger-ui';
7
- import { a as OpenAPIDocument } from '../shared/openapi.CYgMBSUF.mjs';
7
+ import { a as OpenAPIDocument } from '../shared/openapi.ByT4oUeY.mjs';
8
8
  import '@hey-api/spec-types';
9
9
  import '@orpc/client';
10
10
 
@@ -4,7 +4,7 @@ import { Value, Promisable } from '@orpc/shared';
4
4
  import { ApiReferenceConfiguration } from '@scalar/api-reference';
5
5
  import { StandardUrl } from '@standardserver/core';
6
6
  import { SwaggerUIOptions } from 'swagger-ui';
7
- import { a as OpenAPIDocument } from '../shared/openapi.CYgMBSUF.js';
7
+ import { a as OpenAPIDocument } from '../shared/openapi.ByT4oUeY.js';
8
8
  import '@hey-api/spec-types';
9
9
  import '@orpc/client';
10
10
 
@@ -4,7 +4,7 @@ import { StandardHandlerCodec, StandardHandlerHandleOptions, StandardHandlerCode
4
4
  import { Value, Promisable } from '@orpc/shared';
5
5
  import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
6
6
  import { AnyProcedureContract } from '@orpc/contract';
7
- import { O as OpenAPISerializer } from './openapi.C7m7NAmH.js';
7
+ import { O as OpenAPISerializer } from './openapi.BOOA-bde.js';
8
8
 
9
9
  interface OpenAPIMatcherOptions {
10
10
  /**
@@ -31,17 +31,16 @@ declare class OpenAPIMatcher {
31
31
  private resolveProcedure;
32
32
  }
33
33
 
34
- declare class OpenAPIHandlerCodecError extends TypeError {
35
- }
36
- interface OpenAPIHandlerCodecOptions<_T extends Context> extends OpenAPIMatcherOptions {
34
+ interface OpenAPIHandlerCodecCoreOptions<_T extends Context> {
37
35
  /**
38
36
  * Override the default OpenAPI serializer.
39
37
  */
40
38
  serializer?: Pick<OpenAPISerializer, keyof OpenAPISerializer>;
41
39
  /**
42
40
  * Mapping ORPCError Code -> HTTP Status Code
41
+ * The status code should be in the `4xx` or `5xx` range (must be greater than or equal to `400`).
43
42
  *
44
- * @default COMMON_ERROR_STATUS_MAP, DEFAULT_ERROR_STATUS
43
+ * @default COMMON_ERROR_STATUS_MAP
45
44
  */
46
45
  errorStatusMap?: Record<string, number> | undefined;
47
46
  /**
@@ -55,25 +54,30 @@ interface OpenAPIHandlerCodecOptions<_T extends Context> extends OpenAPIMatcherO
55
54
  */
56
55
  customErrorResponseBodyEncoder?: (error: AnyORPCError) => unknown;
57
56
  }
58
- declare class OpenAPIHandlerCodec<T extends Context> implements StandardHandlerCodec<T> {
59
- private readonly matcher;
57
+ declare class OpenAPIHandlerCodecCore<T extends Context> {
60
58
  private readonly serializer;
61
59
  private readonly errorStatusMap;
62
60
  private readonly customErrorResponseBodySerializer;
63
- constructor(router: AnyRouter, options?: OpenAPIHandlerCodecOptions<T>);
61
+ constructor(options?: OpenAPIHandlerCodecCoreOptions<T>);
64
62
  decodeInput(matched: {
65
63
  procedure: AnyProcedure;
66
64
  params?: undefined | Record<string, string>;
67
65
  }, request: StandardLazyRequest): Promise<unknown>;
68
- resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerCodecResolvedProcedure | undefined>;
69
66
  /**
70
- * @throws {Error} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
67
+ * @throws {TypeError} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
71
68
  */
72
- encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
73
- encodeError(error: AnyORPCError, _procedure: AnyProcedure, _path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
69
+ encodeOutput(output: unknown, procedure: AnyProcedure, path: string[]): Promisable<StandardResponse>;
70
+ encodeError(error: AnyORPCError): Promisable<StandardResponse>;
74
71
  private deserializeQuery;
75
72
  private deserializeParams;
76
73
  }
74
+ interface OpenAPIHandlerCodecOptions<T extends Context> extends OpenAPIHandlerCodecCoreOptions<T>, OpenAPIMatcherOptions {
75
+ }
76
+ declare class OpenAPIHandlerCodec<T extends Context> extends OpenAPIHandlerCodecCore<T> implements StandardHandlerCodec<T> {
77
+ private readonly matcher;
78
+ constructor(router: AnyRouter, options?: OpenAPIHandlerCodecOptions<T>);
79
+ resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerCodecResolvedProcedure | undefined>;
80
+ }
77
81
 
78
- export { OpenAPIHandlerCodec as a, OpenAPIHandlerCodecError as b, OpenAPIMatcher as c };
79
- export type { OpenAPIHandlerCodecOptions as O, OpenAPIMatcherOptions as d };
82
+ export { OpenAPIHandlerCodec as a, OpenAPIHandlerCodecCore as b, OpenAPIMatcher as d };
83
+ export type { OpenAPIHandlerCodecOptions as O, OpenAPIHandlerCodecCoreOptions as c, OpenAPIMatcherOptions as e };
@@ -118,7 +118,7 @@ interface OpenAPISerializerSerializeOptions {
118
118
  */
119
119
  asFormData?: boolean | undefined;
120
120
  }
121
- interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPISerializerSerializeOptions {
121
+ interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions {
122
122
  /**
123
123
  * Options for bracket notation serializer, like maxExplicitDeserializingArrayIndex
124
124
  */
@@ -118,7 +118,7 @@ interface OpenAPISerializerSerializeOptions {
118
118
  */
119
119
  asFormData?: boolean | undefined;
120
120
  }
121
- interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPISerializerSerializeOptions {
121
+ interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions {
122
122
  /**
123
123
  * Options for bracket notation serializer, like maxExplicitDeserializingArrayIndex
124
124
  */
@@ -4,7 +4,7 @@ import { StandardHandlerCodec, StandardHandlerHandleOptions, StandardHandlerCode
4
4
  import { Value, Promisable } from '@orpc/shared';
5
5
  import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
6
6
  import { AnyProcedureContract } from '@orpc/contract';
7
- import { O as OpenAPISerializer } from './openapi.C7m7NAmH.mjs';
7
+ import { O as OpenAPISerializer } from './openapi.BOOA-bde.mjs';
8
8
 
9
9
  interface OpenAPIMatcherOptions {
10
10
  /**
@@ -31,17 +31,16 @@ declare class OpenAPIMatcher {
31
31
  private resolveProcedure;
32
32
  }
33
33
 
34
- declare class OpenAPIHandlerCodecError extends TypeError {
35
- }
36
- interface OpenAPIHandlerCodecOptions<_T extends Context> extends OpenAPIMatcherOptions {
34
+ interface OpenAPIHandlerCodecCoreOptions<_T extends Context> {
37
35
  /**
38
36
  * Override the default OpenAPI serializer.
39
37
  */
40
38
  serializer?: Pick<OpenAPISerializer, keyof OpenAPISerializer>;
41
39
  /**
42
40
  * Mapping ORPCError Code -> HTTP Status Code
41
+ * The status code should be in the `4xx` or `5xx` range (must be greater than or equal to `400`).
43
42
  *
44
- * @default COMMON_ERROR_STATUS_MAP, DEFAULT_ERROR_STATUS
43
+ * @default COMMON_ERROR_STATUS_MAP
45
44
  */
46
45
  errorStatusMap?: Record<string, number> | undefined;
47
46
  /**
@@ -55,25 +54,30 @@ interface OpenAPIHandlerCodecOptions<_T extends Context> extends OpenAPIMatcherO
55
54
  */
56
55
  customErrorResponseBodyEncoder?: (error: AnyORPCError) => unknown;
57
56
  }
58
- declare class OpenAPIHandlerCodec<T extends Context> implements StandardHandlerCodec<T> {
59
- private readonly matcher;
57
+ declare class OpenAPIHandlerCodecCore<T extends Context> {
60
58
  private readonly serializer;
61
59
  private readonly errorStatusMap;
62
60
  private readonly customErrorResponseBodySerializer;
63
- constructor(router: AnyRouter, options?: OpenAPIHandlerCodecOptions<T>);
61
+ constructor(options?: OpenAPIHandlerCodecCoreOptions<T>);
64
62
  decodeInput(matched: {
65
63
  procedure: AnyProcedure;
66
64
  params?: undefined | Record<string, string>;
67
65
  }, request: StandardLazyRequest): Promise<unknown>;
68
- resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerCodecResolvedProcedure | undefined>;
69
66
  /**
70
- * @throws {Error} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
67
+ * @throws {TypeError} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
71
68
  */
72
- encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
73
- encodeError(error: AnyORPCError, _procedure: AnyProcedure, _path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
69
+ encodeOutput(output: unknown, procedure: AnyProcedure, path: string[]): Promisable<StandardResponse>;
70
+ encodeError(error: AnyORPCError): Promisable<StandardResponse>;
74
71
  private deserializeQuery;
75
72
  private deserializeParams;
76
73
  }
74
+ interface OpenAPIHandlerCodecOptions<T extends Context> extends OpenAPIHandlerCodecCoreOptions<T>, OpenAPIMatcherOptions {
75
+ }
76
+ declare class OpenAPIHandlerCodec<T extends Context> extends OpenAPIHandlerCodecCore<T> implements StandardHandlerCodec<T> {
77
+ private readonly matcher;
78
+ constructor(router: AnyRouter, options?: OpenAPIHandlerCodecOptions<T>);
79
+ resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerCodecResolvedProcedure | undefined>;
80
+ }
77
81
 
78
- export { OpenAPIHandlerCodec as a, OpenAPIHandlerCodecError as b, OpenAPIMatcher as c };
79
- export type { OpenAPIHandlerCodecOptions as O, OpenAPIMatcherOptions as d };
82
+ export { OpenAPIHandlerCodec as a, OpenAPIHandlerCodecCore as b, OpenAPIMatcher as d };
83
+ export type { OpenAPIHandlerCodecOptions as O, OpenAPIHandlerCodecCoreOptions as c, OpenAPIMatcherOptions as e };
@@ -1,5 +1,5 @@
1
1
  import { OpenAPIV3_1 } from '@hey-api/spec-types';
2
- import { ORPCError, AnyNestedClient, Client } from '@orpc/client';
2
+ import { AnyNestedClient, Client, ORPCError } from '@orpc/client';
3
3
 
4
4
  type OpenAPIDocument = OpenAPIV3_1.Document;
5
5
  type OpenAPIOperationObject = OpenAPIV3_1.OperationObject;
@@ -15,4 +15,4 @@ type JsonifiedClient<T extends AnyNestedClient> = T extends Client<infer UClient
15
15
  [K in keyof T]: T[K] extends AnyNestedClient ? JsonifiedClient<T[K]> : T[K];
16
16
  };
17
17
 
18
- export type { JsonifiedValue as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedClientError as b, JsonifiedClient as c, JsonifiedArray as d };
18
+ export type { JsonifiedClient as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedArray as b, JsonifiedClientError as c, JsonifiedValue as d };
@@ -1,5 +1,5 @@
1
1
  import { OpenAPIV3_1 } from '@hey-api/spec-types';
2
- import { ORPCError, AnyNestedClient, Client } from '@orpc/client';
2
+ import { AnyNestedClient, Client, ORPCError } from '@orpc/client';
3
3
 
4
4
  type OpenAPIDocument = OpenAPIV3_1.Document;
5
5
  type OpenAPIOperationObject = OpenAPIV3_1.OperationObject;
@@ -15,4 +15,4 @@ type JsonifiedClient<T extends AnyNestedClient> = T extends Client<infer UClient
15
15
  [K in keyof T]: T[K] extends AnyNestedClient ? JsonifiedClient<T[K]> : T[K];
16
16
  };
17
17
 
18
- export type { JsonifiedValue as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedClientError as b, JsonifiedClient as c, JsonifiedArray as d };
18
+ export type { JsonifiedClient as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedArray as b, JsonifiedClientError as c, JsonifiedValue as d };
@@ -4,7 +4,7 @@ import { unlazy } from '@orpc/server';
4
4
  import { value, pathToHttpPath, mergeHttpPath, isTypescriptObject, stringifyJSON } from '@orpc/shared';
5
5
  import { mergeStandardHeaders, parseStandardUrl, isStandardHeaders } from '@standardserver/core';
6
6
  import { toStandardHeaders } from '@standardserver/fetch';
7
- import { O as OpenAPISerializer, D as DEFAULT_OPENAPI_METHOD, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, g as getDynamicPathParams, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE } from './openapi.DmAa7YPO.mjs';
7
+ import { O as OpenAPISerializer, D as DEFAULT_OPENAPI_METHOD, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, g as getDynamicPathParams, i as isBodylessMethod, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE } from './openapi.zZH_UksW.mjs';
8
8
  import { g as getOpenAPIMeta } from './openapi.B9PQzqBn.mjs';
9
9
 
10
10
  class OpenAPILinkCodecError extends TypeError {
@@ -56,7 +56,7 @@ class OpenAPILinkCodec {
56
56
  data = Object.keys(remaining).length > 0 ? remaining : void 0;
57
57
  }
58
58
  pathname = `${basePathname.replace(END_SLASH_REGEX, "")}${pathname}`;
59
- if (method === "GET") {
59
+ if (isBodylessMethod(method)) {
60
60
  const queryString2 = this.serializeQueryString(data, meta?.queryStyles);
61
61
  const search2 = combineSearch(baseSearch, queryString2);
62
62
  const url3 = `${pathname}${search2 ?? ""}${baseHash ?? ""}`;
@@ -110,7 +110,7 @@ class OpenAPILinkCodec {
110
110
  const queryString = this.serializeQueryString(input?.query, meta?.queryStyles);
111
111
  const search = combineSearch(baseSearch, queryString);
112
112
  const url = `${pathname}${search ?? ""}${baseHash ?? ""}`;
113
- if (method === "GET") {
113
+ if (isBodylessMethod(method)) {
114
114
  return {
115
115
  body: void 0,
116
116
  method,
@@ -243,7 +243,7 @@ class OpenAPILinkCodec {
243
243
  return query || void 0;
244
244
  }
245
245
  async decodeResponse(response, path, _options) {
246
- const isOk = response.status >= 200 && response.status < 400;
246
+ const isOk = response.status < 400;
247
247
  const procedure = await this.resolveProcedure(path);
248
248
  const meta = getOpenAPIMeta(procedure);
249
249
  const deserialized = await (async () => {
@@ -2,7 +2,7 @@ import { COMMON_ERROR_STATUS_MAP } from '@orpc/client';
2
2
  import { walkProcedureContractsSync, Procedure, unlazy, getRouter, createContractProcedure, DEFAULT_SUCCESS_STATUS, DEFAULT_ERROR_STATUS } from '@orpc/server';
3
3
  import { value, pathToHttpPath, mergeHttpPath, normalizeHttpPath, tryDecodeURIComponent, isPlainObject, stringifyJSON, parseEmptyableJSON, isTypescriptObject, NullProtoObj } from '@orpc/shared';
4
4
  import { parseStandardUrl, isStandardHeaders } from '@standardserver/core';
5
- import { D as DEFAULT_OPENAPI_METHOD, g as getDynamicPathParams, O as OpenAPISerializer, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE } from './openapi.DmAa7YPO.mjs';
5
+ import { D as DEFAULT_OPENAPI_METHOD, g as getDynamicPathParams, O as OpenAPISerializer, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, i as isBodylessMethod, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE } from './openapi.zZH_UksW.mjs';
6
6
  import { g as getOpenAPIMeta } from './openapi.B9PQzqBn.mjs';
7
7
  import { createRouter, addRoute, findRoute, routeToRegExp } from 'rou3';
8
8
 
@@ -124,15 +124,11 @@ function decodeParams(params) {
124
124
  return Object.fromEntries(Object.entries(params).map(([key, val]) => [key, tryDecodeURIComponent(val)]));
125
125
  }
126
126
 
127
- class OpenAPIHandlerCodecError extends TypeError {
128
- }
129
- class OpenAPIHandlerCodec {
130
- matcher;
127
+ class OpenAPIHandlerCodecCore {
131
128
  serializer;
132
129
  errorStatusMap;
133
130
  customErrorResponseBodySerializer;
134
- constructor(router, options = {}) {
135
- this.matcher = new OpenAPIMatcher(router, options);
131
+ constructor(options = {}) {
136
132
  this.serializer = options.serializer ?? new OpenAPISerializer();
137
133
  this.errorStatusMap = options.errorStatusMap ?? COMMON_ERROR_STATUS_MAP;
138
134
  this.customErrorResponseBodySerializer = options.customErrorResponseBodyEncoder;
@@ -144,7 +140,7 @@ class OpenAPIHandlerCodec {
144
140
  const params = this.deserializeParams(matched.params, meta?.paramsStyles);
145
141
  const query = this.deserializeQuery(search, meta?.queryStyles);
146
142
  if (inputStructure === "compact") {
147
- const data = request.method === "GET" ? query : this.serializer.deserialize(await request.resolveBody(meta?.requestBodyHint));
143
+ const data = isBodylessMethod(request.method) ? query : this.serializer.deserialize(await request.resolveBody(meta?.requestBodyHint));
148
144
  if (data === void 0) {
149
145
  return params;
150
146
  }
@@ -166,22 +162,10 @@ class OpenAPIHandlerCodec {
166
162
  body: this.serializer.deserialize(await request.resolveBody(meta?.requestBodyHint))
167
163
  };
168
164
  }
169
- async resolveProcedure(request, options) {
170
- const [pathname] = parseStandardUrl(request.url);
171
- const matched = await this.matcher.match(request.method, pathname, options.prefix);
172
- if (!matched) {
173
- return void 0;
174
- }
175
- return {
176
- procedure: matched.procedure,
177
- path: matched.path,
178
- decodeInput: () => this.decodeInput(matched, request)
179
- };
180
- }
181
165
  /**
182
- * @throws {Error} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
166
+ * @throws {TypeError} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
183
167
  */
184
- encodeOutput(output, procedure, path, _options) {
168
+ encodeOutput(output, procedure, path) {
185
169
  const meta = getOpenAPIMeta(procedure);
186
170
  const successStatus = meta?.successStatus ?? DEFAULT_SUCCESS_STATUS;
187
171
  const outputStructure = meta?.outputStructure ?? DEFAULT_OPENAPI_OUTPUT_STRUCTURE;
@@ -193,7 +177,7 @@ class OpenAPIHandlerCodec {
193
177
  };
194
178
  }
195
179
  if (!isValidDetailedOutput(output)) {
196
- throw new OpenAPIHandlerCodecError(`
180
+ throw new TypeError(`
197
181
  Invalid "detailed" output structure returned by procedure (${path.join(".")}):
198
182
  \u2022 Expected an object with optional properties:
199
183
  - status (number 200-399)
@@ -211,7 +195,7 @@ class OpenAPIHandlerCodec {
211
195
  body: this.serializer.serialize(output.body)
212
196
  };
213
197
  }
214
- encodeError(error, _procedure, _path, _options) {
198
+ encodeError(error) {
215
199
  const status = this.errorStatusMap[error.code] ?? DEFAULT_ERROR_STATUS;
216
200
  return {
217
201
  status,
@@ -278,6 +262,25 @@ class OpenAPIHandlerCodec {
278
262
  return parsed;
279
263
  }
280
264
  }
265
+ class OpenAPIHandlerCodec extends OpenAPIHandlerCodecCore {
266
+ matcher;
267
+ constructor(router, options = {}) {
268
+ super(options);
269
+ this.matcher = new OpenAPIMatcher(router, options);
270
+ }
271
+ async resolveProcedure(request, options) {
272
+ const [pathname] = parseStandardUrl(request.url);
273
+ const matched = await this.matcher.match(request.method, pathname, options.prefix);
274
+ if (!matched) {
275
+ return void 0;
276
+ }
277
+ return {
278
+ procedure: matched.procedure,
279
+ path: matched.path,
280
+ decodeInput: () => this.decodeInput(matched, request)
281
+ };
282
+ }
283
+ }
281
284
  function isValidDetailedOutput(output) {
282
285
  if (!isTypescriptObject(output)) {
283
286
  return false;
@@ -312,4 +315,4 @@ function decodeDelimitedObject(value, delimiter) {
312
315
  return obj;
313
316
  }
314
317
 
315
- export { OpenAPIHandlerCodec as O, OpenAPIHandlerCodecError as a, OpenAPIMatcher as b };
318
+ export { OpenAPIHandlerCodec as O, OpenAPIHandlerCodecCore as a, OpenAPIMatcher as b };
@@ -2,7 +2,7 @@ import { AnySchema, ErrorMap, MetaPlugin, AnyProcedureContract } from '@orpc/con
2
2
  import { Lazy } from '@orpc/server';
3
3
  import { Value } from '@orpc/shared';
4
4
  import { StandardBodyHint } from '@standardserver/core';
5
- import { O as OpenAPIOperationObject } from './openapi.CYgMBSUF.js';
5
+ import { O as OpenAPIOperationObject } from './openapi.ByT4oUeY.js';
6
6
 
7
7
  interface OpenAPIMeta {
8
8
  /**
@@ -12,9 +12,10 @@ interface OpenAPIMeta {
12
12
  */
13
13
  method?: 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | undefined;
14
14
  /**
15
- * URL path for this procedure. Supports dynamic segments via `${}` syntax.
15
+ * URL path for this procedure. Supports dynamic parameters via `{param}` syntax,
16
+ * and `{+param}` to allow slashes in the matched value.
16
17
  *
17
- * @example `/users`, `/users/${id}`
18
+ * @example `/users`, `/users/{id}`, `/files/{+path}`
18
19
  * @default Router segments joined by `'/`
19
20
  */
20
21
  path?: `/${string}` | undefined;
@@ -39,11 +40,13 @@ interface OpenAPIMeta {
39
40
  /**
40
41
  * Tags associated with this procedure.
41
42
  *
42
- * **Note**: Tags are merged when defined multiple times.
43
+ * **Merging**: When defined multiple times, tags are concatenated in definition order.
44
+ * Explicitly setting `undefined` resets the tags instead of merging.
43
45
  */
44
46
  tags?: string[] | undefined;
45
47
  /**
46
- * HTTP status code returned on success. Must be in the 200–399 range.
48
+ * HTTP status code returned on success.
49
+ * Should be in the `2xx` range and must be less than `400`.
47
50
  *
48
51
  * @default 200
49
52
  */
@@ -57,7 +60,9 @@ interface OpenAPIMeta {
57
60
  /**
58
61
  * Controls how individual path parameters are decoded.
59
62
  *
60
- * **Note**: Param styles are merged when defined multiple times.
63
+ * **Merging**: When defined multiple times, styles are merged per parameter.
64
+ * The most recent style defined for a parameter wins.
65
+ * Explicitly setting `undefined` resets the styles instead of merging.
61
66
  *
62
67
  * Each key maps a path parameter name to one of the following strategies:
63
68
  *
@@ -102,7 +107,9 @@ interface OpenAPIMeta {
102
107
  /**
103
108
  * Controls how individual query parameters are encoding/decoding.
104
109
  *
105
- * **Note**: Query styles are merged when defined multiple times.
110
+ * **Merging**: When defined multiple times, styles are merged per parameter.
111
+ * The most recent style defined for a parameter wins.
112
+ * Explicitly setting `undefined` resets the styles instead of merging.
106
113
  *
107
114
  * Each key maps a query parameter name to one of the following strategies:
108
115
  *
@@ -260,13 +267,20 @@ interface OpenAPIMeta {
260
267
  * Pass a plain object to replace entire operation object, or a function that receives the current
261
268
  * operation object and returns the modified version.
262
269
  *
263
- * **Note**: Spec is merged when defined multiple times.
270
+ * **Merging**: When defined multiple times:
271
+ *
272
+ * - Two functions are chained: the most recent function receives the result of the previous one.
273
+ * - A function combined with an object: the function is applied to that object.
274
+ * - Two objects: the most recent object wins.
275
+ *
276
+ * Explicitly setting `undefined` resets the spec instead of merging.
264
277
  */
265
278
  spec?: Value<OpenAPIOperationObject, [current: OpenAPIOperationObject]>;
266
279
  /**
267
280
  * Prefix for the path. Useful when you want to apply a common path prefix across multiple procedures.
268
281
  *
269
- * **Note**: Prefixes are merged when defined multiple times.
282
+ * **Merging**: When defined multiple times, prefixes are concatenated in definition order.
283
+ * Explicitly setting `undefined` resets the prefix instead of merging.
270
284
  */
271
285
  prefix?: `/${string}` | undefined;
272
286
  }
@@ -2,7 +2,7 @@ import { AnySchema, ErrorMap, MetaPlugin, AnyProcedureContract } from '@orpc/con
2
2
  import { Lazy } from '@orpc/server';
3
3
  import { Value } from '@orpc/shared';
4
4
  import { StandardBodyHint } from '@standardserver/core';
5
- import { O as OpenAPIOperationObject } from './openapi.CYgMBSUF.mjs';
5
+ import { O as OpenAPIOperationObject } from './openapi.ByT4oUeY.mjs';
6
6
 
7
7
  interface OpenAPIMeta {
8
8
  /**
@@ -12,9 +12,10 @@ interface OpenAPIMeta {
12
12
  */
13
13
  method?: 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | undefined;
14
14
  /**
15
- * URL path for this procedure. Supports dynamic segments via `${}` syntax.
15
+ * URL path for this procedure. Supports dynamic parameters via `{param}` syntax,
16
+ * and `{+param}` to allow slashes in the matched value.
16
17
  *
17
- * @example `/users`, `/users/${id}`
18
+ * @example `/users`, `/users/{id}`, `/files/{+path}`
18
19
  * @default Router segments joined by `'/`
19
20
  */
20
21
  path?: `/${string}` | undefined;
@@ -39,11 +40,13 @@ interface OpenAPIMeta {
39
40
  /**
40
41
  * Tags associated with this procedure.
41
42
  *
42
- * **Note**: Tags are merged when defined multiple times.
43
+ * **Merging**: When defined multiple times, tags are concatenated in definition order.
44
+ * Explicitly setting `undefined` resets the tags instead of merging.
43
45
  */
44
46
  tags?: string[] | undefined;
45
47
  /**
46
- * HTTP status code returned on success. Must be in the 200–399 range.
48
+ * HTTP status code returned on success.
49
+ * Should be in the `2xx` range and must be less than `400`.
47
50
  *
48
51
  * @default 200
49
52
  */
@@ -57,7 +60,9 @@ interface OpenAPIMeta {
57
60
  /**
58
61
  * Controls how individual path parameters are decoded.
59
62
  *
60
- * **Note**: Param styles are merged when defined multiple times.
63
+ * **Merging**: When defined multiple times, styles are merged per parameter.
64
+ * The most recent style defined for a parameter wins.
65
+ * Explicitly setting `undefined` resets the styles instead of merging.
61
66
  *
62
67
  * Each key maps a path parameter name to one of the following strategies:
63
68
  *
@@ -102,7 +107,9 @@ interface OpenAPIMeta {
102
107
  /**
103
108
  * Controls how individual query parameters are encoding/decoding.
104
109
  *
105
- * **Note**: Query styles are merged when defined multiple times.
110
+ * **Merging**: When defined multiple times, styles are merged per parameter.
111
+ * The most recent style defined for a parameter wins.
112
+ * Explicitly setting `undefined` resets the styles instead of merging.
106
113
  *
107
114
  * Each key maps a query parameter name to one of the following strategies:
108
115
  *
@@ -260,13 +267,20 @@ interface OpenAPIMeta {
260
267
  * Pass a plain object to replace entire operation object, or a function that receives the current
261
268
  * operation object and returns the modified version.
262
269
  *
263
- * **Note**: Spec is merged when defined multiple times.
270
+ * **Merging**: When defined multiple times:
271
+ *
272
+ * - Two functions are chained: the most recent function receives the result of the previous one.
273
+ * - A function combined with an object: the function is applied to that object.
274
+ * - Two objects: the most recent object wins.
275
+ *
276
+ * Explicitly setting `undefined` resets the spec instead of merging.
264
277
  */
265
278
  spec?: Value<OpenAPIOperationObject, [current: OpenAPIOperationObject]>;
266
279
  /**
267
280
  * Prefix for the path. Useful when you want to apply a common path prefix across multiple procedures.
268
281
  *
269
- * **Note**: Prefixes are merged when defined multiple times.
282
+ * **Merging**: When defined multiple times, prefixes are concatenated in definition order.
283
+ * Explicitly setting `undefined` resets the prefix instead of merging.
270
284
  */
271
285
  prefix?: `/${string}` | undefined;
272
286
  }
@@ -1,4 +1,4 @@
1
- import { wrapEventIteratorPreservingMeta, toORPCError, isORPCErrorJson, createORPCErrorFromJson } from '@orpc/client';
1
+ import { wrapAsyncIteratorPreservingEventMeta, toORPCError, isORPCErrorJson, createORPCErrorFromJson } from '@orpc/client';
2
2
  import { isPlainObject, isAsyncIteratorObject } from '@orpc/shared';
3
3
  import { ErrorEvent } from '@standardserver/core';
4
4
  import { B as BracketNotationSerializer } from './openapi.Bt87OzTt.mjs';
@@ -173,7 +173,7 @@ class OpenAPISerializer {
173
173
  return data;
174
174
  }
175
175
  if (isAsyncIteratorObject(data)) {
176
- return wrapEventIteratorPreservingMeta(data, {
176
+ return wrapAsyncIteratorPreservingEventMeta(data, {
177
177
  mapResult: (result) => {
178
178
  if (result.value === void 0) {
179
179
  return result;
@@ -211,7 +211,7 @@ class OpenAPISerializer {
211
211
  return data;
212
212
  }
213
213
  if (isAsyncIteratorObject(data)) {
214
- return wrapEventIteratorPreservingMeta(data, {
214
+ return wrapAsyncIteratorPreservingEventMeta(data, {
215
215
  mapResult: (result) => {
216
216
  if (result.value === void 0) {
217
217
  return result;
@@ -236,6 +236,9 @@ class OpenAPISerializer {
236
236
  }
237
237
  }
238
238
 
239
+ function isBodylessMethod(method) {
240
+ return method === "GET" || method === "HEAD";
241
+ }
239
242
  const PARAMETER_NAME_REGEX = /^[\w-]+$/;
240
243
  function getDynamicPathParams(path) {
241
244
  if (!path.includes("{")) {
@@ -272,4 +275,4 @@ function getDynamicPathParams(path) {
272
275
  return params;
273
276
  }
274
277
 
275
- export { DEFAULT_OPENAPI_METHOD as D, OpenAPISerializer as O, DEFAULT_OPENAPI_INPUT_STRUCTURE as a, DEFAULT_OPENAPI_OUTPUT_STRUCTURE as b, DEFAULT_OPENAPI_SUCCESS_DESCRIPTION as c, OpenAPIJsonSerializer as d, getDynamicPathParams as g };
278
+ export { DEFAULT_OPENAPI_METHOD as D, OpenAPISerializer as O, DEFAULT_OPENAPI_INPUT_STRUCTURE as a, DEFAULT_OPENAPI_OUTPUT_STRUCTURE as b, DEFAULT_OPENAPI_SUCCESS_DESCRIPTION as c, OpenAPIJsonSerializer as d, getDynamicPathParams as g, isBodylessMethod as i };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/openapi",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.2",
4
+ "version": "2.0.0-beta.20",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.dev",
7
7
  "repository": {
@@ -57,22 +57,38 @@
57
57
  "files": [
58
58
  "dist"
59
59
  ],
60
+ "peerDependencies": {
61
+ "@scalar/api-reference": ">=1.57.2",
62
+ "@types/swagger-ui": ">=5.32.0",
63
+ "swagger-ui": ">=5.32.6"
64
+ },
65
+ "peerDependenciesMeta": {
66
+ "@scalar/api-reference": {
67
+ "optional": true
68
+ },
69
+ "@types/swagger-ui": {
70
+ "optional": true
71
+ },
72
+ "swagger-ui": {
73
+ "optional": true
74
+ }
75
+ },
60
76
  "dependencies": {
61
77
  "@hey-api/spec-types": "0.0.0-next-20260408030107",
78
+ "@standardserver/core": "^0.5.0",
79
+ "@standardserver/fetch": "^0.5.0",
80
+ "rou3": "^0.9.1",
81
+ "@orpc/client": "2.0.0-beta.20",
82
+ "@orpc/contract": "2.0.0-beta.20",
83
+ "@orpc/server": "2.0.0-beta.20",
84
+ "@orpc/shared": "2.0.0-beta.20",
85
+ "@orpc/json-schema": "2.0.0-beta.20"
86
+ },
87
+ "devDependencies": {
62
88
  "@scalar/api-reference": "^1.57.2",
63
- "@standardserver/core": "^0.0.25",
64
- "@standardserver/fetch": "^0.0.25",
65
89
  "@types/swagger-ui": "^5.32.0",
66
- "rou3": "^0.8.1",
90
+ "fastify": "^5.8.5",
67
91
  "swagger-ui": "^5.32.6",
68
- "@orpc/client": "2.0.0-beta.2",
69
- "@orpc/json-schema": "2.0.0-beta.2",
70
- "@orpc/server": "2.0.0-beta.2",
71
- "@orpc/shared": "2.0.0-beta.2",
72
- "@orpc/contract": "2.0.0-beta.2"
73
- },
74
- "devDependencies": {
75
- "fastify": "^5.6.2",
76
92
  "zod": "^4.4.3"
77
93
  },
78
94
  "scripts": {