fastapi-spawn 0.4.23__tar.gz → 0.4.24__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.23 → fastapi_spawn-0.4.24}/PKG-INFO +6 -1
  2. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/README.md +5 -0
  3. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/cli.py +95 -0
  4. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/interactive.py +95 -15
  5. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/router.py.j2 +12 -0
  6. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/pyproject.toml +1 -1
  7. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/.gitignore +0 -0
  8. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/LICENSE +0 -0
  9. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/__init__.py +0 -0
  10. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/config.py +0 -0
  11. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/constants.py +0 -0
  12. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/generator.py +0 -0
  13. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/alembic/alembic.ini.j2 +0 -0
  14. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/alembic/env.py.j2 +0 -0
  15. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/__init__.py.j2 +0 -0
  16. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/admin/setup.py.j2 +0 -0
  17. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/deps.py.j2 +0 -0
  18. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/graphql.py.j2 +0 -0
  19. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2 +0 -0
  20. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2 +0 -0
  21. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/health/router.py.j2 +0 -0
  22. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/pagination/router.py.j2 +0 -0
  23. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/payments/router.py.j2 +0 -0
  24. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/permissions/router.py.j2 +0 -0
  25. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/streaming/router.py.j2 +0 -0
  26. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/uploads/router.py.j2 +0 -0
  27. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2 +0 -0
  28. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/ai.py.j2 +0 -0
  29. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/cache.py.j2 +0 -0
  30. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/config.py.j2 +0 -0
  31. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/email.py.j2 +0 -0
  32. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/exceptions.py.j2 +0 -0
  33. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/logger.py.j2 +0 -0
  34. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/logging.py.j2 +0 -0
  35. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/monitoring.py.j2 +0 -0
  36. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/notifications.py.j2 +0 -0
  37. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/ocr.py.j2 +0 -0
  38. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/permissions.py.j2 +0 -0
  39. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/search.py.j2 +0 -0
  40. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/security.py.j2 +0 -0
  41. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/storage.py.j2 +0 -0
  42. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/vector_db.py.j2 +0 -0
  43. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/core/ws_manager.py.j2 +0 -0
  44. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/db/session.py.j2 +0 -0
  45. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/frontend/index.html.j2 +0 -0
  46. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/main.py.j2 +0 -0
  47. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/middleware/__init__.py.j2 +0 -0
  48. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/middleware/rate_limit.py.j2 +0 -0
  49. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/middleware/request_logger.py.j2 +0 -0
  50. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/app/middleware/response_format.py.j2 +0 -0
  51. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/Makefile.j2 +0 -0
  52. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/README.md.j2 +0 -0
  53. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/env.j2 +0 -0
  54. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/env_example.j2 +0 -0
  55. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/gitignore.j2 +0 -0
  56. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/pre_commit.j2 +0 -0
  57. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/base/pyproject.toml.j2 +0 -0
  58. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/ci/github/publish.yml.j2 +0 -0
  59. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/ci/github/tests.yml.j2 +0 -0
  60. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2 +0 -0
  61. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/db/seed.py.j2 +0 -0
  62. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/docker/Dockerfile.j2 +0 -0
  63. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/docker/docker-compose.yml.j2 +0 -0
  64. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/docker/dockerignore.j2 +0 -0
  65. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/infra/docker/docker-compose.prod.yml.j2 +0 -0
  66. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2 +0 -0
  67. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/infra/helm/values.yaml.j2 +0 -0
  68. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/infra/terraform/main.tf.j2 +0 -0
  69. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/infra/terraform/variables.tf.j2 +0 -0
  70. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/root/main.py.j2 +0 -0
  71. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/tasks/arq_worker.py.j2 +0 -0
  72. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/tasks/celery_app.py.j2 +0 -0
  73. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/tasks/sample_tasks.py.j2 +0 -0
  74. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/tests/conftest.py.j2 +0 -0
  75. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/templates/tests/test_health.py.j2 +0 -0
  76. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/fastapi_spawn/utils.py +0 -0
  77. {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.24}/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.23
3
+ Version: 0.4.24
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
@@ -72,6 +72,11 @@ uv pip install fastapi-spawn
72
72
  # Interactive TUI — guided step-by-step
73
73
  fastapi-spawn new my-api
74
74
 
75
+ # Or use a preset template (New in 0.4.24!)
76
+ fastapi-spawn start basic my-api
77
+ fastapi-spawn start full-local my-api
78
+ fastapi-spawn start full my-api
79
+
75
80
  # Full stack one-liner
76
81
  fastapi-spawn new my-api \
77
82
  --db postgresql \
@@ -31,6 +31,11 @@ uv pip install fastapi-spawn
31
31
  # Interactive TUI — guided step-by-step
32
32
  fastapi-spawn new my-api
33
33
 
34
+ # Or use a preset template (New in 0.4.24!)
35
+ fastapi-spawn start basic my-api
36
+ fastapi-spawn start full-local my-api
37
+ fastapi-spawn start full my-api
38
+
34
39
  # Full stack one-liner
35
40
  fastapi-spawn new my-api \
36
41
  --db postgresql \
@@ -219,6 +219,101 @@ def new(
219
219
  if not dry_run:
220
220
  console.print(f"\n[bold green]✓ Project created:[/bold green] {project_path.resolve()}")
221
221
  _print_next_steps(config)
222
+ @app.command("start", help="Create a project using a preset template.")
223
+ def start(
224
+ preset: str = typer.Argument(..., help="Preset name (basic, full)"),
225
+ project_name: str = typer.Argument(..., help="Name of the new project"),
226
+ output: Path = typer.Option(Path("."), "--output", "-o", help="Output directory"),
227
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing directory"),
228
+ ) -> None:
229
+ _print_banner()
230
+
231
+ if preset == "basic":
232
+ config = ProjectConfig(
233
+ project_name=project_name,
234
+ db=Database.sqlite,
235
+ orm=ORM.sqlalchemy,
236
+ migration=MigrationTool.alembic,
237
+ auth=AuthType.jwt,
238
+ broker=Broker.none,
239
+ cache=Cache.none,
240
+ storage=Storage.local,
241
+ ai=AIProvider.none,
242
+ api_extra=APIExtra.none,
243
+ monitoring=MonitoringProvider.none,
244
+ log_lib=LogLibrary.loguru,
245
+ log_dest=LogDestination.local,
246
+ email=EmailProvider.none,
247
+ notify=NotificationProvider.none,
248
+ vector_db=VectorDB.none,
249
+ stack=Stack.minimal,
250
+ ci=CIProvider.none,
251
+ include_docker=True,
252
+ include_tests=True,
253
+ force=force,
254
+ )
255
+ elif preset == "full-local":
256
+ config = ProjectConfig(
257
+ project_name=project_name,
258
+ db=Database.postgresql,
259
+ orm=ORM.sqlalchemy,
260
+ migration=MigrationTool.alembic,
261
+ auth=AuthType.jwt,
262
+ broker=Broker.none,
263
+ cache=Cache.none,
264
+ storage=Storage.local,
265
+ ai=AIProvider.none,
266
+ api_extra=APIExtra.none,
267
+ monitoring=MonitoringProvider.none,
268
+ log_lib=LogLibrary.loguru,
269
+ log_dest=LogDestination.local,
270
+ email=EmailProvider.none,
271
+ notify=NotificationProvider.none,
272
+ vector_db=VectorDB.chroma,
273
+ stack=Stack.standard,
274
+ ci=CIProvider.none,
275
+ include_docker=True,
276
+ include_tests=True,
277
+ force=force,
278
+ )
279
+ elif preset == "full":
280
+ config = ProjectConfig(
281
+ project_name=project_name,
282
+ db=Database.postgresql,
283
+ orm=ORM.sqlalchemy,
284
+ migration=MigrationTool.alembic,
285
+ auth=AuthType.jwt,
286
+ broker=Broker.redis,
287
+ cache=Cache.redis,
288
+ storage=Storage.s3,
289
+ ai=AIProvider.openai,
290
+ api_extra=APIExtra.websockets,
291
+ monitoring=MonitoringProvider.both,
292
+ log_lib=LogLibrary.loguru,
293
+ log_dest=LogDestination.local,
294
+ email=EmailProvider.none,
295
+ notify=NotificationProvider.none,
296
+ vector_db=VectorDB.qdrant,
297
+ stack=Stack.full,
298
+ ci=CIProvider.github,
299
+ include_docker=True,
300
+ include_tests=True,
301
+ force=force,
302
+ )
303
+ else:
304
+ rprint(f"[bold red]✗ Error:[/bold red] Unknown preset '{preset}'. Available presets: basic, full-local, full")
305
+ raise typer.Exit(1)
306
+
307
+ _print_summary(config)
308
+
309
+ try:
310
+ generator = ProjectGenerator(config, output)
311
+ project_path = generator.generate()
312
+ rprint(f"\n[bold green]✓ Project created:[/bold green] {project_path.resolve()}")
313
+ _print_next_steps(config)
314
+ except Exception as exc:
315
+ rprint(f"\n[bold red]✗ Generation failed:[/bold red] {exc}")
316
+ raise typer.Exit(1) from exc
222
317
 
223
318
 
224
319
  # ── `list-templates` command ───────────────────────────────────────────────────
@@ -19,6 +19,10 @@ from fastapi_spawn.constants import (
19
19
  ORM,
20
20
  ORM_DB_COMPAT,
21
21
  Stack,
22
+ Storage,
23
+ AIProvider,
24
+ MonitoringProvider,
25
+ VectorDB,
22
26
  )
23
27
  from fastapi_spawn.validators import questionary_validator, validate_project_name
24
28
 
@@ -47,8 +51,8 @@ def prompt_project_name(default: str = "") -> str:
47
51
 
48
52
  def prompt_database() -> Database:
49
53
  choices = [
50
- questionary.Choice(title=label, value=db)
51
- for db, label in DB_LABELS.items()
54
+ questionary.Choice(title=f"{i}) {label}", value=db)
55
+ for i, (db, label) in enumerate(DB_LABELS.items(), 1)
52
56
  ]
53
57
  return questionary.select(
54
58
  "Database backend:",
@@ -68,7 +72,7 @@ def prompt_orm(db: Database) -> ORM:
68
72
  orm for orm in ORM
69
73
  if db in ORM_DB_COMPAT.get(orm, compatible)
70
74
  ]
71
- choices = [questionary.Choice(title=o.value, value=o) for o in valid_orms]
75
+ choices = [questionary.Choice(title=f"{i}) {o.value}", value=o) for i, o in enumerate(valid_orms, 1)]
72
76
  if not choices:
73
77
  return ORM.none
74
78
  return questionary.select(
@@ -80,8 +84,8 @@ def prompt_orm(db: Database) -> ORM:
80
84
 
81
85
  def prompt_auth() -> AuthType:
82
86
  choices = [
83
- questionary.Choice(title=label, value=auth)
84
- for auth, label in AUTH_LABELS.items()
87
+ questionary.Choice(title=f"{i}) {label}", value=auth)
88
+ for i, (auth, label) in enumerate(AUTH_LABELS.items(), 1)
85
89
  ]
86
90
  return questionary.select(
87
91
  "Authentication strategy:",
@@ -92,8 +96,8 @@ def prompt_auth() -> AuthType:
92
96
 
93
97
  def prompt_broker() -> Broker:
94
98
  choices = [
95
- questionary.Choice(title=label, value=broker)
96
- for broker, label in BROKER_LABELS.items()
99
+ questionary.Choice(title=f"{i}) {label}", value=broker)
100
+ for i, (broker, label) in enumerate(BROKER_LABELS.items(), 1)
97
101
  ]
98
102
  return questionary.select(
99
103
  "Message broker:",
@@ -104,8 +108,8 @@ def prompt_broker() -> Broker:
104
108
 
105
109
  def prompt_cache() -> Cache:
106
110
  choices = [
107
- questionary.Choice(title=c.value, value=c)
108
- for c in Cache
111
+ questionary.Choice(title=f"{i}) {c.value}", value=c)
112
+ for i, c in enumerate(Cache, 1)
109
113
  ]
110
114
  return questionary.select(
111
115
  "Cache layer:",
@@ -116,8 +120,8 @@ def prompt_cache() -> Cache:
116
120
 
117
121
  def prompt_stack() -> Stack:
118
122
  choices = [
119
- questionary.Choice(title=f"{s.value} — {STACK_DESCRIPTIONS[s]}", value=s)
120
- for s in Stack
123
+ questionary.Choice(title=f"{i}) {s.value} — {STACK_DESCRIPTIONS[s]}", value=s)
124
+ for i, s in enumerate(Stack, 1)
121
125
  ]
122
126
  return questionary.select(
123
127
  "Deployment stack:",
@@ -128,8 +132,8 @@ def prompt_stack() -> Stack:
128
132
 
129
133
  def prompt_ci() -> CIProvider:
130
134
  choices = [
131
- questionary.Choice(title=c.value, value=c)
132
- for c in CIProvider
135
+ questionary.Choice(title=f"{i}) {c.value}", value=c)
136
+ for i, c in enumerate(CIProvider, 1)
133
137
  ]
134
138
  return questionary.select(
135
139
  "CI/CD provider:",
@@ -140,8 +144,8 @@ def prompt_ci() -> CIProvider:
140
144
 
141
145
  def prompt_log_lib() -> LogLibrary:
142
146
  choices = [
143
- questionary.Choice(title=l.value, value=l)
144
- for l in LogLibrary
147
+ questionary.Choice(title=f"{i}) {l.value}", value=l)
148
+ for i, l in enumerate(LogLibrary, 1)
145
149
  ]
146
150
  return questionary.select(
147
151
  "Logging library:",
@@ -150,6 +154,74 @@ def prompt_log_lib() -> LogLibrary:
150
154
  ).unsafe_ask()
151
155
 
152
156
 
157
+ def prompt_storage() -> Storage:
158
+ use_storage = questionary.confirm(
159
+ "Do you need file storage?", default=False, style=SPAWN_STYLE
160
+ ).unsafe_ask()
161
+ if not use_storage:
162
+ return Storage.none
163
+ choices = [
164
+ questionary.Choice(title=f"{i}) {s.value}", value=s)
165
+ for i, s in enumerate(Storage, 1) if s != Storage.none
166
+ ]
167
+ return questionary.select(
168
+ "Storage provider:",
169
+ choices=choices,
170
+ style=SPAWN_STYLE,
171
+ ).unsafe_ask()
172
+
173
+
174
+ def prompt_ai() -> AIProvider:
175
+ use_ai = questionary.confirm(
176
+ "Do you need AI/LLM integration?", default=False, style=SPAWN_STYLE
177
+ ).unsafe_ask()
178
+ if not use_ai:
179
+ return AIProvider.none
180
+ choices = [
181
+ questionary.Choice(title=f"{i}) {a.value}", value=a)
182
+ for i, a in enumerate(AIProvider, 1) if a != AIProvider.none
183
+ ]
184
+ return questionary.select(
185
+ "AI provider:",
186
+ choices=choices,
187
+ style=SPAWN_STYLE,
188
+ ).unsafe_ask()
189
+
190
+
191
+ def prompt_vector_db() -> VectorDB:
192
+ use_vdb = questionary.confirm(
193
+ "Do you need a Vector Database?", default=False, style=SPAWN_STYLE
194
+ ).unsafe_ask()
195
+ if not use_vdb:
196
+ return VectorDB.none
197
+ choices = [
198
+ questionary.Choice(title=f"{i}) {v.value}", value=v)
199
+ for i, v in enumerate(VectorDB, 1) if v != VectorDB.none
200
+ ]
201
+ return questionary.select(
202
+ "Vector database:",
203
+ choices=choices,
204
+ style=SPAWN_STYLE,
205
+ ).unsafe_ask()
206
+
207
+
208
+ def prompt_monitoring() -> MonitoringProvider:
209
+ use_mon = questionary.confirm(
210
+ "Do you need Monitoring?", default=False, style=SPAWN_STYLE
211
+ ).unsafe_ask()
212
+ if not use_mon:
213
+ return MonitoringProvider.none
214
+ choices = [
215
+ questionary.Choice(title=f"{i}) {m.value}", value=m)
216
+ for i, m in enumerate(MonitoringProvider, 1) if m != MonitoringProvider.none
217
+ ]
218
+ return questionary.select(
219
+ "Monitoring provider:",
220
+ choices=choices,
221
+ style=SPAWN_STYLE,
222
+ ).unsafe_ask()
223
+
224
+
153
225
  def prompt_flags() -> tuple[bool, bool]:
154
226
  """Returns (include_docker, include_tests)."""
155
227
  include_docker = questionary.confirm(
@@ -175,6 +247,10 @@ def run_interactive_flow(project_name: str = "") -> dict:
175
247
  stack = prompt_stack()
176
248
  ci = prompt_ci()
177
249
  log_lib = prompt_log_lib()
250
+ storage = prompt_storage()
251
+ ai = prompt_ai()
252
+ vector_db = prompt_vector_db()
253
+ monitoring = prompt_monitoring()
178
254
  include_docker, include_tests = prompt_flags()
179
255
 
180
256
  return {
@@ -187,6 +263,10 @@ def run_interactive_flow(project_name: str = "") -> dict:
187
263
  "stack": stack,
188
264
  "ci": ci,
189
265
  "log_lib": log_lib,
266
+ "storage": storage,
267
+ "ai": ai,
268
+ "vector_db": vector_db,
269
+ "monitoring": monitoring,
190
270
  "include_docker": include_docker,
191
271
  "include_tests": include_tests,
192
272
  }
@@ -7,6 +7,12 @@ from app.api.v1.auth.router import router as auth_router
7
7
  {% if has_websockets %}
8
8
  from app.api.v1.ws.router import router as ws_router
9
9
  {% endif %}
10
+ {% if "rbac" in extras %}
11
+ from app.api.v1.permissions.router import router as permissions_router
12
+ {% endif %}
13
+ {% if "uploads" in extras %}
14
+ from app.api.v1.uploads.router import router as uploads_router
15
+ {% endif %}
10
16
 
11
17
 
12
18
  router = APIRouter()
@@ -18,3 +24,9 @@ router.include_router(auth_router)
18
24
  {% if has_websockets %}
19
25
  router.include_router(ws_router)
20
26
  {% endif %}
27
+ {% if "rbac" in extras %}
28
+ router.include_router(permissions_router)
29
+ {% endif %}
30
+ {% if "uploads" in extras %}
31
+ router.include_router(uploads_router)
32
+ {% endif %}
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fastapi-spawn"
7
- version = "0.4.23"
7
+ version = "0.4.24"
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