fastapi-spawn 0.4.12__tar.gz → 0.4.14__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 (73) hide show
  1. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/PKG-INFO +30 -1
  2. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/README.md +29 -0
  3. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/__init__.py +1 -1
  4. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/cli.py +6 -0
  5. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/generator.py +11 -0
  6. fastapi_spawn-0.4.14/fastapi_spawn/templates/app/core/cache.py.j2 +32 -0
  7. fastapi_spawn-0.4.14/fastapi_spawn/templates/app/core/permissions.py.j2 +52 -0
  8. fastapi_spawn-0.4.14/fastapi_spawn/templates/app/middleware/response_format.py.j2 +64 -0
  9. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/pyproject.toml.j2 +3 -0
  10. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/pyproject.toml +1 -1
  11. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/.gitignore +0 -0
  12. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/LICENSE +0 -0
  13. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/config.py +0 -0
  14. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/constants.py +0 -0
  15. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/interactive.py +0 -0
  16. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/alembic/alembic.ini.j2 +0 -0
  17. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/alembic/env.py.j2 +0 -0
  18. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/__init__.py.j2 +0 -0
  19. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/deps.py.j2 +0 -0
  20. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/graphql.py.j2 +0 -0
  21. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2 +0 -0
  22. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2 +0 -0
  23. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/health/router.py.j2 +0 -0
  24. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/payments/router.py.j2 +0 -0
  25. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/router.py.j2 +0 -0
  26. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/streaming/router.py.j2 +0 -0
  27. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2 +0 -0
  28. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/ai.py.j2 +0 -0
  29. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/config.py.j2 +0 -0
  30. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/email.py.j2 +0 -0
  31. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/exceptions.py.j2 +0 -0
  32. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/logger.py.j2 +0 -0
  33. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/logging.py.j2 +0 -0
  34. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/monitoring.py.j2 +0 -0
  35. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/notifications.py.j2 +0 -0
  36. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/ocr.py.j2 +0 -0
  37. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/search.py.j2 +0 -0
  38. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/security.py.j2 +0 -0
  39. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/storage.py.j2 +0 -0
  40. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/vector_db.py.j2 +0 -0
  41. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/core/ws_manager.py.j2 +0 -0
  42. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/db/session.py.j2 +0 -0
  43. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/frontend/index.html.j2 +0 -0
  44. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/main.py.j2 +0 -0
  45. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/middleware/__init__.py.j2 +0 -0
  46. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/middleware/rate_limit.py.j2 +0 -0
  47. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/app/middleware/request_logger.py.j2 +0 -0
  48. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/Makefile.j2 +0 -0
  49. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/README.md.j2 +0 -0
  50. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/env.j2 +0 -0
  51. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/env_example.j2 +0 -0
  52. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/gitignore.j2 +0 -0
  53. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/base/pre_commit.j2 +0 -0
  54. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/ci/github/publish.yml.j2 +0 -0
  55. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/ci/github/tests.yml.j2 +0 -0
  56. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2 +0 -0
  57. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/db/seed.py.j2 +0 -0
  58. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/docker/Dockerfile.j2 +0 -0
  59. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/docker/docker-compose.yml.j2 +0 -0
  60. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/docker/dockerignore.j2 +0 -0
  61. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/infra/docker/docker-compose.prod.yml.j2 +0 -0
  62. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2 +0 -0
  63. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/infra/helm/values.yaml.j2 +0 -0
  64. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/infra/terraform/main.tf.j2 +0 -0
  65. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/infra/terraform/variables.tf.j2 +0 -0
  66. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/root/main.py.j2 +0 -0
  67. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/tasks/arq_worker.py.j2 +0 -0
  68. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/tasks/celery_app.py.j2 +0 -0
  69. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/tasks/sample_tasks.py.j2 +0 -0
  70. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/tests/conftest.py.j2 +0 -0
  71. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/templates/tests/test_health.py.j2 +0 -0
  72. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/fastapi_spawn/utils.py +0 -0
  73. {fastapi_spawn-0.4.12 → fastapi_spawn-0.4.14}/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.12
3
+ Version: 0.4.14
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
@@ -100,6 +100,30 @@ fastapi-spawn add alembic
100
100
  fastapi-spawn add sentry
101
101
  ```
102
102
 
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 🆘 Built-in Help & Auto-Suggestions
108
+
109
+ `fastapi-spawn` comes with an integrated global help menu and intelligent typo correction:
110
+
111
+ ```bash
112
+ # Display the interactive global help menu
113
+ fastapi-spawn help
114
+
115
+ # Or use the standard flag
116
+ fastapi-spawn --help
117
+ ```
118
+
119
+ ### Auto-Typo Correction (Did you mean?)
120
+ If you accidentally misspell a command, the CLI will catch it and suggest the right one automatically to save you time.
121
+ ```bash
122
+ $ fastapi-spawn nw my_app
123
+
124
+ Error: No such command 'nw'. Did you mean 'new'?
125
+ ```
126
+
103
127
  ---
104
128
 
105
129
  ## Generated Project Structure
@@ -528,6 +552,11 @@ fastapi-spawn add seed # Faker database seeding script (Users, Posts, Co
528
552
  fastapi-spawn add resend # Resend modern email client
529
553
  fastapi-spawn add sentry # Sentry APM integration
530
554
  fastapi-spawn add prometheus # Prometheus metrics
555
+
556
+ # Advanced API Features
557
+ fastapi-spawn add rbac # Role-Based Access Control (@RequireRole decorator)
558
+ fastapi-spawn add caching # Redis API Response Caching (@cache decorator)
559
+ fastapi-spawn add response-format # Global formatted JSON response middleware
531
560
  ```
532
561
 
533
562
  *Example:*
@@ -59,6 +59,30 @@ fastapi-spawn add alembic
59
59
  fastapi-spawn add sentry
60
60
  ```
61
61
 
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 🆘 Built-in Help & Auto-Suggestions
67
+
68
+ `fastapi-spawn` comes with an integrated global help menu and intelligent typo correction:
69
+
70
+ ```bash
71
+ # Display the interactive global help menu
72
+ fastapi-spawn help
73
+
74
+ # Or use the standard flag
75
+ fastapi-spawn --help
76
+ ```
77
+
78
+ ### Auto-Typo Correction (Did you mean?)
79
+ If you accidentally misspell a command, the CLI will catch it and suggest the right one automatically to save you time.
80
+ ```bash
81
+ $ fastapi-spawn nw my_app
82
+
83
+ Error: No such command 'nw'. Did you mean 'new'?
84
+ ```
85
+
62
86
  ---
63
87
 
64
88
  ## Generated Project Structure
@@ -487,6 +511,11 @@ fastapi-spawn add seed # Faker database seeding script (Users, Posts, Co
487
511
  fastapi-spawn add resend # Resend modern email client
488
512
  fastapi-spawn add sentry # Sentry APM integration
489
513
  fastapi-spawn add prometheus # Prometheus metrics
514
+
515
+ # Advanced API Features
516
+ fastapi-spawn add rbac # Role-Based Access Control (@RequireRole decorator)
517
+ fastapi-spawn add caching # Redis API Response Caching (@cache decorator)
518
+ fastapi-spawn add response-format # Global formatted JSON response middleware
490
519
  ```
491
520
 
492
521
  *Example:*
@@ -1,6 +1,6 @@
1
1
  """fastapi-spawn — Production-ready FastAPI project scaffolding CLI."""
2
2
 
3
- __version__ = "0.4.12"
3
+ __version__ = "0.4.14"
4
4
  __author__ = "Bishwajit Garai"
5
5
  __email__ = "bishwajitgarai@gmail.com"
6
6
  __license__ = "MIT"
@@ -305,6 +305,9 @@ _ADDABLE_FEATURES = {
305
305
  "sso-microsoft": "FastAPI SSO (Microsoft only)",
306
306
  "seed": "Database seeding script using Faker",
307
307
  "ocr": "PDF & OCR data pipeline (PyMuPDF / Tesseract)",
308
+ "rbac": "Role-Based Access Control (Permissions) boilerplate",
309
+ "caching": "Redis-based response caching (fastapi-cache2)",
310
+ "response-format": "Global JSON response formatting middleware",
308
311
  "docker": "Dockerfile + docker-compose.yml",
309
312
  "ci": "GitHub Actions CI/CD workflows",
310
313
  "helm": "Helm chart (infra/helm/)",
@@ -379,6 +382,9 @@ def _feature_guidance(feature: str, _project_dir: Path) -> None:
379
382
  "sso-microsoft": ["1. Use 'fastapi-spawn new temp_app --extra sso-microsoft' and copy the resulting sso.py"],
380
383
  "seed": ["Add dep: faker>=25.0.0", "Create db/seed.py (generate 100 mock users/posts)", "Run: uv run python db/seed.py"],
381
384
  "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']))])"],
386
+ "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
+ "response-format": ["Create app/middleware/response_format.py", "Add app.add_middleware(ResponseFormattingMiddleware) to main.py"],
382
388
  "docker": ["Create Dockerfile (multi-stage, uv-based)", "Create docker-compose.yml with all selected services", "Create .dockerignore"],
383
389
  "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"],
384
390
  "helm": ["Create infra/helm/Chart.yaml", "Create infra/helm/values.yaml (replicas, image, resources)", "Run: helm install my-release ./infra/helm"],
@@ -236,6 +236,17 @@ class ProjectGenerator:
236
236
  if "meilisearch" in extras:
237
237
  self._render_to(core / "search.py", "app/core/search.py.j2")
238
238
 
239
+ if "rbac" in extras:
240
+ self._render_to(core / "permissions.py", "app/core/permissions.py.j2")
241
+
242
+ if "caching" in extras:
243
+ self._render_to(core / "cache.py", "app/core/cache.py.j2")
244
+
245
+ if "response-format" in extras:
246
+ middleware = pkg / "middleware"
247
+ middleware.mkdir(exist_ok=True)
248
+ self._render_to(middleware / "response_format.py", "app/middleware/response_format.py.j2")
249
+
239
250
 
240
251
  def _generate_tasks(self, root: Path) -> None:
241
252
  """Root-level tasks/ directory."""
@@ -0,0 +1,32 @@
1
+ from fastapi_cache import FastAPICache
2
+ from fastapi_cache.backends.redis import RedisBackend
3
+ from redis import asyncio as aioredis
4
+ from app.core.config import settings
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ async def init_cache():
10
+ """
11
+ Initialize Redis caching backend for fastapi-cache2.
12
+ Call this function in your application startup event (e.g., lifespan in main.py).
13
+ """
14
+ try:
15
+ redis_url = getattr(settings, "REDIS_URL", "redis://localhost:6379/0")
16
+ redis = aioredis.from_url(redis_url, encoding="utf8", decode_responses=True)
17
+ FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
18
+ logger.info("Successfully initialized FastAPI Redis Cache.")
19
+ except Exception as e:
20
+ logger.error(f"Failed to initialize cache: {e}")
21
+
22
+ # --- Usage Example ---
23
+ #
24
+ # from fastapi_cache.decorator import cache
25
+ # from fastapi import APIRouter
26
+ #
27
+ # router = APIRouter()
28
+ #
29
+ # @router.get("/heavy-data")
30
+ # @cache(expire=60) # Caches the response for 60 seconds (TTL)
31
+ # async def get_heavy_data():
32
+ # return {"data": "This response is cached!"}
@@ -0,0 +1,52 @@
1
+ from typing import List, Callable
2
+ from fastapi import HTTPException, Security, status
3
+ from pydantic import BaseModel
4
+
5
+ # Mock User model for demonstration. Replace with your actual User model from app.models
6
+ class User(BaseModel):
7
+ id: str
8
+ email: str
9
+ role: str
10
+
11
+ def get_current_user() -> User:
12
+ """
13
+ Mock dependency. Replace this with your actual JWT/Auth dependency.
14
+ """
15
+ return User(id="123", email="user@example.com", role="user")
16
+
17
+ class RequireRole:
18
+ """
19
+ RBAC Dependency.
20
+ Usage:
21
+ @router.get("/admin", dependencies=[Depends(RequireRole(["admin", "superadmin"]))])
22
+ """
23
+ def __init__(self, allowed_roles: List[str]):
24
+ self.allowed_roles = allowed_roles
25
+
26
+ def __call__(self, current_user: User = Security(get_current_user)) -> User:
27
+ if current_user.role not in self.allowed_roles:
28
+ raise HTTPException(
29
+ status_code=status.HTTP_403_FORBIDDEN,
30
+ detail="You do not have the required role to access this resource."
31
+ )
32
+ return current_user
33
+
34
+ class RequirePermission:
35
+ """
36
+ Fine-grained access control dependency.
37
+ Usage:
38
+ @router.get("/data", dependencies=[Depends(RequirePermission("read:data"))])
39
+ """
40
+ def __init__(self, required_permission: str):
41
+ self.required_permission = required_permission
42
+
43
+ def __call__(self, current_user: User = Security(get_current_user)) -> User:
44
+ # Replace this logic with your actual permission checking (e.g. query DB for user permissions)
45
+ user_permissions = ["read:data", "write:data"] if current_user.role == "admin" else ["read:data"]
46
+
47
+ if self.required_permission not in user_permissions:
48
+ raise HTTPException(
49
+ status_code=status.HTTP_403_FORBIDDEN,
50
+ detail=f"Missing required permission: {self.required_permission}"
51
+ )
52
+ return current_user
@@ -0,0 +1,64 @@
1
+ import json
2
+ from starlette.middleware.base import BaseHTTPMiddleware
3
+ from fastapi import Request
4
+ from starlette.responses import JSONResponse
5
+
6
+ class ResponseFormattingMiddleware(BaseHTTPMiddleware):
7
+ """
8
+ Intercepts all JSON responses and formats them into a standard structure:
9
+ {
10
+ "status": "success" | "error",
11
+ "message": "...",
12
+ "data": { ... },
13
+ "error": { ... }
14
+ }
15
+ """
16
+ async def dispatch(self, request: Request, call_next):
17
+ response = await call_next(request)
18
+
19
+ # Only process JSON responses
20
+ if response.headers.get("content-type") == "application/json":
21
+ body = b""
22
+ async for chunk in response.body_iterator:
23
+ body += chunk
24
+
25
+ try:
26
+ data = json.loads(body.decode("utf-8"))
27
+ except json.JSONDecodeError:
28
+ data = body.decode("utf-8")
29
+
30
+ is_success = response.status_code < 400
31
+
32
+ # Avoid wrapping if already formatted (e.g. custom exceptions might do this)
33
+ if isinstance(data, dict) and "status" in data and "data" in data and "error" in data:
34
+ return JSONResponse(
35
+ content=data,
36
+ status_code=response.status_code,
37
+ headers=dict(response.headers)
38
+ )
39
+
40
+ # Determine appropriate message
41
+ if is_success:
42
+ message = "Request successful"
43
+ else:
44
+ # FastAPI default validation errors are in `detail`
45
+ message = data.get("detail", "An error occurred") if isinstance(data, dict) else "An error occurred"
46
+
47
+ formatted_response = {
48
+ "status": "success" if is_success else "error",
49
+ "message": message,
50
+ "data": data if is_success else None,
51
+ "error": data if not is_success else None
52
+ }
53
+
54
+ # Remove content-length as the payload size has changed
55
+ headers = dict(response.headers)
56
+ headers.pop("content-length", None)
57
+
58
+ return JSONResponse(
59
+ content=formatted_response,
60
+ status_code=response.status_code,
61
+ headers=headers
62
+ )
63
+
64
+ return response
@@ -174,6 +174,9 @@ dependencies = [
174
174
  "pymupdf>=1.24.0",
175
175
  "pytesseract>=0.3.10",
176
176
  {% endif %}
177
+ {% if "caching" in extras %}
178
+ "fastapi-cache2[redis]>=0.2.1",
179
+ {% endif %}
177
180
  {% if "meilisearch" in extras %}
178
181
  "meilisearch>=0.30.0",
179
182
  {% endif %}
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fastapi-spawn"
7
- version = "0.4.12"
7
+ version = "0.4.14"
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