diff --git a/docs/.vitepress/config/en.ts b/docs/.vitepress/config/en.ts index 689c33995c..48a67a4192 100644 --- a/docs/.vitepress/config/en.ts +++ b/docs/.vitepress/config/en.ts @@ -94,6 +94,10 @@ export default defineConfig({ link: '/openapi-ts/clients/fetch', text: 'Fetch API', }, + { + link: '/openapi-ts/clients/angular', + text: 'Angular', + }, { link: '/openapi-ts/clients/axios', text: 'Axios', @@ -106,10 +110,6 @@ export default defineConfig({ link: '/openapi-ts/clients/nuxt', text: 'Nuxt', }, - { - link: '/openapi-ts/clients/angular', - text: 'Angular', - }, { link: '/openapi-ts/clients/effect', text: 'Effect soon', @@ -218,6 +218,10 @@ export default defineConfig({ { collapsed: true, items: [ + { + link: '/openapi-ts/plugins/angular', + text: 'Angular', + }, { link: '/openapi-ts/plugins/fastify', text: 'Fastify', diff --git a/docs/.vitepress/config/index.ts b/docs/.vitepress/config/index.ts index 84261e5d8b..164d2221dd 100644 --- a/docs/.vitepress/config/index.ts +++ b/docs/.vitepress/config/index.ts @@ -1,3 +1,5 @@ +import path from 'node:path'; + import { defineConfig } from 'vitepress'; import en from './en'; @@ -13,6 +15,12 @@ export default defineConfig({ ...shared.vite, resolve: { ...shared.vite?.resolve, + alias: { + ...shared.vite?.resolve?.alias, + '@components': path.resolve(__dirname, '..', 'theme', 'components'), + '@data': path.resolve(__dirname, '..', '..', 'data'), + '@versions': path.resolve(__dirname, '..', 'theme', 'versions'), + }, preserveSymlinks: true, }, }, diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 8b0195dbcc..37e486cc9f 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -5,21 +5,10 @@ import DefaultTheme from 'vitepress/theme'; // custom CSS must be imported after default theme to correctly apply styles import './custom.css'; -import AuthorsList from './components/AuthorsList.vue'; -import FeatureStatus from './components/FeatureStatus.vue'; -import Heading from './components/Heading.vue'; -import VersionLabel from './components/VersionLabel.vue'; -import VersionSwitcher from './components/VersionSwitcher.vue'; import Layout from './Layout.vue'; export default { Layout, - enhanceApp: ({ app }) => { - app.component('AuthorsList', AuthorsList); - app.component('FeatureStatus', FeatureStatus); - app.component('Heading', Heading); - app.component('VersionLabel', VersionLabel); - app.component('VersionSwitcher', VersionSwitcher); - }, + enhanceApp: () => {}, extends: DefaultTheme, } satisfies Theme; diff --git a/docs/.vitepress/theme/versions/AngularVersionSwitcher.vue b/docs/.vitepress/theme/versions/AngularVersionSwitcher.vue new file mode 100644 index 0000000000..28f9d7fe8c --- /dev/null +++ b/docs/.vitepress/theme/versions/AngularVersionSwitcher.vue @@ -0,0 +1,20 @@ + + + diff --git a/docs/openapi-ts/plugins/zod/ZodHeading.vue b/docs/.vitepress/theme/versions/ZodVersionSwitcher.vue similarity index 70% rename from docs/openapi-ts/plugins/zod/ZodHeading.vue rename to docs/.vitepress/theme/versions/ZodVersionSwitcher.vue index 1efde228e5..1b6b0ede2e 100644 --- a/docs/openapi-ts/plugins/zod/ZodHeading.vue +++ b/docs/.vitepress/theme/versions/ZodVersionSwitcher.vue @@ -1,4 +1,6 @@ diff --git a/docs/data/people.ts b/docs/data/people.ts new file mode 100644 index 0000000000..215f7f86d7 --- /dev/null +++ b/docs/data/people.ts @@ -0,0 +1,14 @@ +type Person = { + github: string; + name: string; +}; + +export const jacobCohen: Person = { + github: 'https://github.com/jacobinu', + name: 'Jacob Cohen', +}; + +export const maxScopp: Person = { + github: 'https://github.com/max-scopp', + name: 'Max Scopp', +}; diff --git a/docs/openapi-ts/clients.md b/docs/openapi-ts/clients.md index 385019d943..2d6944a719 100644 --- a/docs/openapi-ts/clients.md +++ b/docs/openapi-ts/clients.md @@ -26,10 +26,10 @@ We all send HTTP requests in a slightly different way. Hey API doesn't force you Hey API natively supports the following clients. - [Fetch API](/openapi-ts/clients/fetch) +- [Angular](/openapi-ts/clients/angular) - [Axios](/openapi-ts/clients/axios) - [Next.js](/openapi-ts/clients/next-js) - [Nuxt](/openapi-ts/clients/nuxt) -- [Angular](/openapi-ts/clients/angular) Soon - [Effect](/openapi-ts/clients/effect) Soon - [Legacy](/openapi-ts/clients/legacy) diff --git a/docs/openapi-ts/clients/angular.md b/docs/openapi-ts/clients/angular.md index 8c05827728..1379a30041 100644 --- a/docs/openapi-ts/clients/angular.md +++ b/docs/openapi-ts/clients/angular.md @@ -1,58 +1,77 @@ --- -title: Angular client -description: Angular client for Hey API. Compatible with all our features. +title: Angular v20 Client +description: Generate a type-safe Angular v20 client from OpenAPI with the Angular client for openapi-ts. Fully compatible with validators, transformers, and all core features. ---

Angular

- - +
+::: warning +Angular 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). +::: + ### About -[Angular](https://angular.dev/) is a web framework for building fast, reliable applications. +[Angular](https://angular.dev/) is a web framework that empowers developers to build fast, reliable applications. -::: warning Requirements -**Angular 19+** is required for full feature support, including the experimental `httpResource` API. -::: +The Angular client for Hey API generates a type-safe client from your OpenAPI spec, fully compatible with validators, transformers, and all core features. -::: tip First Release -Angular client support is in its first release. Share your feedback on [GitHub](https://github.com/hey-api/openapi-ts/issues). -::: +### Collaborators + + ## Features -- Modern Angular patterns with signals and reactive programming -- Dependency injection with `@Injectable()` decorators -- Type-safe response data and errors -- Experimental **httpResource** support (Angular 19+) +- Angular v20 support +- seamless integration with `@hey-api/openapi-ts` ecosystem +- type-safe response data and errors +- support for [`@Injectable()`](https://angular.dev/api/core/Injectable) decorators +- 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 -## Usage +## Installation -Add `@hey-api/client-angular` to your plugins: +In your [configuration](/openapi-ts/get-started), add `@hey-api/client-angular` to your plugins and you'll be ready to generate client artifacts. :tada: -```js +::: code-group + +```js [config] export default { input: 'https://get.heyapi.dev/hey-api/backend', output: 'src/client', - plugins: [ - '@hey-api/client-angular', // [!code ++] - ], + plugins: ['@hey-api/client-angular'], // [!code ++] }; ``` -After generating the client, integrate it with Angular's `HttpClient` by adding `provideHeyApiClient` to your app configuration: +```sh [cli] +npx @hey-api/openapi-ts \ + -i https://get.heyapi.dev/hey-api/backend \ + -o src/client \ + -c @hey-api/client-angular # [!code ++] +``` + +::: + +### Providers + +You can use the Angular client in your application by adding `provideHeyApiClient` to your providers. ```ts -import { provideHttpClient, withFetch } from '@angular/common/http'; import { provideHeyApiClient, client } from './client/client.gen'; -export const appConfig = { +export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), provideHeyApiClient(client), // [!code ++] @@ -62,46 +81,63 @@ export const appConfig = { ## Configuration -### Injectable Classes Configuration +The Angular client is built as a thin wrapper on top of Angular, extending its functionality to work with Hey API. If you're already familiar with Angular, configuring your client will feel like working directly with Angular. + +When we installed the client above, it created a [`client.gen.ts`](/openapi-ts/output#client) file. You will most likely want to configure the exported `client` instance. There are two ways to do that. + +### `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 `HttpRequest` configuration option to `setConfig()`, and even your own [`httpClient`](#custom-httpclient) implementation. + +```js +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 -You can configure the SDK to generate injectable classes by setting the `asClass` option to `true` in your plugin configuration. This will generate Angular services with `@Injectable()` decorators, making them available for dependency injection. +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. ```js export default { input: 'https://get.heyapi.dev/hey-api/backend', output: 'src/client', plugins: [ - '@hey-api/client-angular', { - name: '@hey-api/sdk', - asClass: true, // [!code ++] + name: '@hey-api/client-angular', + runtimeConfigPath: './src/hey-api.ts', // [!code ++] }, ], }; ``` -::: warning -While this feature is available, it is **discouraged** as it can negatively impact tree shaking, leading to larger bundle sizes. Consider using other configuration options for better optimization. -::: - -### Angular Providers +In our custom file, we need to export a `createClientConfig()` method. This function is a simple wrapper allowing us to override configuration values. -Use `provideHeyApiClient` to integrate the generated client with Angular's `HttpClient`: +::: code-group -```ts -import { provideHttpClient, withFetch } from '@angular/common/http'; -import { provideHeyApiClient, client } from './client/client.gen'; +```ts [hey-api.ts] +import type { CreateClientConfig } from './client/client.gen'; -export const appConfig = { - providers: [provideHttpClient(withFetch()), provideHeyApiClient(client)], -}; +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()` -Manually create a client instance for custom configurations: +You can also create your own client instance. You can use it to manually send requests or point it to a different domain. -```ts +```js import { createClient } from './client/client'; const myClient = createClient({ @@ -109,37 +145,113 @@ const myClient = createClient({ }); ``` -## Plugin Configuration +You can also pass this instance to any SDK function through the `client` option. This will override the default instance from `client.gen.ts`. + +```js +const response = await getFoo({ + client: myClient, +}); +``` + +### SDKs -The `@hey-api/client-angular` plugin supports options like `throwOnError` for error handling: +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. ```js +const response = await getFoo({ + baseUrl: 'https://example.com', // <-- override default configuration +}); +``` + +## `@Injectable` + +If you prefer to use the [`@Injectable()`](https://angular.dev/api/core/Injectable) decorators, set the `asClass` option in your SDK plugin to `true`. + +::: code-group + +```ts [example] +@Injectable({ providedIn: 'root' }) +export class FooService { + // class methods +} +``` + +```js [config] export default { input: 'https://get.heyapi.dev/hey-api/backend', output: 'src/client', plugins: [ + '@hey-api/client-angular', { - name: '@hey-api/client-angular', - throwOnError: false, + name: '@hey-api/sdk', + asClass: true, // [!code ++] }, ], }; ``` -## httpResource +::: -Angular 19 introduces a experimental api – `httpResource`, a reactive approach to data loading. Enable it with: +## Interceptors -```js -export default { - plugins: [ - { - name: '@angular/common', - httpResource: { - enabled: true, - asClass: true, - }, - }, - ], +::: warning +This section is under construction. We appreciate your patience. +::: + +## Auth + +::: warning +This section is under construction. We appreciate your patience. +::: + +## 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. + +```ts +type FooData = { + path: { + fooId: number; + }; + query?: { + bar?: string; + }; + url: '/foo/{fooId}'; }; + +const url = client.buildUrl({ + path: { + fooId: 1, + }, + query: { + bar: 'baz', + }, + url: '/foo/{fooId}', +}); +console.log(url); // prints '/foo/1?bar=baz' ``` + +## Custom `httpClient` + +You can implement your own `httpClient`. This is useful if you need to extend the default `httpClient` methods with extra functionality, or replace it altogether. + +```js +import { client } from 'client/client.gen'; + +client.setConfig({ + httpClient: inject(CustomHttpClient), +}); +``` + +You can use any of the approaches mentioned in [Configuration](#configuration), depending on how granular you want your custom client to be. + +## Plugins + +You might be also interested in the [Angular](/openapi-ts/plugins/angular) plugin. + +## API + +You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/plugins/@hey-api/client-angular/types.d.ts) interface. + + + diff --git a/docs/openapi-ts/clients/angular/v19.md b/docs/openapi-ts/clients/angular/v19.md new file mode 100644 index 0000000000..07cabac479 --- /dev/null +++ b/docs/openapi-ts/clients/angular/v19.md @@ -0,0 +1,257 @@ +--- +title: Angular v19 Client +description: Generate a type-safe Angular v19 client from OpenAPI with the Angular client for openapi-ts. Fully compatible with validators, transformers, and all core features. +--- + + + + +

Angular

+ +
+ +::: warning +Angular 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). +::: + +### About + +[Angular](https://angular.dev/) is a web framework that empowers developers to build fast, reliable applications. + +The Angular client for Hey API generates a type-safe client from your OpenAPI spec, fully compatible with validators, transformers, and all core features. + +### Collaborators + + + +## Features + +- Angular v19 support +- seamless integration with `@hey-api/openapi-ts` ecosystem +- type-safe response data and errors +- support for [`@Injectable()`](https://angular.dev/api/core/Injectable) decorators +- 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 + +In your [configuration](/openapi-ts/get-started), add `@hey-api/client-angular` to your plugins and you'll be ready to generate client artifacts. :tada: + +::: code-group + +```js [config] +export default { + input: 'https://get.heyapi.dev/hey-api/backend', + output: 'src/client', + plugins: ['@hey-api/client-angular'], // [!code ++] +}; +``` + +```sh [cli] +npx @hey-api/openapi-ts \ + -i https://get.heyapi.dev/hey-api/backend \ + -o src/client \ + -c @hey-api/client-angular # [!code ++] +``` + +::: + +### Providers + +You can use the Angular client in your application by adding `provideHeyApiClient` to your providers. + +```ts +import { provideHeyApiClient, client } from './client/client.gen'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideHttpClient(withFetch()), + provideHeyApiClient(client), // [!code ++] + ], +}; +``` + +## Configuration + +The Angular client is built as a thin wrapper on top of Angular, extending its functionality to work with Hey API. If you're already familiar with Angular, configuring your client will feel like working directly with Angular. + +When we installed the client above, it created a [`client.gen.ts`](/openapi-ts/output#client) file. You will most likely want to configure the exported `client` instance. There are two ways to do that. + +### `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 `HttpRequest` configuration option to `setConfig()`, and even your own [`httpClient`](#custom-httpclient) implementation. + +```js +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 + +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. + +```js +export default { + input: 'https://get.heyapi.dev/hey-api/backend', + output: 'src/client', + plugins: [ + { + name: '@hey-api/client-angular', + runtimeConfigPath: './src/hey-api.ts', // [!code ++] + }, + ], +}; +``` + +In our custom file, we need to export a `createClientConfig()` method. This function is a simple wrapper allowing us to override configuration values. + +::: code-group + +```ts [hey-api.ts] +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()` + +You can also create your own client instance. You can use it to manually send requests or point it to a different domain. + +```js +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`. + +```js +const response = await getFoo({ + client: myClient, +}); +``` + +### SDKs + +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. + +```js +const response = await getFoo({ + baseUrl: 'https://example.com', // <-- override default configuration +}); +``` + +## `@Injectable` + +If you prefer to use the [`@Injectable()`](https://angular.dev/api/core/Injectable) decorators, set the `asClass` option in your SDK plugin to `true`. + +::: code-group + +```ts [example] +@Injectable({ providedIn: 'root' }) +export class FooService { + // class methods +} +``` + +```js [config] +export default { + input: 'https://get.heyapi.dev/hey-api/backend', + output: 'src/client', + plugins: [ + '@hey-api/client-angular', + { + name: '@hey-api/sdk', + asClass: true, // [!code ++] + }, + ], +}; +``` + +::: + +## Interceptors + +::: warning +This section is under construction. We appreciate your patience. +::: + +## Auth + +::: warning +This section is under construction. We appreciate your patience. +::: + +## 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. + +```ts +type FooData = { + path: { + fooId: number; + }; + query?: { + bar?: string; + }; + url: '/foo/{fooId}'; +}; + +const url = client.buildUrl({ + path: { + fooId: 1, + }, + query: { + bar: 'baz', + }, + url: '/foo/{fooId}', +}); +console.log(url); // prints '/foo/1?bar=baz' +``` + +## Custom `httpClient` + +You can implement your own `httpClient`. This is useful if you need to extend the default `httpClient` methods with extra functionality, or replace it altogether. + +```js +import { client } from 'client/client.gen'; + +client.setConfig({ + httpClient: inject(CustomHttpClient), +}); +``` + +You can use any of the approaches mentioned in [Configuration](#configuration), depending on how granular you want your custom client to be. + +## Plugins + +You might be also interested in the [Angular](/openapi-ts/plugins/angular/v19) plugin. + +## API + +You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/plugins/@hey-api/client-angular/types.d.ts) interface. + + + diff --git a/docs/openapi-ts/clients/axios.md b/docs/openapi-ts/clients/axios.md index b1ef2b87fe..729418ac4e 100644 --- a/docs/openapi-ts/clients/axios.md +++ b/docs/openapi-ts/clients/axios.md @@ -1,9 +1,12 @@ --- -title: Axios client -description: Axios client for Hey API. Compatible with all our features. +title: Axios v1 Client +description: Generate a type-safe Axios v1 client from OpenAPI with the Axios client for openapi-ts. Fully compatible with validators, transformers, and all core features. --- @@ -16,6 +19,8 @@ import { embedProject } from '../../embed' [Axios](https://axios-http.com) is a simple promise based HTTP client for the browser and Node.js. Axios provides a simple to use library in a small package with a very extensible interface. +The Axios client for Hey API generates a type-safe client from your OpenAPI spec, fully compatible with validators, transformers, and all core features. + ### Demo