Browse Source

👷🏻 Auto-generate frontend client (#1320)

pull/13907/head
Alejandra 11 months ago
committed by GitHub
parent
commit
bbad34aa8d
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 49
      .github/workflows/generate-client.yml
  2. 17
      frontend/README.md
  3. 1
      frontend/biome.json
  4. 2
      frontend/package.json
  5. 6
      frontend/src/client/core/request.ts
  6. 48
      frontend/src/client/services.ts
  7. 8
      scripts/generate-client.sh

49
.github/workflows/generate-client.yml

@ -0,0 +1,49 @@
name: Generate Client
on:
pull_request:
types:
- opened
- synchronize
jobs:
generate-client:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.FULL_STACK_FASTAPI_TEMPLATE_REPO_TOKEN }}
- uses: actions/setup-node@v4
with:
node-version: lts/*
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: npm ci
working-directory: frontend
- run: pip install ./backend
- run: bash scripts/generate-client.sh
- name: Commit changes
run: |
git config --local user.email "github-actions@github.com"
git config --local user.name "github-actions"
git add frontend/src/client
git diff --staged --quiet || git commit -m "✨ Autogenerate frontend client"
git push
# https://github.com/marketplace/actions/alls-green#why
generate-client-alls-green: # This job does nothing and is only used for the branch protection
if: always()
needs:
- generate-client
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}

17
frontend/README.md

@ -4,7 +4,7 @@ The frontend is built with [Vite](https://vitejs.dev/), [React](https://reactjs.
## Frontend development
Before you begin, ensure that you have either the Node Version Manager (nvm) or Fast Node Manager (fnm) installed on your system.
Before you begin, ensure that you have either the Node Version Manager (nvm) or Fast Node Manager (fnm) installed on your system.
* To install fnm follow the [official fnm guide](https://github.com/Schniz/fnm#installation). If you prefer nvm, you can install it using the [official nvm guide](https://github.com/nvm-sh/nvm#installing-and-updating).
@ -27,7 +27,7 @@ nvm install
```bash
# If using fnm
fnm use
fnm use
# If using nvm
nvm use
@ -74,6 +74,19 @@ But it would be only to clean them up, leaving them won't really have any effect
## Generate Client
### Automatically
* Activate the backend virtual environment.
* From the top level project directory, run the script:
```bash
./scripts/generate-frontend-client.sh
```
* Commit the changes.
### Manually
* Start the Docker Compose stack.
* Download the OpenAPI JSON file from `http://localhost/api/v1/openapi.json` and copy it to a new file `openapi.json` at the root of the `frontend` directory.

1
frontend/biome.json

@ -6,7 +6,6 @@
"files": {
"ignore": [
"node_modules",
"src/client/",
"src/routeTree.gen.ts",
"playwright.config.ts",
"playwright-report"

2
frontend/package.json

@ -8,7 +8,7 @@
"build": "tsc && vite build",
"lint": "biome check --apply-unsafe --no-errors-on-unmatched --files-ignore-unknown=true ./",
"preview": "vite preview",
"generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios --exportSchemas true && biome format --write ./src/client"
"generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios --exportSchemas true"
},
"dependencies": {
"@chakra-ui/icons": "2.1.1",

6
frontend/src/client/core/request.ts

@ -1,9 +1,9 @@
import axios from "axios"
import type {
AxiosError,
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
AxiosInstance,
} from "axios"
import { ApiError } from "./ApiError"
@ -151,12 +151,12 @@ export const getHeaders = async (
)
if (isStringWithValue(token)) {
headers.Authorization = `Bearer ${token}`
headers["Authorization"] = `Bearer ${token}`
}
if (isStringWithValue(username) && isStringWithValue(password)) {
const credentials = base64(`${username}:${password}`)
headers.Authorization = `Basic ${credentials}`
headers["Authorization"] = `Basic ${credentials}`
}
if (options.body !== undefined) {

48
frontend/src/client/services.ts

@ -4,20 +4,20 @@ import { request as __request } from "./core/request"
import type {
Body_login_login_access_token,
ItemCreate,
ItemPublic,
ItemUpdate,
ItemsPublic,
Message,
NewPassword,
Token,
UserPublic,
UpdatePassword,
UserCreate,
UserPublic,
UserRegister,
UsersPublic,
UserUpdate,
UserUpdateMe,
UsersPublic,
ItemCreate,
ItemPublic,
ItemsPublic,
ItemUpdate,
} from "./models"
export type TDataLoginAccessToken = {
@ -50,7 +50,7 @@ export class LoginService {
formData: formData,
mediaType: "application/x-www-form-urlencoded",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -85,7 +85,7 @@ export class LoginService {
email,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -106,7 +106,7 @@ export class LoginService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -128,7 +128,7 @@ export class LoginService {
email,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -180,7 +180,7 @@ export class UsersService {
limit,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -201,7 +201,7 @@ export class UsersService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -248,7 +248,7 @@ export class UsersService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -269,7 +269,7 @@ export class UsersService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -290,7 +290,7 @@ export class UsersService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -312,7 +312,7 @@ export class UsersService {
user_id: userId,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -336,7 +336,7 @@ export class UsersService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -356,7 +356,7 @@ export class UsersService {
user_id: userId,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -382,7 +382,7 @@ export class UtilsService {
email_to: emailTo,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -425,7 +425,7 @@ export class ItemsService {
limit,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -446,7 +446,7 @@ export class ItemsService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -466,7 +466,7 @@ export class ItemsService {
id,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -490,7 +490,7 @@ export class ItemsService {
body: requestBody,
mediaType: "application/json",
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}
@ -510,7 +510,7 @@ export class ItemsService {
id,
},
errors: {
422: "Validation Error",
422: `Validation Error`,
},
})
}

8
scripts/generate-client.sh

@ -0,0 +1,8 @@
#! /usr/bin/env bash
PYTHONPATH=backend python -c "import app.main; import json; print(json.dumps(app.main.app.openapi()))" > openapi.json
node frontend/modify-openapi-operationids.js
mv openapi.json frontend/
cd frontend
npm run generate-client
npx biome format --write ./src/client
Loading…
Cancel
Save