fastapi-spawn 0.4.23__tar.gz → 0.4.25__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.
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/PKG-INFO +6 -1
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/README.md +5 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/cli.py +114 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/interactive.py +95 -15
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/router.py.j2 +12 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/pyproject.toml +1 -1
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/.gitignore +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/LICENSE +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/__init__.py +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/config.py +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/constants.py +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/generator.py +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/alembic/alembic.ini.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/alembic/env.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/__init__.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/admin/setup.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/deps.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/graphql.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/health/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/pagination/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/payments/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/permissions/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/streaming/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/uploads/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/ai.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/cache.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/config.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/email.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/exceptions.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/logger.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/logging.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/monitoring.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/notifications.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/ocr.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/permissions.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/search.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/security.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/storage.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/vector_db.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/ws_manager.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/db/session.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/frontend/index.html.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/main.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/middleware/__init__.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/middleware/rate_limit.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/middleware/request_logger.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/middleware/response_format.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/Makefile.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/README.md.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/env.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/env_example.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/gitignore.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/pre_commit.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/pyproject.toml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/ci/github/publish.yml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/ci/github/tests.yml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/db/seed.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/docker/Dockerfile.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/docker/docker-compose.yml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/docker/dockerignore.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/docker/docker-compose.prod.yml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/helm/values.yaml.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/terraform/main.tf.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/terraform/variables.tf.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/root/main.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tasks/arq_worker.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tasks/celery_app.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tasks/sample_tasks.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tests/conftest.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tests/test_health.py.j2 +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/utils.py +0 -0
- {fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/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.
|
|
3
|
+
Version: 0.4.25
|
|
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,120 @@ 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: Optional[str] = typer.Argument(None, help="Preset name (basic, full-local, full)"),
|
|
225
|
+
project_name: Optional[str] = typer.Argument(None, 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 not preset:
|
|
232
|
+
import questionary
|
|
233
|
+
from fastapi_spawn.interactive import SPAWN_STYLE
|
|
234
|
+
preset = questionary.select(
|
|
235
|
+
"Which preset do you want to use?",
|
|
236
|
+
choices=["basic", "full-local", "full"],
|
|
237
|
+
style=SPAWN_STYLE,
|
|
238
|
+
).unsafe_ask()
|
|
239
|
+
|
|
240
|
+
if not project_name:
|
|
241
|
+
import questionary
|
|
242
|
+
from fastapi_spawn.interactive import SPAWN_STYLE
|
|
243
|
+
from fastapi_spawn.validators import questionary_validator, validate_project_name
|
|
244
|
+
project_name = questionary.text(
|
|
245
|
+
"Project name:",
|
|
246
|
+
validate=questionary_validator(validate_project_name),
|
|
247
|
+
style=SPAWN_STYLE,
|
|
248
|
+
).unsafe_ask()
|
|
249
|
+
|
|
250
|
+
if preset == "basic":
|
|
251
|
+
config = ProjectConfig(
|
|
252
|
+
project_name=project_name,
|
|
253
|
+
db=Database.sqlite,
|
|
254
|
+
orm=ORM.sqlalchemy,
|
|
255
|
+
migration=MigrationTool.alembic,
|
|
256
|
+
auth=AuthType.jwt,
|
|
257
|
+
broker=Broker.none,
|
|
258
|
+
cache=Cache.none,
|
|
259
|
+
storage=Storage.local,
|
|
260
|
+
ai=AIProvider.none,
|
|
261
|
+
api_extra=APIExtra.none,
|
|
262
|
+
monitoring=MonitoringProvider.none,
|
|
263
|
+
log_lib=LogLibrary.loguru,
|
|
264
|
+
log_dest=LogDestination.local,
|
|
265
|
+
email=EmailProvider.none,
|
|
266
|
+
notify=NotificationProvider.none,
|
|
267
|
+
vector_db=VectorDB.none,
|
|
268
|
+
stack=Stack.minimal,
|
|
269
|
+
ci=CIProvider.none,
|
|
270
|
+
include_docker=True,
|
|
271
|
+
include_tests=True,
|
|
272
|
+
force=force,
|
|
273
|
+
)
|
|
274
|
+
elif preset == "full-local":
|
|
275
|
+
config = ProjectConfig(
|
|
276
|
+
project_name=project_name,
|
|
277
|
+
db=Database.postgresql,
|
|
278
|
+
orm=ORM.sqlalchemy,
|
|
279
|
+
migration=MigrationTool.alembic,
|
|
280
|
+
auth=AuthType.jwt,
|
|
281
|
+
broker=Broker.none,
|
|
282
|
+
cache=Cache.none,
|
|
283
|
+
storage=Storage.local,
|
|
284
|
+
ai=AIProvider.none,
|
|
285
|
+
api_extra=APIExtra.none,
|
|
286
|
+
monitoring=MonitoringProvider.none,
|
|
287
|
+
log_lib=LogLibrary.loguru,
|
|
288
|
+
log_dest=LogDestination.local,
|
|
289
|
+
email=EmailProvider.none,
|
|
290
|
+
notify=NotificationProvider.none,
|
|
291
|
+
vector_db=VectorDB.chroma,
|
|
292
|
+
stack=Stack.standard,
|
|
293
|
+
ci=CIProvider.none,
|
|
294
|
+
include_docker=True,
|
|
295
|
+
include_tests=True,
|
|
296
|
+
force=force,
|
|
297
|
+
)
|
|
298
|
+
elif preset == "full":
|
|
299
|
+
config = ProjectConfig(
|
|
300
|
+
project_name=project_name,
|
|
301
|
+
db=Database.postgresql,
|
|
302
|
+
orm=ORM.sqlalchemy,
|
|
303
|
+
migration=MigrationTool.alembic,
|
|
304
|
+
auth=AuthType.jwt,
|
|
305
|
+
broker=Broker.redis,
|
|
306
|
+
cache=Cache.redis,
|
|
307
|
+
storage=Storage.s3,
|
|
308
|
+
ai=AIProvider.openai,
|
|
309
|
+
api_extra=APIExtra.websockets,
|
|
310
|
+
monitoring=MonitoringProvider.both,
|
|
311
|
+
log_lib=LogLibrary.loguru,
|
|
312
|
+
log_dest=LogDestination.local,
|
|
313
|
+
email=EmailProvider.none,
|
|
314
|
+
notify=NotificationProvider.none,
|
|
315
|
+
vector_db=VectorDB.qdrant,
|
|
316
|
+
stack=Stack.full,
|
|
317
|
+
ci=CIProvider.github,
|
|
318
|
+
include_docker=True,
|
|
319
|
+
include_tests=True,
|
|
320
|
+
force=force,
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
rprint(f"[bold red]✗ Error:[/bold red] Unknown preset '{preset}'. Available presets: basic, full-local, full")
|
|
324
|
+
raise typer.Exit(1)
|
|
325
|
+
|
|
326
|
+
_print_summary(config)
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
generator = ProjectGenerator(config, output)
|
|
330
|
+
project_path = generator.generate()
|
|
331
|
+
rprint(f"\n[bold green]✓ Project created:[/bold green] {project_path.resolve()}")
|
|
332
|
+
_print_next_steps(config)
|
|
333
|
+
except Exception as exc:
|
|
334
|
+
rprint(f"\n[bold red]✗ Generation failed:[/bold red] {exc}")
|
|
335
|
+
raise typer.Exit(1) from exc
|
|
222
336
|
|
|
223
337
|
|
|
224
338
|
# ── `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
|
}
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/router.py.j2
RENAMED
|
@@ -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.
|
|
7
|
+
version = "0.4.25"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/alembic/alembic.ini.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/health/router.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/exceptions.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/logging.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/monitoring.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/notifications.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/permissions.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/security.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/storage.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/vector_db.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/core/ws_manager.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/frontend/index.html.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/app/middleware/__init__.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/base/pyproject.toml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/ci/github/publish.yml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/ci/github/tests.yml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/docker/docker-compose.yml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/docker/dockerignore.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/helm/values.yaml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/infra/terraform/main.tf.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tasks/arq_worker.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tasks/celery_app.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tasks/sample_tasks.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.23 → fastapi_spawn-0.4.25}/fastapi_spawn/templates/tests/test_health.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|