diff --git a/src/backend/app/app/main.py b/src/backend/app/app/main.py index d5d0a79..006345d 100644 --- a/src/backend/app/app/main.py +++ b/src/backend/app/app/main.py @@ -1,11 +1,19 @@ from fastapi import FastAPI +from fastapi.routing import APIRoute from starlette.middleware.cors import CORSMiddleware from app.api.api_v1.api import api_router from app.core.config import settings + +def custom_generate_unique_id(route: APIRoute): + return f"{route.tags[0]}-{route.name}" + + app = FastAPI( - title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json" + title=settings.PROJECT_NAME, + openapi_url=f"{settings.API_V1_STR}/openapi.json", + generate_unique_id_function=custom_generate_unique_id, ) # Set all CORS enabled origins diff --git a/src/new-frontend/README.md b/src/new-frontend/README.md index 0d6babe..f22e2e4 100644 --- a/src/new-frontend/README.md +++ b/src/new-frontend/README.md @@ -1,30 +1,17 @@ -# React + TypeScript + Vite +# Full Stack FastAPI and PostgreSQL - Frontend -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +## Generate Client -Currently, two official plugins are available: +- 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` next to the `package.json` file. +- To simplify the names in the generated frontend client code, modifying the `openapi.json` file, run: -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: - -- Configure the top-level `parserOptions` property like this: - -```js -export default { - // other rules... - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - project: ['./tsconfig.json', './tsconfig.node.json'], - tsconfigRootDir: __dirname, - }, -} +```bash +node modify-openapi-operationids.js ``` -- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` -- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` -- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list +- To generate or update the frontend client, run: + +```bash +npm run generate-client +``` diff --git a/src/new-frontend/modify-openapi-operationids.js b/src/new-frontend/modify-openapi-operationids.js new file mode 100644 index 0000000..18dc382 --- /dev/null +++ b/src/new-frontend/modify-openapi-operationids.js @@ -0,0 +1,29 @@ +import * as fs from "fs"; + +const filePath = "./openapi.json"; + +fs.readFile(filePath, (err, data) => { + const openapiContent = JSON.parse(data); + if (err) throw err; + + const paths = openapiContent.paths; + + Object.keys(paths).forEach((pathKey) => { + const pathData = paths[pathKey]; + Object.keys(pathData).forEach((method) => { + const operation = pathData[method]; + if (operation.tags && operation.tags.length > 0) { + const tag = operation.tags[0]; + const operationId = operation.operationId; + const toRemove = `${tag}-`; + if (operationId.startsWith(toRemove)) { + const newOperationId = operationId.substring(toRemove.length); + operation.operationId = newOperationId; + } + } + }); + }); + fs.writeFile(filePath, JSON.stringify(openapiContent, null, 2), (err) => { + if (err) throw err; + }); +}); diff --git a/src/new-frontend/package-lock.json b/src/new-frontend/package-lock.json index 4a3ba79..88d8108 100644 --- a/src/new-frontend/package-lock.json +++ b/src/new-frontend/package-lock.json @@ -8,10 +8,13 @@ "name": "new-frontend", "version": "0.0.0", "dependencies": { + "axios": "1.6.2", + "form-data": "4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { + "@types/node": "20.10.5", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", "@typescript-eslint/eslint-plugin": "^6.10.0", @@ -883,6 +886,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/node": { + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", @@ -1204,6 +1216,21 @@ "node": ">=8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1293,6 +1320,17 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", @@ -1351,6 +1389,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1702,6 +1748,38 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -2088,6 +2166,25 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2320,6 +2417,11 @@ "node": ">= 0.8.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2644,6 +2746,12 @@ "node": ">=0.8.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -3213,6 +3321,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "@types/node": { + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, "@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", @@ -3418,6 +3535,21 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3486,6 +3618,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", @@ -3530,6 +3670,11 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3797,6 +3942,21 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -4087,6 +4247,19 @@ "picomatch": "^2.3.1" } }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4242,6 +4415,11 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4446,6 +4624,12 @@ "dev": true, "optional": true }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", diff --git a/src/new-frontend/package.json b/src/new-frontend/package.json index 9061a5e..c7cfd8b 100644 --- a/src/new-frontend/package.json +++ b/src/new-frontend/package.json @@ -7,13 +7,17 @@ "dev": "vite", "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" + "preview": "vite preview", + "generate-client": "openapi --input ./openapi.json --useOptions --useUnionTypes --output ./src/client --client axios" }, "dependencies": { + "axios": "1.6.2", + "form-data": "4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { + "@types/node": "20.10.5", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", "@typescript-eslint/eslint-plugin": "^6.10.0", @@ -22,6 +26,7 @@ "eslint": "^8.53.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.4", + "openapi-typescript-codegen": "0.25.0", "typescript": "^5.2.2", "vite": "^5.0.0" } diff --git a/src/new-frontend/src/client/core/ApiError.ts b/src/new-frontend/src/client/core/ApiError.ts new file mode 100644 index 0000000..d6b8fcc --- /dev/null +++ b/src/new-frontend/src/client/core/ApiError.ts @@ -0,0 +1,25 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { ApiResult } from './ApiResult'; + +export class ApiError extends Error { + public readonly url: string; + public readonly status: number; + public readonly statusText: string; + public readonly body: any; + public readonly request: ApiRequestOptions; + + constructor(request: ApiRequestOptions, response: ApiResult, message: string) { + super(message); + + this.name = 'ApiError'; + this.url = response.url; + this.status = response.status; + this.statusText = response.statusText; + this.body = response.body; + this.request = request; + } +} diff --git a/src/new-frontend/src/client/core/ApiRequestOptions.ts b/src/new-frontend/src/client/core/ApiRequestOptions.ts new file mode 100644 index 0000000..c19adcc --- /dev/null +++ b/src/new-frontend/src/client/core/ApiRequestOptions.ts @@ -0,0 +1,17 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ApiRequestOptions = { + readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; + readonly url: string; + readonly path?: Record; + readonly cookies?: Record; + readonly headers?: Record; + readonly query?: Record; + readonly formData?: Record; + readonly body?: any; + readonly mediaType?: string; + readonly responseHeader?: string; + readonly errors?: Record; +}; diff --git a/src/new-frontend/src/client/core/ApiResult.ts b/src/new-frontend/src/client/core/ApiResult.ts new file mode 100644 index 0000000..ad8fef2 --- /dev/null +++ b/src/new-frontend/src/client/core/ApiResult.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ApiResult = { + readonly url: string; + readonly ok: boolean; + readonly status: number; + readonly statusText: string; + readonly body: any; +}; diff --git a/src/new-frontend/src/client/core/CancelablePromise.ts b/src/new-frontend/src/client/core/CancelablePromise.ts new file mode 100644 index 0000000..55fef85 --- /dev/null +++ b/src/new-frontend/src/client/core/CancelablePromise.ts @@ -0,0 +1,131 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export class CancelError extends Error { + + constructor(message: string) { + super(message); + this.name = 'CancelError'; + } + + public get isCancelled(): boolean { + return true; + } +} + +export interface OnCancel { + readonly isResolved: boolean; + readonly isRejected: boolean; + readonly isCancelled: boolean; + + (cancelHandler: () => void): void; +} + +export class CancelablePromise implements Promise { + #isResolved: boolean; + #isRejected: boolean; + #isCancelled: boolean; + readonly #cancelHandlers: (() => void)[]; + readonly #promise: Promise; + #resolve?: (value: T | PromiseLike) => void; + #reject?: (reason?: any) => void; + + constructor( + executor: ( + resolve: (value: T | PromiseLike) => void, + reject: (reason?: any) => void, + onCancel: OnCancel + ) => void + ) { + this.#isResolved = false; + this.#isRejected = false; + this.#isCancelled = false; + this.#cancelHandlers = []; + this.#promise = new Promise((resolve, reject) => { + this.#resolve = resolve; + this.#reject = reject; + + const onResolve = (value: T | PromiseLike): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isResolved = true; + this.#resolve?.(value); + }; + + const onReject = (reason?: any): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isRejected = true; + this.#reject?.(reason); + }; + + const onCancel = (cancelHandler: () => void): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#cancelHandlers.push(cancelHandler); + }; + + Object.defineProperty(onCancel, 'isResolved', { + get: (): boolean => this.#isResolved, + }); + + Object.defineProperty(onCancel, 'isRejected', { + get: (): boolean => this.#isRejected, + }); + + Object.defineProperty(onCancel, 'isCancelled', { + get: (): boolean => this.#isCancelled, + }); + + return executor(onResolve, onReject, onCancel as OnCancel); + }); + } + + get [Symbol.toStringTag]() { + return "Cancellable Promise"; + } + + public then( + onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, + onRejected?: ((reason: any) => TResult2 | PromiseLike) | null + ): Promise { + return this.#promise.then(onFulfilled, onRejected); + } + + public catch( + onRejected?: ((reason: any) => TResult | PromiseLike) | null + ): Promise { + return this.#promise.catch(onRejected); + } + + public finally(onFinally?: (() => void) | null): Promise { + return this.#promise.finally(onFinally); + } + + public cancel(): void { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isCancelled = true; + if (this.#cancelHandlers.length) { + try { + for (const cancelHandler of this.#cancelHandlers) { + cancelHandler(); + } + } catch (error) { + console.warn('Cancellation threw an error', error); + return; + } + } + this.#cancelHandlers.length = 0; + this.#reject?.(new CancelError('Request aborted')); + } + + public get isCancelled(): boolean { + return this.#isCancelled; + } +} diff --git a/src/new-frontend/src/client/core/OpenAPI.ts b/src/new-frontend/src/client/core/OpenAPI.ts new file mode 100644 index 0000000..e357bb2 --- /dev/null +++ b/src/new-frontend/src/client/core/OpenAPI.ts @@ -0,0 +1,32 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ApiRequestOptions } from './ApiRequestOptions'; + +type Resolver = (options: ApiRequestOptions) => Promise; +type Headers = Record; + +export type OpenAPIConfig = { + BASE: string; + VERSION: string; + WITH_CREDENTIALS: boolean; + CREDENTIALS: 'include' | 'omit' | 'same-origin'; + TOKEN?: string | Resolver | undefined; + USERNAME?: string | Resolver | undefined; + PASSWORD?: string | Resolver | undefined; + HEADERS?: Headers | Resolver | undefined; + ENCODE_PATH?: ((path: string) => string) | undefined; +}; + +export const OpenAPI: OpenAPIConfig = { + BASE: '', + VERSION: '0.1.0', + WITH_CREDENTIALS: false, + CREDENTIALS: 'include', + TOKEN: undefined, + USERNAME: undefined, + PASSWORD: undefined, + HEADERS: undefined, + ENCODE_PATH: undefined, +}; diff --git a/src/new-frontend/src/client/core/request.ts b/src/new-frontend/src/client/core/request.ts new file mode 100644 index 0000000..1142d43 --- /dev/null +++ b/src/new-frontend/src/client/core/request.ts @@ -0,0 +1,319 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import axios from 'axios'; +import type { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios'; +import FormData from 'form-data'; + +import { ApiError } from './ApiError'; +import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { ApiResult } from './ApiResult'; +import { CancelablePromise } from './CancelablePromise'; +import type { OnCancel } from './CancelablePromise'; +import type { OpenAPIConfig } from './OpenAPI'; + +export const isDefined = (value: T | null | undefined): value is Exclude => { + return value !== undefined && value !== null; +}; + +export const isString = (value: any): value is string => { + return typeof value === 'string'; +}; + +export const isStringWithValue = (value: any): value is string => { + return isString(value) && value !== ''; +}; + +export const isBlob = (value: any): value is Blob => { + return ( + typeof value === 'object' && + typeof value.type === 'string' && + typeof value.stream === 'function' && + typeof value.arrayBuffer === 'function' && + typeof value.constructor === 'function' && + typeof value.constructor.name === 'string' && + /^(Blob|File)$/.test(value.constructor.name) && + /^(Blob|File)$/.test(value[Symbol.toStringTag]) + ); +}; + +export const isFormData = (value: any): value is FormData => { + return value instanceof FormData; +}; + +export const isSuccess = (status: number): boolean => { + return status >= 200 && status < 300; +}; + +export const base64 = (str: string): string => { + try { + return btoa(str); + } catch (err) { + // @ts-ignore + return Buffer.from(str).toString('base64'); + } +}; + +export const getQueryString = (params: Record): string => { + const qs: string[] = []; + + const append = (key: string, value: any) => { + qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); + }; + + const process = (key: string, value: any) => { + if (isDefined(value)) { + if (Array.isArray(value)) { + value.forEach(v => { + process(key, v); + }); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => { + process(`${key}[${k}]`, v); + }); + } else { + append(key, value); + } + } + }; + + Object.entries(params).forEach(([key, value]) => { + process(key, value); + }); + + if (qs.length > 0) { + return `?${qs.join('&')}`; + } + + return ''; +}; + +const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { + const encoder = config.ENCODE_PATH || encodeURI; + + const path = options.url + .replace('{api-version}', config.VERSION) + .replace(/{(.*?)}/g, (substring: string, group: string) => { + if (options.path?.hasOwnProperty(group)) { + return encoder(String(options.path[group])); + } + return substring; + }); + + const url = `${config.BASE}${path}`; + if (options.query) { + return `${url}${getQueryString(options.query)}`; + } + return url; +}; + +export const getFormData = (options: ApiRequestOptions): FormData | undefined => { + if (options.formData) { + const formData = new FormData(); + + const process = (key: string, value: any) => { + if (isString(value) || isBlob(value)) { + formData.append(key, value); + } else { + formData.append(key, JSON.stringify(value)); + } + }; + + Object.entries(options.formData) + .filter(([_, value]) => isDefined(value)) + .forEach(([key, value]) => { + if (Array.isArray(value)) { + value.forEach(v => process(key, v)); + } else { + process(key, value); + } + }); + + return formData; + } + return undefined; +}; + +type Resolver = (options: ApiRequestOptions) => Promise; + +export const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { + if (typeof resolver === 'function') { + return (resolver as Resolver)(options); + } + return resolver; +}; + +export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions, formData?: FormData): Promise> => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); + const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} + + const headers = Object.entries({ + Accept: 'application/json', + ...additionalHeaders, + ...options.headers, + ...formHeaders, + }) + .filter(([_, value]) => isDefined(value)) + .reduce((headers, [key, value]) => ({ + ...headers, + [key]: String(value), + }), {} as Record); + + if (isStringWithValue(token)) { + headers['Authorization'] = `Bearer ${token}`; + } + + if (isStringWithValue(username) && isStringWithValue(password)) { + const credentials = base64(`${username}:${password}`); + headers['Authorization'] = `Basic ${credentials}`; + } + + if (options.body) { + if (options.mediaType) { + headers['Content-Type'] = options.mediaType; + } else if (isBlob(options.body)) { + headers['Content-Type'] = options.body.type || 'application/octet-stream'; + } else if (isString(options.body)) { + headers['Content-Type'] = 'text/plain'; + } else if (!isFormData(options.body)) { + headers['Content-Type'] = 'application/json'; + } + } + + return headers; +}; + +export const getRequestBody = (options: ApiRequestOptions): any => { + if (options.body) { + return options.body; + } + return undefined; +}; + +export const sendRequest = async ( + config: OpenAPIConfig, + options: ApiRequestOptions, + url: string, + body: any, + formData: FormData | undefined, + headers: Record, + onCancel: OnCancel, + axiosClient: AxiosInstance +): Promise> => { + const source = axios.CancelToken.source(); + + const requestConfig: AxiosRequestConfig = { + url, + headers, + data: body ?? formData, + method: options.method, + withCredentials: config.WITH_CREDENTIALS, + cancelToken: source.token, + }; + + onCancel(() => source.cancel('The user aborted a request.')); + + try { + return await axiosClient.request(requestConfig); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + return axiosError.response; + } + throw error; + } +}; + +export const getResponseHeader = (response: AxiosResponse, responseHeader?: string): string | undefined => { + if (responseHeader) { + const content = response.headers[responseHeader]; + if (isString(content)) { + return content; + } + } + return undefined; +}; + +export const getResponseBody = (response: AxiosResponse): any => { + if (response.status !== 204) { + return response.data; + } + return undefined; +}; + +export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { + const errors: Record = { + 400: 'Bad Request', + 401: 'Unauthorized', + 403: 'Forbidden', + 404: 'Not Found', + 500: 'Internal Server Error', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + ...options.errors, + } + + const error = errors[result.status]; + if (error) { + throw new ApiError(options, result, error); + } + + if (!result.ok) { + const errorStatus = result.status ?? 'unknown'; + const errorStatusText = result.statusText ?? 'unknown'; + const errorBody = (() => { + try { + return JSON.stringify(result.body, null, 2); + } catch (e) { + return undefined; + } + })(); + + throw new ApiError(options, result, + `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}` + ); + } +}; + +/** + * Request method + * @param config The OpenAPI configuration object + * @param options The request options from the service + * @param axiosClient The axios client instance to use + * @returns CancelablePromise + * @throws ApiError + */ +export const request = (config: OpenAPIConfig, options: ApiRequestOptions, axiosClient: AxiosInstance = axios): CancelablePromise => { + return new CancelablePromise(async (resolve, reject, onCancel) => { + try { + const url = getUrl(config, options); + const formData = getFormData(options); + const body = getRequestBody(options); + const headers = await getHeaders(config, options, formData); + + if (!onCancel.isCancelled) { + const response = await sendRequest(config, options, url, body, formData, headers, onCancel, axiosClient); + const responseBody = getResponseBody(response); + const responseHeader = getResponseHeader(response, options.responseHeader); + + const result: ApiResult = { + url, + ok: isSuccess(response.status), + status: response.status, + statusText: response.statusText, + body: responseHeader ?? responseBody, + }; + + catchErrorCodes(options, result); + + resolve(result.body); + } + } catch (error) { + reject(error); + } + }); +}; diff --git a/src/new-frontend/src/client/index.ts b/src/new-frontend/src/client/index.ts new file mode 100644 index 0000000..98461a0 --- /dev/null +++ b/src/new-frontend/src/client/index.ts @@ -0,0 +1,27 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export { ApiError } from './core/ApiError'; +export { CancelablePromise, CancelError } from './core/CancelablePromise'; +export { OpenAPI } from './core/OpenAPI'; +export type { OpenAPIConfig } from './core/OpenAPI'; + +export type { Body_login_login_access_token } from './models/Body_login_login_access_token'; +export type { Body_login_reset_password } from './models/Body_login_reset_password'; +export type { HTTPValidationError } from './models/HTTPValidationError'; +export type { ItemCreate } from './models/ItemCreate'; +export type { ItemOut } from './models/ItemOut'; +export type { ItemUpdate } from './models/ItemUpdate'; +export type { Msg } from './models/Msg'; +export type { Token } from './models/Token'; +export type { User } from './models/User'; +export type { UserCreate } from './models/UserCreate'; +export type { UserCreateOpen } from './models/UserCreateOpen'; +export type { UserOut } from './models/UserOut'; +export type { ValidationError } from './models/ValidationError'; + +export { ItemsService } from './services/ItemsService'; +export { LoginService } from './services/LoginService'; +export { UsersService } from './services/UsersService'; +export { UtilsService } from './services/UtilsService'; diff --git a/src/new-frontend/src/client/models/Body_login_login_access_token.ts b/src/new-frontend/src/client/models/Body_login_login_access_token.ts new file mode 100644 index 0000000..bc8efd0 --- /dev/null +++ b/src/new-frontend/src/client/models/Body_login_login_access_token.ts @@ -0,0 +1,13 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type Body_login_login_access_token = { + grant_type?: string; + username: string; + password: string; + scope?: string; + client_id?: string; + client_secret?: string; +}; diff --git a/src/new-frontend/src/client/models/Body_login_reset_password.ts b/src/new-frontend/src/client/models/Body_login_reset_password.ts new file mode 100644 index 0000000..0ca3299 --- /dev/null +++ b/src/new-frontend/src/client/models/Body_login_reset_password.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type Body_login_reset_password = { + token: string; + new_password: string; +}; diff --git a/src/new-frontend/src/client/models/HTTPValidationError.ts b/src/new-frontend/src/client/models/HTTPValidationError.ts new file mode 100644 index 0000000..e218a9f --- /dev/null +++ b/src/new-frontend/src/client/models/HTTPValidationError.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ValidationError } from './ValidationError'; + +export type HTTPValidationError = { + detail?: Array; +}; diff --git a/src/new-frontend/src/client/models/ItemCreate.ts b/src/new-frontend/src/client/models/ItemCreate.ts new file mode 100644 index 0000000..fbe7c16 --- /dev/null +++ b/src/new-frontend/src/client/models/ItemCreate.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type ItemCreate = { + title: string; + description?: string; +}; diff --git a/src/new-frontend/src/client/models/ItemOut.ts b/src/new-frontend/src/client/models/ItemOut.ts new file mode 100644 index 0000000..06787f5 --- /dev/null +++ b/src/new-frontend/src/client/models/ItemOut.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type ItemOut = { + title: string; + description?: string; + id: number; +}; diff --git a/src/new-frontend/src/client/models/ItemUpdate.ts b/src/new-frontend/src/client/models/ItemUpdate.ts new file mode 100644 index 0000000..ef82c3c --- /dev/null +++ b/src/new-frontend/src/client/models/ItemUpdate.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type ItemUpdate = { + title?: string; + description?: string; +}; diff --git a/src/new-frontend/src/client/models/Msg.ts b/src/new-frontend/src/client/models/Msg.ts new file mode 100644 index 0000000..f087de4 --- /dev/null +++ b/src/new-frontend/src/client/models/Msg.ts @@ -0,0 +1,8 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type Msg = { + msg: string; +}; diff --git a/src/new-frontend/src/client/models/Token.ts b/src/new-frontend/src/client/models/Token.ts new file mode 100644 index 0000000..c58838f --- /dev/null +++ b/src/new-frontend/src/client/models/Token.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type Token = { + access_token: string; + token_type: string; +}; diff --git a/src/new-frontend/src/client/models/User.ts b/src/new-frontend/src/client/models/User.ts new file mode 100644 index 0000000..ff390ac --- /dev/null +++ b/src/new-frontend/src/client/models/User.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type User = { + email?: string; + is_active?: boolean; + is_superuser?: boolean; + full_name?: string; + id?: number; +}; diff --git a/src/new-frontend/src/client/models/UserCreate.ts b/src/new-frontend/src/client/models/UserCreate.ts new file mode 100644 index 0000000..9970feb --- /dev/null +++ b/src/new-frontend/src/client/models/UserCreate.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type UserCreate = { + email: string; + is_active?: boolean; + is_superuser?: boolean; + full_name?: string; + password: string; +}; diff --git a/src/new-frontend/src/client/models/UserCreateOpen.ts b/src/new-frontend/src/client/models/UserCreateOpen.ts new file mode 100644 index 0000000..27ca0f1 --- /dev/null +++ b/src/new-frontend/src/client/models/UserCreateOpen.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type UserCreateOpen = { + email: string; + password: string; + full_name?: string; +}; diff --git a/src/new-frontend/src/client/models/UserOut.ts b/src/new-frontend/src/client/models/UserOut.ts new file mode 100644 index 0000000..9f2faf5 --- /dev/null +++ b/src/new-frontend/src/client/models/UserOut.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type UserOut = { + email: string; + is_active?: boolean; + is_superuser?: boolean; + full_name?: string; + id: number; +}; diff --git a/src/new-frontend/src/client/models/ValidationError.ts b/src/new-frontend/src/client/models/ValidationError.ts new file mode 100644 index 0000000..0a3e90e --- /dev/null +++ b/src/new-frontend/src/client/models/ValidationError.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type ValidationError = { + loc: Array<(string | number)>; + msg: string; + type: string; +}; diff --git a/src/new-frontend/src/client/services/ItemsService.ts b/src/new-frontend/src/client/services/ItemsService.ts new file mode 100644 index 0000000..2f9ed3c --- /dev/null +++ b/src/new-frontend/src/client/services/ItemsService.ts @@ -0,0 +1,136 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ItemCreate } from '../models/ItemCreate'; +import type { ItemOut } from '../models/ItemOut'; +import type { ItemUpdate } from '../models/ItemUpdate'; + +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; + +export class ItemsService { + + /** + * Read Items + * Retrieve items. + * @returns ItemOut Successful Response + * @throws ApiError + */ + public static readItems({ +skip, +limit = 100, +}: { +skip?: number, +limit?: number, +}): CancelablePromise> { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v1/items/', + query: { + 'skip': skip, + 'limit': limit, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Create Item + * Create new item. + * @returns ItemOut Successful Response + * @throws ApiError + */ + public static createItem({ +requestBody, +}: { +requestBody: ItemCreate, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/items/', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Read Item + * Get item by ID. + * @returns ItemOut Successful Response + * @throws ApiError + */ + public static readItem({ +id, +}: { +id: number, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v1/items/{id}', + path: { + 'id': id, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Update Item + * Update an item. + * @returns ItemOut Successful Response + * @throws ApiError + */ + public static updateItem({ +id, +requestBody, +}: { +id: number, +requestBody: ItemUpdate, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/api/v1/items/{id}', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Delete Item + * Delete an item. + * @returns ItemOut Successful Response + * @throws ApiError + */ + public static deleteItem({ +id, +}: { +id: number, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/api/v1/items/{id}', + path: { + 'id': id, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + +} diff --git a/src/new-frontend/src/client/services/LoginService.ts b/src/new-frontend/src/client/services/LoginService.ts new file mode 100644 index 0000000..a5fd127 --- /dev/null +++ b/src/new-frontend/src/client/services/LoginService.ts @@ -0,0 +1,97 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { Body_login_login_access_token } from '../models/Body_login_login_access_token'; +import type { Body_login_reset_password } from '../models/Body_login_reset_password'; +import type { Msg } from '../models/Msg'; +import type { Token } from '../models/Token'; +import type { User } from '../models/User'; + +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; + +export class LoginService { + + /** + * Login Access Token + * OAuth2 compatible token login, get an access token for future requests + * @returns Token Successful Response + * @throws ApiError + */ + public static loginAccessToken({ +formData, +}: { +formData: Body_login_login_access_token, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/login/access-token', + formData: formData, + mediaType: 'application/x-www-form-urlencoded', + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Test Token + * Test access token + * @returns User Successful Response + * @throws ApiError + */ + public static testToken(): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/login/test-token', + }); + } + + /** + * Recover Password + * Password Recovery + * @returns Msg Successful Response + * @throws ApiError + */ + public static recoverPassword({ +email, +}: { +email: string, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/password-recovery/{email}', + path: { + 'email': email, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Reset Password + * Reset password + * @returns Msg Successful Response + * @throws ApiError + */ + public static resetPassword({ +requestBody, +}: { +requestBody: Body_login_reset_password, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/reset-password/', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + +} diff --git a/src/new-frontend/src/client/services/UsersService.ts b/src/new-frontend/src/client/services/UsersService.ts new file mode 100644 index 0000000..b6cfa1f --- /dev/null +++ b/src/new-frontend/src/client/services/UsersService.ts @@ -0,0 +1,121 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { UserCreate } from '../models/UserCreate'; +import type { UserCreateOpen } from '../models/UserCreateOpen'; +import type { UserOut } from '../models/UserOut'; + +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; + +export class UsersService { + + /** + * Read Users + * Retrieve users. + * @returns UserOut Successful Response + * @throws ApiError + */ + public static readUsers({ +skip, +limit = 100, +}: { +skip?: number, +limit?: number, +}): CancelablePromise> { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v1/users/', + query: { + 'skip': skip, + 'limit': limit, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Create User + * Create new user. + * @returns UserOut Successful Response + * @throws ApiError + */ + public static createUser({ +requestBody, +}: { +requestBody: UserCreate, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/users/', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Read User Me + * Get current user. + * @returns UserOut Successful Response + * @throws ApiError + */ + public static readUserMe(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v1/users/me', + }); + } + + /** + * Create User Open + * Create new user without the need to be logged in. + * @returns UserOut Successful Response + * @throws ApiError + */ + public static createUserOpen({ +requestBody, +}: { +requestBody: UserCreateOpen, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/users/open', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Read User By Id + * Get a specific user by id. + * @returns UserOut Successful Response + * @throws ApiError + */ + public static readUserById({ +userId, +}: { +userId: number, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v1/users/{user_id}', + path: { + 'user_id': userId, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + +} diff --git a/src/new-frontend/src/client/services/UtilsService.ts b/src/new-frontend/src/client/services/UtilsService.ts new file mode 100644 index 0000000..7b34b71 --- /dev/null +++ b/src/new-frontend/src/client/services/UtilsService.ts @@ -0,0 +1,58 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { Msg } from '../models/Msg'; + +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; + +export class UtilsService { + + /** + * Test Celery + * Test Celery worker. + * @returns Msg Successful Response + * @throws ApiError + */ + public static testCelery({ +requestBody, +}: { +requestBody: Msg, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/utils/test-celery/', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + + /** + * Test Email + * Test emails. + * @returns Msg Successful Response + * @throws ApiError + */ + public static testEmail({ +emailTo, +}: { +emailTo: string, +}): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/utils/test-email/', + query: { + 'email_to': emailTo, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + +}