Skip to content

Commit

Permalink
Merge pull request #613 from hey-api/fix/client-beta-2
Browse files Browse the repository at this point in the history
Axios client
  • Loading branch information
mrlubos authored Jul 21, 2024
2 parents e7bd6ae + b0e8a98 commit b642d4c
Show file tree
Hide file tree
Showing 65 changed files with 7,147 additions and 1,207 deletions.
5 changes: 5 additions & 0 deletions .changeset/beige-taxis-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/client-fetch': patch
---

fix: use opts to get responseTransformer instead of options
5 changes: 5 additions & 0 deletions .changeset/gorgeous-timers-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/client-axios': minor
---

feat: initial release
2 changes: 1 addition & 1 deletion .changeset/silver-apples-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'@hey-api/openapi-ts': minor
---

feat: allow inlining standalone clients with `client.inline = true`
feat: allow bundling standalone clients with `client.bundle = true`
5 changes: 5 additions & 0 deletions .changeset/smart-pillows-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/docs': patch
---

docs: add Axios client documentation
7 changes: 7 additions & 0 deletions docs/embed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export const embedProject = (projectId: string) => async (event: Event) => {
}

switch (projectId) {
case 'hey-api-client-axios-example':
return await sdk.embedProjectId(container, projectId, {
height: 700,
openFile:
'openapi-ts.config.ts,src/client/schemas.gen.ts,src/client/services.gen.ts,src/client/types.gen.ts,src/App.tsx',
view: 'editor',
});
case 'hey-api-client-fetch-example':
return await sdk.embedProjectId(container, projectId, {
height: 700,
Expand Down
193 changes: 190 additions & 3 deletions docs/openapi-ts/clients.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import { embedProject } from '../embed'

We all send HTTP requests in a slightly different way. Hey API doesn't force you to use any specific technology. What we do, however, is support your choice with great clients. All seamlessly integrated with our other features.

[Next.js](https://nextjs.org/) and [Axios](https://axios-http.com/) coming soon.
[Next.js](https://nextjs.org/) coming soon.

## Features

- seamless integration with `@hey-api/openapi-ts`
- typesafe response data and errors
- access to the original request and response
- each request call is configurable
- granular request and response customization options
- minimal learning curve thanks to extending the underlying technology
- support bundling inside the generated output

## Fetch API

Expand Down Expand Up @@ -63,7 +64,7 @@ You can now run `openapi-ts` to use the new Fetch API client. 🎉

### Configuration

You will most likely want to configure the global client instance used by services. You can do that with the `createClient()` method. Call it at the beginning of your application.
If you're using services, you will want to configure the internal client instance. You can do that with the `createClient()` method. Call it at the beginning of your application.

```js
import { createClient } from '@hey-api/client-fetch';
Expand All @@ -86,6 +87,55 @@ client.interceptors.request.use((request, options) => {
});
```

### Customization

Our Fetch client is built as a thin wrapper on top of Fetch API, extending its functionality to work with Hey API. If you're already familiar with Fetch, customizing your client will feel like working directly with Fetch API. You can customize requests in three ways – globally, per client, or per request.

#### Global

This is the most common requirement. Our generated services consume an internal Fetch instance, so you will want to configure that.

```js
import { createClient } from '@hey-api/client-fetch';

createClient({
baseUrl: 'https://example.com',
});
```

You can pass any Fetch API configuration option to `createClient()`, and even your own Fetch implementation.

#### Client

If you need to create a client instance pointing to a different domain, you can create a non-global client. This client will not be used by default by the generated services.

```js
import { createClient } from '@hey-api/client-fetch';

const myClient = createClient({
baseUrl: 'https://example.com',
global: false, // <-- create a non-global client
});
```

You can then pass this client to any generated service through the `client` option. This will override the default global instance.

```js
const response = await getFoo({
client: myClient,
});
```

#### Request

Alternatively, you can pass the Fetch API configuration options to each service call directly. This is useful if you don't want to create a separate client for one-off use cases.

```js
const response = await getFoo({
baseUrl: 'https://example.com', // <-- override global configuration
});
```

### Example

You can view a more complete example on this page.
Expand All @@ -94,6 +144,143 @@ You can view a more complete example on this page.
Live demo
</button>

## Axios

::: warning
Axios client is currently in beta. The interface might change before it becomes stable. We encourage you to leave feedback on [GitHub](https://github.com/hey-api/openapi-ts/issues).
:::

Start by adding `@hey-api/client-axios` to your dependencies.

::: code-group

```sh [npm]
npm install @hey-api/client-axios
```

```sh [pnpm]
pnpm add @hey-api/client-axios
```

```sh [yarn]
yarn add @hey-api/client-axios
```

```sh [bun]
bun add @hey-api/client-axios
```

:::

Ensure you have already [configured](/openapi-ts/get-started) `@hey-api/openapi-ts`. Update your configuration to use the Axios client package.

```js{2}
export default {
client: '@hey-api/client-axios',
input: 'path/to/openapi.json',
output: 'src/client',
}
```

You can now run `openapi-ts` to use the new Axios client. 🎉

### Configuration

If you're using services, you will want to configure the internal client instance. You can do that with the `createClient()` method. Call it at the beginning of your application.

```js
import { createClient } from '@hey-api/client-axios';

createClient({
baseURL: 'https://example.com',
});
```

### Interceptors

Another common requirement is request authorization. Interceptors are ideal for adding headers to your requests.

```js
import { client } from '@hey-api/client-axios';

client.instance.interceptors.request.use((config) => {
config.headers.set('Authorization', 'Bearer <my_token>');
return config;
});
```

### Customization

Our Axios client is built as a thin wrapper on top of Axios, extending its functionality to work with Hey API. If you're already familiar with Axios, customizing your client will feel like working directly with Axios. You can customize requests in three ways – globally, per client, or per request.

#### Global

This is the most common requirement. Our generated services consume an internal Axios instance, so you will want to configure that.

```js
import { createClient } from '@hey-api/client-axios';

createClient({
baseURL: 'https://example.com',
});
```

You can pass any Axios configuration option to `createClient()`, and even your own Axios implementation.

#### Client

If you need to create a client instance pointing to a different domain, you can create a non-global client. This client will not be used by default by the generated services.

```js
import { createClient } from '@hey-api/client-axios';

const myClient = createClient({
baseURL: 'https://example.com',
global: false, // <-- create a non-global client
});
```

You can then pass this client to any generated service through the `client` option. This will override the default global instance.

```js
const response = await getFoo({
client: myClient,
});
```

#### Request

Alternatively, you can pass the Axios configuration options to each service call directly. This is useful if you don't want to create a separate client for one-off use cases.

```js
const response = await getFoo({
baseURL: 'https://example.com', // <-- override global configuration
});
```

### Example

You can view a more complete example on this page.

<button class="buttonLink" @click="(event) => embedProject('hey-api-client-axios-example')(event)">
Live demo
</button>

## Bundling

Sometimes, you may not want to declare standalone clients as a dependency. This scenario is common if you're using Hey API to generate output that is repackaged and published for other consumers under your own brand. For such cases, our clients support bundling through the `client.bundle` configuration option.

```js
export default {
client: {
bundle: true, // [!code ++]
name: '@hey-api/client-fetch',
},
input: 'path/to/openapi.json',
output: 'src/client',
};
```

## Legacy Clients

Before standalone client packages, clients were generated using `@hey-api/openapi-ts`. In fact, `@hey-api/openapi-ts` still generates a legacy Fetch API client by default. You can generate other legacy clients with the `client` config option.
Expand Down
19 changes: 17 additions & 2 deletions docs/openapi-ts/interceptors.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ description: Understanding interceptors.

# Interceptors

Interceptors (middleware) can be used to modify requests before they're sent or responses before they're returned to the rest of your application. If you're not using the new Fetch API client, jump to the [legacy clients](#legacy-clients) section.
Interceptors (middleware) can be used to modify requests before they're sent or responses before they're returned to the rest of your application. If you're not using the standalone client packages, jump to the [legacy clients](#legacy-clients) section.

Below is an example request interceptor
## Fetch API

Fetch API does not have the interceptor functionality, so we implement our own. Below is an example request interceptor

::: code-group

Expand Down Expand Up @@ -59,6 +61,19 @@ client.interceptors.response.eject((response, request, options) => {
To eject, you must provide a reference to the function that was passed to `use()`.
:::

## Axios

If you're using the new Axios client, refer to the Axios documentation on [interceptors](https://axios-http.com/docs/interceptors). We expose the Axios instance through the `instance` field.

```js
import { client } from '@hey-api/client-axios';

client.instance.interceptors.request.use((config) => {
trackAnalytics(config);
return config;
});
```

## Legacy Clients

The following section applies to legacy clients generated by `@hey-api/openapi-ts`. Below is an example request interceptor
Expand Down
2 changes: 1 addition & 1 deletion examples/openapi-ts-axios/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hey API + Axios Demo</title>
</head>
Expand Down
15 changes: 12 additions & 3 deletions examples/openapi-ts-axios/openapi-ts.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
format: 'prettier',
base: 'https://petstore3.swagger.io/api/v3',
client: '@hey-api/client-axios',
input:
'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml',
lint: 'eslint',
output: './src/client',
// 'https://raw.githubusercontent.com/Redocly/museum-openapi-example/main/openapi.yaml',
// '../../packages/openapi-ts/test/spec/v3.json',
output: {
format: 'prettier',
lint: 'eslint',
path: './src/client',
},
types: {
enums: 'javascript',
},
});
6 changes: 6 additions & 0 deletions examples/openapi-ts-axios/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
},
"dependencies": {
"@hey-api/client-axios": "workspace:*",
"@radix-ui/react-form": "0.1.0",
"@radix-ui/react-icons": "1.3.0",
"@radix-ui/themes": "3.1.1",
"axios": "1.7.2",
"react": "18.3.1",
"react-dom": "18.3.1"
Expand All @@ -24,10 +27,13 @@
"@typescript-eslint/eslint-plugin": "7.15.0",
"@typescript-eslint/parser": "7.15.0",
"@vitejs/plugin-react": "4.3.1",
"autoprefixer": "10.4.19",
"eslint": "9.6.0",
"eslint-plugin-react-hooks": "4.6.2",
"eslint-plugin-react-refresh": "0.4.7",
"postcss": "8.4.39",
"prettier": "3.3.2",
"tailwindcss": "3.4.4",
"typescript": "5.5.3",
"vite": "5.3.3"
}
Expand Down
6 changes: 6 additions & 0 deletions examples/openapi-ts-axios/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
autoprefixer: {},
tailwindcss: {},
},
};
Loading

0 comments on commit b642d4c

Please sign in to comment.