Skip to content

Commit a7033cc

Browse files
authored
Merge pull request #656 from vintasoftware/feat/openapi-ts
Set up client API code generation
2 parents a229adf + 37d8ba0 commit a7033cc

File tree

22 files changed

+149
-173
lines changed

22 files changed

+149
-173
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
frontend/bundles/
22
frontend/webpack_bundles/
3+
frontend/js/api/

.eslintrc.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ module.exports = {
55
parser: "@typescript-eslint/parser",
66
extends: ["vinta/recommended-typescript"],
77
rules: {
8-
"default-param-last": "off", // due to initialState in Redux
98
"import/extensions": [
109
"error",
1110
"ignorePackages",
@@ -46,4 +45,15 @@ module.exports = {
4645
version: "detect",
4746
},
4847
},
48+
overrides: [
49+
{
50+
files: ["openapi-ts.config.ts"],
51+
rules: {
52+
"import/no-extraneous-dependencies": [
53+
"error",
54+
{ devDependencies: true },
55+
],
56+
},
57+
},
58+
],
4959
};

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
steps:
1818
- name: Checkout code
19-
uses: actions/checkout@v2
19+
uses: actions/checkout@v4
2020
with:
2121
ref: main
2222
- run: mkdir -p github/workflows

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ jobs:
1111
runs-on: ubuntu-latest
1212
steps:
1313
- name: Checkout code
14-
uses: actions/checkout@v2
14+
uses: actions/checkout@v4
1515
- uses: ./.github/workflows/shared-build

.github/workflows/nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
runs-on: ubuntu-latest
1010
steps:
1111
- name: Checkout code
12-
uses: actions/checkout@v2
12+
uses: actions/checkout@v4
1313
with:
1414
ref: main
1515
- uses: ./.github/workflows/shared-build

.github/workflows/shared-build/action.yml

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ runs:
1111
echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
1212
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
1313
- name: Setup Python
14-
uses: actions/setup-python@v2
14+
uses: actions/setup-python@v5
1515
with:
1616
python-version: "3.12"
1717
- name: Setup Node
18-
uses: actions/setup-node@v2
18+
uses: actions/setup-node@v4
1919
with:
20-
node-version: "18.2"
20+
node-version: "18.20"
2121
- name: Cache node modules
22-
uses: actions/cache@v2
22+
uses: actions/cache@v3
2323
env:
2424
cache-name: node-modules-cache
2525
with:
@@ -30,7 +30,7 @@ runs:
3030
build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}
3131
build-${{ env.cache-name }}
3232
- name: Cache pip
33-
uses: actions/cache@v2
33+
uses: actions/cache@v3
3434
env:
3535
cache-name: pip-cache
3636
with:
@@ -59,15 +59,6 @@ runs:
5959
- run: npm dedupe
6060
working-directory: testproject
6161
shell: bash
62-
- run: npm run test
63-
working-directory: testproject
64-
shell: bash
65-
- run: npm run lint
66-
working-directory: testproject
67-
shell: bash
68-
- run: npm run build
69-
working-directory: testproject
70-
shell: bash
7162
- run: pip install poetry==1.7.1 --upgrade
7263
working-directory: testproject
7364
shell: bash
@@ -90,6 +81,25 @@ runs:
9081
env:
9182
DATABASE_URL: "sqlite:///"
9283
shell: bash
84+
- name: Generate backend schema
85+
run: poetry run python manage.py spectacular --color --file schema.yml
86+
working-directory: testproject/backend
87+
env:
88+
DATABASE_URL: "sqlite:///"
89+
shell: bash
90+
- name: Generate frontend API client
91+
run: npm run openapi-ts
92+
working-directory: testproject
93+
shell: bash
94+
- run: npm run lint
95+
working-directory: testproject
96+
shell: bash
97+
- run: npm run build
98+
working-directory: testproject
99+
shell: bash
100+
- run: npm run test
101+
working-directory: testproject
102+
shell: bash
93103
- run: poetry run python manage.py test
94104
working-directory: testproject/backend
95105
env:

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,9 @@ repos:
6464
language: system
6565
files: ^backend/
6666
pass_filenames: false
67+
- id: frontend-api
68+
name: frontend-api-local
69+
entry: npm run openapi-ts
70+
language: system
71+
files: backend/schema\.yml$
72+
pass_filenames: false

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ docker_setup:
2020
docker compose build --no-cache backend
2121
docker compose run --rm backend python manage.py spectacular --color --file schema.yml
2222
docker compose run frontend npm install
23+
docker compose run --rm frontend npm run openapi-ts
2324

2425
docker_test:
2526
docker compose run backend python manage.py test $(ARG) --parallel --keepdb
@@ -51,3 +52,6 @@ docker_backend_shell:
5152

5253
docker_backend_update_schema:
5354
docker compose run --rm backend python manage.py spectacular --color --file schema.yml
55+
56+
docker_frontend_update_api:
57+
docker compose run --rm frontend npm run openapi-ts

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ Also, includes a Render.com `render.yaml` and a working Django `production.py` s
4040
- State management and backend integration
4141
- `axios` for performing asynchronous calls
4242
- `cookie` for easy integration with Django using the `csrftoken` cookie
43-
- `@reduxjs/toolkit` for easy state management across the application with the whole toolkit including devtools for inspecting and debugging Redux via browser and ability to run thunks for interacting with the Redux store through asynchronous logic
44-
- `connected-react-router` for integrating Redux with React Router
43+
- `openapi-ts` for generating TypeScript client API code from the backend OpenAPI schema
4544
- `history` for providing browser history to Connected React Router
46-
- `react-redux` for integrating React with Redux
4745
- Utilities
4846
- `lodash` for general utility functions
4947
- `classnames` for easy working with complex CSS class names on components
@@ -143,13 +141,6 @@ After completing ALL of the above, remove this `Project bootstrap` section from
143141
144142
### If you are not using Docker:
145143
146-
#### Setup and run the frontend app
147-
148-
- Open a new command line window and go to the project's directory
149-
- `npm install`
150-
- `npm run dev`
151-
- This is used to serve the frontend assets to be consumed by [django-webpack-loader](https://github.com/django-webpack/django-webpack-loader) and not to run the React application as usual, so don't worry if you try to check what's running on port 3000 and see an error on your browser
152-
153144
#### Setup the backend app
154145
155146
- Open the `backend/.env` file on a text editor and do one of the following:
@@ -169,9 +160,18 @@ After completing ALL of the above, remove this `Project bootstrap` section from
169160
- Run the migrations:
170161
`poetry run python manage.py migrate`
171162
- Generate the OpenAPI schema:
172-
`poetry run python manage.py spectacular --color --file schema.yml`
163+
`poetry run python manage.py spectacular --color --file schema.yml`
173164
- Run the project:
174165
`poetry run python manage.py runserver`
166+
167+
#### Setup and run the frontend app
168+
169+
- Open a new command line window and go to the project's directory
170+
- `npm install`
171+
- `npm run openapi-ts`
172+
- This is used to generate the TypeScript client API code from the backend OpenAPI schema
173+
- `npm run dev`
174+
- This is used to serve the frontend assets to be consumed by [django-webpack-loader](https://github.com/django-webpack/django-webpack-loader) and not to run the React application as usual, so don't worry if you try to check what's running on port 3000 and see an error on your browser
175175
- Open a browser and go to `http://localhost:8000` to see the project running
176176
177177
#### Setup Celery
@@ -204,19 +204,31 @@ Will run django tests using `--keepdb` and `--parallel`. You may pass a path to
204204
205205
To add a new **backend** dependency, run `poetry add {dependency}`. If the dependency should be only available for development user append `-G dev` to the command.
206206
207-
### API Schema
207+
### API Schema and Client generation
208208
209-
We use the DRF-Spectacular tool to generate an OpenAPI schema from our Django Rest Framework API. The OpenAPI schema serves as the backbone for generating client code, creating comprehensive API documentation, and more.
209+
We use the [`DRF-Spectacular`](https://drf-spectacular.readthedocs.io/en/latest/readme.html) tool to generate an OpenAPI schema from our Django Rest Framework API. The OpenAPI schema serves as the backbone for generating client code, creating comprehensive API documentation, and more.
210210
211211
The API documentation pages are accessible at `http://localhost:8000/api/schema/swagger-ui/` or `http://localhost:8000/api/schema/redoc/`.
212212
213213
> [!IMPORTANT]
214214
> Anytime a view is created, updated, or removed, the schema must be updated to reflect the changes. Failing to do so can lead to outdated client code or documentation.
215-
>
215+
>
216216
> To update the schema, run:
217217
> - If you are using Docker: `make docker_backend_update_schema`
218218
> - If you are not using Docker: `poetry run python manage.py spectacular --color --file schema.yml`
219219
220+
We use the [`openapi-ts`](https://heyapi.vercel.app/openapi-ts/get-started.html) tool to generate TypeScript client code from the OpenAPI schema. The generated client code is used to interact with the API in a type-safe manner.
221+
222+
> [!IMPORTANT]
223+
> Anytime the API schema is updated, the client code must be regenerated to reflect the changes. Failing to do so can lead to type errors in the client code.
224+
>
225+
> To update the client code, run:
226+
> - If you are using Docker: `make docker_frontend_update_api`
227+
> - If you are not using Docker: `npm run openapi-ts`
228+
229+
> [!NOTE]
230+
> If `pre-commit` is properly enabled, it will automatically update both schema and client before each commit whenever necessary.
231+
220232
## Github Actions
221233
222234
To enable Continuous Integration through Github Actions, we provide a `proj_main.yml` file. To connect it to Github you need to rename it to `main.yml` and move it to the `.github/workflows/` directory.

backend/common/serializers.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from rest_framework import serializers
2+
3+
4+
class MessageSerializer(serializers.Serializer):
5+
message = serializers.CharField()

0 commit comments

Comments
 (0)