@orpc/openapi 0.0.0-next.dda04c5 → 0.0.0-next.de2bec7

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 (31) hide show
  1. package/README.md +126 -14
  2. package/dist/adapters/aws-lambda/index.d.mts +8 -5
  3. package/dist/adapters/aws-lambda/index.d.ts +8 -5
  4. package/dist/adapters/aws-lambda/index.mjs +5 -5
  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 +18 -0
  8. package/dist/adapters/fetch/index.d.mts +11 -5
  9. package/dist/adapters/fetch/index.d.ts +11 -5
  10. package/dist/adapters/fetch/index.mjs +3 -3
  11. package/dist/adapters/node/index.d.mts +11 -5
  12. package/dist/adapters/node/index.d.ts +11 -5
  13. package/dist/adapters/node/index.mjs +3 -3
  14. package/dist/adapters/standard/index.d.mts +8 -23
  15. package/dist/adapters/standard/index.d.ts +8 -23
  16. package/dist/adapters/standard/index.mjs +1 -1
  17. package/dist/index.d.mts +10 -3
  18. package/dist/index.d.ts +10 -3
  19. package/dist/index.mjs +2 -2
  20. package/dist/plugins/index.d.mts +20 -3
  21. package/dist/plugins/index.d.ts +20 -3
  22. package/dist/plugins/index.mjs +69 -20
  23. package/dist/shared/{openapi.C_UtQ8Us.mjs → openapi.BB-W-NKv.mjs} +33 -8
  24. package/dist/shared/{openapi.B3hexduL.d.mts → openapi.BGy4N6eR.d.mts} +25 -6
  25. package/dist/shared/{openapi.B3hexduL.d.ts → openapi.BGy4N6eR.d.ts} +25 -6
  26. package/dist/shared/{openapi.DrrBsJ0w.mjs → openapi.BwdtJjDu.mjs} +191 -51
  27. package/dist/shared/openapi.DwaweYRb.d.mts +54 -0
  28. package/dist/shared/openapi.DwaweYRb.d.ts +54 -0
  29. package/package.json +20 -13
  30. package/dist/shared/openapi.D3j94c9n.d.mts +0 -12
  31. package/dist/shared/openapi.D3j94c9n.d.ts +0 -12
@@ -1,4 +1,4 @@
1
- export { S as StandardOpenAPICodec, a as StandardOpenAPIHandler, b as StandardOpenAPIMatcher, d as decodeParams, t as toRou3Pattern } from '../../shared/openapi.C_UtQ8Us.mjs';
1
+ export { S as StandardOpenAPICodec, a as StandardOpenAPIHandler, b as StandardOpenAPIMatcher, d as decodeParams, t as toRou3Pattern } from '../../shared/openapi.BB-W-NKv.mjs';
2
2
  import '@orpc/openapi-client/standard';
3
3
  import '@orpc/server/standard';
4
4
  import '@orpc/client';
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { OpenAPI, AnyContractProcedure } from '@orpc/contract';
2
2
  export { OpenAPI } from '@orpc/contract';
3
- export { e as CompositeSchemaConverter, C as ConditionalSchemaConverter, b as OpenAPIGenerator, a as OpenAPIGeneratorGenerateOptions, O as OpenAPIGeneratorOptions, c as SchemaConvertOptions, d as SchemaConverter, S as SchemaConverterComponent } from './shared/openapi.B3hexduL.mjs';
3
+ export { e as CompositeSchemaConverter, C as ConditionalSchemaConverter, b as OpenAPIGenerator, a as OpenAPIGeneratorGenerateOptions, O as OpenAPIGeneratorOptions, c as SchemaConvertOptions, d as SchemaConverter, S as SchemaConverterComponent } from './shared/openapi.BGy4N6eR.mjs';
4
4
  import { HTTPPath, HTTPMethod } from '@orpc/client';
5
5
  import { JSONSchema } from 'json-schema-typed/draft-2020-12';
6
6
  export { JSONSchema, ContentEncoding as JSONSchemaContentEncoding, Format as JSONSchemaFormat, TypeName as JSONSchemaTypeName } from 'json-schema-typed/draft-2020-12';
@@ -13,7 +13,7 @@ type OverrideOperationValue = Partial<OpenAPI.OperationObject> | ((current: Open
13
13
  /**
14
14
  * Customize The Operation Object by proxy an error map item or a middleware.
15
15
  *
16
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification#customizing-operation-objects Customizing Operation Objects Docs}
16
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification#customizing-operation-objects Customizing Operation Objects Docs}
17
17
  */
18
18
  declare function customOpenAPIOperation<T extends object>(o: T, extend: OverrideOperationValue): T;
19
19
  declare function getCustomOpenAPIOperation(o: object): OverrideOperationValue | undefined;
@@ -66,6 +66,12 @@ declare function checkParamsSchema(schema: ObjectSchema, params: string[]): bool
66
66
  */
67
67
  declare function toOpenAPISchema(schema: JSONSchema): OpenAPI.SchemaObject & object;
68
68
  declare function resolveOpenAPIJsonSchemaRef(doc: OpenAPI.Document, schema: JSONSchema): JSONSchema;
69
+ /**
70
+ * Simplifies composed object JSON Schemas (using anyOf, oneOf, allOf) by flattening nested compositions
71
+ *
72
+ * @warning The result is looser than the original schema and may not fully validate the same data.
73
+ */
74
+ declare function simplifyComposedObjectJsonSchemasAndRefs(schema: JSONSchema, doc?: OpenAPI.Document): JSONSchema;
69
75
 
70
76
  declare function createJsonifiedRouterClient<T extends AnyRouter, TClientContext extends ClientContext>(router: Lazyable<T | undefined>, ...rest: MaybeOptionalOptions<CreateProcedureClientOptions<InferRouterInitialContext<T>, Schema<unknown, unknown>, ErrorMap, Meta, TClientContext>>): JsonifiedClient<RouterClient<T, TClientContext>>;
71
77
 
@@ -81,6 +87,7 @@ declare function isObjectSchema(schema: JSONSchema): schema is ObjectSchema;
81
87
  * @internal
82
88
  */
83
89
  declare function isAnySchema(schema: JSONSchema): boolean;
90
+ declare function isNeverSchema(schema: JSONSchema): boolean;
84
91
  /**
85
92
  * @internal
86
93
  */
@@ -106,5 +113,5 @@ declare const oo: {
106
113
  spec: typeof customOpenAPIOperation;
107
114
  };
108
115
 
109
- export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
116
+ export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isNeverSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, simplifyComposedObjectJsonSchemasAndRefs, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
110
117
  export type { FileSchema, ObjectSchema, OverrideOperationValue };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { OpenAPI, AnyContractProcedure } from '@orpc/contract';
2
2
  export { OpenAPI } from '@orpc/contract';
3
- export { e as CompositeSchemaConverter, C as ConditionalSchemaConverter, b as OpenAPIGenerator, a as OpenAPIGeneratorGenerateOptions, O as OpenAPIGeneratorOptions, c as SchemaConvertOptions, d as SchemaConverter, S as SchemaConverterComponent } from './shared/openapi.B3hexduL.js';
3
+ export { e as CompositeSchemaConverter, C as ConditionalSchemaConverter, b as OpenAPIGenerator, a as OpenAPIGeneratorGenerateOptions, O as OpenAPIGeneratorOptions, c as SchemaConvertOptions, d as SchemaConverter, S as SchemaConverterComponent } from './shared/openapi.BGy4N6eR.js';
4
4
  import { HTTPPath, HTTPMethod } from '@orpc/client';
5
5
  import { JSONSchema } from 'json-schema-typed/draft-2020-12';
6
6
  export { JSONSchema, ContentEncoding as JSONSchemaContentEncoding, Format as JSONSchemaFormat, TypeName as JSONSchemaTypeName } from 'json-schema-typed/draft-2020-12';
@@ -13,7 +13,7 @@ type OverrideOperationValue = Partial<OpenAPI.OperationObject> | ((current: Open
13
13
  /**
14
14
  * Customize The Operation Object by proxy an error map item or a middleware.
15
15
  *
16
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification#customizing-operation-objects Customizing Operation Objects Docs}
16
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification#customizing-operation-objects Customizing Operation Objects Docs}
17
17
  */
18
18
  declare function customOpenAPIOperation<T extends object>(o: T, extend: OverrideOperationValue): T;
19
19
  declare function getCustomOpenAPIOperation(o: object): OverrideOperationValue | undefined;
@@ -66,6 +66,12 @@ declare function checkParamsSchema(schema: ObjectSchema, params: string[]): bool
66
66
  */
67
67
  declare function toOpenAPISchema(schema: JSONSchema): OpenAPI.SchemaObject & object;
68
68
  declare function resolveOpenAPIJsonSchemaRef(doc: OpenAPI.Document, schema: JSONSchema): JSONSchema;
69
+ /**
70
+ * Simplifies composed object JSON Schemas (using anyOf, oneOf, allOf) by flattening nested compositions
71
+ *
72
+ * @warning The result is looser than the original schema and may not fully validate the same data.
73
+ */
74
+ declare function simplifyComposedObjectJsonSchemasAndRefs(schema: JSONSchema, doc?: OpenAPI.Document): JSONSchema;
69
75
 
70
76
  declare function createJsonifiedRouterClient<T extends AnyRouter, TClientContext extends ClientContext>(router: Lazyable<T | undefined>, ...rest: MaybeOptionalOptions<CreateProcedureClientOptions<InferRouterInitialContext<T>, Schema<unknown, unknown>, ErrorMap, Meta, TClientContext>>): JsonifiedClient<RouterClient<T, TClientContext>>;
71
77
 
@@ -81,6 +87,7 @@ declare function isObjectSchema(schema: JSONSchema): schema is ObjectSchema;
81
87
  * @internal
82
88
  */
83
89
  declare function isAnySchema(schema: JSONSchema): boolean;
90
+ declare function isNeverSchema(schema: JSONSchema): boolean;
84
91
  /**
85
92
  * @internal
86
93
  */
@@ -106,5 +113,5 @@ declare const oo: {
106
113
  spec: typeof customOpenAPIOperation;
107
114
  };
108
115
 
109
- export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
116
+ export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isNeverSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, simplifyComposedObjectJsonSchemasAndRefs, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
110
117
  export type { FileSchema, ObjectSchema, OverrideOperationValue };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { c as customOpenAPIOperation } from './shared/openapi.DrrBsJ0w.mjs';
2
- export { C as CompositeSchemaConverter, L as LOGIC_KEYWORDS, O as OpenAPIGenerator, a as applyCustomOpenAPIOperation, n as applySchemaOptionality, h as checkParamsSchema, p as expandArrayableSchema, o as expandUnionSchema, m as filterSchemaBranches, g as getCustomOpenAPIOperation, l as isAnySchema, j as isFileSchema, k as isObjectSchema, q as isPrimitiveSchema, r as resolveOpenAPIJsonSchemaRef, s as separateObjectSchema, d as toOpenAPIContent, e as toOpenAPIEventIteratorContent, b as toOpenAPIMethod, f as toOpenAPIParameters, t as toOpenAPIPath, i as toOpenAPISchema } from './shared/openapi.DrrBsJ0w.mjs';
1
+ import { c as customOpenAPIOperation } from './shared/openapi.BwdtJjDu.mjs';
2
+ export { C as CompositeSchemaConverter, L as LOGIC_KEYWORDS, O as OpenAPIGenerator, a as applyCustomOpenAPIOperation, p as applySchemaOptionality, h as checkParamsSchema, u as expandArrayableSchema, q as expandUnionSchema, o as filterSchemaBranches, g as getCustomOpenAPIOperation, l as isAnySchema, j as isFileSchema, m as isNeverSchema, k as isObjectSchema, v as isPrimitiveSchema, r as resolveOpenAPIJsonSchemaRef, n as separateObjectSchema, s as simplifyComposedObjectJsonSchemasAndRefs, d as toOpenAPIContent, e as toOpenAPIEventIteratorContent, b as toOpenAPIMethod, f as toOpenAPIParameters, t as toOpenAPIPath, i as toOpenAPISchema } from './shared/openapi.BwdtJjDu.mjs';
3
3
  import { createORPCErrorFromJson } from '@orpc/client';
4
4
  import { StandardOpenAPISerializer, StandardOpenAPIJsonSerializer, StandardBracketNotationSerializer } from '@orpc/openapi-client/standard';
5
5
  import { ORPCError, createRouterClient } from '@orpc/server';
@@ -2,7 +2,7 @@ import { OpenAPI } from '@orpc/contract';
2
2
  import { Context, HTTPPath, Router } from '@orpc/server';
3
3
  import { StandardHandlerInterceptorOptions, StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
4
4
  import { Value, Promisable } from '@orpc/shared';
5
- import { O as OpenAPIGeneratorOptions, a as OpenAPIGeneratorGenerateOptions } from '../shared/openapi.B3hexduL.mjs';
5
+ import { O as OpenAPIGeneratorOptions, a as OpenAPIGeneratorGenerateOptions } from '../shared/openapi.BGy4N6eR.mjs';
6
6
  import '@orpc/openapi-client/standard';
7
7
  import 'json-schema-typed/draft-2020-12';
8
8
 
@@ -30,6 +30,12 @@ interface OpenAPIReferencePluginOptions<T extends Context> extends OpenAPIGenera
30
30
  * @default 'API Reference'
31
31
  */
32
32
  docsTitle?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
33
+ /**
34
+ * The UI library to use for rendering the API reference.
35
+ *
36
+ * @default 'scalar'
37
+ */
38
+ docsProvider?: 'scalar' | 'swagger';
33
39
  /**
34
40
  * Arbitrary configuration object for the UI.
35
41
  */
@@ -37,19 +43,28 @@ interface OpenAPIReferencePluginOptions<T extends Context> extends OpenAPIGenera
37
43
  /**
38
44
  * HTML to inject into the <head> of the docs page.
39
45
  *
46
+ * @warning This is not escaped special characters, so must be used with caution to avoid XSS vulnerabilities.
47
+ *
40
48
  * @default ''
41
49
  */
42
50
  docsHead?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
43
51
  /**
44
52
  * URL of the external script bundle for the reference UI.
45
53
  *
46
- * @default 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
54
+ * - For Scalar: defaults to 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
55
+ * - For Swagger UI: defaults to 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-bundle.js'
47
56
  */
48
57
  docsScriptUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
58
+ /**
59
+ * URL of the external CSS bundle for the reference UI (used by Swagger UI).
60
+ *
61
+ * @default 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui.css' (if swagger)
62
+ */
63
+ docsCssUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
49
64
  /**
50
65
  * Override function to generate the full HTML for the docs page.
51
66
  */
52
- renderDocsHtml?: (specUrl: string, title: string, head: string, scriptUrl: string, config: Record<string, unknown> | undefined, spec: OpenAPI.Document) => string;
67
+ renderDocsHtml?: (specUrl: string, title: string, head: string, scriptUrl: string, config: Record<string, unknown> | undefined, spec: OpenAPI.Document, docsProvider: 'scalar' | 'swagger', cssUrl: string | undefined) => string;
53
68
  }
54
69
  declare class OpenAPIReferencePlugin<T extends Context> implements StandardHandlerPlugin<T> {
55
70
  private readonly generator;
@@ -58,7 +73,9 @@ declare class OpenAPIReferencePlugin<T extends Context> implements StandardHandl
58
73
  private readonly docsPath;
59
74
  private readonly docsTitle;
60
75
  private readonly docsHead;
76
+ private readonly docsProvider;
61
77
  private readonly docsScriptUrl;
78
+ private readonly docsCssUrl;
62
79
  private readonly docsConfig;
63
80
  private readonly renderDocsHtml;
64
81
  constructor(options?: OpenAPIReferencePluginOptions<T>);
@@ -2,7 +2,7 @@ import { OpenAPI } from '@orpc/contract';
2
2
  import { Context, HTTPPath, Router } from '@orpc/server';
3
3
  import { StandardHandlerInterceptorOptions, StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
4
4
  import { Value, Promisable } from '@orpc/shared';
5
- import { O as OpenAPIGeneratorOptions, a as OpenAPIGeneratorGenerateOptions } from '../shared/openapi.B3hexduL.js';
5
+ import { O as OpenAPIGeneratorOptions, a as OpenAPIGeneratorGenerateOptions } from '../shared/openapi.BGy4N6eR.js';
6
6
  import '@orpc/openapi-client/standard';
7
7
  import 'json-schema-typed/draft-2020-12';
8
8
 
@@ -30,6 +30,12 @@ interface OpenAPIReferencePluginOptions<T extends Context> extends OpenAPIGenera
30
30
  * @default 'API Reference'
31
31
  */
32
32
  docsTitle?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
33
+ /**
34
+ * The UI library to use for rendering the API reference.
35
+ *
36
+ * @default 'scalar'
37
+ */
38
+ docsProvider?: 'scalar' | 'swagger';
33
39
  /**
34
40
  * Arbitrary configuration object for the UI.
35
41
  */
@@ -37,19 +43,28 @@ interface OpenAPIReferencePluginOptions<T extends Context> extends OpenAPIGenera
37
43
  /**
38
44
  * HTML to inject into the <head> of the docs page.
39
45
  *
46
+ * @warning This is not escaped special characters, so must be used with caution to avoid XSS vulnerabilities.
47
+ *
40
48
  * @default ''
41
49
  */
42
50
  docsHead?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
43
51
  /**
44
52
  * URL of the external script bundle for the reference UI.
45
53
  *
46
- * @default 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
54
+ * - For Scalar: defaults to 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
55
+ * - For Swagger UI: defaults to 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-bundle.js'
47
56
  */
48
57
  docsScriptUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
58
+ /**
59
+ * URL of the external CSS bundle for the reference UI (used by Swagger UI).
60
+ *
61
+ * @default 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui.css' (if swagger)
62
+ */
63
+ docsCssUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
49
64
  /**
50
65
  * Override function to generate the full HTML for the docs page.
51
66
  */
52
- renderDocsHtml?: (specUrl: string, title: string, head: string, scriptUrl: string, config: Record<string, unknown> | undefined, spec: OpenAPI.Document) => string;
67
+ renderDocsHtml?: (specUrl: string, title: string, head: string, scriptUrl: string, config: Record<string, unknown> | undefined, spec: OpenAPI.Document, docsProvider: 'scalar' | 'swagger', cssUrl: string | undefined) => string;
53
68
  }
54
69
  declare class OpenAPIReferencePlugin<T extends Context> implements StandardHandlerPlugin<T> {
55
70
  private readonly generator;
@@ -58,7 +73,9 @@ declare class OpenAPIReferencePlugin<T extends Context> implements StandardHandl
58
73
  private readonly docsPath;
59
74
  private readonly docsTitle;
60
75
  private readonly docsHead;
76
+ private readonly docsProvider;
61
77
  private readonly docsScriptUrl;
78
+ private readonly docsCssUrl;
62
79
  private readonly docsConfig;
63
80
  private readonly renderDocsHtml;
64
81
  constructor(options?: OpenAPIReferencePluginOptions<T>);
@@ -1,5 +1,5 @@
1
1
  import { stringifyJSON, once, value } from '@orpc/shared';
2
- import { O as OpenAPIGenerator } from '../shared/openapi.DrrBsJ0w.mjs';
2
+ import { O as OpenAPIGenerator } from '../shared/openapi.BwdtJjDu.mjs';
3
3
  import '@orpc/client';
4
4
  import '@orpc/client/standard';
5
5
  import '@orpc/contract';
@@ -14,7 +14,9 @@ class OpenAPIReferencePlugin {
14
14
  docsPath;
15
15
  docsTitle;
16
16
  docsHead;
17
+ docsProvider;
17
18
  docsScriptUrl;
19
+ docsCssUrl;
18
20
  docsConfig;
19
21
  renderDocsHtml;
20
22
  constructor(options = {}) {
@@ -22,36 +24,81 @@ class OpenAPIReferencePlugin {
22
24
  this.docsPath = options.docsPath ?? "/";
23
25
  this.docsTitle = options.docsTitle ?? "API Reference";
24
26
  this.docsConfig = options.docsConfig ?? void 0;
25
- this.docsScriptUrl = options.docsScriptUrl ?? "https://cdn.jsdelivr.net/npm/@scalar/api-reference";
27
+ this.docsProvider = options.docsProvider ?? "scalar";
28
+ this.docsScriptUrl = options.docsScriptUrl ?? (this.docsProvider === "swagger" ? "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js" : "https://cdn.jsdelivr.net/npm/@scalar/api-reference");
29
+ this.docsCssUrl = options.docsCssUrl ?? (this.docsProvider === "swagger" ? "https://unpkg.com/swagger-ui-dist/swagger-ui.css" : void 0);
26
30
  this.docsHead = options.docsHead ?? "";
27
31
  this.specPath = options.specPath ?? "/spec.json";
28
32
  this.generator = new OpenAPIGenerator(options);
29
- const esc = (s) => s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
30
- this.renderDocsHtml = options.renderDocsHtml ?? ((specUrl, title, head, scriptUrl, config, spec) => {
31
- const finalConfig = {
32
- content: stringifyJSON(spec),
33
- ...config
34
- };
33
+ const escapeHtmlEntities = (s) => s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
34
+ const escapeJsonForHtml = (obj) => stringifyJSON(obj).replace(/&/g, "\\u0026").replace(/'/g, "\\u0027").replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/\//g, "\\u002F");
35
+ this.renderDocsHtml = options.renderDocsHtml ?? ((specUrl, title, head, scriptUrl, config, spec, docsProvider, cssUrl) => {
36
+ let body;
37
+ if (docsProvider === "swagger") {
38
+ const swaggerConfig = {
39
+ dom_id: "#app",
40
+ spec,
41
+ deepLinking: true,
42
+ presets: [
43
+ "SwaggerUIBundle.presets.apis",
44
+ "SwaggerUIBundle.presets.standalone"
45
+ ],
46
+ plugins: [
47
+ "SwaggerUIBundle.plugins.DownloadUrl"
48
+ ],
49
+ ...config
50
+ };
51
+ body = `
52
+ <body>
53
+ <div id="app"></div>
54
+
55
+ <script src="${escapeHtmlEntities(scriptUrl)}"><\/script>
56
+
57
+ <!-- IMPORTANT: assign to a variable first to prevent ), ( in values breaking the call expression. -->
58
+ <!-- IMPORTANT: escapeJsonForHtml ensures <, > cannot terminate the <\/script> tag prematurely. -->
59
+ <script>
60
+ const swaggerConfig = ${escapeJsonForHtml(swaggerConfig).replace(/"(SwaggerUIBundle\.[^"]+)"/g, "$1")}
61
+
62
+ window.onload = () => {
63
+ window.ui = SwaggerUIBundle(swaggerConfig)
64
+ }
65
+ <\/script>
66
+ </body>
67
+ `;
68
+ } else {
69
+ const scalarConfig = {
70
+ content: stringifyJSON(spec),
71
+ ...config
72
+ };
73
+ body = `
74
+ <body>
75
+ <div id="app"></div>
76
+
77
+ <script src="${escapeHtmlEntities(scriptUrl)}"><\/script>
78
+
79
+ <!-- IMPORTANT: assign to a variable first to prevent ), ( in values breaking the call expression. -->
80
+ <!-- IMPORTANT: escapeJsonForHtml ensures <, > cannot terminate the <\/script> tag prematurely. -->
81
+ <script>
82
+ const scalarConfig = ${escapeJsonForHtml(scalarConfig)}
83
+
84
+ Scalar.createApiReference('#app', scalarConfig)
85
+ <\/script>
86
+ </body>
87
+ `;
88
+ }
35
89
  return `
36
90
  <!doctype html>
37
91
  <html>
38
92
  <head>
39
93
  <meta charset="utf-8" />
40
94
  <meta name="viewport" content="width=device-width, initial-scale=1" />
41
- <title>${esc(title)}</title>
95
+ <title>${escapeHtmlEntities(title)}</title>
96
+ ${cssUrl ? `<link rel="stylesheet" type="text/css" href="${escapeHtmlEntities(cssUrl)}" />` : ""}
42
97
  ${head}
43
98
  </head>
44
- <body>
45
- <div id="app" data-config="${esc(stringifyJSON(finalConfig))}"></div>
46
-
47
- <script src="${esc(scriptUrl)}"><\/script>
48
-
49
- <script>
50
- Scalar.createApiReference('#app', JSON.parse(document.getElementById('app').dataset.config))
51
- <\/script>
52
- </body>
99
+ ${body}
53
100
  </html>
54
- `;
101
+ `;
55
102
  });
56
103
  }
57
104
  init(options, router) {
@@ -89,7 +136,9 @@ class OpenAPIReferencePlugin {
89
136
  await value(this.docsHead, options2),
90
137
  await value(this.docsScriptUrl, options2),
91
138
  await value(this.docsConfig, options2),
92
- await generateSpec()
139
+ await generateSpec(),
140
+ this.docsProvider,
141
+ await value(this.docsCssUrl, options2)
93
142
  );
94
143
  return {
95
144
  matched: true,
@@ -2,15 +2,17 @@ import { standardizeHTTPPath, StandardOpenAPIJsonSerializer, StandardBracketNota
2
2
  import { StandardHandler } from '@orpc/server/standard';
3
3
  import { isORPCErrorStatus } from '@orpc/client';
4
4
  import { fallbackContractConfig } from '@orpc/contract';
5
- import { isObject, stringifyJSON } from '@orpc/shared';
5
+ import { isObject, stringifyJSON, tryDecodeURIComponent, value } from '@orpc/shared';
6
6
  import { toHttpPath } from '@orpc/client/standard';
7
7
  import { traverseContractProcedures, isProcedure, getLazyMeta, unlazy, getRouter, createContractedProcedure } from '@orpc/server';
8
8
  import { createRouter, addRoute, findRoute } from 'rou3';
9
9
 
10
10
  class StandardOpenAPICodec {
11
- constructor(serializer) {
11
+ constructor(serializer, options = {}) {
12
12
  this.serializer = serializer;
13
+ this.customErrorResponseBodyEncoder = options.customErrorResponseBodyEncoder;
13
14
  }
15
+ customErrorResponseBodyEncoder;
14
16
  async decode(request, params, procedure) {
15
17
  const inputStructure = fallbackContractConfig("defaultInputStructure", procedure["~orpc"].route.inputStructure);
16
18
  if (inputStructure === "compact") {
@@ -47,6 +49,13 @@ class StandardOpenAPICodec {
47
49
  const successStatus = fallbackContractConfig("defaultSuccessStatus", procedure["~orpc"].route.successStatus);
48
50
  const outputStructure = fallbackContractConfig("defaultOutputStructure", procedure["~orpc"].route.outputStructure);
49
51
  if (outputStructure === "compact") {
52
+ if (output instanceof ReadableStream) {
53
+ return {
54
+ status: successStatus,
55
+ headers: {},
56
+ body: output
57
+ };
58
+ }
50
59
  return {
51
60
  status: successStatus,
52
61
  headers: {},
@@ -66,6 +75,13 @@ class StandardOpenAPICodec {
66
75
  ${stringifyJSON(output)}
67
76
  `);
68
77
  }
78
+ if (output.body instanceof ReadableStream) {
79
+ return {
80
+ status: output.status ?? successStatus,
81
+ headers: output.headers ?? {},
82
+ body: output.body
83
+ };
84
+ }
69
85
  return {
70
86
  status: output.status ?? successStatus,
71
87
  headers: output.headers ?? {},
@@ -73,10 +89,11 @@ class StandardOpenAPICodec {
73
89
  };
74
90
  }
75
91
  encodeError(error) {
92
+ const body = this.customErrorResponseBodyEncoder?.(error) ?? error.toJSON();
76
93
  return {
77
94
  status: error.status,
78
95
  headers: {},
79
- body: this.serializer.serialize(error.toJSON(), { outputFormat: "plain" })
96
+ body: this.serializer.serialize(body, { outputFormat: "plain" })
80
97
  };
81
98
  }
82
99
  #isDetailedOutput(output) {
@@ -97,14 +114,22 @@ function toRou3Pattern(path) {
97
114
  return standardizeHTTPPath(path).replace(/\/\{\+([^}]+)\}/g, "/**:$1").replace(/\/\{([^}]+)\}/g, "/:$1");
98
115
  }
99
116
  function decodeParams(params) {
100
- return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, decodeURIComponent(value)]));
117
+ return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, tryDecodeURIComponent(value)]));
101
118
  }
102
119
 
103
120
  class StandardOpenAPIMatcher {
121
+ filter;
104
122
  tree = createRouter();
105
123
  pendingRouters = [];
124
+ constructor(options = {}) {
125
+ this.filter = options.filter ?? true;
126
+ }
106
127
  init(router, path = []) {
107
- const laziedOptions = traverseContractProcedures({ router, path }, ({ path: path2, contract }) => {
128
+ const laziedOptions = traverseContractProcedures({ router, path }, (traverseOptions) => {
129
+ if (!value(this.filter, traverseOptions)) {
130
+ return;
131
+ }
132
+ const { path: path2, contract } = traverseOptions;
108
133
  const method = fallbackContractConfig("defaultMethod", contract["~orpc"].route.method);
109
134
  const httpPath = toRou3Pattern(contract["~orpc"].route.path ?? toHttpPath(path2));
110
135
  if (isProcedure(contract)) {
@@ -168,10 +193,10 @@ class StandardOpenAPIMatcher {
168
193
  class StandardOpenAPIHandler extends StandardHandler {
169
194
  constructor(router, options) {
170
195
  const jsonSerializer = new StandardOpenAPIJsonSerializer(options);
171
- const bracketNotationSerializer = new StandardBracketNotationSerializer();
196
+ const bracketNotationSerializer = new StandardBracketNotationSerializer(options);
172
197
  const serializer = new StandardOpenAPISerializer(jsonSerializer, bracketNotationSerializer);
173
- const matcher = new StandardOpenAPIMatcher();
174
- const codec = new StandardOpenAPICodec(serializer);
198
+ const matcher = new StandardOpenAPIMatcher(options);
199
+ const codec = new StandardOpenAPICodec(serializer, options);
175
200
  super(router, matcher, codec, options);
176
201
  }
177
202
  }
@@ -1,7 +1,7 @@
1
1
  import { AnySchema, OpenAPI, AnyContractProcedure, AnyContractRouter } from '@orpc/contract';
2
2
  import { StandardOpenAPIJsonSerializerOptions } from '@orpc/openapi-client/standard';
3
- import { AnyProcedure, AnyRouter } from '@orpc/server';
4
- import { Promisable } from '@orpc/shared';
3
+ import { AnyProcedure, TraverseContractProcedureCallbackOptions, AnyRouter } from '@orpc/server';
4
+ import { Promisable, Value } from '@orpc/shared';
5
5
  import { JSONSchema } from 'json-schema-typed/draft-2020-12';
6
6
 
7
7
  interface SchemaConverterComponent {
@@ -33,7 +33,7 @@ interface ConditionalSchemaConverter extends SchemaConverter {
33
33
  }
34
34
  declare class CompositeSchemaConverter implements SchemaConverter {
35
35
  private readonly converters;
36
- constructor(converters: ConditionalSchemaConverter[]);
36
+ constructor(converters: readonly ConditionalSchemaConverter[]);
37
37
  convert(schema: AnySchema | undefined, options: SchemaConvertOptions): Promise<[required: boolean, jsonSchema: JSONSchema]>;
38
38
  }
39
39
 
@@ -44,9 +44,16 @@ interface OpenAPIGeneratorGenerateOptions extends Partial<Omit<OpenAPI.Document,
44
44
  /**
45
45
  * Exclude procedures from the OpenAPI specification.
46
46
  *
47
+ * @deprecated Use `filter` option instead.
47
48
  * @default () => false
48
49
  */
49
50
  exclude?: (procedure: AnyProcedure | AnyContractProcedure, path: readonly string[]) => boolean;
51
+ /**
52
+ * Filter procedures. Return `false` to exclude a procedure from the OpenAPI specification.
53
+ *
54
+ * @default true
55
+ */
56
+ filter?: Value<boolean, [options: TraverseContractProcedureCallbackOptions]>;
50
57
  /**
51
58
  * Common schemas to be used for $ref resolution.
52
59
  */
@@ -78,11 +85,23 @@ interface OpenAPIGeneratorGenerateOptions extends Partial<Omit<OpenAPI.Document,
78
85
  error: 'UndefinedError';
79
86
  schema?: never;
80
87
  }>;
88
+ /**
89
+ * Define a custom JSON schema for the error response body when using
90
+ * type-safe errors. Helps align ORPC error formatting with existing API
91
+ * response standards or conventions.
92
+ *
93
+ * @remarks
94
+ * - Return `null | undefined` to use the default error response body shaper.
95
+ */
96
+ customErrorResponseBodySchema?: Value<JSONSchema | undefined | null, [
97
+ definedErrors: [code: string, defaultMessage: string, dataRequired: boolean, dataSchema: JSONSchema][],
98
+ status: number
99
+ ]>;
81
100
  }
82
101
  /**
83
102
  * The generator that converts oRPC routers/contracts to OpenAPI specifications.
84
103
  *
85
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
104
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification OpenAPI Specification Docs}
86
105
  */
87
106
  declare class OpenAPIGenerator {
88
107
  #private;
@@ -92,9 +111,9 @@ declare class OpenAPIGenerator {
92
111
  /**
93
112
  * Generates OpenAPI specifications from oRPC routers/contracts.
94
113
  *
95
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
114
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification OpenAPI Specification Docs}
96
115
  */
97
- generate(router: AnyContractRouter | AnyRouter, options?: OpenAPIGeneratorGenerateOptions): Promise<OpenAPI.Document>;
116
+ generate(router: AnyContractRouter | AnyRouter, { customErrorResponseBodySchema, commonSchemas, filter: baseFilter, exclude, ...baseDoc }?: OpenAPIGeneratorGenerateOptions): Promise<OpenAPI.Document>;
98
117
  }
99
118
 
100
119
  export { OpenAPIGenerator as b, CompositeSchemaConverter as e };
@@ -1,7 +1,7 @@
1
1
  import { AnySchema, OpenAPI, AnyContractProcedure, AnyContractRouter } from '@orpc/contract';
2
2
  import { StandardOpenAPIJsonSerializerOptions } from '@orpc/openapi-client/standard';
3
- import { AnyProcedure, AnyRouter } from '@orpc/server';
4
- import { Promisable } from '@orpc/shared';
3
+ import { AnyProcedure, TraverseContractProcedureCallbackOptions, AnyRouter } from '@orpc/server';
4
+ import { Promisable, Value } from '@orpc/shared';
5
5
  import { JSONSchema } from 'json-schema-typed/draft-2020-12';
6
6
 
7
7
  interface SchemaConverterComponent {
@@ -33,7 +33,7 @@ interface ConditionalSchemaConverter extends SchemaConverter {
33
33
  }
34
34
  declare class CompositeSchemaConverter implements SchemaConverter {
35
35
  private readonly converters;
36
- constructor(converters: ConditionalSchemaConverter[]);
36
+ constructor(converters: readonly ConditionalSchemaConverter[]);
37
37
  convert(schema: AnySchema | undefined, options: SchemaConvertOptions): Promise<[required: boolean, jsonSchema: JSONSchema]>;
38
38
  }
39
39
 
@@ -44,9 +44,16 @@ interface OpenAPIGeneratorGenerateOptions extends Partial<Omit<OpenAPI.Document,
44
44
  /**
45
45
  * Exclude procedures from the OpenAPI specification.
46
46
  *
47
+ * @deprecated Use `filter` option instead.
47
48
  * @default () => false
48
49
  */
49
50
  exclude?: (procedure: AnyProcedure | AnyContractProcedure, path: readonly string[]) => boolean;
51
+ /**
52
+ * Filter procedures. Return `false` to exclude a procedure from the OpenAPI specification.
53
+ *
54
+ * @default true
55
+ */
56
+ filter?: Value<boolean, [options: TraverseContractProcedureCallbackOptions]>;
50
57
  /**
51
58
  * Common schemas to be used for $ref resolution.
52
59
  */
@@ -78,11 +85,23 @@ interface OpenAPIGeneratorGenerateOptions extends Partial<Omit<OpenAPI.Document,
78
85
  error: 'UndefinedError';
79
86
  schema?: never;
80
87
  }>;
88
+ /**
89
+ * Define a custom JSON schema for the error response body when using
90
+ * type-safe errors. Helps align ORPC error formatting with existing API
91
+ * response standards or conventions.
92
+ *
93
+ * @remarks
94
+ * - Return `null | undefined` to use the default error response body shaper.
95
+ */
96
+ customErrorResponseBodySchema?: Value<JSONSchema | undefined | null, [
97
+ definedErrors: [code: string, defaultMessage: string, dataRequired: boolean, dataSchema: JSONSchema][],
98
+ status: number
99
+ ]>;
81
100
  }
82
101
  /**
83
102
  * The generator that converts oRPC routers/contracts to OpenAPI specifications.
84
103
  *
85
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
104
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification OpenAPI Specification Docs}
86
105
  */
87
106
  declare class OpenAPIGenerator {
88
107
  #private;
@@ -92,9 +111,9 @@ declare class OpenAPIGenerator {
92
111
  /**
93
112
  * Generates OpenAPI specifications from oRPC routers/contracts.
94
113
  *
95
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
114
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification OpenAPI Specification Docs}
96
115
  */
97
- generate(router: AnyContractRouter | AnyRouter, options?: OpenAPIGeneratorGenerateOptions): Promise<OpenAPI.Document>;
116
+ generate(router: AnyContractRouter | AnyRouter, { customErrorResponseBodySchema, commonSchemas, filter: baseFilter, exclude, ...baseDoc }?: OpenAPIGeneratorGenerateOptions): Promise<OpenAPI.Document>;
98
117
  }
99
118
 
100
119
  export { OpenAPIGenerator as b, CompositeSchemaConverter as e };