@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/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, localHash, size, now, e_1_1, _b, _c, _d, filePath, fileEntry, allFiles, totalFilesCount, totalSizeSum;
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, 6, 7, 8]);
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*/, 5];
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*/, 4];
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: file.hash || localHash,
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, file.content);
40849
- _g.label = 4;
40850
- case 4:
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 5: return [3 /*break*/, 8];
40854
- case 6:
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*/, 8];
40858
- case 7:
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 8:
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 9:
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, _a, _b, _c, filePath, shadowEntry, localFilePath, localContent, localHash, _d, _e, _f, shadowContent, _g, _h, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
40995
- var e_3, _j, _k, _l, e_4, _m;
40996
- return __generator(this, function (_o) {
40997
- switch (_o.label) {
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
- _o.label = 1;
40998
+ _p.label = 1;
41001
40999
  case 1:
41002
- _o.trys.push([1, 16, 17, 18]);
41003
- _a = __values(Object.entries(this.state.files)), _b = _a.next();
41004
- _o.label = 2;
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 (!!_b.done) return [3 /*break*/, 15];
41007
- _c = __read(_b.value, 2), filePath = _c[0], shadowEntry = _c[1];
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
- _o.label = 3;
41007
+ _p.label = 3;
41010
41008
  case 3:
41011
- _o.trys.push([3, 11, , 14]);
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 = _o.sent();
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
- _d = this.state.files;
41022
- _e = filePath;
41023
- _f = [__assign({}, shadowEntry)];
41024
- _k = { hash: localHash };
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
- _k.size = (_o.sent()).size, _k.lastSyncTime = Date.now(), _k.version = shadowEntry.version + 1;
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
- _d[_e] = __assign.apply(void 0, _f.concat([(_k.mtime = (_o.sent()).mtimeMs, _k.remoteModified = false, _k)]));
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
- _o.label = 7;
41040
+ _p.label = 7;
41036
41041
  case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
41037
41042
  case 8:
41038
- shadowContent = _o.sent();
41039
- _h = (_g = changes).push;
41040
- _l = {
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
- _h.apply(_g, [(_l.timestamp = (_o.sent()).mtime.getTime(),
41049
- _l.diff = {
41053
+ _j.apply(_h, [(_m.timestamp = (_p.sent()).mtime.getTime(),
41054
+ _m.diff = {
41050
41055
  before: shadowContent,
41051
41056
  after: localContent,
41052
41057
  },
41053
- _l.projectId = this.state.projectId,
41054
- _l)]);
41055
- _o.label = 10;
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 = _o.sent();
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 = _o.sent();
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
- _o.label = 13;
41080
+ _p.label = 13;
41076
41081
  case 13: return [3 /*break*/, 14];
41077
41082
  case 14:
41078
- _b = _a.next();
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 = _o.sent();
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 (_b && !_b.done && (_j = _a.return)) _j.call(_a);
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 = _o.sent();
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 && (_m = localFiles_1.return)) _m.call(localFiles_1);
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, error_4, e_6_1;
41248
- var e_6, _a;
41249
- return __generator(this, function (_b) {
41250
- switch (_b.label) {
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
- _b.label = 1;
41292
+ _c.label = 1;
41255
41293
  case 1:
41256
- _b.trys.push([1, 9, 10, 11]);
41294
+ _c.trys.push([1, 9, 10, 11]);
41257
41295
  filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
41258
- _b.label = 2;
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
- _b.label = 3;
41301
+ _c.label = 3;
41264
41302
  case 3:
41265
- _b.trys.push([3, 6, , 7]);
41303
+ _c.trys.push([3, 6, , 7]);
41266
41304
  return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
41267
41305
  case 4:
41268
- stats = _b.sent();
41306
+ stats = _c.sent();
41269
41307
  return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
41270
41308
  case 5:
41271
- content = _b.sent();
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: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash,
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, " (\u7248\u672C ").concat(this.state.files[filePath].version, ")"));
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
- error_4 = _b.sent();
41291
- console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"), error_4);
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 = _b.sent();
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 && (_a = filePaths_1.return)) _a.call(filePaths_1);
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
- _b.sent();
41357
+ _c.sent();
41313
41358
  console.log("\u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
41314
- _b.label = 13;
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, error_5;
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
- error_5 = _e.sent();
41409
- console.error("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167\u5931\u8D25:", error_5);
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, error_7;
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
- error_7 = _a.sent();
41496
- console.warn("[ShadowSpace] \u4FDD\u5B58\u7A7A\u95F4\u914D\u7F6E\u5931\u8D25:", error_7);
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, error_8;
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
- error_8 = _b.sent();
41575
- console.warn("[ShadowSpace] \u8FC1\u79FB\u65E7\u72B6\u6001\u6587\u4EF6\u5931\u8D25:", error_8);
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, error_9;
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
- error_9 = _a.sent();
41603
- console.warn("\u65E0\u6CD5\u83B7\u53D6\u5F71\u5B50\u5185\u5BB9: ".concat(filePath), error_9);
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("[ShadowSpace] \u6587\u4EF6\u901A\u8FC7\u5FFD\u7565\u68C0\u67E5: ".concat(filePath));
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, error_10;
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
- error_10 = _a.sent();
41718
- console.error("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u5931\u8D25: ".concat(fullPath), error_10);
41719
- throw error_10;
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, error_11, e_11_1;
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
- error_11 = _b.sent();
41768
- console.warn("\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_11);
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, _g, error_1, errorMessage;
41880
- return __generator(this, function (_h) {
41881
- switch (_h.label) {
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
- _h.label = 1;
42257
+ _j.label = 1;
41908
42258
  case 1:
41909
- _h.trys.push([1, 26, , 27]);
42259
+ _j.trys.push([1, 28, , 29]);
41910
42260
  result = void 0;
41911
- _g = action;
41912
- switch (_g) {
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*/, 24];
42276
+ return [3 /*break*/, 26];
41926
42277
  case 2: return [4 /*yield*/, this.getChanges()];
41927
42278
  case 3:
41928
- result = _h.sent();
41929
- return [3 /*break*/, 25];
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 = _h.sent();
41938
- return [3 /*break*/, 25];
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 = _h.sent();
41943
- return [3 /*break*/, 25];
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 = _h.sent();
41947
- return [3 /*break*/, 25];
42297
+ result = _j.sent();
42298
+ return [3 /*break*/, 27];
41948
42299
  case 10: return [4 /*yield*/, this.resetShadowSpace()];
41949
42300
  case 11:
41950
- result = _h.sent();
41951
- return [3 /*break*/, 25];
42301
+ result = _j.sent();
42302
+ return [3 /*break*/, 27];
41952
42303
  case 12: return [4 /*yield*/, this.getSpaceInfo()];
41953
42304
  case 13:
41954
- result = _h.sent();
41955
- return [3 /*break*/, 25];
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 = _h.sent();
41959
- return [3 /*break*/, 25];
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 = _h.sent();
41963
- return [3 /*break*/, 25];
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 = _h.sent();
41967
- return [3 /*break*/, 25];
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 = _h.sent();
41971
- return [3 /*break*/, 25];
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 = _h.sent();
41975
- return [3 /*break*/, 25];
41976
- case 24: throw new Error("Unknown shadow space action: ".concat(action));
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*/, 27];
41981
- case 26:
41982
- error_1 = _h.sent();
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*/, 27];
41987
- case 27: return [2 /*return*/];
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, result_1, readError_1, result;
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 [4 /*yield*/, this.shadowSpace.detectChanges()];
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
- if (!change) return [3 /*break*/, 2];
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*/, 7];
42066
- case 2:
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 = 3;
42069
- case 3:
42070
- _a.trys.push([3, 5, , 6]);
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 4:
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
- result_1 = {
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(result_1.metadata.afterSize, " \u5B57\u8282"));
42092
- return [2 /*return*/, result_1];
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*/, 6];
42095
- case 5:
42096
- readError_1 = _a.sent();
42097
- console.error("[ShadowSpace] \u76F4\u63A5\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(normalizedPath), readError_1);
42098
- return [3 /*break*/, 6];
42099
- case 6:
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 7:
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 changes, results, _loop_1, filePaths_1, filePaths_1_1, filePath, result;
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
- _loop_1 = function (filePath) {
42149
- // 🆕 标准化文件路径:去掉开头的 /
42150
- var normalizedPath = filePath.startsWith('/')
42151
- ? filePath.substring(1)
42152
- : filePath;
42153
- console.log("[ShadowSpace] \u6279\u91CF\u5904\u7406: ".concat(filePath, " -> ").concat(normalizedPath));
42154
- var change = changes.find(function (c) { return c.path === normalizedPath; });
42155
- if (change) {
42156
- results.push({
42157
- path: normalizedPath,
42158
- action: change.action,
42159
- version: change.version,
42160
- timestamp: change.timestamp,
42161
- diff: {
42162
- before: change.diff.before,
42163
- after: change.diff.after,
42164
- },
42165
- });
42166
- }
42167
- else {
42168
- console.warn("[ShadowSpace] \u6279\u91CF\u83B7\u53D6\u4E2D\u672A\u627E\u5230\u6587\u4EF6: ".concat(normalizedPath));
42169
- }
42170
- };
42171
- try {
42172
- for (filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next(); !filePaths_1_1.done; filePaths_1_1 = filePaths_1.next()) {
42173
- filePath = filePaths_1_1.value;
42174
- _loop_1(filePath);
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
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
42178
- finally {
42179
- try {
42180
- if (filePaths_1_1 && !filePaths_1_1.done && (_a = filePaths_1.return)) _a.call(filePaths_1);
42181
- }
42182
- finally { if (e_1) throw e_1.error; }
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("[ShadowSpace] \u7A7A\u95F4\u4FE1\u606F: ".concat(info.fileCount, " \u4E2A\u6587\u4EF6, ").concat(info.totalSize));
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 filePaths, result;
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("[ShadowSpace] \u5F53\u524D\u5F71\u5B50\u7A7A\u95F4\u4E2D\u7684\u6587\u4EF6:", allFiles);
42733
+ console.log('[ShadowSpace] 当前影子空间中的文件: ', allFiles);
42316
42734
  console.log("[ShadowSpace] \u8981\u5220\u9664\u7684\u6587\u4EF6\u8DEF\u5F84: \"".concat(filePath, "\""));
42317
- console.log("[ShadowSpace] \u6587\u4EF6\u662F\u5426\u5B58\u5728:", this.shadowSpace.hasFile(filePath) ? '是' : '否');
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("[ShadowSpace] \u68C0\u67E5\u54CD\u5E94: action=".concat(actualAction, ", messageId=").concat(actualMessageId, ", \u671F\u671B=").concat(messageId));
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("[ShadowSpace] \u6536\u5230\u7F16\u8F91\u5668\u72B6\u6001\u54CD\u5E94");
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("[ShadowSpace] \u4E34\u65F6\u76D1\u542C\u5668\u5DF2\u8BBE\u7F6E\uFF0C\u53D1\u9001\u7F16\u8F91\u5668\u72B6\u6001\u8BF7\u6C42: ".concat(messageId));
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("[ShadowSpace] \u6062\u590D\u539F\u59CB\u76D1\u542C\u5668: ".concat(messageId));
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, snapshotCount, changes, summary, error_2;
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
- snapshotCount = Array.isArray(spaceSnapshots)
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("[ShadowSpace] \u53D8\u66F4\u68C0\u6D4B\u5B8C\u6210: \u603B\u8BA1".concat(summary.total, "\u4E2A\u53D8\u66F4, \u9700\u63A8\u9001").concat(summary.needPush, "\u4E2A, \u9700\u62C9\u53D6").concat(summary.needPull, "\u4E2A"));
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
- error_2 = _a.sent();
42507
- console.error("[ShadowSpace] \u68C0\u6D4B\u53D8\u66F4\u5931\u8D25:", error_2);
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: error_2 instanceof Error ? error_2.message : '检测变更失败',
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, _a, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _b, path, spaceFile, editorFile;
42523
- var e_2, _c, e_3, _d;
42524
- return __generator(this, function (_e) {
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
- _a = __read(editorMap_1_1.value, 2), path = _a[0], editorFile = _a[1];
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 && (_c = editorMap_1.return)) _c.call(editorMap_1);
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
- _b = __read(spaceMap_1_1.value, 2), path = _b[0], spaceFile = _b[1];
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 && (_d = spaceMap_1.return)) _d.call(spaceMap_1);
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
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6B63\u5728\u6E05\u7406..."));
42755
- removePidFile();
42756
- process.exit(0);
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, error_2, error_3, userId, current, cwd, type, change, filePath;
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
- error_2 = _d.sent();
42894
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(error_2));
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
- error_3 = _d.sent();
42937
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(error_3));
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: error_3 instanceof Error ? error_3.message : String(error_3),
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
- var TSXComplianceChecker = /** @class */ (function () {
47095
- function TSXComplianceChecker() {
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
- * 使用 AST 检查 TSX 规范
47670
+ * 验证TSX文件内容
47099
47671
  */
47100
- TSXComplianceChecker.checkTSXCompliance = function (content, filename) {
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
- // 使用 Babel 解析 TSX 代码
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
- // 遍历 AST 进行检查
47110
- traverse__default["default"](ast, {
47111
- // 检查变量声明
47112
- VariableDeclarator: function (path) {
47113
- TSXComplianceChecker.checkVariableDeclaration(path, content, issues);
47114
- },
47115
- // 检查方法定义
47116
- ClassMethod: function (path) {
47117
- TSXComplianceChecker.checkMethodDefinition(path, content, issues);
47118
- },
47119
- // 检查 JSX 使用
47120
- JSXElement: function (path) {
47121
- TSXComplianceChecker.checkJSXUsage(path, content, issues);
47122
- },
47123
- // 检查类型注解
47124
- TSTypeAnnotation: function (path) {
47125
- TSXComplianceChecker.checkTypeAnnotation(path, content, issues);
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
- issues.push({
47133
- type: 'error',
47134
- code: 'PARSE_ERROR',
47135
- message: "\u4EE3\u7801\u89E3\u6790\u5931\u8D25: ".concat(error.message),
47136
- suggestion: '检查代码语法是否正确',
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
- TSXComplianceChecker.checkVariableDeclaration = function (path, content, issues) {
47148
- path.node;
47149
- // 检查是否在 render 方法中
47150
- var renderMethod = path.findParent(function (p) {
47151
- return p.isClassMethod() &&
47152
- t__namespace.isIdentifier(p.node.key) &&
47153
- p.node.key.name === 'render';
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
- if (!renderMethod)
47156
- return;
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
- // 其他在 render 方法中的变量声明都是错误的
47185
- var _b = this.getLocation(path, content), line = _b.line, column = _b.column;
47186
- var snippet = this.extractCodeSnippet(content, line);
47187
- issues.push({
47188
- type: 'error',
47189
- code: 'RENDER_VARIABLE_DECLARATION',
47190
- message: 'render() 方法中不能包含变量声明',
47191
- suggestion: '移除所有 const/let/var 声明,直接使用 this.state.xxx',
47192
- line: line,
47193
- column: column,
47194
- codeSnippet: snippet.snippet,
47195
- snippetStartLine: snippet.startLine,
47196
- snippetEndLine: snippet.endLine,
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
- TSXComplianceChecker.isInEventHandler = function (path) {
47203
- // 查找父级 JSX 属性
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
- // 检查是否在 JSX 属性回调中(如 beforeUpload, customRequest 等)
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
- 'customRequest',
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
- // 检查函数是否返回 JSX
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
- TSXComplianceChecker.checkMethodDefinition = function (path, content, issues) {
47294
- var node = path.node;
47295
- // 跳过 render 方法和渲染相关方法
47296
- if (t__namespace.isIdentifier(node.key)) {
47297
- var methodName = node.key.name;
47298
- var renderMethods = [
47299
- 'render',
47300
- 'renderItem',
47301
- 'renderContent',
47302
- 'renderHeader',
47303
- 'renderFooter',
47304
- ];
47305
- if (renderMethods.includes(methodName))
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
- // 检查方法中是否包含 JSX
47308
- var containsJSX_1 = false;
47309
- path.traverse({
47310
- JSXElement: function () {
47311
- containsJSX_1 = true;
47312
- },
47313
- });
47314
- if (containsJSX_1) {
47315
- var _a = this.getLocation(path, content), line = _a.line, column = _a.column;
47316
- var snippet = this.extractCodeSnippet(content, line);
47317
- issues.push({
47318
- type: 'error',
47319
- code: 'METHOD_CONTAINS_JSX',
47320
- message: "\u65B9\u6CD5 ".concat(methodName, " \u4E0D\u80FD\u5305\u542B JSX \u8BED\u6CD5"),
47321
- suggestion: '只有 render() 方法可以包含 JSX,其他方法只处理逻辑',
47322
- line: line,
47323
- column: column,
47324
- codeSnippet: snippet.snippet,
47325
- snippetStartLine: snippet.startLine,
47326
- snippetEndLine: snippet.endLine,
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
- * 检查 JSX 使用
48263
+ * 安全地执行检查方法,避免异常传播
47333
48264
  */
47334
- TSXComplianceChecker.checkJSXUsage = function (path, content, issues) {
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
- TSXComplianceChecker.checkTypeAnnotation = function (path, content, issues) {
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
- TSXComplianceChecker.checkRequiredStructures = function (ast, content, issues) {
47347
- // 这里可以添加对必需结构的检查
47348
- // IProps, IState, Document 类等
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.getLocation = function (path, content) {
47354
- var loc = path.node.loc;
47355
- return {
47356
- line: loc ? loc.start.line : 1,
47357
- column: loc ? loc.start.column : 0,
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
- var isCompliant = result.isCompliant, issues = result.issues;
47385
- var report = '=== TSX 规范检查报告 ===\n';
47386
- report += "\u6587\u4EF6: ".concat(filename, "\n");
47387
- if (isCompliant) {
47388
- report += '✅ 检查通过:文件符合 TSX 规范\n';
47389
- }
47390
- else {
47391
- var errorCount = issues.filter(function (issue) { return issue.type === 'error'; }).length;
47392
- report += "\u274C \u68C0\u67E5\u5931\u8D25\uFF1A\u53D1\u73B0 ".concat(errorCount, " \u4E2A\u9519\u8BEF\n\n");
47393
- report += '--- 问题详情 ---\n';
47394
- issues.forEach(function (issue, index) {
47395
- var icon = issue.type === 'error' ? '❌' : '⚠️';
47396
- report += "".concat(index + 1, ". ").concat(icon, " [").concat(issue.code, "] ").concat(issue.message, "\n");
47397
- if (issue.line) {
47398
- report += " \uD83D\uDCCD \u4F4D\u7F6E: \u7B2C ".concat(issue.line, " \u884C\n");
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 report;
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;