cf-yoyo 1.0.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/.eslintrc.json +28 -0
- package/.github/workflows/ci.yml +96 -0
- package/.prettierrc.json +10 -0
- package/CHANGELOG.md +55 -0
- package/README.md +138 -0
- package/__tests__/cli-e2e.test.ts +145 -0
- package/__tests__/config.test.ts +268 -0
- package/__tests__/filesystem.test.ts +453 -0
- package/__tests__/logger.test.ts +274 -0
- package/__tests__/template-engine.test.ts +450 -0
- package/__tests__/types.test.ts +25 -0
- package/deep_todos.md +766 -0
- package/dist/cli/commands/create.d.ts +26 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +308 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/git.d.ts +10 -0
- package/dist/cli/commands/git.d.ts.map +1 -0
- package/dist/cli/commands/git.js +887 -0
- package/dist/cli/commands/git.js.map +1 -0
- package/dist/cli/commands/list.d.ts +10 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +90 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/index.d.ts +15 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +62 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/config.d.ts +35 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +260 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/filesystem.d.ts +84 -0
- package/dist/core/filesystem.d.ts.map +1 -0
- package/dist/core/filesystem.js +417 -0
- package/dist/core/filesystem.js.map +1 -0
- package/dist/core/git-token.d.ts +81 -0
- package/dist/core/git-token.d.ts.map +1 -0
- package/dist/core/git-token.js +244 -0
- package/dist/core/git-token.js.map +1 -0
- package/dist/core/git.d.ts +70 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +367 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/prompt.d.ts +28 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +253 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/template-engine.d.ts +52 -0
- package/dist/core/template-engine.d.ts.map +1 -0
- package/dist/core/template-engine.js +308 -0
- package/dist/core/template-engine.js.map +1 -0
- package/dist/core/template-manager.d.ts +54 -0
- package/dist/core/template-manager.d.ts.map +1 -0
- package/dist/core/template-manager.js +330 -0
- package/dist/core/template-manager.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +244 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +51 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +68 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +140 -0
- package/dist/utils/logger.js.map +1 -0
- package/memory.md +241 -0
- package/need-debug.md +395 -0
- package/package.json +42 -0
- package/src/cli/commands/create.ts +326 -0
- package/src/cli/commands/git.ts +1001 -0
- package/src/cli/commands/list.ts +97 -0
- package/src/cli/index.ts +71 -0
- package/src/core/config.ts +262 -0
- package/src/core/filesystem.ts +408 -0
- package/src/core/git-token.ts +248 -0
- package/src/core/git.ts +384 -0
- package/src/core/prompt.ts +345 -0
- package/src/core/template-engine.ts +324 -0
- package/src/core/template-manager.ts +338 -0
- package/src/index.ts +19 -0
- package/src/types/index.ts +259 -0
- package/src/utils/logger.ts +150 -0
- package/templates/pages/basic/README.md.mustache +63 -0
- package/templates/pages/basic/package.json.mustache +23 -0
- package/templates/pages/basic/public/css/style.css +199 -0
- package/templates/pages/basic/public/index.html.mustache +72 -0
- package/templates/pages/basic/public/js/main.js +103 -0
- package/templates/pages/basic/template.json +38 -0
- package/templates/pages/basic/tsconfig.json +21 -0
- package/templates/pages/basic/wrangler.toml.mustache +14 -0
- package/templates/pages/basic-js/README.md.mustache +62 -0
- package/templates/pages/basic-js/package.json.mustache +25 -0
- package/templates/pages/basic-js/public/css/style.css +212 -0
- package/templates/pages/basic-js/public/index.html.mustache +53 -0
- package/templates/pages/basic-js/public/js/main.js +134 -0
- package/templates/pages/basic-js/template.json +35 -0
- package/templates/pages/basic-js/wrangler.toml.mustache +14 -0
- package/templates/pages/react/README.md.mustache +97 -0
- package/templates/pages/react/index.html.mustache +14 -0
- package/templates/pages/react/package.json.mustache +34 -0
- package/templates/pages/react/src/App.css +168 -0
- package/templates/pages/react/src/App.tsx.mustache +62 -0
- package/templates/pages/react/src/index.css +53 -0
- package/templates/pages/react/src/main.tsx.mustache +10 -0
- package/templates/pages/react/src/vite-env.d.ts +1 -0
- package/templates/pages/react/template.json +54 -0
- package/templates/pages/react/tsconfig.json +21 -0
- package/templates/pages/react/tsconfig.node.json +10 -0
- package/templates/pages/react/vite.config.ts +16 -0
- package/templates/worker/basic/README.md.mustache +56 -0
- package/templates/worker/basic/package.json.mustache +29 -0
- package/templates/worker/basic/src/index.ts.mustache +125 -0
- package/templates/worker/basic/template.json +30 -0
- package/templates/worker/basic/tsconfig.json +24 -0
- package/templates/worker/basic/wrangler.toml.mustache +33 -0
- package/templates/worker/basic-js/README.md.mustache +55 -0
- package/templates/worker/basic-js/package.json.mustache +25 -0
- package/templates/worker/basic-js/src/index.js.mustache +146 -0
- package/templates/worker/basic-js/template.json +27 -0
- package/templates/worker/basic-js/wrangler.toml.mustache +33 -0
- package/templates/worker/hono/README.md.mustache +79 -0
- package/templates/worker/hono/package.json.mustache +33 -0
- package/templates/worker/hono/src/index.ts.mustache +64 -0
- package/templates/worker/hono/src/routes/index.ts.mustache +165 -0
- package/templates/worker/hono/template.json +34 -0
- package/templates/worker/hono/tsconfig.json +24 -0
- package/templates/worker/hono/wrangler.toml.mustache +36 -0
- package/templates/worker/hono-js/README.md.mustache +67 -0
- package/templates/worker/hono-js/package.json.mustache +29 -0
- package/templates/worker/hono-js/src/index.js.mustache +55 -0
- package/templates/worker/hono-js/src/routes/index.js.mustache +127 -0
- package/templates/worker/hono-js/template.json +31 -0
- package/templates/worker/hono-js/wrangler.toml.mustache +36 -0
- package/thoughts/ledgers/CONTINUITY_ses_287e.md +74 -0
- package/thoughts/ledgers/CONTINUITY_ses_28b5.md +85 -0
- package/tsconfig.json +30 -0
- package/vitest.config.ts +20 -0
- package//351/240/205/347/233/256/350/241/250.md +140 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"root": true,
|
|
3
|
+
"parser": "@typescript-eslint/parser",
|
|
4
|
+
"parserOptions": {
|
|
5
|
+
"ecmaVersion": 2022,
|
|
6
|
+
"sourceType": "module",
|
|
7
|
+
"project": "./tsconfig.json"
|
|
8
|
+
},
|
|
9
|
+
"plugins": ["@typescript-eslint"],
|
|
10
|
+
"extends": [
|
|
11
|
+
"eslint:recommended",
|
|
12
|
+
"plugin:@typescript-eslint/recommended",
|
|
13
|
+
"plugin:@typescript-eslint/recommended-requiring-type-checking"
|
|
14
|
+
],
|
|
15
|
+
"rules": {
|
|
16
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
17
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
18
|
+
"@typescript-eslint/explicit-function-return-type": "warn",
|
|
19
|
+
"@typescript-eslint/no-inferrable-types": "off",
|
|
20
|
+
"@typescript-eslint/no-non-null-assertion": "warn",
|
|
21
|
+
"prefer-const": "error",
|
|
22
|
+
"no-var": "error"
|
|
23
|
+
},
|
|
24
|
+
"env": {
|
|
25
|
+
"node": true,
|
|
26
|
+
"es6": true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# GitHub Actions CI/CD 配置
|
|
2
|
+
# 自動執行測試、類型檢查、建置
|
|
3
|
+
|
|
4
|
+
name: CI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main, develop]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main, develop]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
# 建置與測試
|
|
14
|
+
build-and-test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
node-version: [18.x, 20.x]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: 檢出代碼
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: 設置 Node.js ${{ matrix.node-version }}
|
|
26
|
+
uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: ${{ matrix.node-version }}
|
|
29
|
+
cache: 'npm'
|
|
30
|
+
|
|
31
|
+
- name: 安裝依賴
|
|
32
|
+
run: npm ci
|
|
33
|
+
|
|
34
|
+
- name: 類型檢查
|
|
35
|
+
run: npm run type-check
|
|
36
|
+
|
|
37
|
+
- name: 建置
|
|
38
|
+
run: npm run build
|
|
39
|
+
|
|
40
|
+
- name: 執行測試並生成覆蓋率報告
|
|
41
|
+
run: npm run test:coverage
|
|
42
|
+
|
|
43
|
+
- name: 上傳覆蓋率報告
|
|
44
|
+
uses: actions/upload-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: coverage-report-node-${{ matrix.node-version }}
|
|
47
|
+
path: coverage/
|
|
48
|
+
retention-days: 7
|
|
49
|
+
|
|
50
|
+
# 代碼品質檢查
|
|
51
|
+
lint:
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
|
|
54
|
+
steps:
|
|
55
|
+
- name: 檢出代碼
|
|
56
|
+
uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: 設置 Node.js
|
|
59
|
+
uses: actions/setup-node@v4
|
|
60
|
+
with:
|
|
61
|
+
node-version: '20.x'
|
|
62
|
+
cache: 'npm'
|
|
63
|
+
|
|
64
|
+
- name: 安裝依賴
|
|
65
|
+
run: npm ci
|
|
66
|
+
|
|
67
|
+
- name: 執行 ESLint
|
|
68
|
+
run: npm run lint
|
|
69
|
+
continue-on-error: true
|
|
70
|
+
|
|
71
|
+
# 發布到 npm(僅在 main 分支)
|
|
72
|
+
publish:
|
|
73
|
+
needs: [build-and-test, lint]
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
76
|
+
|
|
77
|
+
steps:
|
|
78
|
+
- name: 檢出代碼
|
|
79
|
+
uses: actions/checkout@v4
|
|
80
|
+
|
|
81
|
+
- name: 設置 Node.js
|
|
82
|
+
uses: actions/setup-node@v4
|
|
83
|
+
with:
|
|
84
|
+
node-version: '20.x'
|
|
85
|
+
registry-url: 'https://registry.npmjs.org'
|
|
86
|
+
|
|
87
|
+
- name: 安裝依賴
|
|
88
|
+
run: npm ci
|
|
89
|
+
|
|
90
|
+
- name: 建置
|
|
91
|
+
run: npm run build
|
|
92
|
+
|
|
93
|
+
- name: 發布到 npm
|
|
94
|
+
run: npm publish --access public
|
|
95
|
+
env:
|
|
96
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.prettierrc.json
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-04-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- 🚀 Initial release of cf-yoyo CLI tool
|
|
13
|
+
- 📝 Interactive project creation with inquirer prompts
|
|
14
|
+
- 📦 Support for multiple project templates:
|
|
15
|
+
- `worker` - Basic Cloudflare Worker
|
|
16
|
+
- `hono` - Worker with Hono framework
|
|
17
|
+
- `pages` - Cloudflare Pages static site
|
|
18
|
+
- `d1` - Worker with D1 database
|
|
19
|
+
- `kv` - Worker with KV storage
|
|
20
|
+
- `r2` - Worker with R2 storage
|
|
21
|
+
- 🔧 Built-in Git operations (init, push, clone)
|
|
22
|
+
- 📋 List command to view available templates
|
|
23
|
+
- 🎨 Template engine with variable substitution
|
|
24
|
+
- ⚙️ Configuration management system
|
|
25
|
+
- 📁 File system utilities
|
|
26
|
+
- 🔍 Comprehensive test suite (186 tests, 83% coverage)
|
|
27
|
+
- 🔄 CI/CD pipeline with GitHub Actions
|
|
28
|
+
|
|
29
|
+
### Technical Details
|
|
30
|
+
|
|
31
|
+
- TypeScript strict mode enabled
|
|
32
|
+
- Vitest testing framework
|
|
33
|
+
- ESLint + Prettier code quality tools
|
|
34
|
+
- Node.js 18+ support
|
|
35
|
+
- Commander.js CLI framework
|
|
36
|
+
- execa for process execution
|
|
37
|
+
|
|
38
|
+
### Test Coverage
|
|
39
|
+
|
|
40
|
+
| Metric | Coverage |
|
|
41
|
+
| ---------- | -------- |
|
|
42
|
+
| Statements | 83.58% |
|
|
43
|
+
| Functions | 98.03% |
|
|
44
|
+
| Branches | 79.05% |
|
|
45
|
+
| Lines | 83.48% |
|
|
46
|
+
|
|
47
|
+
## [Unreleased]
|
|
48
|
+
|
|
49
|
+
### Planned
|
|
50
|
+
|
|
51
|
+
- [ ] Additional project templates (DO, Queue, etc.)
|
|
52
|
+
- [ ] Template customization options
|
|
53
|
+
- [ ] Interactive template preview
|
|
54
|
+
- [ ] Project migration tools
|
|
55
|
+
- [ ] Cloudflare API integration
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# cf-yoyo
|
|
2
|
+
|
|
3
|
+
[](https://github.com/your-username/cf-yoyo/actions/workflows/ci.yml)
|
|
4
|
+
[](https://badge.fury.io/js/cf-yoyo)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](./coverage/)
|
|
7
|
+
|
|
8
|
+
Cloudflare 專案腳手架 CLI 工具 - 快速建立 Cloudflare Workers、Pages 等專案
|
|
9
|
+
|
|
10
|
+
## 功能特色
|
|
11
|
+
|
|
12
|
+
- 🚀 快速建立 Cloudflare 專案
|
|
13
|
+
- 📝 互動式問答流程
|
|
14
|
+
- 📦 支援多種專案模板
|
|
15
|
+
- ⚡ 支援 Workers、Pages、D1、KV、R2 等服務
|
|
16
|
+
- 🔧 內建 Git 操作功能
|
|
17
|
+
|
|
18
|
+
## 安裝使用
|
|
19
|
+
|
|
20
|
+
### 全域安裝
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g cf-yoyo
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 使用 npx(推薦)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx cf-yoyo create my-project
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 快速開始
|
|
33
|
+
|
|
34
|
+
### 建立新專案
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 互動式建立
|
|
38
|
+
npx cf-yoyo create
|
|
39
|
+
|
|
40
|
+
# 指定專案名稱
|
|
41
|
+
npx cf-yoyo create my-worker
|
|
42
|
+
|
|
43
|
+
# 使用特定模板
|
|
44
|
+
npx cf-yoyo create my-app --template pages
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Git 相關操作
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# 初始化 Git 倉庫
|
|
51
|
+
npx cf-yoyo git init
|
|
52
|
+
|
|
53
|
+
# 推送到遠端倉庫
|
|
54
|
+
npx cf-yoyo git push
|
|
55
|
+
|
|
56
|
+
# 克隆遠端倉庫
|
|
57
|
+
npx cf-yoyo git clone <repository-url>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 查看可用模板
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx cf-yoyo list
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 可用模板
|
|
67
|
+
|
|
68
|
+
- `worker` - 基礎 Cloudflare Worker
|
|
69
|
+
- `hono` - 使用 Hono 框架的 Worker
|
|
70
|
+
- `pages` - Cloudflare Pages 靜態網站
|
|
71
|
+
- `d1` - 包含 D1 資料庫的 Worker
|
|
72
|
+
- `kv` - 包含 KV 存儲的 Worker
|
|
73
|
+
- `r2` - 包含 R2 存儲的 Worker
|
|
74
|
+
|
|
75
|
+
## 開發
|
|
76
|
+
|
|
77
|
+
### 前置需求
|
|
78
|
+
|
|
79
|
+
- Node.js >= 18.0.0
|
|
80
|
+
- npm
|
|
81
|
+
- Git(用於 Git 相關功能)
|
|
82
|
+
|
|
83
|
+
### 設置開發環境
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# 安裝依賴
|
|
87
|
+
npm install
|
|
88
|
+
|
|
89
|
+
# 開發模式
|
|
90
|
+
npm run dev
|
|
91
|
+
|
|
92
|
+
# 建置專案
|
|
93
|
+
npm run build
|
|
94
|
+
|
|
95
|
+
# 執行類型檢查
|
|
96
|
+
npm run type-check
|
|
97
|
+
|
|
98
|
+
# 格式化代碼
|
|
99
|
+
npm run format
|
|
100
|
+
|
|
101
|
+
# 執行 Lint
|
|
102
|
+
npm run lint
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 專案結構
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
src/
|
|
109
|
+
├── index.ts # CLI 入口
|
|
110
|
+
├── commands/ # 命令模組
|
|
111
|
+
│ ├── create.ts # create 命令
|
|
112
|
+
│ ├── list.ts # list 命令
|
|
113
|
+
│ └── git.ts # git 命令組
|
|
114
|
+
├── core/ # 核心功能
|
|
115
|
+
│ ├── config.ts # 配置管理
|
|
116
|
+
│ ├── filesystem.ts # 檔案系統操作
|
|
117
|
+
│ ├── git.ts # Git 操作
|
|
118
|
+
│ ├── prompt.ts # 互動問答
|
|
119
|
+
│ ├── template-engine.ts # 模板引擎
|
|
120
|
+
│ └── template-manager.ts # 模板管理
|
|
121
|
+
├── utils/ # 工具函式
|
|
122
|
+
│ └── logger.ts # 日誌工具
|
|
123
|
+
└── types/ # TypeScript 類型
|
|
124
|
+
└── index.ts # 類型定義
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 技術棧
|
|
128
|
+
|
|
129
|
+
- [Commander.js](https://github.com/tj/commander.js) - CLI 框架
|
|
130
|
+
- [Inquirer.js](https://github.com/SBoudrias/Inquirer.js) - 互動式問答
|
|
131
|
+
- [TypeScript](https://www.typescriptlang.org/) - 型別系統
|
|
132
|
+
- [ESLint](https://eslint.org/) - 代碼檢查
|
|
133
|
+
- [Prettier](https://prettier.io/) - 代碼格式化
|
|
134
|
+
- [execa](https://github.com/sindresorhus/execa) - 進程執行
|
|
135
|
+
|
|
136
|
+
## 授權
|
|
137
|
+
|
|
138
|
+
MIT License
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI E2E 整合測試
|
|
3
|
+
* 測試 CLI 命令行執行的完整流程
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
7
|
+
import { execa } from 'execa';
|
|
8
|
+
import { existsSync, rmSync, mkdirSync, readFileSync } from 'fs';
|
|
9
|
+
import { join, resolve } from 'path';
|
|
10
|
+
|
|
11
|
+
// 測試用的臨時目錄
|
|
12
|
+
const TEST_DIR = resolve(__dirname, '__e2e_test_temp__');
|
|
13
|
+
const CLI_PATH = resolve(__dirname, '../dist/index.js');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 執行 CLI 命令
|
|
17
|
+
*/
|
|
18
|
+
async function runCLI(args: string[], options: { cwd?: string; input?: string } = {}) {
|
|
19
|
+
try {
|
|
20
|
+
const result = await execa('node', [CLI_PATH, ...args], {
|
|
21
|
+
cwd: options.cwd || process.cwd(),
|
|
22
|
+
input: options.input,
|
|
23
|
+
timeout: 10000,
|
|
24
|
+
});
|
|
25
|
+
return { success: true, stdout: result.stdout, stderr: result.stderr };
|
|
26
|
+
} catch (error: unknown) {
|
|
27
|
+
const err = error as { stdout?: string; stderr?: string; message?: string };
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
stdout: err.stdout || '',
|
|
31
|
+
stderr: err.stderr || err.message || '',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('CLI E2E Tests', () => {
|
|
37
|
+
beforeAll(() => {
|
|
38
|
+
// 確保 CLI 已建置
|
|
39
|
+
if (!existsSync(CLI_PATH)) {
|
|
40
|
+
throw new Error('CLI 尚未建置,請先執行 npm run build');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 創建測試目錄
|
|
44
|
+
if (!existsSync(TEST_DIR)) {
|
|
45
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
afterAll(() => {
|
|
50
|
+
// 清理測試目錄
|
|
51
|
+
if (existsSync(TEST_DIR)) {
|
|
52
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('CLI 基本命令', () => {
|
|
57
|
+
it('應該顯示版本信息', async () => {
|
|
58
|
+
const result = await runCLI(['--version']);
|
|
59
|
+
expect(result.success).toBe(true);
|
|
60
|
+
expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('應該顯示幫助信息', async () => {
|
|
64
|
+
const result = await runCLI(['--help']);
|
|
65
|
+
expect(result.success).toBe(true);
|
|
66
|
+
expect(result.stdout).toContain('cf-yoyo');
|
|
67
|
+
expect(result.stdout).toContain('Cloudflare');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('應該在無參數時顯示幫助', async () => {
|
|
71
|
+
const result = await runCLI([]);
|
|
72
|
+
expect(result.success).toBe(true);
|
|
73
|
+
expect(result.stdout).toContain('使用範例');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('list 命令', () => {
|
|
78
|
+
it('應該列出所有可用模板', async () => {
|
|
79
|
+
const result = await runCLI(['list']);
|
|
80
|
+
expect(result.success).toBe(true);
|
|
81
|
+
expect(result.stdout).toContain('可用的專案模板');
|
|
82
|
+
expect(result.stdout).toContain('Worker');
|
|
83
|
+
expect(result.stdout).toContain('Pages');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('應該根據類型過濾模板', async () => {
|
|
87
|
+
const result = await runCLI(['list', '--type', 'worker']);
|
|
88
|
+
expect(result.success).toBe(true);
|
|
89
|
+
expect(result.stdout).toContain('Worker');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('應該處理無效的類型過濾', async () => {
|
|
93
|
+
const result = await runCLI(['list', '--type', 'invalid-type']);
|
|
94
|
+
expect(result.success).toBe(true);
|
|
95
|
+
expect(result.stdout).toContain('找不到符合類型');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('create 命令', () => {
|
|
100
|
+
it('應該顯示 create 幫助信息', async () => {
|
|
101
|
+
const result = await runCLI(['create', '--help']);
|
|
102
|
+
expect(result.success).toBe(true);
|
|
103
|
+
expect(result.stdout).toContain('建立新的 Cloudflare 專案');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// 注意:完整 create 流程需要互動式輸入,此處僅測試命令行選項解析
|
|
107
|
+
it('應該接受 create 命令的選項', async () => {
|
|
108
|
+
const result = await runCLI(['create', '--help']);
|
|
109
|
+
expect(result.success).toBe(true);
|
|
110
|
+
expect(result.stdout).toContain('--template');
|
|
111
|
+
expect(result.stdout).toContain('--type');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('git 命令', () => {
|
|
116
|
+
it('應該顯示 git 幫助信息', async () => {
|
|
117
|
+
const result = await runCLI(['git', '--help']);
|
|
118
|
+
expect(result.success).toBe(true);
|
|
119
|
+
expect(result.stdout).toContain('Git 相關操作');
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('CLI 錯誤處理', () => {
|
|
125
|
+
it('應該處理不存在的命令', async () => {
|
|
126
|
+
const result = await runCLI(['nonexistent-command']);
|
|
127
|
+
expect(result.success).toBe(false);
|
|
128
|
+
expect(result.stderr).toContain('error');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe('CLI 整合流程', () => {
|
|
133
|
+
it('應該正確初始化 CLI 程序', async () => {
|
|
134
|
+
// 測試 CLI 入口是否正確導入所有模組
|
|
135
|
+
const result = await runCLI(['--version']);
|
|
136
|
+
expect(result.success).toBe(true);
|
|
137
|
+
expect(result.stderr).toBe('');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('應該支援完整的命令行參數解析', async () => {
|
|
141
|
+
const result = await runCLI(['list', '--type', 'pages']);
|
|
142
|
+
expect(result.success).toBe(true);
|
|
143
|
+
expect(result.stdout).toContain('Pages');
|
|
144
|
+
});
|
|
145
|
+
});
|