👷🏻 Auto-generate frontend client (#1320)
This commit is contained in:
49
.github/workflows/generate-client.yml
vendored
Normal file
49
.github/workflows/generate-client.yml
vendored
Normal file
@@ -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) }}
|
||||
|
@@ -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.
|
||||
|
@@ -6,7 +6,6 @@
|
||||
"files": {
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
"src/client/",
|
||||
"src/routeTree.gen.ts",
|
||||
"playwright.config.ts",
|
||||
"playwright-report"
|
||||
|
@@ -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",
|
||||
|
@@ -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) {
|
||||
|
@@ -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
Normal file
8
scripts/generate-client.sh
Normal file
@@ -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
|
Reference in New Issue
Block a user