fastapi-spawn 0.4.14__tar.gz → 0.4.16__tar.gz

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.
Files changed (77) hide show
  1. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/PKG-INFO +4 -1
  2. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/README.md +3 -0
  3. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/__init__.py +1 -1
  4. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/cli.py +7 -1
  5. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/generator.py +14 -0
  6. fastapi_spawn-0.4.16/fastapi_spawn/templates/app/admin/setup.py.j2 +30 -0
  7. fastapi_spawn-0.4.16/fastapi_spawn/templates/app/api/v1/pagination/router.py.j2 +27 -0
  8. fastapi_spawn-0.4.16/fastapi_spawn/templates/app/api/v1/permissions/router.py.j2 +23 -0
  9. fastapi_spawn-0.4.16/fastapi_spawn/templates/app/api/v1/uploads/router.py.j2 +43 -0
  10. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/pyproject.toml.j2 +6 -0
  11. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/pyproject.toml +1 -1
  12. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/.gitignore +0 -0
  13. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/LICENSE +0 -0
  14. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/config.py +0 -0
  15. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/constants.py +0 -0
  16. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/interactive.py +0 -0
  17. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/alembic/alembic.ini.j2 +0 -0
  18. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/alembic/env.py.j2 +0 -0
  19. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/__init__.py.j2 +0 -0
  20. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/deps.py.j2 +0 -0
  21. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/graphql.py.j2 +0 -0
  22. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2 +0 -0
  23. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2 +0 -0
  24. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/health/router.py.j2 +0 -0
  25. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/payments/router.py.j2 +0 -0
  26. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/router.py.j2 +0 -0
  27. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/streaming/router.py.j2 +0 -0
  28. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2 +0 -0
  29. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/ai.py.j2 +0 -0
  30. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/cache.py.j2 +0 -0
  31. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/config.py.j2 +0 -0
  32. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/email.py.j2 +0 -0
  33. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/exceptions.py.j2 +0 -0
  34. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/logger.py.j2 +0 -0
  35. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/logging.py.j2 +0 -0
  36. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/monitoring.py.j2 +0 -0
  37. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/notifications.py.j2 +0 -0
  38. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/ocr.py.j2 +0 -0
  39. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/permissions.py.j2 +0 -0
  40. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/search.py.j2 +0 -0
  41. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/security.py.j2 +0 -0
  42. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/storage.py.j2 +0 -0
  43. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/vector_db.py.j2 +0 -0
  44. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/core/ws_manager.py.j2 +0 -0
  45. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/db/session.py.j2 +0 -0
  46. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/frontend/index.html.j2 +0 -0
  47. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/main.py.j2 +0 -0
  48. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/middleware/__init__.py.j2 +0 -0
  49. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/middleware/rate_limit.py.j2 +0 -0
  50. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/middleware/request_logger.py.j2 +0 -0
  51. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/app/middleware/response_format.py.j2 +0 -0
  52. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/Makefile.j2 +0 -0
  53. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/README.md.j2 +0 -0
  54. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/env.j2 +0 -0
  55. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/env_example.j2 +0 -0
  56. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/gitignore.j2 +0 -0
  57. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/base/pre_commit.j2 +0 -0
  58. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/ci/github/publish.yml.j2 +0 -0
  59. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/ci/github/tests.yml.j2 +0 -0
  60. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2 +0 -0
  61. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/db/seed.py.j2 +0 -0
  62. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/docker/Dockerfile.j2 +0 -0
  63. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/docker/docker-compose.yml.j2 +0 -0
  64. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/docker/dockerignore.j2 +0 -0
  65. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/infra/docker/docker-compose.prod.yml.j2 +0 -0
  66. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2 +0 -0
  67. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/infra/helm/values.yaml.j2 +0 -0
  68. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/infra/terraform/main.tf.j2 +0 -0
  69. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/infra/terraform/variables.tf.j2 +0 -0
  70. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/root/main.py.j2 +0 -0
  71. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/tasks/arq_worker.py.j2 +0 -0
  72. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/tasks/celery_app.py.j2 +0 -0
  73. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/tasks/sample_tasks.py.j2 +0 -0
  74. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/tests/conftest.py.j2 +0 -0
  75. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/templates/tests/test_health.py.j2 +0 -0
  76. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/utils.py +0 -0
  77. {fastapi_spawn-0.4.14 → fastapi_spawn-0.4.16}/fastapi_spawn/validators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-spawn
3
- Version: 0.4.14
3
+ Version: 0.4.16
4
4
  Summary: A powerful CLI tool to scaffold production-ready FastAPI projects with flexible database, auth, broker, and deployment options.
5
5
  Project-URL: Homepage, https://github.com/Bishwajitgarai/fastapi-spawn
6
6
  Project-URL: Documentation, https://github.com/Bishwajitgarai/fastapi-spawn#readme
@@ -557,6 +557,9 @@ fastapi-spawn add prometheus # Prometheus metrics
557
557
  fastapi-spawn add rbac # Role-Based Access Control (@RequireRole decorator)
558
558
  fastapi-spawn add caching # Redis API Response Caching (@cache decorator)
559
559
  fastapi-spawn add response-format # Global formatted JSON response middleware
560
+ fastapi-spawn add admin # Internal CRUD Admin Dashboard (sqladmin)
561
+ fastapi-spawn add pagination # Automatic endpoint pagination logic
562
+ fastapi-spawn add uploads # File upload router (Multipart Form)
560
563
  ```
561
564
 
562
565
  *Example:*
@@ -516,6 +516,9 @@ fastapi-spawn add prometheus # Prometheus metrics
516
516
  fastapi-spawn add rbac # Role-Based Access Control (@RequireRole decorator)
517
517
  fastapi-spawn add caching # Redis API Response Caching (@cache decorator)
518
518
  fastapi-spawn add response-format # Global formatted JSON response middleware
519
+ fastapi-spawn add admin # Internal CRUD Admin Dashboard (sqladmin)
520
+ fastapi-spawn add pagination # Automatic endpoint pagination logic
521
+ fastapi-spawn add uploads # File upload router (Multipart Form)
519
522
  ```
520
523
 
521
524
  *Example:*
@@ -1,6 +1,6 @@
1
1
  """fastapi-spawn — Production-ready FastAPI project scaffolding CLI."""
2
2
 
3
- __version__ = "0.4.14"
3
+ __version__ = "0.4.16"
4
4
  __author__ = "Bishwajit Garai"
5
5
  __email__ = "bishwajitgarai@gmail.com"
6
6
  __license__ = "MIT"
@@ -308,6 +308,9 @@ _ADDABLE_FEATURES = {
308
308
  "rbac": "Role-Based Access Control (Permissions) boilerplate",
309
309
  "caching": "Redis-based response caching (fastapi-cache2)",
310
310
  "response-format": "Global JSON response formatting middleware",
311
+ "admin": "Auto-generated internal admin dashboard (sqladmin)",
312
+ "pagination": "Automatic endpoint pagination (fastapi-pagination)",
313
+ "uploads": "File upload router & handling",
311
314
  "docker": "Dockerfile + docker-compose.yml",
312
315
  "ci": "GitHub Actions CI/CD workflows",
313
316
  "helm": "Helm chart (infra/helm/)",
@@ -382,9 +385,12 @@ def _feature_guidance(feature: str, _project_dir: Path) -> None:
382
385
  "sso-microsoft": ["1. Use 'fastapi-spawn new temp_app --extra sso-microsoft' and copy the resulting sso.py"],
383
386
  "seed": ["Add dep: faker>=25.0.0", "Create db/seed.py (generate 100 mock users/posts)", "Run: uv run python db/seed.py"],
384
387
  "ocr": ["Add deps: pymupdf>=1.24.0, pytesseract>=0.3.10", "Create app/core/ocr.py (PDF parsing pipeline)", "Install system deps: sudo apt install tesseract-ocr"],
385
- "rbac": ["Create app/core/permissions.py", "Add @router.get(..., dependencies=[Depends(RequireRole(['admin']))])"],
388
+ "rbac": ["Create app/core/permissions.py and app/api/v1/permissions/router.py", "Add app.include_router(permissions.router) to main.py"],
386
389
  "caching": ["Add dep: fastapi-cache2[redis]>=0.2.1", "Create app/core/cache.py", "Initialize cache in lifespan and use @cache(expire=60) on endpoints"],
387
390
  "response-format": ["Create app/middleware/response_format.py", "Add app.add_middleware(ResponseFormattingMiddleware) to main.py"],
391
+ "admin": ["Add dep: sqladmin[full]>=0.16.1", "Create app/admin/setup.py", "Call setup_admin(app, engine) in main.py"],
392
+ "pagination":["Add dep: fastapi-pagination>=0.12.0", "Create app/api/v1/pagination/router.py", "Call add_pagination(app) in main.py"],
393
+ "uploads": ["Create app/api/v1/uploads/router.py", "Include router in app/api/v1/router.py"],
388
394
  "docker": ["Create Dockerfile (multi-stage, uv-based)", "Create docker-compose.yml with all selected services", "Create .dockerignore"],
389
395
  "ci": ["Create .github/workflows/tests.yml (matrix: 3.10, 3.11, 3.12)", "Create .github/workflows/publish.yml (v* tags → PyPI)", "Add PYPI_API_TOKEN to GitHub repo secrets"],
390
396
  "helm": ["Create infra/helm/Chart.yaml", "Create infra/helm/values.yaml (replicas, image, resources)", "Run: helm install my-release ./infra/helm"],
@@ -238,6 +238,8 @@ class ProjectGenerator:
238
238
 
239
239
  if "rbac" in extras:
240
240
  self._render_to(core / "permissions.py", "app/core/permissions.py.j2")
241
+ (v1 / "permissions").mkdir(parents=True, exist_ok=True)
242
+ self._render_to(v1 / "permissions" / "router.py", "app/api/v1/permissions/router.py.j2")
241
243
 
242
244
  if "caching" in extras:
243
245
  self._render_to(core / "cache.py", "app/core/cache.py.j2")
@@ -247,6 +249,18 @@ class ProjectGenerator:
247
249
  middleware.mkdir(exist_ok=True)
248
250
  self._render_to(middleware / "response_format.py", "app/middleware/response_format.py.j2")
249
251
 
252
+ if "admin" in extras:
253
+ (pkg / "admin").mkdir(parents=True, exist_ok=True)
254
+ self._render_to(pkg / "admin" / "setup.py", "app/admin/setup.py.j2")
255
+
256
+ if "pagination" in extras:
257
+ (v1 / "pagination").mkdir(parents=True, exist_ok=True)
258
+ self._render_to(v1 / "pagination" / "router.py", "app/api/v1/pagination/router.py.j2")
259
+
260
+ if "uploads" in extras:
261
+ (v1 / "uploads").mkdir(parents=True, exist_ok=True)
262
+ self._render_to(v1 / "uploads" / "router.py", "app/api/v1/uploads/router.py.j2")
263
+
250
264
 
251
265
  def _generate_tasks(self, root: Path) -> None:
252
266
  """Root-level tasks/ directory."""
@@ -0,0 +1,30 @@
1
+ from sqladmin import Admin, ModelView
2
+
3
+ # Example User model admin view.
4
+ # Uncomment and replace with your actual model from app.models
5
+ #
6
+ # from app.models.user import User
7
+ #
8
+ # class UserAdmin(ModelView, model=User):
9
+ # column_list = [User.id, User.email]
10
+ # column_searchable_list = [User.email]
11
+ # column_sortable_list = [User.id]
12
+ # can_create = True
13
+ # can_edit = True
14
+ # can_delete = True
15
+ # can_view_details = True
16
+
17
+ def setup_admin(app, engine):
18
+ """
19
+ Mounts the sqladmin dashboard at /admin.
20
+ Call this in your main.py:
21
+ from app.admin.setup import setup_admin
22
+ setup_admin(app, engine)
23
+ """
24
+ # Ensure authentication is added if exposing to production!
25
+ admin = Admin(app, engine, title="Admin Dashboard")
26
+
27
+ # Register views here
28
+ # admin.add_view(UserAdmin)
29
+
30
+ return admin
@@ -0,0 +1,27 @@
1
+ from fastapi import APIRouter
2
+ from fastapi_pagination import Page, paginate
3
+ from pydantic import BaseModel
4
+ from typing import List
5
+
6
+ router = APIRouter(
7
+ prefix="/items",
8
+ tags=["pagination"]
9
+ )
10
+
11
+ class ItemResponse(BaseModel):
12
+ id: int
13
+ name: str
14
+
15
+ # Mock data
16
+ fake_items = [{"id": i, "name": f"Item {i}"} for i in range(1, 101)]
17
+
18
+ @router.get("/", response_model=Page[ItemResponse])
19
+ async def get_items():
20
+ """
21
+ Returns a paginated list of items.
22
+ Usage: GET /api/v1/pagination/items?page=1&size=50
23
+ """
24
+ # If using SQLAlchemy:
25
+ # return paginate(db, select(Item))
26
+
27
+ return paginate(fake_items)
@@ -0,0 +1,23 @@
1
+ from fastapi import APIRouter, Depends
2
+ from app.core.permissions import RequireRole, RequirePermission
3
+
4
+ # This router restricts access to all its endpoints using the RequireRole dependency
5
+ router = APIRouter(
6
+ prefix="/admin",
7
+ tags=["admin", "rbac"],
8
+ dependencies=[Depends(RequireRole(["admin"]))]
9
+ )
10
+
11
+ @router.get("/dashboard")
12
+ async def get_admin_dashboard():
13
+ """
14
+ This endpoint is only accessible to users with the 'admin' role.
15
+ """
16
+ return {"message": "Welcome to the secure admin dashboard!"}
17
+
18
+ @router.get("/settings", dependencies=[Depends(RequirePermission("write:settings"))])
19
+ async def update_admin_settings():
20
+ """
21
+ This endpoint requires both the 'admin' role (from the router) AND the 'write:settings' permission.
22
+ """
23
+ return {"message": "Admin settings successfully updated."}
@@ -0,0 +1,43 @@
1
+ from fastapi import APIRouter, UploadFile, File, HTTPException
2
+ import shutil
3
+ import os
4
+ import uuid
5
+
6
+ router = APIRouter(
7
+ prefix="/uploads",
8
+ tags=["uploads"]
9
+ )
10
+
11
+ # Maximum file size (5MB)
12
+ MAX_FILE_SIZE = 5 * 1024 * 1024
13
+
14
+ @router.post("/")
15
+ async def upload_file(file: UploadFile = File(...)):
16
+ """
17
+ Upload a single file. Saves it locally in a 'media/' directory.
18
+ If you configured S3 or GCS, replace the local save logic with your storage client.
19
+ """
20
+ if file.size and file.size > MAX_FILE_SIZE:
21
+ raise HTTPException(status_code=400, detail="File too large. Maximum size is 5MB.")
22
+
23
+ # Ensure secure filename (prevent directory traversal)
24
+ ext = os.path.splitext(file.filename)[1] if file.filename else ""
25
+ safe_filename = f"{uuid.uuid4().hex}{ext}"
26
+
27
+ # Save locally as an example
28
+ upload_dir = "media"
29
+ os.makedirs(upload_dir, exist_ok=True)
30
+ file_path = os.path.join(upload_dir, safe_filename)
31
+
32
+ try:
33
+ with open(file_path, "wb") as buffer:
34
+ shutil.copyfileobj(file.file, buffer)
35
+ except Exception as e:
36
+ raise HTTPException(status_code=500, detail=f"Could not save file: {e}")
37
+
38
+ return {
39
+ "filename": file.filename,
40
+ "saved_as": safe_filename,
41
+ "size": file.size,
42
+ "url": f"/{file_path}"
43
+ }
@@ -177,6 +177,12 @@ dependencies = [
177
177
  {% if "caching" in extras %}
178
178
  "fastapi-cache2[redis]>=0.2.1",
179
179
  {% endif %}
180
+ {% if "admin" in extras %}
181
+ "sqladmin[full]>=0.16.1",
182
+ {% endif %}
183
+ {% if "pagination" in extras %}
184
+ "fastapi-pagination>=0.12.0",
185
+ {% endif %}
180
186
  {% if "meilisearch" in extras %}
181
187
  "meilisearch>=0.30.0",
182
188
  {% endif %}
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fastapi-spawn"
7
- version = "0.4.14"
7
+ version = "0.4.16"
8
8
  description = "A powerful CLI tool to scaffold production-ready FastAPI projects with flexible database, auth, broker, and deployment options."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
File without changes