Skip to content

Commit daba10f

Browse files
authored
Feat(Query) Angular tanstack-query generator (orval-labs#2288)
1 parent 4b17788 commit daba10f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2954
-48
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,4 @@ typings/
103103
package-lock.json
104104
tests/generated
105105
.turbo
106-
.next
106+
.next

.prettierignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ yarn.lock
1414

1515
# Angular build cache
1616
**/.angular/cache
17+
*.svg
18+
*.ico
19+
*.lock
20+
.gitignore
21+
.gitattributes
22+
*.xml
1723

1824
# Data files that aren't really our code
1925
packages/hono/src/zValidator.ts

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
- [Vue Query](https://tanstack.com/query/latest/docs/framework/vue/overview)
2929
- [Svelte Query](https://tanstack.com/query/latest/docs/framework/svelte/overview)
3030
- [Angular](https://angular.dev/)
31+
- [Angular Query](https://tanstack.com/query/latest/docs/framework/angular/overview)
3132
- [Hono](https://hono.dev/)
3233
- [zod](https://zod.dev/)
3334
- [native fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
@@ -43,6 +44,7 @@ You can find some samples below:
4344
- [vue query](https://github.com/orval-labs/orval/tree/master/samples/vue-query)
4445
- [react app with swr](https://github.com/orval-labs/orval/tree/master/samples/react-app-with-swr)
4546
- [angular app](https://github.com/orval-labs/orval/tree/master/samples/angular-app)
47+
- [angular query](https://github.com/orval-labs/orval/tree/master/samples/angular-query)
4648
- [hono](https://github.com/orval-labs/orval/tree/master/samples/hono)
4749
- [next app with fetch](https://github.com/orval-labs/orval/tree/master/samples/next-app-with-fetch)
4850
- [mcp server](https://github.com/orval-labs/orval/tree/master/samples/mcp)

docs/src/manifests/manifest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@
8080
"path": "/guides/angular",
8181
"editUrl": "/guides/angular.md"
8282
},
83+
{
84+
"title": "Angular Query",
85+
"path": "/guides/angular-query",
86+
"editUrl": "/guides/angular-query.md"
87+
},
8388
{
8489
"title": "SWR",
8590
"path": "/guides/swr",
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
---
2+
id: angular-query
3+
title: Angular Query
4+
---
5+
6+
Start by providing an OpenAPI specification and an Orval config file. To use Angular Query, define the `client` in the Orval config to be `angular-query`.
7+
8+
## Example with Angular Query
9+
10+
```js
11+
import { defineConfig } from 'orval';
12+
13+
export default defineConfig({
14+
petstore: {
15+
output: {
16+
mode: 'tags-split',
17+
target: 'src/petstore.ts',
18+
schemas: 'src/model',
19+
client: 'angular-query',
20+
mock: true,
21+
},
22+
input: {
23+
target: './petstore.yaml',
24+
},
25+
},
26+
});
27+
```
28+
29+
Navigate to the [Orval config reference](../reference/configuration/full-example) to see all available options.
30+
31+
The Angular Query mode will generate an implementation file with one injectable query function per path in the OpenAPI Specification. By default, Orval uses Angular's native `HttpClient` via `inject(HttpClient)` for HTTP requests.
32+
33+
For example, <a href="https://github.com/orval-labs/orval/blob/master/samples/angular-query/petstore.yaml" target="_blank">this Swagger specification</a> will generate the following:
34+
35+
```ts
36+
export const showPetById = (
37+
http: HttpClient,
38+
petId: string,
39+
options?: { signal?: AbortSignal },
40+
): Promise<Pet> => {
41+
const request$ = http.get<Pet>(`/pets/${petId}`);
42+
if (options?.signal) {
43+
return lastValueFrom(
44+
request$.pipe(takeUntil(fromEvent(options.signal, 'abort'))),
45+
);
46+
}
47+
return lastValueFrom(request$);
48+
};
49+
50+
export const getShowPetByIdQueryKey = (petId: string) => [`/pets/${petId}`];
51+
52+
export const getShowPetByIdQueryOptions = <
53+
TData = Awaited<ReturnType<typeof showPetById>>,
54+
TError = unknown,
55+
>(
56+
petId: string,
57+
options?: {
58+
query?: Partial<
59+
CreateQueryOptions<Awaited<ReturnType<typeof showPetById>>, TError, TData>
60+
>;
61+
fetch?: { signal?: AbortSignal };
62+
},
63+
) => {
64+
const { query: queryOptions, fetch: fetchOptions } = options ?? {};
65+
const http = inject(HttpClient);
66+
67+
const queryKey = queryOptions?.queryKey ?? getShowPetByIdQueryKey(petId);
68+
69+
const queryFn: QueryFunction<Awaited<ReturnType<typeof showPetById>>> = ({
70+
signal,
71+
}) => showPetById(http, petId, { signal, ...fetchOptions });
72+
73+
return {
74+
queryKey,
75+
queryFn,
76+
enabled: !!petId,
77+
...queryOptions,
78+
} as CreateQueryOptions<
79+
Awaited<ReturnType<typeof showPetById>>,
80+
TError,
81+
TData
82+
>;
83+
};
84+
85+
export const injectShowPetById = <
86+
TData = Awaited<ReturnType<typeof showPetById>>,
87+
TError = unknown,
88+
>(
89+
petId: string,
90+
options?: {
91+
query?: Partial<
92+
CreateQueryOptions<Awaited<ReturnType<typeof showPetById>>, TError, TData>
93+
>;
94+
fetch?: { signal?: AbortSignal };
95+
},
96+
) => {
97+
const queryOptions = getShowPetByIdQueryOptions(petId, options);
98+
99+
const query = injectQuery(() => queryOptions) as CreateQueryResult<
100+
TData,
101+
TError
102+
>;
103+
104+
return query;
105+
};
106+
```
107+
108+
## How to Use Other Queries
109+
110+
Given the following configuration, Orval will generate query and infinite query functions with a `nextId` query parameter. It is also possible to override the config for every query with the `options` field.
111+
112+
```js
113+
import { defineConfig } from 'orval';
114+
115+
export default defineConfig({
116+
petstore: {
117+
output: {
118+
...
119+
override: {
120+
query: {
121+
useQuery: true,
122+
useInfinite: true,
123+
useInfiniteQueryParam: 'nextId',
124+
options: {
125+
staleTime: 10000,
126+
},
127+
},
128+
},
129+
},
130+
...
131+
},
132+
});
133+
```
134+
135+
If needed, it is also possible to override the `query` options for a single operation or tag:
136+
137+
```js
138+
import { defineConfig } from 'orval';
139+
140+
export default defineConfig({
141+
petstore: {
142+
output: {
143+
...
144+
override: {
145+
operations: {
146+
listPets: {
147+
query: {
148+
...
149+
},
150+
}
151+
},
152+
},
153+
}
154+
...
155+
},
156+
});
157+
```
158+
159+
Go <a href="https://github.com/orval-labs/orval/tree/master/samples/angular-query" target="_blank">here</a> for a full example

packages/core/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ export type InputOptions = {
258258

259259
export const OutputClient = {
260260
ANGULAR: 'angular',
261+
ANGULAR_QUERY: 'angular-query',
261262
AXIOS: 'axios',
262263
AXIOS_FUNCTIONS: 'axios-functions',
263264
REACT_QUERY: 'react-query',
@@ -275,6 +276,7 @@ export type OutputClient = (typeof OutputClient)[keyof typeof OutputClient];
275276
export const OutputHttpClient = {
276277
AXIOS: 'axios',
277278
FETCH: 'fetch',
279+
ANGULAR: 'angular',
278280
} as const;
279281

280282
export type OutputHttpClient =

packages/orval/src/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const getGeneratorClient = (
3939
axios: axios({ type: 'axios' })(),
4040
'axios-functions': axios({ type: 'axios-functions' })(),
4141
angular: angular()(),
42+
'angular-query': query({ output, type: 'angular-query' })(),
4243
'react-query': query({ output, type: 'react-query' })(),
4344
'svelte-query': query({ output, type: 'svelte-query' })(),
4445
'vue-query': query({ output, type: 'vue-query' })(),

packages/orval/src/utils/options.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,12 @@ export async function normalizeOptions(
197197
workspace: outputOptions.workspace ? outputWorkspace : undefined,
198198
client: outputOptions.client ?? client ?? OutputClient.AXIOS_FUNCTIONS,
199199
httpClient:
200-
outputOptions.httpClient ?? httpClient ?? OutputHttpClient.FETCH,
200+
outputOptions.httpClient ??
201+
httpClient ??
202+
// Auto-detect: use Angular HttpClient for angular-query by default
203+
((outputOptions.client ?? client) === OutputClient.ANGULAR_QUERY
204+
? OutputHttpClient.ANGULAR
205+
: OutputHttpClient.FETCH),
201206
mode: normalizeOutputMode(outputOptions.mode ?? mode),
202207
mock,
203208
clean: outputOptions.clean ?? clean ?? false,

0 commit comments

Comments
 (0)