205 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import APIRouter, HTTPException
from typing import Dict, Any
from pathlib import Path
import re
router = APIRouter()
def to_snake(name: str) -> str:
return name.replace(' ', '_').replace('-', '_').lower()
@router.post("/dev/create-pagetype-template")
async def create_pagetypes(payload: Dict[str, Any]):
try:
name = payload.get("pagetype")
app = payload.get("app", "jingrow")
module = payload.get("module", "").replace('.', '/').lower()
create_frontend = bool(payload.get("create_frontend", True))
create_backend = bool(payload.get("create_backend", True))
if not name:
raise ValueError("pagetype is required")
slug = to_snake(name)
current = Path(__file__).resolve()
# project root (apps/jingrow/jingrow/core/api/dev.py) -> go up 5
root = current.parents[5]
frontend_path = None
backend_path = None
frontend_exists = False
backend_exists = False
if create_frontend:
fp = root / "apps" / app / "frontend" / module / "pagetype" / slug / f"{slug}_toolbar.vue"
fp.parent.mkdir(parents=True, exist_ok=True)
if fp.exists():
frontend_exists = True
else:
fp.write_text("<template>\n <div></div>\n</template>\n<script setup lang=\"ts\">\n</script>\n", encoding="utf-8")
frontend_path = str(fp)
if create_backend:
bp = root / "apps" / app / app / app / module / "pagetype" / slug / f"{slug}.py"
bp.parent.mkdir(parents=True, exist_ok=True)
if bp.exists():
backend_exists = True
else:
bp.write_text("# coding: utf-8\n\n# Blank template for PageType backend hooks\n", encoding="utf-8")
backend_path = str(bp)
return {
"success": True,
"frontend_path": frontend_path,
"backend_path": backend_path,
"frontend_exists": frontend_exists,
"backend_exists": backend_exists
}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@router.post("/dev/create-app-template")
async def create_app_template(payload: Dict[str, Any]):
"""创建现代化的App模板符合最佳实践"""
try:
app_name = payload.get("appName", "").strip()
app_title = payload.get("appTitle", "").strip()
publisher = payload.get("publisher", "").strip()
description = payload.get("description", "").strip()
email = payload.get("email", "").strip()
license_type = payload.get("license", "MIT")
# 自动生成模块名称与bench new-app保持一致
module_name = app_title # 使用app_title作为模块名称
# 默认包含所有功能,简化用户选择
include_api = True
include_frontend = True
include_tests = True
cloud_compatible = True
if not app_name:
raise ValueError("App name is required")
if not app_title:
raise ValueError("App title is required")
if not publisher:
raise ValueError("Publisher is required")
if not description:
raise ValueError("Description is required")
# 验证app名称格式
if not re.match(r'^[a-z][a-z0-9_]*$', app_name):
raise ValueError("App name must start with lowercase letter and contain only lowercase letters, numbers, and underscores")
current = Path(__file__).resolve()
root = current.parents[5] # 调整路径层级
# 创建app目录结构 - 保存到apps/app_name
app_dir = root / "apps" / app_name
app_dir.mkdir(parents=True, exist_ok=True)
# 创建frontend和app_name子目录
frontend_dir = app_dir / "frontend"
backend_dir = app_dir / app_name
frontend_dir.mkdir(parents=True, exist_ok=True)
backend_dir.mkdir(parents=True, exist_ok=True)
# 创建app内部结构在app_name目录下
app_inner_dir = backend_dir
# 创建hooks.py
hooks_content = f'''app_name = "{app_name}"
app_title = "{app_title}"
app_publisher = "{publisher}"
app_description = "{description}"
app_email = "{email}"
app_license = "{license_type.lower()}"
'''
hooks_file = app_inner_dir / "hooks.py"
hooks_file.write_text(hooks_content, encoding="utf-8")
# 创建__init__.py
init_content = f'''__version__ = "0.0.1"
'''
(app_inner_dir / "__init__.py").write_text(init_content, encoding="utf-8")
# 创建modules.txt
modules_content = f'''{app_title}
'''
(app_inner_dir / "modules.txt").write_text(modules_content, encoding="utf-8")
# 创建目录结构
(app_inner_dir / "config").mkdir(exist_ok=True)
(app_inner_dir / "config" / "__init__.py").write_text("", encoding="utf-8")
(app_inner_dir / "public").mkdir(exist_ok=True)
(app_inner_dir / "public" / "css").mkdir(exist_ok=True)
(app_inner_dir / "public" / "js").mkdir(exist_ok=True)
(app_inner_dir / "public" / ".gitkeep").write_text("", encoding="utf-8")
# 创建module目录与config、public平级
(app_inner_dir / app_name).mkdir(exist_ok=True)
(app_inner_dir / app_name / "__init__.py").write_text("", encoding="utf-8")
# 创建README.md最小化文档
readme_content = f'''# {app_title}
{description}
## 安装
```bash
pip install -e .
```
## 开发
```bash
pip install -e ".[dev]"
```
## 许可证
{license_type} License
'''
(app_dir / "README.md").write_text(readme_content, encoding="utf-8")
pyproject_content = f'''[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "{app_name}"
version = "0.0.1"
description = "{description}"
authors = [
{{name = "{publisher}", email = "{email}"}}
]
license = {{text = "{license_type}"}}
requires-python = ">=3.8"
dependencies = [
# Add your app-specific dependencies here
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
]
'''
(app_dir / "pyproject.toml").write_text(pyproject_content, encoding="utf-8")
return {
"success": True,
"appName": app_name,
"appTitle": app_title,
"appPath": str(app_dir),
"backendPath": str(app_inner_dir),
"frontendPath": str(frontend_dir) if include_frontend else None
}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))