fastapi-spawn 0.4.9__tar.gz → 0.4.12__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.9 → fastapi_spawn-0.4.12}/PKG-INFO +42 -8
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/README.md +41 -7
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/__init__.py +1 -1
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/cli.py +20 -4
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/constants.py +6 -2
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/generator.py +2 -1
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2 +48 -3
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/env.j2 +21 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/env_example.j2 +41 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/pyproject.toml.j2 +4 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/pyproject.toml +1 -1
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/.gitignore +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/LICENSE +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/config.py +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/interactive.py +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/alembic/alembic.ini.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/alembic/env.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/__init__.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/deps.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/graphql.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/health/router.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/payments/router.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/router.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/streaming/router.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/ai.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/config.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/email.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/exceptions.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/logger.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/logging.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/monitoring.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/notifications.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/ocr.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/search.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/security.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/storage.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/vector_db.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/ws_manager.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/db/session.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/frontend/index.html.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/main.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/middleware/__init__.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/middleware/rate_limit.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/middleware/request_logger.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/Makefile.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/README.md.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/gitignore.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/base/pre_commit.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/ci/github/publish.yml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/ci/github/tests.yml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/db/seed.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/docker/Dockerfile.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/docker/docker-compose.yml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/docker/dockerignore.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/docker/docker-compose.prod.yml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/helm/values.yaml.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/terraform/main.tf.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/terraform/variables.tf.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/root/main.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tasks/arq_worker.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tasks/celery_app.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tasks/sample_tasks.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tests/conftest.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tests/test_health.py.j2 +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/utils.py +0 -0
- {fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/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.12
|
|
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
|
|
@@ -381,6 +381,10 @@ SMTP_SSL=false
|
|
|
381
381
|
# ── AWS SES ──────────────────────────────────────────────────────────────
|
|
382
382
|
SES_FROM_EMAIL=noreply@example.com # uses AWS_* credentials above
|
|
383
383
|
|
|
384
|
+
# ── Resend ───────────────────────────────────────────────────────────────
|
|
385
|
+
RESEND_API_KEY=re_placeholder
|
|
386
|
+
RESEND_FROM_EMAIL=noreply@example.com
|
|
387
|
+
|
|
384
388
|
# ── Slack ────────────────────────────────────────────────────────────────
|
|
385
389
|
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/CHANGE_ME
|
|
386
390
|
|
|
@@ -402,6 +406,31 @@ ELASTICSEARCH_HOST=localhost
|
|
|
402
406
|
ELASTICSEARCH_PORT=9200
|
|
403
407
|
ELASTICSEARCH_API_KEY=
|
|
404
408
|
# → assembled as: http://HOST:PORT
|
|
409
|
+
|
|
410
|
+
# ── OpenSearch ───────────────────────────────────────────────────────────
|
|
411
|
+
OPENSEARCH_HOST=localhost
|
|
412
|
+
OPENSEARCH_PORT=9200
|
|
413
|
+
OPENSEARCH_USER=admin
|
|
414
|
+
OPENSEARCH_PASSWORD=admin
|
|
415
|
+
|
|
416
|
+
# ── Vespa ────────────────────────────────────────────────────────────────
|
|
417
|
+
VESPA_ENDPOINT=http://localhost:8080
|
|
418
|
+
|
|
419
|
+
# ── Extras (Stripe, SSO, Meilisearch) ────────────────────────────────────
|
|
420
|
+
STRIPE_API_KEY=sk_test_placeholder
|
|
421
|
+
STRIPE_WEBHOOK_SECRET=whsec_placeholder
|
|
422
|
+
|
|
423
|
+
GOOGLE_CLIENT_ID=placeholder
|
|
424
|
+
GOOGLE_CLIENT_SECRET=placeholder
|
|
425
|
+
|
|
426
|
+
GITHUB_CLIENT_ID=placeholder
|
|
427
|
+
GITHUB_CLIENT_SECRET=placeholder
|
|
428
|
+
|
|
429
|
+
MICROSOFT_CLIENT_ID=placeholder
|
|
430
|
+
MICROSOFT_CLIENT_SECRET=placeholder
|
|
431
|
+
|
|
432
|
+
MEILISEARCH_HOST=http://localhost:7700
|
|
433
|
+
MEILISEARCH_API_KEY=masterKey
|
|
405
434
|
```
|
|
406
435
|
|
|
407
436
|
> All variables are assembled into connection URLs inside `app/core/config.py` via `@property`. Your code always reads from structured fields — never a fragile connection string.
|
|
@@ -450,12 +479,12 @@ Did you generate a minimal project and now realize you need WebSockets, AWS S3,
|
|
|
450
479
|
fastapi-spawn add [FEATURE]
|
|
451
480
|
```
|
|
452
481
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
482
|
+
Or you can add them at creation time with the `--extra` flag:
|
|
483
|
+
```bash
|
|
484
|
+
fastapi-spawn new my_app --extra stripe --extra sso --extra seed
|
|
485
|
+
```
|
|
457
486
|
|
|
458
|
-
### All Possibilities you can `add`:
|
|
487
|
+
### All Possibilities you can `add` or `--extra`:
|
|
459
488
|
|
|
460
489
|
You can run any of the following commands inside an existing project:
|
|
461
490
|
|
|
@@ -474,11 +503,16 @@ fastapi-spawn add qdrant # Qdrant vector DB
|
|
|
474
503
|
fastapi-spawn add chroma # ChromaDB local vector DB
|
|
475
504
|
fastapi-spawn add pinecone # Pinecone cloud vector DB
|
|
476
505
|
fastapi-spawn add meilisearch # Meilisearch typo-tolerant search
|
|
506
|
+
fastapi-spawn add opensearch # OpenSearch vector & text search
|
|
507
|
+
fastapi-spawn add vespa # Vespa big data serving engine
|
|
477
508
|
fastapi-spawn add ocr # PDF & OCR data extraction pipeline
|
|
478
509
|
|
|
479
510
|
# Payments & Identity
|
|
480
511
|
fastapi-spawn add stripe # Stripe payments & webhooks
|
|
481
|
-
fastapi-spawn add sso # FastAPI SSO (Google
|
|
512
|
+
fastapi-spawn add sso # FastAPI SSO (Google, GitHub, Microsoft)
|
|
513
|
+
fastapi-spawn add sso-google # FastAPI SSO (Google only)
|
|
514
|
+
fastapi-spawn add sso-github # FastAPI SSO (GitHub only)
|
|
515
|
+
fastapi-spawn add sso-microsoft # FastAPI SSO (Microsoft only)
|
|
482
516
|
|
|
483
517
|
# Messaging & Async Workers
|
|
484
518
|
fastapi-spawn add celery # Celery worker + tasks/
|
|
@@ -490,7 +524,7 @@ fastapi-spawn add sse # Server-Sent Events streaming
|
|
|
490
524
|
fastapi-spawn add s3 # AWS S3 / MinIO storage
|
|
491
525
|
fastapi-spawn add graphql # Strawberry GraphQL schema
|
|
492
526
|
fastapi-spawn add alembic # Alembic async migrations
|
|
493
|
-
fastapi-spawn add seed # Faker database seeding script
|
|
527
|
+
fastapi-spawn add seed # Faker database seeding script (Users, Posts, Comments)
|
|
494
528
|
fastapi-spawn add resend # Resend modern email client
|
|
495
529
|
fastapi-spawn add sentry # Sentry APM integration
|
|
496
530
|
fastapi-spawn add prometheus # Prometheus metrics
|
|
@@ -340,6 +340,10 @@ SMTP_SSL=false
|
|
|
340
340
|
# ── AWS SES ──────────────────────────────────────────────────────────────
|
|
341
341
|
SES_FROM_EMAIL=noreply@example.com # uses AWS_* credentials above
|
|
342
342
|
|
|
343
|
+
# ── Resend ───────────────────────────────────────────────────────────────
|
|
344
|
+
RESEND_API_KEY=re_placeholder
|
|
345
|
+
RESEND_FROM_EMAIL=noreply@example.com
|
|
346
|
+
|
|
343
347
|
# ── Slack ────────────────────────────────────────────────────────────────
|
|
344
348
|
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/CHANGE_ME
|
|
345
349
|
|
|
@@ -361,6 +365,31 @@ ELASTICSEARCH_HOST=localhost
|
|
|
361
365
|
ELASTICSEARCH_PORT=9200
|
|
362
366
|
ELASTICSEARCH_API_KEY=
|
|
363
367
|
# → assembled as: http://HOST:PORT
|
|
368
|
+
|
|
369
|
+
# ── OpenSearch ───────────────────────────────────────────────────────────
|
|
370
|
+
OPENSEARCH_HOST=localhost
|
|
371
|
+
OPENSEARCH_PORT=9200
|
|
372
|
+
OPENSEARCH_USER=admin
|
|
373
|
+
OPENSEARCH_PASSWORD=admin
|
|
374
|
+
|
|
375
|
+
# ── Vespa ────────────────────────────────────────────────────────────────
|
|
376
|
+
VESPA_ENDPOINT=http://localhost:8080
|
|
377
|
+
|
|
378
|
+
# ── Extras (Stripe, SSO, Meilisearch) ────────────────────────────────────
|
|
379
|
+
STRIPE_API_KEY=sk_test_placeholder
|
|
380
|
+
STRIPE_WEBHOOK_SECRET=whsec_placeholder
|
|
381
|
+
|
|
382
|
+
GOOGLE_CLIENT_ID=placeholder
|
|
383
|
+
GOOGLE_CLIENT_SECRET=placeholder
|
|
384
|
+
|
|
385
|
+
GITHUB_CLIENT_ID=placeholder
|
|
386
|
+
GITHUB_CLIENT_SECRET=placeholder
|
|
387
|
+
|
|
388
|
+
MICROSOFT_CLIENT_ID=placeholder
|
|
389
|
+
MICROSOFT_CLIENT_SECRET=placeholder
|
|
390
|
+
|
|
391
|
+
MEILISEARCH_HOST=http://localhost:7700
|
|
392
|
+
MEILISEARCH_API_KEY=masterKey
|
|
364
393
|
```
|
|
365
394
|
|
|
366
395
|
> All variables are assembled into connection URLs inside `app/core/config.py` via `@property`. Your code always reads from structured fields — never a fragile connection string.
|
|
@@ -409,12 +438,12 @@ Did you generate a minimal project and now realize you need WebSockets, AWS S3,
|
|
|
409
438
|
fastapi-spawn add [FEATURE]
|
|
410
439
|
```
|
|
411
440
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
441
|
+
Or you can add them at creation time with the `--extra` flag:
|
|
442
|
+
```bash
|
|
443
|
+
fastapi-spawn new my_app --extra stripe --extra sso --extra seed
|
|
444
|
+
```
|
|
416
445
|
|
|
417
|
-
### All Possibilities you can `add`:
|
|
446
|
+
### All Possibilities you can `add` or `--extra`:
|
|
418
447
|
|
|
419
448
|
You can run any of the following commands inside an existing project:
|
|
420
449
|
|
|
@@ -433,11 +462,16 @@ fastapi-spawn add qdrant # Qdrant vector DB
|
|
|
433
462
|
fastapi-spawn add chroma # ChromaDB local vector DB
|
|
434
463
|
fastapi-spawn add pinecone # Pinecone cloud vector DB
|
|
435
464
|
fastapi-spawn add meilisearch # Meilisearch typo-tolerant search
|
|
465
|
+
fastapi-spawn add opensearch # OpenSearch vector & text search
|
|
466
|
+
fastapi-spawn add vespa # Vespa big data serving engine
|
|
436
467
|
fastapi-spawn add ocr # PDF & OCR data extraction pipeline
|
|
437
468
|
|
|
438
469
|
# Payments & Identity
|
|
439
470
|
fastapi-spawn add stripe # Stripe payments & webhooks
|
|
440
|
-
fastapi-spawn add sso # FastAPI SSO (Google
|
|
471
|
+
fastapi-spawn add sso # FastAPI SSO (Google, GitHub, Microsoft)
|
|
472
|
+
fastapi-spawn add sso-google # FastAPI SSO (Google only)
|
|
473
|
+
fastapi-spawn add sso-github # FastAPI SSO (GitHub only)
|
|
474
|
+
fastapi-spawn add sso-microsoft # FastAPI SSO (Microsoft only)
|
|
441
475
|
|
|
442
476
|
# Messaging & Async Workers
|
|
443
477
|
fastapi-spawn add celery # Celery worker + tasks/
|
|
@@ -449,7 +483,7 @@ fastapi-spawn add sse # Server-Sent Events streaming
|
|
|
449
483
|
fastapi-spawn add s3 # AWS S3 / MinIO storage
|
|
450
484
|
fastapi-spawn add graphql # Strawberry GraphQL schema
|
|
451
485
|
fastapi-spawn add alembic # Alembic async migrations
|
|
452
|
-
fastapi-spawn add seed # Faker database seeding script
|
|
486
|
+
fastapi-spawn add seed # Faker database seeding script (Users, Posts, Comments)
|
|
453
487
|
fastapi-spawn add resend # Resend modern email client
|
|
454
488
|
fastapi-spawn add sentry # Sentry APM integration
|
|
455
489
|
fastapi-spawn add prometheus # Prometheus metrics
|
|
@@ -62,6 +62,14 @@ def version_callback(value: bool) -> None:
|
|
|
62
62
|
raise typer.Exit()
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
@app.command("help", help="Show this help message and exit.")
|
|
66
|
+
def show_help(ctx: typer.Context) -> None:
|
|
67
|
+
"""Print the global CLI help."""
|
|
68
|
+
# We leverage Click's internal help formatting to render the same as --help
|
|
69
|
+
rprint(ctx.parent.get_help())
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
65
73
|
# ── `new` command ──────────────────────────────────────────────────────────────
|
|
66
74
|
|
|
67
75
|
@app.command("new", help="Create a new FastAPI project.")
|
|
@@ -278,8 +286,6 @@ _ADDABLE_FEATURES = {
|
|
|
278
286
|
"opentelemetry": "OpenTelemetry distributed tracing",
|
|
279
287
|
"sendgrid": "SendGrid email",
|
|
280
288
|
"smtp": "SMTP email (fastapi-mail)",
|
|
281
|
-
"ses": "AWS SES email",
|
|
282
|
-
"resend": "Resend email client (modern React/HTML emails)",
|
|
283
289
|
"slack": "Slack webhook notifications",
|
|
284
290
|
"discord": "Discord webhook notifications",
|
|
285
291
|
"qdrant": "Qdrant vector database",
|
|
@@ -287,11 +293,16 @@ _ADDABLE_FEATURES = {
|
|
|
287
293
|
"pinecone": "Pinecone managed vector database",
|
|
288
294
|
"elasticsearch": "Elasticsearch KNN search",
|
|
289
295
|
"meilisearch": "Meilisearch ultra-fast typo-tolerant search",
|
|
296
|
+
"opensearch": "OpenSearch vector and text search",
|
|
297
|
+
"vespa": "Vespa big data serving engine",
|
|
290
298
|
"websockets": "WebSocket connection manager + endpoints",
|
|
291
299
|
"sse": "Server-Sent Events (SSE) streaming endpoint",
|
|
292
300
|
"graphql": "Strawberry GraphQL schema + subscriptions",
|
|
293
301
|
"stripe": "Stripe payments & webhook signature validation",
|
|
294
|
-
"sso": "FastAPI SSO (
|
|
302
|
+
"sso": "FastAPI SSO (Google, GitHub, Microsoft)",
|
|
303
|
+
"sso-google": "FastAPI SSO (Google only)",
|
|
304
|
+
"sso-github": "FastAPI SSO (GitHub only)",
|
|
305
|
+
"sso-microsoft": "FastAPI SSO (Microsoft only)",
|
|
295
306
|
"seed": "Database seeding script using Faker",
|
|
296
307
|
"ocr": "PDF & OCR data pipeline (PyMuPDF / Tesseract)",
|
|
297
308
|
"docker": "Dockerfile + docker-compose.yml",
|
|
@@ -356,11 +367,16 @@ def _feature_guidance(feature: str, _project_dir: Path) -> None:
|
|
|
356
367
|
"pinecone": ["Add dep: pinecone-client>=3.2.0", "Create app/core/vector_db.py", "Add to .env: PINECONE_API_KEY, PINECONE_INDEX_NAME"],
|
|
357
368
|
"elasticsearch": ["Add dep: elasticsearch[async]>=8.13.0", "Create app/core/vector_db.py (kNN search)", "Add to .env: ELASTICSEARCH_HOST, ELASTICSEARCH_PORT, ELASTICSEARCH_API_KEY"],
|
|
358
369
|
"meilisearch": ["Add dep: meilisearch>=0.30.0", "Create app/core/search.py (Meilisearch client)", "Add to .env: MEILISEARCH_HOST=http://localhost:7700, MEILISEARCH_API_KEY"],
|
|
370
|
+
"opensearch": ["Add dep: opensearch-py[async]>=2.5.0", "Create app/core/search.py (OpenSearch client)", "Add to .env: OPENSEARCH_HOST, OPENSEARCH_PORT, OPENSEARCH_USER, OPENSEARCH_PASSWORD"],
|
|
371
|
+
"vespa": ["Add dep: pyvespa>=0.40.0", "Create app/core/search.py (Vespa client)", "Add to .env: VESPA_ENDPOINT"],
|
|
359
372
|
"websockets":["No extra dep (built into FastAPI)", "Create app/core/ws_manager.py (ConnectionManager)", "Create app/api/v1/ws/router.py — /ws/connect, /ws/connect/{room_id}"],
|
|
360
373
|
"sse": ["Add dep: sse-starlette>=2.1.0", "Create app/api/v1/streaming/router.py", "Return EventSourceResponse(async_generator)"],
|
|
361
374
|
"graphql": ["Add dep: strawberry-graphql[fastapi]>=0.227.0", "Create app/api/graphql.py (Query + Mutation + Subscription)", "Mount: app.include_router(graphql_router, prefix='/graphql')"],
|
|
362
375
|
"stripe": ["Add dep: stripe>=9.0.0", "Create app/api/v1/payments/router.py (webhook endpoint)", "Add to .env: STRIPE_API_KEY, STRIPE_WEBHOOK_SECRET"],
|
|
363
|
-
"sso": ["Add dep: fastapi-sso>=0.14.0", "Create app/api/v1/auth/sso.py (
|
|
376
|
+
"sso": ["Add dep: fastapi-sso>=0.14.0", "Create app/api/v1/auth/sso.py (Google/Github/Microsoft SSO)", "Add to .env: GOOGLE_CLIENT_ID, GITHUB_CLIENT_ID, etc."],
|
|
377
|
+
"sso-google": ["1. Use 'fastapi-spawn new temp_app --extra sso-google' and copy the resulting sso.py"],
|
|
378
|
+
"sso-github": ["1. Use 'fastapi-spawn new temp_app --extra sso-github' and copy the resulting sso.py"],
|
|
379
|
+
"sso-microsoft": ["1. Use 'fastapi-spawn new temp_app --extra sso-microsoft' and copy the resulting sso.py"],
|
|
364
380
|
"seed": ["Add dep: faker>=25.0.0", "Create db/seed.py (generate 100 mock users/posts)", "Run: uv run python db/seed.py"],
|
|
365
381
|
"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"],
|
|
366
382
|
"docker": ["Create Dockerfile (multi-stage, uv-based)", "Create docker-compose.yml with all selected services", "Create .dockerignore"],
|
|
@@ -128,6 +128,8 @@ class VectorDB(str, Enum):
|
|
|
128
128
|
pinecone = "pinecone"
|
|
129
129
|
supabase = "supabase" # pgvector on Supabase
|
|
130
130
|
elasticsearch = "elasticsearch"
|
|
131
|
+
opensearch = "opensearch"
|
|
132
|
+
vespa = "vespa"
|
|
131
133
|
none = "none"
|
|
132
134
|
|
|
133
135
|
|
|
@@ -256,8 +258,10 @@ VECTOR_DB_LABELS = {
|
|
|
256
258
|
VectorDB.qdrant: "Qdrant — local Docker or Qdrant Cloud",
|
|
257
259
|
VectorDB.chroma: "ChromaDB — local open-source vector DB",
|
|
258
260
|
VectorDB.pinecone: "Pinecone — managed cloud",
|
|
259
|
-
VectorDB.supabase: "Supabase pgvector",
|
|
260
|
-
VectorDB.elasticsearch: "Elasticsearch
|
|
261
|
+
VectorDB.supabase: "Supabase (pgvector)",
|
|
262
|
+
VectorDB.elasticsearch: "Elasticsearch",
|
|
263
|
+
VectorDB.opensearch: "OpenSearch",
|
|
264
|
+
VectorDB.vespa: "Vespa",
|
|
261
265
|
VectorDB.none: "No vector database",
|
|
262
266
|
}
|
|
263
267
|
|
|
@@ -216,7 +216,8 @@ class ProjectGenerator:
|
|
|
216
216
|
self._render_to(v1 / "payments" / "router.py", "app/api/v1/payments/router.py.j2")
|
|
217
217
|
self._render_to(v1 / "payments" / "__init__.py", "app/__init__.py.j2")
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
has_sso = any(e.startswith("sso") for e in extras)
|
|
220
|
+
if has_sso:
|
|
220
221
|
(v1 / "auth").mkdir(parents=True, exist_ok=True)
|
|
221
222
|
self._render_to(v1 / "auth" / "sso.py", "app/api/v1/auth/sso.py.j2")
|
|
222
223
|
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/auth/sso.py.j2
RENAMED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from fastapi import APIRouter, Request, HTTPException
|
|
2
|
-
from fastapi_sso.sso.google import GoogleSSO
|
|
3
|
-
from fastapi_sso.sso.github import GithubSSO
|
|
4
2
|
from app.core.config import settings
|
|
5
3
|
|
|
6
4
|
router = APIRouter(prefix="/sso", tags=["auth"])
|
|
7
5
|
|
|
6
|
+
{% if "sso-google" in extras or "sso" in extras %}
|
|
7
|
+
from fastapi_sso.sso.google import GoogleSSO
|
|
8
|
+
|
|
8
9
|
# Requires GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env
|
|
9
10
|
google_sso = GoogleSSO(
|
|
10
11
|
client_id=getattr(settings, "GOOGLE_CLIENT_ID", "placeholder"),
|
|
@@ -27,7 +28,6 @@ async def google_callback(request: Request):
|
|
|
27
28
|
if not user:
|
|
28
29
|
raise HTTPException(status_code=400, detail="Failed to login via Google")
|
|
29
30
|
|
|
30
|
-
# TODO: Create or update user in database, then generate and return JWT
|
|
31
31
|
return {
|
|
32
32
|
"id": user.id,
|
|
33
33
|
"email": user.email,
|
|
@@ -36,6 +36,10 @@ async def google_callback(request: Request):
|
|
|
36
36
|
"picture": user.picture,
|
|
37
37
|
"provider": "google"
|
|
38
38
|
}
|
|
39
|
+
{% endif %}
|
|
40
|
+
|
|
41
|
+
{% if "sso-github" in extras or "sso" in extras %}
|
|
42
|
+
from fastapi_sso.sso.github import GithubSSO
|
|
39
43
|
|
|
40
44
|
# --- GitHub SSO ---
|
|
41
45
|
|
|
@@ -69,3 +73,44 @@ async def github_callback(request: Request):
|
|
|
69
73
|
"picture": getattr(user, "picture", None),
|
|
70
74
|
"provider": "github"
|
|
71
75
|
}
|
|
76
|
+
{% endif %}
|
|
77
|
+
|
|
78
|
+
{% if "sso-microsoft" in extras or "sso" in extras %}
|
|
79
|
+
from fastapi_sso.sso.microsoft import MicrosoftSSO
|
|
80
|
+
|
|
81
|
+
# --- Microsoft SSO ---
|
|
82
|
+
|
|
83
|
+
# Requires MICROSOFT_CLIENT_ID and MICROSOFT_CLIENT_SECRET in .env
|
|
84
|
+
microsoft_sso = MicrosoftSSO(
|
|
85
|
+
client_id=getattr(settings, "MICROSOFT_CLIENT_ID", "placeholder"),
|
|
86
|
+
client_secret=getattr(settings, "MICROSOFT_CLIENT_SECRET", "placeholder"),
|
|
87
|
+
tenant="common", # Or your specific tenant ID
|
|
88
|
+
redirect_uri="http://localhost:8000/api/v1/auth/sso/microsoft/callback",
|
|
89
|
+
allow_insecure_http=True, # Set to False in production
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
@router.get("/microsoft/login")
|
|
93
|
+
async def microsoft_login():
|
|
94
|
+
"""Redirects the user to the Microsoft login page."""
|
|
95
|
+
with microsoft_sso:
|
|
96
|
+
return await microsoft_sso.get_login_redirect()
|
|
97
|
+
|
|
98
|
+
@router.get("/microsoft/callback")
|
|
99
|
+
async def microsoft_callback(request: Request):
|
|
100
|
+
"""Process login response from Microsoft and return user info."""
|
|
101
|
+
with microsoft_sso:
|
|
102
|
+
user = await microsoft_sso.verify_and_process(request)
|
|
103
|
+
if not user:
|
|
104
|
+
raise HTTPException(status_code=400, detail="Failed to login via Microsoft")
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
"id": user.id,
|
|
108
|
+
"email": user.email,
|
|
109
|
+
"first_name": getattr(user, "first_name", None),
|
|
110
|
+
"last_name": getattr(user, "last_name", None),
|
|
111
|
+
"picture": getattr(user, "picture", None),
|
|
112
|
+
"provider": "microsoft"
|
|
113
|
+
}
|
|
114
|
+
{% endif %}
|
|
115
|
+
|
|
116
|
+
|
|
@@ -80,3 +80,24 @@ OPENAI_BASE_URL= # leave blank for api.openai.com; set fo
|
|
|
80
80
|
ANTHROPIC_API_KEY=sk-ant-placeholder
|
|
81
81
|
ANTHROPIC_MODEL=claude-3-5-sonnet-20241022
|
|
82
82
|
{% endif %}
|
|
83
|
+
{% if extras %}
|
|
84
|
+
{% if "stripe" in extras %}
|
|
85
|
+
# Stripe
|
|
86
|
+
STRIPE_API_KEY=sk_test_placeholder
|
|
87
|
+
STRIPE_WEBHOOK_SECRET=whsec_placeholder
|
|
88
|
+
{% endif %}
|
|
89
|
+
{% if "sso" in extras or "sso-google" in extras or "sso-github" in extras or "sso-microsoft" in extras %}
|
|
90
|
+
# SSO (Google, GitHub, Microsoft)
|
|
91
|
+
GOOGLE_CLIENT_ID=placeholder
|
|
92
|
+
GOOGLE_CLIENT_SECRET=placeholder
|
|
93
|
+
GITHUB_CLIENT_ID=placeholder
|
|
94
|
+
GITHUB_CLIENT_SECRET=placeholder
|
|
95
|
+
MICROSOFT_CLIENT_ID=placeholder
|
|
96
|
+
MICROSOFT_CLIENT_SECRET=placeholder
|
|
97
|
+
{% endif %}
|
|
98
|
+
{% if "meilisearch" in extras %}
|
|
99
|
+
# Meilisearch
|
|
100
|
+
MEILISEARCH_HOST=http://localhost:7700
|
|
101
|
+
MEILISEARCH_API_KEY=masterKey
|
|
102
|
+
{% endif %}
|
|
103
|
+
{% endif %}
|
|
@@ -229,11 +229,16 @@ SMTP_SSL=false
|
|
|
229
229
|
{% elif email == "ses" %}
|
|
230
230
|
# AWS SES (active) — uses AWS_* credentials above
|
|
231
231
|
SES_FROM_EMAIL=noreply@example.com
|
|
232
|
+
{% elif email == "resend" %}
|
|
233
|
+
# Resend (active)
|
|
234
|
+
RESEND_API_KEY=re_placeholder
|
|
235
|
+
RESEND_FROM_EMAIL=noreply@example.com
|
|
232
236
|
{% else %}
|
|
233
237
|
# Email — uncomment the provider you need:
|
|
234
238
|
# SendGrid: SENDGRID_API_KEY=SG.placeholder | SENDGRID_FROM_EMAIL=noreply@example.com
|
|
235
239
|
# SMTP: SMTP_HOST=smtp.gmail.com | SMTP_PORT=587 | SMTP_USER=... | SMTP_PASSWORD=... | SMTP_FROM_EMAIL=... | SMTP_STARTTLS=true | SMTP_SSL=false
|
|
236
240
|
# AWS SES: SES_FROM_EMAIL=noreply@example.com (uses AWS_* credentials)
|
|
241
|
+
# Resend: RESEND_API_KEY=re_placeholder | RESEND_FROM_EMAIL=noreply@example.com
|
|
237
242
|
{% endif %}
|
|
238
243
|
|
|
239
244
|
# =============================================================================
|
|
@@ -273,6 +278,15 @@ PINECONE_INDEX_NAME={{ slug }}-index
|
|
|
273
278
|
ELASTICSEARCH_HOST=localhost
|
|
274
279
|
ELASTICSEARCH_PORT=9200
|
|
275
280
|
ELASTICSEARCH_API_KEY=
|
|
281
|
+
{% elif vector_db == "opensearch" %}
|
|
282
|
+
# OpenSearch (active)
|
|
283
|
+
OPENSEARCH_HOST=localhost
|
|
284
|
+
OPENSEARCH_PORT=9200
|
|
285
|
+
OPENSEARCH_USER=admin
|
|
286
|
+
OPENSEARCH_PASSWORD=admin
|
|
287
|
+
{% elif vector_db == "vespa" %}
|
|
288
|
+
# Vespa (active)
|
|
289
|
+
VESPA_ENDPOINT=http://localhost:8080
|
|
276
290
|
{% else %}
|
|
277
291
|
# Vector DB — uncomment the provider you need:
|
|
278
292
|
# Qdrant: QDRANT_HOST=localhost | QDRANT_PORT=6333 | QDRANT_API_KEY= (blank for local)
|
|
@@ -280,6 +294,8 @@ ELASTICSEARCH_API_KEY=
|
|
|
280
294
|
# Pinecone: PINECONE_API_KEY=CHANGE_ME | PINECONE_INDEX_NAME={{ slug }}-index
|
|
281
295
|
# Supabase: uses SUPABASE_URL / SUPABASE_KEY above
|
|
282
296
|
# Elasticsearch: ELASTICSEARCH_HOST=localhost | ELASTICSEARCH_PORT=9200 | ELASTICSEARCH_API_KEY=
|
|
297
|
+
# OpenSearch: OPENSEARCH_HOST=localhost | OPENSEARCH_PORT=9200 | OPENSEARCH_USER=admin | OPENSEARCH_PASSWORD=admin
|
|
298
|
+
# Vespa: VESPA_ENDPOINT=http://localhost:8080
|
|
283
299
|
{% endif %}
|
|
284
300
|
|
|
285
301
|
# =============================================================================
|
|
@@ -298,3 +314,28 @@ DD_SITE=datadoghq.com
|
|
|
298
314
|
# Datadog: DD_API_KEY=CHANGE_ME | DD_SITE=datadoghq.com
|
|
299
315
|
# OpenTelemetry: OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317 (set in compose)
|
|
300
316
|
{% endif %}
|
|
317
|
+
|
|
318
|
+
# =============================================================================
|
|
319
|
+
# EXTRAS (Payments, SSO, Search)
|
|
320
|
+
# =============================================================================
|
|
321
|
+
{% if extras %}
|
|
322
|
+
{% if "stripe" in extras %}
|
|
323
|
+
# Stripe (active)
|
|
324
|
+
STRIPE_API_KEY=sk_test_placeholder
|
|
325
|
+
STRIPE_WEBHOOK_SECRET=whsec_placeholder
|
|
326
|
+
{% endif %}
|
|
327
|
+
{% if "sso" in extras or "sso-google" in extras or "sso-github" in extras or "sso-microsoft" in extras %}
|
|
328
|
+
# SSO - Google, GitHub, Microsoft (active)
|
|
329
|
+
GOOGLE_CLIENT_ID=placeholder
|
|
330
|
+
GOOGLE_CLIENT_SECRET=placeholder
|
|
331
|
+
GITHUB_CLIENT_ID=placeholder
|
|
332
|
+
GITHUB_CLIENT_SECRET=placeholder
|
|
333
|
+
MICROSOFT_CLIENT_ID=placeholder
|
|
334
|
+
MICROSOFT_CLIENT_SECRET=placeholder
|
|
335
|
+
{% endif %}
|
|
336
|
+
{% if "meilisearch" in extras %}
|
|
337
|
+
# Meilisearch (active)
|
|
338
|
+
MEILISEARCH_HOST=http://localhost:7700
|
|
339
|
+
MEILISEARCH_API_KEY=masterKey
|
|
340
|
+
{% endif %}
|
|
341
|
+
{% endif %}
|
|
@@ -111,6 +111,10 @@ dependencies = [
|
|
|
111
111
|
"supabase>=2.4.0",
|
|
112
112
|
{% elif vector_db == "elasticsearch" %}
|
|
113
113
|
"elasticsearch[async]>=8.13.0",
|
|
114
|
+
{% elif vector_db == "opensearch" %}
|
|
115
|
+
"opensearch-py[async]>=2.5.0",
|
|
116
|
+
{% elif vector_db == "vespa" %}
|
|
117
|
+
"pyvespa>=0.40.0",
|
|
114
118
|
{% endif %}
|
|
115
119
|
|
|
116
120
|
{% if has_websockets %}
|
|
@@ -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.12"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/auth/router.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/health/router.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/router.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/api/v1/ws/router.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/exceptions.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/monitoring.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/notifications.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/security.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/vector_db.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/core/ws_manager.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/frontend/index.html.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/middleware/__init__.py.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/app/middleware/rate_limit.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.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/ci/github/publish.yml.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/ci/gitlab/gitlab-ci.yml.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/docker/docker-compose.yml.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/helm/Chart.yaml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/helm/values.yaml.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/terraform/main.tf.j2
RENAMED
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/infra/terraform/variables.tf.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tasks/sample_tasks.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_spawn-0.4.9 → fastapi_spawn-0.4.12}/fastapi_spawn/templates/tests/test_health.py.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|