@orpc/openapi 2.0.0-beta.3 → 2.0.0-beta.31

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/README.md +71 -101
  2. package/dist/adapters/aws-lambda/index.d.mts +26 -0
  3. package/dist/adapters/aws-lambda/index.d.ts +26 -0
  4. package/dist/adapters/aws-lambda/index.mjs +21 -0
  5. package/dist/adapters/fastify/index.d.mts +23 -0
  6. package/dist/adapters/fastify/index.d.ts +23 -0
  7. package/dist/adapters/fastify/index.mjs +21 -0
  8. package/dist/adapters/fetch/index.d.mts +12 -2
  9. package/dist/adapters/fetch/index.d.ts +12 -2
  10. package/dist/adapters/fetch/index.mjs +4 -4
  11. package/dist/adapters/node/index.d.mts +7 -2
  12. package/dist/adapters/node/index.d.ts +7 -2
  13. package/dist/adapters/node/index.mjs +3 -3
  14. package/dist/adapters/standard/index.d.mts +10 -46
  15. package/dist/adapters/standard/index.d.ts +10 -46
  16. package/dist/adapters/standard/index.mjs +4 -4
  17. package/dist/extensions/route.d.mts +2 -2
  18. package/dist/extensions/route.d.ts +2 -2
  19. package/dist/helpers/index.d.mts +9 -1
  20. package/dist/helpers/index.d.ts +9 -1
  21. package/dist/helpers/index.mjs +1 -1
  22. package/dist/index.d.mts +70 -36
  23. package/dist/index.d.ts +70 -36
  24. package/dist/index.mjs +701 -738
  25. package/dist/plugins/index.d.mts +18 -1
  26. package/dist/plugins/index.d.ts +18 -1
  27. package/dist/plugins/index.mjs +6 -1
  28. package/dist/shared/{openapi.DmAa7YPO.mjs → openapi.0yE-t1W-.mjs} +120 -42
  29. package/dist/shared/{openapi.DuDd2iQz.d.mts → openapi.9smDzQwj.d.mts} +10 -7
  30. package/dist/shared/{openapi.B2SK0ZAr.mjs → openapi.B6jrmH-p.mjs} +21 -29
  31. package/dist/shared/openapi.Bd9icEUa.d.mts +45 -0
  32. package/dist/shared/openapi.D1CqEIRy.d.ts +45 -0
  33. package/dist/shared/{openapi.BQzzr4-4.d.ts → openapi.DTYZZ6Ph.d.ts} +36 -10
  34. package/dist/shared/{openapi.CYgMBSUF.d.mts → openapi.DfTTLtn5.d.mts} +19 -5
  35. package/dist/shared/{openapi.CYgMBSUF.d.ts → openapi.DfTTLtn5.d.ts} +19 -5
  36. package/dist/shared/{openapi.BcEtAxQj.d.mts → openapi.Drcd0PuL.d.mts} +36 -10
  37. package/dist/shared/{openapi.C7m7NAmH.d.mts → openapi.Dz-JaXHo.d.mts} +13 -2
  38. package/dist/shared/{openapi.C7m7NAmH.d.ts → openapi.Dz-JaXHo.d.ts} +13 -2
  39. package/dist/shared/{openapi.DBYxUpK8.d.ts → openapi.YCiBHaJ-.d.ts} +10 -7
  40. package/dist/shared/{openapi.B3H7yHQa.mjs → openapi.iEFYDEKB.mjs} +92 -43
  41. package/dist/shared/{openapi.Bt87OzTt.mjs → openapi.s_p5sN-P.mjs} +20 -15
  42. package/package.json +54 -14
@@ -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 { d as OpenAPIOperationObject } from './openapi.DfTTLtn5.js';
6
6
 
7
7
  interface OpenAPIMeta {
8
8
  /**
@@ -10,11 +10,12 @@ interface OpenAPIMeta {
10
10
  *
11
11
  * @default 'POST'
12
12
  */
13
- method?: 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | undefined;
13
+ method?: 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'QUERY' | 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
  }
@@ -292,7 +306,19 @@ interface OpenAPIFunction {
292
306
  spec(method: OpenAPIMeta['spec']): OpenAPISpecMetaPlugin<any, any, any>;
293
307
  prefix(method: OpenAPIMeta['prefix']): OpenAPIPrefixMetaPlugin<any, any, any>;
294
308
  }
309
+ /**
310
+ * Creates OpenAPI meta plugins that control how a procedure is exposed over HTTP,
311
+ * such as its method, path, prefix, and OpenAPI operation spec.
312
+ *
313
+ * @see {@link https://orpc.dev/docs/openapi/routing | OpenAPI Routing}
314
+ * @see {@link https://orpc.dev/docs/openapi/specification | OpenAPI Specification}
315
+ */
295
316
  declare const openapi: OpenAPIFunction;
317
+ /**
318
+ * Retrieves the OpenAPI metadata attached to a procedure or router, or `undefined` if not set.
319
+ *
320
+ * @see {@link https://orpc.dev/docs/rpc/handler#enabling-the-get-method | RPC Handler - Enabling the GET Method}
321
+ */
296
322
  declare function getOpenAPIMeta(procedureOrLazy: AnyProcedureContract | Lazy<any>): OpenAPIMeta | undefined;
297
323
 
298
324
  export { getOpenAPIMeta as g, openapi as o };
@@ -1,18 +1,32 @@
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
+ import { AsyncIteratorClass } from '@orpc/shared';
3
4
 
4
- type OpenAPIDocument = OpenAPIV3_1.Document;
5
5
  type OpenAPIOperationObject = OpenAPIV3_1.OperationObject;
6
+ /**
7
+ * An OpenAPI 3.1 document with the OpenAPI 3.2 QUERY additions used by oRPC.
8
+ * This type does not claim support for the complete OpenAPI 3.2 specification.
9
+ */
10
+ type OpenAPIDocument = Omit<OpenAPIV3_1.Document, 'openapi' | 'paths'> & {
11
+ openapi: OpenAPIV3_1.Document['openapi'] | '3.2.0';
12
+ paths?: undefined | (OpenAPIV3_1.PathsObject & {
13
+ [path: `/${string}`]: OpenAPIV3_1.PathItemObject & {
14
+ query?: OpenAPIOperationObject | undefined;
15
+ };
16
+ });
17
+ };
6
18
  type JsonifiedValue<T> = T extends string ? T : T extends number ? T : T extends boolean ? T : T extends null ? T : T extends undefined ? T : T extends Array<unknown> ? JsonifiedArray<T> : T extends Record<string, unknown> ? {
7
19
  [K in keyof T]: JsonifiedValue<T[K]>;
8
- } : T extends Date ? string : T extends bigint ? string : T extends File ? File : T extends Blob ? Blob : T extends RegExp ? string : T extends URL ? string : T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]> : T extends Set<infer U> ? JsonifiedArray<U[]> : T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>> : unknown;
20
+ } : T extends Date ? string : T extends bigint ? string : T extends File ? File : T extends Blob ? Blob : T extends RegExp ? string : T extends URL ? string : T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]> : T extends Set<infer U> ? JsonifiedArray<U[]> : T extends AsyncIteratorClass<infer U, infer V> ? AsyncIteratorClass<JsonifiedValue<U>, JsonifiedValue<V>> : T extends AsyncGenerator<infer U, infer V> ? AsyncGenerator<JsonifiedValue<U>, JsonifiedValue<V>> : T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>> : unknown;
9
21
  type JsonifiedArray<T extends Array<unknown>> = T extends readonly [] ? [] : T extends readonly [infer U, ...infer V] ? [U extends undefined ? null : JsonifiedValue<U>, ...JsonifiedArray<V>] : T extends Array<infer U> ? Array<JsonifiedValue<U>> : unknown;
10
22
  type JsonifiedClientError<T> = T extends ORPCError<infer UCode, infer UData> ? ORPCError<UCode, JsonifiedValue<UData>> : T;
11
23
  /**
12
- * Convert types that JSON not support to corresponding json types
24
+ * Client type whose outputs and error data replace types JSON cannot represent with their JSON equivalents.
25
+ *
26
+ * @see {@link https://orpc.dev/docs/openapi/link | OpenAPI Link}
13
27
  */
14
28
  type JsonifiedClient<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Client<UClientContext, UInput, JsonifiedValue<UOutput>, JsonifiedClientError<UError>> : {
15
29
  [K in keyof T]: T[K] extends AnyNestedClient ? JsonifiedClient<T[K]> : T[K];
16
30
  };
17
31
 
18
- export type { JsonifiedValue as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedClientError as b, JsonifiedClient as c, JsonifiedArray as d };
32
+ export type { JsonifiedClient as J, OpenAPIDocument as O, JsonifiedArray as a, JsonifiedClientError as b, JsonifiedValue as c, OpenAPIOperationObject as d };
@@ -1,18 +1,32 @@
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
+ import { AsyncIteratorClass } from '@orpc/shared';
3
4
 
4
- type OpenAPIDocument = OpenAPIV3_1.Document;
5
5
  type OpenAPIOperationObject = OpenAPIV3_1.OperationObject;
6
+ /**
7
+ * An OpenAPI 3.1 document with the OpenAPI 3.2 QUERY additions used by oRPC.
8
+ * This type does not claim support for the complete OpenAPI 3.2 specification.
9
+ */
10
+ type OpenAPIDocument = Omit<OpenAPIV3_1.Document, 'openapi' | 'paths'> & {
11
+ openapi: OpenAPIV3_1.Document['openapi'] | '3.2.0';
12
+ paths?: undefined | (OpenAPIV3_1.PathsObject & {
13
+ [path: `/${string}`]: OpenAPIV3_1.PathItemObject & {
14
+ query?: OpenAPIOperationObject | undefined;
15
+ };
16
+ });
17
+ };
6
18
  type JsonifiedValue<T> = T extends string ? T : T extends number ? T : T extends boolean ? T : T extends null ? T : T extends undefined ? T : T extends Array<unknown> ? JsonifiedArray<T> : T extends Record<string, unknown> ? {
7
19
  [K in keyof T]: JsonifiedValue<T[K]>;
8
- } : T extends Date ? string : T extends bigint ? string : T extends File ? File : T extends Blob ? Blob : T extends RegExp ? string : T extends URL ? string : T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]> : T extends Set<infer U> ? JsonifiedArray<U[]> : T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>> : unknown;
20
+ } : T extends Date ? string : T extends bigint ? string : T extends File ? File : T extends Blob ? Blob : T extends RegExp ? string : T extends URL ? string : T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]> : T extends Set<infer U> ? JsonifiedArray<U[]> : T extends AsyncIteratorClass<infer U, infer V> ? AsyncIteratorClass<JsonifiedValue<U>, JsonifiedValue<V>> : T extends AsyncGenerator<infer U, infer V> ? AsyncGenerator<JsonifiedValue<U>, JsonifiedValue<V>> : T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>> : unknown;
9
21
  type JsonifiedArray<T extends Array<unknown>> = T extends readonly [] ? [] : T extends readonly [infer U, ...infer V] ? [U extends undefined ? null : JsonifiedValue<U>, ...JsonifiedArray<V>] : T extends Array<infer U> ? Array<JsonifiedValue<U>> : unknown;
10
22
  type JsonifiedClientError<T> = T extends ORPCError<infer UCode, infer UData> ? ORPCError<UCode, JsonifiedValue<UData>> : T;
11
23
  /**
12
- * Convert types that JSON not support to corresponding json types
24
+ * Client type whose outputs and error data replace types JSON cannot represent with their JSON equivalents.
25
+ *
26
+ * @see {@link https://orpc.dev/docs/openapi/link | OpenAPI Link}
13
27
  */
14
28
  type JsonifiedClient<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Client<UClientContext, UInput, JsonifiedValue<UOutput>, JsonifiedClientError<UError>> : {
15
29
  [K in keyof T]: T[K] extends AnyNestedClient ? JsonifiedClient<T[K]> : T[K];
16
30
  };
17
31
 
18
- export type { JsonifiedValue as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedClientError as b, JsonifiedClient as c, JsonifiedArray as d };
32
+ export type { JsonifiedClient as J, OpenAPIDocument as O, JsonifiedArray as a, JsonifiedClientError as b, JsonifiedValue as c, OpenAPIOperationObject as d };
@@ -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 { d as OpenAPIOperationObject } from './openapi.DfTTLtn5.mjs';
6
6
 
7
7
  interface OpenAPIMeta {
8
8
  /**
@@ -10,11 +10,12 @@ interface OpenAPIMeta {
10
10
  *
11
11
  * @default 'POST'
12
12
  */
13
- method?: 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | undefined;
13
+ method?: 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'QUERY' | 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
  }
@@ -292,7 +306,19 @@ interface OpenAPIFunction {
292
306
  spec(method: OpenAPIMeta['spec']): OpenAPISpecMetaPlugin<any, any, any>;
293
307
  prefix(method: OpenAPIMeta['prefix']): OpenAPIPrefixMetaPlugin<any, any, any>;
294
308
  }
309
+ /**
310
+ * Creates OpenAPI meta plugins that control how a procedure is exposed over HTTP,
311
+ * such as its method, path, prefix, and OpenAPI operation spec.
312
+ *
313
+ * @see {@link https://orpc.dev/docs/openapi/routing | OpenAPI Routing}
314
+ * @see {@link https://orpc.dev/docs/openapi/specification | OpenAPI Specification}
315
+ */
295
316
  declare const openapi: OpenAPIFunction;
317
+ /**
318
+ * Retrieves the OpenAPI metadata attached to a procedure or router, or `undefined` if not set.
319
+ *
320
+ * @see {@link https://orpc.dev/docs/rpc/handler#enabling-the-get-method | RPC Handler - Enabling the GET Method}
321
+ */
296
322
  declare function getOpenAPIMeta(procedureOrLazy: AnyProcedureContract | Lazy<any>): OpenAPIMeta | undefined;
297
323
 
298
324
  export { getOpenAPIMeta as g, openapi as o };
@@ -95,10 +95,15 @@ interface OpenAPIJsonSerializerOptions {
95
95
  omitUndefinedProperties?: boolean | undefined;
96
96
  }
97
97
  declare class OpenAPIJsonSerializer {
98
- private readonly handlers;
98
+ private readonly inlineBuiltInHandlers;
99
+ private readonly handlerEntries;
99
100
  private readonly omitUndefinedProperties;
100
101
  constructor(options?: OpenAPIJsonSerializerOptions);
101
102
  serialize(data: unknown): OpenAPIJsonSerialization;
103
+ /**
104
+ * `segments` is a shared mutable stack (push/pop while walking),
105
+ * so it must be copied before being stored in `maps`.
106
+ */
102
107
  private serializeValue;
103
108
  deserialize(serialized: OpenAPIJsonSerialization): unknown;
104
109
  }
@@ -118,7 +123,7 @@ interface OpenAPISerializerSerializeOptions {
118
123
  */
119
124
  asFormData?: boolean | undefined;
120
125
  }
121
- interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPISerializerSerializeOptions {
126
+ interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions {
122
127
  /**
123
128
  * Options for bracket notation serializer, like maxExplicitDeserializingArrayIndex
124
129
  */
@@ -128,6 +133,12 @@ interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPI
128
133
  */
129
134
  serialize?: OpenAPISerializerSerializeOptions | undefined;
130
135
  }
136
+ /**
137
+ * Handles one-way serialization of oRPC payloads into JSON-friendly formats,
138
+ * partially supporting complex data types beyond plain JSON such as `Date`, `BigInt`, and `Set`.
139
+ *
140
+ * @see {@link https://orpc.dev/docs/openapi/serializer | OpenAPI Serializer}
141
+ */
131
142
  declare class OpenAPISerializer {
132
143
  private readonly jsonSerializer;
133
144
  private readonly bracketNotation;
@@ -95,10 +95,15 @@ interface OpenAPIJsonSerializerOptions {
95
95
  omitUndefinedProperties?: boolean | undefined;
96
96
  }
97
97
  declare class OpenAPIJsonSerializer {
98
- private readonly handlers;
98
+ private readonly inlineBuiltInHandlers;
99
+ private readonly handlerEntries;
99
100
  private readonly omitUndefinedProperties;
100
101
  constructor(options?: OpenAPIJsonSerializerOptions);
101
102
  serialize(data: unknown): OpenAPIJsonSerialization;
103
+ /**
104
+ * `segments` is a shared mutable stack (push/pop while walking),
105
+ * so it must be copied before being stored in `maps`.
106
+ */
102
107
  private serializeValue;
103
108
  deserialize(serialized: OpenAPIJsonSerialization): unknown;
104
109
  }
@@ -118,7 +123,7 @@ interface OpenAPISerializerSerializeOptions {
118
123
  */
119
124
  asFormData?: boolean | undefined;
120
125
  }
121
- interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPISerializerSerializeOptions {
126
+ interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions {
122
127
  /**
123
128
  * Options for bracket notation serializer, like maxExplicitDeserializingArrayIndex
124
129
  */
@@ -128,6 +133,12 @@ interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPI
128
133
  */
129
134
  serialize?: OpenAPISerializerSerializeOptions | undefined;
130
135
  }
136
+ /**
137
+ * Handles one-way serialization of oRPC payloads into JSON-friendly formats,
138
+ * partially supporting complex data types beyond plain JSON such as `Date`, `BigInt`, and `Set`.
139
+ *
140
+ * @see {@link https://orpc.dev/docs/openapi/serializer | OpenAPI Serializer}
141
+ */
131
142
  declare class OpenAPISerializer {
132
143
  private readonly jsonSerializer;
133
144
  private readonly bracketNotation;
@@ -1,10 +1,10 @@
1
1
  import { AnyORPCError } from '@orpc/client';
2
2
  import { AnyProcedure, AnyRouter, Context } from '@orpc/server';
3
- import { StandardHandlerHandleOptions, StandardHandlerCodec, StandardHandlerCodecResolvedProcedure } from '@orpc/server/standard';
3
+ import { StandardHandlerCodec, StandardHandlerHandleOptions, StandardHandlerCodecResolvedProcedure } from '@orpc/server/standard';
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.Dz-JaXHo.js';
8
8
 
9
9
  interface OpenAPIMatcherOptions {
10
10
  /**
@@ -18,7 +18,7 @@ declare class OpenAPIMatcher {
18
18
  private readonly filter;
19
19
  private readonly rootRouter;
20
20
  private readonly tree;
21
- private pendingLazyRouters;
21
+ private readonly pendingLazyRouters;
22
22
  constructor(router: AnyRouter, options?: OpenAPIMatcherOptions);
23
23
  private index;
24
24
  match(method: string, pathname: `/${string}`, prefix: `/${string}` | undefined): Promise<{
@@ -26,8 +26,10 @@ declare class OpenAPIMatcher {
26
26
  procedure: AnyProcedure;
27
27
  params?: Record<string, string> | undefined;
28
28
  } | undefined>;
29
- private matchPathname;
30
29
  private resolvePendingLazyRouters;
30
+ private loadPendingLazyRouters;
31
+ private loadPendingLazyRouter;
32
+ private indexPendingLazyRouter;
31
33
  private resolveProcedure;
32
34
  }
33
35
 
@@ -38,8 +40,9 @@ interface OpenAPIHandlerCodecCoreOptions<_T extends Context> {
38
40
  serializer?: Pick<OpenAPISerializer, keyof OpenAPISerializer>;
39
41
  /**
40
42
  * Mapping ORPCError Code -> HTTP Status Code
43
+ * The status code should be in the `4xx` or `5xx` range (must be greater than or equal to `400`).
41
44
  *
42
- * @default COMMON_ERROR_STATUS_MAP, DEFAULT_ERROR_STATUS
45
+ * @default COMMON_ERROR_STATUS_MAP
43
46
  */
44
47
  errorStatusMap?: Record<string, number> | undefined;
45
48
  /**
@@ -65,8 +68,8 @@ declare class OpenAPIHandlerCodecCore<T extends Context> {
65
68
  /**
66
69
  * @throws {TypeError} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
67
70
  */
68
- encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
69
- encodeError(error: AnyORPCError, _procedure: AnyProcedure, _path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
71
+ encodeOutput(output: unknown, procedure: AnyProcedure, path: string[]): Promisable<StandardResponse>;
72
+ encodeError(error: AnyORPCError): Promisable<StandardResponse>;
70
73
  private deserializeQuery;
71
74
  private deserializeParams;
72
75
  }
@@ -1,8 +1,8 @@
1
1
  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
- import { value, pathToHttpPath, mergeHttpPath, normalizeHttpPath, tryDecodeURIComponent, isPlainObject, stringifyJSON, parseEmptyableJSON, isTypescriptObject, NullProtoObj } from '@orpc/shared';
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';
3
+ import { value, pathToHttpPath, mergeHttpPath, normalizeHttpPath, tryDecodeURIComponent, NullProtoObj, isTypescriptObject, isPlainObject, stringifyJSON, getOwn, parseEmptyableJSON } from '@orpc/shared';
4
+ import { parseStandardUrl } from '@standardserver/core';
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.0yE-t1W-.mjs';
6
6
  import { g as getOpenAPIMeta } from './openapi.B9PQzqBn.mjs';
7
7
  import { createRouter, addRoute, findRoute, routeToRegExp } from 'rou3';
8
8
 
@@ -10,7 +10,7 @@ class OpenAPIMatcher {
10
10
  filter;
11
11
  rootRouter;
12
12
  tree = createRouter();
13
- pendingLazyRouters = [];
13
+ pendingLazyRouters = /* @__PURE__ */ new Set();
14
14
  constructor(router, options = {}) {
15
15
  this.filter = options.filter ?? true;
16
16
  this.rootRouter = router;
@@ -32,13 +32,13 @@ class OpenAPIMatcher {
32
32
  procedure: contract instanceof Procedure ? contract : void 0
33
33
  });
34
34
  }, path);
35
- this.pendingLazyRouters.push(...lazyResults.map((result) => {
35
+ for (const result of lazyResults) {
36
36
  const prefix = getOpenAPIMeta(result.router)?.prefix;
37
- return {
37
+ this.pendingLazyRouters.add({
38
38
  ...result,
39
39
  matcher: prefix ? toRou3PrefixMatcher(prefix) : void 0
40
- };
41
- }));
40
+ });
41
+ }
42
42
  }
43
43
  async match(method, pathname, prefix) {
44
44
  if (prefix) {
@@ -56,44 +56,58 @@ class OpenAPIMatcher {
56
56
  return void 0;
57
57
  }
58
58
  }
59
- const result = await this.matchPathname(method, pathname);
60
- if (!result && pathname.includes("%")) {
61
- return this.matchPathname(method, normalizeHttpPath(pathname));
59
+ const loading = this.resolvePendingLazyRouters(pathname);
60
+ if (loading !== void 0) {
61
+ await loading;
62
62
  }
63
- return result;
64
- }
65
- async matchPathname(method, pathname) {
66
- await this.resolvePendingLazyRouters(pathname);
67
- const match = findRoute(this.tree, method, pathname);
68
- if (!match) {
63
+ let match = findRoute(this.tree, method, pathname);
64
+ if (match === void 0 && pathname.includes("%")) {
65
+ const normalizedPathname = normalizeHttpPath(pathname);
66
+ const normalizedLoading = this.resolvePendingLazyRouters(normalizedPathname);
67
+ if (normalizedLoading !== void 0) {
68
+ await normalizedLoading;
69
+ }
70
+ match = findRoute(this.tree, method, normalizedPathname);
71
+ }
72
+ if (match === void 0) {
69
73
  return void 0;
70
74
  }
71
- const procedure = await this.resolveProcedure(match.data);
75
+ const entry = match.data;
72
76
  return {
73
- path: match.data.path,
74
- procedure,
77
+ path: entry.path,
78
+ procedure: entry.procedure ?? await this.resolveProcedure(entry),
75
79
  params: match.params ? decodeParams(match.params) : void 0
76
80
  };
77
81
  }
78
- async resolvePendingLazyRouters(pathname) {
79
- if (!this.pendingLazyRouters.length) {
80
- return;
82
+ resolvePendingLazyRouters(pathname) {
83
+ for (const pending of this.pendingLazyRouters) {
84
+ if (pending.matcher === void 0 || pending.matcher.test(pathname)) {
85
+ return this.loadPendingLazyRouters(pathname);
86
+ }
81
87
  }
82
- const stillPending = [];
88
+ }
89
+ async loadPendingLazyRouters(pathname) {
83
90
  for (const pending of this.pendingLazyRouters) {
84
- if (!pending.matcher || pending.matcher.test(pathname)) {
85
- const { default: router } = await unlazy(pending.router);
86
- this.index(router, pending.path);
87
- } else {
88
- stillPending.push(pending);
91
+ if (pending.matcher === void 0 || pending.matcher.test(pathname)) {
92
+ await this.loadPendingLazyRouter(pending);
89
93
  }
90
94
  }
91
- this.pendingLazyRouters = stillPending;
92
95
  }
93
- async resolveProcedure(entry) {
94
- if (entry.procedure) {
95
- return entry.procedure;
96
+ loadPendingLazyRouter(pending) {
97
+ if (pending.loading === void 0) {
98
+ pending.loading = this.indexPendingLazyRouter(pending).catch((error) => {
99
+ pending.loading = void 0;
100
+ throw error;
101
+ });
96
102
  }
103
+ return pending.loading;
104
+ }
105
+ async indexPendingLazyRouter(pending) {
106
+ const { default: router } = await unlazy(pending.router);
107
+ this.index(router, pending.path);
108
+ this.pendingLazyRouters.delete(pending);
109
+ }
110
+ async resolveProcedure(entry) {
97
111
  const { default: maybeProcedure } = await unlazy(getRouter(this.rootRouter, entry.path));
98
112
  if (!(maybeProcedure instanceof Procedure)) {
99
113
  throw new TypeError(
@@ -124,6 +138,41 @@ function decodeParams(params) {
124
138
  return Object.fromEntries(Object.entries(params).map(([key, val]) => [key, tryDecodeURIComponent(val)]));
125
139
  }
126
140
 
141
+ function serializeHeaders(headers, serializer) {
142
+ const result = new NullProtoObj();
143
+ for (const [key, value] of Object.entries(headers)) {
144
+ if (Array.isArray(value)) {
145
+ const lines = [];
146
+ for (const item of value) {
147
+ const line2 = serializeHeaderValue(item, serializer);
148
+ if (line2 !== void 0) {
149
+ lines.push(line2);
150
+ }
151
+ }
152
+ result[key] = lines;
153
+ continue;
154
+ }
155
+ const line = serializeHeaderValue(value, serializer);
156
+ if (line !== void 0) {
157
+ result[key] = line;
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+ function serializeHeaderValue(value, serializer) {
163
+ const serialized = serializer.serialize(value);
164
+ if (Array.isArray(serialized)) {
165
+ return serialized.filter((item) => item !== void 0 && item !== null).map(String).join(",");
166
+ }
167
+ if (isTypescriptObject(serialized)) {
168
+ return Object.entries(serialized).filter(([, val]) => val !== void 0 && val !== null).map(([key, val]) => `${String(key)},${String(val)}`).join(",");
169
+ }
170
+ if (serialized !== void 0 && serialized !== null) {
171
+ return String(serialized);
172
+ }
173
+ return void 0;
174
+ }
175
+
127
176
  class OpenAPIHandlerCodecCore {
128
177
  serializer;
129
178
  errorStatusMap;
@@ -140,7 +189,7 @@ class OpenAPIHandlerCodecCore {
140
189
  const params = this.deserializeParams(matched.params, meta?.paramsStyles);
141
190
  const query = this.deserializeQuery(search, meta?.queryStyles);
142
191
  if (inputStructure === "compact") {
143
- const data = request.method === "GET" ? query : this.serializer.deserialize(await request.resolveBody(meta?.requestBodyHint));
192
+ const data = isBodylessMethod(request.method) ? query : this.serializer.deserialize(await request.resolveBody(meta?.requestBodyHint));
144
193
  if (data === void 0) {
145
194
  return params;
146
195
  }
@@ -165,7 +214,7 @@ class OpenAPIHandlerCodecCore {
165
214
  /**
166
215
  * @throws {TypeError} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
167
216
  */
168
- encodeOutput(output, procedure, path, _options) {
217
+ encodeOutput(output, procedure, path) {
169
218
  const meta = getOpenAPIMeta(procedure);
170
219
  const successStatus = meta?.successStatus ?? DEFAULT_SUCCESS_STATUS;
171
220
  const outputStructure = meta?.outputStructure ?? DEFAULT_OPENAPI_OUTPUT_STRUCTURE;
@@ -180,8 +229,8 @@ class OpenAPIHandlerCodecCore {
180
229
  throw new TypeError(`
181
230
  Invalid "detailed" output structure returned by procedure (${path.join(".")}):
182
231
  \u2022 Expected an object with optional properties:
183
- - status (number 200-399)
184
- - headers (Record<string, string | string[] | undefined>)
232
+ - status (number <400)
233
+ - headers (object)
185
234
  - body (any)
186
235
  \u2022 No extra keys allowed.
187
236
 
@@ -191,12 +240,12 @@ class OpenAPIHandlerCodecCore {
191
240
  }
192
241
  return {
193
242
  status: output.status ?? successStatus,
194
- headers: output.headers ?? {},
243
+ headers: output.headers !== void 0 ? serializeHeaders(output.headers, this.serializer) : {},
195
244
  body: this.serializer.serialize(output.body)
196
245
  };
197
246
  }
198
- encodeError(error, _procedure, _path, _options) {
199
- const status = this.errorStatusMap[error.code] ?? DEFAULT_ERROR_STATUS;
247
+ encodeError(error) {
248
+ const status = getOwn(this.errorStatusMap, error.code) ?? DEFAULT_ERROR_STATUS;
200
249
  return {
201
250
  status,
202
251
  headers: {},
@@ -288,10 +337,10 @@ function isValidDetailedOutput(output) {
288
337
  if (Object.keys(output).some((key) => key !== "status" && key !== "headers" && key !== "body")) {
289
338
  return false;
290
339
  }
291
- if (output.status !== void 0 && (typeof output.status !== "number" || !Number.isInteger(output.status) || output.status < 200 || output.status > 399)) {
340
+ if (output.status !== void 0 && (typeof output.status !== "number" || !Number.isInteger(output.status) || output.status > 399)) {
292
341
  return false;
293
342
  }
294
- if (output.headers !== void 0 && !isStandardHeaders(output.headers)) {
343
+ if (output.headers !== void 0 && !isTypescriptObject(output.headers)) {
295
344
  return false;
296
345
  }
297
346
  return true;
@@ -315,4 +364,4 @@ function decodeDelimitedObject(value, delimiter) {
315
364
  return obj;
316
365
  }
317
366
 
318
- export { OpenAPIHandlerCodec as O, OpenAPIHandlerCodecCore as a, OpenAPIMatcher as b };
367
+ export { OpenAPIHandlerCodec as O, OpenAPIHandlerCodecCore as a, OpenAPIMatcher as b, serializeHeaders as s };