create-idp 0.1.0 → 0.2.1
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/README.md +88 -127
- package/dist/index.js +162 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/django/README.md +27 -0
- package/templates/django/_gitignore +20 -0
- package/templates/django/_template.json +14 -0
- package/templates/django/manage.py +22 -0
- package/templates/django/project_name/__init__.py +1 -0
- package/templates/django/project_name/asgi.py +11 -0
- package/templates/django/project_name/settings.py +75 -0
- package/templates/django/project_name/urls.py +16 -0
- package/templates/django/project_name/wsgi.py +11 -0
- package/templates/django/pyproject.toml +20 -0
- package/templates/express-ts/README.md +27 -0
- package/templates/express-ts/_gitignore +7 -0
- package/templates/express-ts/_template.json +13 -0
- package/templates/express-ts/package.json +23 -0
- package/templates/express-ts/src/index.ts +17 -0
- package/templates/express-ts/src/middleware/error-handler.ts +14 -0
- package/templates/express-ts/src/routes/index.ts +11 -0
- package/templates/express-ts/tsconfig.json +17 -0
- package/templates/express-ts/tsup.config.ts +9 -0
- package/templates/fastapi/README.md +21 -0
- package/templates/fastapi/_gitignore +16 -0
- package/templates/fastapi/_template.json +14 -0
- package/templates/fastapi/pyproject.toml +21 -0
- package/templates/fastapi/src/project_name/__init__.py +1 -0
- package/templates/fastapi/src/project_name/main.py +20 -0
- package/templates/fastapi/src/project_name/routes/__init__.py +8 -0
- package/templates/flask/README.md +15 -0
- package/templates/flask/_gitignore +17 -0
- package/templates/flask/_template.json +14 -0
- package/templates/flask/pyproject.toml +19 -0
- package/templates/flask/src/project_name/__init__.py +1 -0
- package/templates/flask/src/project_name/app.py +15 -0
- package/templates/flask/src/project_name/routes/__init__.py +8 -0
- package/templates/fullstack-react-node/README.md +35 -0
- package/templates/fullstack-react-node/_gitignore +7 -0
- package/templates/fullstack-react-node/_template.json +14 -0
- package/templates/fullstack-react-node/backend/package.json +22 -0
- package/templates/fullstack-react-node/backend/src/index.ts +20 -0
- package/templates/fullstack-react-node/backend/tsconfig.json +17 -0
- package/templates/fullstack-react-node/backend/tsup.config.ts +9 -0
- package/templates/fullstack-react-node/frontend/index.html +12 -0
- package/templates/fullstack-react-node/frontend/package.json +22 -0
- package/templates/fullstack-react-node/frontend/src/App.css +16 -0
- package/templates/fullstack-react-node/frontend/src/App.tsx +22 -0
- package/templates/fullstack-react-node/frontend/src/main.tsx +9 -0
- package/templates/fullstack-react-node/frontend/tsconfig.json +20 -0
- package/templates/fullstack-react-node/frontend/vite.config.ts +14 -0
- package/templates/fullstack-react-node/package.json +10 -0
- package/templates/fullstack-react-node/pnpm-workspace.yaml +3 -0
- package/templates/fullstack-react-python/Makefile +35 -0
- package/templates/fullstack-react-python/README.md +43 -0
- package/templates/fullstack-react-python/_gitignore +18 -0
- package/templates/fullstack-react-python/_template.json +25 -0
- package/templates/fullstack-react-python/backend/pyproject.toml +21 -0
- package/templates/fullstack-react-python/backend/src/project_name/__init__.py +1 -0
- package/templates/fullstack-react-python/backend/src/project_name/main.py +29 -0
- package/templates/fullstack-react-python/backend/src/project_name/routes/__init__.py +8 -0
- package/templates/fullstack-react-python/frontend/index.html +12 -0
- package/templates/fullstack-react-python/frontend/package.json +22 -0
- package/templates/fullstack-react-python/frontend/src/App.css +16 -0
- package/templates/fullstack-react-python/frontend/src/App.tsx +22 -0
- package/templates/fullstack-react-python/frontend/src/main.tsx +9 -0
- package/templates/fullstack-react-python/frontend/tsconfig.json +20 -0
- package/templates/fullstack-react-python/frontend/vite.config.ts +14 -0
- package/templates/fullstack-vue-node/README.md +35 -0
- package/templates/fullstack-vue-node/_gitignore +7 -0
- package/templates/fullstack-vue-node/_template.json +14 -0
- package/templates/fullstack-vue-node/backend/package.json +22 -0
- package/templates/fullstack-vue-node/backend/src/index.ts +20 -0
- package/templates/fullstack-vue-node/backend/tsconfig.json +17 -0
- package/templates/fullstack-vue-node/backend/tsup.config.ts +9 -0
- package/templates/fullstack-vue-node/frontend/index.html +12 -0
- package/templates/fullstack-vue-node/frontend/package.json +20 -0
- package/templates/fullstack-vue-node/frontend/src/App.vue +41 -0
- package/templates/fullstack-vue-node/frontend/src/main.ts +4 -0
- package/templates/fullstack-vue-node/frontend/src/vite-env.d.ts +1 -0
- package/templates/fullstack-vue-node/frontend/tsconfig.json +20 -0
- package/templates/fullstack-vue-node/frontend/vite.config.ts +14 -0
- package/templates/fullstack-vue-node/package.json +10 -0
- package/templates/fullstack-vue-node/pnpm-workspace.yaml +3 -0
- package/templates/next-ts/README.md +26 -0
- package/templates/next-ts/_gitignore +34 -0
- package/templates/next-ts/_template.json +13 -0
- package/templates/next-ts/next.config.ts +7 -0
- package/templates/next-ts/package.json +22 -0
- package/templates/next-ts/src/app/globals.css +21 -0
- package/templates/next-ts/src/app/layout.tsx +19 -0
- package/templates/next-ts/src/app/page.tsx +10 -0
- package/templates/next-ts/tsconfig.json +27 -0
- package/templates/springboot/.mvn/wrapper/maven-wrapper.properties +2 -0
- package/templates/springboot/README.md +27 -0
- package/templates/springboot/_gitignore +36 -0
- package/templates/springboot/_template.json +14 -0
- package/templates/springboot/mvnw +19 -0
- package/templates/springboot/mvnw.cmd +13 -0
- package/templates/springboot/pom.xml +46 -0
- package/templates/springboot/src/main/java/com/example/project_name/Application.java +12 -0
- package/templates/springboot/src/main/java/com/example/project_name/controller/HelloController.java +25 -0
- package/templates/springboot/src/main/resources/application.yml +6 -0
- package/templates/springboot/src/test/java/com/example/project_name/ApplicationTests.java +12 -0
- package/templates/template.config.json +78 -10
package/README.md
CHANGED
|
@@ -2,110 +2,115 @@
|
|
|
2
2
|
|
|
3
3
|
快速创建项目并自动初始化 GitHub 仓库的 CLI 脚手架工具。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 快速开始
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
- 🔐 安全的 Token 管理
|
|
11
|
-
- 📦 多模板支持
|
|
12
|
-
- ⚡ Node.js 18+ 原生支持
|
|
7
|
+
```bash
|
|
8
|
+
# 使用 npx (推荐)
|
|
9
|
+
npx create-idp my-app
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
# 或使用 npm create
|
|
12
|
+
npm create idp my-app
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
# 或全局安装后使用
|
|
17
15
|
npm install -g create-idp
|
|
16
|
+
create-idp my-app
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
##
|
|
19
|
+
## 用法
|
|
21
20
|
|
|
22
|
-
###
|
|
21
|
+
### 交互式创建
|
|
23
22
|
|
|
24
23
|
```bash
|
|
25
|
-
create-idp
|
|
24
|
+
npx create-idp
|
|
26
25
|
```
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
### 2. 创建项目
|
|
27
|
+
### 指定模板创建
|
|
31
28
|
|
|
32
29
|
```bash
|
|
33
|
-
|
|
34
|
-
create-idp
|
|
35
|
-
|
|
36
|
-
# 或一条命令
|
|
37
|
-
create-idp my-app --github --template node-ts
|
|
30
|
+
npx create-idp my-app --template react-ts
|
|
31
|
+
npx create-idp my-api --template fastapi
|
|
32
|
+
npx create-idp my-fullstack --template fullstack-react-node
|
|
38
33
|
```
|
|
39
34
|
|
|
40
|
-
###
|
|
35
|
+
### 一条命令创建并推送到 GitHub
|
|
41
36
|
|
|
42
37
|
```bash
|
|
43
|
-
|
|
44
|
-
pnpm dev
|
|
38
|
+
npx create-idp my-app --github --template node-ts
|
|
45
39
|
```
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
### 配置管理
|
|
41
|
+
### 列出所有可用模板
|
|
50
42
|
|
|
51
43
|
```bash
|
|
52
|
-
create-idp
|
|
53
|
-
create-idp config --show # 显示当前配置
|
|
54
|
-
create-idp config --path # 显示配置文件路径
|
|
44
|
+
npx create-idp list
|
|
55
45
|
```
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
## 可用模板
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
create-idp # 交互式创建
|
|
61
|
-
create-idp my-app # 指定项目名
|
|
62
|
-
create-idp my-app --template node-ts # 指定模板
|
|
63
|
-
create-idp my-app --github # 创建 + GitHub 仓库
|
|
64
|
-
create-idp my-app --github --public # 创建公开仓库
|
|
65
|
-
create-idp my-app --no-git # 不初始化 Git
|
|
66
|
-
```
|
|
49
|
+
### 单体项目
|
|
67
50
|
|
|
68
|
-
|
|
51
|
+
| 模板名 | 描述 |
|
|
52
|
+
|--------|------|
|
|
53
|
+
| `node-ts` | Node.js + TypeScript |
|
|
54
|
+
| `express-ts` | Express + TypeScript API |
|
|
55
|
+
| `react-ts` | React 18 + Vite + TypeScript |
|
|
56
|
+
| `vue-ts` | Vue 3 + Vite + TypeScript |
|
|
57
|
+
| `next-ts` | Next.js 14 + App Router |
|
|
58
|
+
| `python-uv` | Python + uv 包管理器 |
|
|
59
|
+
| `fastapi` | FastAPI + uv |
|
|
60
|
+
| `django` | Django + uv |
|
|
61
|
+
| `flask` | Flask + uv |
|
|
62
|
+
| `springboot` | Spring Boot 3.x + Maven |
|
|
63
|
+
| `empty` | 空项目 |
|
|
69
64
|
|
|
70
|
-
###
|
|
65
|
+
### 前后端分离
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
pnpm
|
|
76
|
-
|
|
67
|
+
| 模板名 | 描述 |
|
|
68
|
+
|--------|------|
|
|
69
|
+
| `fullstack-react-node` | React + Express (pnpm workspace) |
|
|
70
|
+
| `fullstack-vue-node` | Vue 3 + Express (pnpm workspace) |
|
|
71
|
+
| `fullstack-react-python` | React + FastAPI (Makefile) |
|
|
77
72
|
|
|
78
|
-
|
|
73
|
+
## 命令参考
|
|
79
74
|
|
|
80
|
-
|
|
75
|
+
### 创建项目
|
|
81
76
|
|
|
82
77
|
```bash
|
|
83
|
-
create-idp
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
create-idp my-
|
|
87
|
-
|
|
78
|
+
npx create-idp # 交互式创建
|
|
79
|
+
npx create-idp my-app # 指定项目名
|
|
80
|
+
npx create-idp my-app --template node-ts # 指定模板
|
|
81
|
+
npx create-idp my-app --github # 创建 + GitHub 仓库
|
|
82
|
+
npx create-idp my-app --github --public # 创建公开仓库
|
|
83
|
+
npx create-idp my-app --no-git # 不初始化 Git
|
|
84
|
+
npx create-idp my-app --no-install # 跳过依赖安装
|
|
88
85
|
```
|
|
89
86
|
|
|
90
|
-
###
|
|
87
|
+
### 列出模板
|
|
91
88
|
|
|
92
89
|
```bash
|
|
93
|
-
create-idp
|
|
90
|
+
npx create-idp list
|
|
94
91
|
```
|
|
95
92
|
|
|
96
|
-
|
|
93
|
+
### 配置管理
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
```bash
|
|
96
|
+
create-idp config --setup-github # 配置 GitHub Token
|
|
97
|
+
create-idp config --show # 显示当前配置
|
|
98
|
+
create-idp config --path # 显示配置文件路径
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## GitHub 集成
|
|
99
102
|
|
|
100
|
-
###
|
|
103
|
+
### 首次使用配置 Token
|
|
101
104
|
|
|
102
105
|
```bash
|
|
103
|
-
create-idp config --
|
|
106
|
+
npx create-idp config --setup-github
|
|
104
107
|
```
|
|
105
108
|
|
|
106
|
-
|
|
109
|
+
按提示获取 Token: https://github.com/settings/tokens/new?scopes=repo
|
|
107
110
|
|
|
108
|
-
|
|
111
|
+
### 配置文件
|
|
112
|
+
|
|
113
|
+
配置文件位置: `~/.create-idp.json`
|
|
109
114
|
|
|
110
115
|
```json
|
|
111
116
|
{
|
|
@@ -121,85 +126,41 @@ create-idp config --show
|
|
|
121
126
|
}
|
|
122
127
|
```
|
|
123
128
|
|
|
124
|
-
##
|
|
125
|
-
|
|
126
|
-
- ✅ Token 验证 (GET /user)
|
|
127
|
-
- ✅ 创建个人仓库 (POST /user/repos)
|
|
128
|
-
- ✅ 创建组织仓库 (POST /orgs/{org}/repos)
|
|
129
|
-
- ✅ 自动配置 git remote
|
|
130
|
-
- ✅ 自动推送初始提交
|
|
131
|
-
|
|
132
|
-
## 安全性
|
|
133
|
-
|
|
134
|
-
- 配置文件权限自动设置为 600 (仅所有者读写)
|
|
135
|
-
- Token 存储在本地,不会上传
|
|
136
|
-
- 使用 HTTPS 连接 GitHub
|
|
137
|
-
- 完善的错误处理
|
|
129
|
+
## 项目结构示例
|
|
138
130
|
|
|
139
|
-
|
|
131
|
+
### 单体项目 (node-ts)
|
|
140
132
|
|
|
141
|
-
### Q: Token 失效了怎么办?
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
create-idp config --setup-github
|
|
145
133
|
```
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
### Q: 如何跳过创建 GitHub 仓库?
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
create-idp my-app --no-git
|
|
134
|
+
my-app/
|
|
135
|
+
├── src/
|
|
136
|
+
│ └── index.ts
|
|
137
|
+
├── package.json
|
|
138
|
+
├── tsconfig.json
|
|
139
|
+
└── README.md
|
|
157
140
|
```
|
|
158
141
|
|
|
159
|
-
###
|
|
142
|
+
### 全栈项目 (fullstack-react-node)
|
|
160
143
|
|
|
161
|
-
```bash
|
|
162
|
-
create-idp config --setup-github
|
|
163
144
|
```
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
- `node-ts` - Node.js + TypeScript
|
|
176
|
-
- `react-ts` - React + TypeScript
|
|
177
|
-
- `vue-ts` - Vue + TypeScript
|
|
178
|
-
- 更多自定义模板
|
|
145
|
+
my-app/
|
|
146
|
+
├── frontend/
|
|
147
|
+
│ ├── src/
|
|
148
|
+
│ ├── package.json
|
|
149
|
+
│ └── vite.config.ts
|
|
150
|
+
├── backend/
|
|
151
|
+
│ ├── src/
|
|
152
|
+
│ └── package.json
|
|
153
|
+
├── package.json
|
|
154
|
+
└── pnpm-workspace.yaml
|
|
155
|
+
```
|
|
179
156
|
|
|
180
157
|
## 系统要求
|
|
181
158
|
|
|
182
159
|
- Node.js >= 18.0.0
|
|
183
|
-
- npm
|
|
160
|
+
- pnpm (推荐) / npm / yarn
|
|
161
|
+
- uv (Python 模板)
|
|
162
|
+
- Maven (Spring Boot 模板)
|
|
184
163
|
|
|
185
164
|
## 许可证
|
|
186
165
|
|
|
187
166
|
MIT
|
|
188
|
-
|
|
189
|
-
## 相关链接
|
|
190
|
-
|
|
191
|
-
- [GitHub](https://github.com/your-username/create-idp)
|
|
192
|
-
- [npm Package](https://www.npmjs.com/package/create-idp)
|
|
193
|
-
|
|
194
|
-
## 贡献
|
|
195
|
-
|
|
196
|
-
欢迎提交 Issue 和 Pull Request!
|
|
197
|
-
|
|
198
|
-
## 变更日志
|
|
199
|
-
|
|
200
|
-
### v0.1.0
|
|
201
|
-
|
|
202
|
-
- 初始发布
|
|
203
|
-
- GitHub API 集成
|
|
204
|
-
- CLI 命令完整
|
|
205
|
-
- 完整的文档和指南
|
package/dist/index.js
CHANGED
|
@@ -7,16 +7,18 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
|
+
import path7 from "path";
|
|
11
|
+
import fs5 from "fs";
|
|
10
12
|
import { Command } from "commander";
|
|
11
13
|
import pc6 from "picocolors";
|
|
12
14
|
|
|
13
15
|
// package.json
|
|
14
|
-
var version = "0.1
|
|
16
|
+
var version = "0.2.1";
|
|
15
17
|
|
|
16
18
|
// src/prompts.ts
|
|
17
19
|
import path2 from "path";
|
|
18
20
|
import fs from "fs";
|
|
19
|
-
import { input, select, confirm } from "@inquirer/prompts";
|
|
21
|
+
import { input, select, confirm, Separator } from "@inquirer/prompts";
|
|
20
22
|
import pc from "picocolors";
|
|
21
23
|
|
|
22
24
|
// src/utils.ts
|
|
@@ -35,11 +37,11 @@ function toValidPackageName(name) {
|
|
|
35
37
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
|
|
36
38
|
}
|
|
37
39
|
function isEmpty(dirPath) {
|
|
38
|
-
const
|
|
39
|
-
if (!
|
|
40
|
+
const fs6 = __require("fs");
|
|
41
|
+
if (!fs6.existsSync(dirPath)) {
|
|
40
42
|
return true;
|
|
41
43
|
}
|
|
42
|
-
const files =
|
|
44
|
+
const files = fs6.readdirSync(dirPath);
|
|
43
45
|
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
44
46
|
}
|
|
45
47
|
function execAsync(command, args, options = {}) {
|
|
@@ -109,10 +111,25 @@ async function runPrompts(argProjectName, options, userConfig = {}) {
|
|
|
109
111
|
let template = options.template;
|
|
110
112
|
if (!template) {
|
|
111
113
|
const defaultTemplate = defaults.template;
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
const singleTemplates = registry.templates.filter((t) => t.category !== "fullstack");
|
|
115
|
+
const fullstackTemplates = registry.templates.filter((t) => t.category === "fullstack");
|
|
116
|
+
const templateChoices = [];
|
|
117
|
+
templateChoices.push(new Separator("\u2500\u2500 \u5355\u4F53\u9879\u76EE \u2500\u2500"));
|
|
118
|
+
for (const t of singleTemplates) {
|
|
119
|
+
templateChoices.push({
|
|
120
|
+
name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,
|
|
121
|
+
value: t.name
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (fullstackTemplates.length > 0) {
|
|
125
|
+
templateChoices.push(new Separator("\u2500\u2500 \u524D\u540E\u7AEF\u5206\u79BB \u2500\u2500"));
|
|
126
|
+
for (const t of fullstackTemplates) {
|
|
127
|
+
templateChoices.push({
|
|
128
|
+
name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,
|
|
129
|
+
value: t.name
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
116
133
|
template = await select({
|
|
117
134
|
message: "\u9009\u62E9\u6A21\u677F:",
|
|
118
135
|
choices: templateChoices,
|
|
@@ -266,6 +283,22 @@ import fs3 from "fs";
|
|
|
266
283
|
import path4 from "path";
|
|
267
284
|
import os from "os";
|
|
268
285
|
var CONFIG_PATH = path4.join(os.homedir(), ".create-idp.json");
|
|
286
|
+
var DEFAULT_CONFIG = {
|
|
287
|
+
defaults: {
|
|
288
|
+
github: false,
|
|
289
|
+
public: false,
|
|
290
|
+
template: ""
|
|
291
|
+
},
|
|
292
|
+
github: {
|
|
293
|
+
token: "",
|
|
294
|
+
defaultOrg: ""
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
function ensureConfigExists() {
|
|
298
|
+
if (!fs3.existsSync(CONFIG_PATH)) {
|
|
299
|
+
saveConfig(DEFAULT_CONFIG);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
269
302
|
function loadConfig() {
|
|
270
303
|
try {
|
|
271
304
|
if (fs3.existsSync(CONFIG_PATH)) {
|
|
@@ -430,6 +463,7 @@ async function createGithubRepo(repoName, targetDir, isPublic) {
|
|
|
430
463
|
}
|
|
431
464
|
|
|
432
465
|
// src/post-init.ts
|
|
466
|
+
import path5 from "path";
|
|
433
467
|
import pc3 from "picocolors";
|
|
434
468
|
async function runPostInit(targetDir, commands) {
|
|
435
469
|
for (const cmd of commands) {
|
|
@@ -447,13 +481,27 @@ async function runPostInit(targetDir, commands) {
|
|
|
447
481
|
}
|
|
448
482
|
}
|
|
449
483
|
}
|
|
484
|
+
async function runWorkspacePostInit(targetDir, config) {
|
|
485
|
+
if (config.postInit && config.postInit.length > 0) {
|
|
486
|
+
await runPostInit(targetDir, config.postInit);
|
|
487
|
+
}
|
|
488
|
+
if (config.workspaces) {
|
|
489
|
+
for (const ws of config.workspaces) {
|
|
490
|
+
if (ws.postInit && ws.postInit.length > 0) {
|
|
491
|
+
const wsDir = path5.join(targetDir, ws.name);
|
|
492
|
+
console.log(pc3.dim(` [${ws.name}]`));
|
|
493
|
+
await runPostInit(wsDir, ws.postInit);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
450
498
|
|
|
451
499
|
// src/update-check.ts
|
|
452
500
|
import fs4 from "fs";
|
|
453
|
-
import
|
|
501
|
+
import path6 from "path";
|
|
454
502
|
import os2 from "os";
|
|
455
503
|
import pc4 from "picocolors";
|
|
456
|
-
var CACHE_PATH =
|
|
504
|
+
var CACHE_PATH = path6.join(os2.homedir(), ".create-idp-update-check");
|
|
457
505
|
var CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
458
506
|
var PACKAGE_NAME = "create-idp";
|
|
459
507
|
function readCache() {
|
|
@@ -521,6 +569,10 @@ async function checkForUpdates(currentVersion) {
|
|
|
521
569
|
import { input as input2, confirm as confirm2 } from "@inquirer/prompts";
|
|
522
570
|
import pc5 from "picocolors";
|
|
523
571
|
var TOKEN_HELP_URL = "https://github.com/settings/tokens/new?scopes=repo&description=create-idp";
|
|
572
|
+
function isUserCancelled(err) {
|
|
573
|
+
const error = err;
|
|
574
|
+
return error.message === "PROMPT_CANCELLED" || error.name === "ExitPromptError" || error.message.includes("User force closed");
|
|
575
|
+
}
|
|
524
576
|
async function runGitHubSetup() {
|
|
525
577
|
console.log();
|
|
526
578
|
console.log(pc5.cyan("\u914D\u7F6E GitHub Token"));
|
|
@@ -535,58 +587,66 @@ async function runGitHubSetup() {
|
|
|
535
587
|
console.log();
|
|
536
588
|
console.log(pc5.dim(`\u5FEB\u6377\u94FE\u63A5: ${TOKEN_HELP_URL}`));
|
|
537
589
|
console.log();
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
if (!value.trim()) {
|
|
542
|
-
return "Token \u4E0D\u80FD\u4E3A\u7A7A";
|
|
543
|
-
}
|
|
544
|
-
if (!value.startsWith("ghp_") && !value.startsWith("github_pat_")) {
|
|
545
|
-
return "Token \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5E94\u4EE5 ghp_ \u6216 github_pat_ \u5F00\u5934";
|
|
546
|
-
}
|
|
547
|
-
return true;
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
console.log();
|
|
551
|
-
console.log(pc5.dim("\u6B63\u5728\u9A8C\u8BC1 Token..."));
|
|
552
|
-
const result = await validateToken(token.trim());
|
|
553
|
-
if (!result.success) {
|
|
554
|
-
console.log(pc5.red(`\u2717 Token \u9A8C\u8BC1\u5931\u8D25: ${result.error}`));
|
|
555
|
-
if (result.rateLimitReset) {
|
|
556
|
-
console.log(pc5.dim(` Rate limit \u5C06\u5728 ${result.rateLimitReset.toLocaleString()} \u91CD\u7F6E`));
|
|
557
|
-
}
|
|
558
|
-
return false;
|
|
559
|
-
}
|
|
560
|
-
const user = result.data;
|
|
561
|
-
console.log(pc5.green(`\u2714 Token \u6709\u6548\uFF0C\u5DF2\u767B\u5F55\u4E3A: ${user.login}${user.name ? ` (${user.name})` : ""}`));
|
|
562
|
-
console.log();
|
|
563
|
-
const setOrg = await confirm2({
|
|
564
|
-
message: "\u662F\u5426\u8BBE\u7F6E\u9ED8\u8BA4\u7EC4\u7EC7? (\u5426\u5219\u4ED3\u5E93\u5C06\u521B\u5EFA\u5728\u4E2A\u4EBA\u8D26\u6237\u4E0B)",
|
|
565
|
-
default: false
|
|
566
|
-
});
|
|
567
|
-
let defaultOrg;
|
|
568
|
-
if (setOrg) {
|
|
569
|
-
defaultOrg = await input2({
|
|
570
|
-
message: "\u9ED8\u8BA4\u7EC4\u7EC7\u540D\u79F0:",
|
|
590
|
+
try {
|
|
591
|
+
const token = await input2({
|
|
592
|
+
message: "\u8BF7\u8F93\u5165 GitHub Token:",
|
|
571
593
|
validate: (value) => {
|
|
572
594
|
if (!value.trim()) {
|
|
573
|
-
return "\
|
|
595
|
+
return "Token \u4E0D\u80FD\u4E3A\u7A7A";
|
|
596
|
+
}
|
|
597
|
+
if (!value.startsWith("ghp_") && !value.startsWith("github_pat_")) {
|
|
598
|
+
return "Token \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5E94\u4EE5 ghp_ \u6216 github_pat_ \u5F00\u5934";
|
|
574
599
|
}
|
|
575
600
|
return true;
|
|
576
601
|
}
|
|
577
602
|
});
|
|
578
|
-
|
|
603
|
+
console.log();
|
|
604
|
+
console.log(pc5.dim("\u6B63\u5728\u9A8C\u8BC1 Token..."));
|
|
605
|
+
const result = await validateToken(token.trim());
|
|
606
|
+
if (!result.success) {
|
|
607
|
+
console.log(pc5.red(`\u2717 Token \u9A8C\u8BC1\u5931\u8D25: ${result.error}`));
|
|
608
|
+
if (result.rateLimitReset) {
|
|
609
|
+
console.log(pc5.dim(` Rate limit \u5C06\u5728 ${result.rateLimitReset.toLocaleString()} \u91CD\u7F6E`));
|
|
610
|
+
}
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
const user = result.data;
|
|
614
|
+
console.log(pc5.green(`\u2714 Token \u6709\u6548\uFF0C\u5DF2\u767B\u5F55\u4E3A: ${user.login}${user.name ? ` (${user.name})` : ""}`));
|
|
615
|
+
console.log();
|
|
616
|
+
const setOrg = await confirm2({
|
|
617
|
+
message: "\u662F\u5426\u8BBE\u7F6E\u9ED8\u8BA4\u7EC4\u7EC7? (\u5426\u5219\u4ED3\u5E93\u5C06\u521B\u5EFA\u5728\u4E2A\u4EBA\u8D26\u6237\u4E0B)",
|
|
618
|
+
default: false
|
|
619
|
+
});
|
|
620
|
+
let defaultOrg;
|
|
621
|
+
if (setOrg) {
|
|
622
|
+
defaultOrg = await input2({
|
|
623
|
+
message: "\u9ED8\u8BA4\u7EC4\u7EC7\u540D\u79F0:",
|
|
624
|
+
validate: (value) => {
|
|
625
|
+
if (!value.trim()) {
|
|
626
|
+
return "\u7EC4\u7EC7\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
|
|
627
|
+
}
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
defaultOrg = defaultOrg.trim();
|
|
632
|
+
}
|
|
633
|
+
const config = loadConfig();
|
|
634
|
+
config.github = {
|
|
635
|
+
token: token.trim(),
|
|
636
|
+
...defaultOrg && { defaultOrg }
|
|
637
|
+
};
|
|
638
|
+
saveConfig(config);
|
|
639
|
+
console.log();
|
|
640
|
+
console.log(pc5.green("\u2714 GitHub \u914D\u7F6E\u5DF2\u4FDD\u5B58"));
|
|
641
|
+
console.log(pc5.dim(" \u914D\u7F6E\u6587\u4EF6\u5DF2\u8BBE\u7F6E\u4E3A\u4EC5\u5F53\u524D\u7528\u6237\u53EF\u8BFB"));
|
|
642
|
+
return true;
|
|
643
|
+
} catch (err) {
|
|
644
|
+
if (isUserCancelled(err)) {
|
|
645
|
+
console.log(pc5.yellow("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
throw err;
|
|
579
649
|
}
|
|
580
|
-
const config = loadConfig();
|
|
581
|
-
config.github = {
|
|
582
|
-
token: token.trim(),
|
|
583
|
-
...defaultOrg && { defaultOrg }
|
|
584
|
-
};
|
|
585
|
-
saveConfig(config);
|
|
586
|
-
console.log();
|
|
587
|
-
console.log(pc5.green("\u2714 GitHub \u914D\u7F6E\u5DF2\u4FDD\u5B58"));
|
|
588
|
-
console.log(pc5.dim(" \u914D\u7F6E\u6587\u4EF6\u5DF2\u8BBE\u7F6E\u4E3A\u4EC5\u5F53\u524D\u7528\u6237\u53EF\u8BFB"));
|
|
589
|
-
return true;
|
|
590
650
|
}
|
|
591
651
|
function showConfig() {
|
|
592
652
|
const config = loadConfig();
|
|
@@ -635,13 +695,36 @@ async function createCli() {
|
|
|
635
695
|
const projectOptions = await runPrompts(projectName, options, userConfig);
|
|
636
696
|
await executeProject(projectOptions);
|
|
637
697
|
} catch (err) {
|
|
638
|
-
|
|
698
|
+
const error = err;
|
|
699
|
+
if (error.message === "PROMPT_CANCELLED" || error.name === "ExitPromptError" || error.message.includes("User force closed")) {
|
|
639
700
|
console.log(pc6.yellow("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
|
|
640
701
|
process.exit(0);
|
|
641
702
|
}
|
|
642
703
|
throw err;
|
|
643
704
|
}
|
|
644
705
|
});
|
|
706
|
+
program.command("list").description("\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u677F").action(() => {
|
|
707
|
+
const templatesDir = getTemplatesDir();
|
|
708
|
+
const registryPath = path7.join(templatesDir, "template.config.json");
|
|
709
|
+
const registry = JSON.parse(
|
|
710
|
+
fs5.readFileSync(registryPath, "utf-8")
|
|
711
|
+
);
|
|
712
|
+
const singleTemplates = registry.templates.filter((t) => t.category !== "fullstack");
|
|
713
|
+
const fullstackTemplates = registry.templates.filter((t) => t.category === "fullstack");
|
|
714
|
+
console.log();
|
|
715
|
+
console.log(pc6.cyan(" \u5355\u4F53\u9879\u76EE:"));
|
|
716
|
+
for (const t of singleTemplates) {
|
|
717
|
+
console.log(` ${pc6.green(t.name.padEnd(24))} ${pc6.dim(t.displayName)}`);
|
|
718
|
+
}
|
|
719
|
+
if (fullstackTemplates.length > 0) {
|
|
720
|
+
console.log();
|
|
721
|
+
console.log(pc6.cyan(" \u524D\u540E\u7AEF\u5206\u79BB:"));
|
|
722
|
+
for (const t of fullstackTemplates) {
|
|
723
|
+
console.log(` ${pc6.green(t.name.padEnd(24))} ${pc6.dim(t.displayName)}`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
console.log();
|
|
727
|
+
});
|
|
645
728
|
program.command("config").description("\u7BA1\u7406\u914D\u7F6E").option("--setup-github", "\u914D\u7F6E GitHub Token").option("--show", "\u663E\u793A\u5F53\u524D\u914D\u7F6E").option("--path", "\u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
|
|
646
729
|
if (options.setupGithub) {
|
|
647
730
|
const success = await runGitHubSetup();
|
|
@@ -665,9 +748,14 @@ async function createCli() {
|
|
|
665
748
|
async function executeProject(options) {
|
|
666
749
|
const templateConfig = await scaffoldProject(options);
|
|
667
750
|
console.log(pc6.green("\u2714 \u9879\u76EE\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
668
|
-
if (!options.noInstall && templateConfig
|
|
669
|
-
|
|
670
|
-
|
|
751
|
+
if (!options.noInstall && templateConfig) {
|
|
752
|
+
if (templateConfig.type === "workspace") {
|
|
753
|
+
await runWorkspacePostInit(options.targetDir, templateConfig);
|
|
754
|
+
console.log(pc6.green("\u2714 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210"));
|
|
755
|
+
} else if (templateConfig.postInit) {
|
|
756
|
+
await runPostInit(options.targetDir, templateConfig.postInit);
|
|
757
|
+
console.log(pc6.green("\u2714 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210"));
|
|
758
|
+
}
|
|
671
759
|
}
|
|
672
760
|
if (options.initGit) {
|
|
673
761
|
await initGit(options.targetDir);
|
|
@@ -686,12 +774,25 @@ async function executeProject(options) {
|
|
|
686
774
|
console.log();
|
|
687
775
|
const pm = templateConfig?.packageManager ?? "pnpm";
|
|
688
776
|
const cdCmd = options.targetDir !== process.cwd() ? `cd ${options.projectName} && ` : "";
|
|
689
|
-
|
|
777
|
+
if (templateConfig?.type === "workspace") {
|
|
778
|
+
if (pm === "pnpm") {
|
|
779
|
+
console.log(pc6.dim(` ${cdCmd}pnpm dev`));
|
|
780
|
+
} else {
|
|
781
|
+
console.log(pc6.dim(` ${cdCmd}make dev`));
|
|
782
|
+
}
|
|
783
|
+
} else if (pm === "maven") {
|
|
784
|
+
console.log(pc6.dim(` ${cdCmd}./mvnw spring-boot:run`));
|
|
785
|
+
} else if (pm === "gradle") {
|
|
786
|
+
console.log(pc6.dim(` ${cdCmd}./gradlew bootRun`));
|
|
787
|
+
} else {
|
|
788
|
+
console.log(pc6.dim(` ${cdCmd}${pm} dev`));
|
|
789
|
+
}
|
|
690
790
|
console.log();
|
|
691
791
|
}
|
|
692
792
|
|
|
693
793
|
// src/index.ts
|
|
694
794
|
async function main() {
|
|
795
|
+
ensureConfigExists();
|
|
695
796
|
const program = await createCli();
|
|
696
797
|
await program.parseAsync(process.argv);
|
|
697
798
|
}
|