Skip to content

Commit aad6d32

Browse files
committed
Merge branch 'master' into v1.7.0-integration
2 parents 29d6f6d + cecda16 commit aad6d32

Some content is hidden

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

62 files changed

+10699
-996
lines changed

.codesandbox/ci.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
"packages": [
1212
"packages/toolkit",
1313
"packages/rtk-query-graphql-request-base-query",
14-
"packages/action-listener-middleware"
14+
"packages/action-listener-middleware",
15+
"packages/rtk-query-codegen-openapi"
1516
],
1617
"publishDirectory": {
1718
"@reduxjs/toolkit": "packages/toolkit",
1819
"@rtk-query/graphql-request-base-query": "packages/rtk-query-graphql-request-base-query",
19-
"@rtk-incubator/action-listener-middleware": "packages/action-listener-middleware"
20+
"@rtk-incubator/action-listener-middleware": "packages/action-listener-middleware",
21+
"@rtk-query/codegen-openapi": "packages/rtk-query-codegen-openapi"
2022
}
2123
}

.github/workflows/test-codegen.yml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3+
4+
name: RTK-Query OpenAPI Codegen Tests
5+
defaults:
6+
run:
7+
working-directory: ./packages/rtk-query-codegen-openapi
8+
9+
on: [push, pull_request]
10+
11+
jobs:
12+
changes:
13+
name: Check for changes
14+
runs-on: ubuntu-latest
15+
outputs:
16+
codegen: ${{ steps.filter.outputs.codegen }}
17+
steps:
18+
- uses: actions/checkout@v2
19+
- uses: dorny/paths-filter@v2
20+
id: filter
21+
with:
22+
filters: |
23+
codegen:
24+
- 'packages/rtk-query-codegen-openapi/**'
25+
26+
build:
27+
needs: changes
28+
if: ${{ needs.changes.outputs.codegen == 'true' }}
29+
30+
runs-on: ubuntu-latest
31+
32+
strategy:
33+
matrix:
34+
node-version: [12.x]
35+
36+
steps:
37+
- uses: actions/checkout@v2
38+
- name: Use Node.js ${{ matrix.node-version }}
39+
uses: actions/setup-node@v2
40+
with:
41+
node-version: ${{ matrix.node }}
42+
cache: 'yarn'
43+
44+
- run: yarn install
45+
- run: yarn test

.github/workflows/tests.yml

+17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,24 @@ defaults:
55
working-directory: ./packages/toolkit
66

77
jobs:
8+
changes:
9+
name: Check for changes
10+
runs-on: ubuntu-latest
11+
outputs:
12+
toolkit: ${{ steps.filter.outputs.toolkit }}
13+
steps:
14+
- uses: actions/checkout@v2
15+
- uses: dorny/paths-filter@v2
16+
id: filter
17+
with:
18+
filters: |
19+
toolkit:
20+
- 'packages/toolkit/**'
21+
822
build:
23+
needs: changes
24+
if: ${{ needs.changes.outputs.toolkit == 'true' }}
25+
926
name: Lint, Test, Build & Pack on Node ${{ matrix.node }}
1027

1128
runs-on: ubuntu-latest

docs/rtk-query/comparison.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ RTK Query has some unique API design aspects and capabilities that are worth con
3333
- You can easily invalidate entities or patch existing query data (via `util.updateQueryData`) from middleware.
3434
- RTK Query enables [streaming cache updates](./usage/streaming-updates.mdx), such as updating the initial fetched data as messages are received over a websocket, and has built in support for [optimistic updates](./usage/manual-cache-updates.mdx#optimistic-updates) as well.
3535
- RTK Query ships a very tiny and flexible fetch wrapper: [`fetchBaseQuery`](./api/fetchBaseQuery.mdx). It's also very easy to [swap our client with your own](./usage/customizing-queries.mdx), such as using `axios`, `redaxios`, or something custom.
36-
- RTK Query has [a (currently experimental) code-gen tool](https://github.com/rtk-incubator/rtk-query-codegen) that will take an OpenAPI spec or GraphQL schema and give you a typed API client, as well as provide methods for enhancing the generated client after the fact.
36+
- RTK Query has [a (currently experimental) code-gen tool](https://github.com/reduxjs/redux-toolkit/tree/master/packages/rtk-query-codegen-openapi) that will take an OpenAPI spec or GraphQL schema and give you a typed API client, as well as provide methods for enhancing the generated client after the fact.
3737

3838
## Tradeoffs
3939

docs/rtk-query/usage/code-generation.mdx

+123-51
Original file line numberDiff line numberDiff line change
@@ -14,70 +14,142 @@ RTK Query's API and architecture is oriented around declaring API endpoints up f
1414

1515
We have early previews of code generation capabilities available as separate tools.
1616

17+
## GraphQL
18+
19+
We provide a [Plugin for GraphQL Codegen](https://www.graphql-code-generator.com/docs/plugins/typescript-rtk-query). You can find the documentation to that on the graphql-codegen homepage.
20+
21+
For a full example on how to use it, you can see [this example project](https://github.com/reduxjs/redux-toolkit/tree/master/examples/query/react/graphql-codegen).
22+
1723
## OpenAPI
1824

19-
We have a first version of a code generator from OpenAPI schemas over at [`rtk-incubator/rtk-query-codegen`](https://github.com/rtk-incubator/rtk-query-codegen).
25+
We provide a package for RTK Query code generation from OpenAPI schemas. It is published as `@rtk-query/codegen-openapi` and you can find the source code at [`packages/rtk-query-codegen-openapi`](https://github.com/reduxjs/redux-toolkit/tree/master/packages/rtk-query-codegen-openapi).
26+
27+
### Usage
28+
29+
Create an empty api using `createApi` like
30+
31+
```ts no-transpile title="src/store/emptyApi.ts"
32+
33+
// Or from '@reduxjs/toolkit/query' if not using the auto-generated hooks
34+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
35+
36+
// initialize an empty api service that we'll inject endpoints into later as needed
37+
export const emptySplitApi = createApi({
38+
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
39+
endpoints: () => ({}),
40+
})
41+
```
42+
43+
Generate a config file (json, js or ts) with contents like
44+
45+
```ts no-transpile title="openapi-config.ts"
46+
47+
import { ConfigFile } from '@rtk-query/codegen-openapi'
48+
49+
const config: ConfigFile = {
50+
schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json',
51+
apiFile: './src/store/emptyApi.ts',
52+
apiImport: 'emptySplitApi',
53+
outputFile: './src/store/petApi.ts',
54+
exportName: 'petApi',
55+
hooks: true,
56+
}
2057

21-
You can create an api by running:
58+
export default config
59+
```
60+
61+
and then call the code generator:
2262

2363
```bash
24-
curl -o petstore.json https://petstore3.swagger.io/api/v3/openapi.json
25-
npx @rtk-incubator/rtk-query-codegen-openapi --hooks petstore.json > petstore-api.generated.ts
64+
npx @rtk-query/codegen-openapi openapi-config.ts
2665
```
2766

28-
We recommend placing these generated types in one file that you do not modify (so you can constantly re-generate it when your API definition changes) and creating a second file to enhance it with additional info:
67+
### Programmatic usage
2968

30-
```ts title="petstore-api.ts"
31-
// file: petstore-api.generated.ts noEmit
32-
export * from 'petstore-api.generated'
69+
```ts no-transpile title="src/store/petApi.ts"
3370

34-
// file: petstoreApi.ts
35-
import { api as generatedApi } from './petstore-api.generated'
71+
import { generateEndpoints } from '@rtk-query/codegen-openapi'
3672

37-
export const api = generatedApi.enhanceEndpoints({
38-
addTagTypes: ['Pet'],
39-
endpoints: {
40-
// basic notation: just specify properties to be overridden
41-
getPetById: {
42-
providesTags: (result, error, arg) => [{ type: 'Pet', id: arg.petId }],
43-
},
44-
findPetsByStatus: {
45-
providesTags: (result) =>
46-
// is result available?
47-
result
48-
? // successful query
49-
[
50-
{ type: 'Pet', id: 'LIST' },
51-
...result.map((pet) => ({ type: 'Pet' as const, id: pet.id })),
52-
]
53-
: // an error occurred, but we still want to refetch this query when `{ type: 'Pet', id: 'LIST' }` is invalidated
54-
[{ type: 'Pet', id: 'LIST' }],
73+
const api = await generateEndpoints({
74+
apiFile: './fixtures/emptyApi.ts',
75+
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
76+
filterEndpoints: ['getPetById', 'addPet'],
77+
hooks: true,
78+
})
79+
```
80+
81+
### Config file options
82+
83+
#### Simple usage
84+
85+
```ts no-transpile
86+
interface SimpleUsage {
87+
apiFile: string
88+
schemaFile: string
89+
apiImport?: string
90+
exportName?: string
91+
argSuffix?: string
92+
responseSuffix?: string
93+
hooks?: boolean
94+
outputFile: string
95+
filterEndpoints?:
96+
| string
97+
| RegExp
98+
| EndpointMatcherFunction
99+
| Array<string | RegExp | EndpointMatcherFunction>
100+
endpointOverrides?: EndpointOverrides[]
101+
}
102+
103+
export type EndpointMatcherFunction = (
104+
operationName: string,
105+
operationDefinition: OperationDefinition
106+
) => boolean
107+
```
108+
109+
#### Filtering endpoints
110+
111+
If you only want to include a few endpoints, you can use the `filterEndpoints` config option to filter your endpoints.
112+
113+
```ts no-transpile title="openapi-config.ts"
114+
const filteredConfig: ConfigFile = {
115+
// ...
116+
// should only have endpoints loginUser, placeOrder, getOrderById, deleteOrder
117+
filterEndpoints: ['loginUser', /Order/],
118+
}
119+
```
120+
121+
#### Endpoint overrides
122+
123+
If an endpoint is generated as a mutation instead of a query or the other way round, you can override that:
124+
125+
```ts no-transpile title="openapi-config.ts"
126+
const withOverride: ConfigFile = {
127+
// ...
128+
endpointOverrides: [
129+
{
130+
pattern: 'loginUser',
131+
type: 'mutation',
55132
},
56-
// alternate notation: callback that gets passed in `endpoint` - you can freely modify the object here
57-
addPet: (endpoint) => {
58-
endpoint.invalidatesTags = (result) =>
59-
result ? [{ type: 'Pet', id: result.id }] : []
133+
],
134+
}
135+
```
136+
137+
#### Multiple output files
138+
139+
```ts no-transpile title="openapi-config.ts"
140+
const config: ConfigFile = {
141+
schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json',
142+
apiFile: './src/store/emptyApi.ts',
143+
outputFiles: {
144+
'./src/store/user.ts': {
145+
filterEndpoints: [/user/i],
60146
},
61-
updatePet: {
62-
invalidatesTags: (result, error, arg) => [
63-
{ type: 'Pet', id: arg.pet.id },
64-
],
147+
'./src/store/order.ts': {
148+
filterEndpoints: [/order/i],
65149
},
66-
deletePet: {
67-
invalidatesTags: (result, error, arg) => [{ type: 'Pet', id: arg.petId }],
150+
'./src/store/pet.ts': {
151+
filterEndpoints: [/pet/i],
68152
},
69153
},
70-
})
71-
72-
export const {
73-
useGetPetByIdQuery,
74-
useFindPetsByStatusQuery,
75-
useAddPetMutation,
76-
useUpdatePetMutation,
77-
useDeletePetMutation,
78-
} = api
154+
}
79155
```
80-
81-
## GraphQL
82-
83-
There is a _very_ early WIP PR that [implements code generation based on a GraphQL spec](https://github.com/phryneas/graphql-code-generator/pull/1), and an open issue on the GraphQL Generator repo asking [if an RTK Query generator would be potentially useful](https://github.com/dotansimha/graphql-code-generator/issues/6085).

docs/rtk-query/usage/customizing-queries.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ export const api = createApi({
450450
getPosts: build.query<PostsResponse, void>({
451451
query: () => ({ url: 'posts' }),
452452
}),
453-
getPost: build.query<PostsResponse, string>({
453+
getPost: build.query<Post, string>({
454454
query: (id) => ({ url: `post/${id}` }),
455455
extraOptions: { maxRetries: 8 }, // You can override the retry behavior on each endpoint
456456
}),

0 commit comments

Comments
 (0)