@appthen/cli 1.2.2 → 1.2.4
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 +2652 -510
- 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) {
|
|
@@ -37867,37 +37880,7 @@ function create(options) {
|
|
|
37867
37880
|
console.log('[e] ', e_1);
|
|
37868
37881
|
// return {} as any;
|
|
37869
37882
|
throw e_1;
|
|
37870
|
-
case 7:
|
|
37871
|
-
// await createProjectFromTemplate(options.template);
|
|
37872
|
-
// await createProjectFromTemplate('https://cdn.appthen.cn/templates/appthen-vite-starter.zip', 'my-new-project');
|
|
37873
|
-
// const { projectType } = await inquirer.prompt([
|
|
37874
|
-
// {
|
|
37875
|
-
// type: 'list',
|
|
37876
|
-
// name: 'projectType',
|
|
37877
|
-
// message: 'Which type of project do you want to initialize?',
|
|
37878
|
-
// choices: ['Vite Project', 'Taro Project', 'Asset Package Project'],
|
|
37879
|
-
// },
|
|
37880
|
-
// ]);
|
|
37881
|
-
// switch (projectType) {
|
|
37882
|
-
// case 'Vite Project':
|
|
37883
|
-
// console.log('projectType: ', projectType);
|
|
37884
|
-
// // Initialize a Vite project
|
|
37885
|
-
// // await require('../dist/index.js').initViteProject(options);
|
|
37886
|
-
// break;
|
|
37887
|
-
// case 'Taro Project':
|
|
37888
|
-
// console.log('projectType: ', projectType);
|
|
37889
|
-
// // Initialize a Taro project
|
|
37890
|
-
// // await require('../dist/index.js').initTaroProject(options);
|
|
37891
|
-
// break;
|
|
37892
|
-
// case 'Asset Package Project':
|
|
37893
|
-
// console.log('projectType: ', projectType);
|
|
37894
|
-
// // Initialize an asset package project
|
|
37895
|
-
// // await require('../dist/index.js').initAssetPackageProject(options);
|
|
37896
|
-
// break;
|
|
37897
|
-
// default:
|
|
37898
|
-
// console.error('Unknown project type');
|
|
37899
|
-
// }
|
|
37900
|
-
return [2 /*return*/, 1];
|
|
37883
|
+
case 7: return [2 /*return*/, 1];
|
|
37901
37884
|
}
|
|
37902
37885
|
});
|
|
37903
37886
|
});
|
|
@@ -40679,6 +40662,10 @@ function regExpEscape (s) {
|
|
|
40679
40662
|
var ShadowSpace = /** @class */ (function () {
|
|
40680
40663
|
function ShadowSpace(config) {
|
|
40681
40664
|
this.contentCache = new Map(); // 内容缓存
|
|
40665
|
+
// 🆕 文件监听相关
|
|
40666
|
+
this.watcher = null;
|
|
40667
|
+
this.changeListeners = new Set();
|
|
40668
|
+
this.isWatching = false;
|
|
40682
40669
|
this.config = __assign({ spaceId: 'default', ignorePatterns: [
|
|
40683
40670
|
'node_modules/**',
|
|
40684
40671
|
'.git/**',
|
|
@@ -40719,6 +40706,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40719
40706
|
'.php',
|
|
40720
40707
|
'.rb',
|
|
40721
40708
|
'.swift',
|
|
40709
|
+
'.flow',
|
|
40710
|
+
'.draw',
|
|
40722
40711
|
'.kt',
|
|
40723
40712
|
'.data', // 添加 .data 扩展名支持
|
|
40724
40713
|
] }, config);
|
|
@@ -40798,7 +40787,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40798
40787
|
ShadowSpace.prototype.syncFromEditor = function (projectFiles) {
|
|
40799
40788
|
var _a;
|
|
40800
40789
|
return __awaiter(this, void 0, void 0, function () {
|
|
40801
|
-
var newFiles, projectFiles_1, projectFiles_1_1, file,
|
|
40790
|
+
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
40791
|
var e_1, _e, e_2, _f;
|
|
40803
40792
|
return __generator(this, function (_g) {
|
|
40804
40793
|
switch (_g.label) {
|
|
@@ -40807,61 +40796,69 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40807
40796
|
newFiles = {};
|
|
40808
40797
|
_g.label = 1;
|
|
40809
40798
|
case 1:
|
|
40810
|
-
_g.trys.push([1,
|
|
40799
|
+
_g.trys.push([1, 7, 8, 9]);
|
|
40811
40800
|
projectFiles_1 = __values(projectFiles), projectFiles_1_1 = projectFiles_1.next();
|
|
40812
40801
|
_g.label = 2;
|
|
40813
40802
|
case 2:
|
|
40814
|
-
if (!!projectFiles_1_1.done) return [3 /*break*/,
|
|
40803
|
+
if (!!projectFiles_1_1.done) return [3 /*break*/, 6];
|
|
40815
40804
|
file = projectFiles_1_1.value;
|
|
40816
40805
|
if (this.shouldIgnoreFile(file.path)) {
|
|
40817
40806
|
console.log("[ShadowSpace] \u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(file.path));
|
|
40818
|
-
return [3 /*break*/,
|
|
40807
|
+
return [3 /*break*/, 5];
|
|
40819
40808
|
}
|
|
40820
|
-
localHash = this.calculateHash(file.content);
|
|
40821
40809
|
size = Buffer.byteLength(file.content, 'utf8');
|
|
40822
40810
|
now = Date.now();
|
|
40823
40811
|
// 记录空内容文件
|
|
40824
40812
|
if (file.content === '') {
|
|
40825
40813
|
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7A7A\u5185\u5BB9\u6587\u4EF6: ".concat(file.path, " (size: ").concat(size, ")"));
|
|
40826
40814
|
}
|
|
40815
|
+
// 写入本地文件
|
|
40816
|
+
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40817
|
+
case 3:
|
|
40818
|
+
// 写入本地文件
|
|
40819
|
+
_g.sent();
|
|
40820
|
+
fullPath = path__default["default"].join(this.config.projectRoot, file.path);
|
|
40821
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
40822
|
+
case 4:
|
|
40823
|
+
writtenContent = _g.sent();
|
|
40824
|
+
localHash = this.calculateHash(writtenContent);
|
|
40825
|
+
remoteHash = file.hash || localHash;
|
|
40827
40826
|
newFiles[file.path] = {
|
|
40828
40827
|
path: file.path,
|
|
40829
40828
|
hash: localHash,
|
|
40830
|
-
remoteHash:
|
|
40829
|
+
remoteHash: remoteHash,
|
|
40831
40830
|
size: size,
|
|
40832
40831
|
lastSyncTime: now,
|
|
40833
40832
|
lastModified: file.modify || now,
|
|
40834
40833
|
version: ((_a = this.state.files[file.path]) === null || _a === void 0 ? void 0 : _a.version) + 1 || 1,
|
|
40835
40834
|
mtime: now,
|
|
40835
|
+
remoteModified: true,
|
|
40836
|
+
remoteModifiedTime: now,
|
|
40836
40837
|
};
|
|
40837
40838
|
console.log("[ShadowSpace] \u540C\u6B65\u6587\u4EF6: ".concat(file.path), {
|
|
40839
|
+
remoteHash: remoteHash.substring(0, 16),
|
|
40838
40840
|
localHash: localHash.substring(0, 16),
|
|
40839
|
-
remoteHash: (file.hash || localHash).substring(0, 16),
|
|
40840
40841
|
size: size,
|
|
40842
|
+
version: newFiles[file.path].version,
|
|
40841
40843
|
});
|
|
40842
|
-
// 写入本地文件
|
|
40843
|
-
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40844
|
-
case 3:
|
|
40845
|
-
// 写入本地文件
|
|
40846
|
-
_g.sent();
|
|
40847
40844
|
// 缓存内容用于diff
|
|
40848
|
-
this.contentCache.set(file.path,
|
|
40849
|
-
_g.label =
|
|
40850
|
-
case
|
|
40845
|
+
this.contentCache.set(file.path, writtenContent);
|
|
40846
|
+
_g.label = 5;
|
|
40847
|
+
case 5:
|
|
40851
40848
|
projectFiles_1_1 = projectFiles_1.next();
|
|
40852
40849
|
return [3 /*break*/, 2];
|
|
40853
|
-
case
|
|
40854
|
-
case
|
|
40850
|
+
case 6: return [3 /*break*/, 9];
|
|
40851
|
+
case 7:
|
|
40855
40852
|
e_1_1 = _g.sent();
|
|
40856
40853
|
e_1 = { error: e_1_1 };
|
|
40857
|
-
return [3 /*break*/,
|
|
40858
|
-
case
|
|
40854
|
+
return [3 /*break*/, 9];
|
|
40855
|
+
case 8:
|
|
40859
40856
|
try {
|
|
40860
40857
|
if (projectFiles_1_1 && !projectFiles_1_1.done && (_e = projectFiles_1.return)) _e.call(projectFiles_1);
|
|
40861
40858
|
}
|
|
40862
40859
|
finally { if (e_1) throw e_1.error; }
|
|
40863
40860
|
return [7 /*endfinally*/];
|
|
40864
|
-
case
|
|
40861
|
+
case 9:
|
|
40865
40862
|
try {
|
|
40866
40863
|
// 合并文件记录,而不是替换
|
|
40867
40864
|
for (_b = __values(Object.entries(newFiles)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
@@ -40887,11 +40884,11 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40887
40884
|
console.log("[ShadowSpace] \u66F4\u65B0\u540E\u7684\u6587\u4EF6\u7EDF\u8BA1:", {
|
|
40888
40885
|
totalFiles: totalFilesCount,
|
|
40889
40886
|
totalSize: totalSizeSum,
|
|
40890
|
-
fileList: Object.keys(this.state.files),
|
|
40887
|
+
// fileList: Object.keys(this.state.files),
|
|
40891
40888
|
});
|
|
40892
40889
|
this.state.lastUpdateTime = Date.now();
|
|
40893
40890
|
return [4 /*yield*/, this.saveState()];
|
|
40894
|
-
case
|
|
40891
|
+
case 10:
|
|
40895
40892
|
_g.sent();
|
|
40896
40893
|
console.log("\u5F71\u5B50\u7A7A\u95F4\u540C\u6B65\u5B8C\u6210: ".concat(this.state.metadata.totalFiles, " \u4E2A\u6587\u4EF6"));
|
|
40897
40894
|
return [2 /*return*/];
|
|
@@ -40990,54 +40987,62 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40990
40987
|
* 检测本地文件系统与影子空间的差异
|
|
40991
40988
|
*/
|
|
40992
40989
|
ShadowSpace.prototype.detectChanges = function () {
|
|
40990
|
+
var _a;
|
|
40993
40991
|
return __awaiter(this, void 0, void 0, function () {
|
|
40994
|
-
var changes,
|
|
40995
|
-
var e_3,
|
|
40996
|
-
return __generator(this, function (
|
|
40997
|
-
switch (
|
|
40992
|
+
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;
|
|
40993
|
+
var e_3, _k, _l, _m, e_4, _o;
|
|
40994
|
+
return __generator(this, function (_p) {
|
|
40995
|
+
switch (_p.label) {
|
|
40998
40996
|
case 0:
|
|
40999
40997
|
changes = [];
|
|
41000
|
-
|
|
40998
|
+
_p.label = 1;
|
|
41001
40999
|
case 1:
|
|
41002
|
-
|
|
41003
|
-
|
|
41004
|
-
|
|
41000
|
+
_p.trys.push([1, 16, 17, 18]);
|
|
41001
|
+
_b = __values(Object.entries(this.state.files)), _c = _b.next();
|
|
41002
|
+
_p.label = 2;
|
|
41005
41003
|
case 2:
|
|
41006
|
-
if (!!
|
|
41007
|
-
|
|
41004
|
+
if (!!_c.done) return [3 /*break*/, 15];
|
|
41005
|
+
_d = __read(_c.value, 2), filePath = _d[0], shadowEntry = _d[1];
|
|
41008
41006
|
localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
|
|
41009
|
-
|
|
41007
|
+
_p.label = 3;
|
|
41010
41008
|
case 3:
|
|
41011
|
-
|
|
41009
|
+
_p.trys.push([3, 11, , 14]);
|
|
41012
41010
|
return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
|
|
41013
41011
|
case 4:
|
|
41014
|
-
localContent =
|
|
41012
|
+
localContent = _p.sent();
|
|
41015
41013
|
localHash = this.calculateHash(localContent);
|
|
41016
41014
|
if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
|
|
41015
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(filePath), {
|
|
41016
|
+
localHash: localHash.substring(0, 16),
|
|
41017
|
+
shadowHash: shadowEntry.hash.substring(0, 16),
|
|
41018
|
+
remoteHash: ((_a = shadowEntry.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41019
|
+
remoteModified: shadowEntry.remoteModified || false,
|
|
41020
|
+
version: shadowEntry.version,
|
|
41021
|
+
});
|
|
41017
41022
|
if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
|
|
41018
41023
|
// 如果是远程修改,先更新影子空间记录并清除远程修改标记
|
|
41019
41024
|
console.log("\u68C0\u6D4B\u5230\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u53D8\u5316: ".concat(filePath));
|
|
41020
41025
|
// 更新影子空间记录
|
|
41021
|
-
|
|
41022
|
-
|
|
41023
|
-
|
|
41024
|
-
|
|
41026
|
+
_e = this.state.files;
|
|
41027
|
+
_f = filePath;
|
|
41028
|
+
_g = [__assign({}, shadowEntry)];
|
|
41029
|
+
_l = { hash: localHash };
|
|
41025
41030
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41026
41031
|
case 5:
|
|
41027
|
-
|
|
41032
|
+
_l.size = (_p.sent()).size, _l.lastSyncTime = Date.now(), _l.version = shadowEntry.version + 1;
|
|
41028
41033
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41029
41034
|
case 6:
|
|
41030
41035
|
// 更新影子空间记录
|
|
41031
|
-
|
|
41036
|
+
_e[_f] = __assign.apply(void 0, _g.concat([(_l.mtime = (_p.sent()).mtimeMs, _l.remoteModified = false, _l)]));
|
|
41032
41037
|
// 如果本地内容与最初的远程内容不同,则认为是本地修改
|
|
41033
41038
|
// 这里我们简化处理:任何在远程修改基础上的本地变化都视为本地修改
|
|
41034
41039
|
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
|
-
|
|
41040
|
+
_p.label = 7;
|
|
41036
41041
|
case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41037
41042
|
case 8:
|
|
41038
|
-
shadowContent =
|
|
41039
|
-
|
|
41040
|
-
|
|
41043
|
+
shadowContent = _p.sent();
|
|
41044
|
+
_j = (_h = changes).push;
|
|
41045
|
+
_m = {
|
|
41041
41046
|
id: this.generateId(),
|
|
41042
41047
|
action: 'modify',
|
|
41043
41048
|
path: filePath,
|
|
@@ -41045,21 +41050,21 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41045
41050
|
};
|
|
41046
41051
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41047
41052
|
case 9:
|
|
41048
|
-
|
|
41049
|
-
|
|
41053
|
+
_j.apply(_h, [(_m.timestamp = (_p.sent()).mtime.getTime(),
|
|
41054
|
+
_m.diff = {
|
|
41050
41055
|
before: shadowContent,
|
|
41051
41056
|
after: localContent,
|
|
41052
41057
|
},
|
|
41053
|
-
|
|
41054
|
-
|
|
41055
|
-
|
|
41058
|
+
_m.projectId = this.state.projectId,
|
|
41059
|
+
_m)]);
|
|
41060
|
+
_p.label = 10;
|
|
41056
41061
|
case 10: return [3 /*break*/, 14];
|
|
41057
41062
|
case 11:
|
|
41058
|
-
error_2 =
|
|
41063
|
+
error_2 = _p.sent();
|
|
41059
41064
|
if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
|
|
41060
41065
|
return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41061
41066
|
case 12:
|
|
41062
|
-
shadowContent =
|
|
41067
|
+
shadowContent = _p.sent();
|
|
41063
41068
|
changes.push({
|
|
41064
41069
|
id: this.generateId(),
|
|
41065
41070
|
action: 'delete',
|
|
@@ -41072,25 +41077,25 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41072
41077
|
},
|
|
41073
41078
|
projectId: this.state.projectId,
|
|
41074
41079
|
});
|
|
41075
|
-
|
|
41080
|
+
_p.label = 13;
|
|
41076
41081
|
case 13: return [3 /*break*/, 14];
|
|
41077
41082
|
case 14:
|
|
41078
|
-
|
|
41083
|
+
_c = _b.next();
|
|
41079
41084
|
return [3 /*break*/, 2];
|
|
41080
41085
|
case 15: return [3 /*break*/, 18];
|
|
41081
41086
|
case 16:
|
|
41082
|
-
e_3_1 =
|
|
41087
|
+
e_3_1 = _p.sent();
|
|
41083
41088
|
e_3 = { error: e_3_1 };
|
|
41084
41089
|
return [3 /*break*/, 18];
|
|
41085
41090
|
case 17:
|
|
41086
41091
|
try {
|
|
41087
|
-
if (
|
|
41092
|
+
if (_c && !_c.done && (_k = _b.return)) _k.call(_b);
|
|
41088
41093
|
}
|
|
41089
41094
|
finally { if (e_3) throw e_3.error; }
|
|
41090
41095
|
return [7 /*endfinally*/];
|
|
41091
41096
|
case 18: return [4 /*yield*/, this.scanLocalFiles()];
|
|
41092
41097
|
case 19:
|
|
41093
|
-
localFiles =
|
|
41098
|
+
localFiles = _p.sent();
|
|
41094
41099
|
try {
|
|
41095
41100
|
for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
|
|
41096
41101
|
localFile = localFiles_1_1.value;
|
|
@@ -41113,7 +41118,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41113
41118
|
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
41114
41119
|
finally {
|
|
41115
41120
|
try {
|
|
41116
|
-
if (localFiles_1_1 && !localFiles_1_1.done && (
|
|
41121
|
+
if (localFiles_1_1 && !localFiles_1_1.done && (_o = localFiles_1.return)) _o.call(localFiles_1);
|
|
41117
41122
|
}
|
|
41118
41123
|
finally { if (e_4) throw e_4.error; }
|
|
41119
41124
|
}
|
|
@@ -41208,7 +41213,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41208
41213
|
return !!this.state.files[filePath];
|
|
41209
41214
|
};
|
|
41210
41215
|
/**
|
|
41211
|
-
* 🆕
|
|
41216
|
+
* 🆕 读取影子空间中的文件内容(带缓存)
|
|
41212
41217
|
*/
|
|
41213
41218
|
ShadowSpace.prototype.readFile = function (filePath) {
|
|
41214
41219
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -41238,43 +41243,77 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41238
41243
|
});
|
|
41239
41244
|
});
|
|
41240
41245
|
};
|
|
41246
|
+
/**
|
|
41247
|
+
* 🆕 实时读取文件内容(直接从文件系统,不使用缓存)
|
|
41248
|
+
*/
|
|
41249
|
+
ShadowSpace.prototype.readRealTimeFile = function (filePath) {
|
|
41250
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41251
|
+
var fullPath, content, error_4;
|
|
41252
|
+
return __generator(this, function (_a) {
|
|
41253
|
+
switch (_a.label) {
|
|
41254
|
+
case 0:
|
|
41255
|
+
_a.trys.push([0, 3, , 4]);
|
|
41256
|
+
fullPath = path__default["default"].join(this.config.projectRoot, filePath);
|
|
41257
|
+
// 检查文件是否存在
|
|
41258
|
+
return [4 /*yield*/, fs__default$1["default"].access(fullPath)];
|
|
41259
|
+
case 1:
|
|
41260
|
+
// 检查文件是否存在
|
|
41261
|
+
_a.sent();
|
|
41262
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
41263
|
+
case 2:
|
|
41264
|
+
content = _a.sent();
|
|
41265
|
+
console.log("[ShadowSpace] \u5B9E\u65F6\u8BFB\u53D6\u6587\u4EF6\u6210\u529F: ".concat(filePath, ", \u957F\u5EA6: ").concat(content.length));
|
|
41266
|
+
// 可选:更新内存缓存以确保一致性
|
|
41267
|
+
this.contentCache.set(filePath, content);
|
|
41268
|
+
return [2 /*return*/, content];
|
|
41269
|
+
case 3:
|
|
41270
|
+
error_4 = _a.sent();
|
|
41271
|
+
console.warn("[ShadowSpace] \u5B9E\u65F6\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_4);
|
|
41272
|
+
return [2 /*return*/, null];
|
|
41273
|
+
case 4: return [2 /*return*/];
|
|
41274
|
+
}
|
|
41275
|
+
});
|
|
41276
|
+
});
|
|
41277
|
+
};
|
|
41241
41278
|
/**
|
|
41242
41279
|
* 标记文件为远程修改
|
|
41243
41280
|
* 当编辑器通过WebSocket修改文件后调用此方法
|
|
41244
41281
|
*/
|
|
41245
41282
|
ShadowSpace.prototype.markAsRemoteModified = function (filePaths) {
|
|
41283
|
+
var _a;
|
|
41246
41284
|
return __awaiter(this, void 0, void 0, function () {
|
|
41247
|
-
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile,
|
|
41248
|
-
var e_6,
|
|
41249
|
-
return __generator(this, function (
|
|
41250
|
-
switch (
|
|
41285
|
+
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_5, e_6_1;
|
|
41286
|
+
var e_6, _b;
|
|
41287
|
+
return __generator(this, function (_c) {
|
|
41288
|
+
switch (_c.label) {
|
|
41251
41289
|
case 0:
|
|
41252
41290
|
now = Date.now();
|
|
41253
41291
|
hasChanges = false;
|
|
41254
|
-
|
|
41292
|
+
_c.label = 1;
|
|
41255
41293
|
case 1:
|
|
41256
|
-
|
|
41294
|
+
_c.trys.push([1, 9, 10, 11]);
|
|
41257
41295
|
filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
|
|
41258
|
-
|
|
41296
|
+
_c.label = 2;
|
|
41259
41297
|
case 2:
|
|
41260
41298
|
if (!!filePaths_1_1.done) return [3 /*break*/, 8];
|
|
41261
41299
|
filePath = filePaths_1_1.value;
|
|
41262
41300
|
fullPath = path__default["default"].resolve(this.config.projectRoot, filePath);
|
|
41263
|
-
|
|
41301
|
+
_c.label = 3;
|
|
41264
41302
|
case 3:
|
|
41265
|
-
|
|
41303
|
+
_c.trys.push([3, 6, , 7]);
|
|
41266
41304
|
return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
|
|
41267
41305
|
case 4:
|
|
41268
|
-
stats =
|
|
41306
|
+
stats = _c.sent();
|
|
41269
41307
|
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
41270
41308
|
case 5:
|
|
41271
|
-
content =
|
|
41309
|
+
content = _c.sent();
|
|
41272
41310
|
hash = this.calculateHash(content);
|
|
41273
41311
|
existingFile = this.state.files[filePath];
|
|
41312
|
+
remoteHash = (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash;
|
|
41274
41313
|
this.state.files[filePath] = {
|
|
41275
41314
|
path: filePath,
|
|
41276
41315
|
hash: hash,
|
|
41277
|
-
remoteHash:
|
|
41316
|
+
remoteHash: remoteHash,
|
|
41278
41317
|
size: stats.size,
|
|
41279
41318
|
lastSyncTime: now,
|
|
41280
41319
|
lastModified: now,
|
|
@@ -41284,23 +41323,29 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41284
41323
|
remoteModifiedTime: now,
|
|
41285
41324
|
};
|
|
41286
41325
|
hasChanges = true;
|
|
41287
|
-
console.log("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath
|
|
41326
|
+
console.log("[ShadowSpace] \u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath), {
|
|
41327
|
+
版本: this.state.files[filePath].version,
|
|
41328
|
+
hash: hash.substring(0, 16),
|
|
41329
|
+
remoteHash: remoteHash.substring(0, 16),
|
|
41330
|
+
旧remoteHash: ((_a = existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41331
|
+
remoteHashChanged: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) !== remoteHash,
|
|
41332
|
+
});
|
|
41288
41333
|
return [3 /*break*/, 7];
|
|
41289
41334
|
case 6:
|
|
41290
|
-
|
|
41291
|
-
console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"),
|
|
41335
|
+
error_5 = _c.sent();
|
|
41336
|
+
console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"), error_5);
|
|
41292
41337
|
return [3 /*break*/, 7];
|
|
41293
41338
|
case 7:
|
|
41294
41339
|
filePaths_1_1 = filePaths_1.next();
|
|
41295
41340
|
return [3 /*break*/, 2];
|
|
41296
41341
|
case 8: return [3 /*break*/, 11];
|
|
41297
41342
|
case 9:
|
|
41298
|
-
e_6_1 =
|
|
41343
|
+
e_6_1 = _c.sent();
|
|
41299
41344
|
e_6 = { error: e_6_1 };
|
|
41300
41345
|
return [3 /*break*/, 11];
|
|
41301
41346
|
case 10:
|
|
41302
41347
|
try {
|
|
41303
|
-
if (filePaths_1_1 && !filePaths_1_1.done && (
|
|
41348
|
+
if (filePaths_1_1 && !filePaths_1_1.done && (_b = filePaths_1.return)) _b.call(filePaths_1);
|
|
41304
41349
|
}
|
|
41305
41350
|
finally { if (e_6) throw e_6.error; }
|
|
41306
41351
|
return [7 /*endfinally*/];
|
|
@@ -41309,9 +41354,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41309
41354
|
this.updateMetadata();
|
|
41310
41355
|
return [4 /*yield*/, this.saveState()];
|
|
41311
41356
|
case 12:
|
|
41312
|
-
|
|
41357
|
+
_c.sent();
|
|
41313
41358
|
console.log("\u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
|
|
41314
|
-
|
|
41359
|
+
_c.label = 13;
|
|
41315
41360
|
case 13: return [2 /*return*/];
|
|
41316
41361
|
}
|
|
41317
41362
|
});
|
|
@@ -41365,7 +41410,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41365
41410
|
*/
|
|
41366
41411
|
ShadowSpace.prototype.getSpaceSnapshots = function (_spaceId) {
|
|
41367
41412
|
return __awaiter(this, void 0, void 0, function () {
|
|
41368
|
-
var snapshots, _a, _b, _c, filePath, shadowEntry,
|
|
41413
|
+
var snapshots, _a, _b, _c, filePath, shadowEntry, error_6;
|
|
41369
41414
|
var e_8, _d;
|
|
41370
41415
|
return __generator(this, function (_e) {
|
|
41371
41416
|
switch (_e.label) {
|
|
@@ -41405,8 +41450,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41405
41450
|
console.log("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167: ".concat(snapshots.length, " \u4E2A\u6587\u4EF6"));
|
|
41406
41451
|
return [2 /*return*/, snapshots];
|
|
41407
41452
|
case 2:
|
|
41408
|
-
|
|
41409
|
-
console.error("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167\u5931\u8D25:",
|
|
41453
|
+
error_6 = _e.sent();
|
|
41454
|
+
console.error("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167\u5931\u8D25:", error_6);
|
|
41410
41455
|
return [2 /*return*/, []]; // 返回空数组而不是 undefined
|
|
41411
41456
|
case 3: return [2 /*return*/];
|
|
41412
41457
|
}
|
|
@@ -41467,7 +41512,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41467
41512
|
*/
|
|
41468
41513
|
ShadowSpace.prototype.saveSpaceConfig = function () {
|
|
41469
41514
|
return __awaiter(this, void 0, void 0, function () {
|
|
41470
|
-
var configFile, config,
|
|
41515
|
+
var configFile, config, error_8;
|
|
41471
41516
|
return __generator(this, function (_a) {
|
|
41472
41517
|
switch (_a.label) {
|
|
41473
41518
|
case 0:
|
|
@@ -41492,8 +41537,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41492
41537
|
console.log("[ShadowSpace] \u7A7A\u95F4\u914D\u7F6E\u5DF2\u4FDD\u5B58: ".concat(configFile));
|
|
41493
41538
|
return [3 /*break*/, 5];
|
|
41494
41539
|
case 4:
|
|
41495
|
-
|
|
41496
|
-
console.warn("[ShadowSpace] \u4FDD\u5B58\u7A7A\u95F4\u914D\u7F6E\u5931\u8D25:",
|
|
41540
|
+
error_8 = _a.sent();
|
|
41541
|
+
console.warn("[ShadowSpace] \u4FDD\u5B58\u7A7A\u95F4\u914D\u7F6E\u5931\u8D25:", error_8);
|
|
41497
41542
|
return [3 /*break*/, 5];
|
|
41498
41543
|
case 5: return [2 /*return*/];
|
|
41499
41544
|
}
|
|
@@ -41505,7 +41550,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41505
41550
|
*/
|
|
41506
41551
|
ShadowSpace.prototype.migrateOldStateFiles = function () {
|
|
41507
41552
|
return __awaiter(this, void 0, void 0, function () {
|
|
41508
|
-
var appthenDir, files, oldStateFiles, oldStateFiles_1, oldStateFiles_1_1, oldFile, oldFilePath, oldState, backupFile, e_9_1,
|
|
41553
|
+
var appthenDir, files, oldStateFiles, oldStateFiles_1, oldStateFiles_1_1, oldFile, oldFilePath, oldState, backupFile, e_9_1, error_9;
|
|
41509
41554
|
var e_9, _a;
|
|
41510
41555
|
var _this = this;
|
|
41511
41556
|
return __generator(this, function (_b) {
|
|
@@ -41571,8 +41616,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41571
41616
|
return [7 /*endfinally*/];
|
|
41572
41617
|
case 11: return [3 /*break*/, 13];
|
|
41573
41618
|
case 12:
|
|
41574
|
-
|
|
41575
|
-
console.warn("[ShadowSpace] \u8FC1\u79FB\u65E7\u72B6\u6001\u6587\u4EF6\u5931\u8D25:",
|
|
41619
|
+
error_9 = _b.sent();
|
|
41620
|
+
console.warn("[ShadowSpace] \u8FC1\u79FB\u65E7\u72B6\u6001\u6587\u4EF6\u5931\u8D25:", error_9);
|
|
41576
41621
|
return [3 /*break*/, 13];
|
|
41577
41622
|
case 13: return [2 /*return*/];
|
|
41578
41623
|
}
|
|
@@ -41581,7 +41626,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41581
41626
|
};
|
|
41582
41627
|
ShadowSpace.prototype.getShadowContent = function (filePath) {
|
|
41583
41628
|
return __awaiter(this, void 0, void 0, function () {
|
|
41584
|
-
var localPath, content,
|
|
41629
|
+
var localPath, content, error_10;
|
|
41585
41630
|
return __generator(this, function (_a) {
|
|
41586
41631
|
switch (_a.label) {
|
|
41587
41632
|
case 0:
|
|
@@ -41599,8 +41644,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41599
41644
|
this.contentCache.set(filePath, content);
|
|
41600
41645
|
return [2 /*return*/, content];
|
|
41601
41646
|
case 3:
|
|
41602
|
-
|
|
41603
|
-
console.warn("\u65E0\u6CD5\u83B7\u53D6\u5F71\u5B50\u5185\u5BB9: ".concat(filePath),
|
|
41647
|
+
error_10 = _a.sent();
|
|
41648
|
+
console.warn("\u65E0\u6CD5\u83B7\u53D6\u5F71\u5B50\u5185\u5BB9: ".concat(filePath), error_10);
|
|
41604
41649
|
return [2 /*return*/, ''];
|
|
41605
41650
|
case 4: return [2 /*return*/];
|
|
41606
41651
|
}
|
|
@@ -41614,44 +41659,27 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41614
41659
|
return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
41615
41660
|
};
|
|
41616
41661
|
ShadowSpace.prototype.shouldIgnoreFile = function (filePath) {
|
|
41662
|
+
// console.log(`[ShadowSpace] shouldIgnoreFile 检查: "${filePath}"`);
|
|
41617
41663
|
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
41664
|
// 特殊处理:过滤掉特定的系统文件
|
|
41623
41665
|
var fileName = filePath.split('/').pop() || '';
|
|
41624
41666
|
if (fileName === '.dirty_files.json') {
|
|
41625
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41626
41667
|
return true;
|
|
41627
41668
|
}
|
|
41628
41669
|
if (fileName === 'assets.json') {
|
|
41629
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41630
41670
|
return true;
|
|
41631
41671
|
}
|
|
41632
41672
|
if (fileName === 'project.json') {
|
|
41633
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41634
41673
|
return true;
|
|
41635
41674
|
}
|
|
41636
41675
|
if (fileName.endsWith('.doc')) {
|
|
41637
|
-
console.log("[ShadowSpace] .doc\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41638
41676
|
return true;
|
|
41639
41677
|
}
|
|
41640
|
-
//
|
|
41678
|
+
// 🔥 目录白名单检查:简化逻辑,允许 src/ 和 docs/ 下的所有文件
|
|
41679
|
+
var isInSrc = filePath.startsWith('src/');
|
|
41641
41680
|
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
41681
|
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) {
|
|
41682
|
+
if (!isInSrc && !isInDocs && !isRootConfig) {
|
|
41655
41683
|
console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u767D\u540D\u5355\u76EE\u5F55\u4E2D: ".concat(filePath));
|
|
41656
41684
|
return true;
|
|
41657
41685
|
}
|
|
@@ -41686,12 +41714,12 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41686
41714
|
return true;
|
|
41687
41715
|
}
|
|
41688
41716
|
}
|
|
41689
|
-
console.log(
|
|
41717
|
+
// console.log(`[ShadowSpace] 文件通过忽略检查: ${filePath}`);
|
|
41690
41718
|
return false;
|
|
41691
41719
|
};
|
|
41692
41720
|
ShadowSpace.prototype.writeLocalFile = function (filePath, content) {
|
|
41693
41721
|
return __awaiter(this, void 0, void 0, function () {
|
|
41694
|
-
var fullPath,
|
|
41722
|
+
var fullPath, error_11;
|
|
41695
41723
|
return __generator(this, function (_a) {
|
|
41696
41724
|
switch (_a.label) {
|
|
41697
41725
|
case 0:
|
|
@@ -41714,9 +41742,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41714
41742
|
console.log("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u6210\u529F: ".concat(fullPath));
|
|
41715
41743
|
return [3 /*break*/, 5];
|
|
41716
41744
|
case 4:
|
|
41717
|
-
|
|
41718
|
-
console.error("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u5931\u8D25: ".concat(fullPath),
|
|
41719
|
-
throw
|
|
41745
|
+
error_11 = _a.sent();
|
|
41746
|
+
console.error("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u5931\u8D25: ".concat(fullPath), error_11);
|
|
41747
|
+
throw error_11;
|
|
41720
41748
|
case 5: return [2 /*return*/];
|
|
41721
41749
|
}
|
|
41722
41750
|
});
|
|
@@ -41724,7 +41752,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41724
41752
|
};
|
|
41725
41753
|
ShadowSpace.prototype.scanLocalFiles = function () {
|
|
41726
41754
|
return __awaiter(this, void 0, void 0, function () {
|
|
41727
|
-
var files, pattern, options, filePaths, filePaths_2, filePaths_2_1, filePath, fullPath, content, stats,
|
|
41755
|
+
var files, pattern, options, filePaths, filePaths_2, filePaths_2_1, filePath, fullPath, content, stats, error_12, e_11_1;
|
|
41728
41756
|
var e_11, _a;
|
|
41729
41757
|
return __generator(this, function (_b) {
|
|
41730
41758
|
switch (_b.label) {
|
|
@@ -41764,8 +41792,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41764
41792
|
});
|
|
41765
41793
|
return [3 /*break*/, 7];
|
|
41766
41794
|
case 6:
|
|
41767
|
-
|
|
41768
|
-
console.warn("\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(filePath),
|
|
41795
|
+
error_12 = _b.sent();
|
|
41796
|
+
console.warn("\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_12);
|
|
41769
41797
|
return [3 /*break*/, 7];
|
|
41770
41798
|
case 7:
|
|
41771
41799
|
filePaths_2_1 = filePaths_2.next();
|
|
@@ -41851,15 +41879,330 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41851
41879
|
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
41852
41880
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
41853
41881
|
};
|
|
41882
|
+
// ==================== 🆕 文件监听功能 ====================
|
|
41883
|
+
/**
|
|
41884
|
+
* 启动文件监听
|
|
41885
|
+
*/
|
|
41886
|
+
ShadowSpace.prototype.startWatching = function () {
|
|
41887
|
+
var _this = this;
|
|
41888
|
+
if (this.isWatching) {
|
|
41889
|
+
console.log('[ShadowSpace] 文件监听已经在运行中');
|
|
41890
|
+
return;
|
|
41891
|
+
}
|
|
41892
|
+
console.log('[ShadowSpace] 启动文件监听...');
|
|
41893
|
+
console.log('[ShadowSpace] 监听目录:', this.config.projectRoot);
|
|
41894
|
+
try {
|
|
41895
|
+
// 🔥 使用轮询模式 + ignored 函数过滤
|
|
41896
|
+
this.watcher = chokidar__default["default"].watch(this.config.projectRoot, {
|
|
41897
|
+
ignored: function (filePath) {
|
|
41898
|
+
var relativePath = path__default["default"].relative(_this.config.projectRoot, filePath);
|
|
41899
|
+
// 忽略根目录本身
|
|
41900
|
+
if (!relativePath || relativePath === '.') {
|
|
41901
|
+
return true;
|
|
41902
|
+
}
|
|
41903
|
+
// 使用白名单过滤
|
|
41904
|
+
return _this.shouldIgnoreFile(relativePath);
|
|
41905
|
+
},
|
|
41906
|
+
persistent: true,
|
|
41907
|
+
ignoreInitial: true,
|
|
41908
|
+
usePolling: true,
|
|
41909
|
+
interval: 2000,
|
|
41910
|
+
binaryInterval: 3000,
|
|
41911
|
+
depth: 99,
|
|
41912
|
+
awaitWriteFinish: {
|
|
41913
|
+
stabilityThreshold: 500,
|
|
41914
|
+
pollInterval: 100,
|
|
41915
|
+
},
|
|
41916
|
+
});
|
|
41917
|
+
console.log('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
|
|
41918
|
+
}
|
|
41919
|
+
catch (error) {
|
|
41920
|
+
console.error('[ShadowSpace] 创建文件监听器失败:', error);
|
|
41921
|
+
return;
|
|
41922
|
+
}
|
|
41923
|
+
this.watcher
|
|
41924
|
+
.on('change', function (filePath) {
|
|
41925
|
+
_this.onFileChanged(filePath);
|
|
41926
|
+
})
|
|
41927
|
+
.on('add', function (filePath) {
|
|
41928
|
+
_this.onFileAdded(filePath);
|
|
41929
|
+
})
|
|
41930
|
+
.on('unlink', function (filePath) {
|
|
41931
|
+
_this.onFileDeleted(filePath);
|
|
41932
|
+
})
|
|
41933
|
+
.on('error', function (error) {
|
|
41934
|
+
console.error('[ShadowSpace] 文件监听错误:', error);
|
|
41935
|
+
})
|
|
41936
|
+
.on('ready', function () {
|
|
41937
|
+
_this.isWatching = true;
|
|
41938
|
+
console.log('[ShadowSpace] 文件监听已启动,正在监听:', _this.config.projectRoot);
|
|
41939
|
+
console.log('[ShadowSpace] 监听配置: 轮询模式 (interval: 2s)');
|
|
41940
|
+
});
|
|
41941
|
+
};
|
|
41942
|
+
/**
|
|
41943
|
+
* 停止文件监听
|
|
41944
|
+
*/
|
|
41945
|
+
ShadowSpace.prototype.stopWatching = function () {
|
|
41946
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41947
|
+
return __generator(this, function (_a) {
|
|
41948
|
+
switch (_a.label) {
|
|
41949
|
+
case 0:
|
|
41950
|
+
if (!this.isWatching || !this.watcher) {
|
|
41951
|
+
console.log('[ShadowSpace] 文件监听未运行');
|
|
41952
|
+
return [2 /*return*/];
|
|
41953
|
+
}
|
|
41954
|
+
console.log('[ShadowSpace] 停止文件监听...');
|
|
41955
|
+
return [4 /*yield*/, this.watcher.close()];
|
|
41956
|
+
case 1:
|
|
41957
|
+
_a.sent();
|
|
41958
|
+
this.watcher = null;
|
|
41959
|
+
this.isWatching = false;
|
|
41960
|
+
console.log('[ShadowSpace] 文件监听已停止');
|
|
41961
|
+
return [2 /*return*/];
|
|
41962
|
+
}
|
|
41963
|
+
});
|
|
41964
|
+
});
|
|
41965
|
+
};
|
|
41966
|
+
/**
|
|
41967
|
+
* 添加变更事件监听器
|
|
41968
|
+
*/
|
|
41969
|
+
ShadowSpace.prototype.addChangeListener = function (listener) {
|
|
41970
|
+
this.changeListeners.add(listener);
|
|
41971
|
+
};
|
|
41972
|
+
/**
|
|
41973
|
+
* 移除变更事件监听器
|
|
41974
|
+
*/
|
|
41975
|
+
ShadowSpace.prototype.removeChangeListener = function (listener) {
|
|
41976
|
+
this.changeListeners.delete(listener);
|
|
41977
|
+
};
|
|
41978
|
+
/**
|
|
41979
|
+
* 触发变更事件
|
|
41980
|
+
*/
|
|
41981
|
+
ShadowSpace.prototype.emitChangeEvent = function (event) {
|
|
41982
|
+
console.log('[ShadowSpace] 触发变更事件:', event);
|
|
41983
|
+
this.changeListeners.forEach(function (listener) {
|
|
41984
|
+
try {
|
|
41985
|
+
listener(event);
|
|
41986
|
+
}
|
|
41987
|
+
catch (error) {
|
|
41988
|
+
console.error('[ShadowSpace] 变更事件监听器执行失败:', error);
|
|
41989
|
+
}
|
|
41990
|
+
});
|
|
41991
|
+
};
|
|
41992
|
+
/**
|
|
41993
|
+
* 文件变更处理
|
|
41994
|
+
*/
|
|
41995
|
+
ShadowSpace.prototype.onFileChanged = function (filePath) {
|
|
41996
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41997
|
+
var relativePath, shadowEntry, content, hash, stats, error_14;
|
|
41998
|
+
return __generator(this, function (_a) {
|
|
41999
|
+
switch (_a.label) {
|
|
42000
|
+
case 0:
|
|
42001
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42002
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(relativePath));
|
|
42003
|
+
shadowEntry = this.state.files[relativePath];
|
|
42004
|
+
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42005
|
+
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42006
|
+
shadowEntry.remoteModified = false; // 清除标记
|
|
42007
|
+
return [4 /*yield*/, this.saveState()];
|
|
42008
|
+
case 1:
|
|
42009
|
+
_a.sent();
|
|
42010
|
+
return [2 /*return*/];
|
|
42011
|
+
case 2:
|
|
42012
|
+
_a.trys.push([2, 5, , 6]);
|
|
42013
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
|
|
42014
|
+
case 3:
|
|
42015
|
+
content = _a.sent();
|
|
42016
|
+
hash = this.calculateHash(content);
|
|
42017
|
+
return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
|
|
42018
|
+
case 4:
|
|
42019
|
+
stats = _a.sent();
|
|
42020
|
+
// 🔑 推送变更事件
|
|
42021
|
+
this.emitChangeEvent({
|
|
42022
|
+
path: relativePath,
|
|
42023
|
+
action: 'modify',
|
|
42024
|
+
timestamp: Date.now(),
|
|
42025
|
+
source: 'local',
|
|
42026
|
+
hash: hash,
|
|
42027
|
+
size: stats.size,
|
|
42028
|
+
});
|
|
42029
|
+
return [3 /*break*/, 6];
|
|
42030
|
+
case 5:
|
|
42031
|
+
error_14 = _a.sent();
|
|
42032
|
+
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath), error_14);
|
|
42033
|
+
return [3 /*break*/, 6];
|
|
42034
|
+
case 6: return [2 /*return*/];
|
|
42035
|
+
}
|
|
42036
|
+
});
|
|
42037
|
+
});
|
|
42038
|
+
};
|
|
42039
|
+
/**
|
|
42040
|
+
* 文件新增处理
|
|
42041
|
+
*/
|
|
42042
|
+
ShadowSpace.prototype.onFileAdded = function (filePath) {
|
|
42043
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42044
|
+
var relativePath, content, hash, stats, error_15;
|
|
42045
|
+
return __generator(this, function (_a) {
|
|
42046
|
+
switch (_a.label) {
|
|
42047
|
+
case 0:
|
|
42048
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42049
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u65B0\u589E: ".concat(relativePath));
|
|
42050
|
+
_a.label = 1;
|
|
42051
|
+
case 1:
|
|
42052
|
+
_a.trys.push([1, 4, , 5]);
|
|
42053
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
|
|
42054
|
+
case 2:
|
|
42055
|
+
content = _a.sent();
|
|
42056
|
+
hash = this.calculateHash(content);
|
|
42057
|
+
return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
|
|
42058
|
+
case 3:
|
|
42059
|
+
stats = _a.sent();
|
|
42060
|
+
// 🔑 推送变更事件
|
|
42061
|
+
this.emitChangeEvent({
|
|
42062
|
+
path: relativePath,
|
|
42063
|
+
action: 'add',
|
|
42064
|
+
timestamp: Date.now(),
|
|
42065
|
+
source: 'local',
|
|
42066
|
+
hash: hash,
|
|
42067
|
+
size: stats.size,
|
|
42068
|
+
});
|
|
42069
|
+
return [3 /*break*/, 5];
|
|
42070
|
+
case 4:
|
|
42071
|
+
error_15 = _a.sent();
|
|
42072
|
+
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath), error_15);
|
|
42073
|
+
return [3 /*break*/, 5];
|
|
42074
|
+
case 5: return [2 /*return*/];
|
|
42075
|
+
}
|
|
42076
|
+
});
|
|
42077
|
+
});
|
|
42078
|
+
};
|
|
42079
|
+
/**
|
|
42080
|
+
* 文件删除处理
|
|
42081
|
+
*/
|
|
42082
|
+
ShadowSpace.prototype.onFileDeleted = function (filePath) {
|
|
42083
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42084
|
+
var relativePath, shadowEntry;
|
|
42085
|
+
return __generator(this, function (_a) {
|
|
42086
|
+
switch (_a.label) {
|
|
42087
|
+
case 0:
|
|
42088
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42089
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5220\u9664: ".concat(relativePath));
|
|
42090
|
+
shadowEntry = this.state.files[relativePath];
|
|
42091
|
+
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42092
|
+
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u5220\u9664\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42093
|
+
shadowEntry.remoteModified = false; // 清除标记
|
|
42094
|
+
return [4 /*yield*/, this.saveState()];
|
|
42095
|
+
case 1:
|
|
42096
|
+
_a.sent();
|
|
42097
|
+
return [2 /*return*/];
|
|
42098
|
+
case 2:
|
|
42099
|
+
// 🔑 推送变更事件
|
|
42100
|
+
this.emitChangeEvent({
|
|
42101
|
+
path: relativePath,
|
|
42102
|
+
action: 'delete',
|
|
42103
|
+
timestamp: Date.now(),
|
|
42104
|
+
source: 'local',
|
|
42105
|
+
});
|
|
42106
|
+
return [2 /*return*/];
|
|
42107
|
+
}
|
|
42108
|
+
});
|
|
42109
|
+
});
|
|
42110
|
+
};
|
|
42111
|
+
/**
|
|
42112
|
+
* 获取监听状态
|
|
42113
|
+
*/
|
|
42114
|
+
ShadowSpace.prototype.isFileWatching = function () {
|
|
42115
|
+
return this.isWatching;
|
|
42116
|
+
};
|
|
41854
42117
|
return ShadowSpace;
|
|
41855
42118
|
}());
|
|
41856
42119
|
|
|
42120
|
+
/**
|
|
42121
|
+
* 变更聚合器
|
|
42122
|
+
* 将短时间内的多个文件变更聚合为一次批量推送,减少网络开销
|
|
42123
|
+
*/
|
|
42124
|
+
var ChangeAggregator = /** @class */ (function () {
|
|
42125
|
+
function ChangeAggregator(spaceId, userId, handler, debounceMs) {
|
|
42126
|
+
if (debounceMs === void 0) { debounceMs = 500; }
|
|
42127
|
+
this.pendingChanges = new Map();
|
|
42128
|
+
this.timer = null;
|
|
42129
|
+
this.spaceId = spaceId;
|
|
42130
|
+
this.userId = userId;
|
|
42131
|
+
this.handler = handler;
|
|
42132
|
+
this.debounceMs = debounceMs;
|
|
42133
|
+
}
|
|
42134
|
+
/**
|
|
42135
|
+
* 添加变更
|
|
42136
|
+
*/
|
|
42137
|
+
ChangeAggregator.prototype.addChange = function (change) {
|
|
42138
|
+
var _this = this;
|
|
42139
|
+
console.log("[ChangeAggregator] \u6DFB\u52A0\u53D8\u66F4: ".concat(change.path, " (").concat(change.action, ")"));
|
|
42140
|
+
// 使用文件路径作为 key,相同文件的多次变更只保留最后一次
|
|
42141
|
+
this.pendingChanges.set(change.path, change);
|
|
42142
|
+
// 防抖:重置定时器
|
|
42143
|
+
if (this.timer) {
|
|
42144
|
+
clearTimeout(this.timer);
|
|
42145
|
+
}
|
|
42146
|
+
this.timer = setTimeout(function () {
|
|
42147
|
+
_this.flush();
|
|
42148
|
+
}, this.debounceMs);
|
|
42149
|
+
};
|
|
42150
|
+
/**
|
|
42151
|
+
* 立即推送所有待处理的变更
|
|
42152
|
+
*/
|
|
42153
|
+
ChangeAggregator.prototype.flush = function () {
|
|
42154
|
+
if (this.pendingChanges.size === 0) {
|
|
42155
|
+
return;
|
|
42156
|
+
}
|
|
42157
|
+
var changes = Array.from(this.pendingChanges.values());
|
|
42158
|
+
this.pendingChanges.clear();
|
|
42159
|
+
if (this.timer) {
|
|
42160
|
+
clearTimeout(this.timer);
|
|
42161
|
+
this.timer = null;
|
|
42162
|
+
}
|
|
42163
|
+
console.log("[ChangeAggregator] \u63A8\u9001\u6279\u91CF\u53D8\u66F4: ".concat(changes.length, " \u4E2A\u6587\u4EF6"));
|
|
42164
|
+
// 调用处理器
|
|
42165
|
+
try {
|
|
42166
|
+
this.handler({
|
|
42167
|
+
spaceId: this.spaceId,
|
|
42168
|
+
userId: this.userId,
|
|
42169
|
+
changes: changes,
|
|
42170
|
+
timestamp: Date.now(),
|
|
42171
|
+
});
|
|
42172
|
+
}
|
|
42173
|
+
catch (error) {
|
|
42174
|
+
console.error('[ChangeAggregator] 批量变更处理失败:', error);
|
|
42175
|
+
}
|
|
42176
|
+
};
|
|
42177
|
+
/**
|
|
42178
|
+
* 清理资源
|
|
42179
|
+
*/
|
|
42180
|
+
ChangeAggregator.prototype.destroy = function () {
|
|
42181
|
+
if (this.timer) {
|
|
42182
|
+
clearTimeout(this.timer);
|
|
42183
|
+
this.timer = null;
|
|
42184
|
+
}
|
|
42185
|
+
this.pendingChanges.clear();
|
|
42186
|
+
};
|
|
42187
|
+
/**
|
|
42188
|
+
* 获取待处理变更数量
|
|
42189
|
+
*/
|
|
42190
|
+
ChangeAggregator.prototype.getPendingCount = function () {
|
|
42191
|
+
return this.pendingChanges.size;
|
|
42192
|
+
};
|
|
42193
|
+
return ChangeAggregator;
|
|
42194
|
+
}());
|
|
42195
|
+
|
|
41857
42196
|
/**
|
|
41858
42197
|
* 影子空间WebSocket指令处理器
|
|
41859
42198
|
*/
|
|
41860
42199
|
var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
41861
42200
|
function ShadowSpaceCommandHandler(shadowSpace, socketStore) {
|
|
41862
42201
|
this.currentUserId = null;
|
|
42202
|
+
// 🆕 变更聚合器
|
|
42203
|
+
this.changeAggregator = null;
|
|
42204
|
+
// 🆕 实时读取配置
|
|
42205
|
+
this.useRealtimeFileRead = true;
|
|
41863
42206
|
this.shadowSpace = shadowSpace;
|
|
41864
42207
|
this.socketStore = socketStore;
|
|
41865
42208
|
}
|
|
@@ -41870,15 +42213,22 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41870
42213
|
this.currentUserId = userId;
|
|
41871
42214
|
console.log("[ShadowSpace] \u8BBE\u7F6E\u5F53\u524D\u7528\u6237ID: ".concat(userId));
|
|
41872
42215
|
};
|
|
42216
|
+
/**
|
|
42217
|
+
* 设置是否使用实时文件读取
|
|
42218
|
+
*/
|
|
42219
|
+
ShadowSpaceCommandHandler.prototype.setRealtimeFileRead = function (enabled) {
|
|
42220
|
+
this.useRealtimeFileRead = enabled;
|
|
42221
|
+
console.log("[ShadowSpace] \u5B9E\u65F6\u6587\u4EF6\u8BFB\u53D6\u5DF2".concat(enabled ? '启用' : '禁用'));
|
|
42222
|
+
};
|
|
41873
42223
|
/**
|
|
41874
42224
|
* 处理WebSocket消息
|
|
41875
42225
|
*/
|
|
41876
42226
|
ShadowSpaceCommandHandler.prototype.handleMessage = function (data) {
|
|
41877
|
-
var _a, _b, _c, _d, _e, _f;
|
|
42227
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
41878
42228
|
return __awaiter(this, void 0, void 0, function () {
|
|
41879
|
-
var action, messageId, message, spaceInfo, requestSpaceId, result,
|
|
41880
|
-
return __generator(this, function (
|
|
41881
|
-
switch (
|
|
42229
|
+
var action, messageId, message, spaceInfo, requestSpaceId, result, _h, error_1, errorMessage;
|
|
42230
|
+
return __generator(this, function (_j) {
|
|
42231
|
+
switch (_j.label) {
|
|
41882
42232
|
case 0:
|
|
41883
42233
|
action = data.action, messageId = data.messageId, message = data.message;
|
|
41884
42234
|
console.log("[ShadowSpaceCommandHandler] \u6536\u5230\u6D88\u606F: ".concat(action), {
|
|
@@ -41904,12 +42254,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41904
42254
|
// 不发送响应,让其他CLI实例处理
|
|
41905
42255
|
return [2 /*return*/];
|
|
41906
42256
|
}
|
|
41907
|
-
|
|
42257
|
+
_j.label = 1;
|
|
41908
42258
|
case 1:
|
|
41909
|
-
|
|
42259
|
+
_j.trys.push([1, 28, , 29]);
|
|
41910
42260
|
result = void 0;
|
|
41911
|
-
|
|
41912
|
-
switch (
|
|
42261
|
+
_h = action;
|
|
42262
|
+
switch (_h) {
|
|
41913
42263
|
case 'shadow-space-get-changes': return [3 /*break*/, 2];
|
|
41914
42264
|
case 'shadow-space-get-file-content': return [3 /*break*/, 4];
|
|
41915
42265
|
case 'shadow-space-get-files-content': return [3 /*break*/, 6];
|
|
@@ -41921,70 +42271,75 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41921
42271
|
case 'shadow-space-mark-remote-modified': return [3 /*break*/, 18];
|
|
41922
42272
|
case 'shadow-space-clear-remote-flags': return [3 /*break*/, 20];
|
|
41923
42273
|
case 'shadow-space-detect-changes': return [3 /*break*/, 22];
|
|
42274
|
+
case 'shadow-space-discard-changes': return [3 /*break*/, 24];
|
|
41924
42275
|
}
|
|
41925
|
-
return [3 /*break*/,
|
|
42276
|
+
return [3 /*break*/, 26];
|
|
41926
42277
|
case 2: return [4 /*yield*/, this.getChanges()];
|
|
41927
42278
|
case 3:
|
|
41928
|
-
result =
|
|
41929
|
-
return [3 /*break*/,
|
|
42279
|
+
result = _j.sent();
|
|
42280
|
+
return [3 /*break*/, 27];
|
|
41930
42281
|
case 4:
|
|
41931
42282
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message:', JSON.stringify(message, null, 2));
|
|
41932
42283
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message.path:', message.path);
|
|
41933
42284
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message.message.path:', (_b = message.message) === null || _b === void 0 ? void 0 : _b.path);
|
|
41934
|
-
return [4 /*yield*/, this.getFileContent(((_c = message.message) === null || _c === void 0 ? void 0 : _c.path) || message.path)];
|
|
42285
|
+
return [4 /*yield*/, this.getFileContent(((_c = message.message) === null || _c === void 0 ? void 0 : _c.path) || message.path, this.useRealtimeFileRead)];
|
|
41935
42286
|
case 5:
|
|
41936
|
-
// 🆕 修复:路径在 message.message.path
|
|
41937
|
-
result =
|
|
41938
|
-
return [3 /*break*/,
|
|
41939
|
-
case 6: return [4 /*yield*/, this.getFilesContent(((_d = message.message) === null || _d === void 0 ? void 0 : _d.paths) || message.paths)];
|
|
42287
|
+
// 🆕 修复:路径在 message.message.path 中,使用配置的实时读取选项
|
|
42288
|
+
result = _j.sent();
|
|
42289
|
+
return [3 /*break*/, 27];
|
|
42290
|
+
case 6: return [4 /*yield*/, this.getFilesContent(((_d = message.message) === null || _d === void 0 ? void 0 : _d.paths) || message.paths, this.useRealtimeFileRead)];
|
|
41940
42291
|
case 7:
|
|
41941
|
-
// 🆕 修复:路径在 message.message.paths
|
|
41942
|
-
result =
|
|
41943
|
-
return [3 /*break*/,
|
|
42292
|
+
// 🆕 修复:路径在 message.message.paths 中,使用配置的实时读取选项
|
|
42293
|
+
result = _j.sent();
|
|
42294
|
+
return [3 /*break*/, 27];
|
|
41944
42295
|
case 8: return [4 /*yield*/, this.applyChanges(message.changes)];
|
|
41945
42296
|
case 9:
|
|
41946
|
-
result =
|
|
41947
|
-
return [3 /*break*/,
|
|
42297
|
+
result = _j.sent();
|
|
42298
|
+
return [3 /*break*/, 27];
|
|
41948
42299
|
case 10: return [4 /*yield*/, this.resetShadowSpace()];
|
|
41949
42300
|
case 11:
|
|
41950
|
-
result =
|
|
41951
|
-
return [3 /*break*/,
|
|
42301
|
+
result = _j.sent();
|
|
42302
|
+
return [3 /*break*/, 27];
|
|
41952
42303
|
case 12: return [4 /*yield*/, this.getSpaceInfo()];
|
|
41953
42304
|
case 13:
|
|
41954
|
-
result =
|
|
41955
|
-
return [3 /*break*/,
|
|
42305
|
+
result = _j.sent();
|
|
42306
|
+
return [3 /*break*/, 27];
|
|
41956
42307
|
case 14: return [4 /*yield*/, this.syncFromEditor(message.message.files)];
|
|
41957
42308
|
case 15:
|
|
41958
|
-
result =
|
|
41959
|
-
return [3 /*break*/,
|
|
42309
|
+
result = _j.sent();
|
|
42310
|
+
return [3 /*break*/, 27];
|
|
41960
42311
|
case 16: return [4 /*yield*/, this.deleteFile(message.filePath)];
|
|
41961
42312
|
case 17:
|
|
41962
|
-
result =
|
|
41963
|
-
return [3 /*break*/,
|
|
42313
|
+
result = _j.sent();
|
|
42314
|
+
return [3 /*break*/, 27];
|
|
41964
42315
|
case 18: return [4 /*yield*/, this.markRemoteModified(message.filePaths)];
|
|
41965
42316
|
case 19:
|
|
41966
|
-
result =
|
|
41967
|
-
return [3 /*break*/,
|
|
42317
|
+
result = _j.sent();
|
|
42318
|
+
return [3 /*break*/, 27];
|
|
41968
42319
|
case 20: return [4 /*yield*/, this.clearRemoteFlags(message.filePaths)];
|
|
41969
42320
|
case 21:
|
|
41970
|
-
result =
|
|
41971
|
-
return [3 /*break*/,
|
|
42321
|
+
result = _j.sent();
|
|
42322
|
+
return [3 /*break*/, 27];
|
|
41972
42323
|
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
42324
|
case 23:
|
|
41974
|
-
result =
|
|
41975
|
-
return [3 /*break*/,
|
|
41976
|
-
case 24:
|
|
42325
|
+
result = _j.sent();
|
|
42326
|
+
return [3 /*break*/, 27];
|
|
42327
|
+
case 24: return [4 /*yield*/, this.discardChanges(((_g = message.message) === null || _g === void 0 ? void 0 : _g.filePaths) || message.filePaths)];
|
|
41977
42328
|
case 25:
|
|
42329
|
+
result = _j.sent();
|
|
42330
|
+
return [3 /*break*/, 27];
|
|
42331
|
+
case 26: throw new Error("Unknown shadow space action: ".concat(action));
|
|
42332
|
+
case 27:
|
|
41978
42333
|
// 发送成功响应
|
|
41979
42334
|
this.sendResponse(action, messageId, true, result);
|
|
41980
|
-
return [3 /*break*/,
|
|
41981
|
-
case
|
|
41982
|
-
error_1 =
|
|
42335
|
+
return [3 /*break*/, 29];
|
|
42336
|
+
case 28:
|
|
42337
|
+
error_1 = _j.sent();
|
|
41983
42338
|
errorMessage = error_1 instanceof Error ? error_1.message : String(error_1);
|
|
41984
42339
|
console.error("Shadow space command error [".concat(action, "]:"), errorMessage);
|
|
41985
42340
|
this.sendResponse(action, messageId, false, undefined, errorMessage);
|
|
41986
|
-
return [3 /*break*/,
|
|
41987
|
-
case
|
|
42341
|
+
return [3 /*break*/, 29];
|
|
42342
|
+
case 29: return [2 /*return*/];
|
|
41988
42343
|
}
|
|
41989
42344
|
});
|
|
41990
42345
|
});
|
|
@@ -42043,9 +42398,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42043
42398
|
/**
|
|
42044
42399
|
* 2. 获取单个文件内容
|
|
42045
42400
|
*/
|
|
42046
|
-
ShadowSpaceCommandHandler.prototype.getFileContent = function (filePath) {
|
|
42401
|
+
ShadowSpaceCommandHandler.prototype.getFileContent = function (filePath, readRealtime) {
|
|
42402
|
+
if (readRealtime === void 0) { readRealtime = true; }
|
|
42047
42403
|
return __awaiter(this, void 0, void 0, function () {
|
|
42048
|
-
var normalizedPath, changes, change, fileContent,
|
|
42404
|
+
var normalizedPath, realTimeContent, result_1, readError_1, changes, change, fileContent, result_2, readError_2, result;
|
|
42049
42405
|
return __generator(this, function (_a) {
|
|
42050
42406
|
switch (_a.label) {
|
|
42051
42407
|
case 0:
|
|
@@ -42055,25 +42411,59 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42055
42411
|
normalizedPath = filePath.startsWith('/')
|
|
42056
42412
|
? filePath.substring(1)
|
|
42057
42413
|
: filePath;
|
|
42058
|
-
console.log("[ShadowSpace] \u83B7\u53D6\u6587\u4EF6\u5185\u5BB9: ".concat(filePath, " -> \u6807\u51C6\u5316\u4E3A: ").concat(normalizedPath));
|
|
42059
|
-
return [
|
|
42414
|
+
console.log("[ShadowSpace] \u83B7\u53D6\u6587\u4EF6\u5185\u5BB9: ".concat(filePath, " -> \u6807\u51C6\u5316\u4E3A: ").concat(normalizedPath, ", \u5B9E\u65F6\u8BFB\u53D6: ").concat(readRealtime));
|
|
42415
|
+
if (!readRealtime) return [3 /*break*/, 4];
|
|
42416
|
+
_a.label = 1;
|
|
42060
42417
|
case 1:
|
|
42418
|
+
_a.trys.push([1, 3, , 4]);
|
|
42419
|
+
return [4 /*yield*/, this.shadowSpace.readRealTimeFile(normalizedPath)];
|
|
42420
|
+
case 2:
|
|
42421
|
+
realTimeContent = _a.sent();
|
|
42422
|
+
if (realTimeContent !== null) {
|
|
42423
|
+
console.log("[ShadowSpace] \u6210\u529F\u8BFB\u53D6\u5B9E\u65F6\u6587\u4EF6: ".concat(normalizedPath));
|
|
42424
|
+
result_1 = {
|
|
42425
|
+
path: normalizedPath,
|
|
42426
|
+
action: 'read',
|
|
42427
|
+
version: 1,
|
|
42428
|
+
timestamp: Date.now(),
|
|
42429
|
+
diff: {
|
|
42430
|
+
before: '',
|
|
42431
|
+
after: realTimeContent,
|
|
42432
|
+
},
|
|
42433
|
+
metadata: {
|
|
42434
|
+
beforeSize: 0,
|
|
42435
|
+
afterSize: Buffer.byteLength(realTimeContent, 'utf8'),
|
|
42436
|
+
encoding: 'utf8',
|
|
42437
|
+
},
|
|
42438
|
+
};
|
|
42439
|
+
console.log("[ShadowSpace] \u5B9E\u65F6\u8BFB\u53D6\u6587\u4EF6\u6210\u529F: ".concat(normalizedPath, ", \u5927\u5C0F: ").concat(result_1.metadata.afterSize, " \u5B57\u8282"));
|
|
42440
|
+
return [2 /*return*/, result_1];
|
|
42441
|
+
}
|
|
42442
|
+
return [3 /*break*/, 4];
|
|
42443
|
+
case 3:
|
|
42444
|
+
readError_1 = _a.sent();
|
|
42445
|
+
console.warn("[ShadowSpace] \u5B9E\u65F6\u8BFB\u53D6\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u7F13\u5B58: ".concat(normalizedPath), readError_1);
|
|
42446
|
+
return [3 /*break*/, 4];
|
|
42447
|
+
case 4: return [4 /*yield*/, this.shadowSpace.detectChanges()];
|
|
42448
|
+
case 5:
|
|
42061
42449
|
changes = _a.sent();
|
|
42062
42450
|
change = changes.find(function (c) { return c.path === normalizedPath; });
|
|
42063
|
-
|
|
42451
|
+
console.log('change: ', change);
|
|
42452
|
+
if (!change) return [3 /*break*/, 6];
|
|
42064
42453
|
console.log("[ShadowSpace] \u5728\u53D8\u66F4\u5217\u8868\u4E2D\u627E\u5230\u6587\u4EF6: ".concat(normalizedPath));
|
|
42065
|
-
return [3 /*break*/,
|
|
42066
|
-
case
|
|
42454
|
+
return [3 /*break*/, 11];
|
|
42455
|
+
case 6:
|
|
42067
42456
|
console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u53D8\u66F4\u5217\u8868\u4E2D\uFF0C\u5C1D\u8BD5\u76F4\u63A5\u4ECE\u5F71\u5B50\u7A7A\u95F4\u8BFB\u53D6: ".concat(normalizedPath));
|
|
42068
|
-
_a.label =
|
|
42069
|
-
case
|
|
42070
|
-
_a.trys.push([
|
|
42457
|
+
_a.label = 7;
|
|
42458
|
+
case 7:
|
|
42459
|
+
_a.trys.push([7, 9, , 10]);
|
|
42071
42460
|
return [4 /*yield*/, this.shadowSpace.readFile(normalizedPath)];
|
|
42072
|
-
case
|
|
42461
|
+
case 8:
|
|
42073
42462
|
fileContent = _a.sent();
|
|
42463
|
+
console.log('fileContent: ', fileContent);
|
|
42074
42464
|
if (fileContent !== null) {
|
|
42075
42465
|
console.log("[ShadowSpace] \u6210\u529F\u4ECE\u5F71\u5B50\u7A7A\u95F4\u8BFB\u53D6\u6587\u4EF6: ".concat(normalizedPath));
|
|
42076
|
-
|
|
42466
|
+
result_2 = {
|
|
42077
42467
|
path: normalizedPath,
|
|
42078
42468
|
action: 'read',
|
|
42079
42469
|
version: 1,
|
|
@@ -42088,19 +42478,19 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42088
42478
|
encoding: 'utf8',
|
|
42089
42479
|
},
|
|
42090
42480
|
};
|
|
42091
|
-
console.log("[ShadowSpace] \u76F4\u63A5\u8BFB\u53D6\u6587\u4EF6\u6210\u529F: ".concat(normalizedPath, ", \u5927\u5C0F: ").concat(
|
|
42092
|
-
return [2 /*return*/,
|
|
42481
|
+
console.log("[ShadowSpace] \u76F4\u63A5\u8BFB\u53D6\u6587\u4EF6\u6210\u529F: ".concat(normalizedPath, ", \u5927\u5C0F: ").concat(result_2.metadata.afterSize, " \u5B57\u8282"));
|
|
42482
|
+
return [2 /*return*/, result_2];
|
|
42093
42483
|
}
|
|
42094
|
-
return [3 /*break*/,
|
|
42095
|
-
case
|
|
42096
|
-
|
|
42097
|
-
console.error("[ShadowSpace] \u76F4\u63A5\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(normalizedPath),
|
|
42098
|
-
return [3 /*break*/,
|
|
42099
|
-
case
|
|
42484
|
+
return [3 /*break*/, 10];
|
|
42485
|
+
case 9:
|
|
42486
|
+
readError_2 = _a.sent();
|
|
42487
|
+
console.error("[ShadowSpace] \u76F4\u63A5\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(normalizedPath), readError_2);
|
|
42488
|
+
return [3 /*break*/, 10];
|
|
42489
|
+
case 10:
|
|
42100
42490
|
// 如果都失败了,抛出错误
|
|
42101
42491
|
console.error("[ShadowSpace] \u83B7\u53D6\u6587\u4EF6\u5185\u5BB9\u5931\u8D25: \u6587\u4EF6\u672A\u627E\u5230: ".concat(normalizedPath));
|
|
42102
42492
|
throw new Error("File not found in shadow space: ".concat(normalizedPath));
|
|
42103
|
-
case
|
|
42493
|
+
case 11:
|
|
42104
42494
|
result = {
|
|
42105
42495
|
path: normalizedPath,
|
|
42106
42496
|
action: change.action,
|
|
@@ -42129,9 +42519,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42129
42519
|
/**
|
|
42130
42520
|
* 3. 批量获取文件内容
|
|
42131
42521
|
*/
|
|
42132
|
-
ShadowSpaceCommandHandler.prototype.getFilesContent = function (filePaths) {
|
|
42522
|
+
ShadowSpaceCommandHandler.prototype.getFilesContent = function (filePaths, readRealtime) {
|
|
42523
|
+
if (readRealtime === void 0) { readRealtime = true; }
|
|
42133
42524
|
return __awaiter(this, void 0, void 0, function () {
|
|
42134
|
-
var
|
|
42525
|
+
var results, filePaths_1, filePaths_1_1, filePath, normalizedPath, realTimeContent, shadowContent, error_2, e_1_1, result;
|
|
42135
42526
|
var e_1, _a;
|
|
42136
42527
|
return __generator(this, function (_b) {
|
|
42137
42528
|
switch (_b.label) {
|
|
@@ -42139,48 +42530,79 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42139
42530
|
if (!Array.isArray(filePaths) || filePaths.length === 0) {
|
|
42140
42531
|
throw new Error('File paths array is required');
|
|
42141
42532
|
}
|
|
42142
|
-
console.log("[ShadowSpace] \u6279\u91CF\u83B7\u53D6\u6587\u4EF6\u5185\u5BB9: ".concat(filePaths.length, " \u4E2A\u6587\u4EF6"));
|
|
42143
|
-
console.log("[ShadowSpace] \u6279\u91CF\u83B7\u53D6\u6587\u4EF6\u8DEF\u5F84:", filePaths.slice(0, 5)); // 显示前5个路径
|
|
42144
|
-
return [4 /*yield*/, this.shadowSpace.detectChanges()];
|
|
42145
|
-
case 1:
|
|
42146
|
-
changes = _b.sent();
|
|
42533
|
+
console.log("[ShadowSpace] \u6279\u91CF\u83B7\u53D6\u6587\u4EF6\u5185\u5BB9: ".concat(filePaths.length, " \u4E2A\u6587\u4EF6, \u5B9E\u65F6\u8BFB\u53D6: ").concat(readRealtime));
|
|
42147
42534
|
results = [];
|
|
42148
|
-
|
|
42149
|
-
|
|
42150
|
-
|
|
42151
|
-
|
|
42152
|
-
|
|
42153
|
-
|
|
42154
|
-
|
|
42155
|
-
|
|
42156
|
-
|
|
42157
|
-
|
|
42158
|
-
|
|
42159
|
-
|
|
42160
|
-
|
|
42161
|
-
|
|
42162
|
-
|
|
42163
|
-
|
|
42164
|
-
|
|
42165
|
-
|
|
42166
|
-
|
|
42167
|
-
|
|
42168
|
-
|
|
42169
|
-
|
|
42170
|
-
|
|
42171
|
-
|
|
42172
|
-
|
|
42173
|
-
|
|
42174
|
-
|
|
42175
|
-
|
|
42535
|
+
_b.label = 1;
|
|
42536
|
+
case 1:
|
|
42537
|
+
_b.trys.push([1, 10, 11, 12]);
|
|
42538
|
+
filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
|
|
42539
|
+
_b.label = 2;
|
|
42540
|
+
case 2:
|
|
42541
|
+
if (!!filePaths_1_1.done) return [3 /*break*/, 9];
|
|
42542
|
+
filePath = filePaths_1_1.value;
|
|
42543
|
+
normalizedPath = filePath.startsWith('/')
|
|
42544
|
+
? filePath.substring(1)
|
|
42545
|
+
: filePath;
|
|
42546
|
+
console.log("[ShadowSpace] \u6279\u91CF\u5904\u7406: ".concat(filePath, " -> ").concat(normalizedPath));
|
|
42547
|
+
_b.label = 3;
|
|
42548
|
+
case 3:
|
|
42549
|
+
_b.trys.push([3, 7, , 8]);
|
|
42550
|
+
if (!readRealtime) return [3 /*break*/, 5];
|
|
42551
|
+
return [4 /*yield*/, this.shadowSpace.readRealTimeFile(normalizedPath)];
|
|
42552
|
+
case 4:
|
|
42553
|
+
realTimeContent = _b.sent();
|
|
42554
|
+
if (realTimeContent !== null) {
|
|
42555
|
+
results.push({
|
|
42556
|
+
path: normalizedPath,
|
|
42557
|
+
action: 'read',
|
|
42558
|
+
version: 1,
|
|
42559
|
+
timestamp: Date.now(),
|
|
42560
|
+
diff: {
|
|
42561
|
+
before: '',
|
|
42562
|
+
after: realTimeContent,
|
|
42563
|
+
},
|
|
42564
|
+
});
|
|
42565
|
+
return [3 /*break*/, 8];
|
|
42176
42566
|
}
|
|
42177
|
-
|
|
42178
|
-
|
|
42179
|
-
|
|
42180
|
-
|
|
42181
|
-
|
|
42182
|
-
|
|
42567
|
+
_b.label = 5;
|
|
42568
|
+
case 5: return [4 /*yield*/, this.shadowSpace.readFile(normalizedPath)];
|
|
42569
|
+
case 6:
|
|
42570
|
+
shadowContent = _b.sent();
|
|
42571
|
+
if (shadowContent !== null) {
|
|
42572
|
+
results.push({
|
|
42573
|
+
path: normalizedPath,
|
|
42574
|
+
action: 'read',
|
|
42575
|
+
version: 1,
|
|
42576
|
+
timestamp: Date.now(),
|
|
42577
|
+
diff: {
|
|
42578
|
+
before: '',
|
|
42579
|
+
after: shadowContent,
|
|
42580
|
+
},
|
|
42581
|
+
});
|
|
42183
42582
|
}
|
|
42583
|
+
else {
|
|
42584
|
+
console.warn("[ShadowSpace] \u6279\u91CF\u83B7\u53D6\u4E2D\u672A\u627E\u5230\u6587\u4EF6: ".concat(normalizedPath));
|
|
42585
|
+
}
|
|
42586
|
+
return [3 /*break*/, 8];
|
|
42587
|
+
case 7:
|
|
42588
|
+
error_2 = _b.sent();
|
|
42589
|
+
console.warn("[ShadowSpace] \u6279\u91CF\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(normalizedPath), error_2);
|
|
42590
|
+
return [3 /*break*/, 8];
|
|
42591
|
+
case 8:
|
|
42592
|
+
filePaths_1_1 = filePaths_1.next();
|
|
42593
|
+
return [3 /*break*/, 2];
|
|
42594
|
+
case 9: return [3 /*break*/, 12];
|
|
42595
|
+
case 10:
|
|
42596
|
+
e_1_1 = _b.sent();
|
|
42597
|
+
e_1 = { error: e_1_1 };
|
|
42598
|
+
return [3 /*break*/, 12];
|
|
42599
|
+
case 11:
|
|
42600
|
+
try {
|
|
42601
|
+
if (filePaths_1_1 && !filePaths_1_1.done && (_a = filePaths_1.return)) _a.call(filePaths_1);
|
|
42602
|
+
}
|
|
42603
|
+
finally { if (e_1) throw e_1.error; }
|
|
42604
|
+
return [7 /*endfinally*/];
|
|
42605
|
+
case 12:
|
|
42184
42606
|
result = {
|
|
42185
42607
|
files: results,
|
|
42186
42608
|
requestedCount: filePaths.length,
|
|
@@ -42253,9 +42675,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42253
42675
|
return __awaiter(this, void 0, void 0, function () {
|
|
42254
42676
|
var info;
|
|
42255
42677
|
return __generator(this, function (_a) {
|
|
42256
|
-
console.log('[ShadowSpace] 获取空间信息...');
|
|
42257
42678
|
info = this.shadowSpace.getSpaceInfo();
|
|
42258
|
-
console.log(
|
|
42679
|
+
// console.log(
|
|
42680
|
+
// `[ShadowSpace] 空间信息: ${info.fileCount} 个文件, ${info.totalSize}`
|
|
42681
|
+
// );
|
|
42259
42682
|
return [2 /*return*/, info];
|
|
42260
42683
|
});
|
|
42261
42684
|
});
|
|
@@ -42265,14 +42688,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42265
42688
|
*/
|
|
42266
42689
|
ShadowSpaceCommandHandler.prototype.syncFromEditor = function (files) {
|
|
42267
42690
|
return __awaiter(this, void 0, void 0, function () {
|
|
42268
|
-
var
|
|
42691
|
+
var result;
|
|
42269
42692
|
return __generator(this, function (_a) {
|
|
42270
42693
|
switch (_a.label) {
|
|
42271
42694
|
case 0:
|
|
42272
42695
|
console.log('[ShadowSpace] syncFromEditor 接收到的参数:', {
|
|
42273
42696
|
filesType: typeof files,
|
|
42274
42697
|
isArray: Array.isArray(files),
|
|
42275
|
-
filesValue: files,
|
|
42698
|
+
// filesValue: files,
|
|
42276
42699
|
filesLength: files === null || files === void 0 ? void 0 : files.length,
|
|
42277
42700
|
});
|
|
42278
42701
|
if (!Array.isArray(files)) {
|
|
@@ -42282,11 +42705,6 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42282
42705
|
return [4 /*yield*/, this.shadowSpace.syncFromEditor(files)];
|
|
42283
42706
|
case 1:
|
|
42284
42707
|
_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
42708
|
result = {
|
|
42291
42709
|
message: 'Sync from editor completed',
|
|
42292
42710
|
fileCount: files.length,
|
|
@@ -42312,9 +42730,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42312
42730
|
}
|
|
42313
42731
|
console.log("[ShadowSpace] \u5220\u9664\u6587\u4EF6: ".concat(filePath));
|
|
42314
42732
|
allFiles = this.shadowSpace.getAllFilePaths();
|
|
42315
|
-
console.log(
|
|
42733
|
+
console.log('[ShadowSpace] 当前影子空间中的文件: ', allFiles);
|
|
42316
42734
|
console.log("[ShadowSpace] \u8981\u5220\u9664\u7684\u6587\u4EF6\u8DEF\u5F84: \"".concat(filePath, "\""));
|
|
42317
|
-
console.log(
|
|
42735
|
+
console.log('[ShadowSpace] 文件是否存在:', this.shadowSpace.hasFile(filePath) ? '是' : '否');
|
|
42318
42736
|
return [4 /*yield*/, this.shadowSpace.deleteFile(filePath)];
|
|
42319
42737
|
case 1:
|
|
42320
42738
|
deleted = _a.sent();
|
|
@@ -42422,10 +42840,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42422
42840
|
var actualMessage = (data === null || data === void 0 ? void 0 : data.message) || data;
|
|
42423
42841
|
var actualMessageId = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.messageId;
|
|
42424
42842
|
var actualAction = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.action;
|
|
42425
|
-
console.log(
|
|
42843
|
+
// console.log(
|
|
42844
|
+
// `[ShadowSpace] 检查响应: action=${actualAction}, messageId=${actualMessageId}, 期望=${messageId}`
|
|
42845
|
+
// );
|
|
42426
42846
|
if (actualMessageId === messageId &&
|
|
42427
42847
|
actualAction === 'editor-state-response') {
|
|
42428
|
-
console.log(
|
|
42848
|
+
// console.log(`[ShadowSpace] 收到编辑器状态响应`);
|
|
42429
42849
|
clearTimeout(timeout);
|
|
42430
42850
|
if ((_a = actualMessage.message) === null || _a === void 0 ? void 0 : _a.success) {
|
|
42431
42851
|
resolve(actualMessage.message.data);
|
|
@@ -42443,7 +42863,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42443
42863
|
originalOnMessage(data);
|
|
42444
42864
|
}
|
|
42445
42865
|
};
|
|
42446
|
-
console.log(
|
|
42866
|
+
// console.log(
|
|
42867
|
+
// `[ShadowSpace] 临时监听器已设置,发送编辑器状态请求: ${messageId}`
|
|
42868
|
+
// );
|
|
42447
42869
|
// 发送请求
|
|
42448
42870
|
_this.socketStore.sendMessage({
|
|
42449
42871
|
action: 'request-editor-state',
|
|
@@ -42454,7 +42876,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42454
42876
|
});
|
|
42455
42877
|
// 恢复原始处理器(在超时时间之后)
|
|
42456
42878
|
setTimeout(function () {
|
|
42457
|
-
console.log(
|
|
42879
|
+
// console.log(`[ShadowSpace] 恢复原始监听器: ${messageId}`);
|
|
42458
42880
|
_this.socketStore.onmsg = originalOnMessage;
|
|
42459
42881
|
}, 31000);
|
|
42460
42882
|
})];
|
|
@@ -42466,23 +42888,20 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42466
42888
|
*/
|
|
42467
42889
|
ShadowSpaceCommandHandler.prototype.detectEditorChanges = function (spaceId, editorSnapshots) {
|
|
42468
42890
|
return __awaiter(this, void 0, void 0, function () {
|
|
42469
|
-
var safeEditorSnapshots, spaceSnapshots,
|
|
42891
|
+
var safeEditorSnapshots, spaceSnapshots, changes, summary, error_3;
|
|
42470
42892
|
return __generator(this, function (_a) {
|
|
42471
42893
|
switch (_a.label) {
|
|
42472
42894
|
case 0:
|
|
42473
42895
|
_a.trys.push([0, 3, , 4]);
|
|
42474
|
-
console.log('editorSnapshots: ', editorSnapshots);
|
|
42475
42896
|
safeEditorSnapshots = Array.isArray(editorSnapshots)
|
|
42476
42897
|
? editorSnapshots
|
|
42477
42898
|
: [];
|
|
42478
|
-
console.log("[ShadowSpace] \u5F00\u59CB\u68C0\u6D4B\u53D8\u66F4: \u7A7A\u95F4=".concat(spaceId, ", \u7F16\u8F91\u5668\u6587\u4EF6=").concat(safeEditorSnapshots.length, "\u4E2A"));
|
|
42479
42899
|
return [4 /*yield*/, this.shadowSpace.getSpaceSnapshots(spaceId)];
|
|
42480
42900
|
case 1:
|
|
42481
42901
|
spaceSnapshots = _a.sent();
|
|
42482
|
-
|
|
42902
|
+
Array.isArray(spaceSnapshots)
|
|
42483
42903
|
? spaceSnapshots.length
|
|
42484
42904
|
: 0;
|
|
42485
|
-
console.log("[ShadowSpace] \u7A7A\u95F4\u5FEB\u7167: ".concat(snapshotCount, "\u4E2A\u6587\u4EF6"));
|
|
42486
42905
|
return [4 /*yield*/, this.compareSnapshots(safeEditorSnapshots, spaceSnapshots)];
|
|
42487
42906
|
case 2:
|
|
42488
42907
|
changes = _a.sent();
|
|
@@ -42491,7 +42910,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42491
42910
|
needPush: changes.filter(function (c) { return c.side === 'editor'; }).length,
|
|
42492
42911
|
needPull: changes.filter(function (c) { return c.side === 'space'; }).length,
|
|
42493
42912
|
};
|
|
42494
|
-
console.log(
|
|
42913
|
+
// console.log(
|
|
42914
|
+
// `[ShadowSpace] 变更检测完成: 总计${summary.total}个变更, 需推送${summary.needPush}个, 需拉取${summary.needPull}个`
|
|
42915
|
+
// );
|
|
42495
42916
|
return [2 /*return*/, {
|
|
42496
42917
|
success: true,
|
|
42497
42918
|
data: {
|
|
@@ -42503,11 +42924,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42503
42924
|
},
|
|
42504
42925
|
}];
|
|
42505
42926
|
case 3:
|
|
42506
|
-
|
|
42507
|
-
console.error("[ShadowSpace] \u68C0\u6D4B\u53D8\u66F4\u5931\u8D25:",
|
|
42927
|
+
error_3 = _a.sent();
|
|
42928
|
+
console.error("[ShadowSpace] \u68C0\u6D4B\u53D8\u66F4\u5931\u8D25:", error_3);
|
|
42508
42929
|
return [2 /*return*/, {
|
|
42509
42930
|
success: false,
|
|
42510
|
-
error:
|
|
42931
|
+
error: error_3 instanceof Error ? error_3.message : '检测变更失败',
|
|
42511
42932
|
}];
|
|
42512
42933
|
case 4: return [2 /*return*/];
|
|
42513
42934
|
}
|
|
@@ -42518,10 +42939,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42518
42939
|
* 比对编辑器和空间快照
|
|
42519
42940
|
*/
|
|
42520
42941
|
ShadowSpaceCommandHandler.prototype.compareSnapshots = function (editorSnapshots, spaceSnapshots) {
|
|
42942
|
+
var _a, _b, _c;
|
|
42521
42943
|
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 (
|
|
42944
|
+
var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _d, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _e, path, spaceFile, editorFile;
|
|
42945
|
+
var e_2, _f, e_3, _g;
|
|
42946
|
+
return __generator(this, function (_h) {
|
|
42525
42947
|
changes = [];
|
|
42526
42948
|
safeEditorSnapshots = Array.isArray(editorSnapshots)
|
|
42527
42949
|
? editorSnapshots
|
|
@@ -42534,7 +42956,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42534
42956
|
try {
|
|
42535
42957
|
// 检测编辑器的变更(新增、修改)
|
|
42536
42958
|
for (editorMap_1 = __values(editorMap), editorMap_1_1 = editorMap_1.next(); !editorMap_1_1.done; editorMap_1_1 = editorMap_1.next()) {
|
|
42537
|
-
|
|
42959
|
+
_d = __read(editorMap_1_1.value, 2), path = _d[0], editorFile = _d[1];
|
|
42538
42960
|
spaceFile = spaceMap.get(path);
|
|
42539
42961
|
if (!spaceFile) {
|
|
42540
42962
|
// 编辑器新增的文件
|
|
@@ -42551,9 +42973,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42551
42973
|
else if (editorFile.hash !== spaceFile.remoteHash) {
|
|
42552
42974
|
// 编辑器修改的文件(基于云端哈希比对)
|
|
42553
42975
|
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,
|
|
42976
|
+
editorHash: (_a = editorFile.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
|
|
42977
|
+
spaceRemoteHash: (_b = spaceFile.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
|
|
42978
|
+
spaceLocalHash: (_c = spaceFile.hash) === null || _c === void 0 ? void 0 : _c.substring(0, 16),
|
|
42979
|
+
editorHashFull: editorFile.hash,
|
|
42980
|
+
spaceRemoteHashFull: spaceFile.remoteHash,
|
|
42557
42981
|
});
|
|
42558
42982
|
changes.push({
|
|
42559
42983
|
action: 'modify',
|
|
@@ -42570,14 +42994,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42570
42994
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
42571
42995
|
finally {
|
|
42572
42996
|
try {
|
|
42573
|
-
if (editorMap_1_1 && !editorMap_1_1.done && (
|
|
42997
|
+
if (editorMap_1_1 && !editorMap_1_1.done && (_f = editorMap_1.return)) _f.call(editorMap_1);
|
|
42574
42998
|
}
|
|
42575
42999
|
finally { if (e_2) throw e_2.error; }
|
|
42576
43000
|
}
|
|
42577
43001
|
try {
|
|
42578
43002
|
// 检测空间的变更(删除、空间独有的修改)
|
|
42579
43003
|
for (spaceMap_1 = __values(spaceMap), spaceMap_1_1 = spaceMap_1.next(); !spaceMap_1_1.done; spaceMap_1_1 = spaceMap_1.next()) {
|
|
42580
|
-
|
|
43004
|
+
_e = __read(spaceMap_1_1.value, 2), path = _e[0], spaceFile = _e[1];
|
|
42581
43005
|
editorFile = editorMap.get(path);
|
|
42582
43006
|
if (!editorFile) {
|
|
42583
43007
|
// 空间独有的文件(编辑器已删除)
|
|
@@ -42597,7 +43021,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42597
43021
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
42598
43022
|
finally {
|
|
42599
43023
|
try {
|
|
42600
|
-
if (spaceMap_1_1 && !spaceMap_1_1.done && (
|
|
43024
|
+
if (spaceMap_1_1 && !spaceMap_1_1.done && (_g = spaceMap_1.return)) _g.call(spaceMap_1);
|
|
42601
43025
|
}
|
|
42602
43026
|
finally { if (e_3) throw e_3.error; }
|
|
42603
43027
|
}
|
|
@@ -42605,12 +43029,132 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42605
43029
|
});
|
|
42606
43030
|
});
|
|
42607
43031
|
};
|
|
43032
|
+
/**
|
|
43033
|
+
* 放弃本地变更
|
|
43034
|
+
* 将影子空间的状态更新为编辑器的版本,不再提示这些文件有变更
|
|
43035
|
+
*/
|
|
43036
|
+
ShadowSpaceCommandHandler.prototype.discardChanges = function (filePaths) {
|
|
43037
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
43038
|
+
var editorState, editorFiles;
|
|
43039
|
+
return __generator(this, function (_a) {
|
|
43040
|
+
switch (_a.label) {
|
|
43041
|
+
case 0:
|
|
43042
|
+
if (!filePaths || filePaths.length === 0) {
|
|
43043
|
+
throw new Error('No file paths provided');
|
|
43044
|
+
}
|
|
43045
|
+
console.log("[ShadowSpace] \u653E\u5F03\u53D8\u66F4: ".concat(filePaths.length, " \u4E2A\u6587\u4EF6"));
|
|
43046
|
+
return [4 /*yield*/, this.requestEditorState()];
|
|
43047
|
+
case 1:
|
|
43048
|
+
editorState = _a.sent();
|
|
43049
|
+
if (!editorState || !editorState.files) {
|
|
43050
|
+
throw new Error('Failed to get editor state');
|
|
43051
|
+
}
|
|
43052
|
+
editorFiles = editorState.files.filter(function (f) {
|
|
43053
|
+
return filePaths.includes(f.path);
|
|
43054
|
+
});
|
|
43055
|
+
console.log("[ShadowSpace] \u4ECE\u7F16\u8F91\u5668\u83B7\u53D6\u5230 ".concat(editorFiles.length, " \u4E2A\u6587\u4EF6"));
|
|
43056
|
+
if (editorFiles.length === 0) {
|
|
43057
|
+
throw new Error('No matching files found in editor');
|
|
43058
|
+
}
|
|
43059
|
+
// 同步到影子空间(覆盖本地变更)
|
|
43060
|
+
return [4 /*yield*/, this.shadowSpace.syncFromEditor(editorFiles)];
|
|
43061
|
+
case 2:
|
|
43062
|
+
// 同步到影子空间(覆盖本地变更)
|
|
43063
|
+
_a.sent();
|
|
43064
|
+
// 标记为远程修改,避免再次检测
|
|
43065
|
+
return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
|
|
43066
|
+
case 3:
|
|
43067
|
+
// 标记为远程修改,避免再次检测
|
|
43068
|
+
_a.sent();
|
|
43069
|
+
console.log("[ShadowSpace] \u6210\u529F\u653E\u5F03 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u7684\u53D8\u66F4"));
|
|
43070
|
+
return [2 /*return*/, {
|
|
43071
|
+
message: 'Changes discarded successfully',
|
|
43072
|
+
fileCount: filePaths.length,
|
|
43073
|
+
discardedFiles: filePaths,
|
|
43074
|
+
timestamp: Date.now(),
|
|
43075
|
+
}];
|
|
43076
|
+
}
|
|
43077
|
+
});
|
|
43078
|
+
});
|
|
43079
|
+
};
|
|
42608
43080
|
/**
|
|
42609
43081
|
* 生成消息ID
|
|
42610
43082
|
*/
|
|
42611
43083
|
ShadowSpaceCommandHandler.prototype.generateMessageId = function () {
|
|
42612
43084
|
return "msg_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
42613
43085
|
};
|
|
43086
|
+
// ==================== 🆕 文件监听功能 ====================
|
|
43087
|
+
/**
|
|
43088
|
+
* 启动文件监听
|
|
43089
|
+
*/
|
|
43090
|
+
ShadowSpaceCommandHandler.prototype.startFileWatching = function () {
|
|
43091
|
+
var _this = this;
|
|
43092
|
+
if (!this.currentUserId) {
|
|
43093
|
+
console.error('[ShadowSpace] 无法启动文件监听:用户ID未设置');
|
|
43094
|
+
return;
|
|
43095
|
+
}
|
|
43096
|
+
var spaceInfo = this.shadowSpace.getSpaceInfo();
|
|
43097
|
+
console.log('[ShadowSpace] 启动文件监听和变更聚合...');
|
|
43098
|
+
// 创建变更聚合器
|
|
43099
|
+
this.changeAggregator = new ChangeAggregator(spaceInfo.spaceId, spaceInfo.userId, function (event) { return _this.handleBatchChange(event); }, 500 // 500ms 防抖
|
|
43100
|
+
);
|
|
43101
|
+
// 添加变更监听器
|
|
43102
|
+
this.shadowSpace.addChangeListener(function (change) {
|
|
43103
|
+
if (_this.changeAggregator) {
|
|
43104
|
+
_this.changeAggregator.addChange(change);
|
|
43105
|
+
}
|
|
43106
|
+
});
|
|
43107
|
+
// 启动文件监听
|
|
43108
|
+
this.shadowSpace.startWatching();
|
|
43109
|
+
console.log('[ShadowSpace] 文件监听和变更聚合已启动');
|
|
43110
|
+
};
|
|
43111
|
+
/**
|
|
43112
|
+
* 停止文件监听
|
|
43113
|
+
*/
|
|
43114
|
+
ShadowSpaceCommandHandler.prototype.stopFileWatching = function () {
|
|
43115
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
43116
|
+
return __generator(this, function (_a) {
|
|
43117
|
+
switch (_a.label) {
|
|
43118
|
+
case 0:
|
|
43119
|
+
console.log('[ShadowSpace] 停止文件监听和变更聚合...');
|
|
43120
|
+
// 停止文件监听
|
|
43121
|
+
return [4 /*yield*/, this.shadowSpace.stopWatching()];
|
|
43122
|
+
case 1:
|
|
43123
|
+
// 停止文件监听
|
|
43124
|
+
_a.sent();
|
|
43125
|
+
// 销毁变更聚合器
|
|
43126
|
+
if (this.changeAggregator) {
|
|
43127
|
+
this.changeAggregator.destroy();
|
|
43128
|
+
this.changeAggregator = null;
|
|
43129
|
+
}
|
|
43130
|
+
console.log('[ShadowSpace] 文件监听和变更聚合已停止');
|
|
43131
|
+
return [2 /*return*/];
|
|
43132
|
+
}
|
|
43133
|
+
});
|
|
43134
|
+
});
|
|
43135
|
+
};
|
|
43136
|
+
/**
|
|
43137
|
+
* 处理批量变更
|
|
43138
|
+
*/
|
|
43139
|
+
ShadowSpaceCommandHandler.prototype.handleBatchChange = function (event) {
|
|
43140
|
+
console.log("[ShadowSpace] \u63A8\u9001\u6279\u91CF\u53D8\u66F4\u4E8B\u4EF6: ".concat(event.changes.length, " \u4E2A\u6587\u4EF6"));
|
|
43141
|
+
// 推送批量变更事件到编辑器
|
|
43142
|
+
this.socketStore.sendMessage({
|
|
43143
|
+
action: 'shadow-space-batch-changed',
|
|
43144
|
+
message: {
|
|
43145
|
+
spaceId: event.spaceId,
|
|
43146
|
+
userId: event.userId,
|
|
43147
|
+
changes: event.changes,
|
|
43148
|
+
timestamp: event.timestamp,
|
|
43149
|
+
},
|
|
43150
|
+
});
|
|
43151
|
+
};
|
|
43152
|
+
/**
|
|
43153
|
+
* 获取监听状态
|
|
43154
|
+
*/
|
|
43155
|
+
ShadowSpaceCommandHandler.prototype.isWatching = function () {
|
|
43156
|
+
return this.shadowSpace.isFileWatching();
|
|
43157
|
+
};
|
|
42614
43158
|
return ShadowSpaceCommandHandler;
|
|
42615
43159
|
}());
|
|
42616
43160
|
|
|
@@ -42750,11 +43294,31 @@ function startConnecting(options) {
|
|
|
42750
43294
|
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
43295
|
shadowSpace_1 = null;
|
|
42752
43296
|
shadowSpaceHandler_1 = null;
|
|
42753
|
-
cleanup_1 = function () {
|
|
42754
|
-
|
|
42755
|
-
|
|
42756
|
-
|
|
42757
|
-
|
|
43297
|
+
cleanup_1 = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
43298
|
+
return __generator(this, function (_a) {
|
|
43299
|
+
switch (_a.label) {
|
|
43300
|
+
case 0:
|
|
43301
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6B63\u5728\u6E05\u7406..."));
|
|
43302
|
+
if (!shadowSpaceHandler_1) return [3 /*break*/, 4];
|
|
43303
|
+
_a.label = 1;
|
|
43304
|
+
case 1:
|
|
43305
|
+
_a.trys.push([1, 3, , 4]);
|
|
43306
|
+
return [4 /*yield*/, shadowSpaceHandler_1.stopFileWatching()];
|
|
43307
|
+
case 2:
|
|
43308
|
+
_a.sent();
|
|
43309
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u505C\u6B62"));
|
|
43310
|
+
return [3 /*break*/, 4];
|
|
43311
|
+
case 3:
|
|
43312
|
+
_a.sent();
|
|
43313
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u505C\u6B62\u6587\u4EF6\u76D1\u542C\u5931\u8D25:"));
|
|
43314
|
+
return [3 /*break*/, 4];
|
|
43315
|
+
case 4:
|
|
43316
|
+
removePidFile();
|
|
43317
|
+
process.exit(0);
|
|
43318
|
+
return [2 /*return*/];
|
|
43319
|
+
}
|
|
43320
|
+
});
|
|
43321
|
+
}); };
|
|
42758
43322
|
process.on('SIGINT', cleanup_1);
|
|
42759
43323
|
process.on('SIGTERM', cleanup_1);
|
|
42760
43324
|
process.on('uncaughtException', function (error) {
|
|
@@ -42786,6 +43350,9 @@ function startConnecting(options) {
|
|
|
42786
43350
|
// 初始化影子空间指令处理器
|
|
42787
43351
|
shadowSpaceHandler_1 = new ShadowSpaceCommandHandler(shadowSpace_1, currentSocket);
|
|
42788
43352
|
shadowSpaceHandler_1.setCurrentUserId(account);
|
|
43353
|
+
// 🆕 启动文件监听
|
|
43354
|
+
shadowSpaceHandler_1.startFileWatching();
|
|
43355
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u542F\u52A8"));
|
|
42789
43356
|
return [3 /*break*/, 3];
|
|
42790
43357
|
case 2:
|
|
42791
43358
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u8DF3\u8FC7\u5F71\u5B50\u7A7A\u95F4\u521D\u59CB\u5316\uFF08\u672A\u542F\u7528workspace\u6A21\u5F0F\uFF09"));
|
|
@@ -42811,13 +43378,11 @@ function startConnecting(options) {
|
|
|
42811
43378
|
}, 5000);
|
|
42812
43379
|
},
|
|
42813
43380
|
onmsg: function (data) { return __awaiter(_this, void 0, void 0, function () {
|
|
42814
|
-
var action, message, extracted, normalizedData, result, _a,
|
|
43381
|
+
var action, message, extracted, normalizedData, result, _a, error_3, error_4, userId, current, cwd, type, change, filePath;
|
|
42815
43382
|
var _b, _c;
|
|
42816
43383
|
return __generator(this, function (_d) {
|
|
42817
43384
|
switch (_d.label) {
|
|
42818
43385
|
case 0:
|
|
42819
|
-
// if (DEV_MODE) {
|
|
42820
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6536\u5230\u6D88\u606F: ").concat(JSON.stringify(data)));
|
|
42821
43386
|
if (data === null || data === void 0 ? void 0 : data.action) {
|
|
42822
43387
|
// 直接格式
|
|
42823
43388
|
action = data.action;
|
|
@@ -42890,8 +43455,8 @@ function startConnecting(options) {
|
|
|
42890
43455
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u5DF2\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ").concat(message.message.path));
|
|
42891
43456
|
return [3 /*break*/, 11];
|
|
42892
43457
|
case 10:
|
|
42893
|
-
|
|
42894
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(
|
|
43458
|
+
error_3 = _d.sent();
|
|
43459
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(error_3));
|
|
42895
43460
|
return [3 /*break*/, 11];
|
|
42896
43461
|
case 11: return [3 /*break*/, 23];
|
|
42897
43462
|
case 12: return [4 /*yield*/, fileHandler_1.readFile(message.path, message.encoding)];
|
|
@@ -42933,13 +43498,13 @@ function startConnecting(options) {
|
|
|
42933
43498
|
});
|
|
42934
43499
|
return [3 /*break*/, 25];
|
|
42935
43500
|
case 24:
|
|
42936
|
-
|
|
42937
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(
|
|
43501
|
+
error_4 = _d.sent();
|
|
43502
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(error_4));
|
|
42938
43503
|
currentSocket === null || currentSocket === void 0 ? void 0 : currentSocket.sendMessage({
|
|
42939
43504
|
action: "".concat(action, "-response"),
|
|
42940
43505
|
message: {
|
|
42941
43506
|
success: false,
|
|
42942
|
-
error:
|
|
43507
|
+
error: error_4 instanceof Error ? error_4.message : String(error_4),
|
|
42943
43508
|
},
|
|
42944
43509
|
});
|
|
42945
43510
|
return [3 /*break*/, 25];
|
|
@@ -47091,186 +47656,411 @@ function executeShadowSpaceDebug(options) {
|
|
|
47091
47656
|
});
|
|
47092
47657
|
}
|
|
47093
47658
|
|
|
47094
|
-
|
|
47095
|
-
|
|
47659
|
+
/**
|
|
47660
|
+
* 统一的TSX/JSX验证器
|
|
47661
|
+
* 同时支持CLI和编辑器使用
|
|
47662
|
+
*/
|
|
47663
|
+
var UnifiedTSXValidator = /** @class */ (function () {
|
|
47664
|
+
function UnifiedTSXValidator(debug) {
|
|
47665
|
+
if (debug === void 0) { debug = false; }
|
|
47666
|
+
this.debug = false;
|
|
47667
|
+
this.debug = debug;
|
|
47096
47668
|
}
|
|
47097
47669
|
/**
|
|
47098
|
-
*
|
|
47670
|
+
* 验证TSX文件内容
|
|
47099
47671
|
*/
|
|
47100
|
-
|
|
47672
|
+
UnifiedTSXValidator.prototype.validate = function (content, filename) {
|
|
47673
|
+
var _this = this;
|
|
47674
|
+
if (filename === void 0) { filename = 'unknown.tsx'; }
|
|
47675
|
+
this.content = content;
|
|
47676
|
+
this.filename = filename;
|
|
47101
47677
|
var issues = [];
|
|
47102
47678
|
try {
|
|
47103
|
-
|
|
47104
|
-
var ast = parser$1.parse(content, {
|
|
47679
|
+
var ast_1 = parser$1.parse(content, {
|
|
47105
47680
|
sourceType: 'module',
|
|
47106
47681
|
plugins: ['jsx', 'typescript', 'decorators-legacy', 'classProperties'],
|
|
47107
47682
|
errorRecovery: true,
|
|
47683
|
+
allowReturnOutsideFunction: true,
|
|
47108
47684
|
});
|
|
47109
|
-
|
|
47110
|
-
|
|
47111
|
-
|
|
47112
|
-
|
|
47113
|
-
|
|
47114
|
-
|
|
47115
|
-
|
|
47116
|
-
|
|
47117
|
-
|
|
47118
|
-
|
|
47119
|
-
|
|
47120
|
-
|
|
47121
|
-
|
|
47122
|
-
|
|
47123
|
-
|
|
47124
|
-
|
|
47125
|
-
|
|
47126
|
-
},
|
|
47127
|
-
});
|
|
47128
|
-
// 检查必需的结构
|
|
47129
|
-
this.checkRequiredStructures(ast, content, issues);
|
|
47685
|
+
this.log('AST解析完成');
|
|
47686
|
+
// 执行所有检查,每个检查都包装在try-catch中
|
|
47687
|
+
this.safeCheck('checkFileStructure', function () { return _this.checkFileStructure(ast_1, issues); });
|
|
47688
|
+
this.safeCheck('checkComponentDefinition', function () { return _this.checkComponentDefinition(ast_1, issues); });
|
|
47689
|
+
this.safeCheck('checkRenderMethod', function () { return _this.checkRenderMethod(ast_1, issues); });
|
|
47690
|
+
this.safeCheck('checkVariableDeclarations', function () { return _this.checkVariableDeclarations(ast_1, issues); });
|
|
47691
|
+
this.safeCheck('checkConditionalRendering', function () { return _this.checkConditionalRendering(ast_1, issues); });
|
|
47692
|
+
this.safeCheck('checkListRendering', function () { return _this.checkListRendering(ast_1, issues); });
|
|
47693
|
+
this.safeCheck('checkStyleUsage', function () { return _this.checkStyleUsage(ast_1, issues); });
|
|
47694
|
+
this.safeCheck('checkStateManagement', function () { return _this.checkStateManagement(ast_1, issues); });
|
|
47695
|
+
this.safeCheck('checkDataSourceUsage', function () { return _this.checkDataSourceUsage(ast_1, issues); });
|
|
47696
|
+
this.safeCheck('checkTypeScriptSyntaxInMethods', function () { return _this.checkTypeScriptSyntaxInMethods(ast_1, issues); });
|
|
47697
|
+
this.log("\u68C0\u67E5\u5B8C\u6210\uFF0C\u53D1\u73B0 ".concat(issues.length, " \u4E2A\u95EE\u9898"));
|
|
47698
|
+
return {
|
|
47699
|
+
isCompliant: issues.filter(function (issue) { return issue.type === 'error'; }).length === 0,
|
|
47700
|
+
issues: issues,
|
|
47701
|
+
};
|
|
47130
47702
|
}
|
|
47131
47703
|
catch (error) {
|
|
47132
|
-
|
|
47133
|
-
|
|
47134
|
-
|
|
47135
|
-
|
|
47136
|
-
|
|
47137
|
-
|
|
47704
|
+
this.log("\u89E3\u6790\u9519\u8BEF: ".concat(error.message));
|
|
47705
|
+
return {
|
|
47706
|
+
isCompliant: false,
|
|
47707
|
+
issues: [{
|
|
47708
|
+
type: 'error',
|
|
47709
|
+
code: 'PARSE_ERROR',
|
|
47710
|
+
message: "\u4EE3\u7801\u89E3\u6790\u5931\u8D25: ".concat(error.message),
|
|
47711
|
+
suggestion: '检查代码语法是否正确',
|
|
47712
|
+
line: 1,
|
|
47713
|
+
column: 0,
|
|
47714
|
+
}],
|
|
47715
|
+
};
|
|
47138
47716
|
}
|
|
47139
|
-
return {
|
|
47140
|
-
isCompliant: issues.filter(function (issue) { return issue.type === 'error'; }).length === 0,
|
|
47141
|
-
issues: issues,
|
|
47142
|
-
};
|
|
47143
47717
|
};
|
|
47144
47718
|
/**
|
|
47145
|
-
*
|
|
47719
|
+
* 检查文件结构
|
|
47146
47720
|
*/
|
|
47147
|
-
|
|
47148
|
-
|
|
47149
|
-
|
|
47150
|
-
var
|
|
47151
|
-
|
|
47152
|
-
|
|
47153
|
-
|
|
47721
|
+
UnifiedTSXValidator.prototype.checkFileStructure = function (ast, issues) {
|
|
47722
|
+
var _this = this;
|
|
47723
|
+
this.log('开始检查文件结构');
|
|
47724
|
+
var hasReactComponent = false;
|
|
47725
|
+
traverse__default["default"](ast, {
|
|
47726
|
+
ClassDeclaration: function (path) {
|
|
47727
|
+
var _a;
|
|
47728
|
+
var className = (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name;
|
|
47729
|
+
_this.log("\u53D1\u73B0\u7C7B: ".concat(className));
|
|
47730
|
+
// 检查是否有继承自React.Component的类(支持 extends Component 和 extends React.Component)
|
|
47731
|
+
if (_this.isReactComponent(path.node.superClass)) {
|
|
47732
|
+
hasReactComponent = true;
|
|
47733
|
+
_this.log("\u53D1\u73B0React\u7EC4\u4EF6\u7C7B: ".concat(className));
|
|
47734
|
+
}
|
|
47735
|
+
},
|
|
47154
47736
|
});
|
|
47155
|
-
|
|
47156
|
-
|
|
47157
|
-
|
|
47158
|
-
var isInEventHandler = this.isInEventHandler(path);
|
|
47159
|
-
if (isInEventHandler)
|
|
47160
|
-
return;
|
|
47161
|
-
// 检查是否在非 JSX 返回的回调函数中
|
|
47162
|
-
var isInNonJSXCallback = this.isInNonJSXCallback(path);
|
|
47163
|
-
if (isInNonJSXCallback)
|
|
47164
|
-
return;
|
|
47165
|
-
// 检查是否在返回 JSX 的回调函数中(如 .map())
|
|
47166
|
-
var isInJSXCallback = this.isInJSXCallback(path);
|
|
47167
|
-
if (isInJSXCallback) {
|
|
47168
|
-
// 这种情况需要报错
|
|
47169
|
-
var _a = this.getLocation(path, content), line_1 = _a.line, column_1 = _a.column;
|
|
47170
|
-
var snippet_1 = this.extractCodeSnippet(content, line_1);
|
|
47171
|
-
issues.push({
|
|
47172
|
-
type: 'error',
|
|
47173
|
-
code: 'CALLBACK_VARIABLE_DECLARATION',
|
|
47174
|
-
message: '返回 JSX 的回调函数中不能包含变量声明',
|
|
47175
|
-
suggestion: '将变量声明移到回调函数外部,或使用内联表达式',
|
|
47176
|
-
line: line_1,
|
|
47177
|
-
column: column_1,
|
|
47178
|
-
codeSnippet: snippet_1.snippet,
|
|
47179
|
-
snippetStartLine: snippet_1.startLine,
|
|
47180
|
-
snippetEndLine: snippet_1.endLine,
|
|
47181
|
-
});
|
|
47182
|
-
return;
|
|
47737
|
+
// 不再强制要求Document类,只要有React组件类即可
|
|
47738
|
+
if (!hasReactComponent) {
|
|
47739
|
+
issues.push(this.createIssue('MISSING_REACT_COMPONENT', 'error', '缺少React组件类定义,必须定义一个继承自React.Component的类', '请定义组件类,如: class MyComponent extends React.Component 或 class MyComponent extends Component', 1));
|
|
47183
47740
|
}
|
|
47184
|
-
|
|
47185
|
-
|
|
47186
|
-
|
|
47187
|
-
|
|
47188
|
-
|
|
47189
|
-
|
|
47190
|
-
|
|
47191
|
-
|
|
47192
|
-
|
|
47193
|
-
|
|
47194
|
-
|
|
47195
|
-
|
|
47196
|
-
|
|
47741
|
+
};
|
|
47742
|
+
/**
|
|
47743
|
+
* 检查组件定义
|
|
47744
|
+
*/
|
|
47745
|
+
UnifiedTSXValidator.prototype.checkComponentDefinition = function (ast, issues) {
|
|
47746
|
+
var _this = this;
|
|
47747
|
+
this.log('开始检查组件定义');
|
|
47748
|
+
traverse__default["default"](ast, {
|
|
47749
|
+
ClassDeclaration: function (path) {
|
|
47750
|
+
var e_1, _a;
|
|
47751
|
+
var _b;
|
|
47752
|
+
// 检查所有继承自React.Component的类
|
|
47753
|
+
if (_this.isReactComponent(path.node.superClass)) {
|
|
47754
|
+
var className = (_b = path.node.id) === null || _b === void 0 ? void 0 : _b.name;
|
|
47755
|
+
_this.log("\u68C0\u67E5React\u7EC4\u4EF6\u7C7B: ".concat(className));
|
|
47756
|
+
// 检查render方法
|
|
47757
|
+
var hasRender = false;
|
|
47758
|
+
try {
|
|
47759
|
+
for (var _c = __values(path.node.body.body), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
47760
|
+
var member = _d.value;
|
|
47761
|
+
if (member.type === 'ClassMethod' && member.key.name === 'render') {
|
|
47762
|
+
hasRender = true;
|
|
47763
|
+
}
|
|
47764
|
+
// 检查constructor
|
|
47765
|
+
if (member.type === 'ClassMethod' && member.key.name === 'constructor') {
|
|
47766
|
+
issues.push(_this.createIssueFromNode('CONSTRUCTOR_NOT_ALLOWED', 'error', "".concat(className, "\u7C7B\u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528constructor"), '请使用state属性直接定义状态,使用componentDidMount进行初始化', member));
|
|
47767
|
+
}
|
|
47768
|
+
}
|
|
47769
|
+
}
|
|
47770
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
47771
|
+
finally {
|
|
47772
|
+
try {
|
|
47773
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
47774
|
+
}
|
|
47775
|
+
finally { if (e_1) throw e_1.error; }
|
|
47776
|
+
}
|
|
47777
|
+
// 移除对state属性的强制检查,React组件可以不定义state
|
|
47778
|
+
if (!hasRender) {
|
|
47779
|
+
issues.push(_this.createIssueFromNode('MISSING_RENDER_METHOD', 'error', "".concat(className, "\u7C7B\u5FC5\u987B\u5B9A\u4E49render\u65B9\u6CD5"), '请添加: render() { return <View>...</View> }', path.node));
|
|
47780
|
+
}
|
|
47781
|
+
}
|
|
47782
|
+
},
|
|
47197
47783
|
});
|
|
47198
47784
|
};
|
|
47199
47785
|
/**
|
|
47200
|
-
*
|
|
47786
|
+
* 检查render方法
|
|
47201
47787
|
*/
|
|
47202
|
-
|
|
47203
|
-
|
|
47788
|
+
UnifiedTSXValidator.prototype.checkRenderMethod = function (ast, issues) {
|
|
47789
|
+
var _this = this;
|
|
47790
|
+
this.log('开始检查render方法');
|
|
47791
|
+
traverse__default["default"](ast, {
|
|
47792
|
+
ClassMethod: function (path) {
|
|
47793
|
+
var e_2, _a, e_3, _b;
|
|
47794
|
+
if (path.node.key.name === 'render') {
|
|
47795
|
+
var body = path.node.body.body;
|
|
47796
|
+
try {
|
|
47797
|
+
// 检查变量声明
|
|
47798
|
+
for (var body_1 = __values(body), body_1_1 = body_1.next(); !body_1_1.done; body_1_1 = body_1.next()) {
|
|
47799
|
+
var statement = body_1_1.value;
|
|
47800
|
+
if (statement.type === 'VariableDeclaration') {
|
|
47801
|
+
// 检查是否在事件处理函数中
|
|
47802
|
+
if (!_this.isInEventHandler(path)) {
|
|
47803
|
+
issues.push(_this.createIssueFromNode('RENDER_VARIABLE_DECLARATION', 'error', 'render方法中不允许声明变量', '直接使用this.state访问状态', statement));
|
|
47804
|
+
}
|
|
47805
|
+
}
|
|
47806
|
+
// 检查函数声明
|
|
47807
|
+
if (statement.type === 'FunctionDeclaration') {
|
|
47808
|
+
issues.push(_this.createIssueFromNode('RENDER_FUNCTION_DECLARATION', 'error', 'render方法中不允许声明函数', '将函数声明移到render方法外部', statement));
|
|
47809
|
+
}
|
|
47810
|
+
// 检查if语句
|
|
47811
|
+
if (statement.type === 'IfStatement') {
|
|
47812
|
+
issues.push(_this.createIssueFromNode('RENDER_IF_STATEMENT', 'error', 'render方法中不允许使用if语句进行条件渲染', '请使用JSX中的条件渲染语法 {condition && <View>}', statement));
|
|
47813
|
+
}
|
|
47814
|
+
}
|
|
47815
|
+
}
|
|
47816
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
47817
|
+
finally {
|
|
47818
|
+
try {
|
|
47819
|
+
if (body_1_1 && !body_1_1.done && (_a = body_1.return)) _a.call(body_1);
|
|
47820
|
+
}
|
|
47821
|
+
finally { if (e_2) throw e_2.error; }
|
|
47822
|
+
}
|
|
47823
|
+
// 检查是否有return语句
|
|
47824
|
+
var hasReturn = false;
|
|
47825
|
+
try {
|
|
47826
|
+
for (var body_2 = __values(body), body_2_1 = body_2.next(); !body_2_1.done; body_2_1 = body_2.next()) {
|
|
47827
|
+
var statement = body_2_1.value;
|
|
47828
|
+
if (statement.type === 'ReturnStatement') {
|
|
47829
|
+
hasReturn = true;
|
|
47830
|
+
break;
|
|
47831
|
+
}
|
|
47832
|
+
}
|
|
47833
|
+
}
|
|
47834
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
47835
|
+
finally {
|
|
47836
|
+
try {
|
|
47837
|
+
if (body_2_1 && !body_2_1.done && (_b = body_2.return)) _b.call(body_2);
|
|
47838
|
+
}
|
|
47839
|
+
finally { if (e_3) throw e_3.error; }
|
|
47840
|
+
}
|
|
47841
|
+
if (!hasReturn) {
|
|
47842
|
+
issues.push(_this.createIssueFromNode('MISSING_RETURN', 'error', 'render方法必须返回JSX元素', '请在render方法末尾添加return语句', path.node));
|
|
47843
|
+
}
|
|
47844
|
+
}
|
|
47845
|
+
},
|
|
47846
|
+
});
|
|
47847
|
+
};
|
|
47848
|
+
/**
|
|
47849
|
+
* 检查变量声明 - 兼容TSXComplianceChecker的逻辑
|
|
47850
|
+
*/
|
|
47851
|
+
UnifiedTSXValidator.prototype.checkVariableDeclarations = function (ast, issues) {
|
|
47852
|
+
var _this = this;
|
|
47853
|
+
this.log('开始检查变量声明');
|
|
47854
|
+
traverse__default["default"](ast, {
|
|
47855
|
+
VariableDeclarator: function (path) {
|
|
47856
|
+
// 检查是否在 render 方法中
|
|
47857
|
+
var renderMethod = path.findParent(function (p) {
|
|
47858
|
+
return p.isClassMethod() &&
|
|
47859
|
+
t__namespace.isIdentifier(p.node.key) &&
|
|
47860
|
+
p.node.key.name === 'render';
|
|
47861
|
+
});
|
|
47862
|
+
if (!renderMethod)
|
|
47863
|
+
return;
|
|
47864
|
+
// 检查是否在事件处理函数中
|
|
47865
|
+
if (_this.isInEventHandler(path))
|
|
47866
|
+
return;
|
|
47867
|
+
// 检查是否在非JSX回调函数中
|
|
47868
|
+
if (_this.isInNonJSXCallback(path))
|
|
47869
|
+
return;
|
|
47870
|
+
// 检查是否在返回JSX的回调函数中
|
|
47871
|
+
if (_this.isInJSXCallback(path)) {
|
|
47872
|
+
issues.push(_this.createIssueFromNode('CALLBACK_VARIABLE_DECLARATION', 'error', '返回JSX的回调函数中不能包含变量声明', '将变量声明移到回调函数外部,或使用内联表达式', path.node));
|
|
47873
|
+
return;
|
|
47874
|
+
}
|
|
47875
|
+
// 其他在render方法中的变量声明都是错误的
|
|
47876
|
+
issues.push(_this.createIssueFromNode('RENDER_VARIABLE_DECLARATION', 'error', 'render()方法中不能包含变量声明', '移除所有const/let/var声明,直接使用this.state.xxx', path.node));
|
|
47877
|
+
},
|
|
47878
|
+
});
|
|
47879
|
+
};
|
|
47880
|
+
/**
|
|
47881
|
+
* 检查条件渲染
|
|
47882
|
+
*/
|
|
47883
|
+
UnifiedTSXValidator.prototype.checkConditionalRendering = function (ast, issues) {
|
|
47884
|
+
var _this = this;
|
|
47885
|
+
this.log('开始检查条件渲染');
|
|
47886
|
+
traverse__default["default"](ast, {
|
|
47887
|
+
JSXExpressionContainer: function (path) {
|
|
47888
|
+
var expression = path.node.expression;
|
|
47889
|
+
if (expression.type === 'LogicalExpression') {
|
|
47890
|
+
// 检查右侧是否包含JSX元素
|
|
47891
|
+
var hasJSXInRight = _this.hasJSXInNode(expression.right);
|
|
47892
|
+
if (hasJSXInRight && expression.operator !== '&&') {
|
|
47893
|
+
issues.push(_this.createIssueFromNode('INVALID_CONDITIONAL_OPERATOR', 'error', '条件渲染必须使用&&运算符,不支持其他运算符', '请使用 && 运算符进行条件渲染', path.node));
|
|
47894
|
+
}
|
|
47895
|
+
if (hasJSXInRight && expression.left.type === 'Identifier') {
|
|
47896
|
+
issues.push(_this.createIssueFromNode('VARIABLE_IN_CONDITIONAL', 'error', '条件渲染中不允许使用变量', '请直接使用this.state访问状态', path.node));
|
|
47897
|
+
}
|
|
47898
|
+
}
|
|
47899
|
+
},
|
|
47900
|
+
});
|
|
47901
|
+
};
|
|
47902
|
+
/**
|
|
47903
|
+
* 检查列表渲染
|
|
47904
|
+
*/
|
|
47905
|
+
UnifiedTSXValidator.prototype.checkListRendering = function (ast, issues) {
|
|
47906
|
+
var _this = this;
|
|
47907
|
+
this.log('开始检查列表渲染');
|
|
47908
|
+
traverse__default["default"](ast, {
|
|
47909
|
+
CallExpression: function (path) {
|
|
47910
|
+
if (path.node.callee.type === 'MemberExpression' &&
|
|
47911
|
+
path.node.callee.property.name === 'map') {
|
|
47912
|
+
// 检查是否在render方法的JSX中使用
|
|
47913
|
+
if (_this.isInRenderJSX(path)) {
|
|
47914
|
+
var parent_1 = path.parentPath;
|
|
47915
|
+
if (parent_1.node.type === 'VariableDeclaration') {
|
|
47916
|
+
issues.push(_this.createIssueFromNode('LIST_RENDER_VARIABLE', 'error', '列表渲染中不允许使用变量', '请直接使用map方法渲染', path.node));
|
|
47917
|
+
}
|
|
47918
|
+
}
|
|
47919
|
+
}
|
|
47920
|
+
},
|
|
47921
|
+
});
|
|
47922
|
+
};
|
|
47923
|
+
/**
|
|
47924
|
+
* 检查样式使用
|
|
47925
|
+
*/
|
|
47926
|
+
UnifiedTSXValidator.prototype.checkStyleUsage = function (ast, issues) {
|
|
47927
|
+
var _this = this;
|
|
47928
|
+
this.log('开始检查样式使用');
|
|
47929
|
+
traverse__default["default"](ast, {
|
|
47930
|
+
JSXAttribute: function (path) {
|
|
47931
|
+
var _a;
|
|
47932
|
+
if (path.node.name.name === 'inlineStyle') {
|
|
47933
|
+
var parent_2 = path.parentPath.node;
|
|
47934
|
+
var componentName = (_a = parent_2.name) === null || _a === void 0 ? void 0 : _a.name;
|
|
47935
|
+
if (componentName !== 'View' && componentName !== 'Text') {
|
|
47936
|
+
issues.push(_this.createIssueFromNode('INVALID_INLINE_STYLE', 'error', 'inlineStyle属性仅支持View和Text组件使用', '请检查组件类型或使用其他样式属性', path.node));
|
|
47937
|
+
}
|
|
47938
|
+
}
|
|
47939
|
+
},
|
|
47940
|
+
});
|
|
47941
|
+
};
|
|
47942
|
+
/**
|
|
47943
|
+
* 检查状态管理
|
|
47944
|
+
*/
|
|
47945
|
+
UnifiedTSXValidator.prototype.checkStateManagement = function (ast, issues) {
|
|
47946
|
+
var _this = this;
|
|
47947
|
+
this.log('开始检查状态管理');
|
|
47948
|
+
traverse__default["default"](ast, {
|
|
47949
|
+
AssignmentExpression: function (path) {
|
|
47950
|
+
if (_this.isDirectStateMutation(path.node.left)) {
|
|
47951
|
+
issues.push(_this.createIssueFromNode('DIRECT_STATE_MUTATION', 'error', '不允许直接修改state', '请使用this.setState方法', path.node));
|
|
47952
|
+
}
|
|
47953
|
+
},
|
|
47954
|
+
});
|
|
47955
|
+
};
|
|
47956
|
+
/**
|
|
47957
|
+
* 检查数据源使用
|
|
47958
|
+
*/
|
|
47959
|
+
UnifiedTSXValidator.prototype.checkDataSourceUsage = function (ast, issues) {
|
|
47960
|
+
var _this = this;
|
|
47961
|
+
this.log('开始检查数据源使用');
|
|
47962
|
+
traverse__default["default"](ast, {
|
|
47963
|
+
CallExpression: function (path) {
|
|
47964
|
+
var _a;
|
|
47965
|
+
if (_this.isDataSourceLoadCall(path.node)) {
|
|
47966
|
+
var isInRender = false;
|
|
47967
|
+
var isInCallback = false;
|
|
47968
|
+
var currentPath = path;
|
|
47969
|
+
while (currentPath) {
|
|
47970
|
+
var node = currentPath.node;
|
|
47971
|
+
if (node.type === 'ClassMethod' && ((_a = node.key) === null || _a === void 0 ? void 0 : _a.name) === 'render') {
|
|
47972
|
+
isInRender = true;
|
|
47973
|
+
}
|
|
47974
|
+
if ((node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression')) {
|
|
47975
|
+
var parentPath = currentPath.parentPath;
|
|
47976
|
+
if ((parentPath === null || parentPath === void 0 ? void 0 : parentPath.node.type) === 'JSXExpressionContainer') {
|
|
47977
|
+
isInCallback = true;
|
|
47978
|
+
break;
|
|
47979
|
+
}
|
|
47980
|
+
}
|
|
47981
|
+
currentPath = currentPath.parentPath;
|
|
47982
|
+
}
|
|
47983
|
+
if (isInRender && !isInCallback) {
|
|
47984
|
+
issues.push(_this.createIssueFromNode('DATA_SOURCE_IN_RENDER', 'error', 'render方法中不允许直接调用数据源', '请在回调函数中调用数据源', path.node));
|
|
47985
|
+
}
|
|
47986
|
+
}
|
|
47987
|
+
},
|
|
47988
|
+
});
|
|
47989
|
+
};
|
|
47990
|
+
// ========== 辅助方法 ==========
|
|
47991
|
+
UnifiedTSXValidator.prototype.isReactComponent = function (superClass) {
|
|
47992
|
+
if (!superClass)
|
|
47993
|
+
return false;
|
|
47994
|
+
// 支持 extends React.Component
|
|
47995
|
+
if (superClass.type === 'MemberExpression' &&
|
|
47996
|
+
superClass.object.name === 'React' &&
|
|
47997
|
+
superClass.property.name === 'Component') {
|
|
47998
|
+
return true;
|
|
47999
|
+
}
|
|
48000
|
+
// 支持 extends Component 和 extends Component<IProps, IState>
|
|
48001
|
+
// 泛型参数不会影响标识符本身的识别
|
|
48002
|
+
if (superClass.type === 'Identifier' &&
|
|
48003
|
+
superClass.name === 'Component') {
|
|
48004
|
+
return true;
|
|
48005
|
+
}
|
|
48006
|
+
// 额外检查:如果父节点是TSExpressionWithTypeArguments,检查其expression
|
|
48007
|
+
// 这种情况出现在 extends Component<IProps, IState> 中
|
|
48008
|
+
if (superClass.type === 'TSExpressionWithTypeArguments' &&
|
|
48009
|
+
superClass.expression &&
|
|
48010
|
+
superClass.expression.type === 'Identifier' &&
|
|
48011
|
+
superClass.expression.name === 'Component') {
|
|
48012
|
+
return true;
|
|
48013
|
+
}
|
|
48014
|
+
return false;
|
|
48015
|
+
};
|
|
48016
|
+
UnifiedTSXValidator.prototype.isReactComponentSuperClass = function (path) {
|
|
48017
|
+
var superClass = path.node.superClass;
|
|
48018
|
+
return this.isReactComponent(superClass);
|
|
48019
|
+
};
|
|
48020
|
+
UnifiedTSXValidator.prototype.hasJSXInNode = function (node) {
|
|
48021
|
+
if (!node)
|
|
48022
|
+
return false;
|
|
48023
|
+
if (node.type === 'JSXElement' || node.type === 'JSXFragment')
|
|
48024
|
+
return true;
|
|
48025
|
+
if (node.type === 'ConditionalExpression') {
|
|
48026
|
+
return this.hasJSXInNode(node.consequent) || this.hasJSXInNode(node.alternate);
|
|
48027
|
+
}
|
|
48028
|
+
return false;
|
|
48029
|
+
};
|
|
48030
|
+
UnifiedTSXValidator.prototype.isInEventHandler = function (path) {
|
|
47204
48031
|
var jsxAttribute = path.findParent(function (p) { return p.isJSXAttribute(); });
|
|
47205
48032
|
if (jsxAttribute && t__namespace.isJSXIdentifier(jsxAttribute.node.name)) {
|
|
47206
48033
|
var attrName = jsxAttribute.node.name.name;
|
|
47207
|
-
// 检查是否是事件处理属性(onXxx)
|
|
47208
48034
|
if (/^on[A-Z]/.test(attrName)) {
|
|
47209
48035
|
return true;
|
|
47210
48036
|
}
|
|
47211
48037
|
}
|
|
47212
|
-
// 检查是否在 addEventListener 回调中
|
|
47213
|
-
var callExpression = path.findParent(function (p) { return p.isCallExpression(); });
|
|
47214
|
-
if (callExpression && t__namespace.isMemberExpression(callExpression.node.callee)) {
|
|
47215
|
-
var memberExpr = callExpression.node.callee;
|
|
47216
|
-
if (t__namespace.isIdentifier(memberExpr.property) &&
|
|
47217
|
-
memberExpr.property.name === 'addEventListener') {
|
|
47218
|
-
return true;
|
|
47219
|
-
}
|
|
47220
|
-
}
|
|
47221
48038
|
return false;
|
|
47222
48039
|
};
|
|
47223
|
-
|
|
47224
|
-
* 检查是否在非 JSX 返回的回调函数中
|
|
47225
|
-
*/
|
|
47226
|
-
TSXComplianceChecker.isInNonJSXCallback = function (path) {
|
|
47227
|
-
// 查找父级函数
|
|
48040
|
+
UnifiedTSXValidator.prototype.isInNonJSXCallback = function (path) {
|
|
47228
48041
|
var parentFunction = path.findParent(function (p) { return p.isArrowFunctionExpression() || p.isFunctionExpression(); });
|
|
47229
48042
|
if (!parentFunction)
|
|
47230
48043
|
return false;
|
|
47231
|
-
|
|
47232
|
-
var jsxAttribute = parentFunction.findParent(function (p) {
|
|
47233
|
-
return p.isJSXAttribute();
|
|
47234
|
-
});
|
|
48044
|
+
var jsxAttribute = parentFunction.findParent(function (p) { return p.isJSXAttribute(); });
|
|
47235
48045
|
if (jsxAttribute && t__namespace.isJSXIdentifier(jsxAttribute.node.name)) {
|
|
47236
48046
|
var attrName = jsxAttribute.node.name.name;
|
|
47237
|
-
// 这些属性通常不返回 JSX
|
|
47238
48047
|
var nonJSXAttributes = [
|
|
47239
|
-
'beforeUpload',
|
|
47240
|
-
'
|
|
47241
|
-
'onChange',
|
|
47242
|
-
'onFinish',
|
|
47243
|
-
'onSubmit',
|
|
47244
|
-
'onSuccess',
|
|
47245
|
-
'onError',
|
|
47246
|
-
'onProgress',
|
|
47247
|
-
'request',
|
|
47248
|
-
'dataHandler',
|
|
48048
|
+
'beforeUpload', 'customRequest', 'onChange', 'onFinish',
|
|
48049
|
+
'onSubmit', 'onSuccess', 'onError', 'onProgress', 'request', 'dataHandler'
|
|
47249
48050
|
];
|
|
47250
48051
|
if (nonJSXAttributes.includes(attrName)) {
|
|
47251
48052
|
return true;
|
|
47252
48053
|
}
|
|
47253
48054
|
}
|
|
47254
|
-
|
|
47255
|
-
var returnsJSX = this.functionReturnsJSX(parentFunction);
|
|
47256
|
-
// 如果不返回 JSX,则认为是非 JSX 回调
|
|
47257
|
-
return !returnsJSX;
|
|
48055
|
+
return !this.functionReturnsJSX(parentFunction);
|
|
47258
48056
|
};
|
|
47259
|
-
|
|
47260
|
-
* 检查是否在返回 JSX 的回调函数中
|
|
47261
|
-
*/
|
|
47262
|
-
TSXComplianceChecker.isInJSXCallback = function (path) {
|
|
47263
|
-
// 查找父级函数
|
|
48057
|
+
UnifiedTSXValidator.prototype.isInJSXCallback = function (path) {
|
|
47264
48058
|
var parentFunction = path.findParent(function (p) { return p.isArrowFunctionExpression() || p.isFunctionExpression(); });
|
|
47265
48059
|
if (!parentFunction)
|
|
47266
48060
|
return false;
|
|
47267
|
-
// 检查函数是否返回 JSX
|
|
47268
48061
|
return this.functionReturnsJSX(parentFunction);
|
|
47269
48062
|
};
|
|
47270
|
-
|
|
47271
|
-
* 检查函数是否返回 JSX
|
|
47272
|
-
*/
|
|
47273
|
-
TSXComplianceChecker.functionReturnsJSX = function (functionPath) {
|
|
48063
|
+
UnifiedTSXValidator.prototype.functionReturnsJSX = function (functionPath) {
|
|
47274
48064
|
var returnsJSX = false;
|
|
47275
48065
|
functionPath.traverse({
|
|
47276
48066
|
ReturnStatement: function (path) {
|
|
@@ -47279,7 +48069,6 @@ var TSXComplianceChecker = /** @class */ (function () {
|
|
|
47279
48069
|
}
|
|
47280
48070
|
},
|
|
47281
48071
|
JSXElement: function (path) {
|
|
47282
|
-
// 如果函数体直接包含 JSX(箭头函数的隐式返回)
|
|
47283
48072
|
if (path.parent === functionPath.node.body) {
|
|
47284
48073
|
returnsJSX = true;
|
|
47285
48074
|
}
|
|
@@ -47287,76 +48076,280 @@ var TSXComplianceChecker = /** @class */ (function () {
|
|
|
47287
48076
|
});
|
|
47288
48077
|
return returnsJSX;
|
|
47289
48078
|
};
|
|
48079
|
+
UnifiedTSXValidator.prototype.isInRenderJSX = function (path) {
|
|
48080
|
+
var isInRender = false;
|
|
48081
|
+
var isInJSX = false;
|
|
48082
|
+
var currentPath = path;
|
|
48083
|
+
while (currentPath) {
|
|
48084
|
+
if (currentPath.node.type === 'ClassMethod' && currentPath.node.key.name === 'render') {
|
|
48085
|
+
isInRender = true;
|
|
48086
|
+
}
|
|
48087
|
+
if (currentPath.node.type === 'JSXExpressionContainer') {
|
|
48088
|
+
isInJSX = true;
|
|
48089
|
+
}
|
|
48090
|
+
currentPath = currentPath.parentPath;
|
|
48091
|
+
}
|
|
48092
|
+
return isInRender && isInJSX;
|
|
48093
|
+
};
|
|
48094
|
+
UnifiedTSXValidator.prototype.isDirectStateMutation = function (left) {
|
|
48095
|
+
return (left.type === 'MemberExpression' &&
|
|
48096
|
+
left.object.type === 'MemberExpression' &&
|
|
48097
|
+
left.object.object.type === 'ThisExpression' &&
|
|
48098
|
+
left.object.property.name === 'state');
|
|
48099
|
+
};
|
|
48100
|
+
UnifiedTSXValidator.prototype.isDataSourceLoadCall = function (node) {
|
|
48101
|
+
return (node.callee.type === 'MemberExpression' &&
|
|
48102
|
+
node.callee.object.type === 'MemberExpression' &&
|
|
48103
|
+
node.callee.object.object.type === 'MemberExpression' &&
|
|
48104
|
+
node.callee.object.object.object.type === 'ThisExpression' &&
|
|
48105
|
+
node.callee.object.object.property.name === 'dataSourceMap' &&
|
|
48106
|
+
node.callee.property.name === 'load');
|
|
48107
|
+
};
|
|
48108
|
+
UnifiedTSXValidator.prototype.createIssueFromNode = function (code, type, message, suggestion, node) {
|
|
48109
|
+
var loc = node.loc;
|
|
48110
|
+
return {
|
|
48111
|
+
type: type,
|
|
48112
|
+
code: code,
|
|
48113
|
+
message: message,
|
|
48114
|
+
suggestion: suggestion,
|
|
48115
|
+
line: loc ? loc.start.line : 1,
|
|
48116
|
+
column: loc ? loc.start.column : 0,
|
|
48117
|
+
};
|
|
48118
|
+
};
|
|
48119
|
+
UnifiedTSXValidator.prototype.createIssue = function (code, type, message, suggestion, line, column) {
|
|
48120
|
+
if (column === void 0) { column = 0; }
|
|
48121
|
+
return {
|
|
48122
|
+
type: type,
|
|
48123
|
+
code: code,
|
|
48124
|
+
message: message,
|
|
48125
|
+
suggestion: suggestion,
|
|
48126
|
+
line: line,
|
|
48127
|
+
column: column,
|
|
48128
|
+
};
|
|
48129
|
+
};
|
|
47290
48130
|
/**
|
|
47291
|
-
*
|
|
48131
|
+
* 检查TypeScript语法在组件方法中
|
|
47292
48132
|
*/
|
|
47293
|
-
|
|
47294
|
-
var
|
|
47295
|
-
|
|
47296
|
-
|
|
47297
|
-
|
|
47298
|
-
|
|
47299
|
-
|
|
47300
|
-
|
|
47301
|
-
|
|
47302
|
-
|
|
47303
|
-
|
|
47304
|
-
|
|
47305
|
-
|
|
48133
|
+
UnifiedTSXValidator.prototype.checkTypeScriptSyntaxInMethods = function (ast, issues) {
|
|
48134
|
+
var _this = this;
|
|
48135
|
+
this.log('开始检查TypeScript语法在组件方法中');
|
|
48136
|
+
// 找到React组件类并检查方法
|
|
48137
|
+
traverse__default["default"](ast, {
|
|
48138
|
+
ClassDeclaration: function (path) {
|
|
48139
|
+
var _a;
|
|
48140
|
+
if (_this.isReactComponent(path.node.superClass)) {
|
|
48141
|
+
var className = (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name;
|
|
48142
|
+
_this.log("\u68C0\u67E5TypeScript\u8BED\u6CD5\u5728\u7EC4\u4EF6\u7C7B: ".concat(className));
|
|
48143
|
+
// 检查类中的所有方法
|
|
48144
|
+
path.node.body.body.forEach(function (member) {
|
|
48145
|
+
var _a;
|
|
48146
|
+
if (member.type === 'ClassMethod') {
|
|
48147
|
+
var methodName_1 = (_a = member.key) === null || _a === void 0 ? void 0 : _a.name;
|
|
48148
|
+
// 跳过render方法的TypeScript语法检查(render方法本身已经单独处理)
|
|
48149
|
+
if (methodName_1 === 'render')
|
|
48150
|
+
return;
|
|
48151
|
+
// 检查方法参数中的TypeScript语法
|
|
48152
|
+
member.params.forEach(function (param, index) {
|
|
48153
|
+
// 检查是否有类型注解
|
|
48154
|
+
if (param.typeAnnotation) {
|
|
48155
|
+
issues.push(_this.createIssueFromNode('TYPESCRIPT_IN_METHOD_PARAMS', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u7684\u7B2C ").concat(index + 1, " \u4E2A\u53C2\u6570\u5305\u542BTypeScript\u7C7B\u578B\u6CE8\u89E3"), "\u8BF7\u79FB\u9664\u53C2\u6570\u7684\u7C7B\u578B\u6CE8\u89E3\uFF0C\u4F7F\u7528\u7EAFJavaScript\u8BED\u6CD5\uFF0C\u5982\u5C06 '".concat(param.name.name || param.name, ": string' \u6539\u4E3A '").concat(param.name.name || param.name, "'"), param));
|
|
48156
|
+
}
|
|
48157
|
+
});
|
|
48158
|
+
// 检查方法返回值的TypeScript语法
|
|
48159
|
+
if (member.returnType) {
|
|
48160
|
+
issues.push(_this.createIssueFromNode('TYPESCRIPT_IN_RETURN_TYPE', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u5305\u542BTypeScript\u8FD4\u56DE\u503C\u7C7B\u578B\u6CE8\u89E3"), "\u8BF7\u79FB\u9664\u8FD4\u56DE\u503C\u7684\u7C7B\u578B\u6CE8\u89E3\uFF0C\u4F7F\u7528\u7EAFJavaScript\u8BED\u6CD5", member));
|
|
48161
|
+
}
|
|
48162
|
+
// 检查方法中是否包含JSX返回
|
|
48163
|
+
if (_this.methodContainsJSX(member)) {
|
|
48164
|
+
issues.push(_this.createIssueFromNode('METHOD_CONTAINS_JSX', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u4E0D\u80FD\u5305\u542B JSX \u8BED\u6CD5"), '只有 render() 方法可以包含 JSX,其他方法只处理逻辑', member));
|
|
48165
|
+
}
|
|
48166
|
+
// 检查方法体中的变量声明的TypeScript语法
|
|
48167
|
+
// 直接遍历AST节点而不使用traverse
|
|
48168
|
+
_this.checkVariableTypeAnnotationsInNode(member, methodName_1, issues);
|
|
48169
|
+
}
|
|
48170
|
+
});
|
|
48171
|
+
}
|
|
48172
|
+
},
|
|
48173
|
+
});
|
|
48174
|
+
};
|
|
48175
|
+
/**
|
|
48176
|
+
* 检查方法中是否包含JSX语法
|
|
48177
|
+
*/
|
|
48178
|
+
UnifiedTSXValidator.prototype.methodContainsJSX = function (methodNode) {
|
|
48179
|
+
var e_4, _a;
|
|
48180
|
+
if (!methodNode || !methodNode.body)
|
|
48181
|
+
return false;
|
|
48182
|
+
var containsJSX = false;
|
|
48183
|
+
var checkJSX = function (node) {
|
|
48184
|
+
if (!node)
|
|
47306
48185
|
return;
|
|
47307
|
-
|
|
47308
|
-
|
|
47309
|
-
|
|
47310
|
-
|
|
47311
|
-
|
|
47312
|
-
|
|
47313
|
-
|
|
47314
|
-
|
|
47315
|
-
|
|
47316
|
-
|
|
47317
|
-
|
|
47318
|
-
|
|
47319
|
-
|
|
47320
|
-
|
|
47321
|
-
|
|
47322
|
-
|
|
47323
|
-
|
|
47324
|
-
|
|
47325
|
-
|
|
47326
|
-
|
|
47327
|
-
|
|
48186
|
+
if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
|
|
48187
|
+
containsJSX = true;
|
|
48188
|
+
return true; // 找到JSX,停止递归
|
|
48189
|
+
}
|
|
48190
|
+
// 递归检查子节点
|
|
48191
|
+
for (var key in node) {
|
|
48192
|
+
if (node[key] && typeof node[key] === 'object') {
|
|
48193
|
+
if (checkJSX(node[key])) {
|
|
48194
|
+
return true;
|
|
48195
|
+
}
|
|
48196
|
+
}
|
|
48197
|
+
}
|
|
48198
|
+
return false;
|
|
48199
|
+
};
|
|
48200
|
+
// 检查方法体中的所有语句
|
|
48201
|
+
if (Array.isArray(methodNode.body.body)) {
|
|
48202
|
+
try {
|
|
48203
|
+
for (var _b = __values(methodNode.body.body), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
48204
|
+
var statement = _c.value;
|
|
48205
|
+
if (checkJSX(statement)) {
|
|
48206
|
+
return true;
|
|
48207
|
+
}
|
|
48208
|
+
}
|
|
47328
48209
|
}
|
|
48210
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
48211
|
+
finally {
|
|
48212
|
+
try {
|
|
48213
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
48214
|
+
}
|
|
48215
|
+
finally { if (e_4) throw e_4.error; }
|
|
48216
|
+
}
|
|
48217
|
+
}
|
|
48218
|
+
else if (methodNode.body) {
|
|
48219
|
+
if (checkJSX(methodNode.body)) {
|
|
48220
|
+
return true;
|
|
48221
|
+
}
|
|
48222
|
+
}
|
|
48223
|
+
return containsJSX;
|
|
48224
|
+
};
|
|
48225
|
+
/**
|
|
48226
|
+
* 递归检查节点中的变量类型注解
|
|
48227
|
+
*/
|
|
48228
|
+
UnifiedTSXValidator.prototype.checkVariableTypeAnnotationsInNode = function (node, methodName, issues) {
|
|
48229
|
+
var _this = this;
|
|
48230
|
+
if (!node)
|
|
48231
|
+
return;
|
|
48232
|
+
// 如果是数组,遍历每个元素
|
|
48233
|
+
if (Array.isArray(node)) {
|
|
48234
|
+
node.forEach(function (item) { return _this.checkVariableTypeAnnotationsInNode(item, methodName, issues); });
|
|
48235
|
+
return;
|
|
48236
|
+
}
|
|
48237
|
+
// 检查变量声明
|
|
48238
|
+
if (node.type === 'VariableDeclaration') {
|
|
48239
|
+
node.declarations.forEach(function (declaration) {
|
|
48240
|
+
if (declaration.id && declaration.id.typeAnnotation) {
|
|
48241
|
+
issues.push(_this.createIssueFromNode('TYPESCRIPT_IN_VARIABLES', 'error', "\u65B9\u6CD5 ".concat(methodName, " \u4E2D\u7684\u53D8\u91CF\u58F0\u660E\u5305\u542BTypeScript\u7C7B\u578B\u6CE8\u89E3"), "\u8BF7\u79FB\u9664\u53D8\u91CF\u7684\u7C7B\u578B\u6CE8\u89E3\uFF0C\u4F7F\u7528\u7EAFJavaScript\u8BED\u6CD5\uFF0C\u5982\u5C06 'let name: string' \u6539\u4E3A 'let name'", declaration));
|
|
48242
|
+
}
|
|
48243
|
+
});
|
|
48244
|
+
}
|
|
48245
|
+
// 递归检查子节点
|
|
48246
|
+
if (node.body && Array.isArray(node.body)) {
|
|
48247
|
+
node.body.forEach(function (child) { return _this.checkVariableTypeAnnotationsInNode(child, methodName, issues); });
|
|
48248
|
+
}
|
|
48249
|
+
else if (node.body) {
|
|
48250
|
+
this.checkVariableTypeAnnotationsInNode(node.body, methodName, issues);
|
|
48251
|
+
}
|
|
48252
|
+
if (node.consequent) {
|
|
48253
|
+
this.checkVariableTypeAnnotationsInNode(node.consequent, methodName, issues);
|
|
48254
|
+
}
|
|
48255
|
+
if (node.alternate) {
|
|
48256
|
+
this.checkVariableTypeAnnotationsInNode(node.alternate, methodName, issues);
|
|
48257
|
+
}
|
|
48258
|
+
if (node.expression) {
|
|
48259
|
+
this.checkVariableTypeAnnotationsInNode(node.expression, methodName, issues);
|
|
47329
48260
|
}
|
|
47330
48261
|
};
|
|
47331
48262
|
/**
|
|
47332
|
-
*
|
|
48263
|
+
* 安全地执行检查方法,避免异常传播
|
|
47333
48264
|
*/
|
|
47334
|
-
|
|
47335
|
-
|
|
48265
|
+
UnifiedTSXValidator.prototype.safeCheck = function (methodName, checkFunction) {
|
|
48266
|
+
try {
|
|
48267
|
+
checkFunction();
|
|
48268
|
+
}
|
|
48269
|
+
catch (error) {
|
|
48270
|
+
this.log("".concat(methodName, " \u68C0\u67E5\u65F6\u53D1\u751F\u9519\u8BEF: ").concat(error.message));
|
|
48271
|
+
// 不抛出异常,只记录日志
|
|
48272
|
+
}
|
|
48273
|
+
};
|
|
48274
|
+
UnifiedTSXValidator.prototype.log = function (message) {
|
|
48275
|
+
if (this.debug) {
|
|
48276
|
+
console.log("[UnifiedTSXValidator] ".concat(message));
|
|
48277
|
+
}
|
|
47336
48278
|
};
|
|
47337
48279
|
/**
|
|
47338
|
-
*
|
|
48280
|
+
* 生成简化的错误信息(兼容编辑器使用)
|
|
47339
48281
|
*/
|
|
47340
|
-
|
|
47341
|
-
|
|
48282
|
+
UnifiedTSXValidator.prototype.generateSimpleErrors = function (result) {
|
|
48283
|
+
return result.issues
|
|
48284
|
+
.filter(function (issue) { return issue.type === 'error'; })
|
|
48285
|
+
.map(function (issue) {
|
|
48286
|
+
var location = issue.line ? " (\u7B2C".concat(issue.line, "\u884C)") : '';
|
|
48287
|
+
return "[".concat(issue.code, "] ").concat(issue.message).concat(location);
|
|
48288
|
+
});
|
|
47342
48289
|
};
|
|
47343
48290
|
/**
|
|
47344
|
-
*
|
|
48291
|
+
* 生成详细报告(兼容CLI使用)
|
|
47345
48292
|
*/
|
|
47346
|
-
|
|
47347
|
-
|
|
47348
|
-
|
|
48293
|
+
UnifiedTSXValidator.prototype.generateReport = function (result) {
|
|
48294
|
+
var isCompliant = result.isCompliant, issues = result.issues;
|
|
48295
|
+
var report = '=== TSX 规范检查报告 ===\n';
|
|
48296
|
+
report += "\u6587\u4EF6: ".concat(this.filename, "\n");
|
|
48297
|
+
if (isCompliant) {
|
|
48298
|
+
report += '✅ 检查通过:文件符合 TSX 规范\n';
|
|
48299
|
+
}
|
|
48300
|
+
else {
|
|
48301
|
+
var errorCount = issues.filter(function (issue) { return issue.type === 'error'; }).length;
|
|
48302
|
+
report += "\u274C \u68C0\u67E5\u5931\u8D25\uFF1A\u53D1\u73B0 ".concat(errorCount, " \u4E2A\u9519\u8BEF\n\n");
|
|
48303
|
+
report += '--- 问题详情 ---\n';
|
|
48304
|
+
issues.forEach(function (issue, index) {
|
|
48305
|
+
var icon = issue.type === 'error' ? '❌' : '⚠️';
|
|
48306
|
+
report += "".concat(index + 1, ". ").concat(icon, " [").concat(issue.code, "] ").concat(issue.message, "\n");
|
|
48307
|
+
if (issue.line) {
|
|
48308
|
+
report += " \uD83D\uDCCD \u4F4D\u7F6E: \u7B2C ".concat(issue.line, " \u884C\n");
|
|
48309
|
+
}
|
|
48310
|
+
report += " \uD83D\uDCA1 \u5EFA\u8BAE: ".concat(issue.suggestion, "\n\n");
|
|
48311
|
+
});
|
|
48312
|
+
}
|
|
48313
|
+
return report;
|
|
47349
48314
|
};
|
|
48315
|
+
return UnifiedTSXValidator;
|
|
48316
|
+
}());
|
|
48317
|
+
|
|
48318
|
+
var TSXComplianceChecker = /** @class */ (function () {
|
|
48319
|
+
function TSXComplianceChecker() {
|
|
48320
|
+
}
|
|
47350
48321
|
/**
|
|
47351
|
-
*
|
|
48322
|
+
* 使用统一验证器检查 TSX 规范
|
|
47352
48323
|
*/
|
|
47353
|
-
TSXComplianceChecker.
|
|
47354
|
-
var
|
|
47355
|
-
|
|
47356
|
-
|
|
47357
|
-
|
|
47358
|
-
|
|
48324
|
+
TSXComplianceChecker.checkTSXCompliance = function (content, filename) {
|
|
48325
|
+
var _this = this;
|
|
48326
|
+
try {
|
|
48327
|
+
var result = this.validator.validate(content, filename);
|
|
48328
|
+
// 转换为兼容的格式
|
|
48329
|
+
var compliantIssues = result.issues.map(function (issue) { return (__assign(__assign({}, issue), {
|
|
48330
|
+
// 为CLI添加代码片段
|
|
48331
|
+
codeSnippet: issue.line ? _this.extractCodeSnippet(content, issue.line).snippet : undefined, snippetStartLine: issue.line ? _this.extractCodeSnippet(content, issue.line).startLine : undefined, snippetEndLine: issue.line ? _this.extractCodeSnippet(content, issue.line).endLine : undefined })); });
|
|
48332
|
+
return {
|
|
48333
|
+
isCompliant: result.isCompliant,
|
|
48334
|
+
issues: compliantIssues,
|
|
48335
|
+
};
|
|
48336
|
+
}
|
|
48337
|
+
catch (error) {
|
|
48338
|
+
// 捕获任何异常并返回合规结果,而不是让异常向上传播
|
|
48339
|
+
return {
|
|
48340
|
+
isCompliant: false,
|
|
48341
|
+
issues: [{
|
|
48342
|
+
type: 'error',
|
|
48343
|
+
code: 'VALIDATION_ERROR',
|
|
48344
|
+
message: "\u9A8C\u8BC1\u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF: ".concat(error.message),
|
|
48345
|
+
suggestion: '请检查代码语法或联系开发团队',
|
|
48346
|
+
line: 1,
|
|
48347
|
+
column: 0,
|
|
48348
|
+
}],
|
|
48349
|
+
};
|
|
48350
|
+
}
|
|
47359
48351
|
};
|
|
48352
|
+
// 移除了所有旧的检查方法,现在使用UnifiedTSXValidator
|
|
47360
48353
|
/**
|
|
47361
48354
|
* 提取代码片段
|
|
47362
48355
|
*/
|
|
@@ -47378,34 +48371,33 @@ var TSXComplianceChecker = /** @class */ (function () {
|
|
|
47378
48371
|
};
|
|
47379
48372
|
};
|
|
47380
48373
|
/**
|
|
47381
|
-
*
|
|
48374
|
+
* 生成检查报告(使用统一验证器)
|
|
47382
48375
|
*/
|
|
47383
48376
|
TSXComplianceChecker.generateReport = function (result, filename) {
|
|
47384
|
-
|
|
47385
|
-
|
|
47386
|
-
|
|
47387
|
-
|
|
47388
|
-
|
|
47389
|
-
|
|
47390
|
-
|
|
47391
|
-
|
|
47392
|
-
|
|
47393
|
-
|
|
47394
|
-
|
|
47395
|
-
|
|
47396
|
-
|
|
47397
|
-
|
|
47398
|
-
|
|
47399
|
-
|
|
47400
|
-
report += " \uD83D\uDCA1 \u5EFA\u8BAE: ".concat(issue.suggestion, "\n");
|
|
47401
|
-
if (issue.codeSnippet) {
|
|
47402
|
-
report += " \uD83D\uDCDD \u4EE3\u7801\u7247\u6BB5:\n".concat(issue.codeSnippet, "\n");
|
|
47403
|
-
}
|
|
47404
|
-
report += '\n';
|
|
47405
|
-
});
|
|
48377
|
+
this.validator = new UnifiedTSXValidator(false);
|
|
48378
|
+
return this.validator.generateReport(result);
|
|
48379
|
+
};
|
|
48380
|
+
/**
|
|
48381
|
+
* 提取代码片段(保留原有逻辑)
|
|
48382
|
+
*/
|
|
48383
|
+
TSXComplianceChecker.extractCodeSnippet = function (content, lineNumber, contextLines) {
|
|
48384
|
+
if (contextLines === void 0) { contextLines = 3; }
|
|
48385
|
+
var lines = content.split('\n');
|
|
48386
|
+
var startLine = Math.max(1, lineNumber - contextLines);
|
|
48387
|
+
var endLine = Math.min(lines.length, lineNumber + contextLines);
|
|
48388
|
+
var snippetLines = [];
|
|
48389
|
+
for (var i = startLine; i <= endLine; i++) {
|
|
48390
|
+
var line = lines[i - 1] || '';
|
|
48391
|
+
var prefix = i === lineNumber ? '>>> ' : ' ';
|
|
48392
|
+
snippetLines.push("".concat(prefix).concat(i.toString().padStart(3), ": ").concat(line));
|
|
47406
48393
|
}
|
|
47407
|
-
return
|
|
48394
|
+
return {
|
|
48395
|
+
snippet: snippetLines.join('\n'),
|
|
48396
|
+
startLine: startLine,
|
|
48397
|
+
endLine: endLine,
|
|
48398
|
+
};
|
|
47408
48399
|
};
|
|
48400
|
+
TSXComplianceChecker.validator = new UnifiedTSXValidator(false);
|
|
47409
48401
|
return TSXComplianceChecker;
|
|
47410
48402
|
}());
|
|
47411
48403
|
|
|
@@ -48298,6 +49290,1155 @@ function cleanupOldLogs(logDir, debugDir) {
|
|
|
48298
49290
|
});
|
|
48299
49291
|
}
|
|
48300
49292
|
|
|
49293
|
+
/**
|
|
49294
|
+
* AI 工具配置
|
|
49295
|
+
*/
|
|
49296
|
+
var AI_TOOLS = [
|
|
49297
|
+
{
|
|
49298
|
+
name: '🤖 Claude Code (Anthropic 官方)',
|
|
49299
|
+
value: 'claude-code',
|
|
49300
|
+
description: '支持 Hooks 和 TSX 检查器',
|
|
49301
|
+
},
|
|
49302
|
+
{
|
|
49303
|
+
name: '🎯 Cursor (AI-first IDE)',
|
|
49304
|
+
value: 'cursor',
|
|
49305
|
+
description: '支持 Rules 和自定义指令',
|
|
49306
|
+
},
|
|
49307
|
+
{
|
|
49308
|
+
name: '🌊 Windsurf (Codeium)',
|
|
49309
|
+
value: 'windsurf',
|
|
49310
|
+
description: '支持 Cascade 配置',
|
|
49311
|
+
},
|
|
49312
|
+
{
|
|
49313
|
+
name: '☁️ 阿里云 Coder',
|
|
49314
|
+
value: 'coder',
|
|
49315
|
+
description: '支持模板配置',
|
|
49316
|
+
},
|
|
49317
|
+
{
|
|
49318
|
+
name: '🔧 Augment (VSCode 插件)',
|
|
49319
|
+
value: 'augment',
|
|
49320
|
+
description: '支持上下文配置',
|
|
49321
|
+
},
|
|
49322
|
+
{
|
|
49323
|
+
name: '⏭️ 其他 / 跳过',
|
|
49324
|
+
value: 'other',
|
|
49325
|
+
description: '只生成基础配置',
|
|
49326
|
+
},
|
|
49327
|
+
];
|
|
49328
|
+
|
|
49329
|
+
/**
|
|
49330
|
+
* 基础生成器 - 生成通用的 Space 配置文件
|
|
49331
|
+
*/
|
|
49332
|
+
var BaseGenerator = /** @class */ (function () {
|
|
49333
|
+
function BaseGenerator(cwd, config, verbose) {
|
|
49334
|
+
this.cwd = cwd;
|
|
49335
|
+
this.config = config;
|
|
49336
|
+
this.verbose = verbose;
|
|
49337
|
+
}
|
|
49338
|
+
/**
|
|
49339
|
+
* 生成基础配置文件
|
|
49340
|
+
*/
|
|
49341
|
+
BaseGenerator.prototype.generate = function (skipPrompts) {
|
|
49342
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49343
|
+
var files, appthenDir, configFile, gitignoreFile, promptFiles, error_1;
|
|
49344
|
+
return __generator(this, function (_a) {
|
|
49345
|
+
switch (_a.label) {
|
|
49346
|
+
case 0:
|
|
49347
|
+
files = [];
|
|
49348
|
+
_a.label = 1;
|
|
49349
|
+
case 1:
|
|
49350
|
+
_a.trys.push([1, 6, , 7]);
|
|
49351
|
+
appthenDir = path__namespace.join(this.cwd, '.appthen');
|
|
49352
|
+
this.ensureDirectory(appthenDir);
|
|
49353
|
+
return [4 /*yield*/, this.createSpaceConfig(appthenDir)];
|
|
49354
|
+
case 2:
|
|
49355
|
+
configFile = _a.sent();
|
|
49356
|
+
files.push(configFile);
|
|
49357
|
+
return [4 /*yield*/, this.createGitignore(appthenDir)];
|
|
49358
|
+
case 3:
|
|
49359
|
+
gitignoreFile = _a.sent();
|
|
49360
|
+
files.push(gitignoreFile);
|
|
49361
|
+
if (!!skipPrompts) return [3 /*break*/, 5];
|
|
49362
|
+
return [4 /*yield*/, this.createPrompts(appthenDir)];
|
|
49363
|
+
case 4:
|
|
49364
|
+
promptFiles = _a.sent();
|
|
49365
|
+
files.push.apply(files, __spreadArray([], __read(promptFiles), false));
|
|
49366
|
+
_a.label = 5;
|
|
49367
|
+
case 5: return [2 /*return*/, {
|
|
49368
|
+
success: true,
|
|
49369
|
+
files: files,
|
|
49370
|
+
message: 'Base configuration created successfully',
|
|
49371
|
+
}];
|
|
49372
|
+
case 6:
|
|
49373
|
+
error_1 = _a.sent();
|
|
49374
|
+
return [2 /*return*/, {
|
|
49375
|
+
success: false,
|
|
49376
|
+
files: [],
|
|
49377
|
+
error: error_1.message,
|
|
49378
|
+
}];
|
|
49379
|
+
case 7: return [2 /*return*/];
|
|
49380
|
+
}
|
|
49381
|
+
});
|
|
49382
|
+
});
|
|
49383
|
+
};
|
|
49384
|
+
/**
|
|
49385
|
+
* 确保目录存在
|
|
49386
|
+
*/
|
|
49387
|
+
BaseGenerator.prototype.ensureDirectory = function (dir) {
|
|
49388
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
49389
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
49390
|
+
if (this.verbose) {
|
|
49391
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(dir));
|
|
49392
|
+
}
|
|
49393
|
+
}
|
|
49394
|
+
};
|
|
49395
|
+
/**
|
|
49396
|
+
* 创建 space-config.json
|
|
49397
|
+
*/
|
|
49398
|
+
BaseGenerator.prototype.createSpaceConfig = function (appthenDir) {
|
|
49399
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49400
|
+
var configPath, configContent;
|
|
49401
|
+
return __generator(this, function (_a) {
|
|
49402
|
+
configPath = path__namespace.join(appthenDir, 'space-config.json');
|
|
49403
|
+
configContent = __assign(__assign({}, this.config), {
|
|
49404
|
+
// 添加一些额外的配置
|
|
49405
|
+
settings: {
|
|
49406
|
+
autoSync: true,
|
|
49407
|
+
watchPatterns: ['src/**/*', 'docs/**/*'],
|
|
49408
|
+
ignorePatterns: [
|
|
49409
|
+
'node_modules/**',
|
|
49410
|
+
'dist/**',
|
|
49411
|
+
'build/**',
|
|
49412
|
+
'.git/**',
|
|
49413
|
+
'*.log',
|
|
49414
|
+
],
|
|
49415
|
+
} });
|
|
49416
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(configContent, null, 2));
|
|
49417
|
+
if (this.verbose) {
|
|
49418
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49419
|
+
}
|
|
49420
|
+
return [2 /*return*/, configPath];
|
|
49421
|
+
});
|
|
49422
|
+
});
|
|
49423
|
+
};
|
|
49424
|
+
/**
|
|
49425
|
+
* 创建 .gitignore
|
|
49426
|
+
*/
|
|
49427
|
+
BaseGenerator.prototype.createGitignore = function (appthenDir) {
|
|
49428
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49429
|
+
var gitignorePath, gitignoreContent;
|
|
49430
|
+
return __generator(this, function (_a) {
|
|
49431
|
+
gitignorePath = path__namespace.join(appthenDir, '.gitignore');
|
|
49432
|
+
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";
|
|
49433
|
+
fs__namespace.writeFileSync(gitignorePath, gitignoreContent);
|
|
49434
|
+
if (this.verbose) {
|
|
49435
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA .gitignore: ".concat(gitignorePath));
|
|
49436
|
+
}
|
|
49437
|
+
return [2 /*return*/, gitignorePath];
|
|
49438
|
+
});
|
|
49439
|
+
});
|
|
49440
|
+
};
|
|
49441
|
+
/**
|
|
49442
|
+
* 创建提示词目录和文件
|
|
49443
|
+
*/
|
|
49444
|
+
BaseGenerator.prototype.createPrompts = function (appthenDir) {
|
|
49445
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49446
|
+
var files, promptsDir, readmeFile, templateFiles;
|
|
49447
|
+
return __generator(this, function (_a) {
|
|
49448
|
+
switch (_a.label) {
|
|
49449
|
+
case 0:
|
|
49450
|
+
files = [];
|
|
49451
|
+
promptsDir = path__namespace.join(appthenDir, 'prompts');
|
|
49452
|
+
this.ensureDirectory(promptsDir);
|
|
49453
|
+
return [4 /*yield*/, this.createPromptsReadme(promptsDir)];
|
|
49454
|
+
case 1:
|
|
49455
|
+
readmeFile = _a.sent();
|
|
49456
|
+
files.push(readmeFile);
|
|
49457
|
+
return [4 /*yield*/, this.copyTemplateFiles(promptsDir)];
|
|
49458
|
+
case 2:
|
|
49459
|
+
templateFiles = _a.sent();
|
|
49460
|
+
files.push.apply(files, __spreadArray([], __read(templateFiles), false));
|
|
49461
|
+
return [2 /*return*/, files];
|
|
49462
|
+
}
|
|
49463
|
+
});
|
|
49464
|
+
});
|
|
49465
|
+
};
|
|
49466
|
+
/**
|
|
49467
|
+
* 创建提示词 README
|
|
49468
|
+
*/
|
|
49469
|
+
BaseGenerator.prototype.createPromptsReadme = function (promptsDir) {
|
|
49470
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49471
|
+
var readmePath, readmeContent;
|
|
49472
|
+
return __generator(this, function (_a) {
|
|
49473
|
+
readmePath = path__namespace.join(promptsDir, 'README.md');
|
|
49474
|
+
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";
|
|
49475
|
+
fs__namespace.writeFileSync(readmePath, readmeContent);
|
|
49476
|
+
if (this.verbose) {
|
|
49477
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u63D0\u793A\u8BCD README: ".concat(readmePath));
|
|
49478
|
+
}
|
|
49479
|
+
return [2 /*return*/, readmePath];
|
|
49480
|
+
});
|
|
49481
|
+
});
|
|
49482
|
+
};
|
|
49483
|
+
/**
|
|
49484
|
+
* 复制模板文件到提示词目录
|
|
49485
|
+
*/
|
|
49486
|
+
BaseGenerator.prototype.copyTemplateFiles = function (promptsDir) {
|
|
49487
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49488
|
+
var files, projectGuidePath, projectGuideContent, tsxGenerationPath, tsxGenerationContent, decisionTreePath, decisionTreeContent, validationPath, validationContent, codeReviewPath, codeReviewContent, refactoringPath, refactoringContent;
|
|
49489
|
+
return __generator(this, function (_a) {
|
|
49490
|
+
files = [];
|
|
49491
|
+
projectGuidePath = path__namespace.join(promptsDir, 'project-guide.md');
|
|
49492
|
+
projectGuideContent = this.getProjectGuideTemplate();
|
|
49493
|
+
fs__namespace.writeFileSync(projectGuidePath, projectGuideContent);
|
|
49494
|
+
files.push(projectGuidePath);
|
|
49495
|
+
if (this.verbose) {
|
|
49496
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: project-guide.md");
|
|
49497
|
+
}
|
|
49498
|
+
tsxGenerationPath = path__namespace.join(promptsDir, 'tsx-generation.md');
|
|
49499
|
+
tsxGenerationContent = this.getTsxGenerationTemplate();
|
|
49500
|
+
fs__namespace.writeFileSync(tsxGenerationPath, tsxGenerationContent);
|
|
49501
|
+
files.push(tsxGenerationPath);
|
|
49502
|
+
if (this.verbose) {
|
|
49503
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: tsx-generation.md");
|
|
49504
|
+
}
|
|
49505
|
+
decisionTreePath = path__namespace.join(promptsDir, 'decision-tree.md');
|
|
49506
|
+
decisionTreeContent = this.getDecisionTreeTemplate();
|
|
49507
|
+
fs__namespace.writeFileSync(decisionTreePath, decisionTreeContent);
|
|
49508
|
+
files.push(decisionTreePath);
|
|
49509
|
+
if (this.verbose) {
|
|
49510
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: decision-tree.md");
|
|
49511
|
+
}
|
|
49512
|
+
validationPath = path__namespace.join(promptsDir, 'validation-checklist.md');
|
|
49513
|
+
validationContent = this.getValidationChecklistTemplate();
|
|
49514
|
+
fs__namespace.writeFileSync(validationPath, validationContent);
|
|
49515
|
+
files.push(validationPath);
|
|
49516
|
+
if (this.verbose) {
|
|
49517
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: validation-checklist.md");
|
|
49518
|
+
}
|
|
49519
|
+
codeReviewPath = path__namespace.join(promptsDir, 'code-review.md');
|
|
49520
|
+
codeReviewContent = this.getCodeReviewTemplate();
|
|
49521
|
+
fs__namespace.writeFileSync(codeReviewPath, codeReviewContent);
|
|
49522
|
+
files.push(codeReviewPath);
|
|
49523
|
+
if (this.verbose) {
|
|
49524
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: code-review.md");
|
|
49525
|
+
}
|
|
49526
|
+
refactoringPath = path__namespace.join(promptsDir, 'refactoring.md');
|
|
49527
|
+
refactoringContent = this.getRefactoringTemplate();
|
|
49528
|
+
fs__namespace.writeFileSync(refactoringPath, refactoringContent);
|
|
49529
|
+
files.push(refactoringPath);
|
|
49530
|
+
if (this.verbose) {
|
|
49531
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: refactoring.md");
|
|
49532
|
+
}
|
|
49533
|
+
return [2 /*return*/, files];
|
|
49534
|
+
});
|
|
49535
|
+
});
|
|
49536
|
+
};
|
|
49537
|
+
/**
|
|
49538
|
+
* 获取项目开发总指南模板内容
|
|
49539
|
+
*/
|
|
49540
|
+
BaseGenerator.prototype.getProjectGuideTemplate = function () {
|
|
49541
|
+
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";
|
|
49542
|
+
};
|
|
49543
|
+
/**
|
|
49544
|
+
* 获取 TSX 生成模板内容
|
|
49545
|
+
*/
|
|
49546
|
+
BaseGenerator.prototype.getTsxGenerationTemplate = function () {
|
|
49547
|
+
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";
|
|
49548
|
+
};
|
|
49549
|
+
/**
|
|
49550
|
+
* 获取决策树模板内容
|
|
49551
|
+
*/
|
|
49552
|
+
BaseGenerator.prototype.getDecisionTreeTemplate = function () {
|
|
49553
|
+
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";
|
|
49554
|
+
};
|
|
49555
|
+
/**
|
|
49556
|
+
* 获取验证清单模板内容
|
|
49557
|
+
*/
|
|
49558
|
+
BaseGenerator.prototype.getValidationChecklistTemplate = function () {
|
|
49559
|
+
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";
|
|
49560
|
+
};
|
|
49561
|
+
/**
|
|
49562
|
+
* 获取代码审查模板内容
|
|
49563
|
+
*/
|
|
49564
|
+
BaseGenerator.prototype.getCodeReviewTemplate = function () {
|
|
49565
|
+
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";
|
|
49566
|
+
};
|
|
49567
|
+
/**
|
|
49568
|
+
* 获取重构模板内容
|
|
49569
|
+
*/
|
|
49570
|
+
BaseGenerator.prototype.getRefactoringTemplate = function () {
|
|
49571
|
+
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";
|
|
49572
|
+
};
|
|
49573
|
+
return BaseGenerator;
|
|
49574
|
+
}());
|
|
49575
|
+
|
|
49576
|
+
/**
|
|
49577
|
+
* Claude Code 生成器
|
|
49578
|
+
* 生成 Claude Code 特定的配置文件和 Hooks
|
|
49579
|
+
*/
|
|
49580
|
+
var ClaudeCodeGenerator = /** @class */ (function () {
|
|
49581
|
+
function ClaudeCodeGenerator(cwd, config, verbose) {
|
|
49582
|
+
this.cwd = cwd;
|
|
49583
|
+
this.config = config;
|
|
49584
|
+
this.verbose = verbose;
|
|
49585
|
+
}
|
|
49586
|
+
/**
|
|
49587
|
+
* 生成 Claude Code 配置
|
|
49588
|
+
*/
|
|
49589
|
+
ClaudeCodeGenerator.prototype.generate = function (skipHooks) {
|
|
49590
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49591
|
+
var files, claudeMdPath, commandFiles, result, error_1;
|
|
49592
|
+
return __generator(this, function (_a) {
|
|
49593
|
+
switch (_a.label) {
|
|
49594
|
+
case 0:
|
|
49595
|
+
files = [];
|
|
49596
|
+
_a.label = 1;
|
|
49597
|
+
case 1:
|
|
49598
|
+
_a.trys.push([1, 7, , 8]);
|
|
49599
|
+
if (this.verbose) {
|
|
49600
|
+
console.log('🤖 配置 Claude Code 集成...');
|
|
49601
|
+
}
|
|
49602
|
+
return [4 /*yield*/, this.createClaudeMd()];
|
|
49603
|
+
case 2:
|
|
49604
|
+
claudeMdPath = _a.sent();
|
|
49605
|
+
files.push(claudeMdPath);
|
|
49606
|
+
return [4 /*yield*/, this.createCustomCommands()];
|
|
49607
|
+
case 3:
|
|
49608
|
+
commandFiles = _a.sent();
|
|
49609
|
+
files.push.apply(files, __spreadArray([], __read(commandFiles), false));
|
|
49610
|
+
if (!!skipHooks) return [3 /*break*/, 5];
|
|
49611
|
+
return [4 /*yield*/, initClaudeHooks({
|
|
49612
|
+
cwd: this.cwd,
|
|
49613
|
+
verbose: this.verbose,
|
|
49614
|
+
projectOnly: true,
|
|
49615
|
+
force: false,
|
|
49616
|
+
})];
|
|
49617
|
+
case 4:
|
|
49618
|
+
result = _a.sent();
|
|
49619
|
+
if (!result.success) {
|
|
49620
|
+
return [2 /*return*/, {
|
|
49621
|
+
success: false,
|
|
49622
|
+
files: [],
|
|
49623
|
+
error: "Claude Hooks \u521D\u59CB\u5316\u5931\u8D25: ".concat(result.error),
|
|
49624
|
+
}];
|
|
49625
|
+
}
|
|
49626
|
+
// 添加生成的文件到列表
|
|
49627
|
+
files.push(path__namespace.join(this.cwd, '.claude/settings.json'), path__namespace.join(this.cwd, '.claude/hooks/tsx-compliance-checker.sh'));
|
|
49628
|
+
if (this.verbose) {
|
|
49629
|
+
console.log('✅ Claude Code Hooks 配置完成');
|
|
49630
|
+
}
|
|
49631
|
+
return [3 /*break*/, 6];
|
|
49632
|
+
case 5:
|
|
49633
|
+
if (this.verbose) {
|
|
49634
|
+
console.log('⏭️ 跳过 Claude Code Hooks 配置');
|
|
49635
|
+
}
|
|
49636
|
+
_a.label = 6;
|
|
49637
|
+
case 6: return [2 /*return*/, {
|
|
49638
|
+
success: true,
|
|
49639
|
+
files: files,
|
|
49640
|
+
message: 'Claude Code configuration created successfully',
|
|
49641
|
+
}];
|
|
49642
|
+
case 7:
|
|
49643
|
+
error_1 = _a.sent();
|
|
49644
|
+
return [2 /*return*/, {
|
|
49645
|
+
success: false,
|
|
49646
|
+
files: [],
|
|
49647
|
+
error: error_1.message,
|
|
49648
|
+
}];
|
|
49649
|
+
case 8: return [2 /*return*/];
|
|
49650
|
+
}
|
|
49651
|
+
});
|
|
49652
|
+
});
|
|
49653
|
+
};
|
|
49654
|
+
/**
|
|
49655
|
+
* 创建项目根目录的 CLAUDE.md
|
|
49656
|
+
*/
|
|
49657
|
+
ClaudeCodeGenerator.prototype.createClaudeMd = function () {
|
|
49658
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49659
|
+
var claudeMdPath, content;
|
|
49660
|
+
return __generator(this, function (_a) {
|
|
49661
|
+
claudeMdPath = path__namespace.join(this.cwd, 'CLAUDE.md');
|
|
49662
|
+
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";
|
|
49663
|
+
fs__namespace.writeFileSync(claudeMdPath, content);
|
|
49664
|
+
if (this.verbose) {
|
|
49665
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA CLAUDE.md: ".concat(claudeMdPath));
|
|
49666
|
+
}
|
|
49667
|
+
return [2 /*return*/, claudeMdPath];
|
|
49668
|
+
});
|
|
49669
|
+
});
|
|
49670
|
+
};
|
|
49671
|
+
/**
|
|
49672
|
+
* 创建自定义命令
|
|
49673
|
+
*/
|
|
49674
|
+
ClaudeCodeGenerator.prototype.createCustomCommands = function () {
|
|
49675
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49676
|
+
var commandsDir, files, checkTsxPath, reviewTsxPath, createPagePath, createComponentPath;
|
|
49677
|
+
return __generator(this, function (_a) {
|
|
49678
|
+
commandsDir = path__namespace.join(this.cwd, '.claude/commands');
|
|
49679
|
+
files = [];
|
|
49680
|
+
// 创建 commands 目录
|
|
49681
|
+
if (!fs__namespace.existsSync(commandsDir)) {
|
|
49682
|
+
fs__namespace.mkdirSync(commandsDir, { recursive: true });
|
|
49683
|
+
if (this.verbose) {
|
|
49684
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(commandsDir));
|
|
49685
|
+
}
|
|
49686
|
+
}
|
|
49687
|
+
checkTsxPath = path__namespace.join(commandsDir, 'check-tsx.md');
|
|
49688
|
+
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");
|
|
49689
|
+
files.push(checkTsxPath);
|
|
49690
|
+
reviewTsxPath = path__namespace.join(commandsDir, 'review-tsx.md');
|
|
49691
|
+
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");
|
|
49692
|
+
files.push(reviewTsxPath);
|
|
49693
|
+
createPagePath = path__namespace.join(commandsDir, 'create-page.md');
|
|
49694
|
+
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");
|
|
49695
|
+
files.push(createPagePath);
|
|
49696
|
+
createComponentPath = path__namespace.join(commandsDir, 'create-component.md');
|
|
49697
|
+
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");
|
|
49698
|
+
files.push(createComponentPath);
|
|
49699
|
+
if (this.verbose) {
|
|
49700
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u547D\u4EE4: ".concat(files.length, " \u4E2A\u6587\u4EF6"));
|
|
49701
|
+
}
|
|
49702
|
+
return [2 /*return*/, files];
|
|
49703
|
+
});
|
|
49704
|
+
});
|
|
49705
|
+
};
|
|
49706
|
+
return ClaudeCodeGenerator;
|
|
49707
|
+
}());
|
|
49708
|
+
|
|
49709
|
+
/**
|
|
49710
|
+
* Cursor 生成器
|
|
49711
|
+
* 生成 Cursor 特定的配置文件
|
|
49712
|
+
*/
|
|
49713
|
+
var CursorGenerator = /** @class */ (function () {
|
|
49714
|
+
function CursorGenerator(cwd, config, verbose) {
|
|
49715
|
+
this.cwd = cwd;
|
|
49716
|
+
this.config = config;
|
|
49717
|
+
this.verbose = verbose;
|
|
49718
|
+
}
|
|
49719
|
+
/**
|
|
49720
|
+
* 生成 Cursor 配置
|
|
49721
|
+
*/
|
|
49722
|
+
CursorGenerator.prototype.generate = function () {
|
|
49723
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49724
|
+
var files, cursorDir, rulesFile, promptsDir, instructionsFile, error_1;
|
|
49725
|
+
return __generator(this, function (_a) {
|
|
49726
|
+
switch (_a.label) {
|
|
49727
|
+
case 0:
|
|
49728
|
+
files = [];
|
|
49729
|
+
_a.label = 1;
|
|
49730
|
+
case 1:
|
|
49731
|
+
_a.trys.push([1, 4, , 5]);
|
|
49732
|
+
if (this.verbose) {
|
|
49733
|
+
console.log('🎯 配置 Cursor 集成...');
|
|
49734
|
+
}
|
|
49735
|
+
cursorDir = path__namespace.join(this.cwd, '.cursor');
|
|
49736
|
+
if (!fs__namespace.existsSync(cursorDir)) {
|
|
49737
|
+
fs__namespace.mkdirSync(cursorDir, { recursive: true });
|
|
49738
|
+
if (this.verbose) {
|
|
49739
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(cursorDir));
|
|
49740
|
+
}
|
|
49741
|
+
}
|
|
49742
|
+
return [4 /*yield*/, this.createRulesFile(cursorDir)];
|
|
49743
|
+
case 2:
|
|
49744
|
+
rulesFile = _a.sent();
|
|
49745
|
+
files.push(rulesFile);
|
|
49746
|
+
promptsDir = path__namespace.join(cursorDir, 'prompts');
|
|
49747
|
+
if (!fs__namespace.existsSync(promptsDir)) {
|
|
49748
|
+
fs__namespace.mkdirSync(promptsDir, { recursive: true });
|
|
49749
|
+
}
|
|
49750
|
+
return [4 /*yield*/, this.createCustomInstructions(promptsDir)];
|
|
49751
|
+
case 3:
|
|
49752
|
+
instructionsFile = _a.sent();
|
|
49753
|
+
files.push(instructionsFile);
|
|
49754
|
+
if (this.verbose) {
|
|
49755
|
+
console.log('✅ Cursor 配置完成');
|
|
49756
|
+
}
|
|
49757
|
+
return [2 /*return*/, {
|
|
49758
|
+
success: true,
|
|
49759
|
+
files: files,
|
|
49760
|
+
message: 'Cursor configuration created successfully',
|
|
49761
|
+
}];
|
|
49762
|
+
case 4:
|
|
49763
|
+
error_1 = _a.sent();
|
|
49764
|
+
return [2 /*return*/, {
|
|
49765
|
+
success: false,
|
|
49766
|
+
files: [],
|
|
49767
|
+
error: error_1.message,
|
|
49768
|
+
}];
|
|
49769
|
+
case 5: return [2 /*return*/];
|
|
49770
|
+
}
|
|
49771
|
+
});
|
|
49772
|
+
});
|
|
49773
|
+
};
|
|
49774
|
+
/**
|
|
49775
|
+
* 创建 Cursor Rules 文件
|
|
49776
|
+
*/
|
|
49777
|
+
CursorGenerator.prototype.createRulesFile = function (cursorDir) {
|
|
49778
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49779
|
+
var rulesPath, rulesContent;
|
|
49780
|
+
return __generator(this, function (_a) {
|
|
49781
|
+
rulesPath = path__namespace.join(cursorDir, 'rules.md');
|
|
49782
|
+
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");
|
|
49783
|
+
fs__namespace.writeFileSync(rulesPath, rulesContent);
|
|
49784
|
+
if (this.verbose) {
|
|
49785
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Cursor Rules: ".concat(rulesPath));
|
|
49786
|
+
}
|
|
49787
|
+
return [2 /*return*/, rulesPath];
|
|
49788
|
+
});
|
|
49789
|
+
});
|
|
49790
|
+
};
|
|
49791
|
+
/**
|
|
49792
|
+
* 创建自定义指令文件
|
|
49793
|
+
*/
|
|
49794
|
+
CursorGenerator.prototype.createCustomInstructions = function (promptsDir) {
|
|
49795
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49796
|
+
var instructionsPath, instructionsContent;
|
|
49797
|
+
return __generator(this, function (_a) {
|
|
49798
|
+
instructionsPath = path__namespace.join(promptsDir, 'custom-instructions.md');
|
|
49799
|
+
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");
|
|
49800
|
+
fs__namespace.writeFileSync(instructionsPath, instructionsContent);
|
|
49801
|
+
if (this.verbose) {
|
|
49802
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u6307\u4EE4: ".concat(instructionsPath));
|
|
49803
|
+
}
|
|
49804
|
+
return [2 /*return*/, instructionsPath];
|
|
49805
|
+
});
|
|
49806
|
+
});
|
|
49807
|
+
};
|
|
49808
|
+
return CursorGenerator;
|
|
49809
|
+
}());
|
|
49810
|
+
|
|
49811
|
+
/**
|
|
49812
|
+
* Windsurf 生成器
|
|
49813
|
+
* 生成 Windsurf (Codeium) 特定的配置文件
|
|
49814
|
+
*/
|
|
49815
|
+
var WindsurfGenerator = /** @class */ (function () {
|
|
49816
|
+
function WindsurfGenerator(cwd, config, verbose) {
|
|
49817
|
+
this.cwd = cwd;
|
|
49818
|
+
this.config = config;
|
|
49819
|
+
this.verbose = verbose;
|
|
49820
|
+
}
|
|
49821
|
+
/**
|
|
49822
|
+
* 生成 Windsurf 配置
|
|
49823
|
+
*/
|
|
49824
|
+
WindsurfGenerator.prototype.generate = function () {
|
|
49825
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49826
|
+
var files, windsurfDir, cascadeFile, rulesFile, error_1;
|
|
49827
|
+
return __generator(this, function (_a) {
|
|
49828
|
+
switch (_a.label) {
|
|
49829
|
+
case 0:
|
|
49830
|
+
files = [];
|
|
49831
|
+
_a.label = 1;
|
|
49832
|
+
case 1:
|
|
49833
|
+
_a.trys.push([1, 4, , 5]);
|
|
49834
|
+
if (this.verbose) {
|
|
49835
|
+
console.log('🌊 配置 Windsurf 集成...');
|
|
49836
|
+
}
|
|
49837
|
+
windsurfDir = path__namespace.join(this.cwd, '.windsurf');
|
|
49838
|
+
if (!fs__namespace.existsSync(windsurfDir)) {
|
|
49839
|
+
fs__namespace.mkdirSync(windsurfDir, { recursive: true });
|
|
49840
|
+
if (this.verbose) {
|
|
49841
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(windsurfDir));
|
|
49842
|
+
}
|
|
49843
|
+
}
|
|
49844
|
+
return [4 /*yield*/, this.createCascadeConfig(windsurfDir)];
|
|
49845
|
+
case 2:
|
|
49846
|
+
cascadeFile = _a.sent();
|
|
49847
|
+
files.push(cascadeFile);
|
|
49848
|
+
return [4 /*yield*/, this.createRulesFile(windsurfDir)];
|
|
49849
|
+
case 3:
|
|
49850
|
+
rulesFile = _a.sent();
|
|
49851
|
+
files.push(rulesFile);
|
|
49852
|
+
if (this.verbose) {
|
|
49853
|
+
console.log('✅ Windsurf 配置完成');
|
|
49854
|
+
}
|
|
49855
|
+
return [2 /*return*/, {
|
|
49856
|
+
success: true,
|
|
49857
|
+
files: files,
|
|
49858
|
+
message: 'Windsurf configuration created successfully',
|
|
49859
|
+
}];
|
|
49860
|
+
case 4:
|
|
49861
|
+
error_1 = _a.sent();
|
|
49862
|
+
return [2 /*return*/, {
|
|
49863
|
+
success: false,
|
|
49864
|
+
files: [],
|
|
49865
|
+
error: error_1.message,
|
|
49866
|
+
}];
|
|
49867
|
+
case 5: return [2 /*return*/];
|
|
49868
|
+
}
|
|
49869
|
+
});
|
|
49870
|
+
});
|
|
49871
|
+
};
|
|
49872
|
+
/**
|
|
49873
|
+
* 创建 Cascade 配置文件
|
|
49874
|
+
*/
|
|
49875
|
+
WindsurfGenerator.prototype.createCascadeConfig = function (windsurfDir) {
|
|
49876
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49877
|
+
var cascadePath, cascadeConfig;
|
|
49878
|
+
return __generator(this, function (_a) {
|
|
49879
|
+
cascadePath = path__namespace.join(windsurfDir, 'cascade.json');
|
|
49880
|
+
cascadeConfig = {
|
|
49881
|
+
name: this.config.projectName,
|
|
49882
|
+
description: "Agent+ Space configuration for ".concat(this.config.projectName),
|
|
49883
|
+
version: '1.0.0',
|
|
49884
|
+
rules: {
|
|
49885
|
+
tsx: {
|
|
49886
|
+
enabled: true,
|
|
49887
|
+
strictMode: true,
|
|
49888
|
+
checkMetadata: true,
|
|
49889
|
+
checkClassDefinitions: true,
|
|
49890
|
+
checkRenderMethod: true,
|
|
49891
|
+
enforceConditionalRendering: true,
|
|
49892
|
+
enforceOptionalChaining: true,
|
|
49893
|
+
},
|
|
49894
|
+
},
|
|
49895
|
+
prompts: {
|
|
49896
|
+
codeGeneration: '.appthen/prompts/tsx-generation.md',
|
|
49897
|
+
codeReview: '.appthen/prompts/code-review.md',
|
|
49898
|
+
refactoring: '.appthen/prompts/refactoring.md',
|
|
49899
|
+
},
|
|
49900
|
+
workspace: {
|
|
49901
|
+
root: this.cwd,
|
|
49902
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49903
|
+
exclude: [
|
|
49904
|
+
'node_modules/**',
|
|
49905
|
+
'dist/**',
|
|
49906
|
+
'build/**',
|
|
49907
|
+
'.git/**',
|
|
49908
|
+
'*.log',
|
|
49909
|
+
],
|
|
49910
|
+
},
|
|
49911
|
+
};
|
|
49912
|
+
fs__namespace.writeFileSync(cascadePath, JSON.stringify(cascadeConfig, null, 2));
|
|
49913
|
+
if (this.verbose) {
|
|
49914
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Cascade \u914D\u7F6E: ".concat(cascadePath));
|
|
49915
|
+
}
|
|
49916
|
+
return [2 /*return*/, cascadePath];
|
|
49917
|
+
});
|
|
49918
|
+
});
|
|
49919
|
+
};
|
|
49920
|
+
/**
|
|
49921
|
+
* 创建 Rules 文件
|
|
49922
|
+
*/
|
|
49923
|
+
WindsurfGenerator.prototype.createRulesFile = function (windsurfDir) {
|
|
49924
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49925
|
+
var rulesPath, rulesContent;
|
|
49926
|
+
return __generator(this, function (_a) {
|
|
49927
|
+
rulesPath = path__namespace.join(windsurfDir, 'rules.md');
|
|
49928
|
+
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");
|
|
49929
|
+
fs__namespace.writeFileSync(rulesPath, rulesContent);
|
|
49930
|
+
if (this.verbose) {
|
|
49931
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Rules \u6587\u4EF6: ".concat(rulesPath));
|
|
49932
|
+
}
|
|
49933
|
+
return [2 /*return*/, rulesPath];
|
|
49934
|
+
});
|
|
49935
|
+
});
|
|
49936
|
+
};
|
|
49937
|
+
return WindsurfGenerator;
|
|
49938
|
+
}());
|
|
49939
|
+
|
|
49940
|
+
/**
|
|
49941
|
+
* 阿里云 Coder 生成器
|
|
49942
|
+
* 生成阿里云 Coder 特定的配置文件
|
|
49943
|
+
*/
|
|
49944
|
+
var CoderGenerator = /** @class */ (function () {
|
|
49945
|
+
function CoderGenerator(cwd, config, verbose) {
|
|
49946
|
+
this.cwd = cwd;
|
|
49947
|
+
this.config = config;
|
|
49948
|
+
this.verbose = verbose;
|
|
49949
|
+
}
|
|
49950
|
+
/**
|
|
49951
|
+
* 生成阿里云 Coder 配置
|
|
49952
|
+
*/
|
|
49953
|
+
CoderGenerator.prototype.generate = function () {
|
|
49954
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49955
|
+
var files, coderDir, configFile, templatesDir, templateFile, error_1;
|
|
49956
|
+
return __generator(this, function (_a) {
|
|
49957
|
+
switch (_a.label) {
|
|
49958
|
+
case 0:
|
|
49959
|
+
files = [];
|
|
49960
|
+
_a.label = 1;
|
|
49961
|
+
case 1:
|
|
49962
|
+
_a.trys.push([1, 4, , 5]);
|
|
49963
|
+
if (this.verbose) {
|
|
49964
|
+
console.log('☁️ 配置阿里云 Coder 集成...');
|
|
49965
|
+
}
|
|
49966
|
+
coderDir = path__namespace.join(this.cwd, '.coder');
|
|
49967
|
+
if (!fs__namespace.existsSync(coderDir)) {
|
|
49968
|
+
fs__namespace.mkdirSync(coderDir, { recursive: true });
|
|
49969
|
+
if (this.verbose) {
|
|
49970
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(coderDir));
|
|
49971
|
+
}
|
|
49972
|
+
}
|
|
49973
|
+
return [4 /*yield*/, this.createConfig(coderDir)];
|
|
49974
|
+
case 2:
|
|
49975
|
+
configFile = _a.sent();
|
|
49976
|
+
files.push(configFile);
|
|
49977
|
+
templatesDir = path__namespace.join(coderDir, 'templates');
|
|
49978
|
+
if (!fs__namespace.existsSync(templatesDir)) {
|
|
49979
|
+
fs__namespace.mkdirSync(templatesDir, { recursive: true });
|
|
49980
|
+
}
|
|
49981
|
+
return [4 /*yield*/, this.createTsxTemplate(templatesDir)];
|
|
49982
|
+
case 3:
|
|
49983
|
+
templateFile = _a.sent();
|
|
49984
|
+
files.push(templateFile);
|
|
49985
|
+
if (this.verbose) {
|
|
49986
|
+
console.log('✅ 阿里云 Coder 配置完成');
|
|
49987
|
+
}
|
|
49988
|
+
return [2 /*return*/, {
|
|
49989
|
+
success: true,
|
|
49990
|
+
files: files,
|
|
49991
|
+
message: 'Coder configuration created successfully',
|
|
49992
|
+
}];
|
|
49993
|
+
case 4:
|
|
49994
|
+
error_1 = _a.sent();
|
|
49995
|
+
return [2 /*return*/, {
|
|
49996
|
+
success: false,
|
|
49997
|
+
files: [],
|
|
49998
|
+
error: error_1.message,
|
|
49999
|
+
}];
|
|
50000
|
+
case 5: return [2 /*return*/];
|
|
50001
|
+
}
|
|
50002
|
+
});
|
|
50003
|
+
});
|
|
50004
|
+
};
|
|
50005
|
+
/**
|
|
50006
|
+
* 创建配置文件
|
|
50007
|
+
*/
|
|
50008
|
+
CoderGenerator.prototype.createConfig = function (coderDir) {
|
|
50009
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50010
|
+
var configPath, config;
|
|
50011
|
+
return __generator(this, function (_a) {
|
|
50012
|
+
configPath = path__namespace.join(coderDir, 'config.json');
|
|
50013
|
+
config = {
|
|
50014
|
+
projectName: this.config.projectName,
|
|
50015
|
+
spaceId: this.config.spaceId,
|
|
50016
|
+
version: '1.0.0',
|
|
50017
|
+
codeGeneration: {
|
|
50018
|
+
tsx: {
|
|
50019
|
+
enabled: true,
|
|
50020
|
+
template: 'templates/tsx-template.md',
|
|
50021
|
+
rules: {
|
|
50022
|
+
requireMetadata: true,
|
|
50023
|
+
requireClassDefinitions: true,
|
|
50024
|
+
enforceRenderStructure: true,
|
|
50025
|
+
useConditionalOperator: true,
|
|
50026
|
+
useOptionalChaining: true,
|
|
50027
|
+
},
|
|
50028
|
+
},
|
|
50029
|
+
},
|
|
50030
|
+
prompts: {
|
|
50031
|
+
generation: '../.appthen/prompts/tsx-generation.md',
|
|
50032
|
+
review: '../.appthen/prompts/code-review.md',
|
|
50033
|
+
refactoring: '../.appthen/prompts/refactoring.md',
|
|
50034
|
+
},
|
|
50035
|
+
workspace: {
|
|
50036
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
50037
|
+
exclude: [
|
|
50038
|
+
'node_modules/**',
|
|
50039
|
+
'dist/**',
|
|
50040
|
+
'build/**',
|
|
50041
|
+
'.git/**',
|
|
50042
|
+
'*.log',
|
|
50043
|
+
],
|
|
50044
|
+
},
|
|
50045
|
+
};
|
|
50046
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
50047
|
+
if (this.verbose) {
|
|
50048
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
50049
|
+
}
|
|
50050
|
+
return [2 /*return*/, configPath];
|
|
50051
|
+
});
|
|
50052
|
+
});
|
|
50053
|
+
};
|
|
50054
|
+
/**
|
|
50055
|
+
* 创建 TSX 模板
|
|
50056
|
+
*/
|
|
50057
|
+
CoderGenerator.prototype.createTsxTemplate = function (templatesDir) {
|
|
50058
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50059
|
+
var templatePath, templateContent;
|
|
50060
|
+
return __generator(this, function (_a) {
|
|
50061
|
+
templatePath = path__namespace.join(templatesDir, 'tsx-template.md');
|
|
50062
|
+
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");
|
|
50063
|
+
fs__namespace.writeFileSync(templatePath, templateContent);
|
|
50064
|
+
if (this.verbose) {
|
|
50065
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA TSX \u6A21\u677F: ".concat(templatePath));
|
|
50066
|
+
}
|
|
50067
|
+
return [2 /*return*/, templatePath];
|
|
50068
|
+
});
|
|
50069
|
+
});
|
|
50070
|
+
};
|
|
50071
|
+
return CoderGenerator;
|
|
50072
|
+
}());
|
|
50073
|
+
|
|
50074
|
+
/**
|
|
50075
|
+
* Augment 生成器
|
|
50076
|
+
* 生成 Augment (VSCode 插件) 特定的配置文件
|
|
50077
|
+
*/
|
|
50078
|
+
var AugmentGenerator = /** @class */ (function () {
|
|
50079
|
+
function AugmentGenerator(cwd, config, verbose) {
|
|
50080
|
+
this.cwd = cwd;
|
|
50081
|
+
this.config = config;
|
|
50082
|
+
this.verbose = verbose;
|
|
50083
|
+
}
|
|
50084
|
+
/**
|
|
50085
|
+
* 生成 Augment 配置
|
|
50086
|
+
*/
|
|
50087
|
+
AugmentGenerator.prototype.generate = function () {
|
|
50088
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50089
|
+
var files, augmentDir, configFile, contextDir, contextFile, error_1;
|
|
50090
|
+
return __generator(this, function (_a) {
|
|
50091
|
+
switch (_a.label) {
|
|
50092
|
+
case 0:
|
|
50093
|
+
files = [];
|
|
50094
|
+
_a.label = 1;
|
|
50095
|
+
case 1:
|
|
50096
|
+
_a.trys.push([1, 4, , 5]);
|
|
50097
|
+
if (this.verbose) {
|
|
50098
|
+
console.log('🔧 配置 Augment 集成...');
|
|
50099
|
+
}
|
|
50100
|
+
augmentDir = path__namespace.join(this.cwd, '.augment');
|
|
50101
|
+
if (!fs__namespace.existsSync(augmentDir)) {
|
|
50102
|
+
fs__namespace.mkdirSync(augmentDir, { recursive: true });
|
|
50103
|
+
if (this.verbose) {
|
|
50104
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(augmentDir));
|
|
50105
|
+
}
|
|
50106
|
+
}
|
|
50107
|
+
return [4 /*yield*/, this.createConfig(augmentDir)];
|
|
50108
|
+
case 2:
|
|
50109
|
+
configFile = _a.sent();
|
|
50110
|
+
files.push(configFile);
|
|
50111
|
+
contextDir = path__namespace.join(augmentDir, 'context');
|
|
50112
|
+
if (!fs__namespace.existsSync(contextDir)) {
|
|
50113
|
+
fs__namespace.mkdirSync(contextDir, { recursive: true });
|
|
50114
|
+
}
|
|
50115
|
+
return [4 /*yield*/, this.createProjectContext(contextDir)];
|
|
50116
|
+
case 3:
|
|
50117
|
+
contextFile = _a.sent();
|
|
50118
|
+
files.push(contextFile);
|
|
50119
|
+
if (this.verbose) {
|
|
50120
|
+
console.log('✅ Augment 配置完成');
|
|
50121
|
+
}
|
|
50122
|
+
return [2 /*return*/, {
|
|
50123
|
+
success: true,
|
|
50124
|
+
files: files,
|
|
50125
|
+
message: 'Augment configuration created successfully',
|
|
50126
|
+
}];
|
|
50127
|
+
case 4:
|
|
50128
|
+
error_1 = _a.sent();
|
|
50129
|
+
return [2 /*return*/, {
|
|
50130
|
+
success: false,
|
|
50131
|
+
files: [],
|
|
50132
|
+
error: error_1.message,
|
|
50133
|
+
}];
|
|
50134
|
+
case 5: return [2 /*return*/];
|
|
50135
|
+
}
|
|
50136
|
+
});
|
|
50137
|
+
});
|
|
50138
|
+
};
|
|
50139
|
+
/**
|
|
50140
|
+
* 创建配置文件
|
|
50141
|
+
*/
|
|
50142
|
+
AugmentGenerator.prototype.createConfig = function (augmentDir) {
|
|
50143
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50144
|
+
var configPath, config;
|
|
50145
|
+
return __generator(this, function (_a) {
|
|
50146
|
+
configPath = path__namespace.join(augmentDir, 'config.json');
|
|
50147
|
+
config = {
|
|
50148
|
+
projectName: this.config.projectName,
|
|
50149
|
+
spaceId: this.config.spaceId,
|
|
50150
|
+
version: '1.0.0',
|
|
50151
|
+
context: {
|
|
50152
|
+
enabled: true,
|
|
50153
|
+
files: ['context/project-context.md'],
|
|
50154
|
+
prompts: [
|
|
50155
|
+
'../.appthen/prompts/tsx-generation.md',
|
|
50156
|
+
'../.appthen/prompts/code-review.md',
|
|
50157
|
+
'../.appthen/prompts/refactoring.md',
|
|
50158
|
+
],
|
|
50159
|
+
},
|
|
50160
|
+
codeGeneration: {
|
|
50161
|
+
tsx: {
|
|
50162
|
+
enabled: true,
|
|
50163
|
+
strictMode: true,
|
|
50164
|
+
autoFormat: true,
|
|
50165
|
+
},
|
|
50166
|
+
},
|
|
50167
|
+
workspace: {
|
|
50168
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
50169
|
+
exclude: [
|
|
50170
|
+
'node_modules/**',
|
|
50171
|
+
'dist/**',
|
|
50172
|
+
'build/**',
|
|
50173
|
+
'.git/**',
|
|
50174
|
+
'*.log',
|
|
50175
|
+
],
|
|
50176
|
+
},
|
|
50177
|
+
};
|
|
50178
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
50179
|
+
if (this.verbose) {
|
|
50180
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
50181
|
+
}
|
|
50182
|
+
return [2 /*return*/, configPath];
|
|
50183
|
+
});
|
|
50184
|
+
});
|
|
50185
|
+
};
|
|
50186
|
+
/**
|
|
50187
|
+
* 创建项目上下文文件
|
|
50188
|
+
*/
|
|
50189
|
+
AugmentGenerator.prototype.createProjectContext = function (contextDir) {
|
|
50190
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50191
|
+
var contextPath, contextContent;
|
|
50192
|
+
return __generator(this, function (_a) {
|
|
50193
|
+
contextPath = path__namespace.join(contextDir, 'project-context.md');
|
|
50194
|
+
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");
|
|
50195
|
+
fs__namespace.writeFileSync(contextPath, contextContent);
|
|
50196
|
+
if (this.verbose) {
|
|
50197
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u9879\u76EE\u4E0A\u4E0B\u6587: ".concat(contextPath));
|
|
50198
|
+
}
|
|
50199
|
+
return [2 /*return*/, contextPath];
|
|
50200
|
+
});
|
|
50201
|
+
});
|
|
50202
|
+
};
|
|
50203
|
+
return AugmentGenerator;
|
|
50204
|
+
}());
|
|
50205
|
+
|
|
50206
|
+
/**
|
|
50207
|
+
* 初始化 Agent+ Space
|
|
50208
|
+
*/
|
|
50209
|
+
function initSpace(options) {
|
|
50210
|
+
if (options === void 0) { options = {}; }
|
|
50211
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50212
|
+
var _a, force, _b, verbose, _c, cwd, _d, skipPrompts, _e, skipHooks, configPath, tool, projectName, spaceId, spaceConfig, baseGenerator, baseResult, toolResult, allFiles, error_1;
|
|
50213
|
+
return __generator(this, function (_f) {
|
|
50214
|
+
switch (_f.label) {
|
|
50215
|
+
case 0:
|
|
50216
|
+
_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;
|
|
50217
|
+
_f.label = 1;
|
|
50218
|
+
case 1:
|
|
50219
|
+
_f.trys.push([1, 6, , 7]);
|
|
50220
|
+
configPath = path__namespace.join(cwd, '.appthen/space-config.json');
|
|
50221
|
+
if (fs__namespace.existsSync(configPath) && !force) {
|
|
50222
|
+
console.log('');
|
|
50223
|
+
console.log('⚠️ Space 已经初始化');
|
|
50224
|
+
console.log(" \u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
50225
|
+
console.log('');
|
|
50226
|
+
console.log('💡 提示:');
|
|
50227
|
+
console.log(' - 使用 --force 强制重新初始化');
|
|
50228
|
+
console.log(' - 使用 appthen connect 连接到编辑器');
|
|
50229
|
+
console.log('');
|
|
50230
|
+
return [2 /*return*/, { success: false, error: 'Already initialized' }];
|
|
50231
|
+
}
|
|
50232
|
+
tool = options.tool;
|
|
50233
|
+
if (!!tool) return [3 /*break*/, 3];
|
|
50234
|
+
return [4 /*yield*/, promptForTool()];
|
|
50235
|
+
case 2:
|
|
50236
|
+
tool = _f.sent();
|
|
50237
|
+
_f.label = 3;
|
|
50238
|
+
case 3:
|
|
50239
|
+
projectName = options.name || path__namespace.basename(cwd);
|
|
50240
|
+
spaceId = "".concat(projectName, "-").concat(nanoid$1(8));
|
|
50241
|
+
spaceConfig = {
|
|
50242
|
+
spaceId: spaceId,
|
|
50243
|
+
projectId: options.projectId,
|
|
50244
|
+
projectName: projectName,
|
|
50245
|
+
projectRoot: cwd,
|
|
50246
|
+
tool: tool,
|
|
50247
|
+
createdAt: new Date().toISOString(),
|
|
50248
|
+
version: '1.0.0',
|
|
50249
|
+
};
|
|
50250
|
+
console.log('');
|
|
50251
|
+
console.log('🚀 初始化 Agent+ Space...');
|
|
50252
|
+
console.log('');
|
|
50253
|
+
if (verbose) {
|
|
50254
|
+
console.log(" \u5DE5\u5177: ".concat(getToolName(tool)));
|
|
50255
|
+
console.log(" \u9879\u76EE: ".concat(projectName));
|
|
50256
|
+
console.log(" \u7A7A\u95F4ID: ".concat(spaceId));
|
|
50257
|
+
console.log('');
|
|
50258
|
+
}
|
|
50259
|
+
baseGenerator = new BaseGenerator(cwd, spaceConfig, verbose);
|
|
50260
|
+
return [4 /*yield*/, baseGenerator.generate(skipPrompts)];
|
|
50261
|
+
case 4:
|
|
50262
|
+
baseResult = _f.sent();
|
|
50263
|
+
if (!baseResult.success) {
|
|
50264
|
+
console.error('❌ 基础配置生成失败:', baseResult.error);
|
|
50265
|
+
return [2 /*return*/, baseResult];
|
|
50266
|
+
}
|
|
50267
|
+
return [4 /*yield*/, generateToolSpecificFiles(tool, cwd, spaceConfig, verbose, skipHooks)];
|
|
50268
|
+
case 5:
|
|
50269
|
+
toolResult = _f.sent();
|
|
50270
|
+
if (!toolResult.success) {
|
|
50271
|
+
console.error('❌ 工具配置生成失败:', toolResult.error);
|
|
50272
|
+
return [2 /*return*/, toolResult];
|
|
50273
|
+
}
|
|
50274
|
+
// 7. 输出成功信息
|
|
50275
|
+
console.log('');
|
|
50276
|
+
console.log('🎉 Agent+ Space 初始化完成!');
|
|
50277
|
+
console.log('');
|
|
50278
|
+
console.log('📋 已创建的文件:');
|
|
50279
|
+
allFiles = __spreadArray(__spreadArray([], __read(baseResult.files), false), __read(toolResult.files), false);
|
|
50280
|
+
allFiles.forEach(function (file) {
|
|
50281
|
+
var relativePath = path__namespace.relative(cwd, file);
|
|
50282
|
+
console.log(" \u2713 ".concat(relativePath));
|
|
50283
|
+
});
|
|
50284
|
+
console.log('');
|
|
50285
|
+
console.log('🚀 下一步:');
|
|
50286
|
+
console.log(" cd ".concat(cwd));
|
|
50287
|
+
console.log(' appthen connect');
|
|
50288
|
+
console.log('');
|
|
50289
|
+
console.log('📖 更多信息:');
|
|
50290
|
+
console.log(' - 查看 .appthen/prompts/README.md 了解提示词使用');
|
|
50291
|
+
if (tool === 'claude-code') {
|
|
50292
|
+
console.log(' - 查看 .claude/settings.json 了解 Hooks 配置');
|
|
50293
|
+
}
|
|
50294
|
+
else if (tool === 'cursor') {
|
|
50295
|
+
console.log(' - 查看 .cursor/rules.md 了解 Cursor Rules');
|
|
50296
|
+
}
|
|
50297
|
+
else if (tool === 'windsurf') {
|
|
50298
|
+
console.log(' - 查看 .windsurf/cascade.json 了解 Cascade 配置');
|
|
50299
|
+
}
|
|
50300
|
+
else if (tool === 'coder') {
|
|
50301
|
+
console.log(' - 查看 .coder/config.json 了解配置选项');
|
|
50302
|
+
}
|
|
50303
|
+
else if (tool === 'augment') {
|
|
50304
|
+
console.log(' - 查看 .augment/context/project-context.md 了解项目上下文');
|
|
50305
|
+
}
|
|
50306
|
+
console.log('');
|
|
50307
|
+
return [2 /*return*/, {
|
|
50308
|
+
success: true,
|
|
50309
|
+
message: 'Space initialized successfully',
|
|
50310
|
+
spaceId: spaceId,
|
|
50311
|
+
files: allFiles,
|
|
50312
|
+
}];
|
|
50313
|
+
case 6:
|
|
50314
|
+
error_1 = _f.sent();
|
|
50315
|
+
console.error('');
|
|
50316
|
+
console.error('❌ 初始化失败:', error_1.message);
|
|
50317
|
+
console.error('');
|
|
50318
|
+
if (verbose) {
|
|
50319
|
+
console.error('错误详情:', error_1);
|
|
50320
|
+
}
|
|
50321
|
+
return [2 /*return*/, {
|
|
50322
|
+
success: false,
|
|
50323
|
+
error: error_1.message,
|
|
50324
|
+
}];
|
|
50325
|
+
case 7: return [2 /*return*/];
|
|
50326
|
+
}
|
|
50327
|
+
});
|
|
50328
|
+
});
|
|
50329
|
+
}
|
|
50330
|
+
/**
|
|
50331
|
+
* 提示用户选择 AI 工具
|
|
50332
|
+
*/
|
|
50333
|
+
function promptForTool() {
|
|
50334
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50335
|
+
var inquirer, answer;
|
|
50336
|
+
return __generator(this, function (_a) {
|
|
50337
|
+
switch (_a.label) {
|
|
50338
|
+
case 0:
|
|
50339
|
+
_a.trys.push([0, 3, , 4]);
|
|
50340
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('inquirer')); })];
|
|
50341
|
+
case 1:
|
|
50342
|
+
inquirer = _a.sent();
|
|
50343
|
+
return [4 /*yield*/, inquirer.default.prompt([
|
|
50344
|
+
{
|
|
50345
|
+
type: 'list',
|
|
50346
|
+
name: 'tool',
|
|
50347
|
+
message: '请选择你使用的 AI 编码工具:',
|
|
50348
|
+
choices: AI_TOOLS.map(function (tool) { return ({
|
|
50349
|
+
name: tool.name,
|
|
50350
|
+
value: tool.value,
|
|
50351
|
+
}); }),
|
|
50352
|
+
},
|
|
50353
|
+
])];
|
|
50354
|
+
case 2:
|
|
50355
|
+
answer = _a.sent();
|
|
50356
|
+
return [2 /*return*/, answer.tool];
|
|
50357
|
+
case 3:
|
|
50358
|
+
_a.sent();
|
|
50359
|
+
// 如果 inquirer 不可用,提供友好的错误提示
|
|
50360
|
+
console.log('');
|
|
50361
|
+
console.log('⚠️ 无法启动交互式选择');
|
|
50362
|
+
console.log('');
|
|
50363
|
+
console.log('💡 请使用 --tool 参数指定 AI 工具:');
|
|
50364
|
+
console.log('');
|
|
50365
|
+
console.log(' appthen init-space --tool claude-code # Claude Code');
|
|
50366
|
+
console.log(' appthen init-space --tool cursor # Cursor');
|
|
50367
|
+
console.log(' appthen init-space --tool windsurf # Windsurf');
|
|
50368
|
+
console.log(' appthen init-space --tool coder # 阿里云 Coder');
|
|
50369
|
+
console.log(' appthen init-space --tool augment # Augment');
|
|
50370
|
+
console.log(' appthen init-space --tool other # 其他/跳过');
|
|
50371
|
+
console.log('');
|
|
50372
|
+
throw new Error('需要指定 --tool 参数');
|
|
50373
|
+
case 4: return [2 /*return*/];
|
|
50374
|
+
}
|
|
50375
|
+
});
|
|
50376
|
+
});
|
|
50377
|
+
}
|
|
50378
|
+
/**
|
|
50379
|
+
* 根据工具生成特定文件
|
|
50380
|
+
*/
|
|
50381
|
+
function generateToolSpecificFiles(tool, cwd, config, verbose, skipHooks) {
|
|
50382
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
50383
|
+
var _a, generator, generator, generator, generator, generator;
|
|
50384
|
+
return __generator(this, function (_b) {
|
|
50385
|
+
switch (_b.label) {
|
|
50386
|
+
case 0:
|
|
50387
|
+
_a = tool;
|
|
50388
|
+
switch (_a) {
|
|
50389
|
+
case 'claude-code': return [3 /*break*/, 1];
|
|
50390
|
+
case 'cursor': return [3 /*break*/, 3];
|
|
50391
|
+
case 'windsurf': return [3 /*break*/, 5];
|
|
50392
|
+
case 'coder': return [3 /*break*/, 7];
|
|
50393
|
+
case 'augment': return [3 /*break*/, 9];
|
|
50394
|
+
case 'other': return [3 /*break*/, 11];
|
|
50395
|
+
}
|
|
50396
|
+
return [3 /*break*/, 11];
|
|
50397
|
+
case 1:
|
|
50398
|
+
generator = new ClaudeCodeGenerator(cwd, config, verbose);
|
|
50399
|
+
return [4 /*yield*/, generator.generate(skipHooks)];
|
|
50400
|
+
case 2: return [2 /*return*/, _b.sent()];
|
|
50401
|
+
case 3:
|
|
50402
|
+
generator = new CursorGenerator(cwd, config, verbose);
|
|
50403
|
+
return [4 /*yield*/, generator.generate()];
|
|
50404
|
+
case 4: return [2 /*return*/, _b.sent()];
|
|
50405
|
+
case 5:
|
|
50406
|
+
generator = new WindsurfGenerator(cwd, config, verbose);
|
|
50407
|
+
return [4 /*yield*/, generator.generate()];
|
|
50408
|
+
case 6: return [2 /*return*/, _b.sent()];
|
|
50409
|
+
case 7:
|
|
50410
|
+
generator = new CoderGenerator(cwd, config, verbose);
|
|
50411
|
+
return [4 /*yield*/, generator.generate()];
|
|
50412
|
+
case 8: return [2 /*return*/, _b.sent()];
|
|
50413
|
+
case 9:
|
|
50414
|
+
generator = new AugmentGenerator(cwd, config, verbose);
|
|
50415
|
+
return [4 /*yield*/, generator.generate()];
|
|
50416
|
+
case 10: return [2 /*return*/, _b.sent()];
|
|
50417
|
+
case 11:
|
|
50418
|
+
{
|
|
50419
|
+
// 只生成基础配置,不生成工具特定文件
|
|
50420
|
+
if (verbose) {
|
|
50421
|
+
console.log('⏭️ 跳过工具特定配置');
|
|
50422
|
+
}
|
|
50423
|
+
return [2 /*return*/, {
|
|
50424
|
+
success: true,
|
|
50425
|
+
files: [],
|
|
50426
|
+
message: 'No tool-specific configuration generated',
|
|
50427
|
+
}];
|
|
50428
|
+
}
|
|
50429
|
+
case 12: return [2 /*return*/];
|
|
50430
|
+
}
|
|
50431
|
+
});
|
|
50432
|
+
});
|
|
50433
|
+
}
|
|
50434
|
+
/**
|
|
50435
|
+
* 获取工具的显示名称
|
|
50436
|
+
*/
|
|
50437
|
+
function getToolName(tool) {
|
|
50438
|
+
var toolChoice = AI_TOOLS.find(function (t) { return t.value === tool; });
|
|
50439
|
+
return toolChoice ? toolChoice.name : tool;
|
|
50440
|
+
}
|
|
50441
|
+
|
|
48301
50442
|
exports.ShadowSpace = ShadowSpace;
|
|
48302
50443
|
exports.ShadowSpaceDebugger = ShadowSpaceDebugger;
|
|
48303
50444
|
exports.TSXComplianceChecker = TSXComplianceChecker;
|
|
@@ -48316,6 +50457,7 @@ exports.generateFixSuggestions = generateFixSuggestions;
|
|
|
48316
50457
|
exports.getPureValue = getPureValue;
|
|
48317
50458
|
exports.initClaudeHooks = initClaudeHooks;
|
|
48318
50459
|
exports.initSolution = initSolution;
|
|
50460
|
+
exports.initSpace = initSpace;
|
|
48319
50461
|
exports.isFileCompliant = isFileCompliant;
|
|
48320
50462
|
exports.releaseMaterial = releaseMaterial;
|
|
48321
50463
|
exports.run = run;
|