kiro-cli 1.0.0__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.
- kiro_cli-1.0.0/LICENSE +23 -0
- kiro_cli-1.0.0/PKG-INFO +83 -0
- kiro_cli-1.0.0/README.md +70 -0
- kiro_cli-1.0.0/kiro/__init__.py +0 -0
- kiro_cli-1.0.0/kiro/cli.py +62 -0
- kiro_cli-1.0.0/kiro/constants.py +0 -0
- kiro_cli-1.0.0/kiro/database.py +23 -0
- kiro_cli-1.0.0/kiro/generators.py +48 -0
- kiro_cli-1.0.0/kiro/installers.py +79 -0
- kiro_cli-1.0.0/kiro/main.py +7 -0
- kiro_cli-1.0.0/kiro/orm.py +99 -0
- kiro_cli-1.0.0/kiro/packages.py +155 -0
- kiro_cli-1.0.0/kiro/prompts.py +122 -0
- kiro_cli-1.0.0/kiro/state.py +12 -0
- kiro_cli-1.0.0/kiro/templates/python/fastapi/app/main.py +7 -0
- kiro_cli-1.0.0/kiro/templates/python/flask/app.py +10 -0
- kiro_cli-1.0.0/kiro/ui.py +10 -0
- kiro_cli-1.0.0/kiro/utils/files.py +24 -0
- kiro_cli-1.0.0/kiro/utils/logger.py +0 -0
- kiro_cli-1.0.0/kiro/utils/shell.py +0 -0
- kiro_cli-1.0.0/kiro_cli.egg-info/PKG-INFO +83 -0
- kiro_cli-1.0.0/kiro_cli.egg-info/SOURCES.txt +26 -0
- kiro_cli-1.0.0/kiro_cli.egg-info/dependency_links.txt +1 -0
- kiro_cli-1.0.0/kiro_cli.egg-info/entry_points.txt +2 -0
- kiro_cli-1.0.0/kiro_cli.egg-info/requires.txt +3 -0
- kiro_cli-1.0.0/kiro_cli.egg-info/top_level.txt +1 -0
- kiro_cli-1.0.0/pyproject.toml +22 -0
- kiro_cli-1.0.0/setup.cfg +4 -0
kiro_cli-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
---
|
|
3
|
+
|
|
4
|
+
# π `LICENSE` (MIT License)
|
|
5
|
+
|
|
6
|
+
Create a file called `LICENSE`:
|
|
7
|
+
|
|
8
|
+
```txt
|
|
9
|
+
MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Jimoh Olamide Prince
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
kiro_cli-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kiro-cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A CLI scaffolding tool for backend projects
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: typer
|
|
10
|
+
Requires-Dist: questionary
|
|
11
|
+
Requires-Dist: rich
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# β‘ Kiro
|
|
15
|
+
|
|
16
|
+
Kiro is a CLI scaffolding tool that helps developers quickly set up backend projects without wasting time on repetitive configuration.
|
|
17
|
+
|
|
18
|
+
Instead of manually setting up folders, dependencies, and boilerplate, Kiro guides you through an interactive setup and generates a ready-to-code project.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## π Features (current stage)
|
|
23
|
+
|
|
24
|
+
- Interactive CLI wizard
|
|
25
|
+
- Runtime selection (Node.js, Python)
|
|
26
|
+
- Framework selection based on runtime
|
|
27
|
+
- Project name prompt
|
|
28
|
+
- Automatic folder generation
|
|
29
|
+
- Basic starter files setup
|
|
30
|
+
- file config for node js(ts/js) and python
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## π¦ Installation (development)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install -r requirements.txt
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Follow the interactive prompts to generate a project.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## π Output Example
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
|
|
48
|
+
my-app/
|
|
49
|
+
βββ src/
|
|
50
|
+
β βββ main.py / index.js
|
|
51
|
+
β βββ routes/
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## π§ Roadmap
|
|
57
|
+
|
|
58
|
+
Template engine system
|
|
59
|
+
Dependency auto-installation
|
|
60
|
+
Git initialization support
|
|
61
|
+
Docker integration
|
|
62
|
+
Database setup wizard
|
|
63
|
+
Plugin-based architecture
|
|
64
|
+
Global CLI installation (npm/pipx-style experience)
|
|
65
|
+
Web landing page + documentation site
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## π§ Philosophy
|
|
69
|
+
|
|
70
|
+
Kiro is built around a simple idea:
|
|
71
|
+
|
|
72
|
+
βStop setting up. Start building.β
|
|
73
|
+
|
|
74
|
+
The focus is on reducing friction between idea and execution.
|
|
75
|
+
|
|
76
|
+
.
|
|
77
|
+
|
|
78
|
+
## π¨βπ» Author
|
|
79
|
+
|
|
80
|
+
Built by Jimoh Olamide Prince
|
|
81
|
+
|
|
82
|
+
## π License
|
|
83
|
+
MIT
|
kiro_cli-1.0.0/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# β‘ Kiro
|
|
2
|
+
|
|
3
|
+
Kiro is a CLI scaffolding tool that helps developers quickly set up backend projects without wasting time on repetitive configuration.
|
|
4
|
+
|
|
5
|
+
Instead of manually setting up folders, dependencies, and boilerplate, Kiro guides you through an interactive setup and generates a ready-to-code project.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## π Features (current stage)
|
|
10
|
+
|
|
11
|
+
- Interactive CLI wizard
|
|
12
|
+
- Runtime selection (Node.js, Python)
|
|
13
|
+
- Framework selection based on runtime
|
|
14
|
+
- Project name prompt
|
|
15
|
+
- Automatic folder generation
|
|
16
|
+
- Basic starter files setup
|
|
17
|
+
- file config for node js(ts/js) and python
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## π¦ Installation (development)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -r requirements.txt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Follow the interactive prompts to generate a project.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## π Output Example
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
|
|
35
|
+
my-app/
|
|
36
|
+
βββ src/
|
|
37
|
+
β βββ main.py / index.js
|
|
38
|
+
β βββ routes/
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## π§ Roadmap
|
|
44
|
+
|
|
45
|
+
Template engine system
|
|
46
|
+
Dependency auto-installation
|
|
47
|
+
Git initialization support
|
|
48
|
+
Docker integration
|
|
49
|
+
Database setup wizard
|
|
50
|
+
Plugin-based architecture
|
|
51
|
+
Global CLI installation (npm/pipx-style experience)
|
|
52
|
+
Web landing page + documentation site
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## π§ Philosophy
|
|
56
|
+
|
|
57
|
+
Kiro is built around a simple idea:
|
|
58
|
+
|
|
59
|
+
βStop setting up. Start building.β
|
|
60
|
+
|
|
61
|
+
The focus is on reducing friction between idea and execution.
|
|
62
|
+
|
|
63
|
+
.
|
|
64
|
+
|
|
65
|
+
## π¨βπ» Author
|
|
66
|
+
|
|
67
|
+
Built by Jimoh Olamide Prince
|
|
68
|
+
|
|
69
|
+
## π License
|
|
70
|
+
MIT
|
|
File without changes
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from kiro.prompts import (
|
|
2
|
+
select_runtime,
|
|
3
|
+
select_framework,
|
|
4
|
+
ask_project_name,
|
|
5
|
+
ask_language,
|
|
6
|
+
select_database,
|
|
7
|
+
select_orm
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from kiro.state import KiroState
|
|
11
|
+
from kiro.generators import create_project
|
|
12
|
+
from kiro.database import setup_database
|
|
13
|
+
from kiro.installers import install_dependencies
|
|
14
|
+
from kiro.ui import show_success
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_cli():
|
|
18
|
+
print("\nβ‘ Welcome to Kiro\n")
|
|
19
|
+
|
|
20
|
+
state = KiroState()
|
|
21
|
+
|
|
22
|
+
# Runtime
|
|
23
|
+
state.runtime = select_runtime()
|
|
24
|
+
print(f"\nβ Selected runtime: {state.runtime}")
|
|
25
|
+
|
|
26
|
+
# Language (Node.js only)
|
|
27
|
+
if state.runtime == "Node.js":
|
|
28
|
+
state.language = ask_language()
|
|
29
|
+
print(f"\nβ Language: {state.language}")
|
|
30
|
+
|
|
31
|
+
# Framework
|
|
32
|
+
state.framework = select_framework(state.runtime)
|
|
33
|
+
print(f"\nβ Selected framework: {state.framework}")
|
|
34
|
+
|
|
35
|
+
# Project name
|
|
36
|
+
state.project_name = ask_project_name()
|
|
37
|
+
print(f"\nβ Project name: {state.project_name}")
|
|
38
|
+
|
|
39
|
+
# Database
|
|
40
|
+
state.database = select_database()
|
|
41
|
+
print(f"\nβ Database: {state.database}")
|
|
42
|
+
|
|
43
|
+
# ORM (only if a database was selected)
|
|
44
|
+
state.orm = select_orm(
|
|
45
|
+
state.runtime,
|
|
46
|
+
state.database
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if state.orm:
|
|
50
|
+
print(f"\nβ ORM: {state.orm}")
|
|
51
|
+
|
|
52
|
+
# Generate project
|
|
53
|
+
create_project(state)
|
|
54
|
+
|
|
55
|
+
# Configure database
|
|
56
|
+
setup_database(state)
|
|
57
|
+
|
|
58
|
+
# Install dependencies
|
|
59
|
+
install_dependencies(state)
|
|
60
|
+
|
|
61
|
+
# Success message (always last)
|
|
62
|
+
show_success(state)
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
def setup_database(state):
|
|
4
|
+
if state.database == "None":
|
|
5
|
+
return
|
|
6
|
+
|
|
7
|
+
project = Path(state.project_name)
|
|
8
|
+
env = project / ".env"
|
|
9
|
+
|
|
10
|
+
database_urls = {
|
|
11
|
+
"PostgreSQL": "postgresql://username:password@localhost:5432/mydb",
|
|
12
|
+
"MySQL": "mysql://root:password@localhost:3306/mydb",
|
|
13
|
+
"SQLite": "file:./database.db",
|
|
14
|
+
"MongoDB": "mongodb://localhost:27017/mydb",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
database_url = database_urls.get(state.database)
|
|
18
|
+
|
|
19
|
+
if database_url:
|
|
20
|
+
with env.open("a") as f:
|
|
21
|
+
f.write(f"DATABASE_URL={database_url}\n")
|
|
22
|
+
|
|
23
|
+
print(f"π Setting up {state.database}...")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Creates files/folders
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import shutil
|
|
5
|
+
from kiro.utils.files import replace_placeholders
|
|
6
|
+
from kiro.ui import show_success
|
|
7
|
+
from kiro.installers import install_dependencies
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def create_project(state):
|
|
12
|
+
base_path = Path(state.project_name)
|
|
13
|
+
base_path.mkdir(exist_ok=True)
|
|
14
|
+
|
|
15
|
+
template_path = get_template_path(state)
|
|
16
|
+
|
|
17
|
+
if template_path and template_path.exists():
|
|
18
|
+
shutil.copytree(
|
|
19
|
+
template_path,
|
|
20
|
+
base_path,
|
|
21
|
+
dirs_exist_ok=True
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
replace_placeholders(base_path, state)
|
|
25
|
+
|
|
26
|
+
show_success(state)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_template_path(state):
|
|
31
|
+
base = Path("kiro") / "templates"
|
|
32
|
+
|
|
33
|
+
if state.runtime == "Node.js":
|
|
34
|
+
framework = state.framework.lower()
|
|
35
|
+
|
|
36
|
+
language = state.language.lower() # javascript / typescript
|
|
37
|
+
|
|
38
|
+
return base / "node" / framework / language
|
|
39
|
+
|
|
40
|
+
if state.runtime == "Python":
|
|
41
|
+
framework = state.framework.lower()
|
|
42
|
+
return base / "python" / framework
|
|
43
|
+
|
|
44
|
+
if state.runtime == "Go":
|
|
45
|
+
framework = state.framework.lower()
|
|
46
|
+
return base / "go" / framework
|
|
47
|
+
|
|
48
|
+
return None
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Install dependencies for generated Kiro projects."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from kiro.packages import get_packages
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def install_dependencies(state):
|
|
12
|
+
"""Install the dependencies implied by the user's project selections."""
|
|
13
|
+
project = Path(state.project_name).resolve()
|
|
14
|
+
|
|
15
|
+
if not project.is_dir():
|
|
16
|
+
raise FileNotFoundError(f"Generated project directory was not found: {project}")
|
|
17
|
+
|
|
18
|
+
packages, dev_packages = get_packages(state)
|
|
19
|
+
|
|
20
|
+
if state.runtime == "Node.js":
|
|
21
|
+
_install_node_dependencies(project, packages, dev_packages)
|
|
22
|
+
elif state.runtime == "Python":
|
|
23
|
+
_install_python_dependencies(project, packages)
|
|
24
|
+
elif state.runtime == "Go":
|
|
25
|
+
_install_go_dependencies(project, packages)
|
|
26
|
+
else:
|
|
27
|
+
raise ValueError(f"Unsupported runtime: {state.runtime}")
|
|
28
|
+
|
|
29
|
+
print("Dependencies installed successfully.")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _require_command(name: str) -> str:
|
|
33
|
+
command = shutil.which(name)
|
|
34
|
+
if not command:
|
|
35
|
+
raise RuntimeError(f"{name} was not found on PATH. Install it and try again.")
|
|
36
|
+
return command
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _install_node_dependencies(project: Path, packages: list[str], dev_packages: list[str]):
|
|
40
|
+
npm = _require_command("npm")
|
|
41
|
+
|
|
42
|
+
# Install dependencies declared by the copied template first.
|
|
43
|
+
subprocess.run([npm, "install"], cwd=project, check=True)
|
|
44
|
+
|
|
45
|
+
if packages:
|
|
46
|
+
subprocess.run([npm, "install", *packages], cwd=project, check=True)
|
|
47
|
+
if dev_packages:
|
|
48
|
+
subprocess.run([npm, "install", "--save-dev", *dev_packages], cwd=project, check=True)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _install_python_dependencies(project: Path, packages: list[str]):
|
|
52
|
+
pip = _create_python_venv(project)
|
|
53
|
+
requirements = project / "requirements.txt"
|
|
54
|
+
|
|
55
|
+
if requirements.is_file():
|
|
56
|
+
subprocess.run([str(pip), "install", "-r", str(requirements)], cwd=project, check=True)
|
|
57
|
+
if packages:
|
|
58
|
+
subprocess.run([str(pip), "install", *packages], cwd=project, check=True)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _create_python_venv(project: Path) -> Path:
|
|
62
|
+
if sys.platform == "win32":
|
|
63
|
+
pip = project / ".venv" / "Scripts" / "pip.exe"
|
|
64
|
+
else:
|
|
65
|
+
pip = project / ".venv" / "bin" / "pip"
|
|
66
|
+
|
|
67
|
+
if not pip.is_file():
|
|
68
|
+
print("Creating virtual environment...")
|
|
69
|
+
subprocess.run([sys.executable, "-m", "venv", ".venv"], cwd=project, check=True)
|
|
70
|
+
|
|
71
|
+
return pip
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _install_go_dependencies(project: Path, packages: list[str]):
|
|
75
|
+
go = _require_command("go")
|
|
76
|
+
|
|
77
|
+
for package in packages:
|
|
78
|
+
subprocess.run([go, "get", package], cwd=project, check=True)
|
|
79
|
+
subprocess.run([go, "mod", "tidy"], cwd=project, check=True)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
def setup_orm(state):
|
|
4
|
+
if state.orm is None:
|
|
5
|
+
return
|
|
6
|
+
|
|
7
|
+
project = Path(state.project_name)
|
|
8
|
+
|
|
9
|
+
if state.runtime == "Node.js":
|
|
10
|
+
setup_node_orm(state, project)
|
|
11
|
+
|
|
12
|
+
elif state.runtime == "Python":
|
|
13
|
+
setup_python_orm(state, project)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def setup_node_orm(state, project):
|
|
17
|
+
|
|
18
|
+
orm = state.orm.lower()
|
|
19
|
+
|
|
20
|
+
if orm == "prisma":
|
|
21
|
+
setup_prisma(project)
|
|
22
|
+
|
|
23
|
+
elif orm == "drizzle":
|
|
24
|
+
setup_drizzle(project)
|
|
25
|
+
|
|
26
|
+
elif orm == "typeorm":
|
|
27
|
+
setup_typeorm(project)
|
|
28
|
+
|
|
29
|
+
elif orm == "mongoose":
|
|
30
|
+
setup_mongoose(project)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def setup_drizzle(project):
|
|
34
|
+
|
|
35
|
+
db = project / "src" / "db"
|
|
36
|
+
|
|
37
|
+
db.mkdir(parents=True, exist_ok=True)
|
|
38
|
+
|
|
39
|
+
(db / "index.ts").write_text(
|
|
40
|
+
"""export * from "./schema";
|
|
41
|
+
"""
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
(db / "schema.ts").write_text(
|
|
45
|
+
"""// Your Drizzle schema goes here
|
|
46
|
+
"""
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def setup_prisma(project):
|
|
51
|
+
|
|
52
|
+
prisma = project / "prisma"
|
|
53
|
+
|
|
54
|
+
prisma.mkdir(exist_ok=True)
|
|
55
|
+
|
|
56
|
+
(prisma / "schema.prisma").write_text(
|
|
57
|
+
"""generator client {
|
|
58
|
+
provider = "prisma-client-js"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
datasource db {
|
|
62
|
+
provider = "sqlite"
|
|
63
|
+
url = env("DATABASE_URL")
|
|
64
|
+
}
|
|
65
|
+
"""
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def setup_typeorm(project):
|
|
70
|
+
|
|
71
|
+
entities = project / "src" / "entities"
|
|
72
|
+
|
|
73
|
+
entities.mkdir(parents=True, exist_ok=True)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def setup_mongoose(project):
|
|
77
|
+
|
|
78
|
+
models = project / "src" / "models"
|
|
79
|
+
|
|
80
|
+
models.mkdir(parents=True, exist_ok=True)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def setup_python_orm(state, project):
|
|
84
|
+
|
|
85
|
+
if state.orm == "SQLAlchemy":
|
|
86
|
+
|
|
87
|
+
db = project / "app" / "db"
|
|
88
|
+
|
|
89
|
+
db.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
|
|
91
|
+
(db / "__init__.py").touch()
|
|
92
|
+
|
|
93
|
+
elif state.orm == "Tortoise ORM":
|
|
94
|
+
|
|
95
|
+
db = project / "app" / "db"
|
|
96
|
+
|
|
97
|
+
db.mkdir(parents=True, exist_ok=True)
|
|
98
|
+
|
|
99
|
+
(db / "__init__.py").touch()
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
def get_packages(state):
|
|
2
|
+
|
|
3
|
+
packages = []
|
|
4
|
+
dev_packages = []
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# ======================
|
|
8
|
+
# NODE.JS
|
|
9
|
+
# ======================
|
|
10
|
+
|
|
11
|
+
if state.runtime == "Node.js":
|
|
12
|
+
|
|
13
|
+
# Framework
|
|
14
|
+
if state.framework == "Express":
|
|
15
|
+
packages += [
|
|
16
|
+
"express",
|
|
17
|
+
"dotenv",
|
|
18
|
+
"cors"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
elif state.framework == "Fastify":
|
|
22
|
+
packages += [
|
|
23
|
+
"fastify",
|
|
24
|
+
"dotenv",
|
|
25
|
+
"@fastify/cors"
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
elif state.framework == "Nest":
|
|
29
|
+
packages += [
|
|
30
|
+
"@nestjs/core",
|
|
31
|
+
"@nestjs/common",
|
|
32
|
+
"@nestjs/platform-express"
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Language
|
|
37
|
+
if getattr(state, "language", None) == "TypeScript":
|
|
38
|
+
dev_packages += [
|
|
39
|
+
"typescript",
|
|
40
|
+
"ts-node-dev",
|
|
41
|
+
"@types/node"
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Database
|
|
46
|
+
if state.database == "PostgreSQL":
|
|
47
|
+
packages.append("pg")
|
|
48
|
+
|
|
49
|
+
elif state.database == "MySQL":
|
|
50
|
+
packages.append("mysql2")
|
|
51
|
+
|
|
52
|
+
elif state.database == "MongoDB":
|
|
53
|
+
packages.append("mongodb")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ORM
|
|
57
|
+
if state.orm == "Prisma":
|
|
58
|
+
packages.append("prisma")
|
|
59
|
+
|
|
60
|
+
elif state.orm == "Drizzle":
|
|
61
|
+
packages.append("drizzle-orm")
|
|
62
|
+
dev_packages.append("drizzle-kit")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ======================
|
|
66
|
+
# PYTHON
|
|
67
|
+
# ======================
|
|
68
|
+
|
|
69
|
+
elif state.runtime == "Python":
|
|
70
|
+
|
|
71
|
+
# Framework
|
|
72
|
+
if state.framework == "FastAPI":
|
|
73
|
+
packages += [
|
|
74
|
+
"fastapi",
|
|
75
|
+
"uvicorn"
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
elif state.framework == "Flask":
|
|
79
|
+
packages.append(
|
|
80
|
+
"flask"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Database
|
|
85
|
+
if state.database == "PostgreSQL":
|
|
86
|
+
packages.append(
|
|
87
|
+
"psycopg2-binary"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
elif state.database == "MySQL":
|
|
91
|
+
packages.append(
|
|
92
|
+
"mysql-connector-python"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
elif state.database == "MongoDB":
|
|
96
|
+
packages.append(
|
|
97
|
+
"pymongo"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
elif state.database == "SQLite":
|
|
101
|
+
packages.append(
|
|
102
|
+
"sqlalchemy"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# ORM
|
|
107
|
+
if state.orm == "SQLAlchemy":
|
|
108
|
+
packages.append(
|
|
109
|
+
"sqlalchemy"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
elif state.orm == "MongoEngine":
|
|
113
|
+
packages.append(
|
|
114
|
+
"mongoengine"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
elif state.orm == "Peewee":
|
|
118
|
+
packages.append(
|
|
119
|
+
"peewee"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ======================
|
|
124
|
+
# GO
|
|
125
|
+
# ======================
|
|
126
|
+
|
|
127
|
+
elif state.runtime == "Go":
|
|
128
|
+
|
|
129
|
+
# Go dependencies are handled by go.mod
|
|
130
|
+
# and go mod tidy
|
|
131
|
+
|
|
132
|
+
if state.framework == "Gin":
|
|
133
|
+
packages.append(
|
|
134
|
+
"github.com/gin-gonic/gin"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if state.database == "PostgreSQL":
|
|
139
|
+
packages.append(
|
|
140
|
+
"github.com/lib/pq"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
elif state.database == "MongoDB":
|
|
144
|
+
packages.append(
|
|
145
|
+
"go.mongodb.org/mongo-driver/mongo"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if state.orm == "GORM":
|
|
150
|
+
packages.append(
|
|
151
|
+
"gorm.io/gorm"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
return packages, dev_packages
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Questionary prompts
|
|
2
|
+
import questionary
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
def confirm_install_dependencies():
|
|
6
|
+
return typer.confirm(
|
|
7
|
+
"Install dependencies?",
|
|
8
|
+
default=True
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def confirm_git_init():
|
|
13
|
+
return typer.confirm(
|
|
14
|
+
"Initialize Git repository?",
|
|
15
|
+
default=True
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def select_runtime():
|
|
19
|
+
return questionary.select(
|
|
20
|
+
"Which runtime do you want to use?",
|
|
21
|
+
choices=[
|
|
22
|
+
"Node.js",
|
|
23
|
+
"Python",
|
|
24
|
+
"Go"
|
|
25
|
+
]
|
|
26
|
+
).ask()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def select_framework(runtime: str):
|
|
30
|
+
if runtime == "Node.js":
|
|
31
|
+
choices = ["Express", "Fastify", "NestJS"]
|
|
32
|
+
elif runtime == "Python":
|
|
33
|
+
choices = ["FastAPI", "Flask", "Django"]
|
|
34
|
+
else:
|
|
35
|
+
choices = ["None"]
|
|
36
|
+
|
|
37
|
+
return questionary.select(
|
|
38
|
+
"Choose a framework",
|
|
39
|
+
choices=choices,
|
|
40
|
+
).ask()
|
|
41
|
+
|
|
42
|
+
def ask_project_name():
|
|
43
|
+
return questionary.text(
|
|
44
|
+
"project name?",
|
|
45
|
+
validate=lambda text: len(text.strip()) > 0 or "Project name cannot be empty"
|
|
46
|
+
).ask()
|
|
47
|
+
|
|
48
|
+
def ask_language():
|
|
49
|
+
return questionary.select(
|
|
50
|
+
"Choose language",
|
|
51
|
+
choices=[
|
|
52
|
+
"JavaScript",
|
|
53
|
+
"TypeScript"
|
|
54
|
+
]
|
|
55
|
+
).ask()
|
|
56
|
+
|
|
57
|
+
return choice
|
|
58
|
+
|
|
59
|
+
def select_database():
|
|
60
|
+
return questionary.select(
|
|
61
|
+
"Select database",
|
|
62
|
+
choices=[
|
|
63
|
+
"PostgreSQL",
|
|
64
|
+
"MySQL",
|
|
65
|
+
"SQLite",
|
|
66
|
+
"MongoDB",
|
|
67
|
+
"None",
|
|
68
|
+
]
|
|
69
|
+
).ask()
|
|
70
|
+
return choice
|
|
71
|
+
|
|
72
|
+
import questionary
|
|
73
|
+
|
|
74
|
+
def select_orm(runtime, database):
|
|
75
|
+
choices = []
|
|
76
|
+
|
|
77
|
+
if runtime == "Node.js":
|
|
78
|
+
if database == "MongoDB":
|
|
79
|
+
choices = [
|
|
80
|
+
"Mongoose",
|
|
81
|
+
"None"
|
|
82
|
+
]
|
|
83
|
+
elif database != "None":
|
|
84
|
+
choices = [
|
|
85
|
+
"Prisma",
|
|
86
|
+
"Drizzle",
|
|
87
|
+
"TypeORM",
|
|
88
|
+
"None"
|
|
89
|
+
]
|
|
90
|
+
else:
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
elif runtime == "Python":
|
|
94
|
+
if database == "MongoDB":
|
|
95
|
+
choices = [
|
|
96
|
+
"MongoEngine",
|
|
97
|
+
"Beanie",
|
|
98
|
+
"None"
|
|
99
|
+
]
|
|
100
|
+
elif database != "None":
|
|
101
|
+
choices = [
|
|
102
|
+
"SQLAlchemy",
|
|
103
|
+
"Tortoise ORM",
|
|
104
|
+
"None"
|
|
105
|
+
]
|
|
106
|
+
else:
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
elif runtime == "Go":
|
|
110
|
+
if database != "None":
|
|
111
|
+
choices = [
|
|
112
|
+
"GORM",
|
|
113
|
+
"sqlx",
|
|
114
|
+
"None"
|
|
115
|
+
]
|
|
116
|
+
else:
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
return questionary.select(
|
|
120
|
+
"Choose ORM",
|
|
121
|
+
choices=choices
|
|
122
|
+
).ask()
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
def show_success(state):
|
|
2
|
+
print("\n⨠Project created successfully!\n")
|
|
3
|
+
print(f"π¦ Project : {state.project_name}")
|
|
4
|
+
print(f"β Runtime : {state.runtime}")
|
|
5
|
+
print(f"π Framework : {state.framework}")
|
|
6
|
+
|
|
7
|
+
if state.language:
|
|
8
|
+
print(f"π» Language : {state.language}")
|
|
9
|
+
|
|
10
|
+
print(f"π Location : ./{state.project_name}\n")
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#for every file read file replace placeholders write file
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
def replace_placeholders(project_path, state):
|
|
5
|
+
placeholders = {
|
|
6
|
+
"{{project_name}}": state.project_name,
|
|
7
|
+
"{{runtime}}": state.runtime,
|
|
8
|
+
"{{framework}}": state.framework,
|
|
9
|
+
"{{language}}": state.language or "",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
for file in Path(project_path).rglob("*"):
|
|
13
|
+
if file.is_file():
|
|
14
|
+
try:
|
|
15
|
+
content = file.read_text(encoding="utf-8")
|
|
16
|
+
|
|
17
|
+
for placeholder, value in placeholders.items():
|
|
18
|
+
content = content.replace(placeholder, value)
|
|
19
|
+
|
|
20
|
+
file.write_text(content, encoding = "utf-8")
|
|
21
|
+
|
|
22
|
+
except UnicodeDecodeError:
|
|
23
|
+
|
|
24
|
+
continue
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kiro-cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A CLI scaffolding tool for backend projects
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: typer
|
|
10
|
+
Requires-Dist: questionary
|
|
11
|
+
Requires-Dist: rich
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# β‘ Kiro
|
|
15
|
+
|
|
16
|
+
Kiro is a CLI scaffolding tool that helps developers quickly set up backend projects without wasting time on repetitive configuration.
|
|
17
|
+
|
|
18
|
+
Instead of manually setting up folders, dependencies, and boilerplate, Kiro guides you through an interactive setup and generates a ready-to-code project.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## π Features (current stage)
|
|
23
|
+
|
|
24
|
+
- Interactive CLI wizard
|
|
25
|
+
- Runtime selection (Node.js, Python)
|
|
26
|
+
- Framework selection based on runtime
|
|
27
|
+
- Project name prompt
|
|
28
|
+
- Automatic folder generation
|
|
29
|
+
- Basic starter files setup
|
|
30
|
+
- file config for node js(ts/js) and python
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## π¦ Installation (development)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install -r requirements.txt
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Follow the interactive prompts to generate a project.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## π Output Example
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
|
|
48
|
+
my-app/
|
|
49
|
+
βββ src/
|
|
50
|
+
β βββ main.py / index.js
|
|
51
|
+
β βββ routes/
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## π§ Roadmap
|
|
57
|
+
|
|
58
|
+
Template engine system
|
|
59
|
+
Dependency auto-installation
|
|
60
|
+
Git initialization support
|
|
61
|
+
Docker integration
|
|
62
|
+
Database setup wizard
|
|
63
|
+
Plugin-based architecture
|
|
64
|
+
Global CLI installation (npm/pipx-style experience)
|
|
65
|
+
Web landing page + documentation site
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## π§ Philosophy
|
|
69
|
+
|
|
70
|
+
Kiro is built around a simple idea:
|
|
71
|
+
|
|
72
|
+
βStop setting up. Start building.β
|
|
73
|
+
|
|
74
|
+
The focus is on reducing friction between idea and execution.
|
|
75
|
+
|
|
76
|
+
.
|
|
77
|
+
|
|
78
|
+
## π¨βπ» Author
|
|
79
|
+
|
|
80
|
+
Built by Jimoh Olamide Prince
|
|
81
|
+
|
|
82
|
+
## π License
|
|
83
|
+
MIT
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
kiro/__init__.py
|
|
5
|
+
kiro/cli.py
|
|
6
|
+
kiro/constants.py
|
|
7
|
+
kiro/database.py
|
|
8
|
+
kiro/generators.py
|
|
9
|
+
kiro/installers.py
|
|
10
|
+
kiro/main.py
|
|
11
|
+
kiro/orm.py
|
|
12
|
+
kiro/packages.py
|
|
13
|
+
kiro/prompts.py
|
|
14
|
+
kiro/state.py
|
|
15
|
+
kiro/ui.py
|
|
16
|
+
kiro/templates/python/fastapi/app/main.py
|
|
17
|
+
kiro/templates/python/flask/app.py
|
|
18
|
+
kiro/utils/files.py
|
|
19
|
+
kiro/utils/logger.py
|
|
20
|
+
kiro/utils/shell.py
|
|
21
|
+
kiro_cli.egg-info/PKG-INFO
|
|
22
|
+
kiro_cli.egg-info/SOURCES.txt
|
|
23
|
+
kiro_cli.egg-info/dependency_links.txt
|
|
24
|
+
kiro_cli.egg-info/entry_points.txt
|
|
25
|
+
kiro_cli.egg-info/requires.txt
|
|
26
|
+
kiro_cli.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
kiro
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "kiro-cli"
|
|
8
|
+
version = "1.0.0"
|
|
9
|
+
description = "A CLI scaffolding tool for backend projects"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
license = {text = "MIT"}
|
|
13
|
+
|
|
14
|
+
dependencies = [
|
|
15
|
+
"typer",
|
|
16
|
+
"questionary",
|
|
17
|
+
"rich"
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
[project.scripts]
|
|
22
|
+
kiro = "kiro.main:app"
|
kiro_cli-1.0.0/setup.cfg
ADDED