OpenAPILink
OpenAPILink enables communication with an OpenAPIHandler or any API that follows the OpenAPI Specification using HTTP/Fetch.
Installation
npm install @orpc/openapi-client@latest
yarn add @orpc/openapi-client@latest
pnpm add @orpc/openapi-client@latest
bun add @orpc/openapi-client@latest
deno install npm:@orpc/openapi-client@latest
Setup
To use OpenAPILink
, ensure you have a contract router and that your server is set up with OpenAPIHandler or any API that follows the OpenAPI Specification.
INFO
A normal router works as a contract router as long as it does not include a lazy router. You can also unlazy a router using the unlazyRouter utility.
import type { JsonifiedClient } from '@orpc/openapi-client'
import type { ContractRouterClient } from '@orpc/contract'
import { createORPCClient } from '@orpc/client'
import { OpenAPILink } from '@orpc/openapi-client/fetch'
const link = new OpenAPILink(contract, {
url: 'http://localhost:3000/api',
headers: () => ({
'x-api-key': 'my-api-key',
}),
// fetch: <-- polyfill fetch if needed
})
const client: JsonifiedClient<ContractRouterClient<typeof contract>> = createORPCClient(link)
WARNING
Wrap your client with JsonifiedClient
to ensure it accurately reflects the server responses.
Limitations
Unlike RPCLink, OpenAPILink
has some constraints:
- Payloads containing a
Blob
orFile
(outside the root level) must usemultipart/form-data
and serialized using Bracket Notation. - For
GET
requests, the payload must be sent asURLSearchParams
and serialized using Bracket Notation.
WARNING
In these cases, both the request and response are subject to the limitations of Bracket Notation Limitations. Additionally, oRPC converts data to strings (exclude null
and undefined
will not be represented).
CORS policy
OpenAPILink
requires access to the Content-Disposition
to distinguish file responses from other responses whe file has a common MIME type like application/json
, plain/text
, etc. To enable this, include Content-Disposition
in your CORS policy's Access-Control-Expose-Headers
:
const handler = new OpenAPIHandler(router, {
plugins: [
new CORSPlugin({
exposeHeaders: ['Content-Disposition'],
}),
],
})
Using Client Context
Client context lets you pass extra information when calling procedures and dynamically modify OpenAPILink's behavior.
import type { JsonifiedClient } from '@orpc/openapi-client'
import type { ContractRouterClient } from '@orpc/contract'
import { createORPCClient } from '@orpc/client'
import { OpenAPILink } from '@orpc/openapi-client/fetch'
interface ClientContext {
something?: string
}
const link = new OpenAPILink<ClientContext>(contract, {
url: 'http://localhost:3000/api',
headers: async ({ context }) => ({
'x-api-key': context?.something ?? ''
})
})
const client: JsonifiedClient<ContractRouterClient<typeof contract, ClientContext>> = createORPCClient(link)
const result = await client.planet.list(
{ limit: 10 },
{ context: { something: 'value' } }
)
INFO
If a property in ClientContext
is required, oRPC enforces its inclusion when calling procedures.
Lazy URL
You can define url
as a function, ensuring compatibility with environments that may lack certain runtime APIs.
const link = new OpenAPILink({
url: () => {
if (typeof window === 'undefined') {
throw new Error('OpenAPILink is not allowed on the server side.')
}
return new URL('/api', window.location.href)
},
})
SSE Like Behavior
Unlike traditional SSE, the Event Iterator does not automatically retry on error. To enable automatic retries, refer to the Client Retry Plugin.
Event Iterator Keep Alive
WARNING
These options for sending Event Iterator from client to the server, not from the server to client as used in RPCHandler Event Iterator Keep Alive or OpenAPIHandler Event Iterator Keep Alive.
In 99% of cases, you don't need to configure these options.
To keep Event Iterator connections alive, OpenAPILink
periodically sends a ping comment to the server. You can configure this behavior using the following options:
eventIteratorKeepAliveEnabled
(default:true
) – Enables or disables pings.eventIteratorKeepAliveInterval
(default:5000
) – Time between pings (in milliseconds).eventIteratorKeepAliveComment
(default:''
) – Custom content for ping messages.
const link = new OpenAPILink({
eventIteratorKeepAliveEnabled: true,
eventIteratorKeepAliveInterval: 5000, // 5 seconds
eventIteratorKeepAliveComment: '',
})