jemo-admin 0.1.4__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.
- jemo_admin-0.1.4/.github/workflows/release.yml +52 -0
- jemo_admin-0.1.4/.github/workflows/store.yml +28 -0
- jemo_admin-0.1.4/.gitignore +1 -0
- jemo_admin-0.1.4/.python-version +1 -0
- jemo_admin-0.1.4/PKG-INFO +61 -0
- jemo_admin-0.1.4/README.md +48 -0
- jemo_admin-0.1.4/build/lib/jemo_admin/generators/backend.py +163 -0
- jemo_admin-0.1.4/build/lib/jemo_admin/generators/frontend.py +186 -0
- jemo_admin-0.1.4/build/lib/jemo_admin/generators/vcs.py +42 -0
- jemo_admin-0.1.4/build/lib/jemo_admin/main.py +194 -0
- jemo_admin-0.1.4/main.py +6 -0
- jemo_admin-0.1.4/pyproject.toml +26 -0
- jemo_admin-0.1.4/release.sh +48 -0
- jemo_admin-0.1.4/src/create_jemo_app.egg-info/PKG-INFO +57 -0
- jemo_admin-0.1.4/src/create_jemo_app.egg-info/SOURCES.txt +12 -0
- jemo_admin-0.1.4/src/create_jemo_app.egg-info/dependency_links.txt +1 -0
- jemo_admin-0.1.4/src/create_jemo_app.egg-info/entry_points.txt +2 -0
- jemo_admin-0.1.4/src/create_jemo_app.egg-info/requires.txt +3 -0
- jemo_admin-0.1.4/src/create_jemo_app.egg-info/top_level.txt +1 -0
- jemo_admin-0.1.4/src/jemo_admin/generators/backend.py +163 -0
- jemo_admin-0.1.4/src/jemo_admin/generators/frontend.py +186 -0
- jemo_admin-0.1.4/src/jemo_admin/generators/vcs.py +42 -0
- jemo_admin-0.1.4/src/jemo_admin/main.py +194 -0
- jemo_admin-0.1.4/uv.lock +150 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
id-token: write # Required for trusted publishing
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release:
|
|
14
|
+
name: Create Release
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment:
|
|
17
|
+
name: pypi
|
|
18
|
+
url: https://pypi.org/p/jemo-admin
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout code
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v5
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
run: uv python install
|
|
31
|
+
|
|
32
|
+
- name: Build package
|
|
33
|
+
run: uv build
|
|
34
|
+
|
|
35
|
+
- name: Publish to PyPI
|
|
36
|
+
run: uv publish
|
|
37
|
+
|
|
38
|
+
- name: Get version from tag
|
|
39
|
+
id: get_version
|
|
40
|
+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
41
|
+
|
|
42
|
+
- name: Create GitHub Release
|
|
43
|
+
uses: softprops/action-gh-release@v1
|
|
44
|
+
with:
|
|
45
|
+
name: Release ${{ steps.get_version.outputs.VERSION }}
|
|
46
|
+
draft: false
|
|
47
|
+
prerelease: false
|
|
48
|
+
files: |
|
|
49
|
+
dist/*.whl
|
|
50
|
+
dist/*.tar.gz
|
|
51
|
+
env:
|
|
52
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name : put on pypi
|
|
2
|
+
on :
|
|
3
|
+
push :
|
|
4
|
+
branches :
|
|
5
|
+
- main
|
|
6
|
+
jobs:
|
|
7
|
+
publish:
|
|
8
|
+
name: Build and publish to PyPI
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
# Required for Trusted Publishing
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
run: uv python install
|
|
23
|
+
|
|
24
|
+
- name: Build package
|
|
25
|
+
run: uv build
|
|
26
|
+
|
|
27
|
+
- name: Publish package
|
|
28
|
+
run: uv publish --token ${{ secrets.PYPI_TOKEN }}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.env
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jemo-admin
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: A CLI tool to scaffold modern web projects with FastAPI, Django, Convex, Next.js, SvelteKit, or TanStack Start.
|
|
5
|
+
Project-URL: Homepage, https://github.com/jemo/jemo-admin
|
|
6
|
+
Project-URL: Repository, https://github.com/jemo/jemo-admin
|
|
7
|
+
Project-URL: Issues, https://github.com/jemo/jemo-admin/issues
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: questionary>=2.1.1
|
|
10
|
+
Requires-Dist: rich>=14.3.2
|
|
11
|
+
Requires-Dist: typer>=0.23.0
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Jemo Admin CLI
|
|
15
|
+
|
|
16
|
+
A powerful CLI tool to scaffold modern web projects with your favorite stack.
|
|
17
|
+
|
|
18
|
+
## Supported Stacks
|
|
19
|
+
|
|
20
|
+
**Backend:**
|
|
21
|
+
- **FastAPI** (with Tortoise ORM & Aerich)
|
|
22
|
+
- **Django**
|
|
23
|
+
- **Convex** (Serverless)
|
|
24
|
+
|
|
25
|
+
**Frontend:**
|
|
26
|
+
- **Next.js**
|
|
27
|
+
- **SvelteKit**
|
|
28
|
+
- **TanStack Start**
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
You can install `jemo-admin` using `pipx`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pipx install .
|
|
36
|
+
# Or from a git repo:
|
|
37
|
+
# pipx install git+https://github.com/Jemo69/create-jemo-app.git
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
Create a new project interactively:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
jemo-admin create
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or specify the project name directly:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
jemo-admin create my-awesome-app
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Follow the interactive prompts to select your backend and frontend framework.
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- **Python 3.12+**
|
|
59
|
+
- **Bun** (for frontend package management)
|
|
60
|
+
- **UV** (for Python package management)
|
|
61
|
+
Note : it does not work on Windows.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Jemo Admin CLI
|
|
2
|
+
|
|
3
|
+
A powerful CLI tool to scaffold modern web projects with your favorite stack.
|
|
4
|
+
|
|
5
|
+
## Supported Stacks
|
|
6
|
+
|
|
7
|
+
**Backend:**
|
|
8
|
+
- **FastAPI** (with Tortoise ORM & Aerich)
|
|
9
|
+
- **Django**
|
|
10
|
+
- **Convex** (Serverless)
|
|
11
|
+
|
|
12
|
+
**Frontend:**
|
|
13
|
+
- **Next.js**
|
|
14
|
+
- **SvelteKit**
|
|
15
|
+
- **TanStack Start**
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
You can install `jemo-admin` using `pipx`:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pipx install .
|
|
23
|
+
# Or from a git repo:
|
|
24
|
+
# pipx install git+https://github.com/Jemo69/create-jemo-app.git
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Create a new project interactively:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
jemo-admin create
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or specify the project name directly:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
jemo-admin create my-awesome-app
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Follow the interactive prompts to select your backend and frontend framework.
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
- **Python 3.12+**
|
|
46
|
+
- **Bun** (for frontend package management)
|
|
47
|
+
- **UV** (for Python package management)
|
|
48
|
+
Note : it does not work on Windows.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import subprocess
|
|
3
|
+
import shutil
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
console = Console()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run_command(command, cwd=None, shell=False):
|
|
10
|
+
"""Run a shell command."""
|
|
11
|
+
try:
|
|
12
|
+
# Capture output to show on error
|
|
13
|
+
subprocess.run(command, cwd=cwd, shell=shell, check=True, capture_output=False)
|
|
14
|
+
except subprocess.CalledProcessError as e:
|
|
15
|
+
console.print(f"[red]Error executing command: {command}[/red]")
|
|
16
|
+
console.print(f"[red]Exit Code: {e.returncode}[/red]")
|
|
17
|
+
if e.stdout:
|
|
18
|
+
console.print(f"[red]Stdout: {e.stdout.decode()}[/red]")
|
|
19
|
+
if e.stderr:
|
|
20
|
+
console.print(f"[red]Stderr: {e.stderr.decode()}[/red]")
|
|
21
|
+
raise e
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def create_fastapi(project_dir: Path, separate_folders: bool = True):
|
|
25
|
+
"""Scaffold a FastAPI project with Tortoise ORM and Aerich."""
|
|
26
|
+
|
|
27
|
+
backend_dir = project_dir / "backend"
|
|
28
|
+
if separate_folders:
|
|
29
|
+
backend_dir.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
else:
|
|
31
|
+
backend_dir = project_dir # If not separate folders, use project dir directly (uncommon for backend+frontend combo)
|
|
32
|
+
|
|
33
|
+
console.print(
|
|
34
|
+
f"[bold cyan]Initializing FastAPI backend in {backend_dir}...[/bold cyan]"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Initialize UV project
|
|
38
|
+
# Use --no-workspace to ensure we create a standalone project
|
|
39
|
+
run_command(["uv", "init", "--app", "--no-workspace"], cwd=backend_dir)
|
|
40
|
+
|
|
41
|
+
# Add dependencies
|
|
42
|
+
console.print(
|
|
43
|
+
"[bold]Adding dependencies: fastapi, uvicorn, tortoise-orm, aerich...[/bold]"
|
|
44
|
+
)
|
|
45
|
+
run_command(
|
|
46
|
+
["uv", "add", "fastapi", "uvicorn", "tortoise-orm", "aerich"], cwd=backend_dir
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Create main.py
|
|
50
|
+
main_py_content = """
|
|
51
|
+
from fastapi import FastAPI
|
|
52
|
+
from tortoise import Tortoise
|
|
53
|
+
from tortoise.contrib.fastapi import register_tortoise
|
|
54
|
+
|
|
55
|
+
app = FastAPI(title="Jemo Admin API")
|
|
56
|
+
|
|
57
|
+
@app.get("/")
|
|
58
|
+
async def read_root():
|
|
59
|
+
return {"message": "Welcome to Jemo Admin FastAPI Backend with Tortoise ORM!"}
|
|
60
|
+
|
|
61
|
+
# Database Configuration
|
|
62
|
+
TORTOISE_ORM = {
|
|
63
|
+
"connections": {"default": "sqlite://db.sqlite3"},
|
|
64
|
+
"apps": {
|
|
65
|
+
"models": {
|
|
66
|
+
"models": ["aerich.models", "models"], # Add your models here
|
|
67
|
+
"default_connection": "default",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
register_tortoise(
|
|
73
|
+
app,
|
|
74
|
+
config=TORTOISE_ORM,
|
|
75
|
+
generate_schemas=True,
|
|
76
|
+
add_exception_handlers=True,
|
|
77
|
+
)
|
|
78
|
+
"""
|
|
79
|
+
(backend_dir / "main.py").write_text(main_py_content)
|
|
80
|
+
|
|
81
|
+
# Create models.py
|
|
82
|
+
models_py_content = """
|
|
83
|
+
from tortoise import fields, models
|
|
84
|
+
|
|
85
|
+
class User(models.Model):
|
|
86
|
+
id = fields.IntField(pk=True)
|
|
87
|
+
username = fields.CharField(max_length=50, unique=True)
|
|
88
|
+
email = fields.CharField(max_length=255, unique=True)
|
|
89
|
+
created_at = fields.DatetimeField(auto_now_add=True)
|
|
90
|
+
|
|
91
|
+
def __str__(self):
|
|
92
|
+
return self.username
|
|
93
|
+
"""
|
|
94
|
+
(backend_dir / "models.py").write_text(models_py_content)
|
|
95
|
+
|
|
96
|
+
# Create tortoise_conf.py for Aerich
|
|
97
|
+
tortoise_conf_content = """
|
|
98
|
+
TORTOISE_ORM = {
|
|
99
|
+
"connections": {"default": "sqlite://db.sqlite3"},
|
|
100
|
+
"apps": {
|
|
101
|
+
"models": {
|
|
102
|
+
"models": ["aerich.models", "models"],
|
|
103
|
+
"default_connection": "default",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
"""
|
|
108
|
+
(backend_dir / "tortoise_conf.py").write_text(tortoise_conf_content)
|
|
109
|
+
|
|
110
|
+
console.print("[green]FastAPI backend setup complete![/green]")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def create_django(project_dir: Path, separate_folders: bool = True):
|
|
114
|
+
"""Scaffold a Django project."""
|
|
115
|
+
|
|
116
|
+
backend_dir = project_dir / "backend"
|
|
117
|
+
if separate_folders:
|
|
118
|
+
backend_dir.mkdir(parents=True, exist_ok=True)
|
|
119
|
+
else:
|
|
120
|
+
backend_dir = project_dir
|
|
121
|
+
|
|
122
|
+
console.print(
|
|
123
|
+
f"[bold cyan]Initializing Django backend in {backend_dir}...[/bold cyan]"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Initialize UV project
|
|
127
|
+
# Use --no-workspace to ensure we create a standalone project
|
|
128
|
+
run_command(["uv", "init", "--app", "--no-workspace"], cwd=backend_dir)
|
|
129
|
+
|
|
130
|
+
# Add Django
|
|
131
|
+
console.print("[bold]Adding dependencies: django...[/bold]")
|
|
132
|
+
run_command(["uv", "add", "django"], cwd=backend_dir)
|
|
133
|
+
|
|
134
|
+
# Create Django Project
|
|
135
|
+
# We use 'config' as the project name usually, or 'core'. Let's use 'config'.
|
|
136
|
+
console.print("[bold]Running django-admin startproject...[/bold]")
|
|
137
|
+
run_command(
|
|
138
|
+
["uv", "run", "django-admin", "startproject", "config", "."], cwd=backend_dir
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
console.print("[green]Django backend setup complete![/green]")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def create_convex_standalone(project_dir: Path):
|
|
145
|
+
"""Initialize Convex in a standalone directory (rarely used without frontend)."""
|
|
146
|
+
console.print(f"[bold cyan]Initializing Convex in {project_dir}...[/bold cyan]")
|
|
147
|
+
|
|
148
|
+
project_dir.mkdir(parents=True, exist_ok=True)
|
|
149
|
+
|
|
150
|
+
# Check if npm/bun init is needed first
|
|
151
|
+
if not (project_dir / "package.json").exists():
|
|
152
|
+
run_command(["bun", "init", "-y"], cwd=project_dir)
|
|
153
|
+
|
|
154
|
+
run_command(["bun", "add", "convex"], cwd=project_dir)
|
|
155
|
+
run_command(
|
|
156
|
+
["npx", "convex", "dev"], cwd=project_dir
|
|
157
|
+
) # This is interactive usually!
|
|
158
|
+
# Wait, 'npx convex dev' is interactive and blocking. We probably shouldn't run it here.
|
|
159
|
+
# We should just install it and tell user to run it.
|
|
160
|
+
|
|
161
|
+
console.print(
|
|
162
|
+
"[green]Convex setup complete! Run 'npx convex dev' to start.[/green]"
|
|
163
|
+
)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import subprocess
|
|
3
|
+
import shutil
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
console = Console()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run_command(command, cwd=None, capture_output=False):
|
|
10
|
+
"""Run a shell command."""
|
|
11
|
+
try:
|
|
12
|
+
result = subprocess.run(
|
|
13
|
+
command, cwd=cwd, check=True, capture_output=capture_output, text=True
|
|
14
|
+
)
|
|
15
|
+
return result
|
|
16
|
+
except subprocess.CalledProcessError as e:
|
|
17
|
+
console.print(f"[red]Error executing command: {' '.join(command)}[/red]")
|
|
18
|
+
if e.stderr:
|
|
19
|
+
console.print(f"[red]{e.stderr}[/red]")
|
|
20
|
+
raise e
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def add_dependency(package_manager, package, cwd, dev=False):
|
|
24
|
+
"""Add a dependency."""
|
|
25
|
+
cmd = [package_manager, "add", "-d" if dev else "", package]
|
|
26
|
+
cmd = [c for c in cmd if c]
|
|
27
|
+
subprocess.run(cmd, cwd=cwd, check=True)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def install_tailwind(project_dir: Path, framework: str):
|
|
31
|
+
"""Install and configure Tailwind CSS."""
|
|
32
|
+
console.print(f"[bold]Setting up Tailwind CSS for {framework}...[/bold]")
|
|
33
|
+
|
|
34
|
+
if framework == "nextjs":
|
|
35
|
+
# Next.js with --yes already includes Tailwind by default
|
|
36
|
+
console.print(
|
|
37
|
+
"[green]Tailwind CSS already included with Next.js defaults[/green]"
|
|
38
|
+
)
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
# For other frameworks, install Tailwind v4 (zero config)
|
|
42
|
+
try:
|
|
43
|
+
# Install tailwindcss v4
|
|
44
|
+
run_command(
|
|
45
|
+
["bun", "add", "-d", "tailwindcss"],
|
|
46
|
+
cwd=project_dir,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
console.print("[green]Tailwind CSS v4 installed (zero config mode)[/green]")
|
|
50
|
+
console.print("[yellow]Note: Import Tailwind in your CSS file:[/yellow]")
|
|
51
|
+
console.print(' @import "tailwindcss";')
|
|
52
|
+
except Exception as e:
|
|
53
|
+
console.print(
|
|
54
|
+
f"[yellow]Warning: Could not auto-configure Tailwind. You may need to set it up manually.[/yellow]"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def create_nextjs(
|
|
59
|
+
project_dir: Path, subfolder: str = "frontend", use_convex: bool = False
|
|
60
|
+
):
|
|
61
|
+
"""Scaffold a Next.js project with Tailwind CSS."""
|
|
62
|
+
target_dir = project_dir / subfolder if subfolder != "." else project_dir
|
|
63
|
+
console.print(f"[bold cyan]Initializing Next.js in {target_dir}...[/bold cyan]")
|
|
64
|
+
|
|
65
|
+
if not project_dir.exists():
|
|
66
|
+
project_dir.mkdir(parents=True)
|
|
67
|
+
|
|
68
|
+
# Use --yes for non-interactive mode with defaults (includes Tailwind)
|
|
69
|
+
cmd = ["bun", "create", "next-app", subfolder if subfolder != "." else ".", "--yes"]
|
|
70
|
+
try:
|
|
71
|
+
run_command(cmd, cwd=project_dir)
|
|
72
|
+
except Exception:
|
|
73
|
+
console.print("[red]Failed to create Next.js project[/red]")
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if not target_dir.exists():
|
|
77
|
+
console.print(f"[red]Error: Directory {target_dir} was not created.[/red]")
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
# Tailwind is already included with --yes flag (default Next.js setup includes it)
|
|
81
|
+
console.print("[green]Next.js with Tailwind CSS created successfully![/green]")
|
|
82
|
+
|
|
83
|
+
if use_convex:
|
|
84
|
+
console.print("[bold]Adding Convex to Next.js...[/bold]")
|
|
85
|
+
add_dependency("bun", "convex", cwd=target_dir)
|
|
86
|
+
console.print(
|
|
87
|
+
"[yellow]Note: Run 'npx convex dev' in the frontend directory to configure Convex.[/yellow]"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def create_sveltekit(
|
|
92
|
+
project_dir: Path, subfolder: str = "frontend", use_convex: bool = False
|
|
93
|
+
):
|
|
94
|
+
"""Scaffold a SvelteKit project with Tailwind CSS."""
|
|
95
|
+
target_dir = project_dir / subfolder if subfolder != "." else project_dir
|
|
96
|
+
console.print(f"[bold cyan]Initializing SvelteKit in {target_dir}...[/bold cyan]")
|
|
97
|
+
|
|
98
|
+
if not project_dir.exists():
|
|
99
|
+
project_dir.mkdir(parents=True)
|
|
100
|
+
|
|
101
|
+
# Use npx sv create with flags for non-interactive mode
|
|
102
|
+
folder_arg = subfolder if subfolder != "." else "."
|
|
103
|
+
cmd = [
|
|
104
|
+
"npx",
|
|
105
|
+
"sv",
|
|
106
|
+
"create",
|
|
107
|
+
folder_arg,
|
|
108
|
+
"--template",
|
|
109
|
+
"demo", # Use demo template (includes more features)
|
|
110
|
+
"--types",
|
|
111
|
+
"ts", # TypeScript
|
|
112
|
+
"--no-add-ons", # Don't prompt for add-ons
|
|
113
|
+
"--install",
|
|
114
|
+
"bun", # Use bun to install
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
run_command(cmd, cwd=project_dir)
|
|
119
|
+
except Exception:
|
|
120
|
+
console.print("[red]Failed to create SvelteKit project[/red]")
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
if not target_dir.exists():
|
|
124
|
+
console.print(
|
|
125
|
+
f"[red]Error: Directory {target_dir} was not created. Skipping subsequent steps.[/red]"
|
|
126
|
+
)
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
console.print("[bold]Installing dependencies...[/bold]")
|
|
130
|
+
run_command(["bun", "install"], cwd=target_dir)
|
|
131
|
+
|
|
132
|
+
# Add Tailwind CSS
|
|
133
|
+
install_tailwind(target_dir, "sveltekit")
|
|
134
|
+
|
|
135
|
+
if use_convex:
|
|
136
|
+
console.print("[bold]Adding Convex to SvelteKit...[/bold]")
|
|
137
|
+
add_dependency("bun", "convex", cwd=target_dir)
|
|
138
|
+
console.print(
|
|
139
|
+
"[yellow]Note: Run 'npx convex dev' in the frontend directory to configure Convex.[/yellow]"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def create_tanstack(
|
|
144
|
+
project_dir: Path, subfolder: str = "frontend", use_convex: bool = False
|
|
145
|
+
):
|
|
146
|
+
"""Scaffold a TanStack Start project with Tailwind CSS."""
|
|
147
|
+
target_dir = project_dir / subfolder if subfolder != "." else project_dir
|
|
148
|
+
console.print(
|
|
149
|
+
f"[bold cyan]Initializing TanStack Start in {target_dir}...[/bold cyan]"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if not project_dir.exists():
|
|
153
|
+
project_dir.mkdir(parents=True)
|
|
154
|
+
|
|
155
|
+
# Use create subcommand (required for @tanstack/start v1)
|
|
156
|
+
folder_arg = subfolder if subfolder != "." else "."
|
|
157
|
+
cmd = [
|
|
158
|
+
"bun",
|
|
159
|
+
"create",
|
|
160
|
+
"@tanstack/start",
|
|
161
|
+
"create", # Subcommand required
|
|
162
|
+
folder_arg,
|
|
163
|
+
"--package-manager",
|
|
164
|
+
"bun",
|
|
165
|
+
"--no-git", # We'll handle git separately
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
run_command(cmd, cwd=project_dir)
|
|
170
|
+
except Exception:
|
|
171
|
+
console.print("[red]Failed to create TanStack Start project[/red]")
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
if not target_dir.exists():
|
|
175
|
+
console.print(f"[red]Error: Directory {target_dir} was not created.[/red]")
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
# Add Tailwind CSS
|
|
179
|
+
install_tailwind(target_dir, "tanstack")
|
|
180
|
+
|
|
181
|
+
if use_convex:
|
|
182
|
+
console.print("[bold]Adding Convex to TanStack Start...[/bold]")
|
|
183
|
+
add_dependency("bun", "convex", cwd=target_dir)
|
|
184
|
+
console.print(
|
|
185
|
+
"[yellow]Note: Run 'npx convex dev' in the frontend directory to configure Convex.[/yellow]"
|
|
186
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import subprocess
|
|
3
|
+
from rich.console import Console
|
|
4
|
+
|
|
5
|
+
console = Console()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def run_command(command, cwd=None):
|
|
9
|
+
"""Run a shell command."""
|
|
10
|
+
try:
|
|
11
|
+
subprocess.run(command, cwd=cwd, check=True, stdout=subprocess.DEVNULL)
|
|
12
|
+
except subprocess.CalledProcessError as e:
|
|
13
|
+
console.print(f"[red]Error executing command: {' '.join(command)}[/red]")
|
|
14
|
+
# Don't raise, just warn for VCS
|
|
15
|
+
console.print(
|
|
16
|
+
f"[yellow]VCS initialization failed. You may need to install the tool or init manually.[/yellow]"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def init_git(project_dir: Path):
|
|
21
|
+
"""Initialize a Git repository."""
|
|
22
|
+
console.print(
|
|
23
|
+
f"[bold cyan]Initializing Git repository in {project_dir}...[/bold cyan]"
|
|
24
|
+
)
|
|
25
|
+
run_command(["git", "init"], cwd=project_dir)
|
|
26
|
+
# create .gitignore if it doesn't exist?
|
|
27
|
+
# Usually frameworks create their own .gitignores.
|
|
28
|
+
# We might want to stage files.
|
|
29
|
+
# run_command(["git", "add", "."], cwd=project_dir)
|
|
30
|
+
# console.print("[green]Git initialized.[/green]")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def init_jj(project_dir: Path):
|
|
34
|
+
"""Initialize a Jujutsu repository (git-backed)."""
|
|
35
|
+
console.print(
|
|
36
|
+
f"[bold cyan]Initializing Jujutsu (jj) repository in {project_dir}...[/bold cyan]"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# 'jj git init' creates a repo backed by git, which is most common for interop.
|
|
40
|
+
run_command(["jj", "git", "init"], cwd=project_dir)
|
|
41
|
+
|
|
42
|
+
console.print("[green]Jujutsu initialized.[/green]")
|