create-dwy 0.9.1 → 0.10.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-dwy",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "项目脚手架与 Claude Code 配置同步工具",
5
5
  "type": "module",
6
6
  "bin": {
package/src/create.js CHANGED
@@ -154,11 +154,14 @@ export async function createProject(name) {
154
154
  }
155
155
 
156
156
  if (context.template === 'fullstack-monorepo') {
157
- console.log(chalk.gray(' cp .env.example .env'))
157
+ console.log(chalk.gray(' cp backend/.env.example backend/.env'))
158
+ if (context.includeFrontend) {
159
+ console.log(chalk.gray(' cp frontend/.env.example frontend/.env'))
160
+ }
158
161
  console.log(chalk.gray(' cd backend && uv sync --dev && cd ..'))
159
162
  if (context.includeFrontend) {
160
163
  console.log(chalk.gray(' cd frontend && pnpm install && cd ..'))
161
164
  }
162
- console.log(chalk.gray(' ./dev.sh'))
165
+ console.log(chalk.gray(' ./scripts/dev.sh'))
163
166
  }
164
167
  }
@@ -2,6 +2,7 @@
2
2
  description: Vue 3 + TS + Vite + Tailwind 应用层规范(强制使用 eui/ekit、业务聚合结构、组件 / TS / 路由 / API / 模板 / 样式 / 错误处理 / 注释)
3
3
  paths:
4
4
  - "**/*.vue"
5
+ - "**/*.ts"
5
6
  - "**/vite.config.*"
6
7
  ---
7
8
 
@@ -108,12 +109,6 @@ src/
108
109
  - 单文件超过约 400 行时再考虑拆分,**禁止**未到规模就预拆分
109
110
  - 模块间引用通过明确 import,**禁止**循环依赖
110
111
 
111
- ### 例外
112
-
113
- - 小型项目(< 3 个业务模块)允许扁平结构(`src/views/` + `src/components/`),但**不得**长大后保持扁平
114
-
115
- ---
116
-
117
112
  ## 二、组件规范
118
113
 
119
114
  ### 强制使用 Composition API + `<script setup>`
@@ -550,43 +545,7 @@ export function formatMoney(value: number, currency = '¥'): string {
550
545
 
551
546
  ---
552
547
 
553
- ## 十四、代码简约原则
554
-
555
- 代码只写**必要的逻辑**,不写"以防万一"的冗余代码。信任 TypeScript 类型系统与框架保证,只在系统边界(用户输入、外部 API)做校验。
556
-
557
- ### 禁止的冗余模式
558
-
559
- ```typescript
560
- // 反例:类型已保证非空,多余 fallback
561
- const name = props.title ?? '' // props.title: string
562
-
563
- // 正例
564
- const name = props.title
565
-
566
- // 反例:值一定存在
567
- const id = user?.id // user 来自必传 prop
568
-
569
- // 正例
570
- const id = user.id
571
-
572
- // 反例:空 catch 吞异常
573
- try { await api.getUsers() } catch {}
574
-
575
- // 正例:让异常暴露或给用户反馈
576
- try { await api.getUsers() } catch { toast.error('加载失败') }
577
- ```
578
-
579
- ### 判断标准
580
-
581
- 写每行防御代码前自问:**这个情况在当前上下文真的会发生吗?**
582
-
583
- - 会 → 写防御,注释说明触发条件
584
- - 不会 → 不写,信任上游保证
585
- - 不确定 → 查类型定义与调用链确认
586
-
587
- ---
588
-
589
- ## 十五、违规检测清单
548
+ ## 十四、违规检测清单
590
549
 
591
550
  AI 编写或审查 Vue 代码时,**必须**检查以下违规模式:
592
551
 
@@ -37,7 +37,8 @@ description: "调用 dwy create CLI 生成全栈 Vue 3 + FastAPI monorepo 骨架
37
37
  **推荐做法**:让用户在终端跑 `dwy create <project_name>` 自己回答交互(每次脚手架问题需要人 review),然后 skill 介入做 post-action。
38
38
  ↓
39
39
  4. 安装依赖(在 <target_parent_dir>/<project_name> 下):
40
- - cp .env.example .env (如未存在)
40
+ - cp backend/.env.example backend/.env (如未存在)
41
+ - cp frontend/.env.example frontend/.env (仅当 include_frontend=true 且未存在)
41
42
  - cd backend && uv sync --dev
42
43
  - cd frontend && pnpm install (仅当 include_frontend=true)
43
44
  ↓
@@ -62,14 +63,17 @@ description: "调用 dwy create CLI 生成全栈 Vue 3 + FastAPI monorepo 骨架
62
63
  ```
63
64
  <project_name>/
64
65
  ├── CLAUDE.md # 项目级总入口
65
- ├── dev.sh # 一键启动: 杀端口 + Docker + backend + frontend
66
- ├── docker-compose.dev.yml # PG + Redis(端口前缀 <port_prefix>xxxx)
67
- ├── .env.example
66
+ ├── scripts/
67
+ │ └── dev.sh # 一键启动: 杀端口 + Docker + backend + frontend
68
+ ├── docs/ # 设计文档占位
69
+ ├── docker-compose.dev.yml # dev: PG + Redis(端口前缀 <port_prefix>xxxx)
70
+ ├── docker-compose.prod.yml # prod: backend + db + redis(资源限制 + 日志轮转)
68
71
  ├── .gitignore
69
72
  ├── backend/
70
73
  │ ├── CLAUDE.md # 后端约束(域分包 / Provider / dwyeapi 优先)
74
+ │ ├── .env.example # backend 环境变量样例
71
75
  │ ├── pyproject.toml # uv workspace + 双 index + 版本中心
72
- │ ├── Dockerfile.dev
76
+ │ ├── Dockerfile.dev / Dockerfile.prod
73
77
  │ ├── alembic.ini + alembic/env.py
74
78
  │ ├── src/app/ # 装配层
75
79
  │ │ ├── main.py # FastAPI lifespan + register 业务包
@@ -91,6 +95,7 @@ description: "调用 dwy create CLI 生成全栈 Vue 3 + FastAPI monorepo 骨架
91
95
  │ └── tests/conftest.py
92
96
  └── frontend/ # 仅当 include_frontend=true
93
97
  ├── CLAUDE.md # 前端约束(eui 优先 / catalog / features 域分包)
98
+ ├── .env.example # Vite VITE_* 变量样例
94
99
  ├── package.json
95
100
  ├── pnpm-workspace.yaml # catalog 统一版本
96
101
  ├── tsconfig.base.json
@@ -157,8 +162,9 @@ description: "调用 dwy create CLI 生成全栈 Vue 3 + FastAPI monorepo 骨架
157
162
 
158
163
  🚀 下一步:
159
164
  cd /Users/chances/WebstormProjects/<project_name>
160
- cp .env.example .env # 修改 DATABASE_URL / SECRET_KEY 等
161
- ./dev.sh
165
+ cp backend/.env.example backend/.env # dev 默认值可直接用,prod 改 DATABASE_URL/SECRET_KEY
166
+ cp frontend/.env.example frontend/.env # Vite 变量(仅 include_frontend=true 时)
167
+ ./scripts/dev.sh
162
168
 
163
169
  🛠 业务开发起点:
164
170
  - backend: backend/src/app/main.py 装载 packages/<scope>-<domain>/
@@ -8,11 +8,15 @@ Monorepo 全栈骨架:
8
8
 
9
9
  ```
10
10
  {{projectName}}/
11
- ├── backend/ # FastAPI 后端(uv workspace + 域分包)
12
- ├── frontend/ # Vue 3 前端(pnpm workspace + catalog)
13
- ├── docker-compose.dev.yml # PostgreSQL + Redis 基础设施
14
- ├── dev.sh # 一键启动脚本
15
- └── .env.example
11
+ ├── backend/ # FastAPI 后端(uv workspace + 域分包)
12
+ │ └── .env.example # backend 自己的环境变量样例
13
+ ├── frontend/ # Vue 3 前端(pnpm workspace + catalog)
14
+ │ └── .env.example # Vite VITE_* 变量样例
15
+ ├── scripts/ # 项目脚本
16
+ │ └── dev.sh # 一键启动 (Docker + backend + frontend)
17
+ ├── docs/ # 设计文档占位
18
+ ├── docker-compose.dev.yml # dev: PostgreSQL + Redis(端口前缀 {{portPrefix}}xxxx)
19
+ └── docker-compose.prod.yml # prod: backend + db + redis(含资源限制 + 日志轮转)
16
20
  ```
17
21
 
18
22
  详细约束见各子目录的 `CLAUDE.md`。
@@ -31,17 +35,25 @@ Monorepo 全栈骨架:
31
35
  ## 启动
32
36
 
33
37
  ```bash
34
- # 1. 复制环境变量
35
- cp .env.example .env
38
+ # 1. 复制环境变量(dev 环境通常不需要改默认值)
39
+ cp backend/.env.example backend/.env
40
+ cp frontend/.env.example frontend/.env
36
41
 
37
42
  # 2. 安装依赖
38
43
  cd backend && uv sync --dev && cd ..
39
44
  cd frontend && pnpm install && cd ..
40
45
 
41
46
  # 3. 一键启动(Docker + backend + frontend)
42
- ./dev.sh
47
+ ./scripts/dev.sh
43
48
  ```
44
49
 
50
+ dev 数据库默认 `postgres / postgres` 密码,docker-compose.dev.yml 内硬编码,
51
+ backend 通过 `DATABASE_URL` 连入(见 `backend/.env.example`)。
52
+
53
+ 生产部署:`docker compose -f docker-compose.prod.yml up -d --build`,
54
+ 凭据从 `backend/.env`(env_file)+ 根级 `POSTGRES_PASSWORD` / `REDIS_PASSWORD`
55
+ 环境变量传入。
56
+
45
57
  ## 常用命令
46
58
 
47
59
  ```bash
@@ -55,7 +67,7 @@ uv run ruff check src/ && uv run ruff format src/
55
67
  # Frontend
56
68
  cd frontend
57
69
  pnpm install
58
- pnpm dev # 单独启 frontend
70
+ pnpm dev # 单独启 frontend (端口 {{portPrefix}}5173)
59
71
  pnpm build
60
72
  pnpm typecheck
61
73
 
@@ -0,0 +1,40 @@
1
+ FROM python:3.11.15-slim AS builder
2
+
3
+ ENV PYTHONDONTWRITEBYTECODE=1 \
4
+ PYTHONUNBUFFERED=1 \
5
+ UV_LINK_MODE=copy \
6
+ UV_COMPILE_BYTECODE=1
7
+
8
+ RUN apt-get update && apt-get install -y --no-install-recommends \
9
+ build-essential curl \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # 安装 uv
13
+ COPY --from=ghcr.io/astral-sh/uv:0.4 /uv /usr/local/bin/uv
14
+
15
+ WORKDIR /app
16
+ COPY pyproject.toml uv.lock* ./
17
+ COPY packages ./packages
18
+ COPY src ./src
19
+ RUN uv sync --frozen --no-dev
20
+
21
+
22
+ FROM python:3.11.15-slim AS runtime
23
+
24
+ ENV PYTHONDONTWRITEBYTECODE=1 \
25
+ PYTHONUNBUFFERED=1 \
26
+ PATH="/app/.venv/bin:$PATH" \
27
+ PYTHONPATH=/app/src
28
+
29
+ RUN apt-get update && apt-get install -y --no-install-recommends \
30
+ libpq5 \
31
+ && rm -rf /var/lib/apt/lists/* \
32
+ && groupadd -r app && useradd -r -g app -d /app -s /usr/sbin/nologin app
33
+
34
+ WORKDIR /app
35
+ COPY --from=builder --chown=app:app /app /app
36
+
37
+ USER app
38
+ EXPOSE 8000
39
+
40
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
@@ -0,0 +1,26 @@
1
+ # ============================================================
2
+ # {{projectName}} backend — 环境变量样例
3
+ # ============================================================
4
+ # 复制为 backend/.env 并填入真实值。.env 已 gitignored。
5
+ # dev 环境直接走 docker-compose.dev.yml(密码硬编码 postgres/postgres),
6
+ # 此文件主要供 prod 部署(docker-compose.prod.yml 的 backend env_file)。
7
+
8
+ # ── 基础 ──
9
+ ENVIRONMENT=prod
10
+ SECRET_KEY=change-me-in-production
11
+ LOG_LEVEL=INFO
12
+
13
+ # ── PostgreSQL ──
14
+ # dev: 默认连本地 docker-compose.dev.yml(127.0.0.1:{{portPrefix}}5432/{{projectName}}, postgres/postgres)
15
+ # prod: db 容器 service 名为 db(同 compose 网络下),端口仍是 5432
16
+ DATABASE_URL=postgresql+asyncpg://app_user:CHANGE_ME@db:5432/{{projectName}}
17
+
18
+ # ── Redis ──
19
+ REDIS_URL=redis://:CHANGE_ME@redis:6379/0
20
+
21
+ # ── 跨域 ──
22
+ ALLOWED_ORIGINS=https://example.com
23
+
24
+ # ── 服务端口 ──
25
+ # 容器内固定 8000,docker-compose.prod.yml 映射到宿主 127.0.0.1:{{portPrefix}}8002
26
+ BACKEND_PORT=8000
@@ -6,14 +6,14 @@ services:
6
6
  environment:
7
7
  TZ: Asia/Shanghai
8
8
  PGTZ: Asia/Shanghai
9
- POSTGRES_DB: ${POSTGRES_DB}
10
- POSTGRES_USER: ${POSTGRES_USER}
11
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
9
+ POSTGRES_DB: {{projectName}}
10
+ POSTGRES_USER: postgres
11
+ POSTGRES_PASSWORD: postgres
12
12
  command: ["postgres", "-c", "timezone=Asia/Shanghai"]
13
13
  volumes:
14
14
  - pgdata:/var/lib/postgresql/data
15
15
  healthcheck:
16
- test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
16
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
17
17
  interval: 5s
18
18
  timeout: 5s
19
19
  retries: 5
@@ -0,0 +1,116 @@
1
+ # {{projectName}} 生产 compose -- 三服务(backend + db + redis)+ 资源限制 + 日志轮转
2
+ #
3
+ # 部署假设:
4
+ # - 前端由宿主机全局 nginx 托管(静态文件在 /var/www/{{projectName}}/dist),
5
+ # 配置见 deploy/nginx/{{projectName}}.conf(用户自维护)。
6
+ # - backend 仅绑定 127.0.0.1:{{portPrefix}}8002,由宿主 nginx 反代上游。
7
+ # - 敏感凭据来自 backend/.env(env_file 引用),不要在 yml 硬编码。
8
+
9
+ x-logging: &default-logging
10
+ driver: json-file
11
+ options:
12
+ max-size: "10m"
13
+ max-file: "5"
14
+ compress: "true"
15
+
16
+ services:
17
+ backend:
18
+ image: {{projectName}}-backend:${BACKEND_TAG:-prod}
19
+ build:
20
+ context: ./backend
21
+ dockerfile: Dockerfile.prod
22
+ ports:
23
+ - "127.0.0.1:{{portPrefix}}8002:8000"
24
+ env_file:
25
+ - ./backend/.env
26
+ depends_on:
27
+ db:
28
+ condition: service_healthy
29
+ redis:
30
+ condition: service_healthy
31
+ healthcheck:
32
+ test: ["CMD-SHELL", "python -c 'import httpx; httpx.get(\"http://127.0.0.1:8000/api/health\")'"]
33
+ interval: 10s
34
+ timeout: 5s
35
+ retries: 5
36
+ start_period: 10s
37
+ read_only: true
38
+ tmpfs:
39
+ - /tmp
40
+ mem_limit: 1g
41
+ logging: *default-logging
42
+ restart: unless-stopped
43
+
44
+ db:
45
+ image: postgres:16.12-alpine3.23
46
+ shm_size: 256m
47
+ environment:
48
+ TZ: Asia/Shanghai
49
+ PGTZ: Asia/Shanghai
50
+ POSTGRES_DB: {{projectName}}
51
+ POSTGRES_USER: ${POSTGRES_USER:-app_user}
52
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD required}
53
+ # 1G 容器: shared_buffers=25%, effective_cache_size=75%
54
+ command:
55
+ - "postgres"
56
+ - "-c"
57
+ - "timezone=Asia/Shanghai"
58
+ - "-c"
59
+ - "max_connections=100"
60
+ - "-c"
61
+ - "shared_buffers=256MB"
62
+ - "-c"
63
+ - "effective_cache_size=768MB"
64
+ - "-c"
65
+ - "work_mem=4MB"
66
+ - "-c"
67
+ - "maintenance_work_mem=64MB"
68
+ - "-c"
69
+ - "log_min_duration_statement=500"
70
+ volumes:
71
+ - pgdata:/var/lib/postgresql/data
72
+ healthcheck:
73
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-app_user} -d {{projectName}}"]
74
+ interval: 5s
75
+ timeout: 3s
76
+ retries: 5
77
+ mem_limit: 1g
78
+ logging:
79
+ driver: json-file
80
+ options:
81
+ max-size: "20m"
82
+ max-file: "10"
83
+ compress: "true"
84
+ # 生产环境不暴露端口
85
+ restart: unless-stopped
86
+
87
+ redis:
88
+ image: redis:7.4.9-alpine3.21
89
+ # maxmemory 256mb 是 Redis 进程自管上限;mem_limit 384m 给 RDB/AOF fork
90
+ # 的 COW 留 buffer,避免被宿主 OOM-killer 杀掉。
91
+ # AOF + RDB 双持久化:重启不丢业务数据(验证码/nonce/限流计数等)。
92
+ command: [
93
+ "redis-server",
94
+ "--requirepass", "${REDIS_PASSWORD:?REDIS_PASSWORD required}",
95
+ "--maxmemory", "256mb",
96
+ "--maxmemory-policy", "allkeys-lru",
97
+ "--appendonly", "yes",
98
+ "--appendfsync", "everysec",
99
+ "--save", "900 1",
100
+ "--save", "300 10"
101
+ ]
102
+ volumes:
103
+ - redisdata:/data
104
+ healthcheck:
105
+ test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "--no-auth-warning", "ping"]
106
+ interval: 5s
107
+ timeout: 3s
108
+ retries: 5
109
+ mem_limit: 384m
110
+ logging: *default-logging
111
+ # 生产环境不暴露端口
112
+ restart: unless-stopped
113
+
114
+ volumes:
115
+ pgdata:
116
+ redisdata:
@@ -0,0 +1,19 @@
1
+ # ============================================================
2
+ # {{projectName}} frontend — Vite 环境变量样例
3
+ # ============================================================
4
+ # 复制为 frontend/.env 并按需调整。.env 已 gitignored。
5
+ # Vite 约定:只有 VITE_ 前缀的变量会暴露给客户端 bundle。
6
+ #
7
+ # 多环境覆盖:
8
+ # .env 所有模式
9
+ # .env.local 所有模式(本地,gitignored)
10
+ # .env.development dev 模式
11
+ # .env.production prod 模式
12
+
13
+ # ── API 基础路径 ──
14
+ # dev: '/api'(走 vite.config.ts 的 proxy → http://127.0.0.1:{{portPrefix}}8001)
15
+ # prod: '/api' 或 'https://api.example.com'(由宿主 nginx 反代)
16
+ VITE_API_BASE_URL=/api
17
+
18
+ # ── 站点元信息 ──
19
+ VITE_APP_TITLE={{projectName}}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
5
5
  BACKEND_PORT={{portPrefix}}8001
6
6
  FRONTEND_PORT={{portPrefix}}5173
7
7
  BACKEND_PID=""
@@ -42,7 +42,7 @@ echo "▶ 启动 Docker 基础设施..."
42
42
  docker compose -f "$SCRIPT_DIR/docker-compose.dev.yml" up -d --remove-orphans
43
43
 
44
44
  echo "▶ 等待 PostgreSQL 就绪..."
45
- until docker compose -f "$SCRIPT_DIR/docker-compose.dev.yml" exec -T db pg_isready > /dev/null 2>&1; do
45
+ until docker compose -f "$SCRIPT_DIR/docker-compose.dev.yml" exec -T db pg_isready -U postgres > /dev/null 2>&1; do
46
46
  sleep 1
47
47
  done
48
48
 
@@ -1,24 +0,0 @@
1
- # ============================================================
2
- # {{projectName}} — 环境变量样例
3
- # ============================================================
4
- # 复制为 .env 并填入真实值。.env 已 gitignored。
5
- # 端口前缀策略:本项目用 {{portPrefix}}xxxx 万位前缀避免与其他项目冲突。
6
-
7
- # ── 基础 ──
8
- ENVIRONMENT=dev
9
- SECRET_KEY=change-me-in-production
10
-
11
- # ── PostgreSQL ──
12
- # docker-compose.dev.yml 默认本地端口:127.0.0.1:{{portPrefix}}5432
13
- POSTGRES_DB={{projectName}}
14
- POSTGRES_USER=postgres
15
- POSTGRES_PASSWORD=postgres
16
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@127.0.0.1:{{portPrefix}}5432/{{projectName}}
17
-
18
- # ── Redis ──
19
- # docker-compose.dev.yml 默认本地端口:127.0.0.1:{{portPrefix}}6379
20
- REDIS_URL=redis://127.0.0.1:{{portPrefix}}6379/0
21
-
22
- # ── 服务端口(dev.sh 读取) ──
23
- BACKEND_PORT={{portPrefix}}8001
24
- FRONTEND_PORT={{portPrefix}}5173