Skip to content

Commit 5559bf8

Browse files
authored
docs: Type‑Safe Validation Errors & Customize OpenAPI Specification (#173)
* Type‑Safe Validation Errors * Customizing Operation Objects * Customizing Operation Objects * Operation Metadata * improve * fix types
1 parent d45a518 commit 5559bf8

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

apps/content/docs/advanced/validation-errors.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,44 @@ Every [procedure](/docs/procedure) built from `base` now uses these customized v
9191
:::warning
9292
Middleware applied before `.input`/`.output` catches validation errors by default, but this behavior can be configured.
9393
:::
94+
95+
## Type‑Safe Validation Errors
96+
97+
As explained in the [error handling guide](/docs/error-handling#combining-both-approaches), when you throw an `ORPCError` instance, if the `code` and `data` match with the errors defined in the `.errors` method, oRPC will treat it exactly as if you had thrown `errors.[code]` using the type‑safe approach.
98+
99+
```ts twoslash
100+
import { z } from 'zod'
101+
import { RPCHandler } from '@orpc/server/fetch'
102+
// ---cut---
103+
import { onError, ORPCError, os, ValidationError } from '@orpc/server'
104+
105+
const base = os.errors({
106+
INPUT_VALIDATION_FAILED: {
107+
data: z.object({
108+
issues: z.array(z.object({
109+
message: z.string(),
110+
})),
111+
})
112+
},
113+
})
114+
115+
const ping = base.handler(() => 'ping')
116+
const pong = base.handler(() => 'pong')
117+
118+
const handler = new RPCHandler({ ping, pong }, {
119+
clientInterceptors: [
120+
onError((error) => {
121+
if (
122+
error instanceof ORPCError
123+
&& error.code === 'BAD_REQUEST'
124+
&& error.cause instanceof ValidationError
125+
) {
126+
throw new ORPCError('INPUT_VALIDATION_FAILED', {
127+
data: { issues: error.cause.issues },
128+
cause: error.cause,
129+
})
130+
}
131+
})
132+
]
133+
})
134+
```

apps/content/docs/openapi/openapi-specification.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@ const specFromRouter = await openAPIGenerator.generate(router, {
6666
})
6767
```
6868

69+
## Operation Metadata
70+
71+
You can enrich your API documentation by specifying operation metadata using the `.route` or `.tag`:
72+
73+
```ts
74+
const ping = os
75+
.route({
76+
summary: 'the summary',
77+
description: 'the description',
78+
deprecated: false,
79+
tags: ['tag'],
80+
successDescription: 'the success description',
81+
})
82+
.handler(() => {})
83+
84+
// or append tag for entire router
85+
86+
const router = os.tag('planets').router({
87+
// ...
88+
})
89+
```
90+
6991
## File Schema
7092

7193
In the [File Upload/Download](/docs/file-upload-download) guide, `z.instanceof` is used to describe file/blob schemas. However, this method prevents oRPC from recognizing file/blob schema. Instead, use the enhanced file schema approach:
@@ -81,7 +103,41 @@ const InputSchema = z.object({
81103
})
82104
```
83105

84-
## Extending the Specification
106+
## Customizing Operation Objects
107+
108+
You can also extend the operation object using the `.spec` helper for an `error` or `middleware`:
109+
110+
```ts
111+
import { oo } from '@orpc/openapi'
112+
113+
const base = os.errors({
114+
UNAUTHORIZED: oo.spec({
115+
data: z.any(),
116+
}, {
117+
security: [{ 'api-key': [] }],
118+
})
119+
})
120+
121+
// OR in middleware
122+
123+
const requireAuth = oo.spec(
124+
os.middleware(async ({ next, errors }) => {
125+
throw new ORPCError('UNAUTHORIZED')
126+
return next()
127+
}),
128+
{
129+
security: [{ 'api-key': [] }]
130+
}
131+
)
132+
```
133+
134+
Any [procedure](/docs/procedure) that includes the use above `errors` or `middleware` will automatically have the defined `security` property applied
135+
136+
:::info
137+
The `.spec` helper accepts a callback as its second argument, allowing you to override the entire operation object.
138+
:::
139+
140+
## JSON Schema Customization
85141

86142
If Zod alone does not cover your JSON Schema requirements, you can extend or override the generated schema:
87143

0 commit comments

Comments
 (0)