Skip to content

Commit f3d4e9f

Browse files
authored
Merge pull request #14 from bnbong/dev
[RELEASE] version 1.1.2
2 parents e1c171d + 0372e1d commit f3d4e9f

File tree

13 files changed

+529
-117
lines changed

13 files changed

+529
-117
lines changed

.github/workflows/changelog.yml

Lines changed: 0 additions & 37 deletions
This file was deleted.

.pre-commit-config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ repos:
1010
- id: end-of-file-fixer
1111
- id: check-yaml
1212
- id: check-toml
13-
- id: check-added-large-files
1413

1514
- repo: local
1615
hooks:

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## v.1.1.2 (2025-09-05)
4+
5+
### Improvements
6+
7+
- add a feature of `fastkit init`, `fastkit startdemo` command to define to make a new project folder at current working directory
8+
- add `setuptools` package at `fastapi-empty` template's dependency list.
9+
- add a feature of `fastkit addroute`command to recognize current working project (with cmd option `.`).
10+
311
## v1.1.1 (2025-08-15)
412

513
### Improvements

CONTRIBUTING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ FastAPI-fastkit uses following stacks:
2929
- isort for import sorting
3030
- mypy for static type checking
3131

32+
### Current Source Structure (Version 1.X.X+)
33+
34+
![fastkit diagram](docs/img/fastkit_diagram.png)
35+
3236
### Quick Setup with Makefile
3337

3438
The easiest way to set up your development environment is using our Makefile:

docs/img/fastkit_diagram.png

595 KB
Loading

src/fastapi_fastkit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "1.1.1"
1+
__version__ = "1.1.2"
22

33
import os
44

src/fastapi_fastkit/backend/main.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
import re
88
from typing import Dict, List
99

10+
import click
11+
1012
from fastapi_fastkit import console
1113
from fastapi_fastkit.backend.package_managers import PackageManagerFactory
12-
from fastapi_fastkit.backend.transducer import copy_and_convert_template_file
13-
from fastapi_fastkit.core.exceptions import BackendExceptions, TemplateExceptions
14+
from fastapi_fastkit.backend.transducer import (
15+
copy_and_convert_template,
16+
copy_and_convert_template_file,
17+
)
18+
from fastapi_fastkit.core.exceptions import BackendExceptions
1419
from fastapi_fastkit.core.settings import settings
1520
from fastapi_fastkit.utils.logging import debug_log, get_logger
1621
from fastapi_fastkit.utils.main import (
@@ -697,3 +702,68 @@ def add_new_route(project_dir: str, route_name: str) -> None:
697702
debug_log(f"Unexpected error while adding route {route_name}: {e}", "error")
698703
handle_exception(e, f"Error adding new route: {str(e)}")
699704
raise BackendExceptions(f"Failed to add new route: {str(e)}")
705+
706+
707+
# ------------------------------------------------------------
708+
# Create Project Folder Functions
709+
# ------------------------------------------------------------
710+
711+
712+
def ask_create_project_folder(project_name: str) -> bool:
713+
"""
714+
Ask user whether to create a new project folder.
715+
716+
:param project_name: Name of the project
717+
:return: True if user wants to create a folder, False otherwise
718+
"""
719+
return click.confirm(
720+
f"\nCreate a new project folder named '{project_name}'?\n"
721+
f"Yes: Templates will be placed in './{project_name}/'\n"
722+
f"No: Templates will be placed in current directory",
723+
default=True,
724+
)
725+
726+
727+
def deploy_template_with_folder_option(
728+
target_template: str, user_local: str, project_name: str, create_folder: bool
729+
) -> tuple[str, str]:
730+
"""
731+
Deploy template based on folder creation option.
732+
733+
:param target_template: Path to template directory
734+
:param user_local: User's workspace directory
735+
:param project_name: Name of the project
736+
:param create_folder: Whether to create a new folder
737+
:return: Tuple of (project_dir, deployment_message)
738+
"""
739+
if create_folder:
740+
project_dir = os.path.join(user_local, project_name)
741+
deployment_message = f"FastAPI template project will deploy at '{user_local}' in folder '{project_name}'"
742+
copy_and_convert_template(target_template, user_local, project_name)
743+
else:
744+
project_dir = user_local
745+
deployment_message = (
746+
f"FastAPI template project will deploy directly at '{user_local}'"
747+
)
748+
copy_and_convert_template(target_template, user_local, "")
749+
750+
click.echo(deployment_message)
751+
return project_dir, deployment_message
752+
753+
754+
def get_deployment_success_message(
755+
template: str, project_name: str, user_local: str, create_folder: bool
756+
) -> str:
757+
"""
758+
Get appropriate success message based on deployment option.
759+
760+
:param template: Template name used
761+
:param project_name: Name of the project
762+
:param user_local: User's workspace directory
763+
:param create_folder: Whether folder was created
764+
:return: Success message string
765+
"""
766+
if create_folder:
767+
return f"FastAPI project '{project_name}' from '{template}' has been created and saved to {user_local}!"
768+
else:
769+
return f"FastAPI project '{project_name}' from '{template}' has been deployed directly to {user_local}!"

src/fastapi_fastkit/cli.py

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# TODO : add a feature to automatically fix appropriate fastkit output console size
12
# --------------------------------------------------------------------------
23
# The Module defines main and core CLI operations for FastAPI-fastkit.
34
#
@@ -17,14 +18,16 @@
1718

1819
from fastapi_fastkit.backend.main import (
1920
add_new_route,
21+
ask_create_project_folder,
2022
create_venv_with_manager,
23+
deploy_template_with_folder_option,
2124
find_template_core_modules,
2225
generate_dependency_file_with_manager,
26+
get_deployment_success_message,
2327
inject_project_metadata,
2428
install_dependencies_with_manager,
2529
read_template_stack,
2630
)
27-
from fastapi_fastkit.backend.transducer import copy_and_convert_template
2831
from fastapi_fastkit.core.exceptions import CLIExceptions
2932
from fastapi_fastkit.core.settings import FastkitConfig
3033
from fastapi_fastkit.utils.logging import get_logger, setup_logging
@@ -191,6 +194,7 @@ def startdemo(
191194
"""
192195
Create a new FastAPI project from templates and inject metadata.
193196
"""
197+
# TODO : add --template-name option to specify the template name
194198
settings = ctx.obj["settings"]
195199

196200
template_dir = settings.FASTKIT_TEMPLATE_ROOT
@@ -258,25 +262,27 @@ def startdemo(
258262
print_error("Project creation aborted!")
259263
return
260264

265+
# Ask user whether to create a new project folder
266+
create_project_folder = ask_create_project_folder(project_name)
267+
261268
try:
262269
user_local = settings.USER_WORKSPACE
263-
project_dir = os.path.join(user_local, project_name)
264-
265-
click.echo(f"FastAPI template project will deploy at '{user_local}'")
266270

267-
copy_and_convert_template(target_template, user_local, project_name)
271+
project_dir, _ = deploy_template_with_folder_option(
272+
target_template, user_local, project_name, create_project_folder
273+
)
268274

269275
inject_project_metadata(
270276
project_dir, project_name, author, author_email, description
271277
)
272278

273-
# Create virtual environment and install dependencies with selected package manager
274279
venv_path = create_venv_with_manager(project_dir, package_manager)
275280
install_dependencies_with_manager(project_dir, venv_path, package_manager)
276281

277-
print_success(
278-
f"FastAPI project '{project_name}' from '{template}' has been created and saved to {user_local}!"
282+
success_message = get_deployment_success_message(
283+
template, project_name, user_local, create_project_folder
279284
)
285+
print_success(success_message)
280286

281287
except Exception as e:
282288
if settings.DEBUG_MODE:
@@ -323,8 +329,11 @@ def init(
323329
) -> None:
324330
"""
325331
Start a empty FastAPI project setup.
332+
326333
This command will automatically create a new FastAPI project directory and a python virtual environment.
334+
327335
Dependencies will be automatically installed based on the selected stack at venv.
336+
328337
Project metadata will be injected to the project files.
329338
"""
330339
settings = ctx.obj["settings"]
@@ -402,13 +411,15 @@ def init(
402411
print_error("Project creation aborted!")
403412
return
404413

414+
# Ask user whether to create a new project folder
415+
create_project_folder = ask_create_project_folder(project_name)
416+
405417
try:
406418
user_local = settings.USER_WORKSPACE
407-
project_dir = os.path.join(user_local, project_name)
408-
409-
click.echo(f"FastAPI project will deploy at '{user_local}'")
410419

411-
copy_and_convert_template(target_template, user_local, project_name)
420+
project_dir, _ = deploy_template_with_folder_option(
421+
target_template, user_local, project_name, create_project_folder
422+
)
412423

413424
inject_project_metadata(
414425
project_dir, project_name, author, author_email, description
@@ -439,9 +450,10 @@ def init(
439450
venv_path = create_venv_with_manager(project_dir, package_manager)
440451
install_dependencies_with_manager(project_dir, venv_path, package_manager)
441452

442-
print_success(
443-
f"FastAPI project '{project_name}' has been created successfully and saved to {user_local}!"
453+
success_message = get_deployment_success_message(
454+
template, project_name, user_local, create_project_folder
444455
)
456+
print_success(success_message)
445457

446458
print_info(
447459
"To start your project, run 'fastkit runserver' at newly created FastAPI project directory"
@@ -457,25 +469,43 @@ def init(
457469

458470

459471
@fastkit_cli.command()
460-
@click.argument("project_name")
461472
@click.argument("route_name")
473+
@click.argument("project_dir", default=".")
462474
@click.pass_context
463-
def addroute(ctx: Context, project_name: str, route_name: str) -> None:
475+
def addroute(ctx: Context, route_name: str, project_dir: str) -> None:
464476
"""
465477
Add a new route to the FastAPI project.
478+
479+
Examples:\n
480+
fastkit addroute user . # Add 'user' route to current directory
481+
fastkit addroute user my_project # Add 'user' route to 'my_project' in workspace
466482
"""
467483
settings = ctx.obj["settings"]
468-
user_local = settings.USER_WORKSPACE
469-
project_dir = os.path.join(user_local, project_name)
484+
485+
if project_dir == ".":
486+
actual_project_dir = os.getcwd()
487+
project_name = os.path.basename(actual_project_dir)
488+
else:
489+
user_local = settings.USER_WORKSPACE
490+
actual_project_dir = os.path.join(user_local, project_dir)
491+
project_name = project_dir
470492

471493
# Check if project exists
472-
if not os.path.exists(project_dir):
473-
print_error(f"Project '{project_name}' does not exist in '{user_local}'.")
494+
if not os.path.exists(actual_project_dir):
495+
if project_dir == ".":
496+
print_error("Current directory is not a valid project directory.")
497+
else:
498+
print_error(
499+
f"Project '{project_dir}' does not exist in '{settings.USER_WORKSPACE}'."
500+
)
474501
return
475502

476503
# Verify it's a fastkit project
477-
if not is_fastkit_project(project_dir):
478-
print_error(f"'{project_name}' is not a FastAPI-fastkit project.")
504+
if not is_fastkit_project(actual_project_dir):
505+
if project_dir == ".":
506+
print_error("Current directory is not a FastAPI-fastkit project.")
507+
else:
508+
print_error(f"'{project_dir}' is not a FastAPI-fastkit project.")
479509
return
480510

481511
# Validate route name
@@ -499,26 +529,34 @@ def addroute(ctx: Context, project_name: str, route_name: str) -> None:
499529
{
500530
"Project": project_name,
501531
"Route Name": route_name,
502-
"Target Directory": project_dir,
532+
"Target Directory": actual_project_dir,
503533
},
504534
)
505535
console.print(table)
506536

507-
# Confirm before proceeding
508-
confirm = click.confirm(
509-
f"\nDo you want to add route '{route_name}' to project '{project_name}'?",
510-
default=True,
511-
)
537+
if project_dir == ".":
538+
confirm_message = (
539+
f"\nDo you want to add route '{route_name}' to the current project?"
540+
)
541+
else:
542+
confirm_message = f"\nDo you want to add route '{route_name}' to project '{project_name}'?"
543+
544+
confirm = click.confirm(confirm_message, default=True)
512545
if not confirm:
513546
print_error("Operation cancelled!")
514547
return
515548

516549
# Add the new route
517-
add_new_route(project_dir, route_name)
550+
add_new_route(actual_project_dir, route_name)
518551

519-
print_success(
520-
f"Successfully added new route '{route_name}' to project `{project_name}`"
521-
)
552+
if project_dir == ".":
553+
print_success(
554+
f"Successfully added new route '{route_name}' to the current project!"
555+
)
556+
else:
557+
print_success(
558+
f"Successfully added new route '{route_name}' to project '{project_name}'!"
559+
)
522560

523561
except Exception as e:
524562
logger = get_logger()

src/fastapi_fastkit/fastapi_project_template/fastapi-empty/requirements.txt-tpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ httpx==0.28.1
77
black==25.1.0
88
isort==6.0.0
99
mypy==1.15.0
10+
setuptools==80.9.0

0 commit comments

Comments
 (0)