OFetch
此内容尚不支持你的语言。
ofetch is a better Fetch API that adds useful defaults and features such as automatic response parsing, request/response hooks, and it works in Node, browser, and workers.
The ofetch client for Hey API generates a type-safe client from your OpenAPI spec, fully compatible with validators, transformers, and all core features.
Collaborators
Section titled “Collaborators”Features
Section titled “Features”- seamless integration with
@hey-api/openapi-tsecosystem - type-safe response data and errors
- response data validation and transformation
- access to the original request and response
- granular request and response customization options
- minimal learning curve thanks to extending the underlying technology
- support bundling inside the generated output
Installation
Section titled “Installation”In your configuration, add @hey-api/client-ofetch to your plugins and you’ll be ready to generate client artifacts. 🎉
export default { input: 'hey-api/backend', // sign up at app.heyapi.dev output: 'src/client', plugins: ['@hey-api/client-ofetch'],};npx @hey-api/openapi-ts \ -i hey-api/backend \ -o src/client \ -c @hey-api/client-ofetchConfiguration
Section titled “Configuration”The ofetch client is built as a thin wrapper on top of ofetch, extending its functionality to work with Hey API. If you’re already familiar with ofetch, configuring your client will feel like working directly with ofetch.
When we installed the client above, it created a client.gen.ts file. You will most likely want to configure the exported client instance. There are two ways to do that.
setConfig()
Section titled “setConfig()”This is the simpler approach. You can call the setConfig() method at the beginning of your application or anytime you need to update the client configuration. You can pass any ofetch configuration option to setConfig(), and even your own ofetch instance.
import { client } from 'client/client.gen';
client.setConfig({ baseUrl: 'https://example.com',});The disadvantage of this approach is that your code may call the client instance before it’s configured for the first time. Depending on your use case, you might need to use the second approach.
Runtime API
Section titled “Runtime API”Since client.gen.ts is a generated file, we can’t directly modify it. Instead, we can tell our configuration to use a custom file implementing the Runtime API. We do that by specifying the runtimeConfigPath option.
export default { input: 'hey-api/backend', // sign up at app.heyapi.dev output: 'src/client', plugins: [ { name: '@hey-api/client-ofetch', runtimeConfigPath: './src/hey-api.ts', }, ],};In our custom file, we need to export a createClientConfig() method. This function is a simple wrapper allowing us to override configuration values.
import type { CreateClientConfig } from './client/client.gen';
export const createClientConfig: CreateClientConfig = (config) => ({ ...config, baseUrl: 'https://example.com',});With this approach, client.gen.ts will call createClientConfig() before initializing the client instance. If needed, you can still use setConfig() to update the client configuration later.
createClient()
Section titled “createClient()”You can also create your own client instance. You can use it to manually send requests or point it to a different domain.
import { createClient } from './client/client';
const myClient = createClient({ baseUrl: 'https://example.com',});You can also pass this instance to any SDK function through the client option. This will override the default instance from client.gen.ts.
const response = await getFoo({ client: myClient,});Alternatively, you can pass the client configuration options to each SDK function. This is useful if you don’t want to create a client instance for one-off use cases.
const response = await getFoo({ baseUrl: 'https://example.com', // <-- override default configuration});Interceptors
Section titled “Interceptors”Interceptors (middleware) can be used to modify requests before they’re sent or responses before they’re returned to your application.
The ofetch client supports two complementary options:
- built-in Hey API interceptors exposed via
client.interceptors - native
ofetchhooks passed through config (e.g.,onRequest)
Example: Request interceptor
Section titled “Example: Request interceptor”import { client } from 'client/client.gen';
async function myInterceptor(request) { // do something return request;}
interceptorId = client.interceptors.request.use(myInterceptor);import { client } from 'client/client.gen';
// eject by IDclient.interceptors.request.eject(interceptorId);
// eject by referenceclient.interceptors.request.eject(myInterceptor);import { client } from 'client/client.gen';
async function myNewInterceptor(request) { // do something return request;}
// update by IDclient.interceptors.request.update(interceptorId, myNewInterceptor);
// update by referenceclient.interceptors.request.update(myInterceptor, myNewInterceptor);Example: Response interceptor
Section titled “Example: Response interceptor”import { client } from 'client/client.gen';
async function myInterceptor(response) { // do something return response;}
interceptorId = client.interceptors.response.use(myInterceptor);import { client } from 'client/client.gen';
// eject by IDclient.interceptors.response.eject(interceptorId);
// eject by referenceclient.interceptors.response.eject(myInterceptor);import { client } from 'client/client.gen';
async function myNewInterceptor(response) { // do something return response;}
// update by IDclient.interceptors.response.update(interceptorId, myNewInterceptor);
// update by referenceclient.interceptors.response.update(myInterceptor, myNewInterceptor);Example: ofetch hooks
Section titled “Example: ofetch hooks”import { client } from 'client/client.gen';
client.setConfig({ onRequest: ({ options }) => { // mutate ofetch options (headers, query, etc.) }, onResponse: ({ response }) => { // inspect/transform the raw Response }, onRequestError: (ctx) => { // handle request errors }, onResponseError: (ctx) => { // handle response errors },});The SDKs include auth mechanisms for every endpoint. You will want to configure the auth field to pass the right token for each request. The auth field can be a string or a function returning a string representing the token. The returned value will be attached only to requests that require auth.
import { client } from 'client/client.gen';
client.setConfig({ auth: () => '<my_token>', baseUrl: 'https://example.com',});If you’re not using SDKs or generating auth, using interceptors is a common approach to configuring auth for each request.
import { client } from 'client/client.gen';
client.interceptors.request.use((request, options) => { request.headers.set('Authorization', 'Bearer <my_token>'); return request;});You can also use the ofetch hooks.
import { client } from 'client/client.gen';
client.setConfig({ onRequest: ({ options }) => { options.headers.set('Authorization', 'Bearer <my_token>'); },});Build URL
Section titled “Build URL”If you need to access the compiled URL, you can use the buildUrl() method. It’s loosely typed by default to accept almost any value; in practice, you will want to pass a type hint.
type FooData = { path: { fooId: number; }; query?: { bar?: string; }; url: '/foo/{fooId}';};
const url = client.buildUrl<FooData>({ path: { fooId: 1, }, query: { bar: 'baz', }, url: '/foo/{fooId}',});console.log(url); // prints '/foo/1?bar=baz'Custom Instance
Section titled “Custom Instance”You can provide a custom ofetch instance. This is useful if you need to extend the default instance with extra functionality, or replace it altogether.
import { ofetch } from 'ofetch';import { client } from 'client/client.gen';
const customOFetchInstance = ofetch.create({ onRequest: ({ options }) => { // customize request }, onResponse: ({ response }) => { // customize response },});
client.setConfig({ ofetch: customOFetchInstance,});You can use any of the approaches mentioned in Configuration, depending on how granular you want your custom instance to be.
You can view the complete list of options in the UserConfig interface.
Examples
You can view live examples on StackBlitz or on GitHub.