@appthen/cli 1.2.2 → 1.2.3
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/bin/main.js +41 -0
- package/dist/index.js +1814 -177
- package/package.json +7 -4
- package/dist/TSXComplianceChecker-AST.js +0 -321
- package/dist/TSXComplianceChecker.js +0 -683
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var prettier = require('prettier');
|
|
|
29
29
|
var fs$2 = require('fs-extra');
|
|
30
30
|
var io = require('socket.io-client');
|
|
31
31
|
var fs$3 = require('fs/promises');
|
|
32
|
+
var chokidar = require('chokidar');
|
|
32
33
|
var whatwgUrl = require('whatwg-url');
|
|
33
34
|
|
|
34
35
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -80,6 +81,7 @@ var fs__default$1 = /*#__PURE__*/_interopDefaultLegacy(fs$2);
|
|
|
80
81
|
var fs__namespace$1 = /*#__PURE__*/_interopNamespace(fs$2);
|
|
81
82
|
var io__default = /*#__PURE__*/_interopDefaultLegacy(io);
|
|
82
83
|
var fs__default$2 = /*#__PURE__*/_interopDefaultLegacy(fs$3);
|
|
84
|
+
var chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);
|
|
83
85
|
var whatwgUrl__default = /*#__PURE__*/_interopDefaultLegacy(whatwgUrl);
|
|
84
86
|
|
|
85
87
|
/******************************************************************************
|
|
@@ -285,6 +287,9 @@ function removeDir(_path) {
|
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
289
|
|
|
290
|
+
let urlAlphabet =
|
|
291
|
+
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
|
|
292
|
+
|
|
288
293
|
const POOL_SIZE_MULTIPLIER = 128;
|
|
289
294
|
let pool, poolOffset;
|
|
290
295
|
let fillPool = bytes => {
|
|
@@ -319,6 +324,14 @@ let customRandom = (alphabet, defaultSize, getRandom) => {
|
|
|
319
324
|
};
|
|
320
325
|
let customAlphabet = (alphabet, size = 21) =>
|
|
321
326
|
customRandom(alphabet, size, random);
|
|
327
|
+
let nanoid$1 = (size = 21) => {
|
|
328
|
+
fillPool((size -= 0));
|
|
329
|
+
let id = '';
|
|
330
|
+
for (let i = poolOffset - size; i < poolOffset; i++) {
|
|
331
|
+
id += urlAlphabet[pool[i] & 63];
|
|
332
|
+
}
|
|
333
|
+
return id
|
|
334
|
+
};
|
|
322
335
|
|
|
323
336
|
require('base-64').encode;
|
|
324
337
|
var svgToBase64 = function (svgString) {
|
|
@@ -40679,6 +40692,10 @@ function regExpEscape (s) {
|
|
|
40679
40692
|
var ShadowSpace = /** @class */ (function () {
|
|
40680
40693
|
function ShadowSpace(config) {
|
|
40681
40694
|
this.contentCache = new Map(); // 内容缓存
|
|
40695
|
+
// 🆕 文件监听相关
|
|
40696
|
+
this.watcher = null;
|
|
40697
|
+
this.changeListeners = new Set();
|
|
40698
|
+
this.isWatching = false;
|
|
40682
40699
|
this.config = __assign({ spaceId: 'default', ignorePatterns: [
|
|
40683
40700
|
'node_modules/**',
|
|
40684
40701
|
'.git/**',
|
|
@@ -40719,6 +40736,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40719
40736
|
'.php',
|
|
40720
40737
|
'.rb',
|
|
40721
40738
|
'.swift',
|
|
40739
|
+
'.flow',
|
|
40740
|
+
'.draw',
|
|
40722
40741
|
'.kt',
|
|
40723
40742
|
'.data', // 添加 .data 扩展名支持
|
|
40724
40743
|
] }, config);
|
|
@@ -40798,7 +40817,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40798
40817
|
ShadowSpace.prototype.syncFromEditor = function (projectFiles) {
|
|
40799
40818
|
var _a;
|
|
40800
40819
|
return __awaiter(this, void 0, void 0, function () {
|
|
40801
|
-
var newFiles, projectFiles_1, projectFiles_1_1, file,
|
|
40820
|
+
var newFiles, projectFiles_1, projectFiles_1_1, file, size, now, fullPath, writtenContent, localHash, remoteHash, e_1_1, _b, _c, _d, filePath, fileEntry, allFiles, totalFilesCount, totalSizeSum;
|
|
40802
40821
|
var e_1, _e, e_2, _f;
|
|
40803
40822
|
return __generator(this, function (_g) {
|
|
40804
40823
|
switch (_g.label) {
|
|
@@ -40807,61 +40826,69 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40807
40826
|
newFiles = {};
|
|
40808
40827
|
_g.label = 1;
|
|
40809
40828
|
case 1:
|
|
40810
|
-
_g.trys.push([1,
|
|
40829
|
+
_g.trys.push([1, 7, 8, 9]);
|
|
40811
40830
|
projectFiles_1 = __values(projectFiles), projectFiles_1_1 = projectFiles_1.next();
|
|
40812
40831
|
_g.label = 2;
|
|
40813
40832
|
case 2:
|
|
40814
|
-
if (!!projectFiles_1_1.done) return [3 /*break*/,
|
|
40833
|
+
if (!!projectFiles_1_1.done) return [3 /*break*/, 6];
|
|
40815
40834
|
file = projectFiles_1_1.value;
|
|
40816
40835
|
if (this.shouldIgnoreFile(file.path)) {
|
|
40817
40836
|
console.log("[ShadowSpace] \u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(file.path));
|
|
40818
|
-
return [3 /*break*/,
|
|
40837
|
+
return [3 /*break*/, 5];
|
|
40819
40838
|
}
|
|
40820
|
-
localHash = this.calculateHash(file.content);
|
|
40821
40839
|
size = Buffer.byteLength(file.content, 'utf8');
|
|
40822
40840
|
now = Date.now();
|
|
40823
40841
|
// 记录空内容文件
|
|
40824
40842
|
if (file.content === '') {
|
|
40825
40843
|
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7A7A\u5185\u5BB9\u6587\u4EF6: ".concat(file.path, " (size: ").concat(size, ")"));
|
|
40826
40844
|
}
|
|
40845
|
+
// 写入本地文件
|
|
40846
|
+
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40847
|
+
case 3:
|
|
40848
|
+
// 写入本地文件
|
|
40849
|
+
_g.sent();
|
|
40850
|
+
fullPath = path__default["default"].join(this.config.projectRoot, file.path);
|
|
40851
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
40852
|
+
case 4:
|
|
40853
|
+
writtenContent = _g.sent();
|
|
40854
|
+
localHash = this.calculateHash(writtenContent);
|
|
40855
|
+
remoteHash = file.hash || localHash;
|
|
40827
40856
|
newFiles[file.path] = {
|
|
40828
40857
|
path: file.path,
|
|
40829
40858
|
hash: localHash,
|
|
40830
|
-
remoteHash:
|
|
40859
|
+
remoteHash: remoteHash,
|
|
40831
40860
|
size: size,
|
|
40832
40861
|
lastSyncTime: now,
|
|
40833
40862
|
lastModified: file.modify || now,
|
|
40834
40863
|
version: ((_a = this.state.files[file.path]) === null || _a === void 0 ? void 0 : _a.version) + 1 || 1,
|
|
40835
40864
|
mtime: now,
|
|
40865
|
+
remoteModified: true,
|
|
40866
|
+
remoteModifiedTime: now,
|
|
40836
40867
|
};
|
|
40837
40868
|
console.log("[ShadowSpace] \u540C\u6B65\u6587\u4EF6: ".concat(file.path), {
|
|
40869
|
+
remoteHash: remoteHash.substring(0, 16),
|
|
40838
40870
|
localHash: localHash.substring(0, 16),
|
|
40839
|
-
remoteHash: (file.hash || localHash).substring(0, 16),
|
|
40840
40871
|
size: size,
|
|
40872
|
+
version: newFiles[file.path].version,
|
|
40841
40873
|
});
|
|
40842
|
-
// 写入本地文件
|
|
40843
|
-
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40844
|
-
case 3:
|
|
40845
|
-
// 写入本地文件
|
|
40846
|
-
_g.sent();
|
|
40847
40874
|
// 缓存内容用于diff
|
|
40848
|
-
this.contentCache.set(file.path,
|
|
40849
|
-
_g.label =
|
|
40850
|
-
case
|
|
40875
|
+
this.contentCache.set(file.path, writtenContent);
|
|
40876
|
+
_g.label = 5;
|
|
40877
|
+
case 5:
|
|
40851
40878
|
projectFiles_1_1 = projectFiles_1.next();
|
|
40852
40879
|
return [3 /*break*/, 2];
|
|
40853
|
-
case
|
|
40854
|
-
case
|
|
40880
|
+
case 6: return [3 /*break*/, 9];
|
|
40881
|
+
case 7:
|
|
40855
40882
|
e_1_1 = _g.sent();
|
|
40856
40883
|
e_1 = { error: e_1_1 };
|
|
40857
|
-
return [3 /*break*/,
|
|
40858
|
-
case
|
|
40884
|
+
return [3 /*break*/, 9];
|
|
40885
|
+
case 8:
|
|
40859
40886
|
try {
|
|
40860
40887
|
if (projectFiles_1_1 && !projectFiles_1_1.done && (_e = projectFiles_1.return)) _e.call(projectFiles_1);
|
|
40861
40888
|
}
|
|
40862
40889
|
finally { if (e_1) throw e_1.error; }
|
|
40863
40890
|
return [7 /*endfinally*/];
|
|
40864
|
-
case
|
|
40891
|
+
case 9:
|
|
40865
40892
|
try {
|
|
40866
40893
|
// 合并文件记录,而不是替换
|
|
40867
40894
|
for (_b = __values(Object.entries(newFiles)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
@@ -40887,11 +40914,11 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40887
40914
|
console.log("[ShadowSpace] \u66F4\u65B0\u540E\u7684\u6587\u4EF6\u7EDF\u8BA1:", {
|
|
40888
40915
|
totalFiles: totalFilesCount,
|
|
40889
40916
|
totalSize: totalSizeSum,
|
|
40890
|
-
fileList: Object.keys(this.state.files),
|
|
40917
|
+
// fileList: Object.keys(this.state.files),
|
|
40891
40918
|
});
|
|
40892
40919
|
this.state.lastUpdateTime = Date.now();
|
|
40893
40920
|
return [4 /*yield*/, this.saveState()];
|
|
40894
|
-
case
|
|
40921
|
+
case 10:
|
|
40895
40922
|
_g.sent();
|
|
40896
40923
|
console.log("\u5F71\u5B50\u7A7A\u95F4\u540C\u6B65\u5B8C\u6210: ".concat(this.state.metadata.totalFiles, " \u4E2A\u6587\u4EF6"));
|
|
40897
40924
|
return [2 /*return*/];
|
|
@@ -40990,54 +41017,62 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40990
41017
|
* 检测本地文件系统与影子空间的差异
|
|
40991
41018
|
*/
|
|
40992
41019
|
ShadowSpace.prototype.detectChanges = function () {
|
|
41020
|
+
var _a;
|
|
40993
41021
|
return __awaiter(this, void 0, void 0, function () {
|
|
40994
|
-
var changes,
|
|
40995
|
-
var e_3,
|
|
40996
|
-
return __generator(this, function (
|
|
40997
|
-
switch (
|
|
41022
|
+
var changes, _b, _c, _d, filePath, shadowEntry, localFilePath, localContent, localHash, _e, _f, _g, shadowContent, _h, _j, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
|
|
41023
|
+
var e_3, _k, _l, _m, e_4, _o;
|
|
41024
|
+
return __generator(this, function (_p) {
|
|
41025
|
+
switch (_p.label) {
|
|
40998
41026
|
case 0:
|
|
40999
41027
|
changes = [];
|
|
41000
|
-
|
|
41028
|
+
_p.label = 1;
|
|
41001
41029
|
case 1:
|
|
41002
|
-
|
|
41003
|
-
|
|
41004
|
-
|
|
41030
|
+
_p.trys.push([1, 16, 17, 18]);
|
|
41031
|
+
_b = __values(Object.entries(this.state.files)), _c = _b.next();
|
|
41032
|
+
_p.label = 2;
|
|
41005
41033
|
case 2:
|
|
41006
|
-
if (!!
|
|
41007
|
-
|
|
41034
|
+
if (!!_c.done) return [3 /*break*/, 15];
|
|
41035
|
+
_d = __read(_c.value, 2), filePath = _d[0], shadowEntry = _d[1];
|
|
41008
41036
|
localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
|
|
41009
|
-
|
|
41037
|
+
_p.label = 3;
|
|
41010
41038
|
case 3:
|
|
41011
|
-
|
|
41039
|
+
_p.trys.push([3, 11, , 14]);
|
|
41012
41040
|
return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
|
|
41013
41041
|
case 4:
|
|
41014
|
-
localContent =
|
|
41042
|
+
localContent = _p.sent();
|
|
41015
41043
|
localHash = this.calculateHash(localContent);
|
|
41016
41044
|
if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
|
|
41045
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(filePath), {
|
|
41046
|
+
localHash: localHash.substring(0, 16),
|
|
41047
|
+
shadowHash: shadowEntry.hash.substring(0, 16),
|
|
41048
|
+
remoteHash: ((_a = shadowEntry.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41049
|
+
remoteModified: shadowEntry.remoteModified || false,
|
|
41050
|
+
version: shadowEntry.version,
|
|
41051
|
+
});
|
|
41017
41052
|
if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
|
|
41018
41053
|
// 如果是远程修改,先更新影子空间记录并清除远程修改标记
|
|
41019
41054
|
console.log("\u68C0\u6D4B\u5230\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u53D8\u5316: ".concat(filePath));
|
|
41020
41055
|
// 更新影子空间记录
|
|
41021
|
-
|
|
41022
|
-
|
|
41023
|
-
|
|
41024
|
-
|
|
41056
|
+
_e = this.state.files;
|
|
41057
|
+
_f = filePath;
|
|
41058
|
+
_g = [__assign({}, shadowEntry)];
|
|
41059
|
+
_l = { hash: localHash };
|
|
41025
41060
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41026
41061
|
case 5:
|
|
41027
|
-
|
|
41062
|
+
_l.size = (_p.sent()).size, _l.lastSyncTime = Date.now(), _l.version = shadowEntry.version + 1;
|
|
41028
41063
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41029
41064
|
case 6:
|
|
41030
41065
|
// 更新影子空间记录
|
|
41031
|
-
|
|
41066
|
+
_e[_f] = __assign.apply(void 0, _g.concat([(_l.mtime = (_p.sent()).mtimeMs, _l.remoteModified = false, _l)]));
|
|
41032
41067
|
// 如果本地内容与最初的远程内容不同,则认为是本地修改
|
|
41033
41068
|
// 这里我们简化处理:任何在远程修改基础上的本地变化都视为本地修改
|
|
41034
41069
|
console.log("\u6587\u4EF6 ".concat(filePath, " \u5728\u8FDC\u7A0B\u4FEE\u6539\u57FA\u7840\u4E0A\u53D1\u751F\u4E86\u672C\u5730\u53D8\u5316\uFF0C\u6807\u8BB0\u4E3A\u672C\u5730\u4FEE\u6539"));
|
|
41035
|
-
|
|
41070
|
+
_p.label = 7;
|
|
41036
41071
|
case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41037
41072
|
case 8:
|
|
41038
|
-
shadowContent =
|
|
41039
|
-
|
|
41040
|
-
|
|
41073
|
+
shadowContent = _p.sent();
|
|
41074
|
+
_j = (_h = changes).push;
|
|
41075
|
+
_m = {
|
|
41041
41076
|
id: this.generateId(),
|
|
41042
41077
|
action: 'modify',
|
|
41043
41078
|
path: filePath,
|
|
@@ -41045,21 +41080,21 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41045
41080
|
};
|
|
41046
41081
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41047
41082
|
case 9:
|
|
41048
|
-
|
|
41049
|
-
|
|
41083
|
+
_j.apply(_h, [(_m.timestamp = (_p.sent()).mtime.getTime(),
|
|
41084
|
+
_m.diff = {
|
|
41050
41085
|
before: shadowContent,
|
|
41051
41086
|
after: localContent,
|
|
41052
41087
|
},
|
|
41053
|
-
|
|
41054
|
-
|
|
41055
|
-
|
|
41088
|
+
_m.projectId = this.state.projectId,
|
|
41089
|
+
_m)]);
|
|
41090
|
+
_p.label = 10;
|
|
41056
41091
|
case 10: return [3 /*break*/, 14];
|
|
41057
41092
|
case 11:
|
|
41058
|
-
error_2 =
|
|
41093
|
+
error_2 = _p.sent();
|
|
41059
41094
|
if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
|
|
41060
41095
|
return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41061
41096
|
case 12:
|
|
41062
|
-
shadowContent =
|
|
41097
|
+
shadowContent = _p.sent();
|
|
41063
41098
|
changes.push({
|
|
41064
41099
|
id: this.generateId(),
|
|
41065
41100
|
action: 'delete',
|
|
@@ -41072,25 +41107,25 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41072
41107
|
},
|
|
41073
41108
|
projectId: this.state.projectId,
|
|
41074
41109
|
});
|
|
41075
|
-
|
|
41110
|
+
_p.label = 13;
|
|
41076
41111
|
case 13: return [3 /*break*/, 14];
|
|
41077
41112
|
case 14:
|
|
41078
|
-
|
|
41113
|
+
_c = _b.next();
|
|
41079
41114
|
return [3 /*break*/, 2];
|
|
41080
41115
|
case 15: return [3 /*break*/, 18];
|
|
41081
41116
|
case 16:
|
|
41082
|
-
e_3_1 =
|
|
41117
|
+
e_3_1 = _p.sent();
|
|
41083
41118
|
e_3 = { error: e_3_1 };
|
|
41084
41119
|
return [3 /*break*/, 18];
|
|
41085
41120
|
case 17:
|
|
41086
41121
|
try {
|
|
41087
|
-
if (
|
|
41122
|
+
if (_c && !_c.done && (_k = _b.return)) _k.call(_b);
|
|
41088
41123
|
}
|
|
41089
41124
|
finally { if (e_3) throw e_3.error; }
|
|
41090
41125
|
return [7 /*endfinally*/];
|
|
41091
41126
|
case 18: return [4 /*yield*/, this.scanLocalFiles()];
|
|
41092
41127
|
case 19:
|
|
41093
|
-
localFiles =
|
|
41128
|
+
localFiles = _p.sent();
|
|
41094
41129
|
try {
|
|
41095
41130
|
for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
|
|
41096
41131
|
localFile = localFiles_1_1.value;
|
|
@@ -41113,7 +41148,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41113
41148
|
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
41114
41149
|
finally {
|
|
41115
41150
|
try {
|
|
41116
|
-
if (localFiles_1_1 && !localFiles_1_1.done && (
|
|
41151
|
+
if (localFiles_1_1 && !localFiles_1_1.done && (_o = localFiles_1.return)) _o.call(localFiles_1);
|
|
41117
41152
|
}
|
|
41118
41153
|
finally { if (e_4) throw e_4.error; }
|
|
41119
41154
|
}
|
|
@@ -41243,38 +41278,40 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41243
41278
|
* 当编辑器通过WebSocket修改文件后调用此方法
|
|
41244
41279
|
*/
|
|
41245
41280
|
ShadowSpace.prototype.markAsRemoteModified = function (filePaths) {
|
|
41281
|
+
var _a;
|
|
41246
41282
|
return __awaiter(this, void 0, void 0, function () {
|
|
41247
|
-
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, error_4, e_6_1;
|
|
41248
|
-
var e_6,
|
|
41249
|
-
return __generator(this, function (
|
|
41250
|
-
switch (
|
|
41283
|
+
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_4, e_6_1;
|
|
41284
|
+
var e_6, _b;
|
|
41285
|
+
return __generator(this, function (_c) {
|
|
41286
|
+
switch (_c.label) {
|
|
41251
41287
|
case 0:
|
|
41252
41288
|
now = Date.now();
|
|
41253
41289
|
hasChanges = false;
|
|
41254
|
-
|
|
41290
|
+
_c.label = 1;
|
|
41255
41291
|
case 1:
|
|
41256
|
-
|
|
41292
|
+
_c.trys.push([1, 9, 10, 11]);
|
|
41257
41293
|
filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
|
|
41258
|
-
|
|
41294
|
+
_c.label = 2;
|
|
41259
41295
|
case 2:
|
|
41260
41296
|
if (!!filePaths_1_1.done) return [3 /*break*/, 8];
|
|
41261
41297
|
filePath = filePaths_1_1.value;
|
|
41262
41298
|
fullPath = path__default["default"].resolve(this.config.projectRoot, filePath);
|
|
41263
|
-
|
|
41299
|
+
_c.label = 3;
|
|
41264
41300
|
case 3:
|
|
41265
|
-
|
|
41301
|
+
_c.trys.push([3, 6, , 7]);
|
|
41266
41302
|
return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
|
|
41267
41303
|
case 4:
|
|
41268
|
-
stats =
|
|
41304
|
+
stats = _c.sent();
|
|
41269
41305
|
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
41270
41306
|
case 5:
|
|
41271
|
-
content =
|
|
41307
|
+
content = _c.sent();
|
|
41272
41308
|
hash = this.calculateHash(content);
|
|
41273
41309
|
existingFile = this.state.files[filePath];
|
|
41310
|
+
remoteHash = (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash;
|
|
41274
41311
|
this.state.files[filePath] = {
|
|
41275
41312
|
path: filePath,
|
|
41276
41313
|
hash: hash,
|
|
41277
|
-
remoteHash:
|
|
41314
|
+
remoteHash: remoteHash,
|
|
41278
41315
|
size: stats.size,
|
|
41279
41316
|
lastSyncTime: now,
|
|
41280
41317
|
lastModified: now,
|
|
@@ -41284,10 +41321,16 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41284
41321
|
remoteModifiedTime: now,
|
|
41285
41322
|
};
|
|
41286
41323
|
hasChanges = true;
|
|
41287
|
-
console.log("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath
|
|
41324
|
+
console.log("[ShadowSpace] \u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath), {
|
|
41325
|
+
版本: this.state.files[filePath].version,
|
|
41326
|
+
hash: hash.substring(0, 16),
|
|
41327
|
+
remoteHash: remoteHash.substring(0, 16),
|
|
41328
|
+
旧remoteHash: ((_a = existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41329
|
+
remoteHashChanged: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) !== remoteHash,
|
|
41330
|
+
});
|
|
41288
41331
|
return [3 /*break*/, 7];
|
|
41289
41332
|
case 6:
|
|
41290
|
-
error_4 =
|
|
41333
|
+
error_4 = _c.sent();
|
|
41291
41334
|
console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"), error_4);
|
|
41292
41335
|
return [3 /*break*/, 7];
|
|
41293
41336
|
case 7:
|
|
@@ -41295,12 +41338,12 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41295
41338
|
return [3 /*break*/, 2];
|
|
41296
41339
|
case 8: return [3 /*break*/, 11];
|
|
41297
41340
|
case 9:
|
|
41298
|
-
e_6_1 =
|
|
41341
|
+
e_6_1 = _c.sent();
|
|
41299
41342
|
e_6 = { error: e_6_1 };
|
|
41300
41343
|
return [3 /*break*/, 11];
|
|
41301
41344
|
case 10:
|
|
41302
41345
|
try {
|
|
41303
|
-
if (filePaths_1_1 && !filePaths_1_1.done && (
|
|
41346
|
+
if (filePaths_1_1 && !filePaths_1_1.done && (_b = filePaths_1.return)) _b.call(filePaths_1);
|
|
41304
41347
|
}
|
|
41305
41348
|
finally { if (e_6) throw e_6.error; }
|
|
41306
41349
|
return [7 /*endfinally*/];
|
|
@@ -41309,9 +41352,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41309
41352
|
this.updateMetadata();
|
|
41310
41353
|
return [4 /*yield*/, this.saveState()];
|
|
41311
41354
|
case 12:
|
|
41312
|
-
|
|
41355
|
+
_c.sent();
|
|
41313
41356
|
console.log("\u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
|
|
41314
|
-
|
|
41357
|
+
_c.label = 13;
|
|
41315
41358
|
case 13: return [2 /*return*/];
|
|
41316
41359
|
}
|
|
41317
41360
|
});
|
|
@@ -41614,44 +41657,27 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41614
41657
|
return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
41615
41658
|
};
|
|
41616
41659
|
ShadowSpace.prototype.shouldIgnoreFile = function (filePath) {
|
|
41660
|
+
// console.log(`[ShadowSpace] shouldIgnoreFile 检查: "${filePath}"`);
|
|
41617
41661
|
var e_10, _a;
|
|
41618
|
-
console.log("[ShadowSpace] shouldIgnoreFile \u68C0\u67E5: ".concat(filePath), {
|
|
41619
|
-
ignorePatterns: this.config.ignorePatterns,
|
|
41620
|
-
includeExtensions: this.config.includeExtensions,
|
|
41621
|
-
});
|
|
41622
41662
|
// 特殊处理:过滤掉特定的系统文件
|
|
41623
41663
|
var fileName = filePath.split('/').pop() || '';
|
|
41624
41664
|
if (fileName === '.dirty_files.json') {
|
|
41625
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41626
41665
|
return true;
|
|
41627
41666
|
}
|
|
41628
41667
|
if (fileName === 'assets.json') {
|
|
41629
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41630
41668
|
return true;
|
|
41631
41669
|
}
|
|
41632
41670
|
if (fileName === 'project.json') {
|
|
41633
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41634
41671
|
return true;
|
|
41635
41672
|
}
|
|
41636
41673
|
if (fileName.endsWith('.doc')) {
|
|
41637
|
-
console.log("[ShadowSpace] .doc\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41638
41674
|
return true;
|
|
41639
41675
|
}
|
|
41640
|
-
//
|
|
41676
|
+
// 🔥 目录白名单检查:简化逻辑,允许 src/ 和 docs/ 下的所有文件
|
|
41677
|
+
var isInSrc = filePath.startsWith('src/');
|
|
41641
41678
|
var isInDocs = filePath.startsWith('docs/');
|
|
41642
|
-
var isInSrcPages = filePath.startsWith('src/pages/');
|
|
41643
|
-
var isInSrcModules = filePath.startsWith('src/modules/');
|
|
41644
|
-
var isInSrcTypes = filePath.startsWith('src/types/');
|
|
41645
|
-
var isInSrcUtils = filePath.startsWith('src/utils/');
|
|
41646
|
-
var isInSrcComponents = filePath.startsWith('src/components/');
|
|
41647
41679
|
var isRootConfig = filePath.match(/^[^\/]+\.(json|md|yml|yaml|toml|js|ts|py|go|rs)$/);
|
|
41648
|
-
if (!isInDocs &&
|
|
41649
|
-
!isInSrcPages &&
|
|
41650
|
-
!isInSrcModules &&
|
|
41651
|
-
!isInSrcTypes &&
|
|
41652
|
-
!isInSrcUtils &&
|
|
41653
|
-
!isInSrcComponents &&
|
|
41654
|
-
!isRootConfig) {
|
|
41680
|
+
if (!isInSrc && !isInDocs && !isRootConfig) {
|
|
41655
41681
|
console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u767D\u540D\u5355\u76EE\u5F55\u4E2D: ".concat(filePath));
|
|
41656
41682
|
return true;
|
|
41657
41683
|
}
|
|
@@ -41686,7 +41712,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41686
41712
|
return true;
|
|
41687
41713
|
}
|
|
41688
41714
|
}
|
|
41689
|
-
console.log(
|
|
41715
|
+
// console.log(`[ShadowSpace] 文件通过忽略检查: ${filePath}`);
|
|
41690
41716
|
return false;
|
|
41691
41717
|
};
|
|
41692
41718
|
ShadowSpace.prototype.writeLocalFile = function (filePath, content) {
|
|
@@ -41851,15 +41877,328 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41851
41877
|
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
41852
41878
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
41853
41879
|
};
|
|
41880
|
+
// ==================== 🆕 文件监听功能 ====================
|
|
41881
|
+
/**
|
|
41882
|
+
* 启动文件监听
|
|
41883
|
+
*/
|
|
41884
|
+
ShadowSpace.prototype.startWatching = function () {
|
|
41885
|
+
var _this = this;
|
|
41886
|
+
if (this.isWatching) {
|
|
41887
|
+
console.log('[ShadowSpace] 文件监听已经在运行中');
|
|
41888
|
+
return;
|
|
41889
|
+
}
|
|
41890
|
+
console.log('[ShadowSpace] 启动文件监听...');
|
|
41891
|
+
console.log('[ShadowSpace] 监听目录:', this.config.projectRoot);
|
|
41892
|
+
try {
|
|
41893
|
+
// 🔥 使用轮询模式 + ignored 函数过滤
|
|
41894
|
+
this.watcher = chokidar__default["default"].watch(this.config.projectRoot, {
|
|
41895
|
+
ignored: function (filePath) {
|
|
41896
|
+
var relativePath = path__default["default"].relative(_this.config.projectRoot, filePath);
|
|
41897
|
+
// 忽略根目录本身
|
|
41898
|
+
if (!relativePath || relativePath === '.') {
|
|
41899
|
+
return true;
|
|
41900
|
+
}
|
|
41901
|
+
// 使用白名单过滤
|
|
41902
|
+
return _this.shouldIgnoreFile(relativePath);
|
|
41903
|
+
},
|
|
41904
|
+
persistent: true,
|
|
41905
|
+
ignoreInitial: true,
|
|
41906
|
+
usePolling: true,
|
|
41907
|
+
interval: 2000,
|
|
41908
|
+
binaryInterval: 3000,
|
|
41909
|
+
depth: 99,
|
|
41910
|
+
awaitWriteFinish: {
|
|
41911
|
+
stabilityThreshold: 500,
|
|
41912
|
+
pollInterval: 100,
|
|
41913
|
+
},
|
|
41914
|
+
});
|
|
41915
|
+
console.log('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
|
|
41916
|
+
}
|
|
41917
|
+
catch (error) {
|
|
41918
|
+
console.error('[ShadowSpace] 创建文件监听器失败:', error);
|
|
41919
|
+
return;
|
|
41920
|
+
}
|
|
41921
|
+
this.watcher
|
|
41922
|
+
.on('change', function (filePath) {
|
|
41923
|
+
_this.onFileChanged(filePath);
|
|
41924
|
+
})
|
|
41925
|
+
.on('add', function (filePath) {
|
|
41926
|
+
_this.onFileAdded(filePath);
|
|
41927
|
+
})
|
|
41928
|
+
.on('unlink', function (filePath) {
|
|
41929
|
+
_this.onFileDeleted(filePath);
|
|
41930
|
+
})
|
|
41931
|
+
.on('error', function (error) {
|
|
41932
|
+
console.error('[ShadowSpace] 文件监听错误:', error);
|
|
41933
|
+
})
|
|
41934
|
+
.on('ready', function () {
|
|
41935
|
+
_this.isWatching = true;
|
|
41936
|
+
console.log('[ShadowSpace] 文件监听已启动,正在监听:', _this.config.projectRoot);
|
|
41937
|
+
console.log('[ShadowSpace] 监听配置: 轮询模式 (interval: 2s)');
|
|
41938
|
+
});
|
|
41939
|
+
};
|
|
41940
|
+
/**
|
|
41941
|
+
* 停止文件监听
|
|
41942
|
+
*/
|
|
41943
|
+
ShadowSpace.prototype.stopWatching = function () {
|
|
41944
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41945
|
+
return __generator(this, function (_a) {
|
|
41946
|
+
switch (_a.label) {
|
|
41947
|
+
case 0:
|
|
41948
|
+
if (!this.isWatching || !this.watcher) {
|
|
41949
|
+
console.log('[ShadowSpace] 文件监听未运行');
|
|
41950
|
+
return [2 /*return*/];
|
|
41951
|
+
}
|
|
41952
|
+
console.log('[ShadowSpace] 停止文件监听...');
|
|
41953
|
+
return [4 /*yield*/, this.watcher.close()];
|
|
41954
|
+
case 1:
|
|
41955
|
+
_a.sent();
|
|
41956
|
+
this.watcher = null;
|
|
41957
|
+
this.isWatching = false;
|
|
41958
|
+
console.log('[ShadowSpace] 文件监听已停止');
|
|
41959
|
+
return [2 /*return*/];
|
|
41960
|
+
}
|
|
41961
|
+
});
|
|
41962
|
+
});
|
|
41963
|
+
};
|
|
41964
|
+
/**
|
|
41965
|
+
* 添加变更事件监听器
|
|
41966
|
+
*/
|
|
41967
|
+
ShadowSpace.prototype.addChangeListener = function (listener) {
|
|
41968
|
+
this.changeListeners.add(listener);
|
|
41969
|
+
};
|
|
41970
|
+
/**
|
|
41971
|
+
* 移除变更事件监听器
|
|
41972
|
+
*/
|
|
41973
|
+
ShadowSpace.prototype.removeChangeListener = function (listener) {
|
|
41974
|
+
this.changeListeners.delete(listener);
|
|
41975
|
+
};
|
|
41976
|
+
/**
|
|
41977
|
+
* 触发变更事件
|
|
41978
|
+
*/
|
|
41979
|
+
ShadowSpace.prototype.emitChangeEvent = function (event) {
|
|
41980
|
+
console.log('[ShadowSpace] 触发变更事件:', event);
|
|
41981
|
+
this.changeListeners.forEach(function (listener) {
|
|
41982
|
+
try {
|
|
41983
|
+
listener(event);
|
|
41984
|
+
}
|
|
41985
|
+
catch (error) {
|
|
41986
|
+
console.error('[ShadowSpace] 变更事件监听器执行失败:', error);
|
|
41987
|
+
}
|
|
41988
|
+
});
|
|
41989
|
+
};
|
|
41990
|
+
/**
|
|
41991
|
+
* 文件变更处理
|
|
41992
|
+
*/
|
|
41993
|
+
ShadowSpace.prototype.onFileChanged = function (filePath) {
|
|
41994
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41995
|
+
var relativePath, shadowEntry, content, hash, stats, error_13;
|
|
41996
|
+
return __generator(this, function (_a) {
|
|
41997
|
+
switch (_a.label) {
|
|
41998
|
+
case 0:
|
|
41999
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42000
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(relativePath));
|
|
42001
|
+
shadowEntry = this.state.files[relativePath];
|
|
42002
|
+
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42003
|
+
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42004
|
+
shadowEntry.remoteModified = false; // 清除标记
|
|
42005
|
+
return [4 /*yield*/, this.saveState()];
|
|
42006
|
+
case 1:
|
|
42007
|
+
_a.sent();
|
|
42008
|
+
return [2 /*return*/];
|
|
42009
|
+
case 2:
|
|
42010
|
+
_a.trys.push([2, 5, , 6]);
|
|
42011
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
|
|
42012
|
+
case 3:
|
|
42013
|
+
content = _a.sent();
|
|
42014
|
+
hash = this.calculateHash(content);
|
|
42015
|
+
return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
|
|
42016
|
+
case 4:
|
|
42017
|
+
stats = _a.sent();
|
|
42018
|
+
// 🔑 推送变更事件
|
|
42019
|
+
this.emitChangeEvent({
|
|
42020
|
+
path: relativePath,
|
|
42021
|
+
action: 'modify',
|
|
42022
|
+
timestamp: Date.now(),
|
|
42023
|
+
source: 'local',
|
|
42024
|
+
hash: hash,
|
|
42025
|
+
size: stats.size,
|
|
42026
|
+
});
|
|
42027
|
+
return [3 /*break*/, 6];
|
|
42028
|
+
case 5:
|
|
42029
|
+
error_13 = _a.sent();
|
|
42030
|
+
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath), error_13);
|
|
42031
|
+
return [3 /*break*/, 6];
|
|
42032
|
+
case 6: return [2 /*return*/];
|
|
42033
|
+
}
|
|
42034
|
+
});
|
|
42035
|
+
});
|
|
42036
|
+
};
|
|
42037
|
+
/**
|
|
42038
|
+
* 文件新增处理
|
|
42039
|
+
*/
|
|
42040
|
+
ShadowSpace.prototype.onFileAdded = function (filePath) {
|
|
42041
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42042
|
+
var relativePath, content, hash, stats, error_14;
|
|
42043
|
+
return __generator(this, function (_a) {
|
|
42044
|
+
switch (_a.label) {
|
|
42045
|
+
case 0:
|
|
42046
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42047
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u65B0\u589E: ".concat(relativePath));
|
|
42048
|
+
_a.label = 1;
|
|
42049
|
+
case 1:
|
|
42050
|
+
_a.trys.push([1, 4, , 5]);
|
|
42051
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
|
|
42052
|
+
case 2:
|
|
42053
|
+
content = _a.sent();
|
|
42054
|
+
hash = this.calculateHash(content);
|
|
42055
|
+
return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
|
|
42056
|
+
case 3:
|
|
42057
|
+
stats = _a.sent();
|
|
42058
|
+
// 🔑 推送变更事件
|
|
42059
|
+
this.emitChangeEvent({
|
|
42060
|
+
path: relativePath,
|
|
42061
|
+
action: 'add',
|
|
42062
|
+
timestamp: Date.now(),
|
|
42063
|
+
source: 'local',
|
|
42064
|
+
hash: hash,
|
|
42065
|
+
size: stats.size,
|
|
42066
|
+
});
|
|
42067
|
+
return [3 /*break*/, 5];
|
|
42068
|
+
case 4:
|
|
42069
|
+
error_14 = _a.sent();
|
|
42070
|
+
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath), error_14);
|
|
42071
|
+
return [3 /*break*/, 5];
|
|
42072
|
+
case 5: return [2 /*return*/];
|
|
42073
|
+
}
|
|
42074
|
+
});
|
|
42075
|
+
});
|
|
42076
|
+
};
|
|
42077
|
+
/**
|
|
42078
|
+
* 文件删除处理
|
|
42079
|
+
*/
|
|
42080
|
+
ShadowSpace.prototype.onFileDeleted = function (filePath) {
|
|
42081
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42082
|
+
var relativePath, shadowEntry;
|
|
42083
|
+
return __generator(this, function (_a) {
|
|
42084
|
+
switch (_a.label) {
|
|
42085
|
+
case 0:
|
|
42086
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42087
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5220\u9664: ".concat(relativePath));
|
|
42088
|
+
shadowEntry = this.state.files[relativePath];
|
|
42089
|
+
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42090
|
+
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u5220\u9664\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42091
|
+
shadowEntry.remoteModified = false; // 清除标记
|
|
42092
|
+
return [4 /*yield*/, this.saveState()];
|
|
42093
|
+
case 1:
|
|
42094
|
+
_a.sent();
|
|
42095
|
+
return [2 /*return*/];
|
|
42096
|
+
case 2:
|
|
42097
|
+
// 🔑 推送变更事件
|
|
42098
|
+
this.emitChangeEvent({
|
|
42099
|
+
path: relativePath,
|
|
42100
|
+
action: 'delete',
|
|
42101
|
+
timestamp: Date.now(),
|
|
42102
|
+
source: 'local',
|
|
42103
|
+
});
|
|
42104
|
+
return [2 /*return*/];
|
|
42105
|
+
}
|
|
42106
|
+
});
|
|
42107
|
+
});
|
|
42108
|
+
};
|
|
42109
|
+
/**
|
|
42110
|
+
* 获取监听状态
|
|
42111
|
+
*/
|
|
42112
|
+
ShadowSpace.prototype.isFileWatching = function () {
|
|
42113
|
+
return this.isWatching;
|
|
42114
|
+
};
|
|
41854
42115
|
return ShadowSpace;
|
|
41855
42116
|
}());
|
|
41856
42117
|
|
|
42118
|
+
/**
|
|
42119
|
+
* 变更聚合器
|
|
42120
|
+
* 将短时间内的多个文件变更聚合为一次批量推送,减少网络开销
|
|
42121
|
+
*/
|
|
42122
|
+
var ChangeAggregator = /** @class */ (function () {
|
|
42123
|
+
function ChangeAggregator(spaceId, userId, handler, debounceMs) {
|
|
42124
|
+
if (debounceMs === void 0) { debounceMs = 500; }
|
|
42125
|
+
this.pendingChanges = new Map();
|
|
42126
|
+
this.timer = null;
|
|
42127
|
+
this.spaceId = spaceId;
|
|
42128
|
+
this.userId = userId;
|
|
42129
|
+
this.handler = handler;
|
|
42130
|
+
this.debounceMs = debounceMs;
|
|
42131
|
+
}
|
|
42132
|
+
/**
|
|
42133
|
+
* 添加变更
|
|
42134
|
+
*/
|
|
42135
|
+
ChangeAggregator.prototype.addChange = function (change) {
|
|
42136
|
+
var _this = this;
|
|
42137
|
+
console.log("[ChangeAggregator] \u6DFB\u52A0\u53D8\u66F4: ".concat(change.path, " (").concat(change.action, ")"));
|
|
42138
|
+
// 使用文件路径作为 key,相同文件的多次变更只保留最后一次
|
|
42139
|
+
this.pendingChanges.set(change.path, change);
|
|
42140
|
+
// 防抖:重置定时器
|
|
42141
|
+
if (this.timer) {
|
|
42142
|
+
clearTimeout(this.timer);
|
|
42143
|
+
}
|
|
42144
|
+
this.timer = setTimeout(function () {
|
|
42145
|
+
_this.flush();
|
|
42146
|
+
}, this.debounceMs);
|
|
42147
|
+
};
|
|
42148
|
+
/**
|
|
42149
|
+
* 立即推送所有待处理的变更
|
|
42150
|
+
*/
|
|
42151
|
+
ChangeAggregator.prototype.flush = function () {
|
|
42152
|
+
if (this.pendingChanges.size === 0) {
|
|
42153
|
+
return;
|
|
42154
|
+
}
|
|
42155
|
+
var changes = Array.from(this.pendingChanges.values());
|
|
42156
|
+
this.pendingChanges.clear();
|
|
42157
|
+
if (this.timer) {
|
|
42158
|
+
clearTimeout(this.timer);
|
|
42159
|
+
this.timer = null;
|
|
42160
|
+
}
|
|
42161
|
+
console.log("[ChangeAggregator] \u63A8\u9001\u6279\u91CF\u53D8\u66F4: ".concat(changes.length, " \u4E2A\u6587\u4EF6"));
|
|
42162
|
+
// 调用处理器
|
|
42163
|
+
try {
|
|
42164
|
+
this.handler({
|
|
42165
|
+
spaceId: this.spaceId,
|
|
42166
|
+
userId: this.userId,
|
|
42167
|
+
changes: changes,
|
|
42168
|
+
timestamp: Date.now(),
|
|
42169
|
+
});
|
|
42170
|
+
}
|
|
42171
|
+
catch (error) {
|
|
42172
|
+
console.error('[ChangeAggregator] 批量变更处理失败:', error);
|
|
42173
|
+
}
|
|
42174
|
+
};
|
|
42175
|
+
/**
|
|
42176
|
+
* 清理资源
|
|
42177
|
+
*/
|
|
42178
|
+
ChangeAggregator.prototype.destroy = function () {
|
|
42179
|
+
if (this.timer) {
|
|
42180
|
+
clearTimeout(this.timer);
|
|
42181
|
+
this.timer = null;
|
|
42182
|
+
}
|
|
42183
|
+
this.pendingChanges.clear();
|
|
42184
|
+
};
|
|
42185
|
+
/**
|
|
42186
|
+
* 获取待处理变更数量
|
|
42187
|
+
*/
|
|
42188
|
+
ChangeAggregator.prototype.getPendingCount = function () {
|
|
42189
|
+
return this.pendingChanges.size;
|
|
42190
|
+
};
|
|
42191
|
+
return ChangeAggregator;
|
|
42192
|
+
}());
|
|
42193
|
+
|
|
41857
42194
|
/**
|
|
41858
42195
|
* 影子空间WebSocket指令处理器
|
|
41859
42196
|
*/
|
|
41860
42197
|
var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
41861
42198
|
function ShadowSpaceCommandHandler(shadowSpace, socketStore) {
|
|
41862
42199
|
this.currentUserId = null;
|
|
42200
|
+
// 🆕 变更聚合器
|
|
42201
|
+
this.changeAggregator = null;
|
|
41863
42202
|
this.shadowSpace = shadowSpace;
|
|
41864
42203
|
this.socketStore = socketStore;
|
|
41865
42204
|
}
|
|
@@ -41874,11 +42213,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41874
42213
|
* 处理WebSocket消息
|
|
41875
42214
|
*/
|
|
41876
42215
|
ShadowSpaceCommandHandler.prototype.handleMessage = function (data) {
|
|
41877
|
-
var _a, _b, _c, _d, _e, _f;
|
|
42216
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
41878
42217
|
return __awaiter(this, void 0, void 0, function () {
|
|
41879
|
-
var action, messageId, message, spaceInfo, requestSpaceId, result,
|
|
41880
|
-
return __generator(this, function (
|
|
41881
|
-
switch (
|
|
42218
|
+
var action, messageId, message, spaceInfo, requestSpaceId, result, _h, error_1, errorMessage;
|
|
42219
|
+
return __generator(this, function (_j) {
|
|
42220
|
+
switch (_j.label) {
|
|
41882
42221
|
case 0:
|
|
41883
42222
|
action = data.action, messageId = data.messageId, message = data.message;
|
|
41884
42223
|
console.log("[ShadowSpaceCommandHandler] \u6536\u5230\u6D88\u606F: ".concat(action), {
|
|
@@ -41904,12 +42243,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41904
42243
|
// 不发送响应,让其他CLI实例处理
|
|
41905
42244
|
return [2 /*return*/];
|
|
41906
42245
|
}
|
|
41907
|
-
|
|
42246
|
+
_j.label = 1;
|
|
41908
42247
|
case 1:
|
|
41909
|
-
|
|
42248
|
+
_j.trys.push([1, 28, , 29]);
|
|
41910
42249
|
result = void 0;
|
|
41911
|
-
|
|
41912
|
-
switch (
|
|
42250
|
+
_h = action;
|
|
42251
|
+
switch (_h) {
|
|
41913
42252
|
case 'shadow-space-get-changes': return [3 /*break*/, 2];
|
|
41914
42253
|
case 'shadow-space-get-file-content': return [3 /*break*/, 4];
|
|
41915
42254
|
case 'shadow-space-get-files-content': return [3 /*break*/, 6];
|
|
@@ -41921,12 +42260,13 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41921
42260
|
case 'shadow-space-mark-remote-modified': return [3 /*break*/, 18];
|
|
41922
42261
|
case 'shadow-space-clear-remote-flags': return [3 /*break*/, 20];
|
|
41923
42262
|
case 'shadow-space-detect-changes': return [3 /*break*/, 22];
|
|
42263
|
+
case 'shadow-space-discard-changes': return [3 /*break*/, 24];
|
|
41924
42264
|
}
|
|
41925
|
-
return [3 /*break*/,
|
|
42265
|
+
return [3 /*break*/, 26];
|
|
41926
42266
|
case 2: return [4 /*yield*/, this.getChanges()];
|
|
41927
42267
|
case 3:
|
|
41928
|
-
result =
|
|
41929
|
-
return [3 /*break*/,
|
|
42268
|
+
result = _j.sent();
|
|
42269
|
+
return [3 /*break*/, 27];
|
|
41930
42270
|
case 4:
|
|
41931
42271
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message:', JSON.stringify(message, null, 2));
|
|
41932
42272
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message.path:', message.path);
|
|
@@ -41934,57 +42274,61 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41934
42274
|
return [4 /*yield*/, this.getFileContent(((_c = message.message) === null || _c === void 0 ? void 0 : _c.path) || message.path)];
|
|
41935
42275
|
case 5:
|
|
41936
42276
|
// 🆕 修复:路径在 message.message.path 中
|
|
41937
|
-
result =
|
|
41938
|
-
return [3 /*break*/,
|
|
42277
|
+
result = _j.sent();
|
|
42278
|
+
return [3 /*break*/, 27];
|
|
41939
42279
|
case 6: return [4 /*yield*/, this.getFilesContent(((_d = message.message) === null || _d === void 0 ? void 0 : _d.paths) || message.paths)];
|
|
41940
42280
|
case 7:
|
|
41941
42281
|
// 🆕 修复:路径在 message.message.paths 中
|
|
41942
|
-
result =
|
|
41943
|
-
return [3 /*break*/,
|
|
42282
|
+
result = _j.sent();
|
|
42283
|
+
return [3 /*break*/, 27];
|
|
41944
42284
|
case 8: return [4 /*yield*/, this.applyChanges(message.changes)];
|
|
41945
42285
|
case 9:
|
|
41946
|
-
result =
|
|
41947
|
-
return [3 /*break*/,
|
|
42286
|
+
result = _j.sent();
|
|
42287
|
+
return [3 /*break*/, 27];
|
|
41948
42288
|
case 10: return [4 /*yield*/, this.resetShadowSpace()];
|
|
41949
42289
|
case 11:
|
|
41950
|
-
result =
|
|
41951
|
-
return [3 /*break*/,
|
|
42290
|
+
result = _j.sent();
|
|
42291
|
+
return [3 /*break*/, 27];
|
|
41952
42292
|
case 12: return [4 /*yield*/, this.getSpaceInfo()];
|
|
41953
42293
|
case 13:
|
|
41954
|
-
result =
|
|
41955
|
-
return [3 /*break*/,
|
|
42294
|
+
result = _j.sent();
|
|
42295
|
+
return [3 /*break*/, 27];
|
|
41956
42296
|
case 14: return [4 /*yield*/, this.syncFromEditor(message.message.files)];
|
|
41957
42297
|
case 15:
|
|
41958
|
-
result =
|
|
41959
|
-
return [3 /*break*/,
|
|
42298
|
+
result = _j.sent();
|
|
42299
|
+
return [3 /*break*/, 27];
|
|
41960
42300
|
case 16: return [4 /*yield*/, this.deleteFile(message.filePath)];
|
|
41961
42301
|
case 17:
|
|
41962
|
-
result =
|
|
41963
|
-
return [3 /*break*/,
|
|
42302
|
+
result = _j.sent();
|
|
42303
|
+
return [3 /*break*/, 27];
|
|
41964
42304
|
case 18: return [4 /*yield*/, this.markRemoteModified(message.filePaths)];
|
|
41965
42305
|
case 19:
|
|
41966
|
-
result =
|
|
41967
|
-
return [3 /*break*/,
|
|
42306
|
+
result = _j.sent();
|
|
42307
|
+
return [3 /*break*/, 27];
|
|
41968
42308
|
case 20: return [4 /*yield*/, this.clearRemoteFlags(message.filePaths)];
|
|
41969
42309
|
case 21:
|
|
41970
|
-
result =
|
|
41971
|
-
return [3 /*break*/,
|
|
42310
|
+
result = _j.sent();
|
|
42311
|
+
return [3 /*break*/, 27];
|
|
41972
42312
|
case 22: return [4 /*yield*/, this.detectEditorChanges(((_e = message.message) === null || _e === void 0 ? void 0 : _e.spaceId) || message.spaceId, ((_f = message.message) === null || _f === void 0 ? void 0 : _f.files) || message.files)];
|
|
41973
42313
|
case 23:
|
|
41974
|
-
result =
|
|
41975
|
-
return [3 /*break*/,
|
|
41976
|
-
case 24:
|
|
42314
|
+
result = _j.sent();
|
|
42315
|
+
return [3 /*break*/, 27];
|
|
42316
|
+
case 24: return [4 /*yield*/, this.discardChanges(((_g = message.message) === null || _g === void 0 ? void 0 : _g.filePaths) || message.filePaths)];
|
|
41977
42317
|
case 25:
|
|
42318
|
+
result = _j.sent();
|
|
42319
|
+
return [3 /*break*/, 27];
|
|
42320
|
+
case 26: throw new Error("Unknown shadow space action: ".concat(action));
|
|
42321
|
+
case 27:
|
|
41978
42322
|
// 发送成功响应
|
|
41979
42323
|
this.sendResponse(action, messageId, true, result);
|
|
41980
|
-
return [3 /*break*/,
|
|
41981
|
-
case
|
|
41982
|
-
error_1 =
|
|
42324
|
+
return [3 /*break*/, 29];
|
|
42325
|
+
case 28:
|
|
42326
|
+
error_1 = _j.sent();
|
|
41983
42327
|
errorMessage = error_1 instanceof Error ? error_1.message : String(error_1);
|
|
41984
42328
|
console.error("Shadow space command error [".concat(action, "]:"), errorMessage);
|
|
41985
42329
|
this.sendResponse(action, messageId, false, undefined, errorMessage);
|
|
41986
|
-
return [3 /*break*/,
|
|
41987
|
-
case
|
|
42330
|
+
return [3 /*break*/, 29];
|
|
42331
|
+
case 29: return [2 /*return*/];
|
|
41988
42332
|
}
|
|
41989
42333
|
});
|
|
41990
42334
|
});
|
|
@@ -42253,9 +42597,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42253
42597
|
return __awaiter(this, void 0, void 0, function () {
|
|
42254
42598
|
var info;
|
|
42255
42599
|
return __generator(this, function (_a) {
|
|
42256
|
-
console.log('[ShadowSpace] 获取空间信息...');
|
|
42257
42600
|
info = this.shadowSpace.getSpaceInfo();
|
|
42258
|
-
console.log(
|
|
42601
|
+
// console.log(
|
|
42602
|
+
// `[ShadowSpace] 空间信息: ${info.fileCount} 个文件, ${info.totalSize}`
|
|
42603
|
+
// );
|
|
42259
42604
|
return [2 /*return*/, info];
|
|
42260
42605
|
});
|
|
42261
42606
|
});
|
|
@@ -42265,14 +42610,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42265
42610
|
*/
|
|
42266
42611
|
ShadowSpaceCommandHandler.prototype.syncFromEditor = function (files) {
|
|
42267
42612
|
return __awaiter(this, void 0, void 0, function () {
|
|
42268
|
-
var
|
|
42613
|
+
var result;
|
|
42269
42614
|
return __generator(this, function (_a) {
|
|
42270
42615
|
switch (_a.label) {
|
|
42271
42616
|
case 0:
|
|
42272
42617
|
console.log('[ShadowSpace] syncFromEditor 接收到的参数:', {
|
|
42273
42618
|
filesType: typeof files,
|
|
42274
42619
|
isArray: Array.isArray(files),
|
|
42275
|
-
filesValue: files,
|
|
42620
|
+
// filesValue: files,
|
|
42276
42621
|
filesLength: files === null || files === void 0 ? void 0 : files.length,
|
|
42277
42622
|
});
|
|
42278
42623
|
if (!Array.isArray(files)) {
|
|
@@ -42282,11 +42627,6 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42282
42627
|
return [4 /*yield*/, this.shadowSpace.syncFromEditor(files)];
|
|
42283
42628
|
case 1:
|
|
42284
42629
|
_a.sent();
|
|
42285
|
-
filePaths = files.map(function (f) { return f.path; });
|
|
42286
|
-
return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
|
|
42287
|
-
case 2:
|
|
42288
|
-
_a.sent();
|
|
42289
|
-
console.log("[ShadowSpace] \u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
|
|
42290
42630
|
result = {
|
|
42291
42631
|
message: 'Sync from editor completed',
|
|
42292
42632
|
fileCount: files.length,
|
|
@@ -42422,10 +42762,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42422
42762
|
var actualMessage = (data === null || data === void 0 ? void 0 : data.message) || data;
|
|
42423
42763
|
var actualMessageId = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.messageId;
|
|
42424
42764
|
var actualAction = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.action;
|
|
42425
|
-
console.log(
|
|
42765
|
+
// console.log(
|
|
42766
|
+
// `[ShadowSpace] 检查响应: action=${actualAction}, messageId=${actualMessageId}, 期望=${messageId}`
|
|
42767
|
+
// );
|
|
42426
42768
|
if (actualMessageId === messageId &&
|
|
42427
42769
|
actualAction === 'editor-state-response') {
|
|
42428
|
-
console.log(
|
|
42770
|
+
// console.log(`[ShadowSpace] 收到编辑器状态响应`);
|
|
42429
42771
|
clearTimeout(timeout);
|
|
42430
42772
|
if ((_a = actualMessage.message) === null || _a === void 0 ? void 0 : _a.success) {
|
|
42431
42773
|
resolve(actualMessage.message.data);
|
|
@@ -42443,7 +42785,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42443
42785
|
originalOnMessage(data);
|
|
42444
42786
|
}
|
|
42445
42787
|
};
|
|
42446
|
-
console.log(
|
|
42788
|
+
// console.log(
|
|
42789
|
+
// `[ShadowSpace] 临时监听器已设置,发送编辑器状态请求: ${messageId}`
|
|
42790
|
+
// );
|
|
42447
42791
|
// 发送请求
|
|
42448
42792
|
_this.socketStore.sendMessage({
|
|
42449
42793
|
action: 'request-editor-state',
|
|
@@ -42454,7 +42798,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42454
42798
|
});
|
|
42455
42799
|
// 恢复原始处理器(在超时时间之后)
|
|
42456
42800
|
setTimeout(function () {
|
|
42457
|
-
console.log(
|
|
42801
|
+
// console.log(`[ShadowSpace] 恢复原始监听器: ${messageId}`);
|
|
42458
42802
|
_this.socketStore.onmsg = originalOnMessage;
|
|
42459
42803
|
}, 31000);
|
|
42460
42804
|
})];
|
|
@@ -42466,23 +42810,20 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42466
42810
|
*/
|
|
42467
42811
|
ShadowSpaceCommandHandler.prototype.detectEditorChanges = function (spaceId, editorSnapshots) {
|
|
42468
42812
|
return __awaiter(this, void 0, void 0, function () {
|
|
42469
|
-
var safeEditorSnapshots, spaceSnapshots,
|
|
42813
|
+
var safeEditorSnapshots, spaceSnapshots, changes, summary, error_2;
|
|
42470
42814
|
return __generator(this, function (_a) {
|
|
42471
42815
|
switch (_a.label) {
|
|
42472
42816
|
case 0:
|
|
42473
42817
|
_a.trys.push([0, 3, , 4]);
|
|
42474
|
-
console.log('editorSnapshots: ', editorSnapshots);
|
|
42475
42818
|
safeEditorSnapshots = Array.isArray(editorSnapshots)
|
|
42476
42819
|
? editorSnapshots
|
|
42477
42820
|
: [];
|
|
42478
|
-
console.log("[ShadowSpace] \u5F00\u59CB\u68C0\u6D4B\u53D8\u66F4: \u7A7A\u95F4=".concat(spaceId, ", \u7F16\u8F91\u5668\u6587\u4EF6=").concat(safeEditorSnapshots.length, "\u4E2A"));
|
|
42479
42821
|
return [4 /*yield*/, this.shadowSpace.getSpaceSnapshots(spaceId)];
|
|
42480
42822
|
case 1:
|
|
42481
42823
|
spaceSnapshots = _a.sent();
|
|
42482
|
-
|
|
42824
|
+
Array.isArray(spaceSnapshots)
|
|
42483
42825
|
? spaceSnapshots.length
|
|
42484
42826
|
: 0;
|
|
42485
|
-
console.log("[ShadowSpace] \u7A7A\u95F4\u5FEB\u7167: ".concat(snapshotCount, "\u4E2A\u6587\u4EF6"));
|
|
42486
42827
|
return [4 /*yield*/, this.compareSnapshots(safeEditorSnapshots, spaceSnapshots)];
|
|
42487
42828
|
case 2:
|
|
42488
42829
|
changes = _a.sent();
|
|
@@ -42491,7 +42832,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42491
42832
|
needPush: changes.filter(function (c) { return c.side === 'editor'; }).length,
|
|
42492
42833
|
needPull: changes.filter(function (c) { return c.side === 'space'; }).length,
|
|
42493
42834
|
};
|
|
42494
|
-
console.log(
|
|
42835
|
+
// console.log(
|
|
42836
|
+
// `[ShadowSpace] 变更检测完成: 总计${summary.total}个变更, 需推送${summary.needPush}个, 需拉取${summary.needPull}个`
|
|
42837
|
+
// );
|
|
42495
42838
|
return [2 /*return*/, {
|
|
42496
42839
|
success: true,
|
|
42497
42840
|
data: {
|
|
@@ -42518,10 +42861,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42518
42861
|
* 比对编辑器和空间快照
|
|
42519
42862
|
*/
|
|
42520
42863
|
ShadowSpaceCommandHandler.prototype.compareSnapshots = function (editorSnapshots, spaceSnapshots) {
|
|
42864
|
+
var _a, _b, _c;
|
|
42521
42865
|
return __awaiter(this, void 0, void 0, function () {
|
|
42522
|
-
var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1,
|
|
42523
|
-
var e_2,
|
|
42524
|
-
return __generator(this, function (
|
|
42866
|
+
var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _d, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _e, path, spaceFile, editorFile;
|
|
42867
|
+
var e_2, _f, e_3, _g;
|
|
42868
|
+
return __generator(this, function (_h) {
|
|
42525
42869
|
changes = [];
|
|
42526
42870
|
safeEditorSnapshots = Array.isArray(editorSnapshots)
|
|
42527
42871
|
? editorSnapshots
|
|
@@ -42534,7 +42878,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42534
42878
|
try {
|
|
42535
42879
|
// 检测编辑器的变更(新增、修改)
|
|
42536
42880
|
for (editorMap_1 = __values(editorMap), editorMap_1_1 = editorMap_1.next(); !editorMap_1_1.done; editorMap_1_1 = editorMap_1.next()) {
|
|
42537
|
-
|
|
42881
|
+
_d = __read(editorMap_1_1.value, 2), path = _d[0], editorFile = _d[1];
|
|
42538
42882
|
spaceFile = spaceMap.get(path);
|
|
42539
42883
|
if (!spaceFile) {
|
|
42540
42884
|
// 编辑器新增的文件
|
|
@@ -42551,9 +42895,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42551
42895
|
else if (editorFile.hash !== spaceFile.remoteHash) {
|
|
42552
42896
|
// 编辑器修改的文件(基于云端哈希比对)
|
|
42553
42897
|
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7F16\u8F91\u5668\u4FEE\u6539: ".concat(path), {
|
|
42554
|
-
editorHash: editorFile.hash,
|
|
42555
|
-
spaceRemoteHash: spaceFile.remoteHash,
|
|
42556
|
-
spaceLocalHash: spaceFile.hash,
|
|
42898
|
+
editorHash: (_a = editorFile.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
|
|
42899
|
+
spaceRemoteHash: (_b = spaceFile.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
|
|
42900
|
+
spaceLocalHash: (_c = spaceFile.hash) === null || _c === void 0 ? void 0 : _c.substring(0, 16),
|
|
42901
|
+
editorHashFull: editorFile.hash,
|
|
42902
|
+
spaceRemoteHashFull: spaceFile.remoteHash,
|
|
42557
42903
|
});
|
|
42558
42904
|
changes.push({
|
|
42559
42905
|
action: 'modify',
|
|
@@ -42570,14 +42916,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42570
42916
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
42571
42917
|
finally {
|
|
42572
42918
|
try {
|
|
42573
|
-
if (editorMap_1_1 && !editorMap_1_1.done && (
|
|
42919
|
+
if (editorMap_1_1 && !editorMap_1_1.done && (_f = editorMap_1.return)) _f.call(editorMap_1);
|
|
42574
42920
|
}
|
|
42575
42921
|
finally { if (e_2) throw e_2.error; }
|
|
42576
42922
|
}
|
|
42577
42923
|
try {
|
|
42578
42924
|
// 检测空间的变更(删除、空间独有的修改)
|
|
42579
42925
|
for (spaceMap_1 = __values(spaceMap), spaceMap_1_1 = spaceMap_1.next(); !spaceMap_1_1.done; spaceMap_1_1 = spaceMap_1.next()) {
|
|
42580
|
-
|
|
42926
|
+
_e = __read(spaceMap_1_1.value, 2), path = _e[0], spaceFile = _e[1];
|
|
42581
42927
|
editorFile = editorMap.get(path);
|
|
42582
42928
|
if (!editorFile) {
|
|
42583
42929
|
// 空间独有的文件(编辑器已删除)
|
|
@@ -42597,7 +42943,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42597
42943
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
42598
42944
|
finally {
|
|
42599
42945
|
try {
|
|
42600
|
-
if (spaceMap_1_1 && !spaceMap_1_1.done && (
|
|
42946
|
+
if (spaceMap_1_1 && !spaceMap_1_1.done && (_g = spaceMap_1.return)) _g.call(spaceMap_1);
|
|
42601
42947
|
}
|
|
42602
42948
|
finally { if (e_3) throw e_3.error; }
|
|
42603
42949
|
}
|
|
@@ -42605,12 +42951,132 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42605
42951
|
});
|
|
42606
42952
|
});
|
|
42607
42953
|
};
|
|
42954
|
+
/**
|
|
42955
|
+
* 放弃本地变更
|
|
42956
|
+
* 将影子空间的状态更新为编辑器的版本,不再提示这些文件有变更
|
|
42957
|
+
*/
|
|
42958
|
+
ShadowSpaceCommandHandler.prototype.discardChanges = function (filePaths) {
|
|
42959
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42960
|
+
var editorState, editorFiles;
|
|
42961
|
+
return __generator(this, function (_a) {
|
|
42962
|
+
switch (_a.label) {
|
|
42963
|
+
case 0:
|
|
42964
|
+
if (!filePaths || filePaths.length === 0) {
|
|
42965
|
+
throw new Error('No file paths provided');
|
|
42966
|
+
}
|
|
42967
|
+
console.log("[ShadowSpace] \u653E\u5F03\u53D8\u66F4: ".concat(filePaths.length, " \u4E2A\u6587\u4EF6"));
|
|
42968
|
+
return [4 /*yield*/, this.requestEditorState()];
|
|
42969
|
+
case 1:
|
|
42970
|
+
editorState = _a.sent();
|
|
42971
|
+
if (!editorState || !editorState.files) {
|
|
42972
|
+
throw new Error('Failed to get editor state');
|
|
42973
|
+
}
|
|
42974
|
+
editorFiles = editorState.files.filter(function (f) {
|
|
42975
|
+
return filePaths.includes(f.path);
|
|
42976
|
+
});
|
|
42977
|
+
console.log("[ShadowSpace] \u4ECE\u7F16\u8F91\u5668\u83B7\u53D6\u5230 ".concat(editorFiles.length, " \u4E2A\u6587\u4EF6"));
|
|
42978
|
+
if (editorFiles.length === 0) {
|
|
42979
|
+
throw new Error('No matching files found in editor');
|
|
42980
|
+
}
|
|
42981
|
+
// 同步到影子空间(覆盖本地变更)
|
|
42982
|
+
return [4 /*yield*/, this.shadowSpace.syncFromEditor(editorFiles)];
|
|
42983
|
+
case 2:
|
|
42984
|
+
// 同步到影子空间(覆盖本地变更)
|
|
42985
|
+
_a.sent();
|
|
42986
|
+
// 标记为远程修改,避免再次检测
|
|
42987
|
+
return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
|
|
42988
|
+
case 3:
|
|
42989
|
+
// 标记为远程修改,避免再次检测
|
|
42990
|
+
_a.sent();
|
|
42991
|
+
console.log("[ShadowSpace] \u6210\u529F\u653E\u5F03 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u7684\u53D8\u66F4"));
|
|
42992
|
+
return [2 /*return*/, {
|
|
42993
|
+
message: 'Changes discarded successfully',
|
|
42994
|
+
fileCount: filePaths.length,
|
|
42995
|
+
discardedFiles: filePaths,
|
|
42996
|
+
timestamp: Date.now(),
|
|
42997
|
+
}];
|
|
42998
|
+
}
|
|
42999
|
+
});
|
|
43000
|
+
});
|
|
43001
|
+
};
|
|
42608
43002
|
/**
|
|
42609
43003
|
* 生成消息ID
|
|
42610
43004
|
*/
|
|
42611
43005
|
ShadowSpaceCommandHandler.prototype.generateMessageId = function () {
|
|
42612
43006
|
return "msg_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
42613
43007
|
};
|
|
43008
|
+
// ==================== 🆕 文件监听功能 ====================
|
|
43009
|
+
/**
|
|
43010
|
+
* 启动文件监听
|
|
43011
|
+
*/
|
|
43012
|
+
ShadowSpaceCommandHandler.prototype.startFileWatching = function () {
|
|
43013
|
+
var _this = this;
|
|
43014
|
+
if (!this.currentUserId) {
|
|
43015
|
+
console.error('[ShadowSpace] 无法启动文件监听:用户ID未设置');
|
|
43016
|
+
return;
|
|
43017
|
+
}
|
|
43018
|
+
var spaceInfo = this.shadowSpace.getSpaceInfo();
|
|
43019
|
+
console.log('[ShadowSpace] 启动文件监听和变更聚合...');
|
|
43020
|
+
// 创建变更聚合器
|
|
43021
|
+
this.changeAggregator = new ChangeAggregator(spaceInfo.spaceId, spaceInfo.userId, function (event) { return _this.handleBatchChange(event); }, 500 // 500ms 防抖
|
|
43022
|
+
);
|
|
43023
|
+
// 添加变更监听器
|
|
43024
|
+
this.shadowSpace.addChangeListener(function (change) {
|
|
43025
|
+
if (_this.changeAggregator) {
|
|
43026
|
+
_this.changeAggregator.addChange(change);
|
|
43027
|
+
}
|
|
43028
|
+
});
|
|
43029
|
+
// 启动文件监听
|
|
43030
|
+
this.shadowSpace.startWatching();
|
|
43031
|
+
console.log('[ShadowSpace] 文件监听和变更聚合已启动');
|
|
43032
|
+
};
|
|
43033
|
+
/**
|
|
43034
|
+
* 停止文件监听
|
|
43035
|
+
*/
|
|
43036
|
+
ShadowSpaceCommandHandler.prototype.stopFileWatching = function () {
|
|
43037
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
43038
|
+
return __generator(this, function (_a) {
|
|
43039
|
+
switch (_a.label) {
|
|
43040
|
+
case 0:
|
|
43041
|
+
console.log('[ShadowSpace] 停止文件监听和变更聚合...');
|
|
43042
|
+
// 停止文件监听
|
|
43043
|
+
return [4 /*yield*/, this.shadowSpace.stopWatching()];
|
|
43044
|
+
case 1:
|
|
43045
|
+
// 停止文件监听
|
|
43046
|
+
_a.sent();
|
|
43047
|
+
// 销毁变更聚合器
|
|
43048
|
+
if (this.changeAggregator) {
|
|
43049
|
+
this.changeAggregator.destroy();
|
|
43050
|
+
this.changeAggregator = null;
|
|
43051
|
+
}
|
|
43052
|
+
console.log('[ShadowSpace] 文件监听和变更聚合已停止');
|
|
43053
|
+
return [2 /*return*/];
|
|
43054
|
+
}
|
|
43055
|
+
});
|
|
43056
|
+
});
|
|
43057
|
+
};
|
|
43058
|
+
/**
|
|
43059
|
+
* 处理批量变更
|
|
43060
|
+
*/
|
|
43061
|
+
ShadowSpaceCommandHandler.prototype.handleBatchChange = function (event) {
|
|
43062
|
+
console.log("[ShadowSpace] \u63A8\u9001\u6279\u91CF\u53D8\u66F4\u4E8B\u4EF6: ".concat(event.changes.length, " \u4E2A\u6587\u4EF6"));
|
|
43063
|
+
// 推送批量变更事件到编辑器
|
|
43064
|
+
this.socketStore.sendMessage({
|
|
43065
|
+
action: 'shadow-space-batch-changed',
|
|
43066
|
+
message: {
|
|
43067
|
+
spaceId: event.spaceId,
|
|
43068
|
+
userId: event.userId,
|
|
43069
|
+
changes: event.changes,
|
|
43070
|
+
timestamp: event.timestamp,
|
|
43071
|
+
},
|
|
43072
|
+
});
|
|
43073
|
+
};
|
|
43074
|
+
/**
|
|
43075
|
+
* 获取监听状态
|
|
43076
|
+
*/
|
|
43077
|
+
ShadowSpaceCommandHandler.prototype.isWatching = function () {
|
|
43078
|
+
return this.shadowSpace.isFileWatching();
|
|
43079
|
+
};
|
|
42614
43080
|
return ShadowSpaceCommandHandler;
|
|
42615
43081
|
}());
|
|
42616
43082
|
|
|
@@ -42750,11 +43216,31 @@ function startConnecting(options) {
|
|
|
42750
43216
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u5904\u7406\u5668\u5DF2\u521D\u59CB\u5316\uFF0C\u57FA\u7840\u76EE\u5F55: ").concat(fileOperationConfig.baseDir));
|
|
42751
43217
|
shadowSpace_1 = null;
|
|
42752
43218
|
shadowSpaceHandler_1 = null;
|
|
42753
|
-
cleanup_1 = function () {
|
|
42754
|
-
|
|
42755
|
-
|
|
42756
|
-
|
|
42757
|
-
|
|
43219
|
+
cleanup_1 = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
43220
|
+
return __generator(this, function (_a) {
|
|
43221
|
+
switch (_a.label) {
|
|
43222
|
+
case 0:
|
|
43223
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6B63\u5728\u6E05\u7406..."));
|
|
43224
|
+
if (!shadowSpaceHandler_1) return [3 /*break*/, 4];
|
|
43225
|
+
_a.label = 1;
|
|
43226
|
+
case 1:
|
|
43227
|
+
_a.trys.push([1, 3, , 4]);
|
|
43228
|
+
return [4 /*yield*/, shadowSpaceHandler_1.stopFileWatching()];
|
|
43229
|
+
case 2:
|
|
43230
|
+
_a.sent();
|
|
43231
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u505C\u6B62"));
|
|
43232
|
+
return [3 /*break*/, 4];
|
|
43233
|
+
case 3:
|
|
43234
|
+
_a.sent();
|
|
43235
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u505C\u6B62\u6587\u4EF6\u76D1\u542C\u5931\u8D25:"));
|
|
43236
|
+
return [3 /*break*/, 4];
|
|
43237
|
+
case 4:
|
|
43238
|
+
removePidFile();
|
|
43239
|
+
process.exit(0);
|
|
43240
|
+
return [2 /*return*/];
|
|
43241
|
+
}
|
|
43242
|
+
});
|
|
43243
|
+
}); };
|
|
42758
43244
|
process.on('SIGINT', cleanup_1);
|
|
42759
43245
|
process.on('SIGTERM', cleanup_1);
|
|
42760
43246
|
process.on('uncaughtException', function (error) {
|
|
@@ -42786,6 +43272,9 @@ function startConnecting(options) {
|
|
|
42786
43272
|
// 初始化影子空间指令处理器
|
|
42787
43273
|
shadowSpaceHandler_1 = new ShadowSpaceCommandHandler(shadowSpace_1, currentSocket);
|
|
42788
43274
|
shadowSpaceHandler_1.setCurrentUserId(account);
|
|
43275
|
+
// 🆕 启动文件监听
|
|
43276
|
+
shadowSpaceHandler_1.startFileWatching();
|
|
43277
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u542F\u52A8"));
|
|
42789
43278
|
return [3 /*break*/, 3];
|
|
42790
43279
|
case 2:
|
|
42791
43280
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u8DF3\u8FC7\u5F71\u5B50\u7A7A\u95F4\u521D\u59CB\u5316\uFF08\u672A\u542F\u7528workspace\u6A21\u5F0F\uFF09"));
|
|
@@ -42811,13 +43300,11 @@ function startConnecting(options) {
|
|
|
42811
43300
|
}, 5000);
|
|
42812
43301
|
},
|
|
42813
43302
|
onmsg: function (data) { return __awaiter(_this, void 0, void 0, function () {
|
|
42814
|
-
var action, message, extracted, normalizedData, result, _a,
|
|
43303
|
+
var action, message, extracted, normalizedData, result, _a, error_3, error_4, userId, current, cwd, type, change, filePath;
|
|
42815
43304
|
var _b, _c;
|
|
42816
43305
|
return __generator(this, function (_d) {
|
|
42817
43306
|
switch (_d.label) {
|
|
42818
43307
|
case 0:
|
|
42819
|
-
// if (DEV_MODE) {
|
|
42820
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6536\u5230\u6D88\u606F: ").concat(JSON.stringify(data)));
|
|
42821
43308
|
if (data === null || data === void 0 ? void 0 : data.action) {
|
|
42822
43309
|
// 直接格式
|
|
42823
43310
|
action = data.action;
|
|
@@ -42890,8 +43377,8 @@ function startConnecting(options) {
|
|
|
42890
43377
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u5DF2\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ").concat(message.message.path));
|
|
42891
43378
|
return [3 /*break*/, 11];
|
|
42892
43379
|
case 10:
|
|
42893
|
-
|
|
42894
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(
|
|
43380
|
+
error_3 = _d.sent();
|
|
43381
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(error_3));
|
|
42895
43382
|
return [3 /*break*/, 11];
|
|
42896
43383
|
case 11: return [3 /*break*/, 23];
|
|
42897
43384
|
case 12: return [4 /*yield*/, fileHandler_1.readFile(message.path, message.encoding)];
|
|
@@ -42933,13 +43420,13 @@ function startConnecting(options) {
|
|
|
42933
43420
|
});
|
|
42934
43421
|
return [3 /*break*/, 25];
|
|
42935
43422
|
case 24:
|
|
42936
|
-
|
|
42937
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(
|
|
43423
|
+
error_4 = _d.sent();
|
|
43424
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(error_4));
|
|
42938
43425
|
currentSocket === null || currentSocket === void 0 ? void 0 : currentSocket.sendMessage({
|
|
42939
43426
|
action: "".concat(action, "-response"),
|
|
42940
43427
|
message: {
|
|
42941
43428
|
success: false,
|
|
42942
|
-
error:
|
|
43429
|
+
error: error_4 instanceof Error ? error_4.message : String(error_4),
|
|
42943
43430
|
},
|
|
42944
43431
|
});
|
|
42945
43432
|
return [3 /*break*/, 25];
|
|
@@ -48298,6 +48785,1155 @@ function cleanupOldLogs(logDir, debugDir) {
|
|
|
48298
48785
|
});
|
|
48299
48786
|
}
|
|
48300
48787
|
|
|
48788
|
+
/**
|
|
48789
|
+
* AI 工具配置
|
|
48790
|
+
*/
|
|
48791
|
+
var AI_TOOLS = [
|
|
48792
|
+
{
|
|
48793
|
+
name: '🤖 Claude Code (Anthropic 官方)',
|
|
48794
|
+
value: 'claude-code',
|
|
48795
|
+
description: '支持 Hooks 和 TSX 检查器',
|
|
48796
|
+
},
|
|
48797
|
+
{
|
|
48798
|
+
name: '🎯 Cursor (AI-first IDE)',
|
|
48799
|
+
value: 'cursor',
|
|
48800
|
+
description: '支持 Rules 和自定义指令',
|
|
48801
|
+
},
|
|
48802
|
+
{
|
|
48803
|
+
name: '🌊 Windsurf (Codeium)',
|
|
48804
|
+
value: 'windsurf',
|
|
48805
|
+
description: '支持 Cascade 配置',
|
|
48806
|
+
},
|
|
48807
|
+
{
|
|
48808
|
+
name: '☁️ 阿里云 Coder',
|
|
48809
|
+
value: 'coder',
|
|
48810
|
+
description: '支持模板配置',
|
|
48811
|
+
},
|
|
48812
|
+
{
|
|
48813
|
+
name: '🔧 Augment (VSCode 插件)',
|
|
48814
|
+
value: 'augment',
|
|
48815
|
+
description: '支持上下文配置',
|
|
48816
|
+
},
|
|
48817
|
+
{
|
|
48818
|
+
name: '⏭️ 其他 / 跳过',
|
|
48819
|
+
value: 'other',
|
|
48820
|
+
description: '只生成基础配置',
|
|
48821
|
+
},
|
|
48822
|
+
];
|
|
48823
|
+
|
|
48824
|
+
/**
|
|
48825
|
+
* 基础生成器 - 生成通用的 Space 配置文件
|
|
48826
|
+
*/
|
|
48827
|
+
var BaseGenerator = /** @class */ (function () {
|
|
48828
|
+
function BaseGenerator(cwd, config, verbose) {
|
|
48829
|
+
this.cwd = cwd;
|
|
48830
|
+
this.config = config;
|
|
48831
|
+
this.verbose = verbose;
|
|
48832
|
+
}
|
|
48833
|
+
/**
|
|
48834
|
+
* 生成基础配置文件
|
|
48835
|
+
*/
|
|
48836
|
+
BaseGenerator.prototype.generate = function (skipPrompts) {
|
|
48837
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48838
|
+
var files, appthenDir, configFile, gitignoreFile, promptFiles, error_1;
|
|
48839
|
+
return __generator(this, function (_a) {
|
|
48840
|
+
switch (_a.label) {
|
|
48841
|
+
case 0:
|
|
48842
|
+
files = [];
|
|
48843
|
+
_a.label = 1;
|
|
48844
|
+
case 1:
|
|
48845
|
+
_a.trys.push([1, 6, , 7]);
|
|
48846
|
+
appthenDir = path__namespace.join(this.cwd, '.appthen');
|
|
48847
|
+
this.ensureDirectory(appthenDir);
|
|
48848
|
+
return [4 /*yield*/, this.createSpaceConfig(appthenDir)];
|
|
48849
|
+
case 2:
|
|
48850
|
+
configFile = _a.sent();
|
|
48851
|
+
files.push(configFile);
|
|
48852
|
+
return [4 /*yield*/, this.createGitignore(appthenDir)];
|
|
48853
|
+
case 3:
|
|
48854
|
+
gitignoreFile = _a.sent();
|
|
48855
|
+
files.push(gitignoreFile);
|
|
48856
|
+
if (!!skipPrompts) return [3 /*break*/, 5];
|
|
48857
|
+
return [4 /*yield*/, this.createPrompts(appthenDir)];
|
|
48858
|
+
case 4:
|
|
48859
|
+
promptFiles = _a.sent();
|
|
48860
|
+
files.push.apply(files, __spreadArray([], __read(promptFiles), false));
|
|
48861
|
+
_a.label = 5;
|
|
48862
|
+
case 5: return [2 /*return*/, {
|
|
48863
|
+
success: true,
|
|
48864
|
+
files: files,
|
|
48865
|
+
message: 'Base configuration created successfully',
|
|
48866
|
+
}];
|
|
48867
|
+
case 6:
|
|
48868
|
+
error_1 = _a.sent();
|
|
48869
|
+
return [2 /*return*/, {
|
|
48870
|
+
success: false,
|
|
48871
|
+
files: [],
|
|
48872
|
+
error: error_1.message,
|
|
48873
|
+
}];
|
|
48874
|
+
case 7: return [2 /*return*/];
|
|
48875
|
+
}
|
|
48876
|
+
});
|
|
48877
|
+
});
|
|
48878
|
+
};
|
|
48879
|
+
/**
|
|
48880
|
+
* 确保目录存在
|
|
48881
|
+
*/
|
|
48882
|
+
BaseGenerator.prototype.ensureDirectory = function (dir) {
|
|
48883
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
48884
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
48885
|
+
if (this.verbose) {
|
|
48886
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(dir));
|
|
48887
|
+
}
|
|
48888
|
+
}
|
|
48889
|
+
};
|
|
48890
|
+
/**
|
|
48891
|
+
* 创建 space-config.json
|
|
48892
|
+
*/
|
|
48893
|
+
BaseGenerator.prototype.createSpaceConfig = function (appthenDir) {
|
|
48894
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48895
|
+
var configPath, configContent;
|
|
48896
|
+
return __generator(this, function (_a) {
|
|
48897
|
+
configPath = path__namespace.join(appthenDir, 'space-config.json');
|
|
48898
|
+
configContent = __assign(__assign({}, this.config), {
|
|
48899
|
+
// 添加一些额外的配置
|
|
48900
|
+
settings: {
|
|
48901
|
+
autoSync: true,
|
|
48902
|
+
watchPatterns: ['src/**/*', 'docs/**/*'],
|
|
48903
|
+
ignorePatterns: [
|
|
48904
|
+
'node_modules/**',
|
|
48905
|
+
'dist/**',
|
|
48906
|
+
'build/**',
|
|
48907
|
+
'.git/**',
|
|
48908
|
+
'*.log',
|
|
48909
|
+
],
|
|
48910
|
+
} });
|
|
48911
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(configContent, null, 2));
|
|
48912
|
+
if (this.verbose) {
|
|
48913
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
48914
|
+
}
|
|
48915
|
+
return [2 /*return*/, configPath];
|
|
48916
|
+
});
|
|
48917
|
+
});
|
|
48918
|
+
};
|
|
48919
|
+
/**
|
|
48920
|
+
* 创建 .gitignore
|
|
48921
|
+
*/
|
|
48922
|
+
BaseGenerator.prototype.createGitignore = function (appthenDir) {
|
|
48923
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48924
|
+
var gitignorePath, gitignoreContent;
|
|
48925
|
+
return __generator(this, function (_a) {
|
|
48926
|
+
gitignorePath = path__namespace.join(appthenDir, '.gitignore');
|
|
48927
|
+
gitignoreContent = "# Shadow Space \u6587\u4EF6\nshadow-space-*.json\n\n# \u65E5\u5FD7\u6587\u4EF6\n*.log\n\n# \u4E34\u65F6\u6587\u4EF6\n*.tmp\n.DS_Store\n\n# \u7F16\u8F91\u5668\u914D\u7F6E\uFF08\u53EF\u9009\uFF09\n# .vscode/\n# .idea/\n";
|
|
48928
|
+
fs__namespace.writeFileSync(gitignorePath, gitignoreContent);
|
|
48929
|
+
if (this.verbose) {
|
|
48930
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA .gitignore: ".concat(gitignorePath));
|
|
48931
|
+
}
|
|
48932
|
+
return [2 /*return*/, gitignorePath];
|
|
48933
|
+
});
|
|
48934
|
+
});
|
|
48935
|
+
};
|
|
48936
|
+
/**
|
|
48937
|
+
* 创建提示词目录和文件
|
|
48938
|
+
*/
|
|
48939
|
+
BaseGenerator.prototype.createPrompts = function (appthenDir) {
|
|
48940
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48941
|
+
var files, promptsDir, readmeFile, templateFiles;
|
|
48942
|
+
return __generator(this, function (_a) {
|
|
48943
|
+
switch (_a.label) {
|
|
48944
|
+
case 0:
|
|
48945
|
+
files = [];
|
|
48946
|
+
promptsDir = path__namespace.join(appthenDir, 'prompts');
|
|
48947
|
+
this.ensureDirectory(promptsDir);
|
|
48948
|
+
return [4 /*yield*/, this.createPromptsReadme(promptsDir)];
|
|
48949
|
+
case 1:
|
|
48950
|
+
readmeFile = _a.sent();
|
|
48951
|
+
files.push(readmeFile);
|
|
48952
|
+
return [4 /*yield*/, this.copyTemplateFiles(promptsDir)];
|
|
48953
|
+
case 2:
|
|
48954
|
+
templateFiles = _a.sent();
|
|
48955
|
+
files.push.apply(files, __spreadArray([], __read(templateFiles), false));
|
|
48956
|
+
return [2 /*return*/, files];
|
|
48957
|
+
}
|
|
48958
|
+
});
|
|
48959
|
+
});
|
|
48960
|
+
};
|
|
48961
|
+
/**
|
|
48962
|
+
* 创建提示词 README
|
|
48963
|
+
*/
|
|
48964
|
+
BaseGenerator.prototype.createPromptsReadme = function (promptsDir) {
|
|
48965
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48966
|
+
var readmePath, readmeContent;
|
|
48967
|
+
return __generator(this, function (_a) {
|
|
48968
|
+
readmePath = path__namespace.join(promptsDir, 'README.md');
|
|
48969
|
+
readmeContent = "# Agent+ Space \u63D0\u793A\u8BCD\n\n\u8FD9\u4E2A\u76EE\u5F55\u5305\u542B\u4E86\u7528\u4E8E AI \u7F16\u7801\u5DE5\u5177\u7684\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u5E2E\u52A9 AI \u7406\u89E3\u9879\u76EE\u89C4\u8303\u5E76\u751F\u6210\u7B26\u5408\u8981\u6C42\u7684\u4EE3\u7801\u3002\n\n## \uD83D\uDCDA \u63D0\u793A\u8BCD\u6587\u4EF6\u8BF4\u660E\n\n### \u6838\u5FC3\u6587\u6863\n\n1. **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357 \u2B50\n - \u9879\u76EE\u6982\u8FF0\u548C\u7ED3\u6784\n - \u5F00\u53D1\u89C4\u8303\u548C\u6D41\u7A0B\n - \u5FEB\u901F\u5F00\u59CB\u6307\u5357\n - \u6700\u4F73\u5B9E\u8DF5\n\n2. **tsx-generation.md** - TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303 \u2B50\u2B50\u2B50\n - \u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\u8981\u6C42\n - \u4E25\u683C\u7684 render() \u65B9\u6CD5\u7EA6\u675F\n - TypeScript \u8BED\u6CD5\u9650\u5236\n - JSX \u4F4D\u7F6E\u9650\u5236\n - \u5B8C\u6574\u793A\u4F8B\u4EE3\u7801\n - \u5E38\u89C1\u9519\u8BEF\u548C\u4FEE\u590D\n\n3. **decision-tree.md** - AI \u51B3\u7B56\u6811 \u2B50\u2B50\n - \u5E2E\u52A9 AI \u505A\u51FA\u6B63\u786E\u51B3\u7B56\n - \u5173\u952E\u51B3\u7B56\u70B9\u8BF4\u660E\n - \u5E38\u89C1\u9519\u8BEF\u51B3\u7B56\u5206\u6790\n - \u62D2\u7EDD\u751F\u6210\u7684\u6807\u51C6\u54CD\u5E94\n\n4. **validation-checklist.md** - \u9A8C\u8BC1\u6E05\u5355 \u2B50\u2B50\n - \u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6D41\u7A0B\n - 8 \u4E2A\u9636\u6BB5\u7684\u68C0\u67E5\u9879\n - \u5E38\u89C1\u9519\u8BEF\u68C0\u67E5\n - \u9A8C\u8BC1\u5DE5\u5177\u4F7F\u7528\n\n5. **code-review.md** - \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n - \u5BA1\u67E5\u68C0\u67E5\u6E05\u5355\n - \u5E38\u89C1\u95EE\u9898\u8BC6\u522B\n - \u53CD\u9988\u6A21\u677F\n\n6. **refactoring.md** - \u91CD\u6784\u6307\u5357\n - \u91CD\u6784\u539F\u5219\n - \u5E38\u89C1\u91CD\u6784\u6A21\u5F0F\n - \u6027\u80FD\u4F18\u5316\u6280\u5DE7\n\n## \uD83D\uDE80 \u4F7F\u7528\u65B9\u6CD5\n\n### \u5BF9\u4E8E\u5F00\u53D1\u8005\n\n1. **\u9996\u6B21\u5F00\u53D1\u524D**\uFF1A\u9605\u8BFB `project-guide.md` \u4E86\u89E3\u9879\u76EE\u6982\u51B5\n2. **\u7F16\u5199 TSX \u4EE3\u7801\u524D**\uFF1A\u8BE6\u7EC6\u9605\u8BFB `tsx-generation.md`\n3. **\u4EE3\u7801\u9A8C\u8BC1**\uFF1A\u4F7F\u7528 `validation-checklist.md` \u8FDB\u884C\u81EA\u67E5\n4. **\u4EE3\u7801\u5BA1\u67E5**\uFF1A\u53C2\u8003 `code-review.md` \u8FDB\u884C\u5BA1\u67E5\n\n### \u5BF9\u4E8E AI \u5DE5\u5177\n\n\u6839\u636E\u4F60\u4F7F\u7528\u7684 AI \u5DE5\u5177\uFF0C\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230\u5BF9\u5E94\u7684\u914D\u7F6E\u4E2D\uFF1A\n\n#### Claude Code\n\u5728\u5BF9\u8BDD\u4E2D\u76F4\u63A5\u5F15\u7528\u8FD9\u4E9B\u63D0\u793A\u8BCD\uFF0C\u6216\u8005\u6DFB\u52A0\u5230\u9879\u76EE\u7684 `.claude/` \u914D\u7F6E\u4E2D\u3002\n\n#### Cursor\n\u5C06\u63D0\u793A\u8BCD\u5185\u5BB9\u6DFB\u52A0\u5230 `.cursor/rules.md` \u6587\u4EF6\u4E2D\u3002\n\n#### Windsurf\n\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230 Cascade \u914D\u7F6E\u4E2D\u3002\n\n#### \u963F\u91CC\u4E91 Coder\n\u5728 Coder \u7684\u8BBE\u7F6E\u4E2D\u6DFB\u52A0\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002\n\n#### Augment\n\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230 `.augment/context/` \u76EE\u5F55\u4E2D\u3002\n\n## \u26A0\uFE0F \u91CD\u8981\u63D0\u793A\n\n### TSX \u4EE3\u7801\u5FC5\u987B\u7B26\u5408\u89C4\u8303\n- \u4E0D\u7B26\u5408\u89C4\u8303\u7684\u4EE3\u7801\u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\n- \u5FC5\u987B\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\n- \u7981\u6B62\u4F7F\u7528\u6807\u51C6\u7684 lint/format \u5DE5\u5177\n\n### AI \u5DE5\u5177\u914D\u7F6E\n- \u5C06\u8FD9\u4E9B\u63D0\u793A\u8BCD\u6587\u4EF6\u6DFB\u52A0\u5230 AI \u5DE5\u5177\u7684\u4E0A\u4E0B\u6587\u4E2D\n- \u786E\u4FDD AI \u7406\u89E3\u5E76\u9075\u5B88\u6240\u6709\u7EA6\u675F\n- \u5F53\u4E0D\u786E\u5B9A\u65F6\uFF0CAI \u5E94\u8BE5\u62D2\u7EDD\u751F\u6210\u800C\u4E0D\u662F\u5192\u9669\n\n## \uD83D\uDEE0\uFE0F \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\n\n\u4F60\u53EF\u4EE5\u6839\u636E\u9879\u76EE\u9700\u6C42\u6DFB\u52A0\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6587\u4EF6\uFF1A\n\n- `api-design.md`: API \u8BBE\u8BA1\u89C4\u8303\n- `testing.md`: \u6D4B\u8BD5\u7F16\u5199\u6307\u5357\n- `styling.md`: \u6837\u5F0F\u7F16\u5199\u89C4\u8303\n- `performance.md`: \u6027\u80FD\u4F18\u5316\u6307\u5357\n- `backend-guide.md`: \u540E\u7AEF\u5F00\u53D1\u6307\u5357\uFF08midwayjs\uFF09\n\n## \uD83D\uDD04 \u66F4\u65B0\u63D0\u793A\u8BCD\n\n\u63D0\u793A\u8BCD\u4F1A\u968F\u7740\u9879\u76EE\u89C4\u8303\u7684\u6F14\u8FDB\u800C\u66F4\u65B0\uFF1A\n- \u5B9A\u671F\u68C0\u67E5\u5E76\u66F4\u65B0\u8FD9\u4E9B\u6587\u4EF6\n- \u6839\u636E\u5B9E\u9645\u95EE\u9898\u8865\u5145\u65B0\u7684\u89C4\u5219\n- \u8BB0\u5F55\u5E38\u89C1\u9519\u8BEF\u548C\u89E3\u51B3\u65B9\u6848\n\n## \uD83D\uDCAC \u53CD\u9988\u548C\u6539\u8FDB\n\n\u5982\u679C\u4F60\u53D1\u73B0\u63D0\u793A\u8BCD\u6709\u95EE\u9898\u6216\u6709\u6539\u8FDB\u5EFA\u8BAE\uFF1A\n- \u5728\u9879\u76EE\u4E2D\u521B\u5EFA Issue\n- \u76F4\u63A5\u4FEE\u6539\u63D0\u793A\u8BCD\u6587\u4EF6\u5E76\u63D0\u4EA4 PR\n- \u4E0E\u56E2\u961F\u5206\u4EAB\u4F60\u7684\u7ECF\u9A8C\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01** \uD83C\uDFAF\n";
|
|
48970
|
+
fs__namespace.writeFileSync(readmePath, readmeContent);
|
|
48971
|
+
if (this.verbose) {
|
|
48972
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u63D0\u793A\u8BCD README: ".concat(readmePath));
|
|
48973
|
+
}
|
|
48974
|
+
return [2 /*return*/, readmePath];
|
|
48975
|
+
});
|
|
48976
|
+
});
|
|
48977
|
+
};
|
|
48978
|
+
/**
|
|
48979
|
+
* 复制模板文件到提示词目录
|
|
48980
|
+
*/
|
|
48981
|
+
BaseGenerator.prototype.copyTemplateFiles = function (promptsDir) {
|
|
48982
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48983
|
+
var files, projectGuidePath, projectGuideContent, tsxGenerationPath, tsxGenerationContent, decisionTreePath, decisionTreeContent, validationPath, validationContent, codeReviewPath, codeReviewContent, refactoringPath, refactoringContent;
|
|
48984
|
+
return __generator(this, function (_a) {
|
|
48985
|
+
files = [];
|
|
48986
|
+
projectGuidePath = path__namespace.join(promptsDir, 'project-guide.md');
|
|
48987
|
+
projectGuideContent = this.getProjectGuideTemplate();
|
|
48988
|
+
fs__namespace.writeFileSync(projectGuidePath, projectGuideContent);
|
|
48989
|
+
files.push(projectGuidePath);
|
|
48990
|
+
if (this.verbose) {
|
|
48991
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: project-guide.md");
|
|
48992
|
+
}
|
|
48993
|
+
tsxGenerationPath = path__namespace.join(promptsDir, 'tsx-generation.md');
|
|
48994
|
+
tsxGenerationContent = this.getTsxGenerationTemplate();
|
|
48995
|
+
fs__namespace.writeFileSync(tsxGenerationPath, tsxGenerationContent);
|
|
48996
|
+
files.push(tsxGenerationPath);
|
|
48997
|
+
if (this.verbose) {
|
|
48998
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: tsx-generation.md");
|
|
48999
|
+
}
|
|
49000
|
+
decisionTreePath = path__namespace.join(promptsDir, 'decision-tree.md');
|
|
49001
|
+
decisionTreeContent = this.getDecisionTreeTemplate();
|
|
49002
|
+
fs__namespace.writeFileSync(decisionTreePath, decisionTreeContent);
|
|
49003
|
+
files.push(decisionTreePath);
|
|
49004
|
+
if (this.verbose) {
|
|
49005
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: decision-tree.md");
|
|
49006
|
+
}
|
|
49007
|
+
validationPath = path__namespace.join(promptsDir, 'validation-checklist.md');
|
|
49008
|
+
validationContent = this.getValidationChecklistTemplate();
|
|
49009
|
+
fs__namespace.writeFileSync(validationPath, validationContent);
|
|
49010
|
+
files.push(validationPath);
|
|
49011
|
+
if (this.verbose) {
|
|
49012
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: validation-checklist.md");
|
|
49013
|
+
}
|
|
49014
|
+
codeReviewPath = path__namespace.join(promptsDir, 'code-review.md');
|
|
49015
|
+
codeReviewContent = this.getCodeReviewTemplate();
|
|
49016
|
+
fs__namespace.writeFileSync(codeReviewPath, codeReviewContent);
|
|
49017
|
+
files.push(codeReviewPath);
|
|
49018
|
+
if (this.verbose) {
|
|
49019
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: code-review.md");
|
|
49020
|
+
}
|
|
49021
|
+
refactoringPath = path__namespace.join(promptsDir, 'refactoring.md');
|
|
49022
|
+
refactoringContent = this.getRefactoringTemplate();
|
|
49023
|
+
fs__namespace.writeFileSync(refactoringPath, refactoringContent);
|
|
49024
|
+
files.push(refactoringPath);
|
|
49025
|
+
if (this.verbose) {
|
|
49026
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: refactoring.md");
|
|
49027
|
+
}
|
|
49028
|
+
return [2 /*return*/, files];
|
|
49029
|
+
});
|
|
49030
|
+
});
|
|
49031
|
+
};
|
|
49032
|
+
/**
|
|
49033
|
+
* 获取项目开发总指南模板内容
|
|
49034
|
+
*/
|
|
49035
|
+
BaseGenerator.prototype.getProjectGuideTemplate = function () {
|
|
49036
|
+
return "# Appthen \u9879\u76EE\u5F00\u53D1\u89C4\u8303\n\n## \uD83D\uDCCB \u9879\u76EE\u6982\u8FF0\n\n\u672C\u9879\u76EE\u662F **Appthen \u4F4E\u4EE3\u7801\u5E73\u53F0**\uFF0C\u652F\u6301\u7528\u9AD8\u4EE3\u7801\u5F00\u53D1\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u7684 React \u9875\u9762\u548C\u7EC4\u4EF6\u3002\n\n### \u9879\u76EE\u7ED3\u6784\n\n- **app/** - \u524D\u7AEF\u4EE3\u7801\uFF08\u540C\u6B65\u81EA\u4F4E\u4EE3\u7801\u4EA7\u54C1 Appthen\uFF09\n - \u4F7F\u7528\u7279\u6B8A\u89C4\u8303\u7684 TSX \u5B9E\u73B0 React \u9875\u9762\u548C\u7EC4\u4EF6\n - \u4EE3\u7801\u4F1A\u88AB\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u89E3\u6790\u548C\u5BFC\u5165\n- **server/** - \u540E\u7AEF\u4EE3\u7801\uFF08\u57FA\u4E8E cool-admin \u548C midwayjs\uFF09\n - \u4F7F\u7528 midwayjs \u6846\u67B6\u5F00\u53D1\u540E\u7AEF\u670D\u52A1\n - \u63D0\u4F9B\u63A5\u53E3\u3001\u6570\u636E\u5B57\u6BB5\u3001\u4E1A\u52A1\u6D41\u7A0B\u7B49\u4FE1\u606F\n\n---\n\n## \uD83D\uDEA8 \u91CD\u8981\uFF1A\u5F00\u53D1\u524D\u5FC5\u8BFB\n\n### \u524D\u7AEF\u5F00\u53D1\u89C4\u8303\n\n**[\u5173\u952E] \u5F00\u53D1 React \u9875\u9762\u548C\u7EC4\u4EF6\uFF08TSX \u6587\u4EF6\uFF09\u65F6\uFF1A**\n\n1. **\u5FC5\u987B\u5148\u9605\u8BFB** `.appthen/prompts/tsx-generation.md`\n - \u4E86\u89E3\u7279\u6B8A\u7684 TSX \u8BED\u6CD5\u89C4\u8303\n - \u4E25\u683C\u9075\u5B88\u975E\u5E38\u89C4\u7684 TSX/JSX \u8BED\u6CD5\u8981\u6C42\n\n2. **\u5FC5\u987B\u8FDB\u884C\u9A8C\u8BC1**\n - \u8BFB\u5199 TSX \u6587\u4EF6\u540E\uFF0C\u8C03\u7528\u547D\u4EE4\u9A8C\u8BC1\u8BED\u6CD5\uFF1A\n ```bash\n appthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n ```\n - \u5982\u4E0D\u7B26\u5408\u89C4\u8303\uFF0C\u6839\u636E\u9A8C\u8BC1\u7ED3\u679C\u8FDB\u884C\u4FEE\u6B63\n\n3. **\u7981\u6B62\u4F7F\u7528\u6807\u51C6\u5DE5\u5177**\n - \u274C \u4E0D\u8981\u8FD0\u884C `eslint`\u3001`prettier`\u3001`tsc` \u7B49\u6807\u51C6\u5DE5\u5177\n - \u274C \u8FD9\u4E9B\u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A TSX \u8BED\u6CD5\n - \u2705 \u53EA\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\n\n---\n\n## \uD83C\uDFAF \u4E1A\u52A1\u5F00\u53D1\u6D41\u7A0B\n\n### 1. \u83B7\u53D6\u63A5\u53E3\u4FE1\u606F\n\n\u4ECE server \u7AEF\u83B7\u53D6\u63A5\u53E3\u5BF9\u63A5\u6240\u9700\u7684\u76F8\u5173\u4FE1\u606F\uFF1A\n- \u63A5\u53E3\u5730\u5740\u548C\u53C2\u6570\n- \u6570\u636E\u5B57\u6BB5\u5B9A\u4E49\n- \u4E1A\u52A1\u6D41\u7A0B\u8BF4\u660E\n\n### 2. \u5F00\u53D1\u524D\u7AEF\u754C\u9762\n\n\u6839\u636E\u63A5\u53E3\u4FE1\u606F\u5F00\u53D1\u524D\u7AEF\u754C\u9762\uFF1A\n- \u4F7F\u7528 TSX \u7279\u6B8A\u8BED\u6CD5\n- \u9075\u5B88\u4E25\u683C\u7684 render() \u65B9\u6CD5\u7EA6\u675F\n- \u4F7F\u7528 @DataSource \u88C5\u9970\u5668\u5BF9\u63A5\u63A5\u53E3\n\n### 3. \u9A8C\u8BC1\u548C\u6D4B\u8BD5\n\n- \u4F7F\u7528 `appthen check-tsx` \u9A8C\u8BC1\u8BED\u6CD5\n- \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n- \u786E\u4FDD\u529F\u80FD\u6B63\u5E38\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - TSX \u4EE3\u7801\u751F\u6210\u5B8C\u6574\u89C4\u8303\n- **decision-tree.md** - AI \u51B3\u7B56\u6811\uFF08\u5E2E\u52A9 AI \u505A\u51FA\u6B63\u786E\u51B3\u7B56\uFF09\n- **validation-checklist.md** - \u4EE3\u7801\u9A8C\u8BC1\u6E05\u5355\n- **code-review.md** - \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n- **refactoring.md** - \u4EE3\u7801\u91CD\u6784\u6307\u5357\n\n---\n\n## \u26A0\uFE0F \u7279\u522B\u6CE8\u610F\n\n### TSX \u8BED\u6CD5\u7684\u7279\u6B8A\u6027\n\n\u6211\u4EEC\u7684 TSX \u8BED\u6CD5\u4E0E\u6807\u51C6 React/TypeScript \u4E0D\u540C\uFF1A\n\n1. **render() \u65B9\u6CD5\u7EA6\u675F**\n - \u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\n - \u4E0D\u80FD\u6709\u4EFB\u4F55\u903B\u8F91\u8BED\u53E5\n - \u53EA\u80FD\u76F4\u63A5\u8BBF\u95EE this.state \u548C this.props\n\n2. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - \u65B9\u6CD5\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\n - \u4E0D\u80FD\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component\uFF09\n\n3. **JSX \u4F4D\u7F6E\u9650\u5236**\n - \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\n - \u5176\u4ED6\u65B9\u6CD5\u548C\u5C5E\u6027\u4E0D\u80FD\u6709 JSX\n\n### \u4E3A\u4EC0\u4E48\u6709\u8FD9\u4E9B\u9650\u5236\uFF1F\n\n\u8FD9\u4E9B\u9650\u5236\u662F\u4E3A\u4E86\u8BA9\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u80FD\u591F\uFF1A\n- \u89E3\u6790\u548C\u7406\u89E3\u4EE3\u7801\u7ED3\u6784\n- \u63D0\u53D6\u6570\u636E\u6A21\u578B\u548C\u63A5\u53E3\u5B9A\u4E49\n- \u5728\u53EF\u89C6\u5316\u7F16\u8F91\u5668\u4E2D\u7F16\u8F91\n- \u751F\u6210\u7B26\u5408\u89C4\u8303\u7684\u4EE3\u7801\n\n**\u8FDD\u53CD\u89C4\u8303 = \u65E0\u6CD5\u5BFC\u5165\u4F4E\u4EE3\u7801\u7CFB\u7EDF\uFF01**\n\n---\n\n## \uD83D\uDE80 \u5FEB\u901F\u5F00\u59CB\n\n### \u521B\u5EFA\u65B0\u9875\u9762\n\n```bash\n# 1. \u67E5\u770B TSX \u751F\u6210\u89C4\u8303\ncat .appthen/prompts/tsx-generation.md\n\n# 2. \u521B\u5EFA\u9875\u9762\u6587\u4EF6\n# \u4F7F\u7528 AI \u5DE5\u5177\u751F\u6210\uFF0C\u786E\u4FDD\u9075\u5B88\u89C4\u8303\n\n# 3. \u9A8C\u8BC1\u8BED\u6CD5\nappthen check-tsx -f \"app/src/pages/NewPage.tsx\"\n\n# 4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n# \u6839\u636E\u9A8C\u8BC1\u7ED3\u679C\u4FEE\u6B63\u4EE3\u7801\n\n# 5. \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n```\n\n### \u4FEE\u6539\u73B0\u6709\u9875\u9762\n\n```bash\n# 1. \u67E5\u770B\u73B0\u6709\u4EE3\u7801\ncat app/src/pages/ExistingPage.tsx\n\n# 2. \u4FEE\u6539\u4EE3\u7801\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n\n# 3. \u9A8C\u8BC1\u8BED\u6CD5\nappthen check-tsx -f \"app/src/pages/ExistingPage.tsx\"\n\n# 4. \u6D4B\u8BD5\u529F\u80FD\n```\n\n---\n\n## \uD83D\uDCA1 \u6700\u4F73\u5B9E\u8DF5\n\n1. **\u59CB\u7EC8\u5148\u9605\u8BFB\u89C4\u8303** - \u4E0D\u8981\u51ED\u7ECF\u9A8C\u5199\u4EE3\u7801\n2. **\u9891\u7E41\u9A8C\u8BC1** - \u6BCF\u6B21\u4FEE\u6539\u540E\u90FD\u8FD0\u884C check-tsx\n3. **\u53C2\u8003\u793A\u4F8B** - \u67E5\u770B\u73B0\u6709\u9875\u9762\u7684\u5B9E\u73B0\u65B9\u5F0F\n4. **\u4F7F\u7528 AI \u8F85\u52A9** - \u8BA9 AI \u9075\u5B88\u89C4\u8303\u751F\u6210\u4EE3\u7801\n5. **\u6D4B\u8BD5\u5BFC\u5165** - \u786E\u4FDD\u80FD\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u6B63\u5E38\u5BFC\u5165\n\n---\n\n## \uD83C\uDD98 \u9047\u5230\u95EE\u9898\uFF1F\n\n1. **\u8BED\u6CD5\u9A8C\u8BC1\u5931\u8D25** \u2192 \u67E5\u770B validation-checklist.md\n2. **\u4E0D\u77E5\u9053\u5982\u4F55\u5B9E\u73B0** \u2192 \u67E5\u770B tsx-generation.md \u4E2D\u7684\u793A\u4F8B\n3. **AI \u751F\u6210\u9519\u8BEF\u4EE3\u7801** \u2192 \u67E5\u770B decision-tree.md \u4E86\u89E3 AI \u51B3\u7B56\u6D41\u7A0B\n4. **\u9700\u8981\u91CD\u6784\u4EE3\u7801** \u2192 \u67E5\u770B refactoring.md\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01** \uD83C\uDFAF\n";
|
|
49037
|
+
};
|
|
49038
|
+
/**
|
|
49039
|
+
* 获取 TSX 生成模板内容
|
|
49040
|
+
*/
|
|
49041
|
+
BaseGenerator.prototype.getTsxGenerationTemplate = function () {
|
|
49042
|
+
return "# TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303\n\n\u751F\u6210\u7B26\u5408\u5E73\u53F0\u89C4\u8303\u7684 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u9075\u5FAA\u4EE5\u4E0B\u89C4\u5219\uFF1A\n\n## 1. \u6587\u4EF6\u7ED3\u6784\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n## 2. \u5173\u952E\u89C4\u5219\n\n- \u2705 \u5FC5\u987B\u5305\u542B JSDoc \u5143\u6570\u636E\u6CE8\u91CA\n- \u2705 \u4F7F\u7528 class IProps \u548C class IState\n- \u2705 render() \u65B9\u6CD5\u53EA\u5305\u542B return \u8BED\u53E5\n- \u2705 \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n- \u274C \u907F\u514D\u5728 render() \u4E2D\u4F7F\u7528\u4E09\u5143\u8868\u8FBE\u5F0F\n- \u274C \u907F\u514D\u5728\u65B9\u6CD5\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n\n\u8BE6\u7EC6\u89C4\u8303\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
|
|
49043
|
+
};
|
|
49044
|
+
/**
|
|
49045
|
+
* 获取决策树模板内容
|
|
49046
|
+
*/
|
|
49047
|
+
BaseGenerator.prototype.getDecisionTreeTemplate = function () {
|
|
49048
|
+
return "# AI \u51B3\u7B56\u6811 - TSX \u4EE3\u7801\u751F\u6210\u51B3\u7B56\u6307\u5357\n\n## \uD83C\uDFAF \u76EE\u7684\n\n\u5E2E\u52A9 AI \u5728\u751F\u6210 TSX \u4EE3\u7801\u65F6\u505A\u51FA\u6B63\u786E\u7684\u51B3\u7B56\uFF0C\u907F\u514D\u5E38\u89C1\u9519\u8BEF\u3002\n\n---\n\n## \uD83D\uDCCA \u51B3\u7B56\u6D41\u7A0B\u56FE\n\n```\n\u7528\u6237\u8BF7\u6C42\n \u2193\n\u662F\u5426\u6D89\u53CA TSX \u6587\u4EF6\uFF1F\n \u251C\u2500 \u5426 \u2192 \u6B63\u5E38\u5904\u7406\n \u2514\u2500 \u662F \u2192 \u8FDB\u5165 TSX \u51B3\u7B56\u6D41\u7A0B\n \u2193\n \u662F\u5426\u662F\"\u521B\u5EFA\u9875\u9762/\u7EC4\u4EF6\"\uFF1F\n \u251C\u2500 \u662F \u2192 [\u9AD8\u5EA6\u8B66\u6212] \u8FDB\u5165\u9875\u9762/\u7EC4\u4EF6\u751F\u6210\u6D41\u7A0B\n \u2502 \u2193\n \u2502 \u6267\u884C\u9884\u751F\u6210\u9A8C\u8BC1\u6E05\u5355\n \u2502 \u2193\n \u2502 \u6240\u6709\u68C0\u67E5\u901A\u8FC7\uFF1F\n \u2502 \u251C\u2500 \u5426 \u2192 \u62D2\u7EDD\u751F\u6210\uFF0C\u8FD4\u56DE\u9519\u8BEF\u63D0\u793A\n \u2502 \u2514\u2500 \u662F \u2192 \u751F\u6210\u5B8C\u6574 TSX \u6587\u4EF6\n \u2502 \u2193\n \u2502 \u5305\u542B\u6240\u6709\u5FC5\u9700\u7ED3\u6784\uFF1F\n \u2502 \u251C\u2500 \u5426 \u2192 \u62D2\u7EDD\u751F\u6210\n \u2502 \u2514\u2500 \u662F \u2192 \u8FD4\u56DE\u4EE3\u7801\n \u2502\n \u2514\u2500 \u5426 \u2192 \u662F\u5426\u4FEE\u6539\u73B0\u6709 TSX\uFF1F\n \u251C\u2500 \u662F \u2192 \u68C0\u67E5\u4FEE\u6539\u5185\u5BB9\n \u2502 \u2193\n \u2502 \u662F\u5426\u4FEE\u6539 render() \u65B9\u6CD5\uFF1F\n \u2502 \u251C\u2500 \u662F \u2192 [\u9AD8\u5EA6\u8B66\u6212] \u68C0\u67E5\u7EA6\u675F\n \u2502 \u2502 \u2193\n \u2502 \u2502 \u662F\u5426\u8FDD\u53CD\u7EA6\u675F\uFF1F\n \u2502 \u2502 \u251C\u2500 \u662F \u2192 \u62D2\u7EDD\u4FEE\u6539\n \u2502 \u2502 \u2514\u2500 \u5426 \u2192 \u5141\u8BB8\u4FEE\u6539\n \u2502 \u2514\u2500 \u5426 \u2192 \u6B63\u5E38\u4FEE\u6539\n \u2502\n \u2514\u2500 \u5426 \u2192 \u5176\u4ED6\u64CD\u4F5C\uFF08\u67E5\u770B\u3001\u5206\u6790\u7B49\uFF09\n```\n\n---\n\n## \uD83D\uDEA8 \u5173\u952E\u51B3\u7B56\u70B9\n\n### \u51B3\u7B56\u70B9 1\uFF1A\u8BC6\u522B TSX \u64CD\u4F5C\n\n**\u89E6\u53D1\u8BCD\u6C47\uFF1A**\n- \"\u521B\u5EFA\u9875\u9762\" / \"\u751F\u6210\u9875\u9762\" / \"\u5199\u4E2A\u9875\u9762\"\n- \"\u521B\u5EFA\u7EC4\u4EF6\" / \"\u751F\u6210\u7EC4\u4EF6\" / \"\u5199\u4E2A\u7EC4\u4EF6\"\n- \"\u4FEE\u6539 XXX.tsx\" / \"\u66F4\u65B0\u9875\u9762\"\n- \"\u6DFB\u52A0\u529F\u80FD\u5230\u9875\u9762\"\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5305\u542B\u4EE5\u4E0A\u8BCD\u6C47 \u2192 \u8FDB\u5165 TSX \u51B3\u7B56\u6D41\u7A0B\n- \u5426\u5219 \u2192 \u6B63\u5E38\u5904\u7406\n\n---\n\n### \u51B3\u7B56\u70B9 2\uFF1A\u9875\u9762/\u7EC4\u4EF6\u751F\u6210\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u7528\u6237\u660E\u786E\u8981\u6C42\"\u521B\u5EFA\"\u6216\"\u751F\u6210\"\n- \u6CA1\u6709\u6307\u5B9A\u73B0\u6709\u6587\u4EF6\n\n**\u51B3\u7B56\uFF1A**\n- \u662F\u9875\u9762/\u7EC4\u4EF6\u751F\u6210 \u2192 \u6267\u884C\u5B8C\u6574\u9A8C\u8BC1\u6E05\u5355\n- \u5426 \u2192 \u8FDB\u5165\u4E0B\u4E00\u4E2A\u51B3\u7B56\u70B9\n\n**\u5FC5\u987B\u6267\u884C\u7684\u68C0\u67E5\uFF1A**\n1. \u2705 \u6211\u662F\u5426\u8981\u751F\u6210\u5B8C\u6574\u7684 TSX \u6587\u4EF6\uFF1F\n2. \u2705 \u6211\u662F\u5426\u5305\u542B\u4E86\u6240\u6709\u5FC5\u9700\u7ED3\u6784\uFF1F\n3. \u2705 \u6211\u662F\u5426\u9075\u5B88\u4E86 render() \u65B9\u6CD5\u7EA6\u675F\uFF1F\n4. \u2705 \u6211\u662F\u5426\u907F\u514D\u4E86 TypeScript \u7C7B\u578B\u6CE8\u89E3\uFF1F\n5. \u2705 \u6211\u662F\u5426\u53EA\u5728 render() \u4E2D\u4F7F\u7528 JSX\uFF1F\n\n**\u5982\u679C\u4EFB\u4F55\u4E00\u9879\u4E0D\u786E\u5B9A \u2192 \u62D2\u7EDD\u751F\u6210\uFF01**\n\n---\n\n### \u51B3\u7B56\u70B9 3\uFF1Arender() \u65B9\u6CD5\u4FEE\u6539\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4FEE\u6539\u6D89\u53CA render() \u65B9\u6CD5\u5185\u90E8\n\n**\u51B3\u7B56\uFF1A**\n- \u662F render() \u4FEE\u6539 \u2192 \u6267\u884C\u4E25\u683C\u7EA6\u675F\u68C0\u67E5\n- \u5426 \u2192 \u6B63\u5E38\u4FEE\u6539\n\n**\u4E25\u683C\u7EA6\u675F\u68C0\u67E5\uFF1A**\n1. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u53D8\u91CF\u58F0\u660E\uFF1F \u2192 \u62D2\u7EDD\n2. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u89E3\u6784\u8D4B\u503C\uFF1F \u2192 \u62D2\u7EDD\n3. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u903B\u8F91\u8BED\u53E5\uFF1F \u2192 \u62D2\u7EDD\n4. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u51FD\u6570\u8C03\u7528\uFF1F \u2192 \u62D2\u7EDD\n5. \u2705 \u662F\u5426\u53EA\u662F\u4FEE\u6539 JSX \u7ED3\u6784\uFF1F \u2192 \u5141\u8BB8\n6. \u2705 \u662F\u5426\u53EA\u662F\u4FEE\u6539 this.state \u8BBF\u95EE\uFF1F \u2192 \u5141\u8BB8\n\n---\n\n### \u51B3\u7B56\u70B9 4\uFF1ATypeScript \u8BED\u6CD5\u4F7F\u7528\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4EE3\u7801\u4E2D\u662F\u5426\u4F7F\u7528\u4E86 TypeScript \u8BED\u6CD5\n\n**\u51B3\u7B56\u89C4\u5219\uFF1A**\n\n| \u4F4D\u7F6E | \u5141\u8BB8\u7684 TS \u8BED\u6CD5 | \u7981\u6B62\u7684 TS \u8BED\u6CD5 |\n|------|---------------|---------------|\n| IProps \u63A5\u53E3 | \u2705 string?, number?, any[] | \u274C \u6CDB\u578B Array<T> |\n| IState \u7C7B | \u2705 string?, number?, any[] | \u274C \u6CDB\u578B Array<T> |\n| defaultProps | \u2705 \u7EAF JS \u503C | \u274C \u4EFB\u4F55\u7C7B\u578B\u6CE8\u89E3 |\n| \u7C7B\u65B9\u6CD5 | \u274C \u4EFB\u4F55\u7C7B\u578B\u6CE8\u89E3 | \u274C \u53C2\u6570\u7C7B\u578B\u3001\u8FD4\u56DE\u7C7B\u578B |\n| render() | \u274C \u4EFB\u4F55 TS \u8BED\u6CD5 | \u274C \u6240\u6709 TS \u8BED\u6CD5 |\n| React.Component | \u2705 <IProps, IState> | \u274C \u5176\u4ED6\u6CDB\u578B |\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5728\u7981\u6B62\u4F4D\u7F6E\u4F7F\u7528 TS \u8BED\u6CD5 \u2192 \u62D2\u7EDD\n- \u5982\u679C\u5728\u5141\u8BB8\u4F4D\u7F6E\u6B63\u786E\u4F7F\u7528 \u2192 \u5141\u8BB8\n\n---\n\n### \u51B3\u7B56\u70B9 5\uFF1AJSX \u4F4D\u7F6E\u68C0\u67E5\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4EE3\u7801\u4E2D\u662F\u5426\u5728\u975E render() \u4F4D\u7F6E\u4F7F\u7528 JSX\n\n**\u51B3\u7B56\u89C4\u5219\uFF1A**\n\n| \u4F4D\u7F6E | \u662F\u5426\u5141\u8BB8 JSX | \u793A\u4F8B |\n|------|-------------|------|\n| render() \u65B9\u6CD5 | \u2705 \u5141\u8BB8 | `return <div>...</div>` |\n| \u5176\u4ED6\u65B9\u6CD5 | \u274C \u7981\u6B62 | `handleClick() { return <div>...</div>; }` |\n| \u7C7B\u5C5E\u6027 | \u274C \u7981\u6B62 | `item = <div>...</div>` |\n| \u7BAD\u5934\u51FD\u6570\u5C5E\u6027 | \u274C \u7981\u6B62 | `renderItem = () => <div>...</div>` |\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5728\u7981\u6B62\u4F4D\u7F6E\u4F7F\u7528 JSX \u2192 \u62D2\u7EDD\n- \u5982\u679C\u53EA\u5728 render() \u4E2D\u4F7F\u7528 \u2192 \u5141\u8BB8\n\n---\n\n## \uD83D\uDEE1\uFE0F \u5B89\u5168\u68C0\u67E5\u6E05\u5355\n\n### \u751F\u6210\u4EE3\u7801\u524D\u5FC5\u987B\u56DE\u7B54\u7684\u95EE\u9898\uFF1A\n\n1. **\u7ED3\u6784\u5B8C\u6574\u6027**\n - [ ] \u662F\u5426\u5305\u542B JSDoc \u5143\u6570\u636E\u6CE8\u91CA\uFF1F\n - [ ] \u662F\u5426\u5305\u542B IProps \u63A5\u53E3\uFF1F\n - [ ] \u662F\u5426\u5305\u542B IState \u7C7B\uFF1F\n - [ ] \u662F\u5426\u5305\u542B Document \u7C7B\uFF1F\n - [ ] \u662F\u5426\u5305\u542B export default\uFF1F\n\n2. **render() \u65B9\u6CD5\u7EA6\u675F**\n - [ ] render() \u7B2C\u4E00\u884C\u662F return ( \u5417\uFF1F\n - [ ] render() \u5185\u90E8\u6CA1\u6709\u53D8\u91CF\u58F0\u660E\u5417\uFF1F\n - [ ] render() \u5185\u90E8\u6CA1\u6709\u903B\u8F91\u8BED\u53E5\u5417\uFF1F\n - [ ] render() \u53EA\u8BBF\u95EE this.state/this.props \u5417\uFF1F\n\n3. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u53D8\u91CF\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u6CA1\u6709\u4F7F\u7528\u6CDB\u578B\uFF08\u9664 React.Component\uFF09\u5417\uFF1F\n\n4. **JSX \u4F4D\u7F6E\u9650\u5236**\n - [ ] JSX \u53EA\u5728 render() \u65B9\u6CD5\u4E2D\u5417\uFF1F\n - [ ] \u5176\u4ED6\u65B9\u6CD5\u6CA1\u6709 JSX \u5417\uFF1F\n - [ ] \u7C7B\u5C5E\u6027\u6CA1\u6709 JSX \u5417\uFF1F\n\n5. **\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168**\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528\u53EF\u9009\u94FE ?. \u5417\uFF1F\n - [ ] \u6570\u7EC4\u8BBF\u95EE\u524D\u68C0\u67E5\u4E86\u5B58\u5728\u6027\u5417\uFF1F\n\n**\u5982\u679C\u4EFB\u4F55\u4E00\u9879\u56DE\u7B54\"\u5426\" \u2192 \u4E0D\u8981\u751F\u6210\u4EE3\u7801\uFF01**\n\n---\n\n## \uD83D\uDC80 \u5E38\u89C1\u9519\u8BEF\u51B3\u7B56\n\n### \u9519\u8BEF\u51B3\u7B56 1\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u4F18\u5316 render()\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"render() \u65B9\u6CD5\u592A\u957F\u4E86\uFF0C\u6211\u53EF\u4EE5\u63D0\u53D6\u4E00\u4E9B\u53D8\u91CF\u6765\u7B80\u5316\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** render() \u65B9\u6CD5\u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\u3002\n\u2705 \u5982\u679C\u9700\u8981\u7B80\u5316\uFF0C\u5E94\u8BE5\u63D0\u53D6\u5230\u7C7B\u65B9\u6CD5\u4E2D\uFF0C\u7136\u540E\u5728 render() \u4E2D\u8C03\u7528\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 2\uFF1A\u8BA4\u4E3A TypeScript \u7C7B\u578B\u6CE8\u89E3\u66F4\u597D\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u6DFB\u52A0\u7C7B\u578B\u6CE8\u89E3\u53EF\u4EE5\u63D0\u9AD8\u4EE3\u7801\u8D28\u91CF\u548C\u7C7B\u578B\u5B89\u5168\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u4E0D\u9002\u7528\u4E8E\u6211\u4EEC\u7684\u67B6\u6784\uFF01** \u65B9\u6CD5\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\u3002\n\u2705 \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\u5B9A\u4E49\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 3\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u5728\u65B9\u6CD5\u4E2D\u8FD4\u56DE JSX\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u6211\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A renderItem() \u65B9\u6CD5\u6765\u6E32\u67D3\u5217\u8868\u9879\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\u3002\n\u2705 \u5982\u679C\u9700\u8981\u590D\u6742\u6E32\u67D3\uFF0C\u5728 render() \u4E2D\u4F7F\u7528\u5185\u8054 map\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 4\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u8FD0\u884C lint \u5DE5\u5177\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u4EE3\u7801\u6709\u4E00\u4E9B\u683C\u5F0F\u95EE\u9898\uFF0C\u6211\u8FD0\u884C eslint --fix \u4FEE\u590D\u4E00\u4E0B\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** lint \u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A\u8BED\u6CD5\u3002\n\u2705 \u53EA\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\u3002\n\n---\n\n## \uD83C\uDFAF \u51B3\u7B56\u4F18\u5148\u7EA7\n\n### \u4F18\u5148\u7EA7 1\uFF1A\u5B89\u5168\u6027\uFF08\u6700\u9AD8\uFF09\n- \u4E0D\u7834\u574F\u73B0\u6709\u89C4\u8303\n- \u4E0D\u751F\u6210\u8FDD\u53CD\u7EA6\u675F\u7684\u4EE3\u7801\n- \u4E0D\u6267\u884C\u5371\u9669\u547D\u4EE4\n\n### \u4F18\u5148\u7EA7 2\uFF1A\u5B8C\u6574\u6027\n- \u751F\u6210\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n- \u5305\u542B\u6240\u6709\u5FC5\u9700\u5143\u7D20\n- \u9075\u5B88\u6240\u6709\u7EA6\u675F\n\n### \u4F18\u5148\u7EA7 3\uFF1A\u529F\u80FD\u6027\n- \u5B9E\u73B0\u7528\u6237\u9700\u6C42\n- \u63D0\u4F9B\u6B63\u786E\u7684\u529F\u80FD\n- \u4F18\u5316\u7528\u6237\u4F53\u9A8C\n\n**\u5F53\u4F18\u5148\u7EA7\u51B2\u7A81\u65F6\uFF0C\u5B89\u5168\u6027 > \u5B8C\u6574\u6027 > \u529F\u80FD\u6027**\n\n---\n\n## \uD83D\uDEAB \u62D2\u7EDD\u751F\u6210\u7684\u6807\u51C6\u54CD\u5E94\n\n\u5F53\u51B3\u7B56\u7ED3\u679C\u662F\"\u62D2\u7EDD\"\u65F6\uFF0C\u4F7F\u7528\u4EE5\u4E0B\u54CD\u5E94\u6A21\u677F\uFF1A\n\n```\n\uD83D\uDEA8 **\u65E0\u6CD5\u751F\u6210\u4EE3\u7801** \uD83D\uDEA8\n\n**\u539F\u56E0**: [\u5177\u4F53\u8BF4\u660E\u8FDD\u53CD\u4E86\u54EA\u4E2A\u7EA6\u675F]\n\n**\u95EE\u9898**: [\u8BE6\u7EC6\u63CF\u8FF0\u95EE\u9898]\n\n**\u6B63\u786E\u505A\u6CD5**:\n[\u63D0\u4F9B\u6B63\u786E\u7684\u5B9E\u73B0\u65B9\u5F0F\u6216\u66FF\u4EE3\u65B9\u6848]\n\n**\u793A\u4F8B**:\n[\u63D0\u4F9B\u6B63\u786E\u7684\u4EE3\u7801\u793A\u4F8B]\n\n\u8BF7\u6309\u7167\u6B63\u786E\u505A\u6CD5\u4FEE\u6539\u9700\u6C42\uFF0C\u7136\u540E\u91CD\u65B0\u63D0\u4EA4\u3002\n```\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - \u5B8C\u6574\u7684 TSX \u751F\u6210\u89C4\u8303\n- **validation-checklist.md** - \u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6E05\u5355\n- **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u5F53\u4E0D\u786E\u5B9A\u65F6\uFF0C\u9009\u62E9\u62D2\u7EDD\u800C\u4E0D\u662F\u5192\u9669\uFF01** \uD83D\uDEE1\uFE0F\n";
|
|
49049
|
+
};
|
|
49050
|
+
/**
|
|
49051
|
+
* 获取验证清单模板内容
|
|
49052
|
+
*/
|
|
49053
|
+
BaseGenerator.prototype.getValidationChecklistTemplate = function () {
|
|
49054
|
+
return "# TSX \u4EE3\u7801\u9A8C\u8BC1\u6E05\u5355\n\n## \uD83C\uDFAF \u76EE\u7684\n\n\u63D0\u4F9B\u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6E05\u5355\uFF0C\u786E\u4FDD\u751F\u6210\u7684 TSX \u4EE3\u7801\u7B26\u5408\u6240\u6709\u89C4\u8303\u8981\u6C42\u3002\n\n---\n\n## \u2705 \u9A8C\u8BC1\u6D41\u7A0B\n\n### \u9636\u6BB5 1\uFF1A\u7ED3\u6784\u9A8C\u8BC1\uFF08\u5FC5\u987B\u5168\u90E8\u901A\u8FC7\uFF09\n\n- [ ] **\u6587\u4EF6\u5934\u90E8\u5143\u6570\u636E**\n - [ ] \u5305\u542B JSDoc \u6CE8\u91CA\n - [ ] \u5305\u542B @type Page \u6216 @type Component\n - [ ] \u6807\u9898\u63CF\u8FF0\u6E05\u6670\n\n- [ ] **\u5BFC\u5165\u8BED\u53E5**\n - [ ] \u5305\u542B `import React from 'react';`\n - [ ] \u5176\u4ED6\u5BFC\u5165\u8BED\u53E5\u6B63\u786E\n\n- [ ] **IProps \u63A5\u53E3**\n - [ ] \u4F7F\u7528 `interface IProps` \u5B9A\u4E49\n - [ ] \u5C5E\u6027\u4F7F\u7528\u53EF\u9009\u7C7B\u578B\uFF08?\uFF09\n - [ ] \u53EA\u4F7F\u7528\u57FA\u7840\u7C7B\u578B\uFF08string, number, boolean, any[], Function\uFF09\n\n- [ ] **IState \u7C7B**\n - [ ] \u4F7F\u7528 `class IState` \u5B9A\u4E49\n - [ ] \u5C5E\u6027\u4F7F\u7528\u53EF\u9009\u7C7B\u578B\uFF08?\uFF09\n - [ ] \u5305\u542B\u5FC5\u8981\u7684\u6CE8\u91CA\u8BF4\u660E\n - [ ] @DataSource \u88C5\u9970\u5668\u914D\u7F6E\u6B63\u786E\uFF08\u5982\u679C\u6709\uFF09\n\n- [ ] **Document \u7C7B**\n - [ ] \u4F7F\u7528 `class Document extends React.Component<IProps, IState>`\n - [ ] \u5305\u542B static defaultProps\uFF08\u5982\u679C\u9700\u8981\uFF09\n - [ ] \u5305\u542B state \u521D\u59CB\u5316\n - [ ] \u5305\u542B render() \u65B9\u6CD5\n\n- [ ] **\u5BFC\u51FA\u8BED\u53E5**\n - [ ] \u5305\u542B `export default Document;`\n\n---\n\n### \u9636\u6BB5 2\uFF1Arender() \u65B9\u6CD5\u9A8C\u8BC1\uFF08\u96F6\u5BB9\u5FCD\uFF09\n\n- [ ] **\u7ED3\u6784\u68C0\u67E5**\n - [ ] \u7B2C\u4E00\u884C\u662F `return (`\n - [ ] \u6700\u540E\u4E00\u884C\u662F `);`\n - [ ] \u6CA1\u6709\u5176\u4ED6\u8BED\u53E5\n\n- [ ] **\u53D8\u91CF\u58F0\u660E\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `const` \u58F0\u660E\n - [ ] \u6CA1\u6709 `let` \u58F0\u660E\n - [ ] \u6CA1\u6709 `var` \u58F0\u660E\n - [ ] \u6CA1\u6709\u89E3\u6784\u8D4B\u503C `const { x } = ...`\n\n- [ ] **\u903B\u8F91\u8BED\u53E5\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `if` \u8BED\u53E5\n - [ ] \u6CA1\u6709 `for` \u5FAA\u73AF\n - [ ] \u6CA1\u6709 `while` \u5FAA\u73AF\n - [ ] \u6CA1\u6709 `switch` \u8BED\u53E5\n\n- [ ] **\u51FD\u6570\u8C03\u7528\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u72EC\u7ACB\u7684\u51FD\u6570\u8C03\u7528\uFF08\u9664\u4E86 this.state/this.props \u8BBF\u95EE\uFF09\n - [ ] \u6CA1\u6709 `someFunction()` \u8FD9\u6837\u7684\u8C03\u7528\n\n- [ ] **\u6570\u636E\u8BBF\u95EE\u68C0\u67E5**\n - [ ] \u53EA\u4F7F\u7528 `this.state.xxx` \u8BBF\u95EE\u72B6\u6001\n - [ ] \u53EA\u4F7F\u7528 `this.props.xxx` \u8BBF\u95EE\u5C5E\u6027\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528\u53EF\u9009\u94FE `this.state.user?.name`\n - [ ] \u6570\u7EC4\u8BBF\u95EE\u4F7F\u7528\u53EF\u9009\u94FE `this.state.items?.map(...)`\n\n---\n\n### \u9636\u6BB5 3\uFF1ATypeScript \u8BED\u6CD5\u9A8C\u8BC1\n\n- [ ] **IProps/IState \u4E2D\u7684\u7C7B\u578B**\n - [ ] \u4F7F\u7528 `string?` \u800C\u4E0D\u662F `string | undefined`\n - [ ] \u4F7F\u7528 `any[]` \u800C\u4E0D\u662F `Array<any>`\n - [ ] \u4F7F\u7528 `Function` \u800C\u4E0D\u662F `() => void`\n\n- [ ] **\u65B9\u6CD5\u5B9A\u4E49\u68C0\u67E5**\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n - \u274C `handleClick(e: Event)`\n - \u2705 `handleClick(e)`\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\n - \u274C `getData(): Promise<any>`\n - \u2705 `getData()`\n\n- [ ] **\u53D8\u91CF\u58F0\u660E\u68C0\u67E5**\n - [ ] \u53D8\u91CF\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u274C `const data: string = 'test'`\n - \u2705 `const data = 'test'`\n\n- [ ] **\u6CDB\u578B\u4F7F\u7528\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component<IProps, IState>\uFF09\n - \u274C `Array<string>`\n - \u2705 `string[]`\n\n- [ ] **\u7C7B\u578B\u65AD\u8A00\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u4F7F\u7528 `as` \u65AD\u8A00\n - [ ] \u6CA1\u6709\u4F7F\u7528 `<Type>` \u65AD\u8A00\n\n---\n\n### \u9636\u6BB5 4\uFF1AJSX \u4F4D\u7F6E\u9A8C\u8BC1\n\n- [ ] **render() \u65B9\u6CD5**\n - [ ] render() \u65B9\u6CD5\u5305\u542B JSX \u2705\n\n- [ ] **\u5176\u4ED6\u65B9\u6CD5**\n - [ ] handleXxx() \u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n - [ ] getXxx() \u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n - [ ] \u6240\u6709\u5176\u4ED6\u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n\n- [ ] **\u7C7B\u5C5E\u6027**\n - [ ] \u6CA1\u6709\u5C5E\u6027\u5305\u542B JSX\n - \u274C `item = <div>...</div>`\n - \u274C `renderItem = () => <div>...</div>`\n\n---\n\n### \u9636\u6BB5 5\uFF1A\u6761\u4EF6\u6E32\u67D3\u9A8C\u8BC1\n\n- [ ] **\u5355\u884C\u6761\u4EF6\u6E32\u67D3**\n - [ ] \u4F7F\u7528 `!!(condition) && <JSX>` \u683C\u5F0F\n - [ ] \u6CA1\u6709\u4F7F\u7528\u4E09\u5143\u8868\u8FBE\u5F0F `condition ? <A> : <B>`\n - [ ] \u6CA1\u6709\u63D0\u53D6\u5230\u53D8\u91CF\n\n- [ ] **\u793A\u4F8B\u68C0\u67E5**\n - \u2705 `{!!(this.state.showDetail) && <div>Detail</div>}`\n - \u2705 `{!!(this.state.user && this.state.user.isActive) && <UserCard />}`\n - \u274C `{this.state.showDetail ? <div>Detail</div> : null}`\n - \u274C `const detail = this.state.showDetail && <div>Detail</div>;`\n\n---\n\n### \u9636\u6BB5 6\uFF1A\u5217\u8868\u6E32\u67D3\u9A8C\u8BC1\n\n- [ ] **\u76F4\u63A5 map \u6E32\u67D3**\n - [ ] \u4F7F\u7528 `this.state.items?.map(...)` \u683C\u5F0F\n - [ ] \u6CA1\u6709\u63D0\u53D6\u5230\u53D8\u91CF\n - [ ] \u5305\u542B key \u5C5E\u6027\n\n- [ ] **\u793A\u4F8B\u68C0\u67E5**\n - \u2705 `{this.state.users?.map((user, index) => <div key={user.id || index}>...</div>)}`\n - \u274C `const userList = this.state.users?.map(...); {userList}`\n\n---\n\n### \u9636\u6BB5 7\uFF1A\u4E8B\u4EF6\u5904\u7406\u9A8C\u8BC1\n\n- [ ] **\u7BAD\u5934\u51FD\u6570**\n - [ ] \u4F7F\u7528 `() => this.handleClick()` \u683C\u5F0F\n - [ ] \u53C2\u6570\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u2705 `(e) => this.setState({...})`\n - \u274C `(e: Event) => this.setState({...})`\n\n- [ ] **\u65B9\u6CD5\u5F15\u7528**\n - [ ] \u4F7F\u7528 `this.handleClick.bind(this)` \u683C\u5F0F\n\n---\n\n### \u9636\u6BB5 8\uFF1A\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\u9A8C\u8BC1\n\n- [ ] **\u53EF\u9009\u94FE\u4F7F\u7528**\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528 `?.` \u8BBF\u95EE\n - [ ] \u6570\u7EC4\u4F7F\u7528 `?.` \u8BBF\u95EE\n - [ ] \u65B9\u6CD5\u8C03\u7528\u4F7F\u7528 `?.` \u8BBF\u95EE\n\n- [ ] **\u5371\u9669\u5199\u6CD5\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `this.state.user.name`\uFF08\u5E94\u8BE5\u662F `this.state.user?.name`\uFF09\n - [ ] \u6CA1\u6709 `this.state.items.length`\uFF08\u5E94\u8BE5\u662F `this.state.items?.length`\uFF09\n - [ ] \u6CA1\u6709 `this.state.data[0].value`\uFF08\u5E94\u8BE5\u662F `this.state.data?.[0]?.value`\uFF09\n\n---\n\n## \uD83D\uDEA8 \u5E38\u89C1\u9519\u8BEF\u68C0\u67E5\n\n### \u9519\u8BEF 1\uFF1Arender() \u4E2D\u7684\u53D8\u91CF\u58F0\u660E\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n const data = this.state.data; // \u274C \u53D8\u91CF\u58F0\u660E\n return <div>{data}</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.data}</div>;\n}\n```\n\n---\n\n### \u9519\u8BEF 2\uFF1A\u65B9\u6CD5\u4E2D\u7684\u7C7B\u578B\u6CE8\u89E3\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nhandleClick(e: Event) { // \u274C \u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n this.setState({ clicked: true });\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nhandleClick(e) { // \u2705 \u65E0\u7C7B\u578B\u6CE8\u89E3\n this.setState({ clicked: true });\n}\n```\n\n---\n\n### \u9519\u8BEF 3\uFF1A\u65B9\u6CD5\u4E2D\u7684 JSX\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrenderItem() { // \u274C \u65B9\u6CD5\u4E2D\u8FD4\u56DE JSX\n return <div>Item</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return (\n <div>\n {this.state.items?.map((item, index) => (\n <div key={index}>Item</div>\n ))}\n </div>\n );\n}\n```\n\n---\n\n### \u9519\u8BEF 4\uFF1A\u4E0D\u5B89\u5168\u7684\u5BF9\u8C61\u8BBF\u95EE\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.user.name}</div>; // \u274C \u53EF\u80FD\u5D29\u6E83\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.user?.name}</div>; // \u2705 \u5B89\u5168\u8BBF\u95EE\n}\n```\n\n---\n\n## \uD83D\uDCCA \u9A8C\u8BC1\u7ED3\u679C\u5224\u5B9A\n\n### \u5168\u90E8\u901A\u8FC7 \u2705\n- \u6240\u6709\u68C0\u67E5\u9879\u90FD\u901A\u8FC7\n- \u4EE3\u7801\u7B26\u5408\u89C4\u8303\n- \u53EF\u4EE5\u63D0\u4EA4/\u4F7F\u7528\n\n### \u90E8\u5206\u5931\u8D25 \u26A0\uFE0F\n- \u6709\u68C0\u67E5\u9879\u672A\u901A\u8FC7\n- \u9700\u8981\u4FEE\u6B63\u4EE3\u7801\n- \u91CD\u65B0\u9A8C\u8BC1\n\n### \u4E25\u91CD\u5931\u8D25 \u274C\n- \u5173\u952E\u68C0\u67E5\u9879\u5931\u8D25\n- \u4EE3\u7801\u4E0D\u7B26\u5408\u89C4\u8303\n- \u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u4F7F\u7528\n\n---\n\n## \uD83D\uDEE0\uFE0F \u4F7F\u7528\u9A8C\u8BC1\u5DE5\u5177\n\n### \u547D\u4EE4\u884C\u9A8C\u8BC1\n\n```bash\n# \u9A8C\u8BC1\u5355\u4E2A\u6587\u4EF6\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n\n# \u9A8C\u8BC1\u591A\u4E2A\u6587\u4EF6\nappthen check-tsx -f \"app/src/pages/**/*.tsx\"\n\n# \u8BE6\u7EC6\u8F93\u51FA\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\" --verbose\n```\n\n### \u9A8C\u8BC1\u8F93\u51FA\u793A\u4F8B\n\n```\n\u2705 \u6587\u4EF6\u7ED3\u6784\u9A8C\u8BC1\u901A\u8FC7\n\u2705 render() \u65B9\u6CD5\u9A8C\u8BC1\u901A\u8FC7\n\u2705 TypeScript \u8BED\u6CD5\u9A8C\u8BC1\u901A\u8FC7\n\u2705 JSX \u4F4D\u7F6E\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u6761\u4EF6\u6E32\u67D3\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u5217\u8868\u6E32\u67D3\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u4E8B\u4EF6\u5904\u7406\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\u9A8C\u8BC1\u901A\u8FC7\n\n\uD83C\uDF89 \u6240\u6709\u9A8C\u8BC1\u901A\u8FC7\uFF01\u4EE3\u7801\u7B26\u5408\u89C4\u8303\u3002\n```\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - \u5B8C\u6574\u7684 TSX \u751F\u6210\u89C4\u8303\n- **decision-tree.md** - AI \u51B3\u7B56\u6811\n- **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9A8C\u8BC1\u662F\u786E\u4FDD\u4EE3\u7801\u8D28\u91CF\u7684\u5173\u952E\u6B65\u9AA4\uFF01** \uD83D\uDD0D\n";
|
|
49055
|
+
};
|
|
49056
|
+
/**
|
|
49057
|
+
* 获取代码审查模板内容
|
|
49058
|
+
*/
|
|
49059
|
+
BaseGenerator.prototype.getCodeReviewTemplate = function () {
|
|
49060
|
+
return "# \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n\n\u5728\u5BA1\u67E5 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u5173\u6CE8\u4EE5\u4E0B\u65B9\u9762\uFF1A\n\n## 1. \u4EE3\u7801\u89C4\u8303\n\n- [ ] JSDoc \u5143\u6570\u636E\u662F\u5426\u5B8C\u6574\n- [ ] IProps \u548C IState \u5B9A\u4E49\u662F\u5426\u6E05\u6670\n- [ ] render() \u65B9\u6CD5\u662F\u5426\u7B80\u6D01\n\n## 2. \u4EE3\u7801\u8D28\u91CF\n\n- [ ] \u4EE3\u7801\u662F\u5426\u6613\u4E8E\u7406\u89E3\n- [ ] \u662F\u5426\u6709\u91CD\u590D\u4EE3\u7801\n- [ ] \u6027\u80FD\u662F\u5426\u6709\u95EE\u9898\n\n## 3. TSX \u89C4\u8303\n\n- [ ] \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u800C\u975E\u4E09\u5143\u8868\u8FBE\u5F0F\n- [ ] \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n- [ ] \u5217\u8868\u6E32\u67D3\u662F\u5426\u6709 key\n\n\u8BE6\u7EC6\u5BA1\u67E5\u6E05\u5355\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
|
|
49061
|
+
};
|
|
49062
|
+
/**
|
|
49063
|
+
* 获取重构模板内容
|
|
49064
|
+
*/
|
|
49065
|
+
BaseGenerator.prototype.getRefactoringTemplate = function () {
|
|
49066
|
+
return "# \u4EE3\u7801\u91CD\u6784\u6307\u5357\n\n\u5728\u91CD\u6784 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u9075\u5FAA\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n## 1. \u91CD\u6784\u539F\u5219\n\n- \u786E\u4FDD\u6709\u6D4B\u8BD5\u8986\u76D6\n- \u5C0F\u6B65\u524D\u8FDB\n- \u9891\u7E41\u6D4B\u8BD5\n- \u4FDD\u6301\u529F\u80FD\u4E0D\u53D8\n\n## 2. \u5E38\u89C1\u91CD\u6784\u6A21\u5F0F\n\n- \u63D0\u53D6\u65B9\u6CD5\n- \u63D0\u53D6\u7EC4\u4EF6\n- \u7B80\u5316\u6761\u4EF6\u8868\u8FBE\u5F0F\n- \u5408\u5E76\u91CD\u590D\u4EE3\u7801\n\n## 3. \u6027\u80FD\u4F18\u5316\n\n- \u907F\u514D\u4E0D\u5FC5\u8981\u7684\u6E32\u67D3\n- \u4F7F\u7528 key \u4F18\u5316\u5217\u8868\n- \u63D0\u53D6\u590D\u6742\u8BA1\u7B97\n\n\u8BE6\u7EC6\u91CD\u6784\u6307\u5357\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
|
|
49067
|
+
};
|
|
49068
|
+
return BaseGenerator;
|
|
49069
|
+
}());
|
|
49070
|
+
|
|
49071
|
+
/**
|
|
49072
|
+
* Claude Code 生成器
|
|
49073
|
+
* 生成 Claude Code 特定的配置文件和 Hooks
|
|
49074
|
+
*/
|
|
49075
|
+
var ClaudeCodeGenerator = /** @class */ (function () {
|
|
49076
|
+
function ClaudeCodeGenerator(cwd, config, verbose) {
|
|
49077
|
+
this.cwd = cwd;
|
|
49078
|
+
this.config = config;
|
|
49079
|
+
this.verbose = verbose;
|
|
49080
|
+
}
|
|
49081
|
+
/**
|
|
49082
|
+
* 生成 Claude Code 配置
|
|
49083
|
+
*/
|
|
49084
|
+
ClaudeCodeGenerator.prototype.generate = function (skipHooks) {
|
|
49085
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49086
|
+
var files, claudeMdPath, commandFiles, result, error_1;
|
|
49087
|
+
return __generator(this, function (_a) {
|
|
49088
|
+
switch (_a.label) {
|
|
49089
|
+
case 0:
|
|
49090
|
+
files = [];
|
|
49091
|
+
_a.label = 1;
|
|
49092
|
+
case 1:
|
|
49093
|
+
_a.trys.push([1, 7, , 8]);
|
|
49094
|
+
if (this.verbose) {
|
|
49095
|
+
console.log('🤖 配置 Claude Code 集成...');
|
|
49096
|
+
}
|
|
49097
|
+
return [4 /*yield*/, this.createClaudeMd()];
|
|
49098
|
+
case 2:
|
|
49099
|
+
claudeMdPath = _a.sent();
|
|
49100
|
+
files.push(claudeMdPath);
|
|
49101
|
+
return [4 /*yield*/, this.createCustomCommands()];
|
|
49102
|
+
case 3:
|
|
49103
|
+
commandFiles = _a.sent();
|
|
49104
|
+
files.push.apply(files, __spreadArray([], __read(commandFiles), false));
|
|
49105
|
+
if (!!skipHooks) return [3 /*break*/, 5];
|
|
49106
|
+
return [4 /*yield*/, initClaudeHooks({
|
|
49107
|
+
cwd: this.cwd,
|
|
49108
|
+
verbose: this.verbose,
|
|
49109
|
+
projectOnly: true,
|
|
49110
|
+
force: false,
|
|
49111
|
+
})];
|
|
49112
|
+
case 4:
|
|
49113
|
+
result = _a.sent();
|
|
49114
|
+
if (!result.success) {
|
|
49115
|
+
return [2 /*return*/, {
|
|
49116
|
+
success: false,
|
|
49117
|
+
files: [],
|
|
49118
|
+
error: "Claude Hooks \u521D\u59CB\u5316\u5931\u8D25: ".concat(result.error),
|
|
49119
|
+
}];
|
|
49120
|
+
}
|
|
49121
|
+
// 添加生成的文件到列表
|
|
49122
|
+
files.push(path__namespace.join(this.cwd, '.claude/settings.json'), path__namespace.join(this.cwd, '.claude/hooks/tsx-compliance-checker.sh'));
|
|
49123
|
+
if (this.verbose) {
|
|
49124
|
+
console.log('✅ Claude Code Hooks 配置完成');
|
|
49125
|
+
}
|
|
49126
|
+
return [3 /*break*/, 6];
|
|
49127
|
+
case 5:
|
|
49128
|
+
if (this.verbose) {
|
|
49129
|
+
console.log('⏭️ 跳过 Claude Code Hooks 配置');
|
|
49130
|
+
}
|
|
49131
|
+
_a.label = 6;
|
|
49132
|
+
case 6: return [2 /*return*/, {
|
|
49133
|
+
success: true,
|
|
49134
|
+
files: files,
|
|
49135
|
+
message: 'Claude Code configuration created successfully',
|
|
49136
|
+
}];
|
|
49137
|
+
case 7:
|
|
49138
|
+
error_1 = _a.sent();
|
|
49139
|
+
return [2 /*return*/, {
|
|
49140
|
+
success: false,
|
|
49141
|
+
files: [],
|
|
49142
|
+
error: error_1.message,
|
|
49143
|
+
}];
|
|
49144
|
+
case 8: return [2 /*return*/];
|
|
49145
|
+
}
|
|
49146
|
+
});
|
|
49147
|
+
});
|
|
49148
|
+
};
|
|
49149
|
+
/**
|
|
49150
|
+
* 创建项目根目录的 CLAUDE.md
|
|
49151
|
+
*/
|
|
49152
|
+
ClaudeCodeGenerator.prototype.createClaudeMd = function () {
|
|
49153
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49154
|
+
var claudeMdPath, content;
|
|
49155
|
+
return __generator(this, function (_a) {
|
|
49156
|
+
claudeMdPath = path__namespace.join(this.cwd, 'CLAUDE.md');
|
|
49157
|
+
content = "# Appthen \u9879\u76EE - Claude Code \u81EA\u5B9A\u4E49\u6307\u4EE4\n\n## \uD83C\uDFAF \u9879\u76EE\u6982\u8FF0\n\n\u8FD9\u662F\u4E00\u4E2A **Appthen \u4F4E\u4EE3\u7801\u5E73\u53F0**\u9879\u76EE\uFF0C\u652F\u6301\u7528\u9AD8\u4EE3\u7801\u5F00\u53D1\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u7684 React \u9875\u9762\u548C\u7EC4\u4EF6\u3002\n\n**\u5173\u952E\u7279\u6027\uFF1A**\n- \u4F7F\u7528\u7279\u6B8A\u89C4\u8303\u7684 TSX \u8BED\u6CD5\n- \u4EE3\u7801\u4F1A\u88AB\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u89E3\u6790\u548C\u5BFC\u5165\n- \u5FC5\u987B\u4E25\u683C\u9075\u5B88\u89C4\u8303\uFF0C\u5426\u5219\u65E0\u6CD5\u5BFC\u5165\n\n---\n\n## \uD83D\uDEA8 \u91CD\u8981\uFF1A\u5F00\u53D1 TSX \u6587\u4EF6\u7684\u5F3A\u5236\u8981\u6C42\n\n### \u5FC5\u987B\u9075\u5B88\u7684\u89C4\u8303\n\n\u5728\u5F00\u53D1\u4EFB\u4F55 TSX \u6587\u4EF6\uFF08\u9875\u9762\u6216\u7EC4\u4EF6\uFF09\u65F6\uFF0C**\u5FC5\u987B\u4E25\u683C\u9075\u5B88**\u4EE5\u4E0B\u89C4\u8303\uFF1A\n\n1. **\u9605\u8BFB\u89C4\u8303\u6587\u6863**\n - \u67E5\u770B `.appthen/prompts/tsx-generation.md` \u4E86\u89E3\u5B8C\u6574\u89C4\u8303\n - \u67E5\u770B `.appthen/prompts/decision-tree.md` \u4E86\u89E3\u51B3\u7B56\u6D41\u7A0B\n - \u67E5\u770B `.appthen/prompts/validation-checklist.md` \u4E86\u89E3\u9A8C\u8BC1\u6E05\u5355\n\n2. **render() \u65B9\u6CD5\u7EA6\u675F**\uFF08\u96F6\u5BB9\u5FCD\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\uFF08const/let/var\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u89E3\u6784\u8D4B\u503C\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u903B\u8F91\u8BED\u53E5\uFF08if/for/while\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u51FD\u6570\u8C03\u7528\uFF08\u9664\u4E86 this.state/this.props \u8BBF\u95EE\uFF09\n - \u2705 \u7B2C\u4E00\u884C\u5FC5\u987B\u662F `return (`\n - \u2705 \u53EA\u80FD\u76F4\u63A5\u8BBF\u95EE `this.state.xxx` \u548C `this.props.xxx`\n\n3. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - \u274C \u65B9\u6CD5\u4E0D\u80FD\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u65B9\u6CD5\u4E0D\u80FD\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u53D8\u91CF\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u4E0D\u80FD\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component<IProps, IState>\uFF09\n - \u2705 \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\u5B9A\u4E49\n\n4. **JSX \u4F4D\u7F6E\u9650\u5236**\n - \u2705 \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\n - \u274C \u5176\u4ED6\u65B9\u6CD5\u4E0D\u80FD\u5305\u542B JSX\n - \u274C \u7C7B\u5C5E\u6027\u4E0D\u80FD\u5305\u542B JSX\n\n5. **\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168**\n - \u2705 \u5D4C\u5957\u5BF9\u8C61\u5FC5\u987B\u4F7F\u7528\u53EF\u9009\u94FE\uFF1A`this.state.user?.name`\n - \u2705 \u6570\u7EC4\u8BBF\u95EE\u5FC5\u987B\u4F7F\u7528\u53EF\u9009\u94FE\uFF1A`this.state.items?.map(...)`\n\n### \u9A8C\u8BC1\u8981\u6C42\n\n**\u6BCF\u6B21\u4FEE\u6539 TSX \u6587\u4EF6\u540E\uFF0C\u5FC5\u987B\u8FD0\u884C\u9A8C\u8BC1\uFF1A**\n\n```bash\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n```\n\n**\u5982\u679C\u9A8C\u8BC1\u5931\u8D25\uFF0C\u5FC5\u987B\u4FEE\u6B63\u540E\u624D\u80FD\u63D0\u4EA4\uFF01**\n\n---\n\n## \uD83D\uDEAB \u7981\u6B62\u7684\u64CD\u4F5C\n\n### \u7EDD\u5BF9\u4E0D\u8981\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A\n\n- \u274C `eslint` \u6216 `eslint --fix`\uFF08\u9488\u5BF9 .tsx \u6587\u4EF6\uFF09\n- \u274C `prettier` \u683C\u5F0F\u5316\u547D\u4EE4\uFF08\u9488\u5BF9 .tsx \u6587\u4EF6\uFF09\n- \u274C `tsc --noEmit` \u6216\u4EFB\u4F55 tsc \u547D\u4EE4\n- \u274C \u4EFB\u4F55 TypeScript \u8BED\u6CD5\u68C0\u67E5\u5DE5\u5177\n- \u274C \u4EFB\u4F55\u81EA\u52A8\u683C\u5F0F\u5316\u5DE5\u5177\n\n**\u539F\u56E0\uFF1A** \u8FD9\u4E9B\u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A TSX \u8BED\u6CD5\uFF01\n\n---\n\n## \uD83D\uDCDA \u5FEB\u901F\u53C2\u8003\n\n### \u6B63\u786E\u7684 TSX \u6587\u4EF6\u7ED3\u6784\n\n```typescript\n/**\n * \u9875\u9762\u6807\u9898\n * @type Page|Component\n */\nimport React from 'react';\n\ninterface IProps {\n title?: string;\n}\n\nclass IState {\n count?: number;\n}\n\nclass Document extends React.Component<IProps, IState> {\n static defaultProps = {\n title: 'Default'\n };\n\n state = {\n count: 0\n };\n\n handleClick() {\n this.setState({ count: this.state.count + 1 });\n }\n\n render() {\n return (\n <div>\n <h1>{this.props.title}</h1>\n <p>{this.state.count}</p>\n <button onClick={() => this.handleClick()}>Click</button>\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5E38\u89C1\u9519\u8BEF\u793A\u4F8B\n\n\u274C **\u9519\u8BEF\uFF1Arender() \u4E2D\u7684\u53D8\u91CF\u58F0\u660E**\n```typescript\nrender() {\n const data = this.state.data; // \u274C \u4E0D\u5141\u8BB8\n return <div>{data}</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\uFF1A\u76F4\u63A5\u8BBF\u95EE**\n```typescript\nrender() {\n return <div>{this.state.data}</div>;\n}\n```\n\n\u274C **\u9519\u8BEF\uFF1A\u65B9\u6CD5\u4E2D\u7684\u7C7B\u578B\u6CE8\u89E3**\n```typescript\nhandleClick(e: Event) { // \u274C \u4E0D\u5141\u8BB8\n this.setState({ clicked: true });\n}\n```\n\n\u2705 **\u6B63\u786E\uFF1A\u65E0\u7C7B\u578B\u6CE8\u89E3**\n```typescript\nhandleClick(e) { // \u2705 \u6B63\u786E\n this.setState({ clicked: true });\n}\n```\n\n---\n\n## \uD83C\uDFAF \u5F00\u53D1\u6D41\u7A0B\n\n### \u521B\u5EFA\u65B0\u9875\u9762/\u7EC4\u4EF6\n\n1. \u67E5\u770B\u89C4\u8303\u6587\u6863\uFF1A`.appthen/prompts/tsx-generation.md`\n2. \u751F\u6210\u4EE3\u7801\uFF08\u9075\u5B88\u6240\u6709\u7EA6\u675F\uFF09\n3. \u9A8C\u8BC1\u8BED\u6CD5\uFF1A`appthen check-tsx -f \"path/to/file.tsx\"`\n4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n5. \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n\n### \u4FEE\u6539\u73B0\u6709\u9875\u9762/\u7EC4\u4EF6\n\n1. \u67E5\u770B\u73B0\u6709\u4EE3\u7801\u7ED3\u6784\n2. \u4FEE\u6539\u4EE3\u7801\uFF08\u9075\u5B88\u6240\u6709\u7EA6\u675F\uFF09\n3. \u9A8C\u8BC1\u8BED\u6CD5\uFF1A`appthen check-tsx -f \"path/to/file.tsx\"`\n4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n5. \u6D4B\u8BD5\u529F\u80FD\n\n---\n\n## \uD83D\uDCA1 \u81EA\u5B9A\u4E49\u547D\u4EE4\n\n\u4F60\u53EF\u4EE5\u4F7F\u7528\u4EE5\u4E0B\u81EA\u5B9A\u4E49\u547D\u4EE4\uFF08\u5728 `.claude/commands/` \u76EE\u5F55\u4E2D\uFF09\uFF1A\n\n- `$check-tsx` - \u9A8C\u8BC1 TSX \u6587\u4EF6\u8BED\u6CD5\n- `$review-tsx` - \u5BA1\u67E5 TSX \u4EE3\u7801\u8D28\u91CF\n- `$create-page` - \u521B\u5EFA\u65B0\u9875\u9762\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n- `$create-component` - \u521B\u5EFA\u65B0\u7EC4\u4EF6\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n\n---\n\n## \uD83D\uDCD6 \u66F4\u591A\u4FE1\u606F\n\n- **\u5B8C\u6574\u89C4\u8303**\uFF1A`.appthen/prompts/tsx-generation.md`\n- **\u51B3\u7B56\u6811**\uFF1A`.appthen/prompts/decision-tree.md`\n- **\u9A8C\u8BC1\u6E05\u5355**\uFF1A`.appthen/prompts/validation-checklist.md`\n- **\u9879\u76EE\u6307\u5357**\uFF1A`.appthen/prompts/project-guide.md`\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01\u8FDD\u53CD\u89C4\u8303\u7684\u4EE3\u7801\u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u4F7F\u7528\u3002** \uD83C\uDFAF\n";
|
|
49158
|
+
fs__namespace.writeFileSync(claudeMdPath, content);
|
|
49159
|
+
if (this.verbose) {
|
|
49160
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA CLAUDE.md: ".concat(claudeMdPath));
|
|
49161
|
+
}
|
|
49162
|
+
return [2 /*return*/, claudeMdPath];
|
|
49163
|
+
});
|
|
49164
|
+
});
|
|
49165
|
+
};
|
|
49166
|
+
/**
|
|
49167
|
+
* 创建自定义命令
|
|
49168
|
+
*/
|
|
49169
|
+
ClaudeCodeGenerator.prototype.createCustomCommands = function () {
|
|
49170
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49171
|
+
var commandsDir, files, checkTsxPath, reviewTsxPath, createPagePath, createComponentPath;
|
|
49172
|
+
return __generator(this, function (_a) {
|
|
49173
|
+
commandsDir = path__namespace.join(this.cwd, '.claude/commands');
|
|
49174
|
+
files = [];
|
|
49175
|
+
// 创建 commands 目录
|
|
49176
|
+
if (!fs__namespace.existsSync(commandsDir)) {
|
|
49177
|
+
fs__namespace.mkdirSync(commandsDir, { recursive: true });
|
|
49178
|
+
if (this.verbose) {
|
|
49179
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(commandsDir));
|
|
49180
|
+
}
|
|
49181
|
+
}
|
|
49182
|
+
checkTsxPath = path__namespace.join(commandsDir, 'check-tsx.md');
|
|
49183
|
+
fs__namespace.writeFileSync(checkTsxPath, "# \u9A8C\u8BC1 TSX \u6587\u4EF6\u8BED\u6CD5\n\n\u8FD0\u884C TSX \u8BED\u6CD5\u9A8C\u8BC1\u5DE5\u5177\uFF0C\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u7B26\u5408 Appthen \u89C4\u8303\u3002\n\n## \u4F7F\u7528\u65B9\u6CD5\n\n```bash\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n```\n\n## \u9A8C\u8BC1\u5185\u5BB9\n\n- \u6587\u4EF6\u7ED3\u6784\u5B8C\u6574\u6027\n- render() \u65B9\u6CD5\u7EA6\u675F\n- TypeScript \u8BED\u6CD5\u9650\u5236\n- JSX \u4F4D\u7F6E\u9650\u5236\n- \u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\n\n## \u8F93\u51FA\n\n\u5982\u679C\u9A8C\u8BC1\u901A\u8FC7\uFF0C\u4F1A\u663E\u793A\uFF1A\n```\n\u2705 \u6240\u6709\u9A8C\u8BC1\u901A\u8FC7\uFF01\u4EE3\u7801\u7B26\u5408\u89C4\u8303\u3002\n```\n\n\u5982\u679C\u9A8C\u8BC1\u5931\u8D25\uFF0C\u4F1A\u663E\u793A\u5177\u4F53\u7684\u9519\u8BEF\u4FE1\u606F\u548C\u4FEE\u590D\u5EFA\u8BAE\u3002\n");
|
|
49184
|
+
files.push(checkTsxPath);
|
|
49185
|
+
reviewTsxPath = path__namespace.join(commandsDir, 'review-tsx.md');
|
|
49186
|
+
fs__namespace.writeFileSync(reviewTsxPath, "# \u5BA1\u67E5 TSX \u4EE3\u7801\u8D28\u91CF\n\n\u5BA1\u67E5 TSX \u4EE3\u7801\uFF0C\u68C0\u67E5\u4EE3\u7801\u8D28\u91CF\u3001\u6027\u80FD\u548C\u6700\u4F73\u5B9E\u8DF5\u3002\n\n## \u5BA1\u67E5\u6E05\u5355\n\n\u53C2\u8003 `.appthen/prompts/code-review.md` \u8FDB\u884C\u5BA1\u67E5\uFF1A\n\n1. **\u4EE3\u7801\u89C4\u8303**\n - JSDoc \u5143\u6570\u636E\u662F\u5426\u5B8C\u6574\n - IProps \u548C IState \u5B9A\u4E49\u662F\u5426\u6E05\u6670\n - render() \u65B9\u6CD5\u662F\u5426\u7B80\u6D01\n\n2. **\u4EE3\u7801\u8D28\u91CF**\n - \u4EE3\u7801\u662F\u5426\u6613\u4E8E\u7406\u89E3\n - \u662F\u5426\u6709\u91CD\u590D\u4EE3\u7801\n - \u6027\u80FD\u662F\u5426\u6709\u95EE\u9898\n\n3. **TSX \u89C4\u8303**\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u800C\u975E\u4E09\u5143\u8868\u8FBE\u5F0F\n - \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n - \u5217\u8868\u6E32\u67D3\u662F\u5426\u6709 key\n\n## \u8F93\u51FA\u683C\u5F0F\n\n\u63D0\u4F9B\u8BE6\u7EC6\u7684\u5BA1\u67E5\u62A5\u544A\uFF0C\u5305\u62EC\uFF1A\n- \u53D1\u73B0\u7684\u95EE\u9898\n- \u6539\u8FDB\u5EFA\u8BAE\n- \u4F18\u5148\u7EA7\u8BC4\u4F30\n");
|
|
49187
|
+
files.push(reviewTsxPath);
|
|
49188
|
+
createPagePath = path__namespace.join(commandsDir, 'create-page.md');
|
|
49189
|
+
fs__namespace.writeFileSync(createPagePath, "# \u521B\u5EFA\u65B0\u9875\u9762\n\n\u521B\u5EFA\u7B26\u5408 Appthen \u89C4\u8303\u7684\u65B0\u9875\u9762\u3002\n\n## \u91CD\u8981\u63D0\u793A\n\n\u26A0\uFE0F **\u5728\u751F\u6210\u4EE3\u7801\u524D\uFF0C\u5FC5\u987B\uFF1A**\n\n1. \u9605\u8BFB `.appthen/prompts/tsx-generation.md`\n2. \u68C0\u67E5 `.appthen/prompts/decision-tree.md` \u4E2D\u7684\u51B3\u7B56\u6D41\u7A0B\n3. \u786E\u8BA4\u7406\u89E3\u6240\u6709\u7EA6\u675F\u548C\u9650\u5236\n\n## \u751F\u6210\u6B65\u9AA4\n\n1. **\u786E\u8BA4\u9700\u6C42**\n - \u9875\u9762\u540D\u79F0\u548C\u8DEF\u7531\n - \u9700\u8981\u7684\u529F\u80FD\n - \u6570\u636E\u6765\u6E90\uFF08API \u63A5\u53E3\uFF09\n\n2. **\u751F\u6210\u4EE3\u7801**\n - \u5305\u542B\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n - \u9075\u5B88\u6240\u6709 TSX \u89C4\u8303\n - \u4F7F\u7528\u6B63\u786E\u7684\u5143\u6570\u636E\u6CE8\u91CA\n\n3. **\u9A8C\u8BC1\u4EE3\u7801**\n - \u8FD0\u884C `appthen check-tsx -f \"path/to/page.tsx\"`\n - \u4FEE\u6B63\u6240\u6709\u9519\u8BEF\n\n4. **\u6D4B\u8BD5\u529F\u80FD**\n - \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\n - \u6D4B\u8BD5\u6240\u6709\u529F\u80FD\n\n## \u6A21\u677F\u53C2\u8003\n\n\u53C2\u8003 `.appthen/prompts/tsx-generation.md` \u4E2D\u7684\u5B8C\u6574\u793A\u4F8B\u3002\n");
|
|
49190
|
+
files.push(createPagePath);
|
|
49191
|
+
createComponentPath = path__namespace.join(commandsDir, 'create-component.md');
|
|
49192
|
+
fs__namespace.writeFileSync(createComponentPath, "# \u521B\u5EFA\u65B0\u7EC4\u4EF6\n\n\u521B\u5EFA\u7B26\u5408 Appthen \u89C4\u8303\u7684\u65B0\u7EC4\u4EF6\u3002\n\n## \u91CD\u8981\u63D0\u793A\n\n\u26A0\uFE0F **\u5728\u751F\u6210\u4EE3\u7801\u524D\uFF0C\u5FC5\u987B\uFF1A**\n\n1. \u9605\u8BFB `.appthen/prompts/tsx-generation.md`\n2. \u68C0\u67E5 `.appthen/prompts/decision-tree.md` \u4E2D\u7684\u51B3\u7B56\u6D41\u7A0B\n3. \u786E\u8BA4\u7406\u89E3\u6240\u6709\u7EA6\u675F\u548C\u9650\u5236\n\n## \u751F\u6210\u6B65\u9AA4\n\n1. **\u786E\u8BA4\u9700\u6C42**\n - \u7EC4\u4EF6\u540D\u79F0\u548C\u7528\u9014\n - Props \u5B9A\u4E49\n - State \u5B9A\u4E49\uFF08\u5982\u679C\u9700\u8981\uFF09\n\n2. **\u751F\u6210\u4EE3\u7801**\n - \u5305\u542B\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n - \u9075\u5B88\u6240\u6709 TSX \u89C4\u8303\n - \u4F7F\u7528 @type Component \u5143\u6570\u636E\n\n3. **\u9A8C\u8BC1\u4EE3\u7801**\n - \u8FD0\u884C `appthen check-tsx -f \"path/to/component.tsx\"`\n - \u4FEE\u6B63\u6240\u6709\u9519\u8BEF\n\n4. **\u6D4B\u8BD5\u529F\u80FD**\n - \u5728\u9875\u9762\u4E2D\u4F7F\u7528\u7EC4\u4EF6\n - \u6D4B\u8BD5\u6240\u6709 Props \u548C\u4EA4\u4E92\n\n## \u7EC4\u4EF6 vs \u9875\u9762\n\n- **\u9875\u9762**\uFF1A\u4F7F\u7528 @type Page\uFF0C\u53EF\u4EE5\u901A\u8FC7 URL \u8BBF\u95EE\n- **\u7EC4\u4EF6**\uFF1A\u4F7F\u7528 @type Component\uFF0C\u53EF\u590D\u7528\u7684 UI \u5355\u5143\n\n## \u6A21\u677F\u53C2\u8003\n\n\u53C2\u8003 `.appthen/prompts/tsx-generation.md` \u4E2D\u7684\u5B8C\u6574\u793A\u4F8B\u3002\n");
|
|
49193
|
+
files.push(createComponentPath);
|
|
49194
|
+
if (this.verbose) {
|
|
49195
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u547D\u4EE4: ".concat(files.length, " \u4E2A\u6587\u4EF6"));
|
|
49196
|
+
}
|
|
49197
|
+
return [2 /*return*/, files];
|
|
49198
|
+
});
|
|
49199
|
+
});
|
|
49200
|
+
};
|
|
49201
|
+
return ClaudeCodeGenerator;
|
|
49202
|
+
}());
|
|
49203
|
+
|
|
49204
|
+
/**
|
|
49205
|
+
* Cursor 生成器
|
|
49206
|
+
* 生成 Cursor 特定的配置文件
|
|
49207
|
+
*/
|
|
49208
|
+
var CursorGenerator = /** @class */ (function () {
|
|
49209
|
+
function CursorGenerator(cwd, config, verbose) {
|
|
49210
|
+
this.cwd = cwd;
|
|
49211
|
+
this.config = config;
|
|
49212
|
+
this.verbose = verbose;
|
|
49213
|
+
}
|
|
49214
|
+
/**
|
|
49215
|
+
* 生成 Cursor 配置
|
|
49216
|
+
*/
|
|
49217
|
+
CursorGenerator.prototype.generate = function () {
|
|
49218
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49219
|
+
var files, cursorDir, rulesFile, promptsDir, instructionsFile, error_1;
|
|
49220
|
+
return __generator(this, function (_a) {
|
|
49221
|
+
switch (_a.label) {
|
|
49222
|
+
case 0:
|
|
49223
|
+
files = [];
|
|
49224
|
+
_a.label = 1;
|
|
49225
|
+
case 1:
|
|
49226
|
+
_a.trys.push([1, 4, , 5]);
|
|
49227
|
+
if (this.verbose) {
|
|
49228
|
+
console.log('🎯 配置 Cursor 集成...');
|
|
49229
|
+
}
|
|
49230
|
+
cursorDir = path__namespace.join(this.cwd, '.cursor');
|
|
49231
|
+
if (!fs__namespace.existsSync(cursorDir)) {
|
|
49232
|
+
fs__namespace.mkdirSync(cursorDir, { recursive: true });
|
|
49233
|
+
if (this.verbose) {
|
|
49234
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(cursorDir));
|
|
49235
|
+
}
|
|
49236
|
+
}
|
|
49237
|
+
return [4 /*yield*/, this.createRulesFile(cursorDir)];
|
|
49238
|
+
case 2:
|
|
49239
|
+
rulesFile = _a.sent();
|
|
49240
|
+
files.push(rulesFile);
|
|
49241
|
+
promptsDir = path__namespace.join(cursorDir, 'prompts');
|
|
49242
|
+
if (!fs__namespace.existsSync(promptsDir)) {
|
|
49243
|
+
fs__namespace.mkdirSync(promptsDir, { recursive: true });
|
|
49244
|
+
}
|
|
49245
|
+
return [4 /*yield*/, this.createCustomInstructions(promptsDir)];
|
|
49246
|
+
case 3:
|
|
49247
|
+
instructionsFile = _a.sent();
|
|
49248
|
+
files.push(instructionsFile);
|
|
49249
|
+
if (this.verbose) {
|
|
49250
|
+
console.log('✅ Cursor 配置完成');
|
|
49251
|
+
}
|
|
49252
|
+
return [2 /*return*/, {
|
|
49253
|
+
success: true,
|
|
49254
|
+
files: files,
|
|
49255
|
+
message: 'Cursor configuration created successfully',
|
|
49256
|
+
}];
|
|
49257
|
+
case 4:
|
|
49258
|
+
error_1 = _a.sent();
|
|
49259
|
+
return [2 /*return*/, {
|
|
49260
|
+
success: false,
|
|
49261
|
+
files: [],
|
|
49262
|
+
error: error_1.message,
|
|
49263
|
+
}];
|
|
49264
|
+
case 5: return [2 /*return*/];
|
|
49265
|
+
}
|
|
49266
|
+
});
|
|
49267
|
+
});
|
|
49268
|
+
};
|
|
49269
|
+
/**
|
|
49270
|
+
* 创建 Cursor Rules 文件
|
|
49271
|
+
*/
|
|
49272
|
+
CursorGenerator.prototype.createRulesFile = function (cursorDir) {
|
|
49273
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49274
|
+
var rulesPath, rulesContent;
|
|
49275
|
+
return __generator(this, function (_a) {
|
|
49276
|
+
rulesPath = path__namespace.join(cursorDir, 'rules.md');
|
|
49277
|
+
rulesContent = "# Cursor Rules for ".concat(this.config.projectName, "\n\n## TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303\n\n### \u6587\u4EF6\u7ED3\u6784\u8981\u6C42\n\n\u6240\u6709 TSX \u6587\u4EF6\u5FC5\u987B\u9075\u5FAA\u4EE5\u4E0B\u7ED3\u6784\uFF1A\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5173\u952E\u89C4\u5219\n\n1. **\u5FC5\u987B\u5305\u542B JSDoc \u5143\u6570\u636E**\n - \u4F7F\u7528 `@type Page` \u6216 `@type Component`\n - \u4F7F\u7528 `@description` \u63CF\u8FF0\u7EC4\u4EF6\u7528\u9014\n\n2. **\u4F7F\u7528 class \u5B9A\u4E49\u63A5\u53E3**\n - Props: `class IProps { }`\n - State: `class IState { }`\n\n3. **render() \u65B9\u6CD5\u89C4\u8303**\n - \u53EA\u5305\u542B `return` \u8BED\u53E5\u548C JSX\n - \u4E0D\u5305\u542B\u590D\u6742\u903B\u8F91\n - \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n\n4. **\u6761\u4EF6\u6E32\u67D3**\n - \u2705 \u4F7F\u7528: `{condition && <Component />}`\n - \u274C \u907F\u514D: `{condition ? <A /> : <B />}`\n\n5. **\u53EF\u9009\u94FE**\n - \u2705 \u4F7F\u7528: `user?.profile?.name`\n - \u274C \u907F\u514D: `user.profile.name`\n\n6. **\u7C7B\u578B\u6CE8\u89E3**\n - \u274C \u4E0D\u8981\u5728\u65B9\u6CD5\u53C2\u6570\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n - \u7C7B\u578B\u4FE1\u606F\u5E94\u8BE5\u5728 IProps \u548C IState \u4E2D\u5B9A\u4E49\n\n### \u4EE3\u7801\u793A\u4F8B\n\n```typescript\n/**\n * @type Page\n * @description \u7528\u6237\u5217\u8868\u9875\u9762\n */\n\nimport React from 'react';\n\nclass IProps {\n users: Array<{ id: string; name: string }>;\n onUserClick: (userId: string) => void;\n}\n\nclass IState {\n loading: boolean;\n searchText: string;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n searchText: '',\n };\n }\n\n getFilteredUsers() {\n const { users } = this.props;\n const { searchText } = this.state;\n \n if (!searchText) return users;\n \n return users.filter(u =>\n u?.name?.toLowerCase().includes(searchText.toLowerCase())\n );\n }\n\n render() {\n const { onUserClick } = this.props;\n const { loading, searchText } = this.state;\n const filteredUsers = this.getFilteredUsers();\n\n return (\n <div>\n <input\n value={searchText}\n onChange={(e) => this.setState({ searchText: e.target.value })}\n />\n \n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {!loading && filteredUsers.length === 0 && (\n <div>\u6682\u65E0\u6570\u636E</div>\n )}\n \n {!loading && filteredUsers.length > 0 && (\n <ul>\n {filteredUsers.map(user => (\n <li key={user.id} onClick={() => onUserClick(user.id)}>\n {user?.name}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u9879\u76EE\u7279\u5B9A\u89C4\u5219\n\n- \u9879\u76EE\u540D\u79F0: ").concat(this.config.projectName, "\n- \u7A7A\u95F4ID: ").concat(this.config.spaceId, "\n- \u521B\u5EFA\u65F6\u95F4: ").concat(this.config.createdAt, "\n\n## \u66F4\u591A\u4FE1\u606F\n\n\u8BE6\u7EC6\u7684\u63D0\u793A\u8BCD\u548C\u89C4\u8303\u8BF7\u67E5\u770B `.appthen/prompts/` \u76EE\u5F55\u3002\n");
|
|
49278
|
+
fs__namespace.writeFileSync(rulesPath, rulesContent);
|
|
49279
|
+
if (this.verbose) {
|
|
49280
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Cursor Rules: ".concat(rulesPath));
|
|
49281
|
+
}
|
|
49282
|
+
return [2 /*return*/, rulesPath];
|
|
49283
|
+
});
|
|
49284
|
+
});
|
|
49285
|
+
};
|
|
49286
|
+
/**
|
|
49287
|
+
* 创建自定义指令文件
|
|
49288
|
+
*/
|
|
49289
|
+
CursorGenerator.prototype.createCustomInstructions = function (promptsDir) {
|
|
49290
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49291
|
+
var instructionsPath, instructionsContent;
|
|
49292
|
+
return __generator(this, function (_a) {
|
|
49293
|
+
instructionsPath = path__namespace.join(promptsDir, 'custom-instructions.md');
|
|
49294
|
+
instructionsContent = "# Custom Instructions for ".concat(this.config.projectName, "\n\n## \u4EE3\u7801\u751F\u6210\u6307\u4EE4\n\n\u5F53\u751F\u6210 TSX \u4EE3\u7801\u65F6\uFF1A\n\n1. \u59CB\u7EC8\u9075\u5FAA `.cursor/rules.md` \u4E2D\u5B9A\u4E49\u7684\u89C4\u8303\n2. \u786E\u4FDD\u5305\u542B\u5B8C\u6574\u7684 JSDoc \u5143\u6570\u636E\n3. \u4F7F\u7528 class \u5B9A\u4E49 IProps \u548C IState\n4. render() \u65B9\u6CD5\u4FDD\u6301\u7B80\u6D01\n5. \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n6. \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n\n## \u4EE3\u7801\u5BA1\u67E5\u6307\u4EE4\n\n\u5F53\u5BA1\u67E5\u4EE3\u7801\u65F6\uFF1A\n\n1. \u68C0\u67E5\u662F\u5426\u7B26\u5408 TSX \u89C4\u8303\n2. \u8BC6\u522B\u6F5C\u5728\u7684\u6027\u80FD\u95EE\u9898\n3. \u68C0\u67E5\u8FB9\u754C\u60C5\u51B5\u5904\u7406\n4. \u9A8C\u8BC1\u9519\u8BEF\u5904\u7406\u903B\u8F91\n5. \u8BC4\u4F30\u4EE3\u7801\u53EF\u7EF4\u62A4\u6027\n\n## \u91CD\u6784\u6307\u4EE4\n\n\u5F53\u91CD\u6784\u4EE3\u7801\u65F6\uFF1A\n\n1. \u4FDD\u6301\u529F\u80FD\u4E0D\u53D8\n2. \u63D0\u53D6\u91CD\u590D\u4EE3\u7801\n3. \u7B80\u5316\u590D\u6742\u903B\u8F91\n4. \u63D0\u9AD8\u4EE3\u7801\u53EF\u8BFB\u6027\n5. \u4F18\u5316\u6027\u80FD\n\n## \u53C2\u8003\u8D44\u6599\n\n- TSX \u751F\u6210\u89C4\u8303: `.appthen/prompts/tsx-generation.md`\n- \u4EE3\u7801\u5BA1\u67E5\u6307\u5357: `.appthen/prompts/code-review.md`\n- \u91CD\u6784\u6307\u5357: `.appthen/prompts/refactoring.md`\n");
|
|
49295
|
+
fs__namespace.writeFileSync(instructionsPath, instructionsContent);
|
|
49296
|
+
if (this.verbose) {
|
|
49297
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u6307\u4EE4: ".concat(instructionsPath));
|
|
49298
|
+
}
|
|
49299
|
+
return [2 /*return*/, instructionsPath];
|
|
49300
|
+
});
|
|
49301
|
+
});
|
|
49302
|
+
};
|
|
49303
|
+
return CursorGenerator;
|
|
49304
|
+
}());
|
|
49305
|
+
|
|
49306
|
+
/**
|
|
49307
|
+
* Windsurf 生成器
|
|
49308
|
+
* 生成 Windsurf (Codeium) 特定的配置文件
|
|
49309
|
+
*/
|
|
49310
|
+
var WindsurfGenerator = /** @class */ (function () {
|
|
49311
|
+
function WindsurfGenerator(cwd, config, verbose) {
|
|
49312
|
+
this.cwd = cwd;
|
|
49313
|
+
this.config = config;
|
|
49314
|
+
this.verbose = verbose;
|
|
49315
|
+
}
|
|
49316
|
+
/**
|
|
49317
|
+
* 生成 Windsurf 配置
|
|
49318
|
+
*/
|
|
49319
|
+
WindsurfGenerator.prototype.generate = function () {
|
|
49320
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49321
|
+
var files, windsurfDir, cascadeFile, rulesFile, error_1;
|
|
49322
|
+
return __generator(this, function (_a) {
|
|
49323
|
+
switch (_a.label) {
|
|
49324
|
+
case 0:
|
|
49325
|
+
files = [];
|
|
49326
|
+
_a.label = 1;
|
|
49327
|
+
case 1:
|
|
49328
|
+
_a.trys.push([1, 4, , 5]);
|
|
49329
|
+
if (this.verbose) {
|
|
49330
|
+
console.log('🌊 配置 Windsurf 集成...');
|
|
49331
|
+
}
|
|
49332
|
+
windsurfDir = path__namespace.join(this.cwd, '.windsurf');
|
|
49333
|
+
if (!fs__namespace.existsSync(windsurfDir)) {
|
|
49334
|
+
fs__namespace.mkdirSync(windsurfDir, { recursive: true });
|
|
49335
|
+
if (this.verbose) {
|
|
49336
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(windsurfDir));
|
|
49337
|
+
}
|
|
49338
|
+
}
|
|
49339
|
+
return [4 /*yield*/, this.createCascadeConfig(windsurfDir)];
|
|
49340
|
+
case 2:
|
|
49341
|
+
cascadeFile = _a.sent();
|
|
49342
|
+
files.push(cascadeFile);
|
|
49343
|
+
return [4 /*yield*/, this.createRulesFile(windsurfDir)];
|
|
49344
|
+
case 3:
|
|
49345
|
+
rulesFile = _a.sent();
|
|
49346
|
+
files.push(rulesFile);
|
|
49347
|
+
if (this.verbose) {
|
|
49348
|
+
console.log('✅ Windsurf 配置完成');
|
|
49349
|
+
}
|
|
49350
|
+
return [2 /*return*/, {
|
|
49351
|
+
success: true,
|
|
49352
|
+
files: files,
|
|
49353
|
+
message: 'Windsurf configuration created successfully',
|
|
49354
|
+
}];
|
|
49355
|
+
case 4:
|
|
49356
|
+
error_1 = _a.sent();
|
|
49357
|
+
return [2 /*return*/, {
|
|
49358
|
+
success: false,
|
|
49359
|
+
files: [],
|
|
49360
|
+
error: error_1.message,
|
|
49361
|
+
}];
|
|
49362
|
+
case 5: return [2 /*return*/];
|
|
49363
|
+
}
|
|
49364
|
+
});
|
|
49365
|
+
});
|
|
49366
|
+
};
|
|
49367
|
+
/**
|
|
49368
|
+
* 创建 Cascade 配置文件
|
|
49369
|
+
*/
|
|
49370
|
+
WindsurfGenerator.prototype.createCascadeConfig = function (windsurfDir) {
|
|
49371
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49372
|
+
var cascadePath, cascadeConfig;
|
|
49373
|
+
return __generator(this, function (_a) {
|
|
49374
|
+
cascadePath = path__namespace.join(windsurfDir, 'cascade.json');
|
|
49375
|
+
cascadeConfig = {
|
|
49376
|
+
name: this.config.projectName,
|
|
49377
|
+
description: "Agent+ Space configuration for ".concat(this.config.projectName),
|
|
49378
|
+
version: '1.0.0',
|
|
49379
|
+
rules: {
|
|
49380
|
+
tsx: {
|
|
49381
|
+
enabled: true,
|
|
49382
|
+
strictMode: true,
|
|
49383
|
+
checkMetadata: true,
|
|
49384
|
+
checkClassDefinitions: true,
|
|
49385
|
+
checkRenderMethod: true,
|
|
49386
|
+
enforceConditionalRendering: true,
|
|
49387
|
+
enforceOptionalChaining: true,
|
|
49388
|
+
},
|
|
49389
|
+
},
|
|
49390
|
+
prompts: {
|
|
49391
|
+
codeGeneration: '.appthen/prompts/tsx-generation.md',
|
|
49392
|
+
codeReview: '.appthen/prompts/code-review.md',
|
|
49393
|
+
refactoring: '.appthen/prompts/refactoring.md',
|
|
49394
|
+
},
|
|
49395
|
+
workspace: {
|
|
49396
|
+
root: this.cwd,
|
|
49397
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49398
|
+
exclude: [
|
|
49399
|
+
'node_modules/**',
|
|
49400
|
+
'dist/**',
|
|
49401
|
+
'build/**',
|
|
49402
|
+
'.git/**',
|
|
49403
|
+
'*.log',
|
|
49404
|
+
],
|
|
49405
|
+
},
|
|
49406
|
+
};
|
|
49407
|
+
fs__namespace.writeFileSync(cascadePath, JSON.stringify(cascadeConfig, null, 2));
|
|
49408
|
+
if (this.verbose) {
|
|
49409
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Cascade \u914D\u7F6E: ".concat(cascadePath));
|
|
49410
|
+
}
|
|
49411
|
+
return [2 /*return*/, cascadePath];
|
|
49412
|
+
});
|
|
49413
|
+
});
|
|
49414
|
+
};
|
|
49415
|
+
/**
|
|
49416
|
+
* 创建 Rules 文件
|
|
49417
|
+
*/
|
|
49418
|
+
WindsurfGenerator.prototype.createRulesFile = function (windsurfDir) {
|
|
49419
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49420
|
+
var rulesPath, rulesContent;
|
|
49421
|
+
return __generator(this, function (_a) {
|
|
49422
|
+
rulesPath = path__namespace.join(windsurfDir, 'rules.md');
|
|
49423
|
+
rulesContent = "# Windsurf Rules for ".concat(this.config.projectName, "\n\n## TSX \u4EE3\u7801\u89C4\u8303\n\n### \u57FA\u672C\u8981\u6C42\n\n1. **\u6587\u4EF6\u7ED3\u6784**\n - JSDoc \u5143\u6570\u636E\u6CE8\u91CA\uFF08@type, @description\uFF09\n - class IProps \u548C class IState \u5B9A\u4E49\n - class Document extends React.Component\n - render() \u65B9\u6CD5\u53EA\u5305\u542B return \u8BED\u53E5\n\n2. **\u6761\u4EF6\u6E32\u67D3**\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\n - \u907F\u514D\u4E09\u5143\u8868\u8FBE\u5F0F\n\n3. **\u5BF9\u8C61\u8BBF\u95EE**\n - \u4F7F\u7528\u53EF\u9009\u94FE\uFF08?.\uFF09\n - \u907F\u514D\u76F4\u63A5\u5C5E\u6027\u8BBF\u95EE\n\n### \u4EE3\u7801\u751F\u6210\u6A21\u677F\n\n```typescript\n/**\n * @type Page|Component\n * @description [\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u6700\u4F73\u5B9E\u8DF5\n\n- \u4FDD\u6301 render() \u65B9\u6CD5\u7B80\u6D01\n- \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n- \u4F7F\u7528\u6709\u610F\u4E49\u7684\u53D8\u91CF\u540D\n- \u6DFB\u52A0\u5FC5\u8981\u7684\u6CE8\u91CA\n- \u5904\u7406\u8FB9\u754C\u60C5\u51B5\n\n### \u53C2\u8003\u8D44\u6599\n\n\u8BE6\u7EC6\u89C4\u8303\u8BF7\u67E5\u770B\uFF1A\n- `.appthen/prompts/tsx-generation.md`\n- `.appthen/prompts/code-review.md`\n- `.appthen/prompts/refactoring.md`\n\n## \u9879\u76EE\u4FE1\u606F\n\n- \u9879\u76EE: ").concat(this.config.projectName, "\n- \u7A7A\u95F4ID: ").concat(this.config.spaceId, "\n- \u5DE5\u5177: Windsurf (Codeium)\n");
|
|
49424
|
+
fs__namespace.writeFileSync(rulesPath, rulesContent);
|
|
49425
|
+
if (this.verbose) {
|
|
49426
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Rules \u6587\u4EF6: ".concat(rulesPath));
|
|
49427
|
+
}
|
|
49428
|
+
return [2 /*return*/, rulesPath];
|
|
49429
|
+
});
|
|
49430
|
+
});
|
|
49431
|
+
};
|
|
49432
|
+
return WindsurfGenerator;
|
|
49433
|
+
}());
|
|
49434
|
+
|
|
49435
|
+
/**
|
|
49436
|
+
* 阿里云 Coder 生成器
|
|
49437
|
+
* 生成阿里云 Coder 特定的配置文件
|
|
49438
|
+
*/
|
|
49439
|
+
var CoderGenerator = /** @class */ (function () {
|
|
49440
|
+
function CoderGenerator(cwd, config, verbose) {
|
|
49441
|
+
this.cwd = cwd;
|
|
49442
|
+
this.config = config;
|
|
49443
|
+
this.verbose = verbose;
|
|
49444
|
+
}
|
|
49445
|
+
/**
|
|
49446
|
+
* 生成阿里云 Coder 配置
|
|
49447
|
+
*/
|
|
49448
|
+
CoderGenerator.prototype.generate = function () {
|
|
49449
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49450
|
+
var files, coderDir, configFile, templatesDir, templateFile, error_1;
|
|
49451
|
+
return __generator(this, function (_a) {
|
|
49452
|
+
switch (_a.label) {
|
|
49453
|
+
case 0:
|
|
49454
|
+
files = [];
|
|
49455
|
+
_a.label = 1;
|
|
49456
|
+
case 1:
|
|
49457
|
+
_a.trys.push([1, 4, , 5]);
|
|
49458
|
+
if (this.verbose) {
|
|
49459
|
+
console.log('☁️ 配置阿里云 Coder 集成...');
|
|
49460
|
+
}
|
|
49461
|
+
coderDir = path__namespace.join(this.cwd, '.coder');
|
|
49462
|
+
if (!fs__namespace.existsSync(coderDir)) {
|
|
49463
|
+
fs__namespace.mkdirSync(coderDir, { recursive: true });
|
|
49464
|
+
if (this.verbose) {
|
|
49465
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(coderDir));
|
|
49466
|
+
}
|
|
49467
|
+
}
|
|
49468
|
+
return [4 /*yield*/, this.createConfig(coderDir)];
|
|
49469
|
+
case 2:
|
|
49470
|
+
configFile = _a.sent();
|
|
49471
|
+
files.push(configFile);
|
|
49472
|
+
templatesDir = path__namespace.join(coderDir, 'templates');
|
|
49473
|
+
if (!fs__namespace.existsSync(templatesDir)) {
|
|
49474
|
+
fs__namespace.mkdirSync(templatesDir, { recursive: true });
|
|
49475
|
+
}
|
|
49476
|
+
return [4 /*yield*/, this.createTsxTemplate(templatesDir)];
|
|
49477
|
+
case 3:
|
|
49478
|
+
templateFile = _a.sent();
|
|
49479
|
+
files.push(templateFile);
|
|
49480
|
+
if (this.verbose) {
|
|
49481
|
+
console.log('✅ 阿里云 Coder 配置完成');
|
|
49482
|
+
}
|
|
49483
|
+
return [2 /*return*/, {
|
|
49484
|
+
success: true,
|
|
49485
|
+
files: files,
|
|
49486
|
+
message: 'Coder configuration created successfully',
|
|
49487
|
+
}];
|
|
49488
|
+
case 4:
|
|
49489
|
+
error_1 = _a.sent();
|
|
49490
|
+
return [2 /*return*/, {
|
|
49491
|
+
success: false,
|
|
49492
|
+
files: [],
|
|
49493
|
+
error: error_1.message,
|
|
49494
|
+
}];
|
|
49495
|
+
case 5: return [2 /*return*/];
|
|
49496
|
+
}
|
|
49497
|
+
});
|
|
49498
|
+
});
|
|
49499
|
+
};
|
|
49500
|
+
/**
|
|
49501
|
+
* 创建配置文件
|
|
49502
|
+
*/
|
|
49503
|
+
CoderGenerator.prototype.createConfig = function (coderDir) {
|
|
49504
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49505
|
+
var configPath, config;
|
|
49506
|
+
return __generator(this, function (_a) {
|
|
49507
|
+
configPath = path__namespace.join(coderDir, 'config.json');
|
|
49508
|
+
config = {
|
|
49509
|
+
projectName: this.config.projectName,
|
|
49510
|
+
spaceId: this.config.spaceId,
|
|
49511
|
+
version: '1.0.0',
|
|
49512
|
+
codeGeneration: {
|
|
49513
|
+
tsx: {
|
|
49514
|
+
enabled: true,
|
|
49515
|
+
template: 'templates/tsx-template.md',
|
|
49516
|
+
rules: {
|
|
49517
|
+
requireMetadata: true,
|
|
49518
|
+
requireClassDefinitions: true,
|
|
49519
|
+
enforceRenderStructure: true,
|
|
49520
|
+
useConditionalOperator: true,
|
|
49521
|
+
useOptionalChaining: true,
|
|
49522
|
+
},
|
|
49523
|
+
},
|
|
49524
|
+
},
|
|
49525
|
+
prompts: {
|
|
49526
|
+
generation: '../.appthen/prompts/tsx-generation.md',
|
|
49527
|
+
review: '../.appthen/prompts/code-review.md',
|
|
49528
|
+
refactoring: '../.appthen/prompts/refactoring.md',
|
|
49529
|
+
},
|
|
49530
|
+
workspace: {
|
|
49531
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49532
|
+
exclude: [
|
|
49533
|
+
'node_modules/**',
|
|
49534
|
+
'dist/**',
|
|
49535
|
+
'build/**',
|
|
49536
|
+
'.git/**',
|
|
49537
|
+
'*.log',
|
|
49538
|
+
],
|
|
49539
|
+
},
|
|
49540
|
+
};
|
|
49541
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
49542
|
+
if (this.verbose) {
|
|
49543
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49544
|
+
}
|
|
49545
|
+
return [2 /*return*/, configPath];
|
|
49546
|
+
});
|
|
49547
|
+
});
|
|
49548
|
+
};
|
|
49549
|
+
/**
|
|
49550
|
+
* 创建 TSX 模板
|
|
49551
|
+
*/
|
|
49552
|
+
CoderGenerator.prototype.createTsxTemplate = function (templatesDir) {
|
|
49553
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49554
|
+
var templatePath, templateContent;
|
|
49555
|
+
return __generator(this, function (_a) {
|
|
49556
|
+
templatePath = path__namespace.join(templatesDir, 'tsx-template.md');
|
|
49557
|
+
templateContent = "# TSX \u4EE3\u7801\u6A21\u677F - ".concat(this.config.projectName, "\n\n## \u57FA\u7840\u6A21\u677F\n\n```typescript\n/**\n * @type [Page|Component]\n * @description [\u7EC4\u4EF6\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // TODO: \u5B9A\u4E49 Props\n}\n\nclass IState {\n // TODO: \u5B9A\u4E49 State\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n // TODO: \u521D\u59CB\u5316 State\n };\n }\n\n render() {\n return (\n <div>\n {/* TODO: \u5B9E\u73B0 JSX */}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u9875\u9762\u6A21\u677F\n\n```typescript\n/**\n * @type Page\n * @description [\u9875\u9762\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // \u9875\u9762 Props\n}\n\nclass IState {\n loading: boolean;\n data: any;\n error: string | null;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n data: null,\n error: null,\n };\n }\n\n componentDidMount() {\n this.loadData();\n }\n\n async loadData() {\n this.setState({ loading: true, error: null });\n \n try {\n // TODO: \u52A0\u8F7D\u6570\u636E\n const data = await fetchData();\n this.setState({ data, loading: false });\n } catch (error) {\n this.setState({ error: error.message, loading: false });\n }\n }\n\n render() {\n const { loading, data, error } = this.state;\n\n return (\n <div className=\"page\">\n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {error && <div className=\"error\">{error}</div>}\n \n {!loading && !error && data && (\n <div className=\"content\">\n {/* TODO: \u6E32\u67D3\u6570\u636E */}\n </div>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u7EC4\u4EF6\u6A21\u677F\n\n```typescript\n/**\n * @type Component\n * @description [\u7EC4\u4EF6\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // \u7EC4\u4EF6 Props\n}\n\nclass IState {\n // \u7EC4\u4EF6 State\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n const { } = this.props;\n \n return (\n <div className=\"component\">\n {/* TODO: \u5B9E\u73B0\u7EC4\u4EF6 */}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u4F7F\u7528\u8BF4\u660E\n\n1. \u9009\u62E9\u5408\u9002\u7684\u6A21\u677F\uFF08\u57FA\u7840/\u9875\u9762/\u7EC4\u4EF6\uFF09\n2. \u66FF\u6362 TODO \u6CE8\u91CA\u4E2D\u7684\u5185\u5BB9\n3. \u786E\u4FDD\u9075\u5FAA TSX \u89C4\u8303\uFF1A\n - \u5305\u542B JSDoc \u5143\u6570\u636E\n - \u4F7F\u7528 class \u5B9A\u4E49 IProps \u548C IState\n - render() \u53EA\u5305\u542B return \u8BED\u53E5\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n - \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n\n## \u53C2\u8003\u8D44\u6599\n\n- \u8BE6\u7EC6\u89C4\u8303: `.appthen/prompts/tsx-generation.md`\n- \u4EE3\u7801\u5BA1\u67E5: `.appthen/prompts/code-review.md`\n- \u91CD\u6784\u6307\u5357: `.appthen/prompts/refactoring.md`\n");
|
|
49558
|
+
fs__namespace.writeFileSync(templatePath, templateContent);
|
|
49559
|
+
if (this.verbose) {
|
|
49560
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA TSX \u6A21\u677F: ".concat(templatePath));
|
|
49561
|
+
}
|
|
49562
|
+
return [2 /*return*/, templatePath];
|
|
49563
|
+
});
|
|
49564
|
+
});
|
|
49565
|
+
};
|
|
49566
|
+
return CoderGenerator;
|
|
49567
|
+
}());
|
|
49568
|
+
|
|
49569
|
+
/**
|
|
49570
|
+
* Augment 生成器
|
|
49571
|
+
* 生成 Augment (VSCode 插件) 特定的配置文件
|
|
49572
|
+
*/
|
|
49573
|
+
var AugmentGenerator = /** @class */ (function () {
|
|
49574
|
+
function AugmentGenerator(cwd, config, verbose) {
|
|
49575
|
+
this.cwd = cwd;
|
|
49576
|
+
this.config = config;
|
|
49577
|
+
this.verbose = verbose;
|
|
49578
|
+
}
|
|
49579
|
+
/**
|
|
49580
|
+
* 生成 Augment 配置
|
|
49581
|
+
*/
|
|
49582
|
+
AugmentGenerator.prototype.generate = function () {
|
|
49583
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49584
|
+
var files, augmentDir, configFile, contextDir, contextFile, error_1;
|
|
49585
|
+
return __generator(this, function (_a) {
|
|
49586
|
+
switch (_a.label) {
|
|
49587
|
+
case 0:
|
|
49588
|
+
files = [];
|
|
49589
|
+
_a.label = 1;
|
|
49590
|
+
case 1:
|
|
49591
|
+
_a.trys.push([1, 4, , 5]);
|
|
49592
|
+
if (this.verbose) {
|
|
49593
|
+
console.log('🔧 配置 Augment 集成...');
|
|
49594
|
+
}
|
|
49595
|
+
augmentDir = path__namespace.join(this.cwd, '.augment');
|
|
49596
|
+
if (!fs__namespace.existsSync(augmentDir)) {
|
|
49597
|
+
fs__namespace.mkdirSync(augmentDir, { recursive: true });
|
|
49598
|
+
if (this.verbose) {
|
|
49599
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(augmentDir));
|
|
49600
|
+
}
|
|
49601
|
+
}
|
|
49602
|
+
return [4 /*yield*/, this.createConfig(augmentDir)];
|
|
49603
|
+
case 2:
|
|
49604
|
+
configFile = _a.sent();
|
|
49605
|
+
files.push(configFile);
|
|
49606
|
+
contextDir = path__namespace.join(augmentDir, 'context');
|
|
49607
|
+
if (!fs__namespace.existsSync(contextDir)) {
|
|
49608
|
+
fs__namespace.mkdirSync(contextDir, { recursive: true });
|
|
49609
|
+
}
|
|
49610
|
+
return [4 /*yield*/, this.createProjectContext(contextDir)];
|
|
49611
|
+
case 3:
|
|
49612
|
+
contextFile = _a.sent();
|
|
49613
|
+
files.push(contextFile);
|
|
49614
|
+
if (this.verbose) {
|
|
49615
|
+
console.log('✅ Augment 配置完成');
|
|
49616
|
+
}
|
|
49617
|
+
return [2 /*return*/, {
|
|
49618
|
+
success: true,
|
|
49619
|
+
files: files,
|
|
49620
|
+
message: 'Augment configuration created successfully',
|
|
49621
|
+
}];
|
|
49622
|
+
case 4:
|
|
49623
|
+
error_1 = _a.sent();
|
|
49624
|
+
return [2 /*return*/, {
|
|
49625
|
+
success: false,
|
|
49626
|
+
files: [],
|
|
49627
|
+
error: error_1.message,
|
|
49628
|
+
}];
|
|
49629
|
+
case 5: return [2 /*return*/];
|
|
49630
|
+
}
|
|
49631
|
+
});
|
|
49632
|
+
});
|
|
49633
|
+
};
|
|
49634
|
+
/**
|
|
49635
|
+
* 创建配置文件
|
|
49636
|
+
*/
|
|
49637
|
+
AugmentGenerator.prototype.createConfig = function (augmentDir) {
|
|
49638
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49639
|
+
var configPath, config;
|
|
49640
|
+
return __generator(this, function (_a) {
|
|
49641
|
+
configPath = path__namespace.join(augmentDir, 'config.json');
|
|
49642
|
+
config = {
|
|
49643
|
+
projectName: this.config.projectName,
|
|
49644
|
+
spaceId: this.config.spaceId,
|
|
49645
|
+
version: '1.0.0',
|
|
49646
|
+
context: {
|
|
49647
|
+
enabled: true,
|
|
49648
|
+
files: ['context/project-context.md'],
|
|
49649
|
+
prompts: [
|
|
49650
|
+
'../.appthen/prompts/tsx-generation.md',
|
|
49651
|
+
'../.appthen/prompts/code-review.md',
|
|
49652
|
+
'../.appthen/prompts/refactoring.md',
|
|
49653
|
+
],
|
|
49654
|
+
},
|
|
49655
|
+
codeGeneration: {
|
|
49656
|
+
tsx: {
|
|
49657
|
+
enabled: true,
|
|
49658
|
+
strictMode: true,
|
|
49659
|
+
autoFormat: true,
|
|
49660
|
+
},
|
|
49661
|
+
},
|
|
49662
|
+
workspace: {
|
|
49663
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49664
|
+
exclude: [
|
|
49665
|
+
'node_modules/**',
|
|
49666
|
+
'dist/**',
|
|
49667
|
+
'build/**',
|
|
49668
|
+
'.git/**',
|
|
49669
|
+
'*.log',
|
|
49670
|
+
],
|
|
49671
|
+
},
|
|
49672
|
+
};
|
|
49673
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
49674
|
+
if (this.verbose) {
|
|
49675
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49676
|
+
}
|
|
49677
|
+
return [2 /*return*/, configPath];
|
|
49678
|
+
});
|
|
49679
|
+
});
|
|
49680
|
+
};
|
|
49681
|
+
/**
|
|
49682
|
+
* 创建项目上下文文件
|
|
49683
|
+
*/
|
|
49684
|
+
AugmentGenerator.prototype.createProjectContext = function (contextDir) {
|
|
49685
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49686
|
+
var contextPath, contextContent;
|
|
49687
|
+
return __generator(this, function (_a) {
|
|
49688
|
+
contextPath = path__namespace.join(contextDir, 'project-context.md');
|
|
49689
|
+
contextContent = "# Project Context - ".concat(this.config.projectName, "\n\n## \u9879\u76EE\u4FE1\u606F\n\n- **\u9879\u76EE\u540D\u79F0**: ").concat(this.config.projectName, "\n- **\u7A7A\u95F4ID**: ").concat(this.config.spaceId, "\n- **\u521B\u5EFA\u65F6\u95F4**: ").concat(this.config.createdAt, "\n- **AI \u5DE5\u5177**: Augment (VSCode)\n\n## TSX \u4EE3\u7801\u89C4\u8303\n\n### \u6587\u4EF6\u7ED3\u6784\n\n\u6240\u6709 TSX \u6587\u4EF6\u5FC5\u987B\u9075\u5FAA\u4EE5\u4E0B\u7ED3\u6784\uFF1A\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5173\u952E\u89C4\u5219\n\n1. **JSDoc \u5143\u6570\u636E**\n - \u5FC5\u987B\u5305\u542B `@type` \u548C `@description`\n - `@type` \u503C\u4E3A `Page` \u6216 `Component`\n\n2. **\u7C7B\u5B9A\u4E49**\n - \u4F7F\u7528 `class IProps` \u5B9A\u4E49 Props\n - \u4F7F\u7528 `class IState` \u5B9A\u4E49 State\n - \u7EC4\u4EF6\u7C7B\u7EE7\u627F `React.Component<IProps, IState>`\n\n3. **render() \u65B9\u6CD5**\n - \u53EA\u5305\u542B `return` \u8BED\u53E5\u548C JSX\n - \u4E0D\u5305\u542B\u590D\u6742\u903B\u8F91\n - \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n\n4. **\u6761\u4EF6\u6E32\u67D3**\n - \u2705 \u4F7F\u7528: `{condition && <Component />}`\n - \u274C \u907F\u514D: `{condition ? <A /> : <B />}`\n\n5. **\u5BF9\u8C61\u8BBF\u95EE**\n - \u2705 \u4F7F\u7528: `user?.profile?.name`\n - \u274C \u907F\u514D: `user.profile.name`\n\n6. **\u7C7B\u578B\u6CE8\u89E3**\n - \u274C \u4E0D\u8981\u5728\u65B9\u6CD5\u53C2\u6570\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n - \u7C7B\u578B\u4FE1\u606F\u5728 IProps \u548C IState \u4E2D\u5B9A\u4E49\n\n### \u4EE3\u7801\u793A\u4F8B\n\n```typescript\n/**\n * @type Page\n * @description \u7528\u6237\u5217\u8868\u9875\u9762\n */\n\nimport React from 'react';\n\nclass IProps {\n users: Array<{ id: string; name: string }>;\n}\n\nclass IState {\n loading: boolean;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n };\n }\n\n render() {\n const { users } = this.props;\n const { loading } = this.state;\n\n return (\n <div>\n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {!loading && users.length === 0 && (\n <div>\u6682\u65E0\u6570\u636E</div>\n )}\n \n {!loading && users.length > 0 && (\n <ul>\n {users.map(user => (\n <li key={user.id}>{user?.name}</li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u5F00\u53D1\u5DE5\u4F5C\u6D41\n\n1. **\u4EE3\u7801\u751F\u6210**\n - \u4F7F\u7528 Augment \u751F\u6210\u7B26\u5408\u89C4\u8303\u7684 TSX \u4EE3\u7801\n - \u53C2\u8003 `.appthen/prompts/tsx-generation.md`\n\n2. **\u4EE3\u7801\u5BA1\u67E5**\n - \u68C0\u67E5\u662F\u5426\u7B26\u5408 TSX \u89C4\u8303\n - \u53C2\u8003 `.appthen/prompts/code-review.md`\n\n3. **\u4EE3\u7801\u91CD\u6784**\n - \u63D0\u53D6\u91CD\u590D\u4EE3\u7801\n - \u7B80\u5316\u590D\u6742\u903B\u8F91\n - \u53C2\u8003 `.appthen/prompts/refactoring.md`\n\n## \u53C2\u8003\u8D44\u6599\n\n- **TSX \u751F\u6210\u89C4\u8303**: `.appthen/prompts/tsx-generation.md`\n- **\u4EE3\u7801\u5BA1\u67E5\u6307\u5357**: `.appthen/prompts/code-review.md`\n- **\u91CD\u6784\u6307\u5357**: `.appthen/prompts/refactoring.md`\n\n## \u6CE8\u610F\u4E8B\u9879\n\n- \u59CB\u7EC8\u9075\u5FAA TSX \u89C4\u8303\n- \u4FDD\u6301\u4EE3\u7801\u7B80\u6D01\u6613\u8BFB\n- \u5904\u7406\u8FB9\u754C\u60C5\u51B5\n- \u6DFB\u52A0\u5FC5\u8981\u7684\u6CE8\u91CA\n- \u4F7F\u7528\u6709\u610F\u4E49\u7684\u53D8\u91CF\u540D\n");
|
|
49690
|
+
fs__namespace.writeFileSync(contextPath, contextContent);
|
|
49691
|
+
if (this.verbose) {
|
|
49692
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u9879\u76EE\u4E0A\u4E0B\u6587: ".concat(contextPath));
|
|
49693
|
+
}
|
|
49694
|
+
return [2 /*return*/, contextPath];
|
|
49695
|
+
});
|
|
49696
|
+
});
|
|
49697
|
+
};
|
|
49698
|
+
return AugmentGenerator;
|
|
49699
|
+
}());
|
|
49700
|
+
|
|
49701
|
+
/**
|
|
49702
|
+
* 初始化 Agent+ Space
|
|
49703
|
+
*/
|
|
49704
|
+
function initSpace(options) {
|
|
49705
|
+
if (options === void 0) { options = {}; }
|
|
49706
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49707
|
+
var _a, force, _b, verbose, _c, cwd, _d, skipPrompts, _e, skipHooks, configPath, tool, projectName, spaceId, spaceConfig, baseGenerator, baseResult, toolResult, allFiles, error_1;
|
|
49708
|
+
return __generator(this, function (_f) {
|
|
49709
|
+
switch (_f.label) {
|
|
49710
|
+
case 0:
|
|
49711
|
+
_a = options.force, force = _a === void 0 ? false : _a, _b = options.verbose, verbose = _b === void 0 ? false : _b, _c = options.cwd, cwd = _c === void 0 ? process.cwd() : _c, _d = options.skipPrompts, skipPrompts = _d === void 0 ? false : _d, _e = options.skipHooks, skipHooks = _e === void 0 ? false : _e;
|
|
49712
|
+
_f.label = 1;
|
|
49713
|
+
case 1:
|
|
49714
|
+
_f.trys.push([1, 6, , 7]);
|
|
49715
|
+
configPath = path__namespace.join(cwd, '.appthen/space-config.json');
|
|
49716
|
+
if (fs__namespace.existsSync(configPath) && !force) {
|
|
49717
|
+
console.log('');
|
|
49718
|
+
console.log('⚠️ Space 已经初始化');
|
|
49719
|
+
console.log(" \u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49720
|
+
console.log('');
|
|
49721
|
+
console.log('💡 提示:');
|
|
49722
|
+
console.log(' - 使用 --force 强制重新初始化');
|
|
49723
|
+
console.log(' - 使用 appthen connect 连接到编辑器');
|
|
49724
|
+
console.log('');
|
|
49725
|
+
return [2 /*return*/, { success: false, error: 'Already initialized' }];
|
|
49726
|
+
}
|
|
49727
|
+
tool = options.tool;
|
|
49728
|
+
if (!!tool) return [3 /*break*/, 3];
|
|
49729
|
+
return [4 /*yield*/, promptForTool()];
|
|
49730
|
+
case 2:
|
|
49731
|
+
tool = _f.sent();
|
|
49732
|
+
_f.label = 3;
|
|
49733
|
+
case 3:
|
|
49734
|
+
projectName = options.name || path__namespace.basename(cwd);
|
|
49735
|
+
spaceId = "".concat(projectName, "-").concat(nanoid$1(8));
|
|
49736
|
+
spaceConfig = {
|
|
49737
|
+
spaceId: spaceId,
|
|
49738
|
+
projectId: options.projectId,
|
|
49739
|
+
projectName: projectName,
|
|
49740
|
+
projectRoot: cwd,
|
|
49741
|
+
tool: tool,
|
|
49742
|
+
createdAt: new Date().toISOString(),
|
|
49743
|
+
version: '1.0.0',
|
|
49744
|
+
};
|
|
49745
|
+
console.log('');
|
|
49746
|
+
console.log('🚀 初始化 Agent+ Space...');
|
|
49747
|
+
console.log('');
|
|
49748
|
+
if (verbose) {
|
|
49749
|
+
console.log(" \u5DE5\u5177: ".concat(getToolName(tool)));
|
|
49750
|
+
console.log(" \u9879\u76EE: ".concat(projectName));
|
|
49751
|
+
console.log(" \u7A7A\u95F4ID: ".concat(spaceId));
|
|
49752
|
+
console.log('');
|
|
49753
|
+
}
|
|
49754
|
+
baseGenerator = new BaseGenerator(cwd, spaceConfig, verbose);
|
|
49755
|
+
return [4 /*yield*/, baseGenerator.generate(skipPrompts)];
|
|
49756
|
+
case 4:
|
|
49757
|
+
baseResult = _f.sent();
|
|
49758
|
+
if (!baseResult.success) {
|
|
49759
|
+
console.error('❌ 基础配置生成失败:', baseResult.error);
|
|
49760
|
+
return [2 /*return*/, baseResult];
|
|
49761
|
+
}
|
|
49762
|
+
return [4 /*yield*/, generateToolSpecificFiles(tool, cwd, spaceConfig, verbose, skipHooks)];
|
|
49763
|
+
case 5:
|
|
49764
|
+
toolResult = _f.sent();
|
|
49765
|
+
if (!toolResult.success) {
|
|
49766
|
+
console.error('❌ 工具配置生成失败:', toolResult.error);
|
|
49767
|
+
return [2 /*return*/, toolResult];
|
|
49768
|
+
}
|
|
49769
|
+
// 7. 输出成功信息
|
|
49770
|
+
console.log('');
|
|
49771
|
+
console.log('🎉 Agent+ Space 初始化完成!');
|
|
49772
|
+
console.log('');
|
|
49773
|
+
console.log('📋 已创建的文件:');
|
|
49774
|
+
allFiles = __spreadArray(__spreadArray([], __read(baseResult.files), false), __read(toolResult.files), false);
|
|
49775
|
+
allFiles.forEach(function (file) {
|
|
49776
|
+
var relativePath = path__namespace.relative(cwd, file);
|
|
49777
|
+
console.log(" \u2713 ".concat(relativePath));
|
|
49778
|
+
});
|
|
49779
|
+
console.log('');
|
|
49780
|
+
console.log('🚀 下一步:');
|
|
49781
|
+
console.log(" cd ".concat(cwd));
|
|
49782
|
+
console.log(' appthen connect');
|
|
49783
|
+
console.log('');
|
|
49784
|
+
console.log('📖 更多信息:');
|
|
49785
|
+
console.log(' - 查看 .appthen/prompts/README.md 了解提示词使用');
|
|
49786
|
+
if (tool === 'claude-code') {
|
|
49787
|
+
console.log(' - 查看 .claude/settings.json 了解 Hooks 配置');
|
|
49788
|
+
}
|
|
49789
|
+
else if (tool === 'cursor') {
|
|
49790
|
+
console.log(' - 查看 .cursor/rules.md 了解 Cursor Rules');
|
|
49791
|
+
}
|
|
49792
|
+
else if (tool === 'windsurf') {
|
|
49793
|
+
console.log(' - 查看 .windsurf/cascade.json 了解 Cascade 配置');
|
|
49794
|
+
}
|
|
49795
|
+
else if (tool === 'coder') {
|
|
49796
|
+
console.log(' - 查看 .coder/config.json 了解配置选项');
|
|
49797
|
+
}
|
|
49798
|
+
else if (tool === 'augment') {
|
|
49799
|
+
console.log(' - 查看 .augment/context/project-context.md 了解项目上下文');
|
|
49800
|
+
}
|
|
49801
|
+
console.log('');
|
|
49802
|
+
return [2 /*return*/, {
|
|
49803
|
+
success: true,
|
|
49804
|
+
message: 'Space initialized successfully',
|
|
49805
|
+
spaceId: spaceId,
|
|
49806
|
+
files: allFiles,
|
|
49807
|
+
}];
|
|
49808
|
+
case 6:
|
|
49809
|
+
error_1 = _f.sent();
|
|
49810
|
+
console.error('');
|
|
49811
|
+
console.error('❌ 初始化失败:', error_1.message);
|
|
49812
|
+
console.error('');
|
|
49813
|
+
if (verbose) {
|
|
49814
|
+
console.error('错误详情:', error_1);
|
|
49815
|
+
}
|
|
49816
|
+
return [2 /*return*/, {
|
|
49817
|
+
success: false,
|
|
49818
|
+
error: error_1.message,
|
|
49819
|
+
}];
|
|
49820
|
+
case 7: return [2 /*return*/];
|
|
49821
|
+
}
|
|
49822
|
+
});
|
|
49823
|
+
});
|
|
49824
|
+
}
|
|
49825
|
+
/**
|
|
49826
|
+
* 提示用户选择 AI 工具
|
|
49827
|
+
*/
|
|
49828
|
+
function promptForTool() {
|
|
49829
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49830
|
+
var inquirer, answer;
|
|
49831
|
+
return __generator(this, function (_a) {
|
|
49832
|
+
switch (_a.label) {
|
|
49833
|
+
case 0:
|
|
49834
|
+
_a.trys.push([0, 3, , 4]);
|
|
49835
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('inquirer')); })];
|
|
49836
|
+
case 1:
|
|
49837
|
+
inquirer = _a.sent();
|
|
49838
|
+
return [4 /*yield*/, inquirer.default.prompt([
|
|
49839
|
+
{
|
|
49840
|
+
type: 'list',
|
|
49841
|
+
name: 'tool',
|
|
49842
|
+
message: '请选择你使用的 AI 编码工具:',
|
|
49843
|
+
choices: AI_TOOLS.map(function (tool) { return ({
|
|
49844
|
+
name: tool.name,
|
|
49845
|
+
value: tool.value,
|
|
49846
|
+
}); }),
|
|
49847
|
+
},
|
|
49848
|
+
])];
|
|
49849
|
+
case 2:
|
|
49850
|
+
answer = _a.sent();
|
|
49851
|
+
return [2 /*return*/, answer.tool];
|
|
49852
|
+
case 3:
|
|
49853
|
+
_a.sent();
|
|
49854
|
+
// 如果 inquirer 不可用,提供友好的错误提示
|
|
49855
|
+
console.log('');
|
|
49856
|
+
console.log('⚠️ 无法启动交互式选择');
|
|
49857
|
+
console.log('');
|
|
49858
|
+
console.log('💡 请使用 --tool 参数指定 AI 工具:');
|
|
49859
|
+
console.log('');
|
|
49860
|
+
console.log(' appthen init-space --tool claude-code # Claude Code');
|
|
49861
|
+
console.log(' appthen init-space --tool cursor # Cursor');
|
|
49862
|
+
console.log(' appthen init-space --tool windsurf # Windsurf');
|
|
49863
|
+
console.log(' appthen init-space --tool coder # 阿里云 Coder');
|
|
49864
|
+
console.log(' appthen init-space --tool augment # Augment');
|
|
49865
|
+
console.log(' appthen init-space --tool other # 其他/跳过');
|
|
49866
|
+
console.log('');
|
|
49867
|
+
throw new Error('需要指定 --tool 参数');
|
|
49868
|
+
case 4: return [2 /*return*/];
|
|
49869
|
+
}
|
|
49870
|
+
});
|
|
49871
|
+
});
|
|
49872
|
+
}
|
|
49873
|
+
/**
|
|
49874
|
+
* 根据工具生成特定文件
|
|
49875
|
+
*/
|
|
49876
|
+
function generateToolSpecificFiles(tool, cwd, config, verbose, skipHooks) {
|
|
49877
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49878
|
+
var _a, generator, generator, generator, generator, generator;
|
|
49879
|
+
return __generator(this, function (_b) {
|
|
49880
|
+
switch (_b.label) {
|
|
49881
|
+
case 0:
|
|
49882
|
+
_a = tool;
|
|
49883
|
+
switch (_a) {
|
|
49884
|
+
case 'claude-code': return [3 /*break*/, 1];
|
|
49885
|
+
case 'cursor': return [3 /*break*/, 3];
|
|
49886
|
+
case 'windsurf': return [3 /*break*/, 5];
|
|
49887
|
+
case 'coder': return [3 /*break*/, 7];
|
|
49888
|
+
case 'augment': return [3 /*break*/, 9];
|
|
49889
|
+
case 'other': return [3 /*break*/, 11];
|
|
49890
|
+
}
|
|
49891
|
+
return [3 /*break*/, 11];
|
|
49892
|
+
case 1:
|
|
49893
|
+
generator = new ClaudeCodeGenerator(cwd, config, verbose);
|
|
49894
|
+
return [4 /*yield*/, generator.generate(skipHooks)];
|
|
49895
|
+
case 2: return [2 /*return*/, _b.sent()];
|
|
49896
|
+
case 3:
|
|
49897
|
+
generator = new CursorGenerator(cwd, config, verbose);
|
|
49898
|
+
return [4 /*yield*/, generator.generate()];
|
|
49899
|
+
case 4: return [2 /*return*/, _b.sent()];
|
|
49900
|
+
case 5:
|
|
49901
|
+
generator = new WindsurfGenerator(cwd, config, verbose);
|
|
49902
|
+
return [4 /*yield*/, generator.generate()];
|
|
49903
|
+
case 6: return [2 /*return*/, _b.sent()];
|
|
49904
|
+
case 7:
|
|
49905
|
+
generator = new CoderGenerator(cwd, config, verbose);
|
|
49906
|
+
return [4 /*yield*/, generator.generate()];
|
|
49907
|
+
case 8: return [2 /*return*/, _b.sent()];
|
|
49908
|
+
case 9:
|
|
49909
|
+
generator = new AugmentGenerator(cwd, config, verbose);
|
|
49910
|
+
return [4 /*yield*/, generator.generate()];
|
|
49911
|
+
case 10: return [2 /*return*/, _b.sent()];
|
|
49912
|
+
case 11:
|
|
49913
|
+
{
|
|
49914
|
+
// 只生成基础配置,不生成工具特定文件
|
|
49915
|
+
if (verbose) {
|
|
49916
|
+
console.log('⏭️ 跳过工具特定配置');
|
|
49917
|
+
}
|
|
49918
|
+
return [2 /*return*/, {
|
|
49919
|
+
success: true,
|
|
49920
|
+
files: [],
|
|
49921
|
+
message: 'No tool-specific configuration generated',
|
|
49922
|
+
}];
|
|
49923
|
+
}
|
|
49924
|
+
case 12: return [2 /*return*/];
|
|
49925
|
+
}
|
|
49926
|
+
});
|
|
49927
|
+
});
|
|
49928
|
+
}
|
|
49929
|
+
/**
|
|
49930
|
+
* 获取工具的显示名称
|
|
49931
|
+
*/
|
|
49932
|
+
function getToolName(tool) {
|
|
49933
|
+
var toolChoice = AI_TOOLS.find(function (t) { return t.value === tool; });
|
|
49934
|
+
return toolChoice ? toolChoice.name : tool;
|
|
49935
|
+
}
|
|
49936
|
+
|
|
48301
49937
|
exports.ShadowSpace = ShadowSpace;
|
|
48302
49938
|
exports.ShadowSpaceDebugger = ShadowSpaceDebugger;
|
|
48303
49939
|
exports.TSXComplianceChecker = TSXComplianceChecker;
|
|
@@ -48316,6 +49952,7 @@ exports.generateFixSuggestions = generateFixSuggestions;
|
|
|
48316
49952
|
exports.getPureValue = getPureValue;
|
|
48317
49953
|
exports.initClaudeHooks = initClaudeHooks;
|
|
48318
49954
|
exports.initSolution = initSolution;
|
|
49955
|
+
exports.initSpace = initSpace;
|
|
48319
49956
|
exports.isFileCompliant = isFileCompliant;
|
|
48320
49957
|
exports.releaseMaterial = releaseMaterial;
|
|
48321
49958
|
exports.run = run;
|