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
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Git Token 管理模組
|
|
4
|
+
* 負責管理私人倉庫推送所需的 Git Token
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.getTokenConfigPath = getTokenConfigPath;
|
|
41
|
+
exports.loadTokens = loadTokens;
|
|
42
|
+
exports.saveTokens = saveTokens;
|
|
43
|
+
exports.addToken = addToken;
|
|
44
|
+
exports.deleteToken = deleteToken;
|
|
45
|
+
exports.updateToken = updateToken;
|
|
46
|
+
exports.updateTokenName = updateTokenName;
|
|
47
|
+
exports.selectToken = selectToken;
|
|
48
|
+
exports.getTokenList = getTokenList;
|
|
49
|
+
const fs_1 = require("fs");
|
|
50
|
+
const path_1 = require("path");
|
|
51
|
+
const os_1 = require("os");
|
|
52
|
+
const uuid_1 = require("uuid");
|
|
53
|
+
const logger_1 = require("../utils/logger");
|
|
54
|
+
/**
|
|
55
|
+
* 獲取配置檔路徑
|
|
56
|
+
* 路徑:~/.config/cf-yoyo/git-token.json(跨平台)
|
|
57
|
+
* 使用 os.homedir() 確保在 Windows、macOS、Linux 上都能正確獲取用戶目錄
|
|
58
|
+
*/
|
|
59
|
+
function getTokenConfigPath() {
|
|
60
|
+
const userHome = (0, os_1.homedir)();
|
|
61
|
+
if (!userHome) {
|
|
62
|
+
throw new Error('無法獲取用戶目錄路徑');
|
|
63
|
+
}
|
|
64
|
+
const configDir = (0, path_1.join)(userHome, '.config', 'cf-yoyo');
|
|
65
|
+
const configPath = (0, path_1.join)(configDir, 'git-token.json');
|
|
66
|
+
return configPath;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 確保配置目錄存在
|
|
70
|
+
*/
|
|
71
|
+
function ensureConfigDir() {
|
|
72
|
+
const configPath = getTokenConfigPath();
|
|
73
|
+
const configDir = (0, path_1.join)(configPath, '..');
|
|
74
|
+
if (!(0, fs_1.existsSync)(configDir)) {
|
|
75
|
+
(0, fs_1.mkdirSync)(configDir, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 載入已存 Token
|
|
80
|
+
* @returns GitTokenConfig 配置對象
|
|
81
|
+
*/
|
|
82
|
+
function loadTokens() {
|
|
83
|
+
const configPath = getTokenConfigPath();
|
|
84
|
+
if (!(0, fs_1.existsSync)(configPath)) {
|
|
85
|
+
return { tokens: [] };
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
|
|
89
|
+
const config = JSON.parse(content);
|
|
90
|
+
return config;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
logger_1.logger.warn('讀取 Token 配置失敗,返回空配置');
|
|
94
|
+
return { tokens: [] };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 保存 Token 配置
|
|
99
|
+
* @param tokens Token 配置對象
|
|
100
|
+
*/
|
|
101
|
+
function saveTokens(tokens) {
|
|
102
|
+
ensureConfigDir();
|
|
103
|
+
const configPath = getTokenConfigPath();
|
|
104
|
+
(0, fs_1.writeFileSync)(configPath, JSON.stringify(tokens, null, 2), 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 新增 Token
|
|
108
|
+
* @param name Token 名稱
|
|
109
|
+
* @param token Token 值
|
|
110
|
+
* @returns 新增的 GitToken 對象
|
|
111
|
+
*/
|
|
112
|
+
function addToken(name, token) {
|
|
113
|
+
const config = loadTokens();
|
|
114
|
+
const newToken = {
|
|
115
|
+
id: (0, uuid_1.v4)(),
|
|
116
|
+
name,
|
|
117
|
+
token,
|
|
118
|
+
createdAt: new Date().toISOString(),
|
|
119
|
+
};
|
|
120
|
+
config.tokens.push(newToken);
|
|
121
|
+
saveTokens(config);
|
|
122
|
+
return newToken;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 刪除 Token
|
|
126
|
+
* @param id Token ID
|
|
127
|
+
* @returns 是否刪除成功
|
|
128
|
+
*/
|
|
129
|
+
function deleteToken(id) {
|
|
130
|
+
const config = loadTokens();
|
|
131
|
+
const initialLength = config.tokens.length;
|
|
132
|
+
config.tokens = config.tokens.filter((tokenItem) => tokenItem.id !== id);
|
|
133
|
+
if (config.tokens.length < initialLength) {
|
|
134
|
+
saveTokens(config);
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 更新 Token
|
|
141
|
+
* @param id Token ID
|
|
142
|
+
* @param name Token 名稱
|
|
143
|
+
* @param token Token 值
|
|
144
|
+
* @returns 是否更新成功
|
|
145
|
+
*/
|
|
146
|
+
function updateToken(id, name, token) {
|
|
147
|
+
const config = loadTokens();
|
|
148
|
+
const tokenIndex = config.tokens.findIndex((tokenItem) => tokenItem.id === id);
|
|
149
|
+
if (tokenIndex === -1) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
const existingToken = config.tokens[tokenIndex];
|
|
153
|
+
if (!existingToken) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
config.tokens[tokenIndex] = {
|
|
157
|
+
...existingToken,
|
|
158
|
+
name,
|
|
159
|
+
token,
|
|
160
|
+
};
|
|
161
|
+
saveTokens(config);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 更新 Token 名稱
|
|
166
|
+
* @param id Token ID
|
|
167
|
+
* @param name 新名稱
|
|
168
|
+
* @returns 是否更新成功
|
|
169
|
+
*/
|
|
170
|
+
function updateTokenName(id, name) {
|
|
171
|
+
const config = loadTokens();
|
|
172
|
+
const tokenIndex = config.tokens.findIndex((tokenItem) => tokenItem.id === id);
|
|
173
|
+
if (tokenIndex === -1) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
const existingToken = config.tokens[tokenIndex];
|
|
177
|
+
if (!existingToken) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
existingToken.name = name;
|
|
181
|
+
saveTokens(config);
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 選擇 Token(互動式)
|
|
186
|
+
* 根據不同情況返回對應的 Token
|
|
187
|
+
* - 若無 Token:返回 null
|
|
188
|
+
* - 若有 1 個 Token:返回該 Token
|
|
189
|
+
* - 若有 2+ 個 Token:讓用戶選擇
|
|
190
|
+
* @returns 選擇的 GitToken 或 null
|
|
191
|
+
*/
|
|
192
|
+
async function selectToken() {
|
|
193
|
+
const config = loadTokens();
|
|
194
|
+
// 若無 Token
|
|
195
|
+
if (config.tokens.length === 0) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
// 若只有 1 個 Token
|
|
199
|
+
if (config.tokens.length === 1) {
|
|
200
|
+
const firstToken = config.tokens[0];
|
|
201
|
+
if (!firstToken) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
return firstToken;
|
|
205
|
+
}
|
|
206
|
+
// 若有多個 Token,讓用戶選擇
|
|
207
|
+
const { selectedToken } = await Promise.resolve().then(() => __importStar(require('inquirer'))).then((mod) => mod.default.prompt([
|
|
208
|
+
{
|
|
209
|
+
type: 'list',
|
|
210
|
+
name: 'selectedToken',
|
|
211
|
+
message: '選擇要使用的 Git Token:',
|
|
212
|
+
choices: [
|
|
213
|
+
...config.tokens.map((tokenItem) => ({
|
|
214
|
+
name: tokenItem.name,
|
|
215
|
+
value: tokenItem.id,
|
|
216
|
+
})),
|
|
217
|
+
{
|
|
218
|
+
name: '❌ 退出',
|
|
219
|
+
value: 'exit',
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
},
|
|
223
|
+
]));
|
|
224
|
+
if (selectedToken === 'exit') {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const selectedTokenItem = config.tokens.find((tokenItem) => tokenItem.id === selectedToken);
|
|
228
|
+
if (!selectedTokenItem) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
return selectedTokenItem;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* 獲取所有 Token 名稱列表(用於顯示,不顯示 Token 值)
|
|
235
|
+
*/
|
|
236
|
+
function getTokenList() {
|
|
237
|
+
const config = loadTokens();
|
|
238
|
+
return config.tokens.map((tokenItem) => ({
|
|
239
|
+
id: tokenItem.id,
|
|
240
|
+
name: tokenItem.name,
|
|
241
|
+
createdAt: tokenItem.createdAt,
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=git-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-token.js","sourceRoot":"","sources":["../../src/core/git-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git 操作核心功能模組
|
|
3
|
+
* 負責執行 Git 相關操作(init、push、clone 等)
|
|
4
|
+
*/
|
|
5
|
+
import { GitResult } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* 檢查是否為 Git 倉庫
|
|
8
|
+
* @param cwd 工作目錄
|
|
9
|
+
*/
|
|
10
|
+
export declare function isGitRepository(cwd?: string): Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* 初始化 Git 倉庫
|
|
13
|
+
* @param cwd 工作目錄
|
|
14
|
+
*/
|
|
15
|
+
export declare function gitInit(cwd?: string): Promise<GitResult>;
|
|
16
|
+
/**
|
|
17
|
+
* 建立 .gitignore 檔案(若不存在)
|
|
18
|
+
* @param cwd 工作目錄
|
|
19
|
+
*/
|
|
20
|
+
export declare function createGitignore(cwd?: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Git 提交
|
|
23
|
+
* @param message 提交信息
|
|
24
|
+
* @param cwd 工作目錄
|
|
25
|
+
*/
|
|
26
|
+
export declare function gitCommit(message: string, cwd?: string): Promise<GitResult>;
|
|
27
|
+
/**
|
|
28
|
+
* 添加 Git remote
|
|
29
|
+
* @param remoteName remote 名稱
|
|
30
|
+
* @param url remote URL
|
|
31
|
+
* @param cwd 工作目錄
|
|
32
|
+
*/
|
|
33
|
+
export declare function gitAddRemote(remoteName: string, url: string, cwd?: string): Promise<GitResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Git push
|
|
36
|
+
* @param remote remote 名稱
|
|
37
|
+
* @param branch 分支名稱
|
|
38
|
+
* @param cwd 工作目錄
|
|
39
|
+
* @param token Git Token(可選,若提供則使用 Token 認證)
|
|
40
|
+
*/
|
|
41
|
+
export declare function gitPush(remote: string, branch: string, cwd?: string, token?: string): Promise<GitResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Git clone
|
|
44
|
+
* @param url 倉庫 URL
|
|
45
|
+
* @param directory 目標目錄
|
|
46
|
+
* @param token Git Token(可選,若提供則使用 Token 認證)
|
|
47
|
+
*/
|
|
48
|
+
export declare function gitClone(url: string, directory?: string, token?: string): Promise<GitResult>;
|
|
49
|
+
/**
|
|
50
|
+
* 獲取當前分支名稱
|
|
51
|
+
* @param cwd 工作目錄
|
|
52
|
+
*/
|
|
53
|
+
export declare function getCurrentBranch(cwd?: string): Promise<string | null>;
|
|
54
|
+
/**
|
|
55
|
+
* 獲取 remote 列表
|
|
56
|
+
* @param cwd 工作目錄
|
|
57
|
+
*/
|
|
58
|
+
export declare function getRemotes(cwd?: string): Promise<string[]>;
|
|
59
|
+
/**
|
|
60
|
+
* 設置 default branch
|
|
61
|
+
* @param branch 分支名稱
|
|
62
|
+
* @param cwd 工作目錄
|
|
63
|
+
*/
|
|
64
|
+
export declare function gitBranchM1(branch: string, cwd?: string): Promise<GitResult>;
|
|
65
|
+
/**
|
|
66
|
+
* 取消 Git 倉庫(刪除 .git 目錄)
|
|
67
|
+
* @param cwd 工作目錄
|
|
68
|
+
*/
|
|
69
|
+
export declare function removeGitRepo(cwd?: string): Promise<GitResult>;
|
|
70
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/core/git.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA8FrC;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGpE;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAa9D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CA+CrD;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAQjF;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,GAAG,CAAC,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,CAAC,CAoEpB;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,CAAC,CAUpB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ3E;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAShE;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAElF;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAyBpE"}
|
package/dist/core/git.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Git 操作核心功能模組
|
|
4
|
+
* 負責執行 Git 相關操作(init、push、clone 等)
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.isGitRepository = isGitRepository;
|
|
41
|
+
exports.gitInit = gitInit;
|
|
42
|
+
exports.createGitignore = createGitignore;
|
|
43
|
+
exports.gitCommit = gitCommit;
|
|
44
|
+
exports.gitAddRemote = gitAddRemote;
|
|
45
|
+
exports.gitPush = gitPush;
|
|
46
|
+
exports.gitClone = gitClone;
|
|
47
|
+
exports.getCurrentBranch = getCurrentBranch;
|
|
48
|
+
exports.getRemotes = getRemotes;
|
|
49
|
+
exports.gitBranchM1 = gitBranchM1;
|
|
50
|
+
exports.removeGitRepo = removeGitRepo;
|
|
51
|
+
const execa_1 = require("execa");
|
|
52
|
+
const fs_1 = require("fs");
|
|
53
|
+
const path_1 = require("path");
|
|
54
|
+
const git_token_1 = require("./git-token");
|
|
55
|
+
/**
|
|
56
|
+
* 檢查錯誤是否為 ExecaError
|
|
57
|
+
*/
|
|
58
|
+
function isExecaError(error) {
|
|
59
|
+
return error instanceof Error && 'stderr' in error;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 將 HTTPS URL 轉換為包含 Token 的格式
|
|
63
|
+
* 例如:https://github.com/user/repo.git -> https://<token>@github.com/user/repo.git
|
|
64
|
+
* @param url Git 倉庫 URL
|
|
65
|
+
* @param token Git Token
|
|
66
|
+
* @returns 包含 Token 的 URL
|
|
67
|
+
*/
|
|
68
|
+
function injectTokenToUrl(url, token) {
|
|
69
|
+
// 只處理 HTTPS URL
|
|
70
|
+
if (!url.startsWith('https://')) {
|
|
71
|
+
return url;
|
|
72
|
+
}
|
|
73
|
+
// 移除 https:// 前綴
|
|
74
|
+
const urlWithoutProtocol = url.slice(8);
|
|
75
|
+
// 插入 token@
|
|
76
|
+
return `https://${token}@${urlWithoutProtocol}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 獲取要使用的 Git Token(若有)
|
|
80
|
+
* @returns GitToken 或 null
|
|
81
|
+
*/
|
|
82
|
+
function getGitToken() {
|
|
83
|
+
const config = (0, git_token_1.loadTokens)();
|
|
84
|
+
if (config.tokens.length === 0) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
// 返回第一個 token(預設使用最新或第一個)
|
|
88
|
+
return config.tokens[0] || null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 執行 Git 命令
|
|
92
|
+
* @param args Git 命令參數
|
|
93
|
+
* @param options 執行選項
|
|
94
|
+
*/
|
|
95
|
+
async function executeGitCommand(args, options = {}) {
|
|
96
|
+
try {
|
|
97
|
+
const execOptions = {
|
|
98
|
+
cwd: options.cwd ?? process.cwd(),
|
|
99
|
+
timeout: options.timeout ?? 60000, // 預設 60 秒超時
|
|
100
|
+
};
|
|
101
|
+
const { stdout, stderr } = await (0, execa_1.execa)('git', args, execOptions);
|
|
102
|
+
return {
|
|
103
|
+
success: true,
|
|
104
|
+
message: '命令執行成功',
|
|
105
|
+
output: stdout || stderr,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
110
|
+
const stderr = isExecaError(error) ? error.stderr : undefined;
|
|
111
|
+
const result = {
|
|
112
|
+
success: false,
|
|
113
|
+
message: `Git 命令執行失敗:${errorMessage}`,
|
|
114
|
+
};
|
|
115
|
+
// 只有在有 stderr 時才添加 output 屬性
|
|
116
|
+
if (stderr !== undefined) {
|
|
117
|
+
result.output = stderr;
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 檢查是否為 Git 倉庫
|
|
124
|
+
* @param cwd 工作目錄
|
|
125
|
+
*/
|
|
126
|
+
async function isGitRepository(cwd) {
|
|
127
|
+
const result = await executeGitCommand(['rev-parse', '--git-dir'], { cwd: cwd ?? process.cwd() });
|
|
128
|
+
return result.success;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 初始化 Git 倉庫
|
|
132
|
+
* @param cwd 工作目錄
|
|
133
|
+
*/
|
|
134
|
+
async function gitInit(cwd) {
|
|
135
|
+
const targetDir = cwd || process.cwd();
|
|
136
|
+
// 檢查是否已為 Git 倉庫
|
|
137
|
+
const alreadyGit = await isGitRepository(targetDir);
|
|
138
|
+
if (alreadyGit) {
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
message: '此目錄已經是 Git 倉庫',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return await executeGitCommand(['init'], { cwd: targetDir });
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 建立 .gitignore 檔案(若不存在)
|
|
148
|
+
* @param cwd 工作目錄
|
|
149
|
+
*/
|
|
150
|
+
function createGitignore(cwd) {
|
|
151
|
+
const targetDir = cwd || process.cwd();
|
|
152
|
+
const gitignorePath = (0, path_1.join)(targetDir, '.gitignore');
|
|
153
|
+
if ((0, fs_1.existsSync)(gitignorePath)) {
|
|
154
|
+
return false; // 已存在
|
|
155
|
+
}
|
|
156
|
+
const defaultGitignore = `# 依賴
|
|
157
|
+
node_modules/
|
|
158
|
+
.pnpm-store/
|
|
159
|
+
|
|
160
|
+
# 構建輸出
|
|
161
|
+
dist/
|
|
162
|
+
build/
|
|
163
|
+
.next/
|
|
164
|
+
out/
|
|
165
|
+
|
|
166
|
+
# 環境變量
|
|
167
|
+
.env
|
|
168
|
+
.env.local
|
|
169
|
+
.env.*.local
|
|
170
|
+
|
|
171
|
+
# 日誌
|
|
172
|
+
*.log
|
|
173
|
+
npm-debug.log*
|
|
174
|
+
yarn-debug.log*
|
|
175
|
+
yarn-error.log*
|
|
176
|
+
|
|
177
|
+
# 編輯器
|
|
178
|
+
.vscode/
|
|
179
|
+
.idea/
|
|
180
|
+
*.swp
|
|
181
|
+
*.swo
|
|
182
|
+
*~
|
|
183
|
+
|
|
184
|
+
# 操作系統
|
|
185
|
+
.DS_Store
|
|
186
|
+
Thumbs.db
|
|
187
|
+
|
|
188
|
+
# Cloudflare
|
|
189
|
+
.wrangler/
|
|
190
|
+
.dev.vars
|
|
191
|
+
`;
|
|
192
|
+
(0, fs_1.writeFileSync)(gitignorePath, defaultGitignore, 'utf-8');
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Git 提交
|
|
197
|
+
* @param message 提交信息
|
|
198
|
+
* @param cwd 工作目錄
|
|
199
|
+
*/
|
|
200
|
+
async function gitCommit(message, cwd) {
|
|
201
|
+
const targetCwd = cwd ?? process.cwd();
|
|
202
|
+
const result = await executeGitCommand(['add', '-A'], { cwd: targetCwd });
|
|
203
|
+
if (!result.success) {
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
return await executeGitCommand(['commit', '-m', message], { cwd: targetCwd });
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* 添加 Git remote
|
|
210
|
+
* @param remoteName remote 名稱
|
|
211
|
+
* @param url remote URL
|
|
212
|
+
* @param cwd 工作目錄
|
|
213
|
+
*/
|
|
214
|
+
async function gitAddRemote(remoteName, url, cwd) {
|
|
215
|
+
return await executeGitCommand(['remote', 'add', remoteName, url], { cwd: cwd ?? process.cwd() });
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Git push
|
|
219
|
+
* @param remote remote 名稱
|
|
220
|
+
* @param branch 分支名稱
|
|
221
|
+
* @param cwd 工作目錄
|
|
222
|
+
* @param token Git Token(可選,若提供則使用 Token 認證)
|
|
223
|
+
*/
|
|
224
|
+
async function gitPush(remote, branch, cwd, token) {
|
|
225
|
+
const targetCwd = cwd ?? process.cwd();
|
|
226
|
+
// 若有提供 token,先修改 remote URL 以包含 token
|
|
227
|
+
if (token) {
|
|
228
|
+
try {
|
|
229
|
+
// 獲取 remote URL
|
|
230
|
+
const { stdout: remoteUrl } = await (0, execa_1.execa)('git', ['remote', 'get-url', remote], {
|
|
231
|
+
cwd: targetCwd,
|
|
232
|
+
});
|
|
233
|
+
if (!remoteUrl) {
|
|
234
|
+
return {
|
|
235
|
+
success: false,
|
|
236
|
+
message: '無法獲取 remote URL',
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (remoteUrl.startsWith('https://')) {
|
|
240
|
+
// 將 token 注入 URL
|
|
241
|
+
const tokenUrl = injectTokenToUrl(remoteUrl, token);
|
|
242
|
+
// 設置臨時 remote URL
|
|
243
|
+
await (0, execa_1.execa)('git', ['remote', 'set-url', remote, tokenUrl], {
|
|
244
|
+
cwd: targetCwd,
|
|
245
|
+
});
|
|
246
|
+
try {
|
|
247
|
+
// 執行 push
|
|
248
|
+
const result = await executeGitCommand(['push', '-u', remote, branch], {
|
|
249
|
+
cwd: targetCwd,
|
|
250
|
+
});
|
|
251
|
+
// 還原 remote URL(移除 token)
|
|
252
|
+
await (0, execa_1.execa)('git', ['remote', 'set-url', remote, remoteUrl], {
|
|
253
|
+
cwd: targetCwd,
|
|
254
|
+
});
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
// 如果失敗,還是要嘗試還原 URL
|
|
259
|
+
try {
|
|
260
|
+
await (0, execa_1.execa)('git', ['remote', 'set-url', remote, remoteUrl], {
|
|
261
|
+
cwd: targetCwd,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// 忽略還原失敗
|
|
266
|
+
}
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
// 非 HTTPS URL(例如 SSH),無法使用 Token
|
|
272
|
+
return {
|
|
273
|
+
success: false,
|
|
274
|
+
message: `Token 認證僅支援 HTTPS URL,目前為:${remoteUrl},請改用 HTTPS 格式的 remote URL`,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
// 如果 token 認證失敗,返回錯誤
|
|
280
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
281
|
+
return {
|
|
282
|
+
success: false,
|
|
283
|
+
message: `Token 認證推送失敗:${errorMessage}`,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return await executeGitCommand(['push', '-u', remote, branch], { cwd: targetCwd });
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Git clone
|
|
291
|
+
* @param url 倉庫 URL
|
|
292
|
+
* @param directory 目標目錄
|
|
293
|
+
* @param token Git Token(可選,若提供則使用 Token 認證)
|
|
294
|
+
*/
|
|
295
|
+
async function gitClone(url, directory, token) {
|
|
296
|
+
// 若有 token 且為 HTTPS URL,注入 token
|
|
297
|
+
const cloneUrl = token && url.startsWith('https://') ? injectTokenToUrl(url, token) : url;
|
|
298
|
+
const args = ['clone', cloneUrl];
|
|
299
|
+
if (directory) {
|
|
300
|
+
args.push(directory);
|
|
301
|
+
}
|
|
302
|
+
return await executeGitCommand(args);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* 獲取當前分支名稱
|
|
306
|
+
* @param cwd 工作目錄
|
|
307
|
+
*/
|
|
308
|
+
async function getCurrentBranch(cwd) {
|
|
309
|
+
const result = await executeGitCommand(['branch', '--show-current'], {
|
|
310
|
+
cwd: cwd ?? process.cwd(),
|
|
311
|
+
});
|
|
312
|
+
if (result.success && result.output) {
|
|
313
|
+
return result.output.trim();
|
|
314
|
+
}
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* 獲取 remote 列表
|
|
319
|
+
* @param cwd 工作目錄
|
|
320
|
+
*/
|
|
321
|
+
async function getRemotes(cwd) {
|
|
322
|
+
const result = await executeGitCommand(['remote'], { cwd: cwd ?? process.cwd() });
|
|
323
|
+
if (result.success && result.output) {
|
|
324
|
+
return result.output
|
|
325
|
+
.trim()
|
|
326
|
+
.split('\n')
|
|
327
|
+
.filter((remoteName) => remoteName.trim() !== '');
|
|
328
|
+
}
|
|
329
|
+
return [];
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* 設置 default branch
|
|
333
|
+
* @param branch 分支名稱
|
|
334
|
+
* @param cwd 工作目錄
|
|
335
|
+
*/
|
|
336
|
+
async function gitBranchM1(branch, cwd) {
|
|
337
|
+
return await executeGitCommand(['branch', '-M', branch], { cwd: cwd ?? process.cwd() });
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* 取消 Git 倉庫(刪除 .git 目錄)
|
|
341
|
+
* @param cwd 工作目錄
|
|
342
|
+
*/
|
|
343
|
+
async function removeGitRepo(cwd) {
|
|
344
|
+
const gitDir = (0, path_1.join)(cwd ?? process.cwd(), '.git');
|
|
345
|
+
if (!(0, fs_1.existsSync)(gitDir)) {
|
|
346
|
+
return {
|
|
347
|
+
success: false,
|
|
348
|
+
message: '此目錄不是 Git 倉庫',
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
const { rmSync } = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
353
|
+
rmSync(gitDir, { recursive: true, force: true });
|
|
354
|
+
return {
|
|
355
|
+
success: true,
|
|
356
|
+
message: '已成功取消 Git 倉庫',
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
361
|
+
return {
|
|
362
|
+
success: false,
|
|
363
|
+
message: `取消 Git 倉庫失敗:${errorMessage}`,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=git.js.map
|