├── .github └── workflows │ └── tests.yml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.md ├── builder ├── __init__.py ├── app_manager.py ├── cli │ ├── __init__.py │ ├── app.py │ ├── config.py │ ├── data.py │ ├── db.py │ └── utils.py ├── config │ ├── __init__.py │ ├── parse.py │ └── tests │ │ ├── __init__.py │ │ └── test_config_parsing.py ├── constants.py ├── generate │ ├── __init__.py │ ├── backend │ │ ├── __init__.py │ │ ├── generator.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ └── test_backend_generator.py │ │ └── utils.py │ ├── docker │ │ ├── __init__.py │ │ ├── generator.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ └── test_docker_generator.py │ ├── frontend │ │ ├── __init__.py │ │ ├── generator.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ └── test_frontend_generator.py │ ├── openapi │ │ ├── __init__.py │ │ ├── generator.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ ├── data │ │ │ └── openapi.json │ │ │ └── test_openapi_generator.py │ └── poetry │ │ ├── __init__.py │ │ ├── generator.py │ │ └── tests │ │ ├── __init__.py │ │ └── test_generator.py ├── jinja │ ├── __init__.py │ └── templates.py ├── main.py ├── managers │ ├── __init__.py │ ├── db │ │ ├── __init__.py │ │ ├── constants.py │ │ └── manager.py │ └── linting │ │ ├── __init__.py │ │ └── manager.py ├── models │ ├── __init__.py │ ├── configs.py │ ├── db.py │ ├── enum.py │ ├── tests │ │ ├── __init__.py │ │ └── test_configs.py │ └── version.py ├── openapi │ ├── __init__.py │ └── export.py ├── templates │ ├── backend │ │ ├── docker │ │ │ ├── .dockerignore │ │ │ ├── .env │ │ │ ├── Dockerfile │ │ │ ├── README.Docker.md │ │ │ └── compose.yml │ │ ├── models │ │ │ └── model.jinja │ │ ├── poetry │ │ │ └── toml.jinja │ │ ├── readme │ │ │ └── README.jinja │ │ └── service │ │ │ ├── route.jinja │ │ │ └── service.jinja │ ├── databases │ │ └── alembic │ │ │ ├── alembic.ini │ │ │ ├── alembic │ │ │ ├── README │ │ │ ├── __init__.py │ │ │ ├── env.jinja │ │ │ └── script.py.mako │ │ │ ├── constants.jinja │ │ │ ├── manager.jinja │ │ │ ├── models.jinja │ │ │ └── utils.jinja │ └── frontend │ │ ├── components │ │ ├── home.tsx │ │ ├── layout.tsx │ │ ├── model_page.tsx │ │ ├── no_page.tsx │ │ └── utils.tsx │ │ └── index.tsx ├── test_data │ ├── __init__.py │ └── create_fake_data.py ├── tests │ ├── __init__.py │ ├── configs │ │ ├── events.yaml │ │ └── restaurant.yaml │ ├── test_app_manager.py │ └── test_restaurant_app.py └── utils.py ├── example └── alembic │ ├── output │ ├── backend │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── README.Docker.md │ │ ├── README.md │ │ ├── __init__.py │ │ ├── compose.yml │ │ ├── openapi.json │ │ ├── poetry.lock │ │ ├── pyproject.toml │ │ ├── requirements.txt │ │ ├── service.py │ │ └── src │ │ │ ├── __init__.py │ │ │ ├── db │ │ │ ├── __init__.py │ │ │ ├── alembic.ini │ │ │ ├── alembic │ │ │ │ ├── README │ │ │ │ ├── __init__.py │ │ │ │ ├── env.py │ │ │ │ └── script.py.mako │ │ │ ├── constants.py │ │ │ ├── models.py │ │ │ ├── reservation_manager.py │ │ │ ├── restaurant_manager.py │ │ │ ├── review_manager.py │ │ │ ├── user_manager.py │ │ │ └── utils.py │ │ │ ├── models │ │ │ ├── __init__.py │ │ │ └── models.py │ │ │ ├── reservation_routes.py │ │ │ ├── restaurant_routes.py │ │ │ ├── review_routes.py │ │ │ └── user_routes.py │ ├── client │ │ ├── .github │ │ │ └── workflows │ │ │ │ └── python.yml │ │ ├── .gitignore │ │ ├── .gitlab-ci.yml │ │ ├── .openapi-generator-ignore │ │ ├── .openapi-generator │ │ │ ├── FILES │ │ │ └── VERSION │ │ ├── .travis.yml │ │ ├── README.md │ │ ├── docs │ │ │ ├── DefaultApi.md │ │ │ ├── HTTPValidationError.md │ │ │ ├── Reservation.md │ │ │ ├── ReservationApi.md │ │ │ ├── ReservationQuery.md │ │ │ ├── Restaurant.md │ │ │ ├── RestaurantApi.md │ │ │ ├── RestaurantQuery.md │ │ │ ├── Review.md │ │ │ ├── ReviewApi.md │ │ │ ├── ReviewQuery.md │ │ │ ├── User.md │ │ │ ├── UserApi.md │ │ │ ├── UserQuery.md │ │ │ ├── ValidationError.md │ │ │ └── ValidationErrorLocInner.md │ │ ├── git_push.sh │ │ ├── openapi_client │ │ │ ├── __init__.py │ │ │ ├── api │ │ │ │ ├── __init__.py │ │ │ │ ├── default_api.py │ │ │ │ ├── reservation_api.py │ │ │ │ ├── restaurant_api.py │ │ │ │ ├── review_api.py │ │ │ │ └── user_api.py │ │ │ ├── api_client.py │ │ │ ├── api_response.py │ │ │ ├── configuration.py │ │ │ ├── exceptions.py │ │ │ ├── models │ │ │ │ ├── __init__.py │ │ │ │ ├── http_validation_error.py │ │ │ │ ├── reservation.py │ │ │ │ ├── reservation_query.py │ │ │ │ ├── restaurant.py │ │ │ │ ├── restaurant_query.py │ │ │ │ ├── review.py │ │ │ │ ├── review_query.py │ │ │ │ ├── user.py │ │ │ │ ├── user_query.py │ │ │ │ ├── validation_error.py │ │ │ │ └── validation_error_loc_inner.py │ │ │ ├── py.typed │ │ │ └── rest.py │ │ ├── pyproject.toml │ │ ├── requirements.txt │ │ ├── setup.cfg │ │ ├── setup.py │ │ ├── test-requirements.txt │ │ ├── test │ │ │ ├── __init__.py │ │ │ ├── test_default_api.py │ │ │ ├── test_http_validation_error.py │ │ │ ├── test_reservation.py │ │ │ ├── test_reservation_api.py │ │ │ ├── test_reservation_query.py │ │ │ ├── test_restaurant.py │ │ │ ├── test_restaurant_api.py │ │ │ ├── test_restaurant_query.py │ │ │ ├── test_review.py │ │ │ ├── test_review_api.py │ │ │ ├── test_review_query.py │ │ │ ├── test_user.py │ │ │ ├── test_user_api.py │ │ │ ├── test_user_query.py │ │ │ ├── test_validation_error.py │ │ │ └── test_validation_error_loc_inner.py │ │ └── tox.ini │ ├── config │ │ └── config.yaml │ └── restaurant_app │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ │ ├── src │ │ ├── App.css │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── api │ │ │ ├── .openapi-generator-ignore │ │ │ ├── .openapi-generator │ │ │ │ ├── FILES │ │ │ │ └── VERSION │ │ │ ├── apis │ │ │ │ ├── DefaultApi.ts │ │ │ │ ├── ReservationApi.ts │ │ │ │ ├── RestaurantApi.ts │ │ │ │ ├── ReviewApi.ts │ │ │ │ ├── UserApi.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── HTTPValidationError.ts │ │ │ │ ├── Reservation.ts │ │ │ │ ├── ReservationQuery.ts │ │ │ │ ├── Restaurant.ts │ │ │ │ ├── RestaurantQuery.ts │ │ │ │ ├── Review.ts │ │ │ │ ├── ReviewQuery.ts │ │ │ │ ├── User.ts │ │ │ │ ├── UserQuery.ts │ │ │ │ ├── ValidationError.ts │ │ │ │ ├── ValidationErrorLocInner.ts │ │ │ │ └── index.ts │ │ │ └── runtime.ts │ │ ├── components │ │ │ ├── Home.tsx │ │ │ ├── Layout.tsx │ │ │ ├── NoPage.tsx │ │ │ ├── reservation_page.tsx │ │ │ ├── restaurant_page.tsx │ │ │ ├── review_page.tsx │ │ │ ├── user_page.tsx │ │ │ └── utils.tsx │ │ ├── index.css │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ │ └── tsconfig.json │ └── restaurant.yaml ├── images ├── home_page.png ├── postman.png ├── reservation_page.png ├── restaurant_page.png ├── review_page.png └── user_page.png ├── poetry.lock └── pyproject.toml /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__ 2 | .idea/ 3 | .idea 4 | .coverage 5 | logs 6 | .env 7 | .coverage 8 | versions 9 | .DS_Store 10 | **/.DS_Store -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v2.3.0 4 | hooks: 5 | - id: check-yaml 6 | - id: end-of-file-fixer 7 | - id: trailing-whitespace 8 | # - repo: https://github.com/psf/black 9 | # rev: 22.10.0 10 | # hooks: 11 | # - id: black 12 | - repo: https://github.com/pycqa/isort 13 | rev: 5.12.0 14 | hooks: 15 | - id: isort 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Nick Roberson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /builder/__init__.py: -------------------------------------------------------------------------------- 1 | # import the app object from the main module for poetry 2 | from .main import app 3 | -------------------------------------------------------------------------------- /builder/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/cli/__init__.py -------------------------------------------------------------------------------- /builder/cli/data.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | import typer 4 | from rich import print 5 | 6 | from builder.cli.utils import validate_config 7 | from builder.constants import TEST_MYSQL_CONFIG 8 | from builder.test_data.create_fake_data import create_fake_data 9 | 10 | app = typer.Typer() 11 | 12 | 13 | @app.command() 14 | def create( 15 | config: Optional[str] = typer.Option( 16 | TEST_MYSQL_CONFIG, "--config", "-c", help="Path to the input YAML config." 17 | ) 18 | ): 19 | """ 20 | Generate fake data for the service based on a specified YAML configuration file. 21 | 22 | Args: 23 | config (str, optional): Path to the input YAML configuration file. 24 | Defaults to TEST_MYSQL_CONFIG. 25 | """ 26 | # Validate and process the configuration file 27 | service_config = validate_config(config) 28 | 29 | # Retrieve and log service name from the configuration 30 | service_name = service_config.service_info.name 31 | print(f"Generating fake data for app `{service_name}`") 32 | print(f"\tconfig: {config}") 33 | 34 | # Generate fake data as per the configuration and log the output 35 | result = create_fake_data(config=service_config) 36 | print("Generated fake data at:") 37 | for model_name, file_path in result.items(): 38 | print(f"\t{model_name}: {file_path}") 39 | print("\nYou can now use this data to seed your database.") 40 | -------------------------------------------------------------------------------- /builder/cli/utils.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from typing import Dict 4 | 5 | import typer 6 | from rich import print 7 | 8 | from builder.config.parse import load_and_validate_config 9 | from builder.models.configs import ServiceConfig 10 | 11 | 12 | def validate_service_name(service_name: str) -> str: 13 | """Validate the service name and return the cleaned version. 14 | 15 | Args: 16 | service_name (str): The service name 17 | 18 | Returns: 19 | str: The cleaned service name 20 | """ 21 | # Check if it is too short or too long 22 | if len(service_name) < 3: 23 | print("Service name must be at least 3 characters") 24 | typer.Exit(code=1) 25 | if len(service_name) > 20: 26 | print("Service name must be less than 20 characters") 27 | typer.Exit(code=1) 28 | 29 | # Clean the service name 30 | service_name = service_name.lower() 31 | service_name = "".join(e for e in service_name if e.isalnum()) 32 | return service_name 33 | 34 | 35 | def validate_config(config_file: str) -> ServiceConfig: 36 | """Validate the config file and return the absolute path. 37 | 38 | Args: 39 | config_file (str): The config file 40 | 41 | Returns: 42 | ServiceConfig: The validated config 43 | """ 44 | # Check if the file exists 45 | if not os.path.exists(config_file): 46 | print(f"Config file not found at {config_file}") 47 | typer.Exit(code=1) 48 | 49 | # Get the absolute path 50 | full_path = os.path.abspath(config_file) 51 | 52 | # Load and validate the config 53 | config = load_and_validate_config(full_path) 54 | return config 55 | 56 | 57 | def process_close(result: Dict, config: ServiceConfig, config_path: str): 58 | """Process the close out of the CLI command. 59 | 60 | Args: 61 | result (Dict): The generated files 62 | config (ServiceConfig): The service configuration 63 | config_path (str): The path to the config file 64 | """ 65 | # Display the generated files 66 | print(f"\nGenerated files:") 67 | print(json.dumps(result, indent=4)) 68 | 69 | # Get rel path for the config file 70 | rel_config = os.path.relpath(config_path) 71 | 72 | # Display the commands for the user to run 73 | migration_lines = [ 74 | " % poetry run builder db migrate \\", 75 | f"\t--config {rel_config} \\", 76 | f"\t--message 'Initial migration for {config.service_info.name}'", 77 | ] 78 | run_backend_lines = [ 79 | " % poetry run builder app run-backend \\", 80 | f"\t--config {rel_config}", 81 | ] 82 | run_frontend_lines = [ 83 | " % poetry run builder app run-frontend \\", 84 | f"\t--config {rel_config}", 85 | ] 86 | 87 | # Display commands for users to create and apply database migrations 88 | print("") 89 | print("1. Apply new migrations:") 90 | print("\n".join(migration_lines)) 91 | 92 | # Display commands for users to go and run the backend 93 | print("") 94 | print("2. Run backend:") 95 | print("\n".join(run_backend_lines)) 96 | 97 | # Display commands for users to go and run the frontend 98 | print("") 99 | print("3. Run frontend:") 100 | print("\n".join(run_frontend_lines)) 101 | -------------------------------------------------------------------------------- /builder/config/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/config/__init__.py -------------------------------------------------------------------------------- /builder/config/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/config/tests/__init__.py -------------------------------------------------------------------------------- /builder/config/tests/test_config_parsing.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | 3 | import pytest 4 | 5 | from builder.config.parse import load_config, parse_config 6 | from builder.constants import TEST_MYSQL_CONFIG 7 | 8 | 9 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 10 | def test_config_not_exists(config): 11 | with pytest.raises(ValueError): 12 | load_config("not_exists.yaml") 13 | 14 | 15 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 16 | def test_config_missing_service(config): 17 | with pytest.raises(ValueError): 18 | config_def = load_config(config) 19 | del config_def["service"] 20 | parse_config(config_def) 21 | 22 | 23 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 24 | def test_config_missing_models(config): 25 | with pytest.raises(ValueError): 26 | config_def = load_config(config) 27 | del config_def["models"] 28 | parse_config(config_def) 29 | 30 | 31 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 32 | def test_config_missing_database(config): 33 | with pytest.raises(ValueError): 34 | config_def = load_config(config) 35 | del config_def["database"] 36 | parse_config(config_def) 37 | 38 | 39 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 40 | def test_config_missing_model_missing_fields(config): 41 | with pytest.raises(ValueError): 42 | config_def = load_config(config) 43 | del config_def["models"][0]["fields"] 44 | parse_config(config_def) 45 | -------------------------------------------------------------------------------- /builder/constants.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Directory containing the generated code within the output directory 4 | CODEGEN_DIR_NAME: str = "backend" 5 | 6 | # Test configs 7 | TEST_MYSQL_CONFIG: str = os.path.abspath("example/alembic/restaurant.yaml") 8 | 9 | # Version directory 10 | VERSIONS_DIR: str = os.path.abspath("versions") 11 | 12 | # Template directories 13 | TEMPLATE_DIR: str = os.path.abspath("builder/templates") 14 | 15 | # Backend templates 16 | MODEL_TEMPLATES: str = f"{TEMPLATE_DIR}/backend/models/" 17 | SERVICE_TEMPLATES: str = f"{TEMPLATE_DIR}/backend/service/" 18 | POETRY_TEMPLATES: str = f"{TEMPLATE_DIR}/backend/poetry/" 19 | README_TEMPLATES: str = f"{TEMPLATE_DIR}/backend/readme/" 20 | DOCKER_TEMPLATES: str = f"{TEMPLATE_DIR}/backend/docker/" 21 | 22 | # Frontend templates 23 | FRONTEND_TEMPLATES: str = f"{TEMPLATE_DIR}/frontend/" 24 | 25 | # Alembic Templates 26 | ALEMBIC_TEMPLATES: str = f"{TEMPLATE_DIR}/databases/alembic/" 27 | 28 | # Default port 29 | DEFAULT_PORT: int = 8000 30 | 31 | # Service Python Dependencies 32 | PYTHON_VERSION = "3.12.2" 33 | PYTHON_DEPENDENCIES = [ 34 | ("python", f"^{PYTHON_VERSION}"), 35 | ("pyyaml", "^6.0.1"), 36 | ("jinja2", "^3.1.3"), 37 | ("pydantic", "^2.6.4"), 38 | ("fastapi", "^0.110.0"), 39 | ("uvicorn", "^0.28.0"), 40 | ("certifi", "^2024.2.2"), 41 | ("rich", "^13.7.1"), 42 | ("isort", "^5.13.2"), 43 | ("black", "^24.2.0"), 44 | ("typer", "^0.9.0"), 45 | ("pytest", "^8.1.1"), 46 | ("coverage", "^7.4.4"), 47 | ("faker", "^24.7.1"), 48 | ("alembic", "^1.13.1"), 49 | ("sqlalchemy", "^2.0.29"), 50 | ("pymysql", "^1.0.2"), 51 | ("httpx", "^0.27.0"), 52 | ("urllib3", "^2.2.1"), 53 | ("requests", "^2.31.0"), 54 | ("psycopg2-binary", "^2.9.9"), 55 | ] 56 | 57 | # Node Dependencies 58 | NODE_DEPENDENCIES = [ 59 | "axios", 60 | "@mui/material", 61 | "@mui/icons-material", 62 | "@mui/x-data-grid", 63 | "@mui/styled-engine", 64 | "@mui/lab", 65 | "@emotion/react", 66 | "@emotion/styled", 67 | "prettier", 68 | "eslint", 69 | "web-vitals", 70 | "react-router-dom", 71 | ] 72 | 73 | # OpenAPI Spec filename 74 | SAMPLE_OPENAPI_DIR: str = "data/openapi/" 75 | OPENAPI_SPEC_FN: str = "openapi.json" 76 | 77 | # Service name 78 | SERVICE_NAME: str = "service:app" 79 | 80 | # Default service name 81 | DEFAULT_SERVICE_NAME: str = "my-service" 82 | 83 | # Verbose logging 84 | VERBOSE: bool = True if os.getenv("VERBOSE") else False 85 | 86 | # Required Database Environment Variables 87 | REQUIRED_DB_ENV_VARS = { 88 | "mysql": ["DB_HOST", "DB_PORT", "DB_USER", "DB_NAME", "DB_PASSWORD"], 89 | "postgres": ["DB_HOST", "DB_PORT", "DB_USER", "DB_NAME", "DB_PASSWORD"], 90 | } 91 | -------------------------------------------------------------------------------- /builder/generate/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/__init__.py -------------------------------------------------------------------------------- /builder/generate/backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/backend/__init__.py -------------------------------------------------------------------------------- /builder/generate/backend/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/backend/tests/__init__.py -------------------------------------------------------------------------------- /builder/generate/backend/tests/test_backend_generator.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | 3 | import pytest 4 | 5 | from builder.config.parse import load_config, parse_config 6 | from builder.constants import TEST_MYSQL_CONFIG 7 | from builder.generate.backend.generator import BackendGenerator 8 | 9 | 10 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 11 | def test_backend_generator(config): 12 | """Simple test to validate the example config""" 13 | with tempfile.TemporaryDirectory() as output_dir: 14 | # Parse the model definitions 15 | config_def = load_config(config) 16 | config = parse_config(config_def) 17 | config.output_dir = output_dir 18 | 19 | # Init the backend generator 20 | generator = BackendGenerator(config=config) 21 | 22 | # Generate the backend code 23 | generator.generate_models() 24 | generator.generate_services() 25 | generator.generate_templated_components() 26 | generator.generate_database() 27 | generator.generate_readme() 28 | -------------------------------------------------------------------------------- /builder/generate/backend/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | -------------------------------------------------------------------------------- /builder/generate/docker/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/docker/__init__.py -------------------------------------------------------------------------------- /builder/generate/docker/generator.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List 3 | 4 | from builder.constants import DOCKER_TEMPLATES 5 | from builder.models import ServiceConfig 6 | from builder.utils import clear_file, run_command 7 | 8 | 9 | class DockerGenerator: 10 | """Class to handle Docker file generation.""" 11 | 12 | # Class constant for the directory name 13 | CODE_DIR = "backend" 14 | # List of Docker related files 15 | DOCKER_FILES = [ 16 | ".env", 17 | "Dockerfile", 18 | "compose.yml", 19 | ".dockerignore", 20 | "README.Docker.md", 21 | ] 22 | 23 | def __init__(self, config: ServiceConfig): 24 | # Set the config and output directory 25 | self.config = config 26 | self.output_dir = config.output_dir 27 | 28 | # Set the code directory 29 | self.code_dir = os.path.join(self.output_dir, self.CODE_DIR) 30 | os.makedirs(self.code_dir, exist_ok=True) # Ensures the directory exists 31 | 32 | # Check all Docker template files exist 33 | for file in self.DOCKER_FILES: 34 | src = os.path.join(DOCKER_TEMPLATES, file) 35 | if not os.path.exists(src): 36 | raise FileNotFoundError(f"Template file {src} not found") 37 | 38 | def copy_dockerfiles(self) -> List[str]: 39 | """Copy Docker template files to the output directory.""" 40 | dockerfiles = [] 41 | for file in self.DOCKER_FILES: 42 | src = os.path.join(DOCKER_TEMPLATES, file) 43 | dst = os.path.join(self.code_dir, file) 44 | run_command(f"cp {src} {dst}", cwd=self.code_dir) 45 | dockerfiles.append(dst) 46 | return dockerfiles 47 | 48 | def clear_docker_files(self) -> None: 49 | """Clear Docker-related files.""" 50 | for docker_file in self.DOCKER_FILES: 51 | clear_file(os.path.join(self.code_dir, docker_file)) 52 | -------------------------------------------------------------------------------- /builder/generate/docker/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/docker/tests/__init__.py -------------------------------------------------------------------------------- /builder/generate/docker/tests/test_docker_generator.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | 3 | import pytest 4 | 5 | from builder.config.parse import load_config, parse_config 6 | from builder.constants import TEST_MYSQL_CONFIG 7 | from builder.generate.docker.generator import DockerGenerator 8 | 9 | 10 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 11 | def test_docker_generator(config): 12 | """Simple test to validate the example config""" 13 | with tempfile.TemporaryDirectory() as output_dir: 14 | # Parse the model definitions 15 | config_def = load_config(config) 16 | config = parse_config(config_def) 17 | config.output_dir = output_dir 18 | 19 | # Create the frontend generator 20 | docker_generator = DockerGenerator(config=config) 21 | 22 | # Generate the docker files 23 | docker_generator.copy_dockerfiles() 24 | docker_generator.clear_docker_files() 25 | -------------------------------------------------------------------------------- /builder/generate/frontend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/frontend/__init__.py -------------------------------------------------------------------------------- /builder/generate/frontend/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/frontend/tests/__init__.py -------------------------------------------------------------------------------- /builder/generate/frontend/tests/test_frontend_generator.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | 3 | import pytest 4 | 5 | from builder.config.parse import load_config, parse_config 6 | from builder.constants import TEST_MYSQL_CONFIG 7 | from builder.generate.frontend.generator import FrontendGenerator 8 | from builder.managers.linting.manager import LintingManager 9 | 10 | 11 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 12 | def test_frontend_generator(config): 13 | """Simple test to validate the example config""" 14 | with tempfile.TemporaryDirectory() as output_dir: 15 | # Parse the model definitions 16 | config_def = load_config(config) 17 | config = parse_config(config_def) 18 | config.output_dir = output_dir 19 | 20 | # Create the frontend generator 21 | frontend_generator = FrontendGenerator(config=config) 22 | 23 | # Generate the application 24 | frontend_generator.generate_application() 25 | # Install the dependencies 26 | frontend_generator.install_dependencies() 27 | # Generate the main page 28 | frontend_generator.generate_templated_components() 29 | 30 | # Lint the frontend 31 | linting_manager = LintingManager(config=config) 32 | linting_manager.lint_frontend() 33 | -------------------------------------------------------------------------------- /builder/generate/openapi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/openapi/__init__.py -------------------------------------------------------------------------------- /builder/generate/openapi/generator.py: -------------------------------------------------------------------------------- 1 | import os 2 | from string import Template 3 | from typing import List 4 | 5 | from rich import print 6 | 7 | from builder.constants import OPENAPI_SPEC_FN 8 | from builder.models import ServiceConfig 9 | from builder.openapi.export import export_openapi 10 | from builder.utils import run_command 11 | 12 | # Command templates for generating client code using the OpenAPI Generator 13 | PYTHON_CLIENT_CMD: Template = Template( 14 | "openapi-generator generate -i $openapi_spec -g python -o $output_dir" 15 | ) 16 | TYPESCRIPT_CLIENT_CMD: Template = Template( 17 | "openapi-generator generate -i $openapi_spec -g typescript-fetch -o $output_dir" 18 | ) 19 | 20 | 21 | class OpenAPIGenerator: 22 | """ 23 | A class responsible for managing OpenAPI specification files and generating client libraries. 24 | 25 | Attributes: 26 | config (ServiceConfig): Configuration data for the service. 27 | output_dir (str): Base directory for output files. 28 | backend_code_dir (str): Directory for backend code. 29 | openapi_file_path (str): Full path to the OpenAPI JSON file. 30 | python_client_dir (str): Directory for the Python client library. 31 | typescript_client_dir (str): Directory for the TypeScript client library. 32 | """ 33 | 34 | def __init__(self, config: ServiceConfig): 35 | """ 36 | Initialize the OpenAPIGenerator with a service configuration. 37 | 38 | Parameters: 39 | config (ServiceConfig): Configuration object for the service. 40 | """ 41 | self.config = config 42 | self.output_dir = config.output_dir 43 | self.backend_code_dir = os.path.join(self.output_dir, "backend") 44 | self.openapi_file_path = os.path.join(self.backend_code_dir, OPENAPI_SPEC_FN) 45 | os.makedirs(self.backend_code_dir, exist_ok=True) 46 | 47 | self.python_client_dir = os.path.join(self.output_dir, "client") 48 | self.typescript_client_dir = os.path.join( 49 | self.output_dir, config.service_info.name, "src/api" 50 | ) 51 | 52 | def generate_openapi_json(self) -> str: 53 | """ 54 | Generate and return the path to the OpenAPI JSON specification file. 55 | 56 | Returns: 57 | str: The path to the generated OpenAPI JSON file. 58 | """ 59 | output_file = export_openapi(output_dir=self.backend_code_dir) 60 | print(f"\t\t> OpenAPI spec generated at: {output_file}") 61 | return output_file 62 | 63 | def validate_openapi_spec(self): 64 | """ 65 | Optional method to validate the generated OpenAPI specification. 66 | 67 | Implement validation logic or integrate with an external validation tool if necessary. 68 | """ 69 | pass 70 | 71 | def generate_python_client(self): 72 | """ 73 | Generate the Python client library using the OpenAPI Generator. 74 | """ 75 | if not os.path.exists(self.python_client_dir): 76 | os.makedirs(self.python_client_dir, exist_ok=True) 77 | command = PYTHON_CLIENT_CMD.substitute( 78 | openapi_spec=self.openapi_file_path, output_dir=self.python_client_dir 79 | ) 80 | run_command(cmd=command, cwd=self.backend_code_dir) 81 | 82 | def generate_typescript_client(self): 83 | """ 84 | Generate the TypeScript client library using the OpenAPI Generator. 85 | """ 86 | if not os.path.exists(self.typescript_client_dir): 87 | os.makedirs(self.typescript_client_dir, exist_ok=True) 88 | command = TYPESCRIPT_CLIENT_CMD.substitute( 89 | openapi_spec=self.openapi_file_path, output_dir=self.typescript_client_dir 90 | ) 91 | run_command(cmd=command, cwd=self.backend_code_dir) 92 | -------------------------------------------------------------------------------- /builder/generate/openapi/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/openapi/tests/__init__.py -------------------------------------------------------------------------------- /builder/generate/openapi/tests/test_openapi_generator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | 4 | import pytest 5 | 6 | from builder.config.parse import load_config, parse_config 7 | from builder.constants import TEST_MYSQL_CONFIG 8 | from builder.generate.openapi.generator import OpenAPIGenerator 9 | 10 | TEST_OPENAPI_CONFIG_PATH: str = "builder/generate/openapi/tests/data/openapi.json" 11 | 12 | 13 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 14 | def test_openapi_generator(config): 15 | with tempfile.TemporaryDirectory() as output_dir: 16 | # Parse the model definitions 17 | config_def = load_config(config) 18 | config = parse_config(config_def) 19 | config.output_dir = output_dir 20 | 21 | # Init the backend generator 22 | generator = OpenAPIGenerator(config=config) 23 | 24 | # Copy the openapi file to the backend code dir 25 | src = os.path.abspath(TEST_OPENAPI_CONFIG_PATH) 26 | dst = os.path.join(generator.backend_code_dir, "openapi.json") 27 | os.makedirs(os.path.dirname(dst), exist_ok=True) 28 | os.system(f"cp {src} {dst}") 29 | 30 | # Generate the openapi code 31 | generator.generate_python_client() 32 | generator.generate_typescript_client() 33 | -------------------------------------------------------------------------------- /builder/generate/poetry/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/poetry/__init__.py -------------------------------------------------------------------------------- /builder/generate/poetry/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/generate/poetry/tests/__init__.py -------------------------------------------------------------------------------- /builder/generate/poetry/tests/test_generator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | 4 | import pytest 5 | 6 | from builder.config.parse import load_config, parse_config 7 | from builder.constants import TEST_MYSQL_CONFIG 8 | from builder.generate.poetry.generator import PoetryGenerator 9 | 10 | 11 | @pytest.mark.parametrize("config", [TEST_MYSQL_CONFIG]) 12 | def test_generate(config): 13 | """Simple test to validate the example config""" 14 | with tempfile.TemporaryDirectory() as output_dir: 15 | # Parse the model definitions 16 | config_def = load_config(config) 17 | config = parse_config(config_def) 18 | 19 | # Init the backend generator 20 | generator = PoetryGenerator(config=config) 21 | 22 | # Generate the backend code 23 | generator.generate_poetry_toml() 24 | assert os.path.exists(generator.poetry_toml) 25 | 26 | # Install the dependencies 27 | generator.install_dependencies() 28 | assert os.path.exists(generator.poetry_lock) 29 | 30 | # Export requirements 31 | generator.export_requirements() 32 | assert os.path.exists(generator.requirements_txt) 33 | -------------------------------------------------------------------------------- /builder/jinja/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/jinja/__init__.py -------------------------------------------------------------------------------- /builder/jinja/templates.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from jinja2 import Environment, FileSystemLoader, Template 4 | from rich import print 5 | 6 | # Constants 7 | VERBOSE: bool = os.environ.get("VERBOSE", False) 8 | 9 | 10 | def load_template(template_path: str, template_name: str) -> Template: 11 | """Load a template file. 12 | 13 | Args: 14 | template_path (str): The path to the template file 15 | template_name (str): The name of the template file 16 | Returns: 17 | str: The template content 18 | """ 19 | try: 20 | # Ensure that the template path is fully qualified and exists 21 | template_path = os.path.abspath(template_path) 22 | if not os.path.exists(template_path): 23 | raise FileNotFoundError(f"Template path not found: {template_path}") 24 | 25 | # Load the template 26 | env = Environment(loader=FileSystemLoader(template_path)) 27 | return env.get_template(template_name) 28 | except Exception as e: 29 | print(f"Error loading template: {template_path}, {e}") 30 | raise e 31 | 32 | 33 | def write_template(template: Template, output_path: str, context: dict) -> None: 34 | """Write a template to a file. 35 | 36 | Args: 37 | template (Template): The template content 38 | output_path (str): The output file path 39 | context (dict): The context for the template 40 | """ 41 | try: 42 | # Render the template 43 | context = context or {} 44 | rendered_template = template.render(**context) 45 | 46 | # Write the rendered template to the output path 47 | with open(output_path, "w") as f: 48 | f.write(rendered_template) 49 | except Exception as e: 50 | print(f"Error writing template: {output_path}, {e}") 51 | raise e 52 | 53 | 54 | def populate_template( 55 | template_dir: str, template_name: str, output_path: str, context: dict = None 56 | ) -> str: 57 | """Populate a template file. 58 | 59 | Args: 60 | template_dir (str): The path to the template file directory 61 | template_name (str): The name of the template file 62 | output_path (str): The output file path 63 | context (dict): The context for the template 64 | """ 65 | try: 66 | # Load the template 67 | template = load_template(template_dir, template_name) 68 | 69 | # Ensure the output directory exists 70 | output_dir = os.path.dirname(output_path) 71 | if not os.path.exists(output_dir): 72 | os.makedirs(output_dir, exist_ok=True) 73 | 74 | # Write the template 75 | write_template(template, output_path, context) 76 | return output_path 77 | 78 | except Exception as e: 79 | print(f"Error populating template: {output_path}, {e}") 80 | raise e 81 | -------------------------------------------------------------------------------- /builder/main.py: -------------------------------------------------------------------------------- 1 | import typer 2 | 3 | from builder.cli.app import app as app_cli 4 | from builder.cli.config import app as config_cli 5 | from builder.cli.data import app as data_cli 6 | from builder.cli.db import app as db_cli 7 | 8 | # Initialize the main Typer application 9 | app = typer.Typer() 10 | 11 | # Add subcommands for creating applications 12 | app.add_typer( 13 | app_cli, 14 | name="app", 15 | help="Create a FastAPI backend and/or React frontend from an input yaml config.", 16 | ) 17 | # Add subcommands for database migrations 18 | app.add_typer( 19 | db_cli, 20 | name="db", 21 | help="Create and apply migrations to the database for any models that have been created.", 22 | ) 23 | # Add subcommands for configs 24 | app.add_typer( 25 | config_cli, 26 | name="config", 27 | help=( 28 | "Interactively create a configuration file that can then be used for generating a FastAPI backend and " 29 | "React frontend." 30 | ), 31 | ) 32 | # Add subcommands for test data 33 | app.add_typer( 34 | data_cli, 35 | name="data", 36 | help="Generate fake data for the service using Faker (https://faker.readthedocs.io/).", 37 | ) 38 | 39 | 40 | if __name__ == "__main__": 41 | app() 42 | -------------------------------------------------------------------------------- /builder/managers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/managers/__init__.py -------------------------------------------------------------------------------- /builder/managers/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/managers/db/__init__.py -------------------------------------------------------------------------------- /builder/managers/db/constants.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Define the environment variable names for the database connection 4 | DB_HOST_ENV = "DB_HOST" 5 | DB_PORT_ENV = "DB_PORT" 6 | DB_USER_ENV = "DB_USER" 7 | DB_NAME_ENV = "DB_NAME" 8 | DB_PASSWORD_ENV = "DB_PASSWORD" 9 | ALL_ENVS = [DB_HOST_ENV, DB_PORT_ENV, DB_USER_ENV, DB_NAME_ENV, DB_PASSWORD_ENV] 10 | 11 | # Pull in environment vars for MYSQL or POSTGRES 12 | DB_HOST = os.getenv(DB_HOST_ENV) 13 | DB_PORT = os.getenv(DB_PORT_ENV) 14 | DB_USER = os.getenv(DB_USER_ENV) 15 | DB_NAME = os.getenv(DB_NAME_ENV) 16 | DB_PASSWORD = os.getenv(DB_PASSWORD_ENV) 17 | ALL_VARS = [DB_HOST, DB_PORT, DB_USER, DB_NAME, DB_PASSWORD] 18 | 19 | DB_TYPES = ["postgres", "mysql"] 20 | 21 | 22 | def get_url(db_type: str) -> str: 23 | """Get the database URL from the environment variables""" 24 | # Validate that all environment variables are set 25 | if not all(v is not None for v in ALL_VARS): 26 | message = f"ERROR: Missing environment variables: {', '.join(ALL_VARS)}" 27 | print(message) 28 | raise ValueError(message) 29 | 30 | # Validate the database type 31 | if db_type not in DB_TYPES: 32 | message = f"ERROR: Unsupported database type: {db_type}" 33 | print(message) 34 | raise ValueError(message) 35 | 36 | # Return the database URL based on the type 37 | if db_type == "postgres": 38 | return f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 39 | elif db_type == "mysql": 40 | return f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 41 | -------------------------------------------------------------------------------- /builder/managers/linting/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/managers/linting/__init__.py -------------------------------------------------------------------------------- /builder/managers/linting/manager.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Dict 3 | 4 | from builder.models import ServiceConfig 5 | from builder.utils import run_command 6 | 7 | 8 | class LintingManager: 9 | """Class to handle linting operations for different parts of a service based on its configuration.""" 10 | 11 | def __init__(self, config: ServiceConfig): 12 | """ 13 | Initialize the LintingManager with the service configuration and output directory. 14 | Args: 15 | config (ServiceConfig): The configuration for the service. 16 | """ 17 | # Set the configuration and output directory 18 | self.config = config 19 | self.output_dir = config.output_dir 20 | 21 | # Set the frontend and backend directories 22 | self.frontend_dir = os.path.join( 23 | self.output_dir, config.service_info.name, "src" 24 | ) 25 | self.backend_dir = os.path.join(self.output_dir, "backend", "src") 26 | 27 | def lint_code(self, directory: str, tools: Dict): 28 | """ 29 | Lint the code in the specified directory using given tools. 30 | Args: 31 | directory (str): The directory where linting needs to be performed. 32 | tools (dict): A dictionary where keys are the linting tools and values are the command options. 33 | Example: {'prettier': '--write', 'eslint': '--fix'} 34 | """ 35 | for tool, options in tools.items(): 36 | command = f"{tool} {options} ." 37 | print(f"Linting directory: {directory} with command `{command}`") 38 | run_command(cmd=command, cwd=directory, show_output=True) 39 | 40 | def lint_all(self): 41 | """Lint all parts of the service based on the configuration.""" 42 | self.lint_frontend() 43 | self.lint_backend() 44 | 45 | def lint_frontend(self): 46 | """Lint frontend-specific code using tools like Prettier and ESLint.""" 47 | tools = {"npx prettier": "--write", "npx eslint": "--fix"} 48 | self.lint_code(self.frontend_dir, tools) 49 | 50 | def lint_backend(self): 51 | """Lint backend-specific code using tools like Black and isort.""" 52 | tools = {"poetry run black": "", "poetry run isort": ""} 53 | self.lint_code(self.backend_dir, tools) 54 | -------------------------------------------------------------------------------- /builder/models/__init__.py: -------------------------------------------------------------------------------- 1 | from builder.models.configs import * 2 | from builder.models.db import * 3 | from builder.models.enum import * 4 | -------------------------------------------------------------------------------- /builder/models/db.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Any, Dict 3 | 4 | from pydantic import BaseModel, ConfigDict, Field, constr 5 | 6 | from builder.models.enum import DatabaseTypes 7 | 8 | # Relational DB drivers 9 | MYSQL_DRIVER = "mysql+pymysql" 10 | POSTGRES_DRIVER = "postgresql" 11 | 12 | # Custom type for string types that enforce a minimum length and no whitespace 13 | MinStrType = constr(strip_whitespace=True, min_length=1) 14 | 15 | 16 | class DBConfig(BaseModel): 17 | """Base class for database config.""" 18 | 19 | model_config = ConfigDict(extra="ignore", from_attributes=True) 20 | 21 | db_type: MinStrType = Field(..., description="Type of the database") 22 | config: Dict[MinStrType, Any] = Field({}, description="Database config") 23 | 24 | def __str__(self): 25 | obfuscated_config = {**self.config} 26 | if "password" in obfuscated_config: 27 | obfuscated_config["password"] = "********" 28 | if "db_uri" in obfuscated_config: 29 | obfuscated_config["db_uri"] = "********" 30 | return f""" 31 | DBConfig( 32 | db_type={self.db_type}, 33 | config={obfuscated_config} 34 | ) 35 | """ 36 | 37 | 38 | class RelationalDBConfig(DBConfig): 39 | """Config for a relational database setup.""" 40 | 41 | db_driver: MinStrType = Field(..., description="Database driver") 42 | host_env: MinStrType = Field(..., description="Environment variable for the host") 43 | port_env: MinStrType = Field(..., description="Environment variable for the port") 44 | user_env: MinStrType = Field(..., description="Environment variable for the user") 45 | password_env: MinStrType = Field( 46 | ..., description="Environment variable for the password" 47 | ) 48 | db_name_env: MinStrType = Field( 49 | ..., description="Environment variable for the database name" 50 | ) 51 | 52 | def __init__(self, **data): 53 | """Initialize the relational database config.""" 54 | # Check for valid db_type 55 | if data["db_type"] not in DatabaseTypes.choices(): 56 | raise ValueError(f"db_type must be one of {DatabaseTypes.choices()}") 57 | 58 | # Set the driver based on the db_type 59 | if data["db_type"] == DatabaseTypes.MYSQL.value: 60 | data["db_driver"] = MYSQL_DRIVER 61 | elif data["db_type"] == DatabaseTypes.POSTGRES.value: 62 | data["db_driver"] = POSTGRES_DRIVER 63 | 64 | # Load the environment variables 65 | data["config"] = { 66 | "host": os.getenv(data["host_env"]), 67 | "port": os.getenv(data["port_env"]), 68 | "user": os.getenv(data["user_env"]), 69 | "password": os.getenv(data["password_env"]), 70 | "db_name": os.getenv(data["db_name_env"]), 71 | } 72 | 73 | # Call the parent constructor 74 | super().__init__(**data) 75 | 76 | def __str__(self): 77 | obfuscated_config = {**self.config, "password": "********", "host": "********"} 78 | return f""" 79 | RelationalDBConfig( 80 | db_type={self.db_type}, 81 | db_driver={self.db_driver}, 82 | config={obfuscated_config}, 83 | host_env={self.host_env}, 84 | port_env={self.port_env}, 85 | user_env={self.user_env}, 86 | password_env={self.password_env}, 87 | db_name_env={self.db_name_env} 88 | ) 89 | """ 90 | -------------------------------------------------------------------------------- /builder/models/enum.py: -------------------------------------------------------------------------------- 1 | import enum 2 | 3 | 4 | class DatabaseTypes(enum.Enum): 5 | """Database types""" 6 | 7 | POSTGRES: str = "postgres" 8 | MYSQL: str = "mysql" 9 | 10 | @classmethod 11 | def choices(cls): 12 | return [choice.value for choice in cls] 13 | 14 | 15 | class FieldDataType(enum.Enum): 16 | """Field data types""" 17 | 18 | STRING: str = "str" 19 | INTEGER: str = "int" 20 | FLOAT: str = "float" 21 | BOOLEAN: str = "bool" 22 | LIST: str = "list" 23 | DICT: str = "dict" 24 | DATETIME: str = "datetime" 25 | 26 | @classmethod 27 | def choices(cls): 28 | return [choice.value for choice in cls] 29 | -------------------------------------------------------------------------------- /builder/models/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/models/tests/__init__.py -------------------------------------------------------------------------------- /builder/models/tests/test_configs.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from builder.models.configs import FieldDefinition, ModelConfig 4 | from builder.models.enum import FieldDataType 5 | 6 | 7 | def test_model_config(): 8 | # Test simple 9 | model = ModelConfig(name="User", fields=[FieldDefinition(name="name", type="str")]) 10 | assert model.model_id_var_name == "user_id" 11 | assert model.manager_name == "UserManager" 12 | assert model.manager_var_name == "user_manager" 13 | 14 | 15 | def test_model_config_validate_type(): 16 | # Invalid 17 | with pytest.raises(ValueError): 18 | ModelConfig(name="User", fields=[FieldDefinition(name="name", type="string")]) 19 | # Valid 20 | for choice in FieldDataType: 21 | ModelConfig( 22 | name="User", fields=[FieldDefinition(name="name", type=choice.value)] 23 | ) 24 | 25 | 26 | def test_model_config_validate_default(): 27 | # Invalid 28 | with pytest.raises(ValueError): 29 | config = ModelConfig( 30 | name="User", 31 | fields=[FieldDefinition(name="name", type="int", default="test")], 32 | ) 33 | 34 | # Valid String 35 | fd = FieldDefinition(name="name", type="str", default="test") 36 | assert fd.default == "test" 37 | 38 | # Valid Int 39 | fd = FieldDefinition(name="name", type="int", default="1") 40 | assert fd.default == 1 41 | fd = FieldDefinition(name="name", type="int", default=1) 42 | assert fd.default == 1 43 | 44 | # Valid Float 45 | fd = FieldDefinition(name="name", type="float", default="1.0") 46 | assert fd.default == 1.0 47 | fd = FieldDefinition(name="name", type="float", default=1.0) 48 | assert fd.default == 1.0 49 | 50 | # Valid Bool 51 | fd = FieldDefinition(name="name", type="bool", default="true") 52 | assert fd.default == True 53 | fd = FieldDefinition(name="name", type="bool", default=True) 54 | assert fd.default == True 55 | fd = FieldDefinition(name="name", type="bool", default="false") 56 | assert fd.default == False 57 | fd = FieldDefinition(name="name", type="bool", default=False) 58 | assert fd.default == False 59 | 60 | # Valid List 61 | fd = FieldDefinition(name="name", type="list", default=[]) 62 | assert fd.default == [] 63 | fd = FieldDefinition(name="name", type="list", default=[1, 2, 3]) 64 | assert fd.default == [1, 2, 3] 65 | 66 | # Valid Dict 67 | fd = FieldDefinition(name="name", type="dict", default={}) 68 | assert fd.default == {} 69 | fd = FieldDefinition(name="name", type="dict", default={"key": "value"}) 70 | assert fd.default == {"key": "value"} 71 | 72 | # Valid None 73 | fd = FieldDefinition(name="name", type="str", default=None) 74 | assert fd.default == None 75 | fd = FieldDefinition(name="name", type="int", default="None") 76 | assert fd.default == None 77 | -------------------------------------------------------------------------------- /builder/models/version.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import yaml 4 | from pydantic import BaseModel 5 | 6 | from builder.models import ServiceConfig 7 | from builder.models.enum import DatabaseTypes 8 | 9 | 10 | class ConfigVersion(BaseModel): 11 | """Version information for the configuration file.""" 12 | 13 | # Version Id 14 | version: str 15 | 16 | # Service configuration 17 | service_config: ServiceConfig 18 | 19 | # Configuration file path 20 | config_file: str 21 | 22 | # Creation date 23 | created_at: str 24 | 25 | def to_file(self, file_path: str): 26 | """Writes config to a YAML file""" 27 | # If the directory does not exist, create it 28 | if not os.path.exists(file_path): 29 | os.makedirs(os.path.dirname(file_path), exist_ok=True) 30 | 31 | # Obfuscate the database password 32 | config_dict = self.model_dump() 33 | if self.database.db_type in DatabaseTypes.choices(): 34 | config_dict["database"]["config"]["password"] = "********" 35 | config_dict["database"]["config"]["host"] = "********" 36 | else: 37 | raise ValueError(f"Invalid db_type: {self.database.db_type}") 38 | 39 | # Write the config to the file 40 | with open(file_path, "w") as file: 41 | yaml.dump(config_dict, file) 42 | 43 | def from_file(file_path: str): 44 | """Reads config from a YAML file""" 45 | # Check if the file exists 46 | if not os.path.exists(file_path): 47 | raise FileNotFoundError(f"Config file not found at {file_path}") 48 | # Read the config from the file 49 | with open(file_path, "r") as file: 50 | data = yaml.safe_load(file) 51 | return ConfigVersion(**data) 52 | -------------------------------------------------------------------------------- /builder/openapi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/openapi/__init__.py -------------------------------------------------------------------------------- /builder/openapi/export.py: -------------------------------------------------------------------------------- 1 | # extract-openapi.py 2 | import json 3 | import os 4 | import sys 5 | 6 | import yaml 7 | from uvicorn.importer import import_from_string 8 | 9 | from builder.constants import CODEGEN_DIR_NAME, OPENAPI_SPEC_FN, SERVICE_NAME 10 | 11 | 12 | def export_openapi(output_dir: str) -> str: 13 | """Export the OpenAPI spec from a FastAPI app 14 | Args: 15 | output_dir (str): The app directory 16 | Returns: 17 | str: The output file 18 | """ 19 | # Add the application directory to the path 20 | if output_dir is not None: 21 | sys.path.insert(0, output_dir) 22 | 23 | # Import the app 24 | app = import_from_string(SERVICE_NAME) 25 | openapi = app.openapi() 26 | 27 | # Write the spec to a file 28 | openapi_spec_file = os.path.join(output_dir, OPENAPI_SPEC_FN) 29 | with open(openapi_spec_file, "w") as f: 30 | if openapi_spec_file.endswith(".json"): 31 | json.dump(openapi, f, indent=2) 32 | else: 33 | yaml.dump(openapi, f, sort_keys=False) 34 | 35 | # Return the output file 36 | return openapi_spec_file 37 | -------------------------------------------------------------------------------- /builder/templates/backend/docker/.dockerignore: -------------------------------------------------------------------------------- 1 | # Include any files or directories that you don't want to be copied to your 2 | # container here (e.g., local build artifacts, temporary files, etc.). 3 | # 4 | # For more help, visit the .dockerignore file reference guide at 5 | # https://docs.docker.com/go/build-context-dockerignore/ 6 | 7 | **/.DS_Store 8 | **/__pycache__ 9 | **/.venv 10 | **/.classpath 11 | **/.dockerignore 12 | **/.env 13 | **/.git 14 | **/.gitignore 15 | **/.project 16 | **/.settings 17 | **/.toolstarget 18 | **/.vs 19 | **/.vscode 20 | **/*.*proj.user 21 | **/*.dbmdl 22 | **/*.jfm 23 | **/bin 24 | **/charts 25 | **/docker-compose* 26 | **/compose* 27 | **/Dockerfile* 28 | **/node_modules 29 | **/npm-debug.log 30 | **/obj 31 | **/secrets.dev.yaml 32 | **/values.dev.yaml 33 | LICENSE 34 | README.md 35 | -------------------------------------------------------------------------------- /builder/templates/backend/docker/.env: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/templates/backend/docker/.env -------------------------------------------------------------------------------- /builder/templates/backend/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | # Comments are provided throughout this file to help you get started. 4 | # If you need more help, visit the Dockerfile reference guide at 5 | # https://docs.docker.com/go/dockerfile-reference/ 6 | 7 | # Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7 8 | 9 | ARG PYTHON_VERSION=3.12.2 10 | FROM python:${PYTHON_VERSION}-slim as base 11 | 12 | # Prevents Python from writing pyc files. 13 | ENV PYTHONDONTWRITEBYTECODE=1 14 | 15 | # Keeps Python from buffering stdout and stderr to avoid situations where 16 | # the application crashes without emitting any logs due to buffering. 17 | ENV PYTHONUNBUFFERED=1 18 | 19 | WORKDIR /app 20 | 21 | # Create a non-privileged user that the app will run under. 22 | # See https://docs.docker.com/go/dockerfile-user-best-practices/ 23 | ARG UID=10001 24 | RUN adduser \ 25 | --disabled-password \ 26 | --gecos "" \ 27 | --home "/nonexistent" \ 28 | --shell "/sbin/nologin" \ 29 | --no-create-home \ 30 | --uid "${UID}" \ 31 | appuser 32 | 33 | # Copy over the poetry files and install the dependencies. 34 | COPY pyproject.toml poetry.lock ./ 35 | COPY requirements.txt ./ 36 | 37 | # Copy over environment variables from user environment 38 | COPY .env ./ 39 | 40 | # Load environment variables 41 | RUN set -o allexport; source .env; set +o allexport 42 | 43 | # Download dependencies as a separate step to take advantage of Docker's caching. 44 | # Leverage a cache mount to /root/.cache/pip to speed up subsequent builds. 45 | # Leverage a bind mount to requirements.txt to avoid having to copy them into 46 | # into this layer. 47 | RUN --mount=type=cache,target=/root/.cache/pip \ 48 | --mount=type=bind,source=requirements.txt,target=requirements.txt \ 49 | python -m pip install -r requirements.txt 50 | 51 | # Switch to the non-privileged user to run the application. 52 | USER appuser 53 | 54 | # Copy the source code into the container. 55 | COPY . . 56 | 57 | # Expose the port that the application listens on. 58 | EXPOSE 8000 59 | 60 | # Run the application. 61 | CMD uvicorn "service:app" --reload --port 8000 62 | -------------------------------------------------------------------------------- /builder/templates/backend/docker/README.Docker.md: -------------------------------------------------------------------------------- 1 | ### Building and running your application 2 | 3 | When you're ready, start your application by running: 4 | 'docker compose up --build'. 5 | 6 | Your application will be available at http://localhost:8000. 7 | 8 | ### Deploying your application to the cloud 9 | 10 | First, build your image, e.g.: 'docker build -t myapp .'. 11 | If your cloud uses a different CPU architecture than your development 12 | machine (e.g., you are on a Mac M1 and your cloud provider is amd64), 13 | you'll want to build the image for that platform, e.g.: 14 | 'docker build --platform=linux/amd64 -t myapp .'. 15 | 16 | Then, push it to your registry, e.g. 'docker push myregistry.com/myapp'. 17 | 18 | Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/) 19 | docs for more detail on building and pushing. 20 | 21 | ### References 22 | * [Docker's Python guide](https://docs.docker.com/language/python/) 23 | -------------------------------------------------------------------------------- /builder/templates/backend/docker/compose.yml: -------------------------------------------------------------------------------- 1 | # Comments are provided throughout this file to help you get started. 2 | # If you need more help, visit the Docker compose reference guide at 3 | # https://docs.docker.com/go/compose-spec-reference/ 4 | 5 | # Here the instructions define your application as a service called "server". 6 | # This service is built from the Dockerfile in the current directory. 7 | # You can add other services your application may depend on here, such as a 8 | # database or a cache. For examples, see the Awesome Compose repository: 9 | # https://github.com/docker/awesome-compose 10 | services: 11 | server: 12 | build: 13 | context: . 14 | ports: 15 | - 8000:8000 16 | 17 | # The commented out section below is an example of how to define a PostgreSQL 18 | # database that your application can use. 'depends_on' tells Docker Compose to 19 | # start the database before your application. The 'alembic-data' volume persists the 20 | # database data between container restarts. The 'alembic-password' secret is used 21 | # to set the database password. You must create 'alembic/password.txt' and add 22 | # a password of your choosing to it before running 'docker compose up'. 23 | # depends_on: 24 | # alembic: 25 | # condition: service_healthy 26 | # alembic: 27 | # image: postgres 28 | # restart: always 29 | # user: postgres 30 | # secrets: 31 | # - alembic-password 32 | # volumes: 33 | # - alembic-data:/var/lib/postgresql/data 34 | # environment: 35 | # - POSTGRES_DB=example 36 | # - POSTGRES_PASSWORD_FILE=/run/secrets/alembic-password 37 | # expose: 38 | # - 5432 39 | # healthcheck: 40 | # test: [ "CMD", "pg_isready" ] 41 | # interval: 10s 42 | # timeout: 5s 43 | # retries: 5 44 | # volumes: 45 | # alembic-data: 46 | # secrets: 47 | # alembic-password: 48 | # file: alembic/password.txt 49 | -------------------------------------------------------------------------------- /builder/templates/backend/models/model.jinja: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel, ConfigDict 2 | from pydantic.fields import FieldInfo 3 | from datetime import datetime 4 | 5 | from typing import List, Dict, Optional 6 | 7 | {% for model in models %} 8 | class {{ model.name }}(BaseModel): 9 | # Pydantic model configuration, enables from_orm and to_orm methods 10 | model_config = ConfigDict(extra='ignore', from_attributes=True) 11 | 12 | # Core model fields 13 | {% for field in model.fields %}{{ field.row }} 14 | {% endfor %} 15 | 16 | # Optional created_at and updated_at fields 17 | created_at: Optional[datetime] = FieldInfo(default=None, alias='created_at', description='The time the record was created') 18 | updated_at: Optional[datetime] = FieldInfo(default=None, alias='updated_at', description='The time the record was last updated') 19 | 20 | def to_dict(self) -> Dict: 21 | """ Convert the model to a dictionary """ 22 | return self.model() 23 | 24 | class {{ model.name }}Query(BaseModel): 25 | """ Query model for {{ model.name }} """ 26 | 27 | # Pydantic model configuration, enables from_orm and to_orm methods 28 | model_config = ConfigDict(extra='ignore', from_attributes=True) 29 | 30 | # Query model fields 31 | {% for field in model.fields %}{{ field.name }}: Optional[{{ field.type }}] = None 32 | {% endfor %} 33 | 34 | def to_dict(self) -> Dict: 35 | """ Convert the model to a dictionary """ 36 | return self.model_dump() 37 | {% endfor %} 38 | -------------------------------------------------------------------------------- /builder/templates/backend/poetry/toml.jinja: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "{{ name }}" 3 | version = "{{version}}" 4 | description = "{{ description }}" 5 | authors = ["{{ author }}"] 6 | readme = "README.md" 7 | 8 | [tool.poetry.dependencies] 9 | {{dependency_rows}} 10 | 11 | [build-system] 12 | requires = ["poetry-core"] 13 | build-backend = "poetry.core.masonry.api" 14 | -------------------------------------------------------------------------------- /builder/templates/backend/readme/README.jinja: -------------------------------------------------------------------------------- 1 | # Generated Service 2 | 3 | This service was generated using the FastAPI Generation tool. All dependencies are managed using Poetry. The database 4 | migrations are managed depending on the database type that was used in the service generate. 5 | 6 | 7 | ## Poetry Commands 8 | 9 | #### Install and update the Poetry dependencies: 10 | ```bash 11 | % poetry install && poetry update 12 | ``` 13 | #### Running the Service 14 | ```bash 15 | % poetry run uvicorn service:app --reload --port 8000 16 | ``` 17 | #### Adding New Dependencies 18 | ```bash 19 | % poetry add 20 | ``` 21 | 22 | ## Alembic Database Migrations 23 | 24 | #### Create a new migration: 25 | ```bash 26 | % poetry run alembic revision --autogenerate -m "migration message" 27 | ``` 28 | #### Apply the migration: 29 | ```bash 30 | % poetry run alembic upgrade head 31 | ``` -------------------------------------------------------------------------------- /builder/templates/backend/service/service.jinja: -------------------------------------------------------------------------------- 1 | import logging 2 | import uvicorn 3 | import argparse 4 | 5 | from fastapi import FastAPI 6 | from fastapi.middleware.cors import CORSMiddleware 7 | 8 | {% for model in models %}from src.{{ model.name.lower() }}_routes import router as {{ model.name.lower() }}_rotes 9 | {% endfor %} 10 | 11 | from src.db.utils import ensure_all_tables 12 | 13 | # Create FastAPI App and Allow CORS 14 | app = FastAPI() 15 | app.add_middleware( 16 | CORSMiddleware, 17 | allow_origins=["*"], 18 | allow_credentials=True, 19 | allow_methods=["*"], 20 | allow_headers=["*"], 21 | ) 22 | 23 | # Add startup event to ensure all tables are created 24 | @app.on_event("startup") 25 | async def startup_event(): 26 | """ Startup Event """ 27 | await ensure_all_tables() 28 | 29 | # Default Host and Port 30 | DEFAULT_HOST = "localhost" 31 | DEFAULT_PORT = 8000 32 | 33 | # Add the API Routes 34 | {% for model in models %}app.include_router({{ model.name.lower() }}_rotes, tags=["{{ model.name }}"]) 35 | {% endfor %} 36 | 37 | ######################################################################################################################## 38 | # Root and Health Endpoints 39 | ######################################################################################################################## 40 | 41 | 42 | @app.get("/") 43 | async def root(): 44 | """ Root Endpoint """ 45 | return {"message": "Welcome to {{ service_name }} API"} 46 | 47 | 48 | @app.get("/health") 49 | async def health(): 50 | """ Health Endpoint """ 51 | return {"message": "Healthy"} 52 | 53 | @app.get("/ready") 54 | async def health(): 55 | """ Ready Endpoint """ 56 | return {"message": "Ready"} 57 | 58 | ######################################################################################################################## 59 | # Logging 60 | ######################################################################################################################## 61 | 62 | 63 | def init_logging(): 64 | """ Initialize Logging """ 65 | logging.basicConfig(level=logging.INFO) 66 | logging.getLogger("uvicorn").setLevel(logging.INFO) 67 | logging.getLogger("uvicorn.error").setLevel(logging.INFO) 68 | logging.getLogger("uvicorn.access").setLevel(logging.INFO) 69 | 70 | 71 | ######################################################################################################################## 72 | # Parse Command Line Arguments 73 | ######################################################################################################################## 74 | 75 | 76 | def parse_args(): 77 | """ Parse Command Line Arguments """ 78 | parser = argparse.ArgumentParser(description="Run the FastAPI Server") 79 | parser.add_argument( 80 | "--host", 81 | "-h", 82 | type=str, 83 | default=DEFAULT_HOST, 84 | help="Host to run the server on" 85 | ) 86 | parser.add_argument( 87 | "--port", 88 | "-p", 89 | type=int, 90 | default=DEFAULT_PORT, 91 | help="Port to run the server on" 92 | ) 93 | return parser.parse_args() 94 | 95 | 96 | ######################################################################################################################## 97 | # Run the Server 98 | ######################################################################################################################## 99 | 100 | 101 | if __name__ == "__main__": 102 | # Initialize Logging 103 | init_logging() 104 | # Parse Command Line Arguments 105 | args = parse_args() 106 | # Start the server 107 | uvicorn.run(app, host=args.host, port=args.port) 108 | -------------------------------------------------------------------------------- /builder/templates/databases/alembic/alembic/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. 2 | -------------------------------------------------------------------------------- /builder/templates/databases/alembic/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/templates/databases/alembic/alembic/__init__.py -------------------------------------------------------------------------------- /builder/templates/databases/alembic/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from typing import Sequence, Union 9 | 10 | from alembic import op 11 | import sqlalchemy as sa 12 | ${imports if imports else ""} 13 | 14 | # revision identifiers, used by Alembic. 15 | revision: str = ${repr(up_revision)} 16 | down_revision: Union[str, None] = ${repr(down_revision)} 17 | branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} 18 | depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} 19 | 20 | 21 | def upgrade() -> None: 22 | ${upgrades if upgrades else "pass"} 23 | 24 | 25 | def downgrade() -> None: 26 | ${downgrades if downgrades else "pass"} 27 | -------------------------------------------------------------------------------- /builder/templates/databases/alembic/constants.jinja: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Define the environment variable names for the database connection 4 | DB_HOST_ENV = "{{ db_config.host_env }}" 5 | DB_PORT_ENV = "{{ db_config.port_env }}" 6 | DB_USER_ENV = "{{ db_config.user_env }}" 7 | DB_NAME_ENV = "{{ db_config.db_name_env }}" 8 | DB_PASSWORD_ENV = "{{ db_config.password_env }}" 9 | ALL_ENVS = [DB_HOST_ENV, DB_PORT_ENV, DB_USER_ENV, DB_NAME_ENV, DB_PASSWORD_ENV] 10 | 11 | # Pull in environment vars for MYSQL or POSTGRES 12 | DB_HOST = os.getenv(DB_HOST_ENV) 13 | DB_PORT = os.getenv(DB_PORT_ENV) 14 | DB_USER = os.getenv(DB_USER_ENV) 15 | DB_NAME = os.getenv(DB_NAME_ENV) 16 | DB_PASSWORD = os.getenv(DB_PASSWORD_ENV) 17 | ALL_VARS = [DB_HOST, DB_PORT, DB_USER, DB_NAME, DB_PASSWORD] 18 | 19 | # Pull in environment var for DB_TYPE 20 | DB_TYPE = "{{ db_config.db_type }}" 21 | 22 | def get_url() -> str: 23 | """Get the database URL from the environment variables""" 24 | # Validate that all environment variables are set 25 | if not all(v is not None for v in ALL_VARS): 26 | raise ValueError( 27 | f"Missing environment variables: {', '.join(ALL_VARS)}" 28 | ) 29 | 30 | # Validate that the DB_TYPE is set 31 | if DB_TYPE is None: 32 | raise ValueError("DB_TYPE environment variable must be set") 33 | 34 | # Return the database URL based on the type 35 | if DB_TYPE == "postgres": 36 | return f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 37 | elif DB_TYPE == "mysql": 38 | return f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 39 | else: 40 | raise ValueError( 41 | f"Invalid database type {DB_TYPE} must be 'postgres' or 'mysql'" 42 | ) 43 | -------------------------------------------------------------------------------- /builder/templates/databases/alembic/models.jinja: -------------------------------------------------------------------------------- 1 | from sqlalchemy import JSON, Boolean, Column, DateTime, Integer, String, Text, Float 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.sql import func 4 | from sqlalchemy.schema import MetaData 5 | 6 | Base = declarative_base() 7 | 8 | {% for model in models %} 9 | class DB{{ model.name }}(Base): 10 | 11 | # Define Table Name 12 | __tablename__ = '{{ model.name.lower() }}' 13 | 14 | # Define Columns 15 | {% for field in model.fields %} 16 | {{ field.name.lower() }} = {{ field.alembic_db_def }} 17 | {% endfor %} 18 | 19 | # Define Updated and Created At (Auto) (Could be used for DB Replication) 20 | created_at = Column(DateTime, default=func.now()) 21 | updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) 22 | 23 | {% endfor %} 24 | -------------------------------------------------------------------------------- /builder/templates/databases/alembic/utils.jinja: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from src.db.constants import get_url 3 | from src.db.models import ( 4 | {% for db_model in db_models %} 5 | {{ db_model }}, 6 | {% endfor %} 7 | ) 8 | 9 | 10 | async def ensure_all_tables(): 11 | """Create all tables if they do not exist""" 12 | engine = create_engine(get_url()) 13 | # Create the tables 14 | {% for db_model in db_models %} 15 | print(f"Ensuring table for {{ db_model }}") 16 | {{ db_model }}.metadata.create_all(engine) 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /builder/templates/frontend/components/home.tsx: -------------------------------------------------------------------------------- 1 | // Simple home page 2 | import React from 'react'; 3 | import { Link } from 'react-router-dom'; 4 | import Box from '@mui/material/Box'; 5 | import Typography from '@mui/material/Typography'; 6 | import Divider from '@mui/material/Divider'; 7 | 8 | export function Home() { 9 | return ( 10 | 11 |
12 | 13 | Welcome to the {{ config.service_info.name }}! 14 | 15 | 16 | 17 | To get started, click on one of the links below to view the different model pages! 18 | 19 | 20 | 21 | Models 22 | 23 | 24 | {% for model in config.models %} 25 | 26 | {{ model.name }}s Page 27 | 28 | {% endfor %} 29 |
30 |
31 | ); 32 | } 33 | 34 | export default Home; 35 | -------------------------------------------------------------------------------- /builder/templates/frontend/components/layout.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Outlet } from 'react-router-dom'; 3 | 4 | // MUI Components 5 | import AppBar from '@mui/material/AppBar'; 6 | import Box from '@mui/material/Box'; 7 | import Toolbar from '@mui/material/Toolbar'; 8 | import Typography from '@mui/material/Typography'; 9 | import Button from '@mui/material/Button'; 10 | 11 | function Layout() { 12 | 13 | // Define the pages and their routes 14 | const [pages_map] = React.useState>({ 15 | 'Home': '/home', 16 | {% for model in config.models %} 17 | '{{ model.name }}': '/{{ model.name|lower }}', 18 | {% endfor %} 19 | }); 20 | 21 | // Handle navigation to the page 22 | const handleNavToPage = (page: string) => { 23 | console.log('Navigating to page: ' + page) 24 | window.location.href = pages_map[page]; 25 | } 26 | 27 | // Render 28 | return ( 29 | <> 30 | 55 | 56 | 57 | ); 58 | } 59 | export default Layout; 60 | -------------------------------------------------------------------------------- /builder/templates/frontend/components/no_page.tsx: -------------------------------------------------------------------------------- 1 | const NoPage = () => { 2 | return

404: Page could not be found!

; 3 | }; 4 | 5 | export default NoPage; 6 | -------------------------------------------------------------------------------- /builder/templates/frontend/components/utils.tsx: -------------------------------------------------------------------------------- 1 | import { Configuration } from "../api"; 2 | {% for model in config.models %} 3 | import { {{ model.name }}Api } from "../api"; 4 | {% endfor %} 5 | 6 | const basePath = "http://localhost:8000"; 7 | 8 | // Helper function to parse fields based on their type prior to sending to the API 9 | const parseField = (field: string, type: string) => { 10 | switch (type) { 11 | case 'string': 12 | return field; 13 | case 'number': 14 | return Number(field); 15 | case 'boolean': 16 | return field === 'true'; 17 | case 'date': 18 | return new Date(field); 19 | case 'datetime': 20 | return new Date(field); 21 | case 'array': 22 | return field.split(',').map(item => (item as string).trim()); 23 | case 'list': 24 | return field.split(',').map(item => (item as string).trim()); 25 | case 'object': 26 | return JSON.parse(field); 27 | default: 28 | return field; 29 | } 30 | } 31 | 32 | {% for model in config.models %} 33 | // Fetch API client for {{ model.name }} 34 | const get{{ model.name }}APIClient = () => { 35 | const apiConfig = new Configuration({ 36 | basePath: basePath 37 | }); 38 | return new {{ model.name }}Api(apiConfig); 39 | } 40 | {% endfor %} 41 | 42 | // Export all API clients and utility functions 43 | export { 44 | {% for model in config.models %} 45 | get{{ model.name }}APIClient, 46 | {% endfor %} 47 | parseField 48 | } 49 | -------------------------------------------------------------------------------- /builder/templates/frontend/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import reportWebVitals from './reportWebVitals'; 5 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 6 | 7 | // Import Models 8 | {% for model in config.models %} 9 | import {{ model.name }}Page from './components/{{ model.name|lower }}_page'; 10 | {% endfor %} 11 | 12 | // Layout and other pages 13 | import Home from './components/Home'; 14 | import Layout from './components/Layout'; 15 | 16 | export default function HomePage() { 17 | return ( 18 | 19 | 20 | }> 21 | 22 | {/* Add other pages here */} 23 | } /> 24 | } /> 25 | 26 | {/* Add other pages here */} 27 | {% for model in config.models %} 28 | } /> 29 | {% endfor %} 30 | 31 | 32 | 33 | 34 | ); 35 | } 36 | 37 | const root = ReactDOM.createRoot( 38 | document.getElementById('root') as HTMLElement 39 | ); 40 | 41 | root.render(); 42 | 43 | // If you want to start measuring performance in your app, pass a function 44 | // to log results (for example: reportWebVitals(console.log)) 45 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 46 | reportWebVitals(); 47 | -------------------------------------------------------------------------------- /builder/test_data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/test_data/__init__.py -------------------------------------------------------------------------------- /builder/test_data/create_fake_data.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from typing import Dict 4 | 5 | from rich import print 6 | 7 | from builder.models.configs import ServiceConfig 8 | 9 | DATA_DIR: str = "data" 10 | 11 | 12 | def create_fake_data(config: ServiceConfig, num: int = 5, no_ids: bool = False) -> Dict: 13 | """Create fake data for the service 14 | 15 | Args: 16 | config (ServiceConfig): Service configuration 17 | num (int, optional): Number of fake data entries to create. Defaults to 5. 18 | no_ids (bool, optional): Flag to exclude the IDs from the fake data. Defaults to False. 19 | Returns: 20 | Dict: Dictionary of model names and their corresponding fake data file paths 21 | """ 22 | data = {} 23 | output_dir = config.output_dir 24 | 25 | # Create the output directory and data directory 26 | data_dir = os.path.join(output_dir, DATA_DIR) 27 | os.makedirs(data_dir, exist_ok=True) 28 | print(f"Creating fake data at {data_dir}") 29 | 30 | # Get model list and create fake data 31 | models = config.models 32 | for model in models: 33 | data[model.name] = [model.create_fake_data(no_ids=no_ids) for _ in range(num)] 34 | print(f"Faked data for {model.name} with {num} entries: {data[model.name][0]}") 35 | 36 | # Output the fake data each to a JSON file 37 | result_files = {} 38 | for model_name, model_data in data.items(): 39 | output_file = os.path.join(data_dir, f"{model_name}.json") 40 | print(f"Creating fake data for {model_name} at {output_file}") 41 | with open(output_file, "w") as f: 42 | json.dump(model_data, f, indent=2) 43 | result_files[model_name] = output_file 44 | 45 | # Return the output directory of the fake data 46 | return result_files 47 | -------------------------------------------------------------------------------- /builder/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/builder/tests/__init__.py -------------------------------------------------------------------------------- /builder/tests/test_app_manager.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import os 3 | import tempfile 4 | 5 | import pytest 6 | 7 | from builder.app_manager import ApplicationManager 8 | from builder.config.parse import load_and_validate_config 9 | from builder.models.configs import ServiceConfig 10 | 11 | # Path to the test restaurant configuration file 12 | TEST_RESTAURANT_CONFIG_PATH: str = os.path.abspath( 13 | "builder/tests/configs/restaurant.yaml" 14 | ) 15 | # Load and validate the configuration 16 | TEST_RESTAURANT_CONFIG: ServiceConfig = load_and_validate_config( 17 | TEST_RESTAURANT_CONFIG_PATH 18 | ) 19 | 20 | 21 | @pytest.fixture 22 | def app_manager(): 23 | """Fixture to create an instance of ApplicationManager with a temporary output directory.""" 24 | with tempfile.TemporaryDirectory() as output_dir: 25 | config = copy.deepcopy(TEST_RESTAURANT_CONFIG) 26 | config.output_dir = output_dir 27 | manager = ApplicationManager(config=config) 28 | yield manager 29 | 30 | 31 | def test_app_manager_create(app_manager): 32 | """Test to create the application code and ensure cleanup post tests.""" 33 | app_manager.generate() 34 | 35 | 36 | def test_app_manager_full_stack(app_manager): 37 | """Test to generate full stack of the application.""" 38 | app_manager.generate_full_stack() 39 | 40 | 41 | def test_app_manager_backend_frontend(app_manager): 42 | """Test to generate separately backend and frontend of the application.""" 43 | app_manager.generate_backend() 44 | app_manager.generate_frontend() 45 | 46 | 47 | def test_app_manager_regenerate(app_manager): 48 | """Test to regenerate the application components.""" 49 | app_manager.regenerate() 50 | app_manager.regenerate_frontend() 51 | app_manager.regenerate_backend() 52 | -------------------------------------------------------------------------------- /builder/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | from rich import print 5 | 6 | from builder.constants import VERBOSE 7 | 8 | 9 | def clear_directory(directory: str) -> None: 10 | """Safely clear a directory. 11 | 12 | Args: 13 | directory (str): The directory to clear 14 | """ 15 | try: 16 | # If the directory exists, clear it 17 | if os.path.exists(directory): 18 | run_command(f"rm -rf {directory}", tabs=2) 19 | 20 | # Create the directory 21 | os.makedirs(directory, exist_ok=True) 22 | except Exception as e: 23 | print(f"Error clearing directory: {directory}, {e}") 24 | raise e 25 | 26 | 27 | def clear_file(file_path: str) -> None: 28 | """Safely clear a file. 29 | 30 | Args: 31 | file_path (str): The file to clear 32 | """ 33 | try: 34 | # If the file exists, clear it 35 | if os.path.exists(file_path): 36 | run_command(f"rm -f {file_path}", tabs=2) 37 | except Exception as e: 38 | print(f"Error clearing file: {file_path}, {e}") 39 | raise e 40 | 41 | 42 | def run_command( 43 | cmd: str, cwd: str = None, tabs: int = 2, show_output: bool = True 44 | ) -> subprocess.CompletedProcess: 45 | """Run a shell command and print the output. 46 | 47 | Args: 48 | cmd (str): The shell command to run 49 | cwd (str): The current working directory 50 | tabs (int): Number of tabs to print before the command 51 | show_output (bool): Whether to show the output 52 | Returns: 53 | subprocess.CompletedProcess: The completed process 54 | """ 55 | try: 56 | # Set the arguments based on whether to show output 57 | if show_output: 58 | args = { 59 | "shell": True, 60 | "text": True, 61 | } 62 | else: 63 | args = { 64 | "shell": True, 65 | "stdout": subprocess.PIPE, 66 | "stderr": subprocess.PIPE, 67 | "text": True, 68 | } 69 | 70 | # Add cwd if provided 71 | if cwd: 72 | args["cwd"] = cwd 73 | 74 | # Run command and log output 75 | print(f"{''.join(['\t' for _ in range(tabs)])}> '{cmd}'") 76 | if VERBOSE: 77 | completed_process = subprocess.run(cmd, **args) 78 | print(completed_process.stdout) 79 | print(completed_process.stderr) 80 | else: 81 | completed_process = subprocess.run(cmd, **args) 82 | return completed_process 83 | 84 | except Exception as e: 85 | print(f"Error running command: {cmd}, {e}") 86 | raise e 87 | -------------------------------------------------------------------------------- /example/alembic/output/backend/.dockerignore: -------------------------------------------------------------------------------- 1 | # Include any files or directories that you don't want to be copied to your 2 | # container here (e.g., local build artifacts, temporary files, etc.). 3 | # 4 | # For more help, visit the .dockerignore file reference guide at 5 | # https://docs.docker.com/go/build-context-dockerignore/ 6 | 7 | **/.DS_Store 8 | **/__pycache__ 9 | **/.venv 10 | **/.classpath 11 | **/.dockerignore 12 | **/.env 13 | **/.git 14 | **/.gitignore 15 | **/.project 16 | **/.settings 17 | **/.toolstarget 18 | **/.vs 19 | **/.vscode 20 | **/*.*proj.user 21 | **/*.dbmdl 22 | **/*.jfm 23 | **/bin 24 | **/charts 25 | **/docker-compose* 26 | **/compose* 27 | **/Dockerfile* 28 | **/node_modules 29 | **/npm-debug.log 30 | **/obj 31 | **/secrets.dev.yaml 32 | **/values.dev.yaml 33 | LICENSE 34 | README.md 35 | -------------------------------------------------------------------------------- /example/alembic/output/backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | # Comments are provided throughout this file to help you get started. 4 | # If you need more help, visit the Dockerfile reference guide at 5 | # https://docs.docker.com/go/dockerfile-reference/ 6 | 7 | # Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7 8 | 9 | ARG PYTHON_VERSION=3.12.2 10 | FROM python:${PYTHON_VERSION}-slim as base 11 | 12 | # Prevents Python from writing pyc files. 13 | ENV PYTHONDONTWRITEBYTECODE=1 14 | 15 | # Keeps Python from buffering stdout and stderr to avoid situations where 16 | # the application crashes without emitting any logs due to buffering. 17 | ENV PYTHONUNBUFFERED=1 18 | 19 | WORKDIR /app 20 | 21 | # Create a non-privileged user that the app will run under. 22 | # See https://docs.docker.com/go/dockerfile-user-best-practices/ 23 | ARG UID=10001 24 | RUN adduser \ 25 | --disabled-password \ 26 | --gecos "" \ 27 | --home "/nonexistent" \ 28 | --shell "/sbin/nologin" \ 29 | --no-create-home \ 30 | --uid "${UID}" \ 31 | appuser 32 | 33 | # Copy over the poetry files and install the dependencies. 34 | COPY pyproject.toml poetry.lock ./ 35 | COPY requirements.txt ./ 36 | 37 | # Copy over environment variables from user environment 38 | COPY .env ./ 39 | 40 | # Load environment variables 41 | RUN set -o allexport; source .env; set +o allexport 42 | 43 | # Download dependencies as a separate step to take advantage of Docker's caching. 44 | # Leverage a cache mount to /root/.cache/pip to speed up subsequent builds. 45 | # Leverage a bind mount to requirements.txt to avoid having to copy them into 46 | # into this layer. 47 | RUN --mount=type=cache,target=/root/.cache/pip \ 48 | --mount=type=bind,source=requirements.txt,target=requirements.txt \ 49 | python -m pip install -r requirements.txt 50 | 51 | # Switch to the non-privileged user to run the application. 52 | USER appuser 53 | 54 | # Copy the source code into the container. 55 | COPY . . 56 | 57 | # Expose the port that the application listens on. 58 | EXPOSE 8000 59 | 60 | # Run the application. 61 | CMD uvicorn "service:app" --reload --port 8000 62 | -------------------------------------------------------------------------------- /example/alembic/output/backend/README.Docker.md: -------------------------------------------------------------------------------- 1 | ### Building and running your application 2 | 3 | When you're ready, start your application by running: 4 | 'docker compose up --build'. 5 | 6 | Your application will be available at http://localhost:8000. 7 | 8 | ### Deploying your application to the cloud 9 | 10 | First, build your image, e.g.: 'docker build -t myapp .'. 11 | If your cloud uses a different CPU architecture than your development 12 | machine (e.g., you are on a Mac M1 and your cloud provider is amd64), 13 | you'll want to build the image for that platform, e.g.: 14 | 'docker build --platform=linux/amd64 -t myapp .'. 15 | 16 | Then, push it to your registry, e.g. 'docker push myregistry.com/myapp'. 17 | 18 | Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/) 19 | docs for more detail on building and pushing. 20 | 21 | ### References 22 | * [Docker's Python guide](https://docs.docker.com/language/python/) 23 | -------------------------------------------------------------------------------- /example/alembic/output/backend/README.md: -------------------------------------------------------------------------------- 1 | # Generated Service 2 | 3 | This service was generated using the FastAPI Generation tool. All dependencies are managed using Poetry. The database 4 | migrations are managed depending on the database type that was used in the service generate. 5 | 6 | 7 | ## Poetry Commands 8 | 9 | #### Install and update the Poetry dependencies: 10 | ```bash 11 | % poetry install && poetry update 12 | ``` 13 | #### Running the Service 14 | ```bash 15 | % poetry run uvicorn service:app --reload --port 8000 16 | ``` 17 | #### Adding New Dependencies 18 | ```bash 19 | % poetry add 20 | ``` 21 | 22 | ## Alembic Database Migrations 23 | 24 | #### Create a new migration: 25 | ```bash 26 | % poetry run alembic revision --autogenerate -m "migration message" 27 | ``` 28 | #### Apply the migration: 29 | ```bash 30 | % poetry run alembic upgrade head 31 | ``` -------------------------------------------------------------------------------- /example/alembic/output/backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/backend/__init__.py -------------------------------------------------------------------------------- /example/alembic/output/backend/compose.yml: -------------------------------------------------------------------------------- 1 | # Comments are provided throughout this file to help you get started. 2 | # If you need more help, visit the Docker compose reference guide at 3 | # https://docs.docker.com/go/compose-spec-reference/ 4 | 5 | # Here the instructions define your application as a service called "server". 6 | # This service is built from the Dockerfile in the current directory. 7 | # You can add other services your application may depend on here, such as a 8 | # database or a cache. For examples, see the Awesome Compose repository: 9 | # https://github.com/docker/awesome-compose 10 | services: 11 | server: 12 | build: 13 | context: . 14 | ports: 15 | - 8000:8000 16 | 17 | # The commented out section below is an example of how to define a PostgreSQL 18 | # database that your application can use. 'depends_on' tells Docker Compose to 19 | # start the database before your application. The 'alembic-data' volume persists the 20 | # database data between container restarts. The 'alembic-password' secret is used 21 | # to set the database password. You must create 'alembic/password.txt' and add 22 | # a password of your choosing to it before running 'docker compose up'. 23 | # depends_on: 24 | # alembic: 25 | # condition: service_healthy 26 | # alembic: 27 | # image: postgres 28 | # restart: always 29 | # user: postgres 30 | # secrets: 31 | # - alembic-password 32 | # volumes: 33 | # - alembic-data:/var/lib/postgresql/data 34 | # environment: 35 | # - POSTGRES_DB=example 36 | # - POSTGRES_PASSWORD_FILE=/run/secrets/alembic-password 37 | # expose: 38 | # - 5432 39 | # healthcheck: 40 | # test: [ "CMD", "pg_isready" ] 41 | # interval: 10s 42 | # timeout: 5s 43 | # retries: 5 44 | # volumes: 45 | # alembic-data: 46 | # secrets: 47 | # alembic-password: 48 | # file: alembic/password.txt 49 | -------------------------------------------------------------------------------- /example/alembic/output/backend/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "restaurant_app" 3 | version = "1.0.0" 4 | description = "An Alembic + MySQL backed simple Reservations Service" 5 | authors = ["restaurant_app "] 6 | readme = "README.md" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.12.2" 10 | pyyaml = "^6.0.1" 11 | jinja2 = "^3.1.3" 12 | pydantic = "^2.6.4" 13 | fastapi = "^0.110.0" 14 | uvicorn = "^0.28.0" 15 | certifi = "^2024.2.2" 16 | rich = "^13.7.1" 17 | isort = "^5.13.2" 18 | black = "^24.2.0" 19 | typer = "^0.9.0" 20 | pytest = "^8.1.1" 21 | coverage = "^7.4.4" 22 | faker = "^24.7.1" 23 | alembic = "^1.13.1" 24 | sqlalchemy = "^2.0.29" 25 | pymysql = "^1.0.2" 26 | httpx = "^0.27.0" 27 | urllib3 = "^2.2.1" 28 | requests = "^2.31.0" 29 | psycopg2-binary = "^2.9.9" 30 | 31 | [build-system] 32 | requires = ["poetry-core"] 33 | build-backend = "poetry.core.masonry.api" -------------------------------------------------------------------------------- /example/alembic/output/backend/src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/backend/src/__init__.py -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/backend/src/db/__init__.py -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/alembic/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. 2 | -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/backend/src/db/alembic/__init__.py -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from typing import Sequence, Union 9 | 10 | from alembic import op 11 | import sqlalchemy as sa 12 | ${imports if imports else ""} 13 | 14 | # revision identifiers, used by Alembic. 15 | revision: str = ${repr(up_revision)} 16 | down_revision: Union[str, None] = ${repr(down_revision)} 17 | branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} 18 | depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} 19 | 20 | 21 | def upgrade() -> None: 22 | ${upgrades if upgrades else "pass"} 23 | 24 | 25 | def downgrade() -> None: 26 | ${downgrades if downgrades else "pass"} 27 | -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/constants.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Define the environment variable names for the database connection 4 | DB_HOST_ENV = "DB_HOST" 5 | DB_PORT_ENV = "DB_PORT" 6 | DB_USER_ENV = "DB_USER" 7 | DB_NAME_ENV = "DB_NAME" 8 | DB_PASSWORD_ENV = "DB_PASSWORD" 9 | ALL_ENVS = [DB_HOST_ENV, DB_PORT_ENV, DB_USER_ENV, DB_NAME_ENV, DB_PASSWORD_ENV] 10 | 11 | # Pull in environment vars for MYSQL or POSTGRES 12 | DB_HOST = os.getenv(DB_HOST_ENV) 13 | DB_PORT = os.getenv(DB_PORT_ENV) 14 | DB_USER = os.getenv(DB_USER_ENV) 15 | DB_NAME = os.getenv(DB_NAME_ENV) 16 | DB_PASSWORD = os.getenv(DB_PASSWORD_ENV) 17 | ALL_VARS = [DB_HOST, DB_PORT, DB_USER, DB_NAME, DB_PASSWORD] 18 | 19 | # Pull in environment var for DB_TYPE 20 | DB_TYPE = "mysql" 21 | 22 | 23 | def get_url() -> str: 24 | """Get the database URL from the environment variables""" 25 | # Validate that all environment variables are set 26 | if not all(v is not None for v in ALL_VARS): 27 | raise ValueError(f"Missing environment variables: {', '.join(ALL_VARS)}") 28 | 29 | # Validate that the DB_TYPE is set 30 | if DB_TYPE is None: 31 | raise ValueError("DB_TYPE environment variable must be set") 32 | 33 | # Return the database URL based on the type 34 | if DB_TYPE == "postgres": 35 | return f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 36 | elif DB_TYPE == "mysql": 37 | return f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 38 | else: 39 | raise ValueError( 40 | f"Invalid database type {DB_TYPE} must be 'postgres' or 'mysql'" 41 | ) 42 | -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/models.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import (JSON, Boolean, Column, DateTime, Float, Integer, 2 | String, Text) 3 | from sqlalchemy.ext.declarative import declarative_base 4 | from sqlalchemy.schema import MetaData 5 | from sqlalchemy.sql import func 6 | 7 | Base = declarative_base() 8 | 9 | 10 | class DBUser(Base): 11 | 12 | # Define Table Name 13 | __tablename__ = "user" 14 | 15 | # Define Columns 16 | 17 | id = Column(Integer, primary_key=True, autoincrement=True) 18 | 19 | username = Column(String(1000), nullable=False, default="") 20 | 21 | email = Column(String(1000), nullable=False, default="") 22 | 23 | phone_number = Column(String(1000), nullable=True, default="") 24 | 25 | preferences = Column(JSON, nullable=True, default=[]) 26 | 27 | role = Column(String(1000), nullable=True, default="user") 28 | 29 | # Define Updated and Created At (Auto) (Could be used for DB Replication) 30 | created_at = Column(DateTime, default=func.now()) 31 | updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) 32 | 33 | 34 | class DBRestaurant(Base): 35 | 36 | # Define Table Name 37 | __tablename__ = "restaurant" 38 | 39 | # Define Columns 40 | 41 | id = Column(Integer, primary_key=True, autoincrement=True) 42 | 43 | name = Column(String(1000), nullable=False, default="") 44 | 45 | location = Column(String(1000), nullable=False, default="") 46 | 47 | cuisine = Column(String(1000), nullable=True, default="") 48 | 49 | rating = Column(Float, nullable=True, default=None) 50 | 51 | price_range = Column(String(1000), nullable=True, default="") 52 | 53 | # Define Updated and Created At (Auto) (Could be used for DB Replication) 54 | created_at = Column(DateTime, default=func.now()) 55 | updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) 56 | 57 | 58 | class DBReservation(Base): 59 | 60 | # Define Table Name 61 | __tablename__ = "reservation" 62 | 63 | # Define Columns 64 | 65 | id = Column(Integer, primary_key=True, autoincrement=True) 66 | 67 | restaurant_id = Column(Integer, nullable=False, default=None) 68 | 69 | user_id = Column(Integer, nullable=False, default=None) 70 | 71 | reservation_time = Column(DateTime, nullable=False, default=func.now()) 72 | 73 | party_size = Column(Integer, nullable=False, default=None) 74 | 75 | special_requests = Column(String(1000), nullable=True, default="") 76 | 77 | # Define Updated and Created At (Auto) (Could be used for DB Replication) 78 | created_at = Column(DateTime, default=func.now()) 79 | updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) 80 | 81 | 82 | class DBReview(Base): 83 | 84 | # Define Table Name 85 | __tablename__ = "review" 86 | 87 | # Define Columns 88 | 89 | id = Column(Integer, primary_key=True, autoincrement=True) 90 | 91 | restaurant_id = Column(Integer, nullable=False, default=None) 92 | 93 | user_id = Column(Integer, nullable=False, default=None) 94 | 95 | rating = Column(Float, nullable=False, default=None) 96 | 97 | comment = Column(String(1000), nullable=True, default="") 98 | 99 | # Define Updated and Created At (Auto) (Could be used for DB Replication) 100 | created_at = Column(DateTime, default=func.now()) 101 | updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) 102 | -------------------------------------------------------------------------------- /example/alembic/output/backend/src/db/utils.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from src.db.constants import get_url 3 | from src.db.models import DBReservation, DBRestaurant, DBReview, DBUser 4 | 5 | 6 | async def ensure_all_tables(): 7 | """Create all tables if they do not exist""" 8 | engine = create_engine(get_url()) 9 | # Create the tables 10 | 11 | print(f"Ensuring table for DBUser") 12 | DBUser.metadata.create_all(engine) 13 | 14 | print(f"Ensuring table for DBRestaurant") 15 | DBRestaurant.metadata.create_all(engine) 16 | 17 | print(f"Ensuring table for DBReservation") 18 | DBReservation.metadata.create_all(engine) 19 | 20 | print(f"Ensuring table for DBReview") 21 | DBReview.metadata.create_all(engine) 22 | -------------------------------------------------------------------------------- /example/alembic/output/backend/src/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/backend/src/models/__init__.py -------------------------------------------------------------------------------- /example/alembic/output/client/.github/workflows/python.yml: -------------------------------------------------------------------------------- 1 | # NOTE: This file is auto generated by OpenAPI Generator. 2 | # URL: https://openapi-generator.tech 3 | # 4 | # ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python 5 | 6 | name: openapi_client Python package 7 | 8 | on: [push, pull_request] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Set up Python ${{ matrix.python-version }} 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: ${{ matrix.python-version }} 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install flake8 pytest 28 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 29 | if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi 30 | - name: Lint with flake8 31 | run: | 32 | # stop the build if there are Python syntax errors or undefined names 33 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 34 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 35 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 36 | - name: Test with pytest 37 | run: | 38 | pytest 39 | -------------------------------------------------------------------------------- /example/alembic/output/client/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | venv/ 48 | .venv/ 49 | .python-version 50 | .pytest_cache 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # PyBuilder 63 | target/ 64 | 65 | #Ipython Notebook 66 | .ipynb_checkpoints 67 | -------------------------------------------------------------------------------- /example/alembic/output/client/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # NOTE: This file is auto generated by OpenAPI Generator. 2 | # URL: https://openapi-generator.tech 3 | # 4 | # ref: https://docs.gitlab.com/ee/ci/README.html 5 | # ref: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml 6 | 7 | stages: 8 | - test 9 | 10 | .pytest: 11 | stage: test 12 | script: 13 | - pip install -r requirements.txt 14 | - pip install -r test-requirements.txt 15 | - pytest --cov=openapi_client 16 | 17 | pytest-3.7: 18 | extends: .pytest 19 | image: python:3.7-alpine 20 | pytest-3.8: 21 | extends: .pytest 22 | image: python:3.8-alpine 23 | pytest-3.9: 24 | extends: .pytest 25 | image: python:3.9-alpine 26 | pytest-3.10: 27 | extends: .pytest 28 | image: python:3.10-alpine 29 | pytest-3.11: 30 | extends: .pytest 31 | image: python:3.11-alpine 32 | -------------------------------------------------------------------------------- /example/alembic/output/client/.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /example/alembic/output/client/.openapi-generator/FILES: -------------------------------------------------------------------------------- 1 | .github/workflows/python.yml 2 | .gitignore 3 | .gitlab-ci.yml 4 | .openapi-generator-ignore 5 | .travis.yml 6 | README.md 7 | docs/DefaultApi.md 8 | docs/HTTPValidationError.md 9 | docs/Reservation.md 10 | docs/ReservationApi.md 11 | docs/ReservationQuery.md 12 | docs/Restaurant.md 13 | docs/RestaurantApi.md 14 | docs/RestaurantQuery.md 15 | docs/Review.md 16 | docs/ReviewApi.md 17 | docs/ReviewQuery.md 18 | docs/User.md 19 | docs/UserApi.md 20 | docs/UserQuery.md 21 | docs/ValidationError.md 22 | docs/ValidationErrorLocInner.md 23 | git_push.sh 24 | openapi_client/__init__.py 25 | openapi_client/api/__init__.py 26 | openapi_client/api/default_api.py 27 | openapi_client/api/reservation_api.py 28 | openapi_client/api/restaurant_api.py 29 | openapi_client/api/review_api.py 30 | openapi_client/api/user_api.py 31 | openapi_client/api_client.py 32 | openapi_client/api_response.py 33 | openapi_client/configuration.py 34 | openapi_client/exceptions.py 35 | openapi_client/models/__init__.py 36 | openapi_client/models/http_validation_error.py 37 | openapi_client/models/reservation.py 38 | openapi_client/models/reservation_query.py 39 | openapi_client/models/restaurant.py 40 | openapi_client/models/restaurant_query.py 41 | openapi_client/models/review.py 42 | openapi_client/models/review_query.py 43 | openapi_client/models/user.py 44 | openapi_client/models/user_query.py 45 | openapi_client/models/validation_error.py 46 | openapi_client/models/validation_error_loc_inner.py 47 | openapi_client/py.typed 48 | openapi_client/rest.py 49 | pyproject.toml 50 | requirements.txt 51 | setup.cfg 52 | setup.py 53 | test-requirements.txt 54 | test/__init__.py 55 | test/test_default_api.py 56 | test/test_http_validation_error.py 57 | test/test_reservation.py 58 | test/test_reservation_api.py 59 | test/test_reservation_query.py 60 | test/test_restaurant.py 61 | test/test_restaurant_api.py 62 | test/test_restaurant_query.py 63 | test/test_review.py 64 | test/test_review_api.py 65 | test/test_review_query.py 66 | test/test_user.py 67 | test/test_user_api.py 68 | test/test_user_query.py 69 | test/test_validation_error.py 70 | test/test_validation_error_loc_inner.py 71 | tox.ini 72 | -------------------------------------------------------------------------------- /example/alembic/output/client/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.5.0 2 | -------------------------------------------------------------------------------- /example/alembic/output/client/.travis.yml: -------------------------------------------------------------------------------- 1 | # ref: https://docs.travis-ci.com/user/languages/python 2 | language: python 3 | python: 4 | - "3.7" 5 | - "3.8" 6 | - "3.9" 7 | - "3.10" 8 | - "3.11" 9 | # uncomment the following if needed 10 | #- "3.11-dev" # 3.11 development branch 11 | #- "nightly" # nightly build 12 | # command to install dependencies 13 | install: 14 | - "pip install -r requirements.txt" 15 | - "pip install -r test-requirements.txt" 16 | # command to run tests 17 | script: pytest --cov=openapi_client 18 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/HTTPValidationError.md: -------------------------------------------------------------------------------- 1 | # HTTPValidationError 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **detail** | [**List[ValidationError]**](ValidationError.md) | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from openapi_client.models.http_validation_error import HTTPValidationError 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of HTTPValidationError from a JSON string 18 | http_validation_error_instance = HTTPValidationError.from_json(json) 19 | # print the JSON string representation of the object 20 | print(HTTPValidationError.to_json()) 21 | 22 | # convert the object into a dict 23 | http_validation_error_dict = http_validation_error_instance.to_dict() 24 | # create an instance of HTTPValidationError from a dict 25 | http_validation_error_from_dict = HTTPValidationError.from_dict(http_validation_error_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/Reservation.md: -------------------------------------------------------------------------------- 1 | # Reservation 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **id** | **int** | | [optional] 9 | **restaurant_id** | **int** | The ID of the alembic where the reservation is made | 10 | **user_id** | **int** | The ID of the user who made the reservation | 11 | **reservation_time** | **datetime** | The date and time of the reservation | 12 | **party_size** | **int** | The size of the party for the reservation | 13 | **special_requests** | **str** | | [optional] 14 | **created_at** | **datetime** | | [optional] 15 | **updated_at** | **datetime** | | [optional] 16 | 17 | ## Example 18 | 19 | ```python 20 | from openapi_client.models.reservation import Reservation 21 | 22 | # TODO update the JSON string below 23 | json = "{}" 24 | # create an instance of Reservation from a JSON string 25 | reservation_instance = Reservation.from_json(json) 26 | # print the JSON string representation of the object 27 | print(Reservation.to_json()) 28 | 29 | # convert the object into a dict 30 | reservation_dict = reservation_instance.to_dict() 31 | # create an instance of Reservation from a dict 32 | reservation_from_dict = Reservation.from_dict(reservation_dict) 33 | ``` 34 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/ReservationQuery.md: -------------------------------------------------------------------------------- 1 | # ReservationQuery 2 | 3 | Query model for Reservation 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | **id** | **int** | | [optional] 10 | **restaurant_id** | **int** | | [optional] 11 | **user_id** | **int** | | [optional] 12 | **reservation_time** | **datetime** | | [optional] 13 | **party_size** | **int** | | [optional] 14 | **special_requests** | **str** | | [optional] 15 | 16 | ## Example 17 | 18 | ```python 19 | from openapi_client.models.reservation_query import ReservationQuery 20 | 21 | # TODO update the JSON string below 22 | json = "{}" 23 | # create an instance of ReservationQuery from a JSON string 24 | reservation_query_instance = ReservationQuery.from_json(json) 25 | # print the JSON string representation of the object 26 | print(ReservationQuery.to_json()) 27 | 28 | # convert the object into a dict 29 | reservation_query_dict = reservation_query_instance.to_dict() 30 | # create an instance of ReservationQuery from a dict 31 | reservation_query_from_dict = ReservationQuery.from_dict(reservation_query_dict) 32 | ``` 33 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/Restaurant.md: -------------------------------------------------------------------------------- 1 | # Restaurant 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **id** | **int** | | [optional] 9 | **name** | **str** | The name of the alembic | 10 | **location** | **str** | The physical location of the alembic | 11 | **cuisine** | **str** | | [optional] 12 | **rating** | **float** | | [optional] 13 | **price_range** | **str** | | [optional] 14 | **created_at** | **datetime** | | [optional] 15 | **updated_at** | **datetime** | | [optional] 16 | 17 | ## Example 18 | 19 | ```python 20 | from openapi_client.models.restaurant import Restaurant 21 | 22 | # TODO update the JSON string below 23 | json = "{}" 24 | # create an instance of Restaurant from a JSON string 25 | restaurant_instance = Restaurant.from_json(json) 26 | # print the JSON string representation of the object 27 | print(Restaurant.to_json()) 28 | 29 | # convert the object into a dict 30 | restaurant_dict = restaurant_instance.to_dict() 31 | # create an instance of Restaurant from a dict 32 | restaurant_from_dict = Restaurant.from_dict(restaurant_dict) 33 | ``` 34 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/RestaurantQuery.md: -------------------------------------------------------------------------------- 1 | # RestaurantQuery 2 | 3 | Query model for Restaurant 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | **id** | **int** | | [optional] 10 | **name** | **str** | | [optional] 11 | **location** | **str** | | [optional] 12 | **cuisine** | **str** | | [optional] 13 | **rating** | **float** | | [optional] 14 | **price_range** | **str** | | [optional] 15 | 16 | ## Example 17 | 18 | ```python 19 | from openapi_client.models.restaurant_query import RestaurantQuery 20 | 21 | # TODO update the JSON string below 22 | json = "{}" 23 | # create an instance of RestaurantQuery from a JSON string 24 | restaurant_query_instance = RestaurantQuery.from_json(json) 25 | # print the JSON string representation of the object 26 | print(RestaurantQuery.to_json()) 27 | 28 | # convert the object into a dict 29 | restaurant_query_dict = restaurant_query_instance.to_dict() 30 | # create an instance of RestaurantQuery from a dict 31 | restaurant_query_from_dict = RestaurantQuery.from_dict(restaurant_query_dict) 32 | ``` 33 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/Review.md: -------------------------------------------------------------------------------- 1 | # Review 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **id** | **int** | | [optional] 9 | **restaurant_id** | **int** | The ID of the alembic being reviewed | 10 | **user_id** | **int** | The ID of the user who wrote the review | 11 | **rating** | **float** | The rating given by the user | 12 | **comment** | **str** | | [optional] 13 | **created_at** | **datetime** | | [optional] 14 | **updated_at** | **datetime** | | [optional] 15 | 16 | ## Example 17 | 18 | ```python 19 | from openapi_client.models.review import Review 20 | 21 | # TODO update the JSON string below 22 | json = "{}" 23 | # create an instance of Review from a JSON string 24 | review_instance = Review.from_json(json) 25 | # print the JSON string representation of the object 26 | print(Review.to_json()) 27 | 28 | # convert the object into a dict 29 | review_dict = review_instance.to_dict() 30 | # create an instance of Review from a dict 31 | review_from_dict = Review.from_dict(review_dict) 32 | ``` 33 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/ReviewQuery.md: -------------------------------------------------------------------------------- 1 | # ReviewQuery 2 | 3 | Query model for Review 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | **id** | **int** | | [optional] 10 | **restaurant_id** | **int** | | [optional] 11 | **user_id** | **int** | | [optional] 12 | **rating** | **float** | | [optional] 13 | **comment** | **str** | | [optional] 14 | 15 | ## Example 16 | 17 | ```python 18 | from openapi_client.models.review_query import ReviewQuery 19 | 20 | # TODO update the JSON string below 21 | json = "{}" 22 | # create an instance of ReviewQuery from a JSON string 23 | review_query_instance = ReviewQuery.from_json(json) 24 | # print the JSON string representation of the object 25 | print(ReviewQuery.to_json()) 26 | 27 | # convert the object into a dict 28 | review_query_dict = review_query_instance.to_dict() 29 | # create an instance of ReviewQuery from a dict 30 | review_query_from_dict = ReviewQuery.from_dict(review_query_dict) 31 | ``` 32 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/User.md: -------------------------------------------------------------------------------- 1 | # User 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **id** | **int** | | [optional] 9 | **username** | **str** | The username of the user | 10 | **email** | **str** | The email address of the user | 11 | **phone_number** | **str** | | [optional] 12 | **preferences** | **List[object]** | | [optional] 13 | **role** | **str** | | [optional] 14 | **created_at** | **datetime** | | [optional] 15 | **updated_at** | **datetime** | | [optional] 16 | 17 | ## Example 18 | 19 | ```python 20 | from openapi_client.models.user import User 21 | 22 | # TODO update the JSON string below 23 | json = "{}" 24 | # create an instance of User from a JSON string 25 | user_instance = User.from_json(json) 26 | # print the JSON string representation of the object 27 | print(User.to_json()) 28 | 29 | # convert the object into a dict 30 | user_dict = user_instance.to_dict() 31 | # create an instance of User from a dict 32 | user_from_dict = User.from_dict(user_dict) 33 | ``` 34 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/UserQuery.md: -------------------------------------------------------------------------------- 1 | # UserQuery 2 | 3 | Query model for User 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | **id** | **int** | | [optional] 10 | **username** | **str** | | [optional] 11 | **email** | **str** | | [optional] 12 | **phone_number** | **str** | | [optional] 13 | **preferences** | **List[object]** | | [optional] 14 | **role** | **str** | | [optional] 15 | 16 | ## Example 17 | 18 | ```python 19 | from openapi_client.models.user_query import UserQuery 20 | 21 | # TODO update the JSON string below 22 | json = "{}" 23 | # create an instance of UserQuery from a JSON string 24 | user_query_instance = UserQuery.from_json(json) 25 | # print the JSON string representation of the object 26 | print(UserQuery.to_json()) 27 | 28 | # convert the object into a dict 29 | user_query_dict = user_query_instance.to_dict() 30 | # create an instance of UserQuery from a dict 31 | user_query_from_dict = UserQuery.from_dict(user_query_dict) 32 | ``` 33 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/ValidationError.md: -------------------------------------------------------------------------------- 1 | # ValidationError 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **loc** | [**List[ValidationErrorLocInner]**](ValidationErrorLocInner.md) | | 9 | **msg** | **str** | | 10 | **type** | **str** | | 11 | 12 | ## Example 13 | 14 | ```python 15 | from openapi_client.models.validation_error import ValidationError 16 | 17 | # TODO update the JSON string below 18 | json = "{}" 19 | # create an instance of ValidationError from a JSON string 20 | validation_error_instance = ValidationError.from_json(json) 21 | # print the JSON string representation of the object 22 | print(ValidationError.to_json()) 23 | 24 | # convert the object into a dict 25 | validation_error_dict = validation_error_instance.to_dict() 26 | # create an instance of ValidationError from a dict 27 | validation_error_from_dict = ValidationError.from_dict(validation_error_dict) 28 | ``` 29 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 30 | 31 | 32 | -------------------------------------------------------------------------------- /example/alembic/output/client/docs/ValidationErrorLocInner.md: -------------------------------------------------------------------------------- 1 | # ValidationErrorLocInner 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | 9 | ## Example 10 | 11 | ```python 12 | from openapi_client.models.validation_error_loc_inner import ValidationErrorLocInner 13 | 14 | # TODO update the JSON string below 15 | json = "{}" 16 | # create an instance of ValidationErrorLocInner from a JSON string 17 | validation_error_loc_inner_instance = ValidationErrorLocInner.from_json(json) 18 | # print the JSON string representation of the object 19 | print(ValidationErrorLocInner.to_json()) 20 | 21 | # convert the object into a dict 22 | validation_error_loc_inner_dict = validation_error_loc_inner_instance.to_dict() 23 | # create an instance of ValidationErrorLocInner from a dict 24 | validation_error_loc_inner_from_dict = ValidationErrorLocInner.from_dict(validation_error_loc_inner_dict) 25 | ``` 26 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/alembic/output/client/git_push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ 3 | # 4 | # Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" 5 | 6 | git_user_id=$1 7 | git_repo_id=$2 8 | release_note=$3 9 | git_host=$4 10 | 11 | if [ "$git_host" = "" ]; then 12 | git_host="github.com" 13 | echo "[INFO] No command line input provided. Set \$git_host to $git_host" 14 | fi 15 | 16 | if [ "$git_user_id" = "" ]; then 17 | git_user_id="GIT_USER_ID" 18 | echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" 19 | fi 20 | 21 | if [ "$git_repo_id" = "" ]; then 22 | git_repo_id="GIT_REPO_ID" 23 | echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" 24 | fi 25 | 26 | if [ "$release_note" = "" ]; then 27 | release_note="Minor update" 28 | echo "[INFO] No command line input provided. Set \$release_note to $release_note" 29 | fi 30 | 31 | # Initialize the local directory as a Git repository 32 | git init 33 | 34 | # Adds the files in the local repository and stages them for commit. 35 | git add . 36 | 37 | # Commits the tracked changes and prepares them to be pushed to a remote repository. 38 | git commit -m "$release_note" 39 | 40 | # Sets the new remote 41 | git_remote=$(git remote) 42 | if [ "$git_remote" = "" ]; then # git remote not defined 43 | 44 | if [ "$GIT_TOKEN" = "" ]; then 45 | echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." 46 | git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git 47 | else 48 | git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git 49 | fi 50 | 51 | fi 52 | 53 | git pull origin master 54 | 55 | # Pushes (Forces) the changes in the local repository up to the remote repository 56 | echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" 57 | git push origin master 2>&1 | grep -v 'To https' 58 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | # flake8: noqa 4 | 5 | """ 6 | FastAPI 7 | 8 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 9 | 10 | The version of the OpenAPI document: 0.1.0 11 | Generated by OpenAPI Generator (https://openapi-generator.tech) 12 | 13 | Do not edit the class manually. 14 | """ # noqa: E501 15 | 16 | 17 | __version__ = "1.0.0" 18 | 19 | from openapi_client.api.default_api import DefaultApi 20 | # import apis into sdk package 21 | from openapi_client.api.reservation_api import ReservationApi 22 | from openapi_client.api.restaurant_api import RestaurantApi 23 | from openapi_client.api.review_api import ReviewApi 24 | from openapi_client.api.user_api import UserApi 25 | from openapi_client.api_client import ApiClient 26 | # import ApiClient 27 | from openapi_client.api_response import ApiResponse 28 | from openapi_client.configuration import Configuration 29 | from openapi_client.exceptions import (ApiAttributeError, ApiException, 30 | ApiKeyError, ApiTypeError, 31 | ApiValueError, OpenApiException) 32 | # import models into sdk package 33 | from openapi_client.models.http_validation_error import HTTPValidationError 34 | from openapi_client.models.reservation import Reservation 35 | from openapi_client.models.reservation_query import ReservationQuery 36 | from openapi_client.models.restaurant import Restaurant 37 | from openapi_client.models.restaurant_query import RestaurantQuery 38 | from openapi_client.models.review import Review 39 | from openapi_client.models.review_query import ReviewQuery 40 | from openapi_client.models.user import User 41 | from openapi_client.models.user_query import UserQuery 42 | from openapi_client.models.validation_error import ValidationError 43 | from openapi_client.models.validation_error_loc_inner import \ 44 | ValidationErrorLocInner 45 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/api/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | 3 | # import apis into api package 4 | from openapi_client.api.default_api import DefaultApi 5 | from openapi_client.api.reservation_api import ReservationApi 6 | from openapi_client.api.restaurant_api import RestaurantApi 7 | from openapi_client.api.review_api import ReviewApi 8 | from openapi_client.api.user_api import UserApi 9 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/api_response.py: -------------------------------------------------------------------------------- 1 | """API response object.""" 2 | 3 | from __future__ import annotations 4 | 5 | from typing import Generic, Mapping, Optional, TypeVar 6 | 7 | from pydantic import BaseModel, Field, StrictBytes, StrictInt 8 | 9 | T = TypeVar("T") 10 | 11 | 12 | class ApiResponse(BaseModel, Generic[T]): 13 | """ 14 | API response object 15 | """ 16 | 17 | status_code: StrictInt = Field(description="HTTP status code") 18 | headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers") 19 | data: T = Field(description="Deserialized data given the data type") 20 | raw_data: StrictBytes = Field(description="Raw data (HTTP response body)") 21 | 22 | model_config = {"arbitrary_types_allowed": True} 23 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/models/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | # flake8: noqa 4 | """ 5 | FastAPI 6 | 7 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 8 | 9 | The version of the OpenAPI document: 0.1.0 10 | Generated by OpenAPI Generator (https://openapi-generator.tech) 11 | 12 | Do not edit the class manually. 13 | """ # noqa: E501 14 | 15 | 16 | # import models into model package 17 | from openapi_client.models.http_validation_error import HTTPValidationError 18 | from openapi_client.models.reservation import Reservation 19 | from openapi_client.models.reservation_query import ReservationQuery 20 | from openapi_client.models.restaurant import Restaurant 21 | from openapi_client.models.restaurant_query import RestaurantQuery 22 | from openapi_client.models.review import Review 23 | from openapi_client.models.review_query import ReviewQuery 24 | from openapi_client.models.user import User 25 | from openapi_client.models.user_query import UserQuery 26 | from openapi_client.models.validation_error import ValidationError 27 | from openapi_client.models.validation_error_loc_inner import \ 28 | ValidationErrorLocInner 29 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/models/http_validation_error.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | from __future__ import annotations 16 | 17 | import json 18 | import pprint 19 | import re # noqa: F401 20 | from typing import Any, ClassVar, Dict, List, Optional, Set 21 | 22 | from openapi_client.models.validation_error import ValidationError 23 | from pydantic import BaseModel, ConfigDict 24 | from typing_extensions import Self 25 | 26 | 27 | class HTTPValidationError(BaseModel): 28 | """ 29 | HTTPValidationError 30 | """ # noqa: E501 31 | 32 | detail: Optional[List[ValidationError]] = None 33 | __properties: ClassVar[List[str]] = ["detail"] 34 | 35 | model_config = ConfigDict( 36 | populate_by_name=True, 37 | validate_assignment=True, 38 | protected_namespaces=(), 39 | ) 40 | 41 | def to_str(self) -> str: 42 | """Returns the string representation of the model using alias""" 43 | return pprint.pformat(self.model_dump(by_alias=True)) 44 | 45 | def to_json(self) -> str: 46 | """Returns the JSON representation of the model using alias""" 47 | # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead 48 | return json.dumps(self.to_dict()) 49 | 50 | @classmethod 51 | def from_json(cls, json_str: str) -> Optional[Self]: 52 | """Create an instance of HTTPValidationError from a JSON string""" 53 | return cls.from_dict(json.loads(json_str)) 54 | 55 | def to_dict(self) -> Dict[str, Any]: 56 | """Return the dictionary representation of the model using alias. 57 | 58 | This has the following differences from calling pydantic's 59 | `self.model_dump(by_alias=True)`: 60 | 61 | * `None` is only added to the output dict for nullable fields that 62 | were set at model initialization. Other fields with value `None` 63 | are ignored. 64 | """ 65 | excluded_fields: Set[str] = set([]) 66 | 67 | _dict = self.model_dump( 68 | by_alias=True, 69 | exclude=excluded_fields, 70 | exclude_none=True, 71 | ) 72 | # override the default output from pydantic by calling `to_dict()` of each item in detail (list) 73 | _items = [] 74 | if self.detail: 75 | for _item in self.detail: 76 | if _item: 77 | _items.append(_item.to_dict()) 78 | _dict["detail"] = _items 79 | return _dict 80 | 81 | @classmethod 82 | def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: 83 | """Create an instance of HTTPValidationError from a dict""" 84 | if obj is None: 85 | return None 86 | 87 | if not isinstance(obj, dict): 88 | return cls.model_validate(obj) 89 | 90 | _obj = cls.model_validate( 91 | { 92 | "detail": ( 93 | [ValidationError.from_dict(_item) for _item in obj["detail"]] 94 | if obj.get("detail") is not None 95 | else None 96 | ) 97 | } 98 | ) 99 | return _obj 100 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/models/validation_error.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | from __future__ import annotations 16 | 17 | import json 18 | import pprint 19 | import re # noqa: F401 20 | from typing import Any, ClassVar, Dict, List, Optional, Set 21 | 22 | from openapi_client.models.validation_error_loc_inner import \ 23 | ValidationErrorLocInner 24 | from pydantic import BaseModel, ConfigDict, StrictStr 25 | from typing_extensions import Self 26 | 27 | 28 | class ValidationError(BaseModel): 29 | """ 30 | ValidationError 31 | """ # noqa: E501 32 | 33 | loc: List[ValidationErrorLocInner] 34 | msg: StrictStr 35 | type: StrictStr 36 | __properties: ClassVar[List[str]] = ["loc", "msg", "type"] 37 | 38 | model_config = ConfigDict( 39 | populate_by_name=True, 40 | validate_assignment=True, 41 | protected_namespaces=(), 42 | ) 43 | 44 | def to_str(self) -> str: 45 | """Returns the string representation of the model using alias""" 46 | return pprint.pformat(self.model_dump(by_alias=True)) 47 | 48 | def to_json(self) -> str: 49 | """Returns the JSON representation of the model using alias""" 50 | # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead 51 | return json.dumps(self.to_dict()) 52 | 53 | @classmethod 54 | def from_json(cls, json_str: str) -> Optional[Self]: 55 | """Create an instance of ValidationError from a JSON string""" 56 | return cls.from_dict(json.loads(json_str)) 57 | 58 | def to_dict(self) -> Dict[str, Any]: 59 | """Return the dictionary representation of the model using alias. 60 | 61 | This has the following differences from calling pydantic's 62 | `self.model_dump(by_alias=True)`: 63 | 64 | * `None` is only added to the output dict for nullable fields that 65 | were set at model initialization. Other fields with value `None` 66 | are ignored. 67 | """ 68 | excluded_fields: Set[str] = set([]) 69 | 70 | _dict = self.model_dump( 71 | by_alias=True, 72 | exclude=excluded_fields, 73 | exclude_none=True, 74 | ) 75 | # override the default output from pydantic by calling `to_dict()` of each item in loc (list) 76 | _items = [] 77 | if self.loc: 78 | for _item in self.loc: 79 | if _item: 80 | _items.append(_item.to_dict()) 81 | _dict["loc"] = _items 82 | return _dict 83 | 84 | @classmethod 85 | def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: 86 | """Create an instance of ValidationError from a dict""" 87 | if obj is None: 88 | return None 89 | 90 | if not isinstance(obj, dict): 91 | return cls.model_validate(obj) 92 | 93 | _obj = cls.model_validate( 94 | { 95 | "loc": ( 96 | [ValidationErrorLocInner.from_dict(_item) for _item in obj["loc"]] 97 | if obj.get("loc") is not None 98 | else None 99 | ), 100 | "msg": obj.get("msg"), 101 | "type": obj.get("type"), 102 | } 103 | ) 104 | return _obj 105 | -------------------------------------------------------------------------------- /example/alembic/output/client/openapi_client/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/client/openapi_client/py.typed -------------------------------------------------------------------------------- /example/alembic/output/client/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "openapi_client" 3 | version = "1.0.0" 4 | description = "FastAPI" 5 | authors = ["OpenAPI Generator Community "] 6 | license = "NoLicense" 7 | readme = "README.md" 8 | repository = "https://github.com/GIT_USER_ID/GIT_REPO_ID" 9 | keywords = ["OpenAPI", "OpenAPI-Generator", "FastAPI"] 10 | include = ["openapi_client/py.typed"] 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.7" 14 | 15 | urllib3 = ">= 1.25.3" 16 | python-dateutil = ">=2.8.2" 17 | pydantic = ">=2" 18 | typing-extensions = ">=4.7.1" 19 | 20 | [tool.poetry.dev-dependencies] 21 | pytest = ">=7.2.1" 22 | tox = ">=3.9.0" 23 | flake8 = ">=4.0.0" 24 | types-python-dateutil = ">=2.8.19.14" 25 | mypy = "1.4.1" 26 | 27 | 28 | [build-system] 29 | requires = ["setuptools"] 30 | build-backend = "setuptools.build_meta" 31 | 32 | [tool.pylint.'MESSAGES CONTROL'] 33 | extension-pkg-whitelist = "pydantic" 34 | 35 | [tool.mypy] 36 | files = [ 37 | "openapi_client", 38 | #"test", # auto-generated tests 39 | "tests", # hand-written tests 40 | ] 41 | # TODO: enable "strict" once all these individual checks are passing 42 | # strict = true 43 | 44 | # List from: https://mypy.readthedocs.io/en/stable/existing_code.html#introduce-stricter-options 45 | warn_unused_configs = true 46 | warn_redundant_casts = true 47 | warn_unused_ignores = true 48 | 49 | ## Getting these passing should be easy 50 | strict_equality = true 51 | strict_concatenate = true 52 | 53 | ## Strongly recommend enabling this one as soon as you can 54 | check_untyped_defs = true 55 | 56 | ## These shouldn't be too much additional work, but may be tricky to 57 | ## get passing if you use a lot of untyped libraries 58 | disallow_subclassing_any = true 59 | disallow_untyped_decorators = true 60 | disallow_any_generics = true 61 | 62 | ### These next few are various gradations of forcing use of type annotations 63 | #disallow_untyped_calls = true 64 | #disallow_incomplete_defs = true 65 | #disallow_untyped_defs = true 66 | # 67 | ### This one isn't too hard to get passing, but return on investment is lower 68 | #no_implicit_reexport = true 69 | # 70 | ### This one can be tricky to get passing if you use a lot of untyped libraries 71 | #warn_return_any = true 72 | -------------------------------------------------------------------------------- /example/alembic/output/client/requirements.txt: -------------------------------------------------------------------------------- 1 | python_dateutil >= 2.5.3 2 | setuptools >= 21.0.0 3 | urllib3 >= 1.25.3, < 2.1.0 4 | pydantic >= 2 5 | typing-extensions >= 4.7.1 6 | -------------------------------------------------------------------------------- /example/alembic/output/client/setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length=99 3 | -------------------------------------------------------------------------------- /example/alembic/output/client/setup.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | from setuptools import find_packages, setup # noqa: H301 16 | 17 | # To install the library, run the following 18 | # 19 | # python setup.py install 20 | # 21 | # prerequisite: setuptools 22 | # http://pypi.python.org/pypi/setuptools 23 | NAME = "openapi-client" 24 | VERSION = "1.0.0" 25 | PYTHON_REQUIRES = ">=3.7" 26 | REQUIRES = [ 27 | "urllib3 >= 1.25.3, < 2.1.0", 28 | "python-dateutil", 29 | "pydantic >= 2", 30 | "typing-extensions >= 4.7.1", 31 | ] 32 | 33 | setup( 34 | name=NAME, 35 | version=VERSION, 36 | description="FastAPI", 37 | author="OpenAPI Generator community", 38 | author_email="team@openapitools.org", 39 | url="", 40 | keywords=["OpenAPI", "OpenAPI-Generator", "FastAPI"], 41 | install_requires=REQUIRES, 42 | packages=find_packages(exclude=["test", "tests"]), 43 | include_package_data=True, 44 | long_description_content_type="text/markdown", 45 | long_description="""\ 46 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 47 | """, # noqa: E501 48 | package_data={"openapi_client": ["py.typed"]}, 49 | ) 50 | -------------------------------------------------------------------------------- /example/alembic/output/client/test-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest~=7.1.3 2 | pytest-cov>=2.8.1 3 | pytest-randomly>=3.12.0 4 | mypy>=1.4.1 5 | types-python-dateutil>=2.8.19 6 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/client/test/__init__.py -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_default_api.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.api.default_api import DefaultApi 18 | 19 | 20 | class TestDefaultApi(unittest.TestCase): 21 | """DefaultApi unit test stubs""" 22 | 23 | def setUp(self) -> None: 24 | self.api = DefaultApi() 25 | 26 | def tearDown(self) -> None: 27 | pass 28 | 29 | def test_health_health_get(self) -> None: 30 | """Test case for health_health_get 31 | 32 | Health 33 | """ 34 | pass 35 | 36 | def test_health_ready_get(self) -> None: 37 | """Test case for health_ready_get 38 | 39 | Health 40 | """ 41 | pass 42 | 43 | def test_root_get(self) -> None: 44 | """Test case for root_get 45 | 46 | Root 47 | """ 48 | pass 49 | 50 | 51 | if __name__ == "__main__": 52 | unittest.main() 53 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_http_validation_error.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.http_validation_error import HTTPValidationError 18 | 19 | 20 | class TestHTTPValidationError(unittest.TestCase): 21 | """HTTPValidationError unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> HTTPValidationError: 30 | """Test HTTPValidationError 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `HTTPValidationError` 35 | """ 36 | model = HTTPValidationError() 37 | if include_optional: 38 | return HTTPValidationError( 39 | detail = [ 40 | openapi_client.models.validation_error.ValidationError( 41 | loc = [ 42 | null 43 | ], 44 | msg = '', 45 | type = '', ) 46 | ] 47 | ) 48 | else: 49 | return HTTPValidationError( 50 | ) 51 | """ 52 | 53 | def testHTTPValidationError(self): 54 | """Test HTTPValidationError""" 55 | # inst_req_only = self.make_instance(include_optional=False) 56 | # inst_req_and_optional = self.make_instance(include_optional=True) 57 | 58 | 59 | if __name__ == "__main__": 60 | unittest.main() 61 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_reservation.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.reservation import Reservation 18 | 19 | 20 | class TestReservation(unittest.TestCase): 21 | """Reservation unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> Reservation: 30 | """Test Reservation 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `Reservation` 35 | """ 36 | model = Reservation() 37 | if include_optional: 38 | return Reservation( 39 | id = 56, 40 | restaurant_id = 56, 41 | user_id = 56, 42 | reservation_time = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 43 | party_size = 56, 44 | special_requests = '', 45 | created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 46 | updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') 47 | ) 48 | else: 49 | return Reservation( 50 | restaurant_id = 56, 51 | user_id = 56, 52 | reservation_time = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 53 | party_size = 56, 54 | ) 55 | """ 56 | 57 | def testReservation(self): 58 | """Test Reservation""" 59 | # inst_req_only = self.make_instance(include_optional=False) 60 | # inst_req_and_optional = self.make_instance(include_optional=True) 61 | 62 | 63 | if __name__ == "__main__": 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_reservation_query.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.reservation_query import ReservationQuery 18 | 19 | 20 | class TestReservationQuery(unittest.TestCase): 21 | """ReservationQuery unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> ReservationQuery: 30 | """Test ReservationQuery 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `ReservationQuery` 35 | """ 36 | model = ReservationQuery() 37 | if include_optional: 38 | return ReservationQuery( 39 | id = 56, 40 | restaurant_id = 56, 41 | user_id = 56, 42 | reservation_time = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 43 | party_size = 56, 44 | special_requests = '' 45 | ) 46 | else: 47 | return ReservationQuery( 48 | ) 49 | """ 50 | 51 | def testReservationQuery(self): 52 | """Test ReservationQuery""" 53 | # inst_req_only = self.make_instance(include_optional=False) 54 | # inst_req_and_optional = self.make_instance(include_optional=True) 55 | 56 | 57 | if __name__ == "__main__": 58 | unittest.main() 59 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_restaurant.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.restaurant import Restaurant 18 | 19 | 20 | class TestRestaurant(unittest.TestCase): 21 | """Restaurant unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> Restaurant: 30 | """Test Restaurant 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `Restaurant` 35 | """ 36 | model = Restaurant() 37 | if include_optional: 38 | return Restaurant( 39 | id = 56, 40 | name = '', 41 | location = '', 42 | cuisine = '', 43 | rating = 1.337, 44 | price_range = '', 45 | created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 46 | updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') 47 | ) 48 | else: 49 | return Restaurant( 50 | name = '', 51 | location = '', 52 | ) 53 | """ 54 | 55 | def testRestaurant(self): 56 | """Test Restaurant""" 57 | # inst_req_only = self.make_instance(include_optional=False) 58 | # inst_req_and_optional = self.make_instance(include_optional=True) 59 | 60 | 61 | if __name__ == "__main__": 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_restaurant_query.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.restaurant_query import RestaurantQuery 18 | 19 | 20 | class TestRestaurantQuery(unittest.TestCase): 21 | """RestaurantQuery unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> RestaurantQuery: 30 | """Test RestaurantQuery 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `RestaurantQuery` 35 | """ 36 | model = RestaurantQuery() 37 | if include_optional: 38 | return RestaurantQuery( 39 | id = 56, 40 | name = '', 41 | location = '', 42 | cuisine = '', 43 | rating = 1.337, 44 | price_range = '' 45 | ) 46 | else: 47 | return RestaurantQuery( 48 | ) 49 | """ 50 | 51 | def testRestaurantQuery(self): 52 | """Test RestaurantQuery""" 53 | # inst_req_only = self.make_instance(include_optional=False) 54 | # inst_req_and_optional = self.make_instance(include_optional=True) 55 | 56 | 57 | if __name__ == "__main__": 58 | unittest.main() 59 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_review.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.review import Review 18 | 19 | 20 | class TestReview(unittest.TestCase): 21 | """Review unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> Review: 30 | """Test Review 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `Review` 35 | """ 36 | model = Review() 37 | if include_optional: 38 | return Review( 39 | id = 56, 40 | restaurant_id = 56, 41 | user_id = 56, 42 | rating = 1.337, 43 | comment = '', 44 | created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 45 | updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') 46 | ) 47 | else: 48 | return Review( 49 | restaurant_id = 56, 50 | user_id = 56, 51 | rating = 1.337, 52 | ) 53 | """ 54 | 55 | def testReview(self): 56 | """Test Review""" 57 | # inst_req_only = self.make_instance(include_optional=False) 58 | # inst_req_and_optional = self.make_instance(include_optional=True) 59 | 60 | 61 | if __name__ == "__main__": 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_review_query.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.review_query import ReviewQuery 18 | 19 | 20 | class TestReviewQuery(unittest.TestCase): 21 | """ReviewQuery unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> ReviewQuery: 30 | """Test ReviewQuery 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `ReviewQuery` 35 | """ 36 | model = ReviewQuery() 37 | if include_optional: 38 | return ReviewQuery( 39 | id = 56, 40 | restaurant_id = 56, 41 | user_id = 56, 42 | rating = 1.337, 43 | comment = '' 44 | ) 45 | else: 46 | return ReviewQuery( 47 | ) 48 | """ 49 | 50 | def testReviewQuery(self): 51 | """Test ReviewQuery""" 52 | # inst_req_only = self.make_instance(include_optional=False) 53 | # inst_req_and_optional = self.make_instance(include_optional=True) 54 | 55 | 56 | if __name__ == "__main__": 57 | unittest.main() 58 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_user.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.user import User 18 | 19 | 20 | class TestUser(unittest.TestCase): 21 | """User unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> User: 30 | """Test User 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `User` 35 | """ 36 | model = User() 37 | if include_optional: 38 | return User( 39 | id = 56, 40 | username = '', 41 | email = '', 42 | phone_number = '', 43 | preferences = [ 44 | null 45 | ], 46 | role = '', 47 | created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), 48 | updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') 49 | ) 50 | else: 51 | return User( 52 | username = '', 53 | email = '', 54 | ) 55 | """ 56 | 57 | def testUser(self): 58 | """Test User""" 59 | # inst_req_only = self.make_instance(include_optional=False) 60 | # inst_req_and_optional = self.make_instance(include_optional=True) 61 | 62 | 63 | if __name__ == "__main__": 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_user_api.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.api.user_api import UserApi 18 | 19 | 20 | class TestUserApi(unittest.TestCase): 21 | """UserApi unit test stubs""" 22 | 23 | def setUp(self) -> None: 24 | self.api = UserApi() 25 | 26 | def tearDown(self) -> None: 27 | pass 28 | 29 | def test_create_user_async_user_async_post(self) -> None: 30 | """Test case for create_user_async_user_async_post 31 | 32 | Create User Async 33 | """ 34 | pass 35 | 36 | def test_create_user_user_post(self) -> None: 37 | """Test case for create_user_user_post 38 | 39 | Create User 40 | """ 41 | pass 42 | 43 | def test_create_users_async_users_async_post(self) -> None: 44 | """Test case for create_users_async_users_async_post 45 | 46 | Create Users Async 47 | """ 48 | pass 49 | 50 | def test_create_users_users_post(self) -> None: 51 | """Test case for create_users_users_post 52 | 53 | Create Users 54 | """ 55 | pass 56 | 57 | def test_delete_user_async_user_async_delete(self) -> None: 58 | """Test case for delete_user_async_user_async_delete 59 | 60 | Delete User Async 61 | """ 62 | pass 63 | 64 | def test_delete_user_user_delete(self) -> None: 65 | """Test case for delete_user_user_delete 66 | 67 | Delete User 68 | """ 69 | pass 70 | 71 | def test_delete_users_async_users_async_delete(self) -> None: 72 | """Test case for delete_users_async_users_async_delete 73 | 74 | Delete Users Async 75 | """ 76 | pass 77 | 78 | def test_delete_users_users_delete(self) -> None: 79 | """Test case for delete_users_users_delete 80 | 81 | Delete Users 82 | """ 83 | pass 84 | 85 | def test_get_user_user_get(self) -> None: 86 | """Test case for get_user_user_get 87 | 88 | Get User 89 | """ 90 | pass 91 | 92 | def test_get_users_users_get(self) -> None: 93 | """Test case for get_users_users_get 94 | 95 | Get Users 96 | """ 97 | pass 98 | 99 | def test_query_user_user_query_post(self) -> None: 100 | """Test case for query_user_user_query_post 101 | 102 | Query User 103 | """ 104 | pass 105 | 106 | def test_update_user_async_user_async_put(self) -> None: 107 | """Test case for update_user_async_user_async_put 108 | 109 | Update User Async 110 | """ 111 | pass 112 | 113 | def test_update_user_user_put(self) -> None: 114 | """Test case for update_user_user_put 115 | 116 | Update User 117 | """ 118 | pass 119 | 120 | def test_update_users_async_users_async_put(self) -> None: 121 | """Test case for update_users_async_users_async_put 122 | 123 | Update Users Async 124 | """ 125 | pass 126 | 127 | def test_update_users_users_put(self) -> None: 128 | """Test case for update_users_users_put 129 | 130 | Update Users 131 | """ 132 | pass 133 | 134 | 135 | if __name__ == "__main__": 136 | unittest.main() 137 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_user_query.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.user_query import UserQuery 18 | 19 | 20 | class TestUserQuery(unittest.TestCase): 21 | """UserQuery unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> UserQuery: 30 | """Test UserQuery 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `UserQuery` 35 | """ 36 | model = UserQuery() 37 | if include_optional: 38 | return UserQuery( 39 | id = 56, 40 | username = '', 41 | email = '', 42 | phone_number = '', 43 | preferences = [ 44 | null 45 | ], 46 | role = '' 47 | ) 48 | else: 49 | return UserQuery( 50 | ) 51 | """ 52 | 53 | def testUserQuery(self): 54 | """Test UserQuery""" 55 | # inst_req_only = self.make_instance(include_optional=False) 56 | # inst_req_and_optional = self.make_instance(include_optional=True) 57 | 58 | 59 | if __name__ == "__main__": 60 | unittest.main() 61 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_validation_error.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.validation_error import ValidationError 18 | 19 | 20 | class TestValidationError(unittest.TestCase): 21 | """ValidationError unit test stubs""" 22 | 23 | def setUp(self): 24 | pass 25 | 26 | def tearDown(self): 27 | pass 28 | 29 | def make_instance(self, include_optional) -> ValidationError: 30 | """Test ValidationError 31 | include_option is a boolean, when False only required 32 | params are included, when True both required and 33 | optional params are included""" 34 | # uncomment below to create an instance of `ValidationError` 35 | """ 36 | model = ValidationError() 37 | if include_optional: 38 | return ValidationError( 39 | loc = [ 40 | null 41 | ], 42 | msg = '', 43 | type = '' 44 | ) 45 | else: 46 | return ValidationError( 47 | loc = [ 48 | null 49 | ], 50 | msg = '', 51 | type = '', 52 | ) 53 | """ 54 | 55 | def testValidationError(self): 56 | """Test ValidationError""" 57 | # inst_req_only = self.make_instance(include_optional=False) 58 | # inst_req_and_optional = self.make_instance(include_optional=True) 59 | 60 | 61 | if __name__ == "__main__": 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /example/alembic/output/client/test/test_validation_error_loc_inner.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | FastAPI 5 | 6 | No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from openapi_client.models.validation_error_loc_inner import \ 18 | ValidationErrorLocInner 19 | 20 | 21 | class TestValidationErrorLocInner(unittest.TestCase): 22 | """ValidationErrorLocInner unit test stubs""" 23 | 24 | def setUp(self): 25 | pass 26 | 27 | def tearDown(self): 28 | pass 29 | 30 | def make_instance(self, include_optional) -> ValidationErrorLocInner: 31 | """Test ValidationErrorLocInner 32 | include_option is a boolean, when False only required 33 | params are included, when True both required and 34 | optional params are included""" 35 | # uncomment below to create an instance of `ValidationErrorLocInner` 36 | """ 37 | model = ValidationErrorLocInner() 38 | if include_optional: 39 | return ValidationErrorLocInner( 40 | ) 41 | else: 42 | return ValidationErrorLocInner( 43 | ) 44 | """ 45 | 46 | def testValidationErrorLocInner(self): 47 | """Test ValidationErrorLocInner""" 48 | # inst_req_only = self.make_instance(include_optional=False) 49 | # inst_req_and_optional = self.make_instance(include_optional=True) 50 | 51 | 52 | if __name__ == "__main__": 53 | unittest.main() 54 | -------------------------------------------------------------------------------- /example/alembic/output/client/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py3 3 | 4 | [testenv] 5 | deps=-r{toxinidir}/requirements.txt 6 | -r{toxinidir}/test-requirements.txt 7 | 8 | commands= 9 | pytest --cov=openapi_client 10 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "restaurant_app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.11.4", 7 | "@emotion/styled": "^11.11.5", 8 | "@mui/icons-material": "^5.15.20", 9 | "@mui/lab": "^5.0.0-alpha.170", 10 | "@mui/material": "^5.15.20", 11 | "@mui/styled-engine": "^5.15.14", 12 | "@mui/x-data-grid": "^7.7.0", 13 | "@testing-library/jest-dom": "^5.17.0", 14 | "@testing-library/react": "^13.4.0", 15 | "@testing-library/user-event": "^13.5.0", 16 | "@types/jest": "^27.5.2", 17 | "@types/node": "^16.18.98", 18 | "@types/react": "^18.3.3", 19 | "@types/react-dom": "^18.3.0", 20 | "axios": "^1.7.2", 21 | "eslint": "^8.57.0", 22 | "prettier": "^3.3.2", 23 | "react": "^18.3.1", 24 | "react-dom": "^18.3.1", 25 | "react-router-dom": "^6.23.1", 26 | "react-scripts": "5.0.1", 27 | "typescript": "^4.9.5", 28 | "web-vitals": "^2.1.4" 29 | }, 30 | "scripts": { 31 | "start": "react-scripts start", 32 | "build": "react-scripts build", 33 | "test": "react-scripts test", 34 | "eject": "react-scripts eject" 35 | }, 36 | "eslintConfig": { 37 | "extends": [ 38 | "react-app", 39 | "react-app/jest" 40 | ] 41 | }, 42 | "browserslist": { 43 | "production": [ 44 | ">0.2%", 45 | "not dead", 46 | "not op_mini all" 47 | ], 48 | "development": [ 49 | "last 1 chrome version", 50 | "last 1 firefox version", 51 | "last 1 safari version" 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/restaurant_app/public/favicon.ico -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/restaurant_app/public/logo192.png -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/example/alembic/output/restaurant_app/public/logo512.png -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render, screen } from "@testing-library/react"; 3 | import App from "./App"; 4 | 5 | test("renders learn react link", () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import logo from "./logo.svg"; 3 | import "./App.css"; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/.openapi-generator/FILES: -------------------------------------------------------------------------------- 1 | .openapi-generator-ignore 2 | apis/DefaultApi.ts 3 | apis/ReservationApi.ts 4 | apis/RestaurantApi.ts 5 | apis/ReviewApi.ts 6 | apis/UserApi.ts 7 | apis/index.ts 8 | index.ts 9 | models/HTTPValidationError.ts 10 | models/Reservation.ts 11 | models/ReservationQuery.ts 12 | models/Restaurant.ts 13 | models/RestaurantQuery.ts 14 | models/Review.ts 15 | models/ReviewQuery.ts 16 | models/User.ts 17 | models/UserQuery.ts 18 | models/ValidationError.ts 19 | models/ValidationErrorLocInner.ts 20 | models/index.ts 21 | runtime.ts 22 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.5.0 2 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/apis/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from "./DefaultApi"; 4 | export * from "./ReservationApi"; 5 | export * from "./RestaurantApi"; 6 | export * from "./ReviewApi"; 7 | export * from "./UserApi"; 8 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from "./runtime"; 4 | export * from "./apis/index"; 5 | export * from "./models/index"; 6 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/HTTPValidationError.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | import type { ValidationError } from "./ValidationError"; 17 | import { 18 | ValidationErrorFromJSON, 19 | ValidationErrorFromJSONTyped, 20 | ValidationErrorToJSON, 21 | } from "./ValidationError"; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface HTTPValidationError 27 | */ 28 | export interface HTTPValidationError { 29 | /** 30 | * 31 | * @type {Array} 32 | * @memberof HTTPValidationError 33 | */ 34 | detail?: Array; 35 | } 36 | 37 | /** 38 | * Check if a given object implements the HTTPValidationError interface. 39 | */ 40 | export function instanceOfHTTPValidationError(value: object): boolean { 41 | return true; 42 | } 43 | 44 | export function HTTPValidationErrorFromJSON(json: any): HTTPValidationError { 45 | return HTTPValidationErrorFromJSONTyped(json, false); 46 | } 47 | 48 | export function HTTPValidationErrorFromJSONTyped( 49 | json: any, 50 | ignoreDiscriminator: boolean, 51 | ): HTTPValidationError { 52 | if (json == null) { 53 | return json; 54 | } 55 | return { 56 | detail: 57 | json["detail"] == null 58 | ? undefined 59 | : (json["detail"] as Array).map(ValidationErrorFromJSON), 60 | }; 61 | } 62 | 63 | export function HTTPValidationErrorToJSON( 64 | value?: HTTPValidationError | null, 65 | ): any { 66 | if (value == null) { 67 | return value; 68 | } 69 | return { 70 | detail: 71 | value["detail"] == null 72 | ? undefined 73 | : (value["detail"] as Array).map(ValidationErrorToJSON), 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/ReservationQuery.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * Query model for Reservation 18 | * @export 19 | * @interface ReservationQuery 20 | */ 21 | export interface ReservationQuery { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof ReservationQuery 26 | */ 27 | id?: number; 28 | /** 29 | * 30 | * @type {number} 31 | * @memberof ReservationQuery 32 | */ 33 | restaurantId?: number; 34 | /** 35 | * 36 | * @type {number} 37 | * @memberof ReservationQuery 38 | */ 39 | userId?: number; 40 | /** 41 | * 42 | * @type {Date} 43 | * @memberof ReservationQuery 44 | */ 45 | reservationTime?: Date; 46 | /** 47 | * 48 | * @type {number} 49 | * @memberof ReservationQuery 50 | */ 51 | partySize?: number; 52 | /** 53 | * 54 | * @type {string} 55 | * @memberof ReservationQuery 56 | */ 57 | specialRequests?: string; 58 | } 59 | 60 | /** 61 | * Check if a given object implements the ReservationQuery interface. 62 | */ 63 | export function instanceOfReservationQuery(value: object): boolean { 64 | return true; 65 | } 66 | 67 | export function ReservationQueryFromJSON(json: any): ReservationQuery { 68 | return ReservationQueryFromJSONTyped(json, false); 69 | } 70 | 71 | export function ReservationQueryFromJSONTyped( 72 | json: any, 73 | ignoreDiscriminator: boolean, 74 | ): ReservationQuery { 75 | if (json == null) { 76 | return json; 77 | } 78 | return { 79 | id: json["id"] == null ? undefined : json["id"], 80 | restaurantId: 81 | json["restaurant_id"] == null ? undefined : json["restaurant_id"], 82 | userId: json["user_id"] == null ? undefined : json["user_id"], 83 | reservationTime: 84 | json["reservation_time"] == null 85 | ? undefined 86 | : new Date(json["reservation_time"]), 87 | partySize: json["party_size"] == null ? undefined : json["party_size"], 88 | specialRequests: 89 | json["special_requests"] == null ? undefined : json["special_requests"], 90 | }; 91 | } 92 | 93 | export function ReservationQueryToJSON(value?: ReservationQuery | null): any { 94 | if (value == null) { 95 | return value; 96 | } 97 | return { 98 | id: value["id"], 99 | restaurant_id: value["restaurantId"], 100 | user_id: value["userId"], 101 | reservation_time: 102 | value["reservationTime"] == null 103 | ? undefined 104 | : (value["reservationTime"] as any).toISOString(), 105 | party_size: value["partySize"], 106 | special_requests: value["specialRequests"], 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/Restaurant.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * 18 | * @export 19 | * @interface Restaurant 20 | */ 21 | export interface Restaurant { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof Restaurant 26 | */ 27 | id?: number; 28 | /** 29 | * The name of the alembic 30 | * @type {string} 31 | * @memberof Restaurant 32 | */ 33 | name: string; 34 | /** 35 | * The physical location of the alembic 36 | * @type {string} 37 | * @memberof Restaurant 38 | */ 39 | location: string; 40 | /** 41 | * 42 | * @type {string} 43 | * @memberof Restaurant 44 | */ 45 | cuisine?: string; 46 | /** 47 | * 48 | * @type {number} 49 | * @memberof Restaurant 50 | */ 51 | rating?: number; 52 | /** 53 | * 54 | * @type {string} 55 | * @memberof Restaurant 56 | */ 57 | priceRange?: string; 58 | /** 59 | * 60 | * @type {Date} 61 | * @memberof Restaurant 62 | */ 63 | createdAt?: Date; 64 | /** 65 | * 66 | * @type {Date} 67 | * @memberof Restaurant 68 | */ 69 | updatedAt?: Date; 70 | } 71 | 72 | /** 73 | * Check if a given object implements the Restaurant interface. 74 | */ 75 | export function instanceOfRestaurant(value: object): boolean { 76 | if (!("name" in value)) return false; 77 | if (!("location" in value)) return false; 78 | return true; 79 | } 80 | 81 | export function RestaurantFromJSON(json: any): Restaurant { 82 | return RestaurantFromJSONTyped(json, false); 83 | } 84 | 85 | export function RestaurantFromJSONTyped( 86 | json: any, 87 | ignoreDiscriminator: boolean, 88 | ): Restaurant { 89 | if (json == null) { 90 | return json; 91 | } 92 | return { 93 | id: json["id"] == null ? undefined : json["id"], 94 | name: json["name"], 95 | location: json["location"], 96 | cuisine: json["cuisine"] == null ? undefined : json["cuisine"], 97 | rating: json["rating"] == null ? undefined : json["rating"], 98 | priceRange: json["price_range"] == null ? undefined : json["price_range"], 99 | createdAt: 100 | json["created_at"] == null ? undefined : new Date(json["created_at"]), 101 | updatedAt: 102 | json["updated_at"] == null ? undefined : new Date(json["updated_at"]), 103 | }; 104 | } 105 | 106 | export function RestaurantToJSON(value?: Restaurant | null): any { 107 | if (value == null) { 108 | return value; 109 | } 110 | return { 111 | id: value["id"], 112 | name: value["name"], 113 | location: value["location"], 114 | cuisine: value["cuisine"], 115 | rating: value["rating"], 116 | price_range: value["priceRange"], 117 | created_at: 118 | value["createdAt"] == null 119 | ? undefined 120 | : (value["createdAt"] as any).toISOString(), 121 | updated_at: 122 | value["updatedAt"] == null 123 | ? undefined 124 | : (value["updatedAt"] as any).toISOString(), 125 | }; 126 | } 127 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/RestaurantQuery.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * Query model for Restaurant 18 | * @export 19 | * @interface RestaurantQuery 20 | */ 21 | export interface RestaurantQuery { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof RestaurantQuery 26 | */ 27 | id?: number; 28 | /** 29 | * 30 | * @type {string} 31 | * @memberof RestaurantQuery 32 | */ 33 | name?: string; 34 | /** 35 | * 36 | * @type {string} 37 | * @memberof RestaurantQuery 38 | */ 39 | location?: string; 40 | /** 41 | * 42 | * @type {string} 43 | * @memberof RestaurantQuery 44 | */ 45 | cuisine?: string; 46 | /** 47 | * 48 | * @type {number} 49 | * @memberof RestaurantQuery 50 | */ 51 | rating?: number; 52 | /** 53 | * 54 | * @type {string} 55 | * @memberof RestaurantQuery 56 | */ 57 | priceRange?: string; 58 | } 59 | 60 | /** 61 | * Check if a given object implements the RestaurantQuery interface. 62 | */ 63 | export function instanceOfRestaurantQuery(value: object): boolean { 64 | return true; 65 | } 66 | 67 | export function RestaurantQueryFromJSON(json: any): RestaurantQuery { 68 | return RestaurantQueryFromJSONTyped(json, false); 69 | } 70 | 71 | export function RestaurantQueryFromJSONTyped( 72 | json: any, 73 | ignoreDiscriminator: boolean, 74 | ): RestaurantQuery { 75 | if (json == null) { 76 | return json; 77 | } 78 | return { 79 | id: json["id"] == null ? undefined : json["id"], 80 | name: json["name"] == null ? undefined : json["name"], 81 | location: json["location"] == null ? undefined : json["location"], 82 | cuisine: json["cuisine"] == null ? undefined : json["cuisine"], 83 | rating: json["rating"] == null ? undefined : json["rating"], 84 | priceRange: json["price_range"] == null ? undefined : json["price_range"], 85 | }; 86 | } 87 | 88 | export function RestaurantQueryToJSON(value?: RestaurantQuery | null): any { 89 | if (value == null) { 90 | return value; 91 | } 92 | return { 93 | id: value["id"], 94 | name: value["name"], 95 | location: value["location"], 96 | cuisine: value["cuisine"], 97 | rating: value["rating"], 98 | price_range: value["priceRange"], 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/Review.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * 18 | * @export 19 | * @interface Review 20 | */ 21 | export interface Review { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof Review 26 | */ 27 | id?: number; 28 | /** 29 | * The ID of the alembic being reviewed 30 | * @type {number} 31 | * @memberof Review 32 | */ 33 | restaurantId: number; 34 | /** 35 | * The ID of the user who wrote the review 36 | * @type {number} 37 | * @memberof Review 38 | */ 39 | userId: number; 40 | /** 41 | * The rating given by the user 42 | * @type {number} 43 | * @memberof Review 44 | */ 45 | rating: number; 46 | /** 47 | * 48 | * @type {string} 49 | * @memberof Review 50 | */ 51 | comment?: string; 52 | /** 53 | * 54 | * @type {Date} 55 | * @memberof Review 56 | */ 57 | createdAt?: Date; 58 | /** 59 | * 60 | * @type {Date} 61 | * @memberof Review 62 | */ 63 | updatedAt?: Date; 64 | } 65 | 66 | /** 67 | * Check if a given object implements the Review interface. 68 | */ 69 | export function instanceOfReview(value: object): boolean { 70 | if (!("restaurantId" in value)) return false; 71 | if (!("userId" in value)) return false; 72 | if (!("rating" in value)) return false; 73 | return true; 74 | } 75 | 76 | export function ReviewFromJSON(json: any): Review { 77 | return ReviewFromJSONTyped(json, false); 78 | } 79 | 80 | export function ReviewFromJSONTyped( 81 | json: any, 82 | ignoreDiscriminator: boolean, 83 | ): Review { 84 | if (json == null) { 85 | return json; 86 | } 87 | return { 88 | id: json["id"] == null ? undefined : json["id"], 89 | restaurantId: json["restaurant_id"], 90 | userId: json["user_id"], 91 | rating: json["rating"], 92 | comment: json["comment"] == null ? undefined : json["comment"], 93 | createdAt: 94 | json["created_at"] == null ? undefined : new Date(json["created_at"]), 95 | updatedAt: 96 | json["updated_at"] == null ? undefined : new Date(json["updated_at"]), 97 | }; 98 | } 99 | 100 | export function ReviewToJSON(value?: Review | null): any { 101 | if (value == null) { 102 | return value; 103 | } 104 | return { 105 | id: value["id"], 106 | restaurant_id: value["restaurantId"], 107 | user_id: value["userId"], 108 | rating: value["rating"], 109 | comment: value["comment"], 110 | created_at: 111 | value["createdAt"] == null 112 | ? undefined 113 | : (value["createdAt"] as any).toISOString(), 114 | updated_at: 115 | value["updatedAt"] == null 116 | ? undefined 117 | : (value["updatedAt"] as any).toISOString(), 118 | }; 119 | } 120 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/ReviewQuery.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * Query model for Review 18 | * @export 19 | * @interface ReviewQuery 20 | */ 21 | export interface ReviewQuery { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof ReviewQuery 26 | */ 27 | id?: number; 28 | /** 29 | * 30 | * @type {number} 31 | * @memberof ReviewQuery 32 | */ 33 | restaurantId?: number; 34 | /** 35 | * 36 | * @type {number} 37 | * @memberof ReviewQuery 38 | */ 39 | userId?: number; 40 | /** 41 | * 42 | * @type {number} 43 | * @memberof ReviewQuery 44 | */ 45 | rating?: number; 46 | /** 47 | * 48 | * @type {string} 49 | * @memberof ReviewQuery 50 | */ 51 | comment?: string; 52 | } 53 | 54 | /** 55 | * Check if a given object implements the ReviewQuery interface. 56 | */ 57 | export function instanceOfReviewQuery(value: object): boolean { 58 | return true; 59 | } 60 | 61 | export function ReviewQueryFromJSON(json: any): ReviewQuery { 62 | return ReviewQueryFromJSONTyped(json, false); 63 | } 64 | 65 | export function ReviewQueryFromJSONTyped( 66 | json: any, 67 | ignoreDiscriminator: boolean, 68 | ): ReviewQuery { 69 | if (json == null) { 70 | return json; 71 | } 72 | return { 73 | id: json["id"] == null ? undefined : json["id"], 74 | restaurantId: 75 | json["restaurant_id"] == null ? undefined : json["restaurant_id"], 76 | userId: json["user_id"] == null ? undefined : json["user_id"], 77 | rating: json["rating"] == null ? undefined : json["rating"], 78 | comment: json["comment"] == null ? undefined : json["comment"], 79 | }; 80 | } 81 | 82 | export function ReviewQueryToJSON(value?: ReviewQuery | null): any { 83 | if (value == null) { 84 | return value; 85 | } 86 | return { 87 | id: value["id"], 88 | restaurant_id: value["restaurantId"], 89 | user_id: value["userId"], 90 | rating: value["rating"], 91 | comment: value["comment"], 92 | }; 93 | } 94 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/User.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * 18 | * @export 19 | * @interface User 20 | */ 21 | export interface User { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof User 26 | */ 27 | id?: number; 28 | /** 29 | * The username of the user 30 | * @type {string} 31 | * @memberof User 32 | */ 33 | username: string; 34 | /** 35 | * The email address of the user 36 | * @type {string} 37 | * @memberof User 38 | */ 39 | email: string; 40 | /** 41 | * 42 | * @type {string} 43 | * @memberof User 44 | */ 45 | phoneNumber?: string; 46 | /** 47 | * 48 | * @type {Array} 49 | * @memberof User 50 | */ 51 | preferences?: Array; 52 | /** 53 | * 54 | * @type {string} 55 | * @memberof User 56 | */ 57 | role?: string; 58 | /** 59 | * 60 | * @type {Date} 61 | * @memberof User 62 | */ 63 | createdAt?: Date; 64 | /** 65 | * 66 | * @type {Date} 67 | * @memberof User 68 | */ 69 | updatedAt?: Date; 70 | } 71 | 72 | /** 73 | * Check if a given object implements the User interface. 74 | */ 75 | export function instanceOfUser(value: object): boolean { 76 | if (!("username" in value)) return false; 77 | if (!("email" in value)) return false; 78 | return true; 79 | } 80 | 81 | export function UserFromJSON(json: any): User { 82 | return UserFromJSONTyped(json, false); 83 | } 84 | 85 | export function UserFromJSONTyped( 86 | json: any, 87 | ignoreDiscriminator: boolean, 88 | ): User { 89 | if (json == null) { 90 | return json; 91 | } 92 | return { 93 | id: json["id"] == null ? undefined : json["id"], 94 | username: json["username"], 95 | email: json["email"], 96 | phoneNumber: 97 | json["phone_number"] == null ? undefined : json["phone_number"], 98 | preferences: json["preferences"] == null ? undefined : json["preferences"], 99 | role: json["role"] == null ? undefined : json["role"], 100 | createdAt: 101 | json["created_at"] == null ? undefined : new Date(json["created_at"]), 102 | updatedAt: 103 | json["updated_at"] == null ? undefined : new Date(json["updated_at"]), 104 | }; 105 | } 106 | 107 | export function UserToJSON(value?: User | null): any { 108 | if (value == null) { 109 | return value; 110 | } 111 | return { 112 | id: value["id"], 113 | username: value["username"], 114 | email: value["email"], 115 | phone_number: value["phoneNumber"], 116 | preferences: value["preferences"], 117 | role: value["role"], 118 | created_at: 119 | value["createdAt"] == null 120 | ? undefined 121 | : (value["createdAt"] as any).toISOString(), 122 | updated_at: 123 | value["updatedAt"] == null 124 | ? undefined 125 | : (value["updatedAt"] as any).toISOString(), 126 | }; 127 | } 128 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/UserQuery.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * Query model for User 18 | * @export 19 | * @interface UserQuery 20 | */ 21 | export interface UserQuery { 22 | /** 23 | * 24 | * @type {number} 25 | * @memberof UserQuery 26 | */ 27 | id?: number; 28 | /** 29 | * 30 | * @type {string} 31 | * @memberof UserQuery 32 | */ 33 | username?: string; 34 | /** 35 | * 36 | * @type {string} 37 | * @memberof UserQuery 38 | */ 39 | email?: string; 40 | /** 41 | * 42 | * @type {string} 43 | * @memberof UserQuery 44 | */ 45 | phoneNumber?: string; 46 | /** 47 | * 48 | * @type {Array} 49 | * @memberof UserQuery 50 | */ 51 | preferences?: Array; 52 | /** 53 | * 54 | * @type {string} 55 | * @memberof UserQuery 56 | */ 57 | role?: string; 58 | } 59 | 60 | /** 61 | * Check if a given object implements the UserQuery interface. 62 | */ 63 | export function instanceOfUserQuery(value: object): boolean { 64 | return true; 65 | } 66 | 67 | export function UserQueryFromJSON(json: any): UserQuery { 68 | return UserQueryFromJSONTyped(json, false); 69 | } 70 | 71 | export function UserQueryFromJSONTyped( 72 | json: any, 73 | ignoreDiscriminator: boolean, 74 | ): UserQuery { 75 | if (json == null) { 76 | return json; 77 | } 78 | return { 79 | id: json["id"] == null ? undefined : json["id"], 80 | username: json["username"] == null ? undefined : json["username"], 81 | email: json["email"] == null ? undefined : json["email"], 82 | phoneNumber: 83 | json["phone_number"] == null ? undefined : json["phone_number"], 84 | preferences: json["preferences"] == null ? undefined : json["preferences"], 85 | role: json["role"] == null ? undefined : json["role"], 86 | }; 87 | } 88 | 89 | export function UserQueryToJSON(value?: UserQuery | null): any { 90 | if (value == null) { 91 | return value; 92 | } 93 | return { 94 | id: value["id"], 95 | username: value["username"], 96 | email: value["email"], 97 | phone_number: value["phoneNumber"], 98 | preferences: value["preferences"], 99 | role: value["role"], 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/ValidationError.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | import type { ValidationErrorLocInner } from "./ValidationErrorLocInner"; 17 | import { 18 | ValidationErrorLocInnerFromJSON, 19 | ValidationErrorLocInnerFromJSONTyped, 20 | ValidationErrorLocInnerToJSON, 21 | } from "./ValidationErrorLocInner"; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface ValidationError 27 | */ 28 | export interface ValidationError { 29 | /** 30 | * 31 | * @type {Array} 32 | * @memberof ValidationError 33 | */ 34 | loc: Array; 35 | /** 36 | * 37 | * @type {string} 38 | * @memberof ValidationError 39 | */ 40 | msg: string; 41 | /** 42 | * 43 | * @type {string} 44 | * @memberof ValidationError 45 | */ 46 | type: string; 47 | } 48 | 49 | /** 50 | * Check if a given object implements the ValidationError interface. 51 | */ 52 | export function instanceOfValidationError(value: object): boolean { 53 | if (!("loc" in value)) return false; 54 | if (!("msg" in value)) return false; 55 | if (!("type" in value)) return false; 56 | return true; 57 | } 58 | 59 | export function ValidationErrorFromJSON(json: any): ValidationError { 60 | return ValidationErrorFromJSONTyped(json, false); 61 | } 62 | 63 | export function ValidationErrorFromJSONTyped( 64 | json: any, 65 | ignoreDiscriminator: boolean, 66 | ): ValidationError { 67 | if (json == null) { 68 | return json; 69 | } 70 | return { 71 | loc: (json["loc"] as Array).map(ValidationErrorLocInnerFromJSON), 72 | msg: json["msg"], 73 | type: json["type"], 74 | }; 75 | } 76 | 77 | export function ValidationErrorToJSON(value?: ValidationError | null): any { 78 | if (value == null) { 79 | return value; 80 | } 81 | return { 82 | loc: (value["loc"] as Array).map(ValidationErrorLocInnerToJSON), 83 | msg: value["msg"], 84 | type: value["type"], 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/ValidationErrorLocInner.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * FastAPI 5 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 6 | * 7 | * The version of the OpenAPI document: 0.1.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { mapValues } from "../runtime"; 16 | /** 17 | * 18 | * @export 19 | * @interface ValidationErrorLocInner 20 | */ 21 | export interface ValidationErrorLocInner {} 22 | 23 | /** 24 | * Check if a given object implements the ValidationErrorLocInner interface. 25 | */ 26 | export function instanceOfValidationErrorLocInner(value: object): boolean { 27 | return true; 28 | } 29 | 30 | export function ValidationErrorLocInnerFromJSON( 31 | json: any, 32 | ): ValidationErrorLocInner { 33 | return ValidationErrorLocInnerFromJSONTyped(json, false); 34 | } 35 | 36 | export function ValidationErrorLocInnerFromJSONTyped( 37 | json: any, 38 | ignoreDiscriminator: boolean, 39 | ): ValidationErrorLocInner { 40 | return json; 41 | } 42 | 43 | export function ValidationErrorLocInnerToJSON( 44 | value?: ValidationErrorLocInner | null, 45 | ): any { 46 | return value; 47 | } 48 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/api/models/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from "./HTTPValidationError"; 4 | export * from "./Reservation"; 5 | export * from "./ReservationQuery"; 6 | export * from "./Restaurant"; 7 | export * from "./RestaurantQuery"; 8 | export * from "./Review"; 9 | export * from "./ReviewQuery"; 10 | export * from "./User"; 11 | export * from "./UserQuery"; 12 | export * from "./ValidationError"; 13 | export * from "./ValidationErrorLocInner"; 14 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/components/Home.tsx: -------------------------------------------------------------------------------- 1 | // Simple home page 2 | import React from "react"; 3 | import { Link } from "react-router-dom"; 4 | import Box from "@mui/material/Box"; 5 | import Typography from "@mui/material/Typography"; 6 | import Divider from "@mui/material/Divider"; 7 | 8 | export function Home() { 9 | return ( 10 | 11 |
12 | 13 | Welcome to the restaurant_app! 14 | 15 | 16 | 17 | To get started, click on one of the links below to view the different 18 | model pages! 19 | 20 | 21 | Models 22 | 23 | 24 | Users Page 25 | 26 | 27 | 28 | Restaurants Page 29 | 30 | 31 | 32 | Reservations Page 33 | 34 | 35 | 36 | Reviews Page 37 | 38 |
39 |
40 | ); 41 | } 42 | 43 | export default Home; 44 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/components/Layout.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Outlet } from "react-router-dom"; 3 | 4 | // MUI Components 5 | import AppBar from "@mui/material/AppBar"; 6 | import Box from "@mui/material/Box"; 7 | import Toolbar from "@mui/material/Toolbar"; 8 | import Typography from "@mui/material/Typography"; 9 | import Button from "@mui/material/Button"; 10 | 11 | function Layout() { 12 | // Define the pages and their routes 13 | const [pages_map] = React.useState>({ 14 | Home: "/home", 15 | 16 | User: "/user", 17 | 18 | Restaurant: "/restaurant", 19 | 20 | Reservation: "/reservation", 21 | 22 | Review: "/review", 23 | }); 24 | 25 | // Handle navigation to the page 26 | const handleNavToPage = (page: string) => { 27 | console.log("Navigating to page: " + page); 28 | window.location.href = pages_map[page]; 29 | }; 30 | 31 | // Render 32 | return ( 33 | <> 34 | 57 | 58 | 59 | ); 60 | } 61 | export default Layout; 62 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/components/NoPage.tsx: -------------------------------------------------------------------------------- 1 | const NoPage = () => { 2 | return

404: Page could not be found!

; 3 | }; 4 | 5 | export default NoPage; 6 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/components/utils.tsx: -------------------------------------------------------------------------------- 1 | import { Configuration } from "../api"; 2 | 3 | import { UserApi } from "../api"; 4 | 5 | import { RestaurantApi } from "../api"; 6 | 7 | import { ReservationApi } from "../api"; 8 | 9 | import { ReviewApi } from "../api"; 10 | 11 | const basePath = "http://localhost:8000"; 12 | 13 | // Helper function to parse fields based on their type prior to sending to the API 14 | const parseField = (field: string, type: string) => { 15 | switch (type) { 16 | case "string": 17 | return field; 18 | case "number": 19 | return Number(field); 20 | case "boolean": 21 | return field === "true"; 22 | case "date": 23 | return new Date(field); 24 | case "datetime": 25 | return new Date(field); 26 | case "array": 27 | return field.split(",").map((item) => (item as string).trim()); 28 | case "list": 29 | return field.split(",").map((item) => (item as string).trim()); 30 | case "object": 31 | return JSON.parse(field); 32 | default: 33 | return field; 34 | } 35 | }; 36 | 37 | // Fetch API client for User 38 | const getUserAPIClient = () => { 39 | const apiConfig = new Configuration({ 40 | basePath: basePath, 41 | }); 42 | return new UserApi(apiConfig); 43 | }; 44 | 45 | // Fetch API client for Restaurant 46 | const getRestaurantAPIClient = () => { 47 | const apiConfig = new Configuration({ 48 | basePath: basePath, 49 | }); 50 | return new RestaurantApi(apiConfig); 51 | }; 52 | 53 | // Fetch API client for Reservation 54 | const getReservationAPIClient = () => { 55 | const apiConfig = new Configuration({ 56 | basePath: basePath, 57 | }); 58 | return new ReservationApi(apiConfig); 59 | }; 60 | 61 | // Fetch API client for Review 62 | const getReviewAPIClient = () => { 63 | const apiConfig = new Configuration({ 64 | basePath: basePath, 65 | }); 66 | return new ReviewApi(apiConfig); 67 | }; 68 | 69 | // Export all API clients and utility functions 70 | export { 71 | getUserAPIClient, 72 | getRestaurantAPIClient, 73 | getReservationAPIClient, 74 | getReviewAPIClient, 75 | parseField, 76 | }; 77 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import reportWebVitals from "./reportWebVitals"; 5 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 6 | 7 | // Import Models 8 | 9 | import UserPage from "./components/user_page"; 10 | 11 | import RestaurantPage from "./components/restaurant_page"; 12 | 13 | import ReservationPage from "./components/reservation_page"; 14 | 15 | import ReviewPage from "./components/review_page"; 16 | 17 | // Layout and other pages 18 | import Home from "./components/Home"; 19 | import Layout from "./components/Layout"; 20 | 21 | export default function HomePage() { 22 | return ( 23 | 24 | 25 | }> 26 | {/* Add other pages here */} 27 | } /> 28 | } /> 29 | 30 | {/* Add other pages here */} 31 | 32 | } /> 33 | 34 | } /> 35 | 36 | } /> 37 | 38 | } /> 39 | 40 | 41 | 42 | ); 43 | } 44 | 45 | const root = ReactDOM.createRoot( 46 | document.getElementById("root") as HTMLElement, 47 | ); 48 | 49 | root.render(); 50 | 51 | // If you want to start measuring performance in your app, pass a function 52 | // to log results (for example: reportWebVitals(console.log)) 53 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 54 | reportWebVitals(); 55 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from "web-vitals"; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import "@testing-library/jest-dom"; 6 | -------------------------------------------------------------------------------- /example/alembic/output/restaurant_app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /images/home_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/images/home_page.png -------------------------------------------------------------------------------- /images/postman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/images/postman.png -------------------------------------------------------------------------------- /images/reservation_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/images/reservation_page.png -------------------------------------------------------------------------------- /images/restaurant_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/images/restaurant_page.png -------------------------------------------------------------------------------- /images/review_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/images/review_page.png -------------------------------------------------------------------------------- /images/user_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick-roberson/fastapi-gen/962ce6f8fe57d6b1b7f525fec8d4daea8a533a99/images/user_page.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "builder" 3 | version = "1.0.0" 4 | description = "A service builder for creating RESTful APIs and React frontends" 5 | authors = ["nick-roberson "] 6 | readme = "README.md" 7 | license = "MIT" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.12.2" 11 | pyyaml = "^6.0.1" 12 | jinja2 = "^3.1.3" 13 | pydantic = "^2.6.4" 14 | fastapi = "^0.110.0" 15 | uvicorn = "^0.28.0" 16 | certifi = "^2024.2.2" 17 | rich = "^13.7.1" 18 | isort = "^5.13.2" 19 | black = "^24.2.0" 20 | typer = "^0.9.0" 21 | pytest = "^8.1.1" 22 | coverage = "^7.4.4" 23 | faker = "^24.7.1" 24 | alembic = "^1.13.1" 25 | sqlalchemy = "^2.0.29" 26 | pymysql = "^1.1.0" 27 | httpx = "^0.27.0" 28 | urllib3 = "^2.2.1" 29 | requests = "^2.31.0" 30 | psycopg2-binary = "^2.9.9" 31 | celery = "^5.4.0" 32 | redis = "^5.0.4" 33 | 34 | [tool.poetry.scripts] 35 | builder = "builder:app" 36 | 37 | [build-system] 38 | requires = ["poetry-core"] 39 | build-backend = "poetry.core.masonry.api" 40 | --------------------------------------------------------------------------------