create-autostack 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -0
- package/bin/index.js +675 -0
- package/lib/PackageManagerClass.js +185 -0
- package/package.json +55 -0
- package/templates/assets/fastapi.svg +1 -0
- package/templates/assets/flask.svg +1 -0
- package/templates/assets/mongodb.svg +1 -0
- package/templates/assets/mysql.svg +1 -0
- package/templates/assets/nodejs.svg +1 -0
- package/templates/assets/postgresql.svg +1 -0
- package/templates/backend/FASTAPI/MONGODB/.env +1 -0
- package/templates/backend/FASTAPI/MONGODB/config.py +26 -0
- package/templates/backend/FASTAPI/MONGODB/main.py +32 -0
- package/templates/backend/FASTAPI/MONGODB/models.py +56 -0
- package/templates/backend/FASTAPI/MONGODB/requirements.txt +6 -0
- package/templates/backend/FASTAPI/MONGODB/routes.py +189 -0
- package/templates/backend/FASTAPI/MONGODB/schemas.py +31 -0
- package/templates/backend/FASTAPI/MYSQL/.env +5 -0
- package/templates/backend/FASTAPI/MYSQL/config.py +29 -0
- package/templates/backend/FASTAPI/MYSQL/main.py +32 -0
- package/templates/backend/FASTAPI/MYSQL/models.py +31 -0
- package/templates/backend/FASTAPI/MYSQL/requirements.txt +6 -0
- package/templates/backend/FASTAPI/MYSQL/routes.py +180 -0
- package/templates/backend/FASTAPI/MYSQL/schemas.py +36 -0
- package/templates/backend/FASTAPI/POSTGRESQL/.env +5 -0
- package/templates/backend/FASTAPI/POSTGRESQL/config.py +29 -0
- package/templates/backend/FASTAPI/POSTGRESQL/main.py +32 -0
- package/templates/backend/FASTAPI/POSTGRESQL/models.py +31 -0
- package/templates/backend/FASTAPI/POSTGRESQL/requirements.txt +6 -0
- package/templates/backend/FASTAPI/POSTGRESQL/routes.py +180 -0
- package/templates/backend/FASTAPI/POSTGRESQL/schemas.py +36 -0
- package/templates/backend/FLASK/MONGODB/.env +6 -0
- package/templates/backend/FLASK/MONGODB/config.py +27 -0
- package/templates/backend/FLASK/MONGODB/main.py +5 -0
- package/templates/backend/FLASK/MONGODB/models.py +16 -0
- package/templates/backend/FLASK/MONGODB/requirements.txt +6 -0
- package/templates/backend/FLASK/MONGODB/routes.py +137 -0
- package/templates/backend/FLASK/MYSQL/.env +7 -0
- package/templates/backend/FLASK/MYSQL/config.py +24 -0
- package/templates/backend/FLASK/MYSQL/main.py +8 -0
- package/templates/backend/FLASK/MYSQL/models.py +26 -0
- package/templates/backend/FLASK/MYSQL/requirements.txt +6 -0
- package/templates/backend/FLASK/MYSQL/routes.py +135 -0
- package/templates/backend/FLASK/POSTGRESQL/.env +5 -0
- package/templates/backend/FLASK/POSTGRESQL/config.py +24 -0
- package/templates/backend/FLASK/POSTGRESQL/main.py +7 -0
- package/templates/backend/FLASK/POSTGRESQL/models.py +26 -0
- package/templates/backend/FLASK/POSTGRESQL/requirements.txt +6 -0
- package/templates/backend/FLASK/POSTGRESQL/routes.py +134 -0
- package/templates/backend/NODEJS/MONGODB/config/dbConn.js +11 -0
- package/templates/backend/NODEJS/MONGODB/controllers/noteController.js +79 -0
- package/templates/backend/NODEJS/MONGODB/controllers/userController.js +79 -0
- package/templates/backend/NODEJS/MONGODB/index.js +39 -0
- package/templates/backend/NODEJS/MONGODB/models/noteModel.js +17 -0
- package/templates/backend/NODEJS/MONGODB/models/userModel.js +17 -0
- package/templates/backend/NODEJS/MYSQL/config/dbConn.js +20 -0
- package/templates/backend/NODEJS/MYSQL/controllers/noteController.js +97 -0
- package/templates/backend/NODEJS/MYSQL/controllers/userController.js +98 -0
- package/templates/backend/NODEJS/MYSQL/index.js +39 -0
- package/templates/backend/NODEJS/MYSQL/models.txt +3 -0
- package/templates/backend/NODEJS/POSTGRESQL/config/dbConn.js +28 -0
- package/templates/backend/NODEJS/POSTGRESQL/controllers/noteController.js +91 -0
- package/templates/backend/NODEJS/POSTGRESQL/controllers/userController.js +92 -0
- package/templates/backend/NODEJS/POSTGRESQL/index.js +39 -0
- package/templates/backend/NODEJS/POSTGRESQL/models.txt +3 -0
- package/templates/backend/NODEJS/common/middleware/upstash.js +12 -0
- package/templates/backend/NODEJS/common/routes/noteRoutes.js +22 -0
- package/templates/backend/NODEJS/common/routes/userRoutes.js +22 -0
- package/templates/frontend/PREACT/src/app.jsx +103 -0
- package/templates/frontend/PREACT/vite.config.js +8 -0
- package/templates/frontend/PREACT-TS/src/app.tsx +112 -0
- package/templates/frontend/PREACT-TS/vite.config.ts +8 -0
- package/templates/frontend/REACT/src/App.css +27 -0
- package/templates/frontend/REACT/src/App.jsx +105 -0
- package/templates/frontend/REACT/vite.config.js +8 -0
- package/templates/frontend/REACT-SWC/src/App.css +27 -0
- package/templates/frontend/REACT-SWC/src/App.jsx +105 -0
- package/templates/frontend/REACT-SWC/vite.config.js +8 -0
- package/templates/frontend/REACT-SWC-TS/src/App.css +27 -0
- package/templates/frontend/REACT-SWC-TS/src/App.tsx +114 -0
- package/templates/frontend/REACT-SWC-TS/vite.config.ts +8 -0
- package/templates/frontend/REACT-TS/src/App.css +27 -0
- package/templates/frontend/REACT-TS/src/App.tsx +114 -0
- package/templates/frontend/REACT-TS/vite.config.ts +8 -0
- package/templates/frontend/SOLID/src/App.jsx +104 -0
- package/templates/frontend/SOLID/vite.config.js +7 -0
- package/templates/frontend/SOLID-TS/src/App.tsx +116 -0
- package/templates/frontend/SOLID-TS/vite.config.ts +7 -0
- package/templates/frontend/SVELTE/src/App.svelte +104 -0
- package/templates/frontend/SVELTE/vite.config.js +8 -0
- package/templates/frontend/SVELTE-TS/src/App.svelte +116 -0
- package/templates/frontend/SVELTE-TS/vite.config.ts +8 -0
- package/templates/frontend/VUE/src/App.vue +96 -0
- package/templates/frontend/VUE/vite.config.js +8 -0
- package/templates/frontend/VUE-TS/src/App.vue +112 -0
- package/templates/frontend/VUE-TS/vite.config.ts +8 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from sqlalchemy import create_engine
|
|
2
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
3
|
+
from sqlalchemy.orm import sessionmaker
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
# MySQL connection via environment variables
|
|
10
|
+
DB_USER = os.getenv("DB_USER", "root")
|
|
11
|
+
DB_PASSWORD = os.getenv("DB_PASSWORD", "")
|
|
12
|
+
DB_HOST = os.getenv("DB_HOST", "localhost")
|
|
13
|
+
DB_PORT = os.getenv("DB_PORT", "3306")
|
|
14
|
+
DB_NAME = os.getenv("DB_NAME", "example_db")
|
|
15
|
+
|
|
16
|
+
DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
|
|
17
|
+
|
|
18
|
+
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
|
|
19
|
+
|
|
20
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
21
|
+
|
|
22
|
+
Base = declarative_base()
|
|
23
|
+
|
|
24
|
+
def get_db():
|
|
25
|
+
db = SessionLocal()
|
|
26
|
+
try:
|
|
27
|
+
yield db
|
|
28
|
+
finally:
|
|
29
|
+
db.close()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from fastapi import FastAPI, HTTPException, status
|
|
2
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
3
|
+
from contextlib import asynccontextmanager
|
|
4
|
+
from config import engine, Base
|
|
5
|
+
from routes import router
|
|
6
|
+
|
|
7
|
+
@asynccontextmanager
|
|
8
|
+
async def lifespan(app: FastAPI):
|
|
9
|
+
Base.metadata.create_all(bind=engine)
|
|
10
|
+
yield
|
|
11
|
+
|
|
12
|
+
app = FastAPI(
|
|
13
|
+
title="AutoStack API",
|
|
14
|
+
description="Full-stack API built with FastAPI and MySQL",
|
|
15
|
+
version="1.0.0",
|
|
16
|
+
lifespan=lifespan
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# CORS middleware
|
|
20
|
+
app.add_middleware(
|
|
21
|
+
CORSMiddleware,
|
|
22
|
+
allow_origins=["*"], # Adjust this in production
|
|
23
|
+
allow_credentials=True,
|
|
24
|
+
allow_methods=["*"],
|
|
25
|
+
allow_headers=["*"],
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
app.include_router(router)
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
import uvicorn
|
|
32
|
+
uvicorn.run("main:app", host="0.0.0.0", port=5000, reload=True)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from sqlalchemy import Column, Integer, String
|
|
2
|
+
from config import Base
|
|
3
|
+
|
|
4
|
+
class User(Base):
|
|
5
|
+
__tablename__ = "user"
|
|
6
|
+
|
|
7
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
8
|
+
username = Column(String(80), unique=True, nullable=False, index=True)
|
|
9
|
+
email = Column(String(120), unique=True, nullable=False)
|
|
10
|
+
|
|
11
|
+
def to_json(self):
|
|
12
|
+
return {
|
|
13
|
+
"id": self.id,
|
|
14
|
+
"username": self.username,
|
|
15
|
+
"email": self.email
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Note(Base):
|
|
20
|
+
__tablename__ = "note"
|
|
21
|
+
|
|
22
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
23
|
+
title = Column(String(80), unique=True, nullable=False, index=True)
|
|
24
|
+
content = Column(String(120), unique=True, nullable=False)
|
|
25
|
+
|
|
26
|
+
def to_json(self):
|
|
27
|
+
return {
|
|
28
|
+
"id": self.id,
|
|
29
|
+
"title": self.title,
|
|
30
|
+
"content": self.content
|
|
31
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from fastapi import APIRouter, Depends, HTTPException, status
|
|
2
|
+
from sqlalchemy.orm import Session
|
|
3
|
+
from typing import List
|
|
4
|
+
from config import get_db
|
|
5
|
+
from models import User, Note
|
|
6
|
+
from schemas import (
|
|
7
|
+
UserCreate, UserUpdate, UserResponse,
|
|
8
|
+
NoteCreate, NoteUpdate, NoteResponse
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
router = APIRouter()
|
|
12
|
+
|
|
13
|
+
@router.get("/", status_code=status.HTTP_200_OK)
|
|
14
|
+
def autostack():
|
|
15
|
+
message = """
|
|
16
|
+
Congrats! You have successfully set up your full-stack project!
|
|
17
|
+
If you're reading this message, it means your frontend and backend are completely connected!
|
|
18
|
+
You are ready to create your next big project!
|
|
19
|
+
"""
|
|
20
|
+
return {"message": message, "backend": "FastAPI", "database": "PostgreSQL", "filepath": 'backend/main.py'}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Example User REST APIs
|
|
24
|
+
@router.get("/get-users", response_model=dict, status_code=status.HTTP_200_OK)
|
|
25
|
+
def get_users(db: Session = Depends(get_db)):
|
|
26
|
+
users = db.query(User).all()
|
|
27
|
+
json_users = [user.to_json() for user in users]
|
|
28
|
+
return {"users": json_users}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@router.post("/create-user", status_code=status.HTTP_201_CREATED)
|
|
32
|
+
def create_user(user: UserCreate, db: Session = Depends(get_db)):
|
|
33
|
+
new_user = User(username=user.username, email=user.email)
|
|
34
|
+
try:
|
|
35
|
+
db.add(new_user)
|
|
36
|
+
db.commit()
|
|
37
|
+
db.refresh(new_user)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
db.rollback()
|
|
40
|
+
raise HTTPException(
|
|
41
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
42
|
+
detail=str(e)
|
|
43
|
+
)
|
|
44
|
+
return {"message": "New User Created"}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@router.patch("/update-users/{user_id}", status_code=status.HTTP_200_OK)
|
|
48
|
+
def update_user(user_id: int, user_data: UserUpdate, db: Session = Depends(get_db)):
|
|
49
|
+
user = db.query(User).filter(User.id == user_id).first()
|
|
50
|
+
|
|
51
|
+
if not user:
|
|
52
|
+
raise HTTPException(
|
|
53
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
54
|
+
detail="User not found"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
update_data = user_data.model_dump(exclude_unset=True)
|
|
58
|
+
if not update_data:
|
|
59
|
+
raise HTTPException(
|
|
60
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
61
|
+
detail="No data provided"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
for field, value in update_data.items():
|
|
65
|
+
setattr(user, field, value)
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
db.commit()
|
|
69
|
+
db.refresh(user)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
db.rollback()
|
|
72
|
+
raise HTTPException(
|
|
73
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
74
|
+
detail=str(e)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return {"message": "User Updated"}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@router.delete("/delete-user/{user_id}", status_code=status.HTTP_200_OK)
|
|
81
|
+
def delete_user(user_id: int, db: Session = Depends(get_db)):
|
|
82
|
+
user = db.query(User).filter(User.id == user_id).first()
|
|
83
|
+
|
|
84
|
+
if not user:
|
|
85
|
+
raise HTTPException(
|
|
86
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
87
|
+
detail="User not found"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
db.delete(user)
|
|
92
|
+
db.commit()
|
|
93
|
+
except Exception as e:
|
|
94
|
+
db.rollback()
|
|
95
|
+
raise HTTPException(
|
|
96
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
97
|
+
detail=str(e)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return {"message": "User Deleted"}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Example Note REST APIs
|
|
104
|
+
@router.get("/get-notes", response_model=dict, status_code=status.HTTP_200_OK)
|
|
105
|
+
def get_notes(db: Session = Depends(get_db)):
|
|
106
|
+
notes = db.query(Note).all()
|
|
107
|
+
json_notes = [note.to_json() for note in notes]
|
|
108
|
+
return {"notes": json_notes}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@router.post("/create-note", status_code=status.HTTP_201_CREATED)
|
|
112
|
+
def create_note(note: NoteCreate, db: Session = Depends(get_db)):
|
|
113
|
+
new_note = Note(title=note.title, content=note.content)
|
|
114
|
+
try:
|
|
115
|
+
db.add(new_note)
|
|
116
|
+
db.commit()
|
|
117
|
+
db.refresh(new_note)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
db.rollback()
|
|
120
|
+
raise HTTPException(
|
|
121
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
122
|
+
detail=str(e)
|
|
123
|
+
)
|
|
124
|
+
return {"message": "New Note Created"}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@router.patch("/update-notes/{note_id}", status_code=status.HTTP_200_OK)
|
|
128
|
+
def update_note(note_id: int, note_data: NoteUpdate, db: Session = Depends(get_db)):
|
|
129
|
+
note = db.query(Note).filter(Note.id == note_id).first()
|
|
130
|
+
|
|
131
|
+
if not note:
|
|
132
|
+
raise HTTPException(
|
|
133
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
134
|
+
detail="Note not found"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
update_data = note_data.model_dump(exclude_unset=True)
|
|
138
|
+
if not update_data:
|
|
139
|
+
raise HTTPException(
|
|
140
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
141
|
+
detail="No data provided for updation"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
for field, value in update_data.items():
|
|
145
|
+
setattr(note, field, value)
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
db.commit()
|
|
149
|
+
db.refresh(note)
|
|
150
|
+
except Exception as e:
|
|
151
|
+
db.rollback()
|
|
152
|
+
raise HTTPException(
|
|
153
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
154
|
+
detail=str(e)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return {"message": "Note Updated"}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@router.delete("/delete-note/{note_id}", status_code=status.HTTP_200_OK)
|
|
161
|
+
def delete_note(note_id: int, db: Session = Depends(get_db)):
|
|
162
|
+
note = db.query(Note).filter(Note.id == note_id).first()
|
|
163
|
+
|
|
164
|
+
if not note:
|
|
165
|
+
raise HTTPException(
|
|
166
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
167
|
+
detail="Note not found"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
db.delete(note)
|
|
172
|
+
db.commit()
|
|
173
|
+
except Exception as e:
|
|
174
|
+
db.rollback()
|
|
175
|
+
raise HTTPException(
|
|
176
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
177
|
+
detail=str(e)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
return {"message": "Note Deleted"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from pydantic import BaseModel, EmailStr
|
|
2
|
+
|
|
3
|
+
# User Schemas
|
|
4
|
+
class UserCreate(BaseModel):
|
|
5
|
+
username: str
|
|
6
|
+
email: EmailStr
|
|
7
|
+
|
|
8
|
+
class UserUpdate(BaseModel):
|
|
9
|
+
username: str | None = None
|
|
10
|
+
email: EmailStr | None = None
|
|
11
|
+
|
|
12
|
+
class UserResponse(BaseModel):
|
|
13
|
+
id: int
|
|
14
|
+
username: str
|
|
15
|
+
email: str
|
|
16
|
+
|
|
17
|
+
class Config:
|
|
18
|
+
from_attributes = True
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Note Schemas
|
|
22
|
+
class NoteCreate(BaseModel):
|
|
23
|
+
title: str
|
|
24
|
+
content: str
|
|
25
|
+
|
|
26
|
+
class NoteUpdate(BaseModel):
|
|
27
|
+
title: str | None = None
|
|
28
|
+
content: str | None = None
|
|
29
|
+
|
|
30
|
+
class NoteResponse(BaseModel):
|
|
31
|
+
id: int
|
|
32
|
+
title: str
|
|
33
|
+
content: str
|
|
34
|
+
|
|
35
|
+
class Config:
|
|
36
|
+
from_attributes = True
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from sqlalchemy import create_engine
|
|
2
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
3
|
+
from sqlalchemy.orm import sessionmaker
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
# PostgreSQL connection via environment variables
|
|
10
|
+
DB_USER = os.getenv("DB_USER", "postgres")
|
|
11
|
+
DB_PASSWORD = os.getenv("DB_PASSWORD", "")
|
|
12
|
+
DB_HOST = os.getenv("DB_HOST", "localhost")
|
|
13
|
+
DB_PORT = os.getenv("DB_PORT", "5432")
|
|
14
|
+
DB_NAME = os.getenv("DB_NAME", "example_db")
|
|
15
|
+
|
|
16
|
+
DATABASE_URL = f"postgresql+psycopg2://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
|
|
17
|
+
|
|
18
|
+
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
|
|
19
|
+
|
|
20
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
21
|
+
|
|
22
|
+
Base = declarative_base()
|
|
23
|
+
|
|
24
|
+
def get_db():
|
|
25
|
+
db = SessionLocal()
|
|
26
|
+
try:
|
|
27
|
+
yield db
|
|
28
|
+
finally:
|
|
29
|
+
db.close()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from fastapi import FastAPI, HTTPException, status
|
|
2
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
3
|
+
from contextlib import asynccontextmanager
|
|
4
|
+
from config import engine, Base
|
|
5
|
+
from routes import router
|
|
6
|
+
|
|
7
|
+
@asynccontextmanager
|
|
8
|
+
async def lifespan(app: FastAPI):
|
|
9
|
+
Base.metadata.create_all(bind=engine)
|
|
10
|
+
yield
|
|
11
|
+
|
|
12
|
+
app = FastAPI(
|
|
13
|
+
title="AutoStack API",
|
|
14
|
+
description="Full-stack API built with FastAPI and MySQL",
|
|
15
|
+
version="1.0.0",
|
|
16
|
+
lifespan=lifespan
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# CORS middleware
|
|
20
|
+
app.add_middleware(
|
|
21
|
+
CORSMiddleware,
|
|
22
|
+
allow_origins=["*"], # Adjust this in production
|
|
23
|
+
allow_credentials=True,
|
|
24
|
+
allow_methods=["*"],
|
|
25
|
+
allow_headers=["*"],
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
app.include_router(router)
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
import uvicorn
|
|
32
|
+
uvicorn.run("main:app", host="0.0.0.0", port=5000, reload=True)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from sqlalchemy import Column, Integer, String
|
|
2
|
+
from config import Base
|
|
3
|
+
|
|
4
|
+
class User(Base):
|
|
5
|
+
__tablename__ = "user"
|
|
6
|
+
|
|
7
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
8
|
+
username = Column(String(80), unique=True, nullable=False, index=True)
|
|
9
|
+
email = Column(String(120), unique=True, nullable=False)
|
|
10
|
+
|
|
11
|
+
def to_json(self):
|
|
12
|
+
return {
|
|
13
|
+
"id": self.id,
|
|
14
|
+
"username": self.username,
|
|
15
|
+
"email": self.email
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Note(Base):
|
|
20
|
+
__tablename__ = "note"
|
|
21
|
+
|
|
22
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
23
|
+
title = Column(String(80), unique=True, nullable=False, index=True)
|
|
24
|
+
content = Column(String(120), unique=True, nullable=False)
|
|
25
|
+
|
|
26
|
+
def to_json(self):
|
|
27
|
+
return {
|
|
28
|
+
"id": self.id,
|
|
29
|
+
"title": self.title,
|
|
30
|
+
"content": self.content
|
|
31
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from fastapi import APIRouter, Depends, HTTPException, status
|
|
2
|
+
from sqlalchemy.orm import Session
|
|
3
|
+
from typing import List
|
|
4
|
+
from config import get_db
|
|
5
|
+
from models import User, Note
|
|
6
|
+
from schemas import (
|
|
7
|
+
UserCreate, UserUpdate, UserResponse,
|
|
8
|
+
NoteCreate, NoteUpdate, NoteResponse
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
router = APIRouter()
|
|
12
|
+
|
|
13
|
+
@router.get("/", status_code=status.HTTP_200_OK)
|
|
14
|
+
def autostack():
|
|
15
|
+
message = """
|
|
16
|
+
Congrats! You have successfully set up your full-stack project!
|
|
17
|
+
If you're reading this message, it means your frontend and backend are completely connected!
|
|
18
|
+
You are ready to create your next big project!
|
|
19
|
+
"""
|
|
20
|
+
return {"message": message, "backend": "FastAPI", "database": "PostgreSQL", "filepath": 'backend/main.py'}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Example User REST APIs
|
|
24
|
+
@router.get("/get-users", response_model=dict, status_code=status.HTTP_200_OK)
|
|
25
|
+
def get_users(db: Session = Depends(get_db)):
|
|
26
|
+
users = db.query(User).all()
|
|
27
|
+
json_users = [user.to_json() for user in users]
|
|
28
|
+
return {"users": json_users}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@router.post("/create-user", status_code=status.HTTP_201_CREATED)
|
|
32
|
+
def create_user(user: UserCreate, db: Session = Depends(get_db)):
|
|
33
|
+
new_user = User(username=user.username, email=user.email)
|
|
34
|
+
try:
|
|
35
|
+
db.add(new_user)
|
|
36
|
+
db.commit()
|
|
37
|
+
db.refresh(new_user)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
db.rollback()
|
|
40
|
+
raise HTTPException(
|
|
41
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
42
|
+
detail=str(e)
|
|
43
|
+
)
|
|
44
|
+
return {"message": "New User Created"}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@router.patch("/update-users/{user_id}", status_code=status.HTTP_200_OK)
|
|
48
|
+
def update_user(user_id: int, user_data: UserUpdate, db: Session = Depends(get_db)):
|
|
49
|
+
user = db.query(User).filter(User.id == user_id).first()
|
|
50
|
+
|
|
51
|
+
if not user:
|
|
52
|
+
raise HTTPException(
|
|
53
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
54
|
+
detail="User not found"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
update_data = user_data.model_dump(exclude_unset=True)
|
|
58
|
+
if not update_data:
|
|
59
|
+
raise HTTPException(
|
|
60
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
61
|
+
detail="No data provided"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
for field, value in update_data.items():
|
|
65
|
+
setattr(user, field, value)
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
db.commit()
|
|
69
|
+
db.refresh(user)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
db.rollback()
|
|
72
|
+
raise HTTPException(
|
|
73
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
74
|
+
detail=str(e)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return {"message": "User Updated"}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@router.delete("/delete-user/{user_id}", status_code=status.HTTP_200_OK)
|
|
81
|
+
def delete_user(user_id: int, db: Session = Depends(get_db)):
|
|
82
|
+
user = db.query(User).filter(User.id == user_id).first()
|
|
83
|
+
|
|
84
|
+
if not user:
|
|
85
|
+
raise HTTPException(
|
|
86
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
87
|
+
detail="User not found"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
db.delete(user)
|
|
92
|
+
db.commit()
|
|
93
|
+
except Exception as e:
|
|
94
|
+
db.rollback()
|
|
95
|
+
raise HTTPException(
|
|
96
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
97
|
+
detail=str(e)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return {"message": "User Deleted"}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Example Note REST APIs
|
|
104
|
+
@router.get("/get-notes", response_model=dict, status_code=status.HTTP_200_OK)
|
|
105
|
+
def get_notes(db: Session = Depends(get_db)):
|
|
106
|
+
notes = db.query(Note).all()
|
|
107
|
+
json_notes = [note.to_json() for note in notes]
|
|
108
|
+
return {"notes": json_notes}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@router.post("/create-note", status_code=status.HTTP_201_CREATED)
|
|
112
|
+
def create_note(note: NoteCreate, db: Session = Depends(get_db)):
|
|
113
|
+
new_note = Note(title=note.title, content=note.content)
|
|
114
|
+
try:
|
|
115
|
+
db.add(new_note)
|
|
116
|
+
db.commit()
|
|
117
|
+
db.refresh(new_note)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
db.rollback()
|
|
120
|
+
raise HTTPException(
|
|
121
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
122
|
+
detail=str(e)
|
|
123
|
+
)
|
|
124
|
+
return {"message": "New Note Created"}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@router.patch("/update-notes/{note_id}", status_code=status.HTTP_200_OK)
|
|
128
|
+
def update_note(note_id: int, note_data: NoteUpdate, db: Session = Depends(get_db)):
|
|
129
|
+
note = db.query(Note).filter(Note.id == note_id).first()
|
|
130
|
+
|
|
131
|
+
if not note:
|
|
132
|
+
raise HTTPException(
|
|
133
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
134
|
+
detail="Note not found"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
update_data = note_data.model_dump(exclude_unset=True)
|
|
138
|
+
if not update_data:
|
|
139
|
+
raise HTTPException(
|
|
140
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
141
|
+
detail="No data provided for updation"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
for field, value in update_data.items():
|
|
145
|
+
setattr(note, field, value)
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
db.commit()
|
|
149
|
+
db.refresh(note)
|
|
150
|
+
except Exception as e:
|
|
151
|
+
db.rollback()
|
|
152
|
+
raise HTTPException(
|
|
153
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
154
|
+
detail=str(e)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return {"message": "Note Updated"}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@router.delete("/delete-note/{note_id}", status_code=status.HTTP_200_OK)
|
|
161
|
+
def delete_note(note_id: int, db: Session = Depends(get_db)):
|
|
162
|
+
note = db.query(Note).filter(Note.id == note_id).first()
|
|
163
|
+
|
|
164
|
+
if not note:
|
|
165
|
+
raise HTTPException(
|
|
166
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
167
|
+
detail="Note not found"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
db.delete(note)
|
|
172
|
+
db.commit()
|
|
173
|
+
except Exception as e:
|
|
174
|
+
db.rollback()
|
|
175
|
+
raise HTTPException(
|
|
176
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
177
|
+
detail=str(e)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
return {"message": "Note Deleted"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from pydantic import BaseModel, EmailStr
|
|
2
|
+
|
|
3
|
+
# User Schemas
|
|
4
|
+
class UserCreate(BaseModel):
|
|
5
|
+
username: str
|
|
6
|
+
email: EmailStr
|
|
7
|
+
|
|
8
|
+
class UserUpdate(BaseModel):
|
|
9
|
+
username: str | None = None
|
|
10
|
+
email: EmailStr | None = None
|
|
11
|
+
|
|
12
|
+
class UserResponse(BaseModel):
|
|
13
|
+
id: int
|
|
14
|
+
username: str
|
|
15
|
+
email: str
|
|
16
|
+
|
|
17
|
+
class Config:
|
|
18
|
+
from_attributes = True
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Note Schemas
|
|
22
|
+
class NoteCreate(BaseModel):
|
|
23
|
+
title: str
|
|
24
|
+
content: str
|
|
25
|
+
|
|
26
|
+
class NoteUpdate(BaseModel):
|
|
27
|
+
title: str | None = None
|
|
28
|
+
content: str | None = None
|
|
29
|
+
|
|
30
|
+
class NoteResponse(BaseModel):
|
|
31
|
+
id: int
|
|
32
|
+
title: str
|
|
33
|
+
content: str
|
|
34
|
+
|
|
35
|
+
class Config:
|
|
36
|
+
from_attributes = True
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from flask import Flask
|
|
2
|
+
from flask_cors import CORS
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
import os
|
|
5
|
+
from pymongo import MongoClient
|
|
6
|
+
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
app = Flask(__name__)
|
|
10
|
+
CORS(app)
|
|
11
|
+
|
|
12
|
+
# MongoDB settings (supports full MONGO_URI or components)
|
|
13
|
+
MONGO_URI = os.getenv("MONGO_URI")
|
|
14
|
+
MDB_USER = os.getenv("DB_USER", "mongodbuser")
|
|
15
|
+
MDB_PASSWORD = os.getenv("DB_PASSWORD", "")
|
|
16
|
+
MDB_HOST = os.getenv("DB_HOST", "localhost")
|
|
17
|
+
MDB_PORT = os.getenv("DB_PORT", "27017")
|
|
18
|
+
MDB_NAME = os.getenv("DB_NAME", os.getenv("DB_NAME", "example_db"))
|
|
19
|
+
|
|
20
|
+
if not MONGO_URI:
|
|
21
|
+
if MDB_USER:
|
|
22
|
+
MONGO_URI = f"mongodb://{MDB_USER}:{MDB_PASSWORD}@{MDB_HOST}:{MDB_PORT}"
|
|
23
|
+
else:
|
|
24
|
+
MONGO_URI = f"mongodb://{MDB_HOST}:{MDB_PORT}"
|
|
25
|
+
|
|
26
|
+
client = MongoClient(MONGO_URI)
|
|
27
|
+
db = client[MDB_NAME]
|