@appthen/cli 1.2.8 → 1.2.11

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.
Files changed (122) hide show
  1. package/.gitignore +1 -0
  2. package/bin/main.js +45 -0
  3. package/dist/index.js +1277 -909
  4. package/package.json +1 -1
  5. package/tests/test-app/.appthen/shadow-space-100001-test-app-e99876b1.json +1406 -0
  6. package/tests/test-app/.appthen/shadow-space-unknown-user-test-app-e99876b1.json +1060 -0
  7. package/tests/test-app/.appthen/space-config.json +8 -0
  8. package/tests/test-app/docs/AI-Workflow.flow +112 -0
  9. package/tests/test-app/docs/Logic-1.flow +16 -0
  10. package/tests/test-app/docs/Logic.flow +16 -0
  11. package/tests/test-app/docs/Project-Blueprint-1.flow +119 -0
  12. package/tests/test-app/docs/Project-Blueprint.flow +119 -0
  13. package/tests/test-app/docs/README.md +3 -0
  14. package/tests/test-app/docs/claude.md +194 -0
  15. package/tests/test-app/docs/page_requirement_analysis.md +149 -0
  16. package/tests/test-app/docs//345/267/245/345/215/225/347/256/241/347/220/206/347/263/273/347/273/237/350/257/246/347/273/206/350/256/276/350/256/241.md +377 -0
  17. package/tests/test-app/src/apis/AddTodoPost.api.ts +42 -0
  18. package/tests/test-app/src/apis/DeleteTodoPost.api.ts +32 -0
  19. package/tests/test-app/src/apis/GetListPost.api.ts +38 -0
  20. package/tests/test-app/src/apis/TicketAttachmentUploadPost.api.ts +42 -0
  21. package/tests/test-app/src/apis/UpdateTodoPost.api.ts +46 -0
  22. package/tests/test-app/src/app.css +15 -0
  23. package/tests/test-app/src/cloud_functions/ticket|attachment|upload.node.ts +86 -0
  24. package/tests/test-app/src/cloud_functions/ticket|comment|add.node.ts +65 -0
  25. package/tests/test-app/src/cloud_functions/types|entity|Ticket.node.ts +88 -0
  26. package/tests/test-app/src/cloud_functions/types|entity|TicketAttachment.node.ts +70 -0
  27. package/tests/test-app/src/cloud_functions/types|entity|TicketCategory.node.ts +56 -0
  28. package/tests/test-app/src/cloud_functions/types|entity|TicketComment.node.ts +62 -0
  29. package/tests/test-app/src/cloud_functions/types|entity|TicketHistory.node.ts +74 -0
  30. package/tests/test-app/src/cloud_functions/types|entity|TicketPriority.node.ts +68 -0
  31. package/tests/test-app/src/cloud_functions/types|entity|TicketStatus.node.ts +63 -0
  32. package/tests/test-app/src/cloud_functions/types|models|CreateTicketParams.node.ts +20 -0
  33. package/tests/test-app/src/cloud_functions/types|models|TicketListParams.node.ts +30 -0
  34. package/tests/test-app/src/cloud_functions/types|models|UpdateTicketParams.node.ts +22 -0
  35. package/tests/test-app/src/components/Button.js +11 -0
  36. package/tests/test-app/src/components/MouduleDemoNzp.tsx +40 -0
  37. package/tests/test-app/src/components/Timeline.tsx +145 -0
  38. package/tests/test-app/src/index.ts +2 -0
  39. package/tests/test-app/src/modules/work_order_module/apis/TicketCommentAddPost.api.ts +48 -0
  40. package/tests/test-app/src/modules/work_order_module/apis/TicketCreatePost.api.ts +52 -0
  41. package/tests/test-app/src/modules/work_order_module/apis/TicketDeleteDelete.api.ts +39 -0
  42. package/tests/test-app/src/modules/work_order_module/apis/TicketDetailGet.api.ts +39 -0
  43. package/tests/test-app/src/modules/work_order_module/apis/TicketListGet.api.ts +61 -0
  44. package/tests/test-app/src/modules/work_order_module/apis/TicketUpdatePut.api.ts +57 -0
  45. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorFaultListGet.ts +76 -0
  46. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorListGet.ts +76 -0
  47. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorOperationRecordsGet.ts +284 -0
  48. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorStatisticsGet.ts +96 -0
  49. package/tests/test-app/src/modules/work_order_module/cloud_function/category|list.node.ts +40 -0
  50. package/tests/test-app/src/modules/work_order_module/cloud_function/priority|list.node.ts +26 -0
  51. package/tests/test-app/src/modules/work_order_module/cloud_function/status|list.node.ts +26 -0
  52. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|create.node.ts +54 -0
  53. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|delete.node.ts +55 -0
  54. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|detail.node.ts +65 -0
  55. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|list.node.ts +85 -0
  56. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|update.node.ts +73 -0
  57. package/tests/test-app/src/modules/work_order_module/data_model/Ticket.m.ts +85 -0
  58. package/tests/test-app/src/modules/work_order_module/data_model/TicketCategory.m.ts +53 -0
  59. package/tests/test-app/src/modules/work_order_module/data_model/TicketStatus.m.ts +60 -0
  60. package/tests/test-app/src/modules/work_order_module//345/267/245/345/215/225/347/263/273/347/273/237/344/272/247/345/223/201/350/256/276/350/256/241/346/226/207/346/241/243.md +301 -0
  61. package/tests/test-app/src/modules/work_order_module//345/267/245/345/215/225/347/263/273/347/273/237/345/274/200/345/217/221/344/273/273/345/212/241/345/210/206/345/267/245/346/226/207/346/241/243.md +345 -0
  62. package/tests/test-app/src/pages/SLAManagement.tsx +668 -0
  63. package/tests/test-app/src/pages/TicketCreate.tsx +27 -0
  64. package/tests/test-app/src/pages/TicketDetail.tsx +27 -0
  65. package/tests/test-app/src/pages/TicketList.tsx +27 -0
  66. package/tests/test-app/src/pages/TicketManagementPage.tsx +1238 -0
  67. package/tests/test-app/src/pages/VisualAIIDEUpgrade.tsx +245 -0
  68. package/tests/test-app/src/pages/appthen_guide/ComponentTreeUnderstanding.tsx +26 -0
  69. package/tests/test-app/src/pages/appthen_guide/DataBindingLearning.tsx +26 -0
  70. package/tests/test-app/src/pages/back-end/adminRootLayout.tsx +155 -0
  71. package/tests/test-app/src/pages/back-end/adminRootLayout10.tsx +157 -0
  72. package/tests/test-app/src/pages/back-end/adminRootLayout2.tsx +156 -0
  73. package/tests/test-app/src/pages/back-end/adminRootLayout3.tsx +156 -0
  74. package/tests/test-app/src/pages/back-end/adminRootLayout4.tsx +157 -0
  75. package/tests/test-app/src/pages/back-end/adminRootLayout5.tsx +157 -0
  76. package/tests/test-app/src/pages/back-end/adminRootLayout6.tsx +157 -0
  77. package/tests/test-app/src/pages/back-end/adminRootLayout7.tsx +157 -0
  78. package/tests/test-app/src/pages/back-end/adminRootLayout8.tsx +157 -0
  79. package/tests/test-app/src/pages/back-end/adminRootLayout9.tsx +157 -0
  80. package/tests/test-app/src/pages/back-end/backgroundManagementSystem.css +5 -0
  81. package/tests/test-app/src/pages/back-end/backgroundManagementSystem.tsx +1745 -0
  82. package/tests/test-app/src/pages/component/WorkOrderCard.tsx +140 -0
  83. package/tests/test-app/src/pages/cover.tsx +42 -0
  84. package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.css +181 -0
  85. package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.tsx +225 -0
  86. package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.css +181 -0
  87. package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.tsx +138 -0
  88. package/tests/test-app/src/pages/data_dashboard/component_library/BlueBrightGreenBorder.tsx +47 -0
  89. package/tests/test-app/src/pages/data_dashboard/component_library/FullScreenContainer.tsx +133 -0
  90. package/tests/test-app/src/pages/description_of_mock_interface.md +32 -0
  91. package/tests/test-app/src/pages/digitalLargeScreen.css +181 -0
  92. package/tests/test-app/src/pages/digitalLargeScreen.tsx +1417 -0
  93. package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.css +3 -0
  94. package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.tsx +362 -0
  95. package/tests/test-app/src/pages/mobile_terminal/WorkOrderHomepage.tsx +337 -0
  96. package/tests/test-app/src/pages/mobile_terminal/newWorkOrder.tsx +224 -0
  97. package/tests/test-app/src/pages/mobile_terminal/tabbar.tsx +67 -0
  98. package/tests/test-app/src/pages/mobile_terminal/uiHandsOnPractice.tsx +638 -0
  99. package/tests/test-app/src/pages/mobile_terminal/workOrderDetails.tsx +346 -0
  100. package/tests/test-app/src/pages/mobile_terminal/workOrderPage.tsx +345 -0
  101. package/tests/test-app/src/pages/testPage.css +3 -0
  102. package/tests/test-app/src/pages/testPage.tsx +158 -0
  103. package/tests/test-app/src/pages/web_version/website.css +205 -0
  104. package/tests/test-app/src/pages/web_version/website.tsx +1066 -0
  105. package/tests/test-app/src/pages//345/276/205/345/212/236.apidoc.json +336 -0
  106. package/tests/test-app/src/project.json +1120 -0
  107. package/tests/test-app/src/store/global.store.ts +10 -0
  108. package/tests/test-app/src/types/CreateTicketParams.m.ts +20 -0
  109. package/tests/test-app/src/types/SLAPolicy.ts +50 -0
  110. package/tests/test-app/src/types/Ticket.ts +68 -0
  111. package/tests/test-app/src/types/TicketAttachment.m.ts +67 -0
  112. package/tests/test-app/src/types/TicketComment.m.ts +59 -0
  113. package/tests/test-app/src/types/TicketEvaluation.ts +44 -0
  114. package/tests/test-app/src/types/TicketHistory.m.ts +71 -0
  115. package/tests/test-app/src/types/TicketListParams.m.ts +30 -0
  116. package/tests/test-app/src/types/TicketPriority.m.ts +65 -0
  117. package/tests/test-app/src/types/TicketRecord.ts +47 -0
  118. package/tests/test-app/src/types/TrainDoor.ts +284 -0
  119. package/tests/test-app/src/types/UpdateTicketParams.m.ts +22 -0
  120. package/tests/test-app/src/utils/__afterRequest.util.ts +3 -0
  121. package/tests/test-app/src/utils/__beforeRequest.util.ts +10 -0
  122. package/tests/test-app/src/utils/testGlobalAction.util.ts +7 -0
package/dist/index.js CHANGED
@@ -2805,36 +2805,29 @@ browser$1.destroy;
2805
2805
  browser$1.colors;
2806
2806
  browser$1.log;
2807
2807
 
2808
- var hasFlag = (flag, argv = process.argv) => {
2808
+ var hasFlag = (flag, argv) => {
2809
+ argv = argv || process.argv;
2809
2810
  const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
2810
- const position = argv.indexOf(prefix + flag);
2811
- const terminatorPosition = argv.indexOf('--');
2812
- return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
2811
+ const pos = argv.indexOf(prefix + flag);
2812
+ const terminatorPos = argv.indexOf('--');
2813
+ return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
2813
2814
  };
2814
2815
 
2815
- const {env} = process;
2816
+ const env = process.env;
2816
2817
 
2817
2818
  let forceColor;
2818
2819
  if (hasFlag('no-color') ||
2819
2820
  hasFlag('no-colors') ||
2820
- hasFlag('color=false') ||
2821
- hasFlag('color=never')) {
2822
- forceColor = 0;
2821
+ hasFlag('color=false')) {
2822
+ forceColor = false;
2823
2823
  } else if (hasFlag('color') ||
2824
2824
  hasFlag('colors') ||
2825
2825
  hasFlag('color=true') ||
2826
2826
  hasFlag('color=always')) {
2827
- forceColor = 1;
2827
+ forceColor = true;
2828
2828
  }
2829
-
2830
2829
  if ('FORCE_COLOR' in env) {
2831
- if (env.FORCE_COLOR === 'true') {
2832
- forceColor = 1;
2833
- } else if (env.FORCE_COLOR === 'false') {
2834
- forceColor = 0;
2835
- } else {
2836
- forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
2837
- }
2830
+ forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
2838
2831
  }
2839
2832
 
2840
2833
  function translateLevel(level) {
@@ -2850,8 +2843,8 @@ function translateLevel(level) {
2850
2843
  };
2851
2844
  }
2852
2845
 
2853
- function supportsColor(haveStream, streamIsTTY) {
2854
- if (forceColor === 0) {
2846
+ function supportsColor(stream) {
2847
+ if (forceColor === false) {
2855
2848
  return 0;
2856
2849
  }
2857
2850
 
@@ -2865,21 +2858,22 @@ function supportsColor(haveStream, streamIsTTY) {
2865
2858
  return 2;
2866
2859
  }
2867
2860
 
2868
- if (haveStream && !streamIsTTY && forceColor === undefined) {
2861
+ if (stream && !stream.isTTY && forceColor !== true) {
2869
2862
  return 0;
2870
2863
  }
2871
2864
 
2872
- const min = forceColor || 0;
2873
-
2874
- if (env.TERM === 'dumb') {
2875
- return min;
2876
- }
2865
+ const min = forceColor ? 1 : 0;
2877
2866
 
2878
2867
  if (process.platform === 'win32') {
2879
- // Windows 10 build 10586 is the first Windows release that supports 256 colors.
2880
- // Windows 10 build 14931 is the first release that supports 16m/TrueColor.
2868
+ // Node.js 7.5.0 is the first version of Node.js to include a patch to
2869
+ // libuv that enables 256 color output on Windows. Anything earlier and it
2870
+ // won't work. However, here we target Node.js 8 at minimum as it is an LTS
2871
+ // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
2872
+ // release that supports 256 colors. Windows 10 build 14931 is the first release
2873
+ // that supports 16m/TrueColor.
2881
2874
  const osRelease = os__default["default"].release().split('.');
2882
2875
  if (
2876
+ Number(process.versions.node.split('.')[0]) >= 8 &&
2883
2877
  Number(osRelease[0]) >= 10 &&
2884
2878
  Number(osRelease[2]) >= 10586
2885
2879
  ) {
@@ -2890,7 +2884,7 @@ function supportsColor(haveStream, streamIsTTY) {
2890
2884
  }
2891
2885
 
2892
2886
  if ('CI' in env) {
2893
- if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
2887
+ if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
2894
2888
  return 1;
2895
2889
  }
2896
2890
 
@@ -2929,18 +2923,22 @@ function supportsColor(haveStream, streamIsTTY) {
2929
2923
  return 1;
2930
2924
  }
2931
2925
 
2926
+ if (env.TERM === 'dumb') {
2927
+ return min;
2928
+ }
2929
+
2932
2930
  return min;
2933
2931
  }
2934
2932
 
2935
2933
  function getSupportLevel(stream) {
2936
- const level = supportsColor(stream, stream && stream.isTTY);
2934
+ const level = supportsColor(stream);
2937
2935
  return translateLevel(level);
2938
2936
  }
2939
2937
 
2940
2938
  var supportsColor_1 = {
2941
2939
  supportsColor: getSupportLevel,
2942
- stdout: translateLevel(supportsColor(true, tty__default["default"].isatty(1))),
2943
- stderr: translateLevel(supportsColor(true, tty__default["default"].isatty(2)))
2940
+ stdout: getSupportLevel(process.stdout),
2941
+ stderr: getSupportLevel(process.stderr)
2944
2942
  };
2945
2943
  supportsColor_1.supportsColor;
2946
2944
  supportsColor_1.stdout;
@@ -17181,7 +17179,7 @@ FormData$2.prototype.submit = function (params, cb) {
17181
17179
  request.removeListener('error', callback);
17182
17180
  request.removeListener('response', onResponse);
17183
17181
 
17184
- return cb.call(this, error, responce); // eslint-disable-line no-invalid-this
17182
+ return cb.call(this, error, responce);
17185
17183
  };
17186
17184
 
17187
17185
  onResponse = callback.bind(this, null);
@@ -17205,7 +17203,7 @@ FormData$2.prototype._error = function (err) {
17205
17203
  FormData$2.prototype.toString = function () {
17206
17204
  return '[object FormData]';
17207
17205
  };
17208
- setToStringTag(FormData$2, 'FormData');
17206
+ setToStringTag(FormData$2.prototype, 'FormData');
17209
17207
 
17210
17208
  // Public API
17211
17209
  var form_data = FormData$2;
@@ -18821,7 +18819,7 @@ var request = function (url, params, _a) {
18821
18819
  };
18822
18820
  return [4 /*yield*/, axios({
18823
18821
  method: method,
18824
- url: (process.env.DEV ? 'http://127.0.0.1:1626' : 'https://editor.appthen.com') +
18822
+ url: (process.env.DEV ? 'http://127.0.0.1:1626' : 'https://api.appthen.com') +
18825
18823
  url,
18826
18824
  data: params,
18827
18825
  headers: headers,
@@ -37900,7 +37898,7 @@ function create(options) {
37900
37898
 
37901
37899
  var fuck = function () { };
37902
37900
 
37903
- var server = 'wss://editor.appthen.com';
37901
+ var server = 'wss://api.appthen.com';
37904
37902
  var devServer = 'ws://127.0.0.1:1626';
37905
37903
  var DEV_MODE$1 = process.env.DEV;
37906
37904
  var SocketStore = /** @class */ (function () {
@@ -37940,7 +37938,9 @@ var SocketStore = /** @class */ (function () {
37940
37938
  var _this = this;
37941
37939
  var _a = this.config, token = _a.token, onconnect = _a.onconnect, onlogined = _a.onlogined, onreconnect = _a.onreconnect; _a.onmsg;
37942
37940
  console.log('token: ', token);
37943
- var socket = io__default["default"](DEV_MODE$1 ? devServer : server, {
37941
+ var SOCKET_SERVER = DEV_MODE$1 ? devServer : server;
37942
+ console.log('SOCKET_SERVER: ', SOCKET_SERVER);
37943
+ var socket = io__default["default"](SOCKET_SERVER, {
37944
37944
  transports: ['websocket'],
37945
37945
  query: {
37946
37946
  token: token,
@@ -40667,7 +40667,13 @@ function regExpEscape (s) {
40667
40667
  return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
40668
40668
  }
40669
40669
 
40670
- var logger = function () { };
40670
+ var logger = function () {
40671
+ var args = [];
40672
+ for (var _i = 0; _i < arguments.length; _i++) {
40673
+ args[_i] = arguments[_i];
40674
+ }
40675
+ console.log.apply(console, __spreadArray([], __read(args), false));
40676
+ };
40671
40677
  /**
40672
40678
  * 影子空间管理器
40673
40679
  * 维护编辑器状态的本地镜像,用于检测文件变更
@@ -40949,6 +40955,7 @@ var ShadowSpace = /** @class */ (function () {
40949
40955
  return [4 /*yield*/, fs__default$1["default"].unlink(fullPath)];
40950
40956
  case 2:
40951
40957
  _a.sent();
40958
+ logger("\u672C\u5730\u6587\u4EF6\u5DF2\u5220\u9664: ".concat(fullPath));
40952
40959
  return [3 /*break*/, 4];
40953
40960
  case 3:
40954
40961
  error_1 = _a.sent();
@@ -40962,6 +40969,7 @@ var ShadowSpace = /** @class */ (function () {
40962
40969
  return [4 /*yield*/, this.saveState()];
40963
40970
  case 5:
40964
40971
  _a.sent();
40972
+ logger("\u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u5DF2\u5220\u9664: ".concat(filePath));
40965
40973
  return [2 /*return*/, true];
40966
40974
  }
40967
40975
  });
@@ -40973,33 +40981,33 @@ var ShadowSpace = /** @class */ (function () {
40973
40981
  */
40974
40982
  ShadowSpace.prototype.detectChanges = function () {
40975
40983
  return __awaiter(this, void 0, void 0, function () {
40976
- var changes, _a, _b, _c, filePath, shadowEntry, localFilePath, localContent, localHash, fileStat, fileModifyTime, shadowContent, _d, _e, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
40977
- var e_3, _f, _g, e_4, _h;
40978
- return __generator(this, function (_j) {
40979
- switch (_j.label) {
40984
+ var changes, _a, _b, _c, filePath, shadowEntry, localFilePath, localContent, localHash, fileStat, fileModifyTime, shadowContent, _d, _e, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile, tempNormalizePath, addsFromRemote, addsFromLocal, _loop_1, addsFromRemote_1, addsFromRemote_1_1, remoteAdd;
40985
+ var e_3, _f, _g, e_4, _h, e_5, _j;
40986
+ return __generator(this, function (_k) {
40987
+ switch (_k.label) {
40980
40988
  case 0:
40981
40989
  changes = [];
40982
- _j.label = 1;
40990
+ _k.label = 1;
40983
40991
  case 1:
40984
- _j.trys.push([1, 16, 17, 18]);
40992
+ _k.trys.push([1, 16, 17, 18]);
40985
40993
  _a = __values(Object.entries(this.state.files)), _b = _a.next();
40986
- _j.label = 2;
40994
+ _k.label = 2;
40987
40995
  case 2:
40988
40996
  if (!!_b.done) return [3 /*break*/, 15];
40989
40997
  _c = __read(_b.value, 2), filePath = _c[0], shadowEntry = _c[1];
40990
40998
  localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
40991
- _j.label = 3;
40999
+ _k.label = 3;
40992
41000
  case 3:
40993
- _j.trys.push([3, 11, , 14]);
41001
+ _k.trys.push([3, 11, , 14]);
40994
41002
  return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
40995
41003
  case 4:
40996
- localContent = _j.sent();
41004
+ localContent = _k.sent();
40997
41005
  localHash = this.calculateHash(localContent);
40998
41006
  if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
40999
41007
  if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
41000
41008
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41001
41009
  case 5:
41002
- fileStat = _j.sent();
41010
+ fileStat = _k.sent();
41003
41011
  fileModifyTime = fileStat.mtimeMs;
41004
41012
  // logger(`[ShadowSpace] 🔍 更新文件时间戳: ${filePath}`, {
41005
41013
  // 旧lastModified: new Date(
@@ -41015,12 +41023,12 @@ var ShadowSpace = /** @class */ (function () {
41015
41023
  return [4 /*yield*/, this.saveState()];
41016
41024
  case 6:
41017
41025
  // 保存状态
41018
- _j.sent();
41026
+ _k.sent();
41019
41027
  // 🔥 跳过,不添加到 changes
41020
41028
  return [3 /*break*/, 14];
41021
41029
  case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
41022
41030
  case 8:
41023
- shadowContent = _j.sent();
41031
+ shadowContent = _k.sent();
41024
41032
  _e = (_d = changes).push;
41025
41033
  _g = {
41026
41034
  id: this.generateId(),
@@ -41030,21 +41038,21 @@ var ShadowSpace = /** @class */ (function () {
41030
41038
  };
41031
41039
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41032
41040
  case 9:
41033
- _e.apply(_d, [(_g.timestamp = (_j.sent()).mtime.getTime(),
41041
+ _e.apply(_d, [(_g.timestamp = (_k.sent()).mtime.getTime(),
41034
41042
  _g.diff = {
41035
41043
  before: shadowContent,
41036
41044
  after: localContent,
41037
41045
  },
41038
41046
  _g.projectId = this.state.projectId,
41039
41047
  _g)]);
41040
- _j.label = 10;
41048
+ _k.label = 10;
41041
41049
  case 10: return [3 /*break*/, 14];
41042
41050
  case 11:
41043
- error_2 = _j.sent();
41051
+ error_2 = _k.sent();
41044
41052
  if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
41045
41053
  return [4 /*yield*/, this.getShadowContent(filePath)];
41046
41054
  case 12:
41047
- shadowContent = _j.sent();
41055
+ shadowContent = _k.sent();
41048
41056
  changes.push({
41049
41057
  id: this.generateId(),
41050
41058
  action: 'delete',
@@ -41057,14 +41065,14 @@ var ShadowSpace = /** @class */ (function () {
41057
41065
  },
41058
41066
  projectId: this.state.projectId,
41059
41067
  });
41060
- _j.label = 13;
41068
+ _k.label = 13;
41061
41069
  case 13: return [3 /*break*/, 14];
41062
41070
  case 14:
41063
41071
  _b = _a.next();
41064
41072
  return [3 /*break*/, 2];
41065
41073
  case 15: return [3 /*break*/, 18];
41066
41074
  case 16:
41067
- e_3_1 = _j.sent();
41075
+ e_3_1 = _k.sent();
41068
41076
  e_3 = { error: e_3_1 };
41069
41077
  return [3 /*break*/, 18];
41070
41078
  case 17:
@@ -41075,7 +41083,7 @@ var ShadowSpace = /** @class */ (function () {
41075
41083
  return [7 /*endfinally*/];
41076
41084
  case 18: return [4 /*yield*/, this.scanLocalFiles()];
41077
41085
  case 19:
41078
- localFiles = _j.sent();
41086
+ localFiles = _k.sent();
41079
41087
  try {
41080
41088
  for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
41081
41089
  localFile = localFiles_1_1.value;
@@ -41102,6 +41110,53 @@ var ShadowSpace = /** @class */ (function () {
41102
41110
  }
41103
41111
  finally { if (e_4) throw e_4.error; }
41104
41112
  }
41113
+ tempNormalizePath = function (p) { return p.replace(/\\/g, '/'); };
41114
+ addsFromRemote = changes.filter(function (c) { return c.action === 'add' && c.side === 'editor'; });
41115
+ addsFromLocal = changes.filter(function (c) { return c.action === 'add' && c.side === 'space'; });
41116
+ _loop_1 = function (remoteAdd) {
41117
+ var localAdd = addsFromLocal.find(function (l) {
41118
+ return tempNormalizePath(l.path) === tempNormalizePath(remoteAdd.path);
41119
+ });
41120
+ if (localAdd) {
41121
+ // 发现双向 Add,说明 Map Key 匹配失败了,但路径标准化后是一样的
41122
+ console.error("[ShadowSpace] CRITICAL: Detected dual ADD for ".concat(remoteAdd.path, ". Merging to CONFLICT."));
41123
+ // 移除这两个 Add
41124
+ var indexR = changes.indexOf(remoteAdd);
41125
+ if (indexR > -1)
41126
+ changes.splice(indexR, 1);
41127
+ var indexL = changes.indexOf(localAdd);
41128
+ if (indexL > -1)
41129
+ changes.splice(indexL, 1);
41130
+ // 添加一个 Modify Conflict
41131
+ changes.push({
41132
+ action: 'modify',
41133
+ path: tempNormalizePath(remoteAdd.path),
41134
+ side: 'editor',
41135
+ sourceLabel: 'remote',
41136
+ targetLabel: 'local',
41137
+ // @ts-ignore
41138
+ editorHash: remoteAdd.editorHash,
41139
+ // @ts-ignore
41140
+ spaceHash: localAdd.spaceHash,
41141
+ conflict: true,
41142
+ // @ts-ignore
41143
+ debug: 'merged_dual_add',
41144
+ });
41145
+ }
41146
+ };
41147
+ try {
41148
+ for (addsFromRemote_1 = __values(addsFromRemote), addsFromRemote_1_1 = addsFromRemote_1.next(); !addsFromRemote_1_1.done; addsFromRemote_1_1 = addsFromRemote_1.next()) {
41149
+ remoteAdd = addsFromRemote_1_1.value;
41150
+ _loop_1(remoteAdd);
41151
+ }
41152
+ }
41153
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
41154
+ finally {
41155
+ try {
41156
+ if (addsFromRemote_1_1 && !addsFromRemote_1_1.done && (_j = addsFromRemote_1.return)) _j.call(addsFromRemote_1);
41157
+ }
41158
+ finally { if (e_5) throw e_5.error; }
41159
+ }
41105
41160
  return [2 /*return*/, changes];
41106
41161
  }
41107
41162
  });
@@ -41112,16 +41167,16 @@ var ShadowSpace = /** @class */ (function () {
41112
41167
  */
41113
41168
  ShadowSpace.prototype.applyChanges = function (changes) {
41114
41169
  return __awaiter(this, void 0, void 0, function () {
41115
- var changes_1, changes_1_1, change, _a, e_5_1;
41116
- var e_5, _b;
41170
+ var changes_1, changes_1_1, change, _a, e_6_1;
41171
+ var e_6, _b;
41117
41172
  return __generator(this, function (_c) {
41118
41173
  switch (_c.label) {
41119
41174
  case 0:
41120
- _c.trys.push([0, 9, 10, 11]);
41175
+ _c.trys.push([0, 10, 11, 12]);
41121
41176
  changes_1 = __values(changes), changes_1_1 = changes_1.next();
41122
41177
  _c.label = 1;
41123
41178
  case 1:
41124
- if (!!changes_1_1.done) return [3 /*break*/, 8];
41179
+ if (!!changes_1_1.done) return [3 /*break*/, 9];
41125
41180
  change = changes_1_1.value;
41126
41181
  _a = change.action;
41127
41182
  switch (_a) {
@@ -41136,26 +41191,27 @@ var ShadowSpace = /** @class */ (function () {
41136
41191
  case 3:
41137
41192
  _c.sent();
41138
41193
  _c.label = 4;
41139
- case 4: return [3 /*break*/, 7];
41194
+ case 4: return [3 /*break*/, 8];
41140
41195
  case 5: return [4 /*yield*/, this.deleteFile(change.path)];
41141
41196
  case 6:
41142
41197
  _c.sent();
41143
- return [3 /*break*/, 7];
41144
- case 7:
41198
+ return [3 /*break*/, 8];
41199
+ case 7: return [3 /*break*/, 8];
41200
+ case 8:
41145
41201
  changes_1_1 = changes_1.next();
41146
41202
  return [3 /*break*/, 1];
41147
- case 8: return [3 /*break*/, 11];
41148
- case 9:
41149
- e_5_1 = _c.sent();
41150
- e_5 = { error: e_5_1 };
41151
- return [3 /*break*/, 11];
41203
+ case 9: return [3 /*break*/, 12];
41152
41204
  case 10:
41205
+ e_6_1 = _c.sent();
41206
+ e_6 = { error: e_6_1 };
41207
+ return [3 /*break*/, 12];
41208
+ case 11:
41153
41209
  try {
41154
41210
  if (changes_1_1 && !changes_1_1.done && (_b = changes_1.return)) _b.call(changes_1);
41155
41211
  }
41156
- finally { if (e_5) throw e_5.error; }
41212
+ finally { if (e_6) throw e_6.error; }
41157
41213
  return [7 /*endfinally*/];
41158
- case 11:
41214
+ case 12:
41159
41215
  logger("\u5F71\u5B50\u7A7A\u95F4\u5DF2\u5E94\u7528 ".concat(changes.length, " \u4E2A\u53D8\u66F4"));
41160
41216
  return [2 /*return*/];
41161
41217
  }
@@ -41203,6 +41259,7 @@ var ShadowSpace = /** @class */ (function () {
41203
41259
  case 0:
41204
41260
  // 检查文件是否在影子空间中
41205
41261
  if (!this.hasFile(filePath)) {
41262
+ logger("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u5F71\u5B50\u7A7A\u95F4\u4E2D: ".concat(filePath));
41206
41263
  return [2 /*return*/, null];
41207
41264
  }
41208
41265
  _a.label = 1;
@@ -41260,8 +41317,8 @@ var ShadowSpace = /** @class */ (function () {
41260
41317
  */
41261
41318
  ShadowSpace.prototype.markAsRemoteModified = function (filePaths) {
41262
41319
  return __awaiter(this, void 0, void 0, function () {
41263
- var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_5, e_6_1;
41264
- var e_6, _a;
41320
+ var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_5, e_7_1;
41321
+ var e_7, _a;
41265
41322
  return __generator(this, function (_b) {
41266
41323
  switch (_b.label) {
41267
41324
  case 0:
@@ -41311,14 +41368,14 @@ var ShadowSpace = /** @class */ (function () {
41311
41368
  return [3 /*break*/, 2];
41312
41369
  case 8: return [3 /*break*/, 11];
41313
41370
  case 9:
41314
- e_6_1 = _b.sent();
41315
- e_6 = { error: e_6_1 };
41371
+ e_7_1 = _b.sent();
41372
+ e_7 = { error: e_7_1 };
41316
41373
  return [3 /*break*/, 11];
41317
41374
  case 10:
41318
41375
  try {
41319
41376
  if (filePaths_1_1 && !filePaths_1_1.done && (_a = filePaths_1.return)) _a.call(filePaths_1);
41320
41377
  }
41321
- finally { if (e_6) throw e_6.error; }
41378
+ finally { if (e_7) throw e_7.error; }
41322
41379
  return [7 /*endfinally*/];
41323
41380
  case 11:
41324
41381
  if (!hasChanges) return [3 /*break*/, 13];
@@ -41340,7 +41397,7 @@ var ShadowSpace = /** @class */ (function () {
41340
41397
  var _a;
41341
41398
  return __awaiter(this, void 0, void 0, function () {
41342
41399
  var hasChanges, pathsToProcess, pathsToProcess_1, pathsToProcess_1_1, filePath;
41343
- var e_7, _b;
41400
+ var e_8, _b;
41344
41401
  return __generator(this, function (_c) {
41345
41402
  switch (_c.label) {
41346
41403
  case 0:
@@ -41356,12 +41413,12 @@ var ShadowSpace = /** @class */ (function () {
41356
41413
  }
41357
41414
  }
41358
41415
  }
41359
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
41416
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
41360
41417
  finally {
41361
41418
  try {
41362
41419
  if (pathsToProcess_1_1 && !pathsToProcess_1_1.done && (_b = pathsToProcess_1.return)) _b.call(pathsToProcess_1);
41363
41420
  }
41364
- finally { if (e_7) throw e_7.error; }
41421
+ finally { if (e_8) throw e_8.error; }
41365
41422
  }
41366
41423
  if (!hasChanges) return [3 /*break*/, 2];
41367
41424
  return [4 /*yield*/, this.saveState()];
@@ -41381,7 +41438,7 @@ var ShadowSpace = /** @class */ (function () {
41381
41438
  ShadowSpace.prototype.getSpaceSnapshots = function (_spaceId) {
41382
41439
  return __awaiter(this, void 0, void 0, function () {
41383
41440
  var snapshots, _a, _b, _c, filePath, shadowEntry, modifyTime, error_6;
41384
- var e_8, _d;
41441
+ var e_9, _d;
41385
41442
  return __generator(this, function (_e) {
41386
41443
  switch (_e.label) {
41387
41444
  case 0:
@@ -41411,12 +41468,12 @@ var ShadowSpace = /** @class */ (function () {
41411
41468
  });
41412
41469
  }
41413
41470
  }
41414
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
41471
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
41415
41472
  finally {
41416
41473
  try {
41417
41474
  if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
41418
41475
  }
41419
- finally { if (e_8) throw e_8.error; }
41476
+ finally { if (e_9) throw e_9.error; }
41420
41477
  }
41421
41478
  logger("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167: ".concat(snapshots.length, " \u4E2A\u6587\u4EF6"));
41422
41479
  return [2 /*return*/, snapshots];
@@ -41455,6 +41512,633 @@ var ShadowSpace = /** @class */ (function () {
41455
41512
  });
41456
41513
  });
41457
41514
  };
41515
+ /**
41516
+ * 独立同步:获取远端文件快照
41517
+ */
41518
+ ShadowSpace.prototype.fetchRemoteSnapshot = function () {
41519
+ var _a, _b, _c, _d, _e, _f;
41520
+ return __awaiter(this, void 0, void 0, function () {
41521
+ var requestParams, response, files, snapshot_1, processNode_1, error_8;
41522
+ var _this = this;
41523
+ return __generator(this, function (_g) {
41524
+ switch (_g.label) {
41525
+ case 0:
41526
+ _g.trys.push([0, 2, , 3]);
41527
+ requestParams = {
41528
+ projectId: this.config.projectId,
41529
+ path: '/',
41530
+ options: {
41531
+ recursive: true,
41532
+ includeTypeEntity: false,
41533
+ },
41534
+ };
41535
+ logger('[ShadowSpace] 开始获取远端快照...', requestParams);
41536
+ return [4 /*yield*/, request('/editor/vfs/readdir', requestParams)];
41537
+ case 1:
41538
+ response = _g.sent();
41539
+ // Log response structure for debugging
41540
+ logger('[ShadowSpace] 远端响应数据结构:', {
41541
+ type: typeof response.data,
41542
+ isSuccess: (_a = response.data) === null || _a === void 0 ? void 0 : _a.success,
41543
+ dataType: typeof ((_b = response.data) === null || _b === void 0 ? void 0 : _b.data),
41544
+ isArray: Array.isArray((_c = response.data) === null || _c === void 0 ? void 0 : _c.data),
41545
+ dataKeys: ((_d = response.data) === null || _d === void 0 ? void 0 : _d.data) ? Object.keys(response.data.data) : [],
41546
+ });
41547
+ if (!((_e = response.data) === null || _e === void 0 ? void 0 : _e.success)) {
41548
+ throw new Error(((_f = response.data) === null || _f === void 0 ? void 0 : _f.message) || 'Failed to fetch remote snapshot');
41549
+ }
41550
+ files = response.data.data;
41551
+ if (!Array.isArray(files)) {
41552
+ // If it's an object with a children property (common file system tree structure)
41553
+ if (files && Array.isArray(files.children)) {
41554
+ files = files.children;
41555
+ }
41556
+ else if (files && Array.isArray(files.entries)) {
41557
+ // Fix: Support entries array
41558
+ files = files.entries;
41559
+ }
41560
+ else if (files && typeof files === 'object') {
41561
+ // If it's a map/object structure, try to convert values to array or wrap single object
41562
+ files = [files];
41563
+ }
41564
+ else {
41565
+ logger('[ShadowSpace] 警告: 远端返回的数据不是数组', files);
41566
+ files = [];
41567
+ }
41568
+ }
41569
+ snapshot_1 = [];
41570
+ processNode_1 = function (node) {
41571
+ if (!node)
41572
+ return;
41573
+ // Try to normalize node structure
41574
+ // If node has 'stats', use it. Otherwise, node itself might be stats or metadata.
41575
+ // Based on user provided example:
41576
+ // { "path": "...", "stats": { "type": "file", "contentHash": "..." } }
41577
+ var stats = node.stats || node;
41578
+ var type = stats.type || node.type;
41579
+ var filePath = node.path || stats.path;
41580
+ if (type === 'file') {
41581
+ // 去除开头的 /
41582
+ var relativePath = filePath;
41583
+ if (relativePath.startsWith('/')) {
41584
+ relativePath = relativePath.slice(1);
41585
+ }
41586
+ // 🔥 调试:打印原始路径和标准化后的路径
41587
+ if (relativePath.includes('TicketHistory') ||
41588
+ filePath.includes('TicketHistory')) {
41589
+ logger("[ShadowSpace] Path Normalization: \"".concat(filePath, "\" -> \"").concat(relativePath, "\""));
41590
+ }
41591
+ // 忽略文件
41592
+ if (_this.shouldIgnoreFile(relativePath)) {
41593
+ return;
41594
+ }
41595
+ snapshot_1.push({
41596
+ path: relativePath,
41597
+ hash: stats.contentHash || '',
41598
+ modify: stats.modifyTime || 0,
41599
+ size: stats.size || 0,
41600
+ });
41601
+ }
41602
+ // Handle recursive directory structure if present
41603
+ if (node.children && Array.isArray(node.children)) {
41604
+ node.children.forEach(processNode_1);
41605
+ }
41606
+ };
41607
+ files.forEach(processNode_1);
41608
+ logger("[ShadowSpace] \u83B7\u53D6\u5230 ".concat(snapshot_1.length, " \u4E2A\u8FDC\u7AEF\u6587\u4EF6"));
41609
+ return [2 /*return*/, snapshot_1];
41610
+ case 2:
41611
+ error_8 = _g.sent();
41612
+ console.error('[ShadowSpace] 获取远端快照失败:', error_8);
41613
+ if (error_8.response) {
41614
+ console.error('[ShadowSpace] 远端响应详情:', {
41615
+ status: error_8.response.status,
41616
+ statusText: error_8.response.statusText,
41617
+ data: error_8.response.data,
41618
+ headers: error_8.response.headers,
41619
+ });
41620
+ }
41621
+ throw error_8;
41622
+ case 3: return [2 /*return*/];
41623
+ }
41624
+ });
41625
+ });
41626
+ };
41627
+ /**
41628
+ * 独立同步:下载远端文件
41629
+ */
41630
+ ShadowSpace.prototype.downloadRemoteFile = function (filePath) {
41631
+ var _a, _b;
41632
+ return __awaiter(this, void 0, void 0, function () {
41633
+ var remotePath, response, error_9;
41634
+ return __generator(this, function (_c) {
41635
+ switch (_c.label) {
41636
+ case 0:
41637
+ _c.trys.push([0, 2, , 3]);
41638
+ remotePath = filePath.startsWith('/') ? filePath : '/' + filePath;
41639
+ return [4 /*yield*/, request('/editor/vfs/read', {
41640
+ projectId: this.config.projectId,
41641
+ path: remotePath,
41642
+ isCodeMode: true,
41643
+ })];
41644
+ case 1:
41645
+ response = _c.sent();
41646
+ if (!((_a = response.data) === null || _a === void 0 ? void 0 : _a.success)) {
41647
+ throw new Error(((_b = response.data) === null || _b === void 0 ? void 0 : _b.message) || "Failed to download file: ".concat(filePath));
41648
+ }
41649
+ return [2 /*return*/, response.data.data.content];
41650
+ case 2:
41651
+ error_9 = _c.sent();
41652
+ console.error("[ShadowSpace] \u4E0B\u8F7D\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_9);
41653
+ throw error_9;
41654
+ case 3: return [2 /*return*/];
41655
+ }
41656
+ });
41657
+ });
41658
+ };
41659
+ /**
41660
+ * 独立同步:上传本地文件
41661
+ */
41662
+ ShadowSpace.prototype.uploadLocalFile = function (filePath, content) {
41663
+ var _a, _b;
41664
+ return __awaiter(this, void 0, void 0, function () {
41665
+ var remotePath, response, error_10;
41666
+ return __generator(this, function (_c) {
41667
+ switch (_c.label) {
41668
+ case 0:
41669
+ _c.trys.push([0, 2, , 3]);
41670
+ remotePath = filePath.startsWith('/') ? filePath : '/' + filePath;
41671
+ return [4 /*yield*/, request('/editor/vfs/write', {
41672
+ projectId: this.config.projectId,
41673
+ path: remotePath,
41674
+ content: content,
41675
+ options: {
41676
+ writeMode: 'code',
41677
+ skipValidation: true,
41678
+ },
41679
+ })];
41680
+ case 1:
41681
+ response = _c.sent();
41682
+ if (!((_a = response.data) === null || _a === void 0 ? void 0 : _a.success)) {
41683
+ throw new Error(((_b = response.data) === null || _b === void 0 ? void 0 : _b.message) || "Failed to upload file: ".concat(filePath));
41684
+ }
41685
+ return [3 /*break*/, 3];
41686
+ case 2:
41687
+ error_10 = _c.sent();
41688
+ console.error("[ShadowSpace] \u4E0A\u4F20\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_10);
41689
+ throw error_10;
41690
+ case 3: return [2 /*return*/];
41691
+ }
41692
+ });
41693
+ });
41694
+ };
41695
+ /**
41696
+ * 比对快照,生成变更列表
41697
+ * (从 ShadowSpaceCommandHandler 移动而来,核心比对逻辑)
41698
+ */
41699
+ ShadowSpace.prototype.compareSnapshots = function (remoteSnapshots, localSnapshots) {
41700
+ var e_10, _a, e_11, _b;
41701
+ var changes = [];
41702
+ // 标准化路径工具函数
41703
+ var normalizePath = function (p) {
41704
+ // 统一替换反斜杠为正斜杠
41705
+ var normalized = p.replace(/\\/g, '/');
41706
+ // 去除开头的 ./
41707
+ if (normalized.startsWith('./'))
41708
+ normalized = normalized.substring(2);
41709
+ // 去除开头的 /
41710
+ if (normalized.startsWith('/'))
41711
+ normalized = normalized.substring(1);
41712
+ return normalized;
41713
+ };
41714
+ // 确保输入参数是数组
41715
+ var safeRemoteSnapshots = Array.isArray(remoteSnapshots)
41716
+ ? remoteSnapshots
41717
+ : [];
41718
+ var safeLocalSnapshots = Array.isArray(localSnapshots)
41719
+ ? localSnapshots
41720
+ : [];
41721
+ // 构建映射表 (强制标准化 key)
41722
+ var remoteMap = new Map(safeRemoteSnapshots.map(function (f) { return [normalizePath(f.path), f]; }));
41723
+ var localMap = new Map(safeLocalSnapshots.map(function (f) { return [normalizePath(f.path), f]; }));
41724
+ var remoteKeys = Array.from(remoteMap.keys());
41725
+ var localKeys = Array.from(localMap.keys());
41726
+ var remoteKey = remoteKeys.find(function (k) { return k.includes('__afterRequest'); });
41727
+ var localKey = localKeys.find(function (k) { return k.includes('__afterRequest'); });
41728
+ if (remoteKey || localKey) {
41729
+ logger('[ShadowSpace] CharCodes Debug:', {
41730
+ remoteKey: remoteKey,
41731
+ remoteCodes: remoteKey
41732
+ ? Array.from(remoteKey).map(function (c) { return c.charCodeAt(0); })
41733
+ : null,
41734
+ localKey: localKey,
41735
+ localCodes: localKey
41736
+ ? Array.from(localKey).map(function (c) { return c.charCodeAt(0); })
41737
+ : null,
41738
+ isEqual: remoteKey === localKey,
41739
+ });
41740
+ }
41741
+ logger('[ShadowSpace] 比对文件列表 (Normalized):', {
41742
+ remoteCount: remoteMap.size,
41743
+ localCount: localMap.size,
41744
+ remoteFiles: Array.from(remoteMap.keys()),
41745
+ localFiles: Array.from(localMap.keys()),
41746
+ });
41747
+ // 1. 检测远端的变更(相对于本地)
41748
+ // 遍历远端文件
41749
+ console.log('localMap: ', localMap.keys());
41750
+ var _loop_2 = function (filePath, remoteFile) {
41751
+ var localFile = localMap.get(filePath);
41752
+ if (!localFile) {
41753
+ console.log('filePath: ', filePath, filePath.length, filePath.startsWith(' '));
41754
+ // 本地缺失 -> 需要从远端拉取 (Pull)
41755
+ logger("[ShadowSpace] \u53D1\u73B0\u672C\u5730\u7F3A\u5931: ".concat(filePath, " (Add to Local)"));
41756
+ changes.push({
41757
+ action: 'add',
41758
+ path: filePath,
41759
+ side: 'editor',
41760
+ sourceLabel: 'remote',
41761
+ targetLabel: 'local',
41762
+ editorHash: remoteFile.hash,
41763
+ spaceHash: null,
41764
+ });
41765
+ }
41766
+ else if (remoteFile.hash !== localFile.hash) {
41767
+ // Hash 不同,需要判断谁是最新版本
41768
+ var remoteModify = remoteFile.modify || 0;
41769
+ var localModify = localFile.modify || 0;
41770
+ logger("[ShadowSpace] \u53D1\u73B0\u53D8\u66F4: ".concat(filePath), {
41771
+ remoteHash: remoteFile.hash,
41772
+ localHash: localFile.hash,
41773
+ remoteModify: remoteModify,
41774
+ localModify: localModify,
41775
+ diff: remoteModify - localModify,
41776
+ });
41777
+ // 如果远端哈希与本地记录的"上次远端哈希"不同,说明远端更新了
41778
+ // const remoteChanged = remoteFile.hash !== localFile.remoteHash;
41779
+ // 如果本地哈希与本地记录的"上次远端哈希"不同,说明本地更新了 (注意:localFile.hash 是当前本地hash)
41780
+ // 实际上 localFile.remoteHash 是上次同步时的远端hash
41781
+ // 如果 localFile.hash != localFile.remoteHash,说明本地有修改
41782
+ // 简单策略:基于时间戳 (或者后续基于 remoteHash 追踪)
41783
+ // 这里沿用 Handler 的时间戳逻辑
41784
+ if (remoteModify > localModify) {
41785
+ // 远端更新 -> 拉取
41786
+ changes.push({
41787
+ action: 'modify',
41788
+ path: filePath,
41789
+ side: 'editor',
41790
+ sourceLabel: 'remote',
41791
+ targetLabel: 'local',
41792
+ editorHash: remoteFile.hash,
41793
+ spaceHash: localFile.hash,
41794
+ });
41795
+ }
41796
+ else if (localModify > remoteModify) {
41797
+ // 本地更新 -> 推送
41798
+ changes.push({
41799
+ action: 'modify',
41800
+ path: filePath,
41801
+ side: 'space',
41802
+ sourceLabel: 'local',
41803
+ targetLabel: 'remote',
41804
+ editorHash: remoteFile.hash,
41805
+ spaceHash: localFile.hash,
41806
+ });
41807
+ }
41808
+ else {
41809
+ // 时间戳相同但哈希不同?冲突,默认拉取远端
41810
+ // 只有当两者都没被放入changes时才放入,避免重复
41811
+ var existingChange = changes.find(function (c) { return c.path === filePath; });
41812
+ if (!existingChange) {
41813
+ changes.push({
41814
+ action: 'modify',
41815
+ path: filePath,
41816
+ side: 'editor',
41817
+ sourceLabel: 'remote',
41818
+ targetLabel: 'local',
41819
+ editorHash: remoteFile.hash,
41820
+ spaceHash: localFile.hash,
41821
+ conflict: true,
41822
+ });
41823
+ }
41824
+ }
41825
+ }
41826
+ };
41827
+ try {
41828
+ for (var remoteMap_1 = __values(remoteMap), remoteMap_1_1 = remoteMap_1.next(); !remoteMap_1_1.done; remoteMap_1_1 = remoteMap_1.next()) {
41829
+ var _c = __read(remoteMap_1_1.value, 2), filePath = _c[0], remoteFile = _c[1];
41830
+ _loop_2(filePath, remoteFile);
41831
+ }
41832
+ }
41833
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
41834
+ finally {
41835
+ try {
41836
+ if (remoteMap_1_1 && !remoteMap_1_1.done && (_a = remoteMap_1.return)) _a.call(remoteMap_1);
41837
+ }
41838
+ finally { if (e_10) throw e_10.error; }
41839
+ }
41840
+ try {
41841
+ // 2. 检测本地的新增/删除 (相对于远端)
41842
+ for (var localMap_1 = __values(localMap), localMap_1_1 = localMap_1.next(); !localMap_1_1.done; localMap_1_1 = localMap_1.next()) {
41843
+ var _d = __read(localMap_1_1.value, 2), filePath = _d[0], localFile = _d[1];
41844
+ var remoteFile = remoteMap.get(filePath);
41845
+ if (remoteFile) {
41846
+ // 远端存在,已经在上面处理过了 (Hash不同或相同)
41847
+ // 除非我们要处理元数据更新等,否则跳过
41848
+ continue;
41849
+ }
41850
+ if (!remoteFile) {
41851
+ // 远端不存在
41852
+ // 如果本地文件有 remoteHash 且不为空,说明之前存在于远端 -> 远端删除了 -> 本地也删除 (Pull)
41853
+ if (localFile.remoteHash) {
41854
+ logger("[ShadowSpace] \u53D1\u73B0\u8FDC\u7AEF\u5220\u9664: ".concat(filePath, " (Delete Local)"));
41855
+ changes.push({
41856
+ action: 'delete',
41857
+ path: filePath,
41858
+ side: 'editor',
41859
+ sourceLabel: 'remote',
41860
+ targetLabel: 'local',
41861
+ editorHash: null,
41862
+ spaceHash: localFile.hash,
41863
+ });
41864
+ }
41865
+ else {
41866
+ // 本地新增 -> 推送到远端 (Push)
41867
+ logger("[ShadowSpace] \u53D1\u73B0\u672C\u5730\u65B0\u589E: ".concat(filePath, " (Push to Remote)"));
41868
+ changes.push({
41869
+ action: 'add',
41870
+ path: filePath,
41871
+ side: 'space',
41872
+ sourceLabel: 'local',
41873
+ targetLabel: 'remote',
41874
+ editorHash: null,
41875
+ spaceHash: localFile.hash,
41876
+ });
41877
+ }
41878
+ }
41879
+ }
41880
+ }
41881
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
41882
+ finally {
41883
+ try {
41884
+ if (localMap_1_1 && !localMap_1_1.done && (_b = localMap_1.return)) _b.call(localMap_1);
41885
+ }
41886
+ finally { if (e_11) throw e_11.error; }
41887
+ }
41888
+ return changes;
41889
+ };
41890
+ /**
41891
+ * 独立同步:执行完整同步
41892
+ */
41893
+ ShadowSpace.prototype.syncWithRemote = function (options) {
41894
+ if (options === void 0) { options = {}; }
41895
+ return __awaiter(this, void 0, void 0, function () {
41896
+ var remoteSnapshot, localSnapshot, changes, result, changes_2, changes_2_1, change, content, remoteHash, content, err_1, e_12_1;
41897
+ var e_12, _a;
41898
+ return __generator(this, function (_b) {
41899
+ switch (_b.label) {
41900
+ case 0: return [4 /*yield*/, this.fetchRemoteSnapshot()];
41901
+ case 1:
41902
+ remoteSnapshot = _b.sent();
41903
+ if (!(Object.keys(this.state.files).length === 0)) return [3 /*break*/, 3];
41904
+ return [4 /*yield*/, this.syncLocalState()];
41905
+ case 2:
41906
+ _b.sent();
41907
+ _b.label = 3;
41908
+ case 3: return [4 /*yield*/, this.getSpaceSnapshots()];
41909
+ case 4:
41910
+ localSnapshot = _b.sent();
41911
+ changes = this.compareSnapshots(remoteSnapshot, localSnapshot);
41912
+ result = {
41913
+ changes: changes,
41914
+ summary: {
41915
+ total: changes.length,
41916
+ pull: changes.filter(function (c) { return c.side === 'editor'; }).length,
41917
+ push: changes.filter(function (c) { return c.side === 'space'; }).length,
41918
+ },
41919
+ };
41920
+ if (options.dryRun || !options.autoApply) {
41921
+ return [2 /*return*/, result];
41922
+ }
41923
+ _b.label = 5;
41924
+ case 5:
41925
+ _b.trys.push([5, 22, 23, 24]);
41926
+ changes_2 = __values(changes), changes_2_1 = changes_2.next();
41927
+ _b.label = 6;
41928
+ case 6:
41929
+ if (!!changes_2_1.done) return [3 /*break*/, 21];
41930
+ change = changes_2_1.value;
41931
+ _b.label = 7;
41932
+ case 7:
41933
+ _b.trys.push([7, 19, , 20]);
41934
+ if (!(change.side === 'editor')) return [3 /*break*/, 15];
41935
+ if (!(change.action === 'delete')) return [3 /*break*/, 9];
41936
+ return [4 /*yield*/, this.deleteFile(change.path)];
41937
+ case 8:
41938
+ _b.sent();
41939
+ return [3 /*break*/, 14];
41940
+ case 9: return [4 /*yield*/, this.downloadRemoteFile(change.path)];
41941
+ case 10:
41942
+ content = _b.sent();
41943
+ remoteHash = change.editorHash;
41944
+ if (!remoteHash) return [3 /*break*/, 12];
41945
+ return [4 /*yield*/, this.updateFileFromRemote(change.path, content, remoteHash)];
41946
+ case 11:
41947
+ _b.sent();
41948
+ return [3 /*break*/, 14];
41949
+ case 12:
41950
+ // 如果没有 remoteHash (理论上不应该),回退到普通 update
41951
+ return [4 /*yield*/, this.updateFile(change.path, content)];
41952
+ case 13:
41953
+ // 如果没有 remoteHash (理论上不应该),回退到普通 update
41954
+ _b.sent();
41955
+ _b.label = 14;
41956
+ case 14: return [3 /*break*/, 18];
41957
+ case 15:
41958
+ if (!(change.action === 'add' || change.action === 'modify')) return [3 /*break*/, 18];
41959
+ return [4 /*yield*/, this.getShadowContent(change.path)];
41960
+ case 16:
41961
+ content = _b.sent();
41962
+ if (!content) return [3 /*break*/, 18];
41963
+ return [4 /*yield*/, this.uploadLocalFile(change.path, content)];
41964
+ case 17:
41965
+ _b.sent();
41966
+ // 更新状态
41967
+ if (this.state.files[change.path]) {
41968
+ // Push 成功后,远端 Hash 应该等于本地 Hash
41969
+ this.state.files[change.path].remoteHash =
41970
+ this.state.files[change.path].hash;
41971
+ }
41972
+ _b.label = 18;
41973
+ case 18: return [3 /*break*/, 20];
41974
+ case 19:
41975
+ err_1 = _b.sent();
41976
+ console.error("Failed to apply change for ".concat(change.path), err_1);
41977
+ return [3 /*break*/, 20];
41978
+ case 20:
41979
+ changes_2_1 = changes_2.next();
41980
+ return [3 /*break*/, 6];
41981
+ case 21: return [3 /*break*/, 24];
41982
+ case 22:
41983
+ e_12_1 = _b.sent();
41984
+ e_12 = { error: e_12_1 };
41985
+ return [3 /*break*/, 24];
41986
+ case 23:
41987
+ try {
41988
+ if (changes_2_1 && !changes_2_1.done && (_a = changes_2.return)) _a.call(changes_2);
41989
+ }
41990
+ finally { if (e_12) throw e_12.error; }
41991
+ return [7 /*endfinally*/];
41992
+ case 24: return [4 /*yield*/, this.saveState()];
41993
+ case 25:
41994
+ _b.sent();
41995
+ return [2 /*return*/, result];
41996
+ }
41997
+ });
41998
+ });
41999
+ };
42000
+ /**
42001
+ * 🆕 从远端更新文件(正确维护 remoteHash)
42002
+ */
42003
+ ShadowSpace.prototype.updateFileFromRemote = function (filePath, content, remoteHash) {
42004
+ return __awaiter(this, void 0, void 0, function () {
42005
+ var localHash, size, now, currentEntry;
42006
+ return __generator(this, function (_a) {
42007
+ switch (_a.label) {
42008
+ case 0:
42009
+ if (this.shouldIgnoreFile(filePath)) {
42010
+ return [2 /*return*/, false];
42011
+ }
42012
+ // 1. 写入本地文件
42013
+ return [4 /*yield*/, this.writeLocalFile(filePath, content)];
42014
+ case 1:
42015
+ // 1. 写入本地文件
42016
+ _a.sent();
42017
+ localHash = this.calculateHash(content);
42018
+ size = Buffer.byteLength(content, 'utf8');
42019
+ now = Date.now();
42020
+ currentEntry = this.state.files[filePath];
42021
+ this.state.files[filePath] = {
42022
+ path: filePath,
42023
+ hash: localHash,
42024
+ remoteHash: remoteHash,
42025
+ size: size,
42026
+ lastSyncTime: now,
42027
+ lastModified: now,
42028
+ version: currentEntry ? currentEntry.version + 1 : 1,
42029
+ mtime: now,
42030
+ remoteModified: false, // 已同步,清除标记
42031
+ };
42032
+ // 更新缓存
42033
+ this.contentCache.set(filePath, content);
42034
+ return [2 /*return*/, true];
42035
+ }
42036
+ });
42037
+ });
42038
+ };
42039
+ // ==================== 🆕 文件监听功能 ====================
42040
+ /**
42041
+ * 启动文件监听
42042
+ */
42043
+ ShadowSpace.prototype.startWatching = function () {
42044
+ var _this = this;
42045
+ if (this.isWatching) {
42046
+ logger('[ShadowSpace] 文件监听已经在运行中');
42047
+ return;
42048
+ }
42049
+ logger('[ShadowSpace] 启动文件监听...');
42050
+ logger('[ShadowSpace] 监听目录:', this.config.projectRoot);
42051
+ try {
42052
+ // 🔥 使用轮询模式 + ignored 函数过滤
42053
+ this.watcher = chokidar__default["default"].watch(this.config.projectRoot, {
42054
+ ignored: function (filePath) {
42055
+ var relativePath = path__default["default"].relative(_this.config.projectRoot, filePath);
42056
+ // 忽略根目录本身
42057
+ if (!relativePath || relativePath === '.') {
42058
+ return true;
42059
+ }
42060
+ // 使用白名单过滤
42061
+ return _this.shouldIgnoreFile(relativePath);
42062
+ },
42063
+ persistent: true,
42064
+ ignoreInitial: true,
42065
+ usePolling: true,
42066
+ interval: 2000,
42067
+ binaryInterval: 3000,
42068
+ depth: 99,
42069
+ awaitWriteFinish: {
42070
+ stabilityThreshold: 500,
42071
+ pollInterval: 100,
42072
+ },
42073
+ });
42074
+ logger('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
42075
+ }
42076
+ catch (error) {
42077
+ console.error('[ShadowSpace] 创建文件监听器失败:', error);
42078
+ }
42079
+ if (this.watcher) {
42080
+ this.watcher
42081
+ .on('change', function (filePath) {
42082
+ _this.onFileChanged(filePath);
42083
+ })
42084
+ .on('add', function (filePath) {
42085
+ _this.onFileAdded(filePath);
42086
+ })
42087
+ .on('unlink', function (filePath) {
42088
+ _this.onFileDeleted(filePath);
42089
+ })
42090
+ .on('error', function (error) {
42091
+ console.error('[ShadowSpace] 文件监听错误:', error);
42092
+ })
42093
+ .on('ready', function () {
42094
+ _this.isWatching = true;
42095
+ logger('[ShadowSpace] 文件监听已启动,正在监听:', _this.config.projectRoot);
42096
+ logger('[ShadowSpace] 监听配置: 轮询模式 (interval: 2s)');
42097
+ });
42098
+ }
42099
+ };
42100
+ /**
42101
+ * 停止文件监听
42102
+ */
42103
+ ShadowSpace.prototype.stopWatching = function () {
42104
+ return __awaiter(this, void 0, void 0, function () {
42105
+ return __generator(this, function (_a) {
42106
+ switch (_a.label) {
42107
+ case 0:
42108
+ if (!this.isWatching || !this.watcher) {
42109
+ logger('[ShadowSpace] 文件监听未运行');
42110
+ return [2 /*return*/];
42111
+ }
42112
+ logger('[ShadowSpace] 停止文件监听...');
42113
+ return [4 /*yield*/, this.watcher.close()];
42114
+ case 1:
42115
+ _a.sent();
42116
+ this.watcher = null;
42117
+ this.isWatching = false;
42118
+ logger('[ShadowSpace] 文件监听已停止');
42119
+ return [2 /*return*/];
42120
+ }
42121
+ });
42122
+ });
42123
+ };
42124
+ /**
42125
+ * 添加变更事件监听器
42126
+ */
42127
+ ShadowSpace.prototype.addChangeListener = function (listener) {
42128
+ this.changeListeners.add(listener);
42129
+ };
42130
+ /**
42131
+ * 移除变更事件监听器
42132
+ */
42133
+ ShadowSpace.prototype.removeChangeListener = function (listener) {
42134
+ this.changeListeners.delete(listener);
42135
+ };
42136
+ /**
42137
+ * 获取监听状态
42138
+ */
42139
+ ShadowSpace.prototype.isFileWatching = function () {
42140
+ return this.isWatching;
42141
+ };
41458
42142
  // ==================== 私有方法 ====================
41459
42143
  /**
41460
42144
  * 生成基于路径的唯一空间ID
@@ -41475,6 +42159,7 @@ var ShadowSpace = /** @class */ (function () {
41475
42159
  var dirName = path__default["default"].basename(absolutePath);
41476
42160
  // 组合生成空间ID: 目录名-路径hash
41477
42161
  var spaceId = "".concat(dirName, "-").concat(pathHash);
42162
+ logger("[ShadowSpace] \u751F\u6210\u7A7A\u95F4ID: ".concat(spaceId, " (\u8DEF\u5F84: ").concat(absolutePath, ")"));
41478
42163
  return spaceId;
41479
42164
  };
41480
42165
  /**
@@ -41482,7 +42167,7 @@ var ShadowSpace = /** @class */ (function () {
41482
42167
  */
41483
42168
  ShadowSpace.prototype.saveSpaceConfig = function () {
41484
42169
  return __awaiter(this, void 0, void 0, function () {
41485
- var configFile, config, error_8;
42170
+ var configFile, config, error_11;
41486
42171
  return __generator(this, function (_a) {
41487
42172
  switch (_a.label) {
41488
42173
  case 0:
@@ -41504,10 +42189,11 @@ var ShadowSpace = /** @class */ (function () {
41504
42189
  return [4 /*yield*/, fs__default$1["default"].writeFile(configFile, JSON.stringify(config, null, 2))];
41505
42190
  case 3:
41506
42191
  _a.sent();
42192
+ logger("[ShadowSpace] \u7A7A\u95F4\u914D\u7F6E\u5DF2\u4FDD\u5B58: ".concat(configFile));
41507
42193
  return [3 /*break*/, 5];
41508
42194
  case 4:
41509
- error_8 = _a.sent();
41510
- console.warn('[ShadowSpace] 保存空间配置失败:', error_8);
42195
+ error_11 = _a.sent();
42196
+ console.warn('[ShadowSpace] 保存空间配置失败:', error_11);
41511
42197
  return [3 /*break*/, 5];
41512
42198
  case 5: return [2 /*return*/];
41513
42199
  }
@@ -41519,14 +42205,15 @@ var ShadowSpace = /** @class */ (function () {
41519
42205
  */
41520
42206
  ShadowSpace.prototype.migrateOldStateFiles = function () {
41521
42207
  return __awaiter(this, void 0, void 0, function () {
41522
- var appthenDir, files, oldStateFiles, oldStateFiles_1, oldStateFiles_1_1, oldFile, oldFilePath, oldState, backupFile, e_9_1, error_9;
41523
- var e_9, _a;
42208
+ var appthenDir, files, oldStateFiles, oldStateFiles_1, oldStateFiles_1_1, oldFile, oldFilePath, oldState, backupFile, e_13_1, error_12;
42209
+ var e_13, _a;
41524
42210
  var _this = this;
41525
42211
  return __generator(this, function (_b) {
41526
42212
  switch (_b.label) {
41527
42213
  case 0:
41528
42214
  _b.trys.push([0, 12, , 13]);
41529
42215
  appthenDir = path__default["default"].join(this.config.projectRoot, '.appthen');
42216
+ logger("[ShadowSpace] \u68C0\u67E5\u8FC1\u79FB: ".concat(appthenDir));
41530
42217
  return [4 /*yield*/, fs__default$1["default"].readdir(appthenDir)];
41531
42218
  case 1:
41532
42219
  files = _b.sent();
@@ -41566,25 +42253,26 @@ var ShadowSpace = /** @class */ (function () {
41566
42253
  case 6:
41567
42254
  _b.sent();
41568
42255
  logger("[ShadowSpace] \u5DF2\u8FC1\u79FB ".concat(Object.keys(this.state.files).length, " \u4E2A\u6587\u4EF6\u5230\u65B0\u7A7A\u95F4 ").concat(this.config.spaceId));
42256
+ logger("[ShadowSpace] \u65E7\u6587\u4EF6\u5DF2\u5907\u4EFD\u4E3A: ".concat(backupFile));
41569
42257
  return [3 /*break*/, 8]; // 只迁移第一个匹配的文件
41570
42258
  case 7:
41571
42259
  oldStateFiles_1_1 = oldStateFiles_1.next();
41572
42260
  return [3 /*break*/, 3];
41573
42261
  case 8: return [3 /*break*/, 11];
41574
42262
  case 9:
41575
- e_9_1 = _b.sent();
41576
- e_9 = { error: e_9_1 };
42263
+ e_13_1 = _b.sent();
42264
+ e_13 = { error: e_13_1 };
41577
42265
  return [3 /*break*/, 11];
41578
42266
  case 10:
41579
42267
  try {
41580
42268
  if (oldStateFiles_1_1 && !oldStateFiles_1_1.done && (_a = oldStateFiles_1.return)) _a.call(oldStateFiles_1);
41581
42269
  }
41582
- finally { if (e_9) throw e_9.error; }
42270
+ finally { if (e_13) throw e_13.error; }
41583
42271
  return [7 /*endfinally*/];
41584
42272
  case 11: return [3 /*break*/, 13];
41585
42273
  case 12:
41586
- error_9 = _b.sent();
41587
- console.warn('[ShadowSpace] 迁移旧状态文件失败:', error_9);
42274
+ error_12 = _b.sent();
42275
+ console.warn('[ShadowSpace] 迁移旧状态文件失败:', error_12);
41588
42276
  return [3 /*break*/, 13];
41589
42277
  case 13: return [2 /*return*/];
41590
42278
  }
@@ -41593,7 +42281,7 @@ var ShadowSpace = /** @class */ (function () {
41593
42281
  };
41594
42282
  ShadowSpace.prototype.getShadowContent = function (filePath) {
41595
42283
  return __awaiter(this, void 0, void 0, function () {
41596
- var localPath, content, error_10;
42284
+ var localPath, content, error_13;
41597
42285
  return __generator(this, function (_a) {
41598
42286
  switch (_a.label) {
41599
42287
  case 0:
@@ -41611,8 +42299,8 @@ var ShadowSpace = /** @class */ (function () {
41611
42299
  this.contentCache.set(filePath, content);
41612
42300
  return [2 /*return*/, content];
41613
42301
  case 3:
41614
- error_10 = _a.sent();
41615
- console.warn("\u65E0\u6CD5\u83B7\u53D6\u5F71\u5B50\u5185\u5BB9: ".concat(filePath), error_10);
42302
+ error_13 = _a.sent();
42303
+ console.warn("\u65E0\u6CD5\u83B7\u53D6\u5F71\u5B50\u5185\u5BB9: ".concat(filePath), error_13);
41616
42304
  return [2 /*return*/, ''];
41617
42305
  case 4: return [2 /*return*/];
41618
42306
  }
@@ -41627,11 +42315,13 @@ var ShadowSpace = /** @class */ (function () {
41627
42315
  .digest('hex');
41628
42316
  };
41629
42317
  ShadowSpace.prototype.generateId = function () {
41630
- return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
42318
+ return "change_".concat(Date.now(), "_").concat(Math.random()
42319
+ .toString(36)
42320
+ .substring(2, 11));
41631
42321
  };
41632
42322
  ShadowSpace.prototype.shouldIgnoreFile = function (filePath) {
41633
42323
  // logger(`[ShadowSpace] shouldIgnoreFile 检查: "${filePath}"`);
41634
- var e_10, _a;
42324
+ var e_14, _a;
41635
42325
  // 特殊处理:过滤掉特定的系统文件
41636
42326
  var fileName = filePath.split('/').pop() || '';
41637
42327
  if (fileName === '.dirty_files.json') {
@@ -41646,12 +42336,14 @@ var ShadowSpace = /** @class */ (function () {
41646
42336
  // 🔥 目录白名单检查:简化逻辑,允许 src/ 和 docs/ 下的所有文件
41647
42337
  var isInSrc = filePath.startsWith('src/');
41648
42338
  var isInDocs = filePath.startsWith('docs/');
41649
- var isRootConfig = filePath.match(/^[^\/]+\.(json|md|yml|yaml|toml|js|ts|py|go|rs)$/);
42339
+ var isRootConfig = filePath.match(/^[^/]+\.(json|md|yml|yaml|toml|js|ts|py|go|rs)$/);
41650
42340
  if (!isInSrc && !isInDocs && !isRootConfig) {
42341
+ logger("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u767D\u540D\u5355\u76EE\u5F55\u4E2D: ".concat(filePath));
41651
42342
  return true;
41652
42343
  }
41653
42344
  // 特殊处理:不忽略其他 .json 文件(即使以 . 开头)
41654
42345
  if (filePath.endsWith('.json')) {
42346
+ logger("[ShadowSpace] JSON\u6587\u4EF6\u4E0D\u5FFD\u7565: ".concat(filePath));
41655
42347
  return false;
41656
42348
  }
41657
42349
  try {
@@ -41664,27 +42356,28 @@ var ShadowSpace = /** @class */ (function () {
41664
42356
  }
41665
42357
  }
41666
42358
  }
41667
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
42359
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
41668
42360
  finally {
41669
42361
  try {
41670
42362
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
41671
42363
  }
41672
- finally { if (e_10) throw e_10.error; }
42364
+ finally { if (e_14) throw e_14.error; }
41673
42365
  }
41674
42366
  // 检查扩展名白名单
41675
42367
  if (this.config.includeExtensions &&
41676
42368
  this.config.includeExtensions.length > 0) {
41677
42369
  var ext = path__default["default"].extname(filePath).toLowerCase();
41678
42370
  if (!this.config.includeExtensions.includes(ext)) {
42371
+ logger("[ShadowSpace] \u6587\u4EF6\u6269\u5C55\u540D\u4E0D\u5728\u767D\u540D\u5355: ".concat(filePath, " -> ").concat(ext));
41679
42372
  return true;
41680
42373
  }
41681
42374
  }
41682
- // logger(`[ShadowSpace] 文件通过忽略检查: ${filePath}`);
42375
+ logger("[ShadowSpace] \u6587\u4EF6\u901A\u8FC7\u5FFD\u7565\u68C0\u67E5: ".concat(filePath));
41683
42376
  return false;
41684
42377
  };
41685
42378
  ShadowSpace.prototype.writeLocalFile = function (filePath, content) {
41686
42379
  return __awaiter(this, void 0, void 0, function () {
41687
- var fullPath, error_11;
42380
+ var fullPath, error_14;
41688
42381
  return __generator(this, function (_a) {
41689
42382
  switch (_a.label) {
41690
42383
  case 0:
@@ -41706,18 +42399,99 @@ var ShadowSpace = /** @class */ (function () {
41706
42399
  _a.sent();
41707
42400
  return [3 /*break*/, 5];
41708
42401
  case 4:
41709
- error_11 = _a.sent();
41710
- console.error("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u5931\u8D25: ".concat(fullPath), error_11);
41711
- throw error_11;
42402
+ error_14 = _a.sent();
42403
+ console.error("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u5931\u8D25: ".concat(fullPath), error_14);
42404
+ throw error_14;
41712
42405
  case 5: return [2 /*return*/];
41713
42406
  }
41714
42407
  });
41715
42408
  });
41716
42409
  };
42410
+ /**
42411
+ * 同步本地文件状态到内存和状态文件
42412
+ * (用于CLI独立运行时刷新状态)
42413
+ */
42414
+ ShadowSpace.prototype.syncLocalState = function () {
42415
+ return __awaiter(this, void 0, void 0, function () {
42416
+ var localFiles, snapshots, currentPaths, localFiles_2, localFiles_2_1, file, hash, entry, _a, _b, key;
42417
+ var e_15, _c, e_16, _d;
42418
+ return __generator(this, function (_e) {
42419
+ switch (_e.label) {
42420
+ case 0: return [4 /*yield*/, this.loadState()];
42421
+ case 1:
42422
+ _e.sent();
42423
+ return [4 /*yield*/, this.scanLocalFiles()];
42424
+ case 2:
42425
+ localFiles = _e.sent();
42426
+ snapshots = [];
42427
+ currentPaths = new Set();
42428
+ try {
42429
+ for (localFiles_2 = __values(localFiles), localFiles_2_1 = localFiles_2.next(); !localFiles_2_1.done; localFiles_2_1 = localFiles_2.next()) {
42430
+ file = localFiles_2_1.value;
42431
+ currentPaths.add(file.relativePath);
42432
+ hash = this.calculateHash(file.content);
42433
+ // Update state
42434
+ if (!this.state.files[file.relativePath]) {
42435
+ this.state.files[file.relativePath] = {
42436
+ path: file.relativePath,
42437
+ hash: hash,
42438
+ size: file.content.length,
42439
+ lastSyncTime: 0,
42440
+ lastModified: 0,
42441
+ version: 1,
42442
+ mtime: file.mtime,
42443
+ };
42444
+ }
42445
+ else {
42446
+ entry = this.state.files[file.relativePath];
42447
+ if (entry.hash !== hash || entry.mtime !== file.mtime) {
42448
+ entry.hash = hash;
42449
+ entry.mtime = file.mtime;
42450
+ }
42451
+ }
42452
+ snapshots.push({
42453
+ path: file.relativePath,
42454
+ hash: hash,
42455
+ modify: file.mtime,
42456
+ remoteHash: this.state.files[file.relativePath].remoteHash,
42457
+ });
42458
+ }
42459
+ }
42460
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
42461
+ finally {
42462
+ try {
42463
+ if (localFiles_2_1 && !localFiles_2_1.done && (_c = localFiles_2.return)) _c.call(localFiles_2);
42464
+ }
42465
+ finally { if (e_15) throw e_15.error; }
42466
+ }
42467
+ try {
42468
+ // Remove deleted files from state
42469
+ for (_a = __values(Object.keys(this.state.files)), _b = _a.next(); !_b.done; _b = _a.next()) {
42470
+ key = _b.value;
42471
+ if (!currentPaths.has(key)) {
42472
+ delete this.state.files[key];
42473
+ }
42474
+ }
42475
+ }
42476
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
42477
+ finally {
42478
+ try {
42479
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
42480
+ }
42481
+ finally { if (e_16) throw e_16.error; }
42482
+ }
42483
+ return [4 /*yield*/, this.saveState()];
42484
+ case 3:
42485
+ _e.sent();
42486
+ return [2 /*return*/, snapshots];
42487
+ }
42488
+ });
42489
+ });
42490
+ };
41717
42491
  ShadowSpace.prototype.scanLocalFiles = function () {
41718
42492
  return __awaiter(this, void 0, void 0, function () {
41719
- var files, pattern, options, filePaths, filePaths_2, filePaths_2_1, filePath, fullPath, content, stats, error_12, e_11_1;
41720
- var e_11, _a;
42493
+ var files, pattern, options, globPromise, filePaths, filePaths_2, filePaths_2_1, filePath, fullPath, content, stats, error_15, e_17_1;
42494
+ var e_17, _a;
41721
42495
  return __generator(this, function (_b) {
41722
42496
  switch (_b.label) {
41723
42497
  case 0:
@@ -41728,52 +42502,55 @@ var ShadowSpace = /** @class */ (function () {
41728
42502
  ignore: this.config.ignorePatterns,
41729
42503
  nodir: true,
41730
42504
  };
41731
- filePaths = glob$1.glob.sync(pattern, options);
41732
- _b.label = 1;
42505
+ globPromise = util$3.promisify(glob__default["default"]);
42506
+ return [4 /*yield*/, globPromise(pattern, options)];
41733
42507
  case 1:
41734
- _b.trys.push([1, 9, 10, 11]);
41735
- filePaths_2 = __values(filePaths), filePaths_2_1 = filePaths_2.next();
42508
+ filePaths = _b.sent();
41736
42509
  _b.label = 2;
41737
42510
  case 2:
41738
- if (!!filePaths_2_1.done) return [3 /*break*/, 8];
41739
- filePath = filePaths_2_1.value;
41740
- if (this.shouldIgnoreFile(filePath))
41741
- return [3 /*break*/, 7];
42511
+ _b.trys.push([2, 10, 11, 12]);
42512
+ filePaths_2 = __values(filePaths), filePaths_2_1 = filePaths_2.next();
41742
42513
  _b.label = 3;
41743
42514
  case 3:
41744
- _b.trys.push([3, 6, , 7]);
42515
+ if (!!filePaths_2_1.done) return [3 /*break*/, 9];
42516
+ filePath = filePaths_2_1.value;
42517
+ if (this.shouldIgnoreFile(filePath))
42518
+ return [3 /*break*/, 8];
42519
+ _b.label = 4;
42520
+ case 4:
42521
+ _b.trys.push([4, 7, , 8]);
41745
42522
  fullPath = path__default["default"].join(this.config.projectRoot, filePath);
41746
42523
  return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
41747
- case 4:
42524
+ case 5:
41748
42525
  content = _b.sent();
41749
42526
  return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
41750
- case 5:
42527
+ case 6:
41751
42528
  stats = _b.sent();
41752
42529
  files.push({
41753
42530
  relativePath: filePath,
41754
42531
  content: content,
41755
42532
  mtime: stats.mtime.getTime(),
41756
42533
  });
41757
- return [3 /*break*/, 7];
41758
- case 6:
41759
- error_12 = _b.sent();
41760
- console.warn("\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_12);
41761
- return [3 /*break*/, 7];
42534
+ return [3 /*break*/, 8];
41762
42535
  case 7:
42536
+ error_15 = _b.sent();
42537
+ console.warn("\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ".concat(filePath), error_15);
42538
+ return [3 /*break*/, 8];
42539
+ case 8:
41763
42540
  filePaths_2_1 = filePaths_2.next();
41764
- return [3 /*break*/, 2];
41765
- case 8: return [3 /*break*/, 11];
41766
- case 9:
41767
- e_11_1 = _b.sent();
41768
- e_11 = { error: e_11_1 };
41769
- return [3 /*break*/, 11];
42541
+ return [3 /*break*/, 3];
42542
+ case 9: return [3 /*break*/, 12];
41770
42543
  case 10:
42544
+ e_17_1 = _b.sent();
42545
+ e_17 = { error: e_17_1 };
42546
+ return [3 /*break*/, 12];
42547
+ case 11:
41771
42548
  try {
41772
42549
  if (filePaths_2_1 && !filePaths_2_1.done && (_a = filePaths_2.return)) _a.call(filePaths_2);
41773
42550
  }
41774
- finally { if (e_11) throw e_11.error; }
42551
+ finally { if (e_17) throw e_17.error; }
41775
42552
  return [7 /*endfinally*/];
41776
- case 11: return [2 /*return*/, files];
42553
+ case 12: return [2 /*return*/, files];
41777
42554
  }
41778
42555
  });
41779
42556
  });
@@ -41815,20 +42592,33 @@ var ShadowSpace = /** @class */ (function () {
41815
42592
  };
41816
42593
  ShadowSpace.prototype.loadState = function () {
41817
42594
  return __awaiter(this, void 0, void 0, function () {
41818
- var content;
42595
+ var content, error_16;
41819
42596
  return __generator(this, function (_a) {
41820
42597
  switch (_a.label) {
41821
42598
  case 0:
41822
- _a.trys.push([0, 2, , 3]);
42599
+ _a.trys.push([0, 2, , 6]);
41823
42600
  return [4 /*yield*/, fs__default$1["default"].readFile(this.stateFile, 'utf8')];
41824
42601
  case 1:
41825
42602
  content = _a.sent();
41826
42603
  this.state = __assign(__assign({}, this.state), JSON.parse(content));
41827
- return [3 /*break*/, 3];
42604
+ return [3 /*break*/, 6];
41828
42605
  case 2:
42606
+ error_16 = _a.sent();
42607
+ if (!(error_16.code === 'ENOENT')) return [3 /*break*/, 4];
42608
+ logger('影子空间状态文件不存在,使用默认状态');
42609
+ // Ensure directory exists for future saves
42610
+ // 使用 ensureDir 确保整个路径存在,包括 .appthen
42611
+ return [4 /*yield*/, fs__default$1["default"].ensureDir(path__default["default"].dirname(this.stateFile))];
42612
+ case 3:
42613
+ // Ensure directory exists for future saves
42614
+ // 使用 ensureDir 确保整个路径存在,包括 .appthen
41829
42615
  _a.sent();
41830
- return [3 /*break*/, 3];
41831
- case 3: return [2 /*return*/];
42616
+ return [3 /*break*/, 5];
42617
+ case 4:
42618
+ console.warn('[ShadowSpace] 读取状态文件失败:', error_16);
42619
+ _a.label = 5;
42620
+ case 5: return [3 /*break*/, 6];
42621
+ case 6: return [2 /*return*/];
41832
42622
  }
41833
42623
  });
41834
42624
  });
@@ -41839,102 +42629,13 @@ var ShadowSpace = /** @class */ (function () {
41839
42629
  var k = 1024;
41840
42630
  var sizes = ['B', 'KB', 'MB', 'GB'];
41841
42631
  var i = Math.floor(Math.log(bytes) / Math.log(k));
41842
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
41843
- };
41844
- // ==================== 🆕 文件监听功能 ====================
41845
- /**
41846
- * 启动文件监听
41847
- */
41848
- ShadowSpace.prototype.startWatching = function () {
41849
- var _this = this;
41850
- if (this.isWatching) {
41851
- return;
41852
- }
41853
- logger('[ShadowSpace] 监听目录:', this.config.projectRoot);
41854
- try {
41855
- // 🔥 使用轮询模式 + ignored 函数过滤
41856
- this.watcher = chokidar__default["default"].watch(this.config.projectRoot, {
41857
- ignored: function (filePath) {
41858
- var relativePath = path__default["default"].relative(_this.config.projectRoot, filePath);
41859
- // 忽略根目录本身
41860
- if (!relativePath || relativePath === '.') {
41861
- return true;
41862
- }
41863
- // 使用白名单过滤
41864
- return _this.shouldIgnoreFile(relativePath);
41865
- },
41866
- persistent: true,
41867
- ignoreInitial: true,
41868
- usePolling: true,
41869
- interval: 2000,
41870
- binaryInterval: 3000,
41871
- depth: 99,
41872
- awaitWriteFinish: {
41873
- stabilityThreshold: 500,
41874
- pollInterval: 100,
41875
- },
41876
- });
41877
- logger('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
41878
- }
41879
- catch (error) {
41880
- console.error('[ShadowSpace] 创建文件监听器失败:', error);
41881
- return;
41882
- }
41883
- this.watcher
41884
- .on('change', function (filePath) {
41885
- _this.onFileChanged(filePath);
41886
- })
41887
- .on('add', function (filePath) {
41888
- _this.onFileAdded(filePath);
41889
- })
41890
- .on('unlink', function (filePath) {
41891
- _this.onFileDeleted(filePath);
41892
- })
41893
- .on('error', function (error) {
41894
- console.error('[ShadowSpace] 文件监听错误:', error);
41895
- })
41896
- .on('ready', function () {
41897
- _this.isWatching = true;
41898
- logger('[ShadowSpace] 文件监听已启动,正在监听:', _this.config.projectRoot);
41899
- });
41900
- };
41901
- /**
41902
- * 停止文件监听
41903
- */
41904
- ShadowSpace.prototype.stopWatching = function () {
41905
- return __awaiter(this, void 0, void 0, function () {
41906
- return __generator(this, function (_a) {
41907
- switch (_a.label) {
41908
- case 0:
41909
- if (!this.isWatching || !this.watcher) {
41910
- return [2 /*return*/];
41911
- }
41912
- return [4 /*yield*/, this.watcher.close()];
41913
- case 1:
41914
- _a.sent();
41915
- this.watcher = null;
41916
- this.isWatching = false;
41917
- return [2 /*return*/];
41918
- }
41919
- });
41920
- });
41921
- };
41922
- /**
41923
- * 添加变更事件监听器
41924
- */
41925
- ShadowSpace.prototype.addChangeListener = function (listener) {
41926
- this.changeListeners.add(listener);
41927
- };
41928
- /**
41929
- * 移除变更事件监听器
41930
- */
41931
- ShadowSpace.prototype.removeChangeListener = function (listener) {
41932
- this.changeListeners.delete(listener);
42632
+ return "".concat(parseFloat((bytes / Math.pow(k, i)).toFixed(2)), " ").concat(sizes[i]);
41933
42633
  };
41934
42634
  /**
41935
42635
  * 触发变更事件
41936
42636
  */
41937
42637
  ShadowSpace.prototype.emitChangeEvent = function (event) {
42638
+ logger('[ShadowSpace] 触发变更事件:', event);
41938
42639
  this.changeListeners.forEach(function (listener) {
41939
42640
  try {
41940
42641
  listener(event);
@@ -41949,13 +42650,15 @@ var ShadowSpace = /** @class */ (function () {
41949
42650
  */
41950
42651
  ShadowSpace.prototype.onFileChanged = function (filePath) {
41951
42652
  return __awaiter(this, void 0, void 0, function () {
41952
- var relativePath, shadowEntry, content, hash, stats, error_14;
42653
+ var relativePath, shadowEntry, content, hash, stats, error_17;
41953
42654
  return __generator(this, function (_a) {
41954
42655
  switch (_a.label) {
41955
42656
  case 0:
41956
42657
  relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
42658
+ logger("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(relativePath));
41957
42659
  shadowEntry = this.state.files[relativePath];
41958
42660
  if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
42661
+ logger("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u7684\u6587\u4EF6: ".concat(relativePath));
41959
42662
  shadowEntry.remoteModified = false; // 清除标记
41960
42663
  return [4 /*yield*/, this.saveState()];
41961
42664
  case 1:
@@ -41981,8 +42684,8 @@ var ShadowSpace = /** @class */ (function () {
41981
42684
  });
41982
42685
  return [3 /*break*/, 6];
41983
42686
  case 5:
41984
- error_14 = _a.sent();
41985
- console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath), error_14);
42687
+ error_17 = _a.sent();
42688
+ console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath), error_17);
41986
42689
  return [3 /*break*/, 6];
41987
42690
  case 6: return [2 /*return*/];
41988
42691
  }
@@ -41994,11 +42697,12 @@ var ShadowSpace = /** @class */ (function () {
41994
42697
  */
41995
42698
  ShadowSpace.prototype.onFileAdded = function (filePath) {
41996
42699
  return __awaiter(this, void 0, void 0, function () {
41997
- var relativePath, content, hash, stats, error_15;
42700
+ var relativePath, content, hash, stats, error_18;
41998
42701
  return __generator(this, function (_a) {
41999
42702
  switch (_a.label) {
42000
42703
  case 0:
42001
42704
  relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
42705
+ logger("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u65B0\u589E: ".concat(relativePath));
42002
42706
  _a.label = 1;
42003
42707
  case 1:
42004
42708
  _a.trys.push([1, 4, , 5]);
@@ -42020,8 +42724,8 @@ var ShadowSpace = /** @class */ (function () {
42020
42724
  });
42021
42725
  return [3 /*break*/, 5];
42022
42726
  case 4:
42023
- error_15 = _a.sent();
42024
- console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath), error_15);
42727
+ error_18 = _a.sent();
42728
+ console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath), error_18);
42025
42729
  return [3 /*break*/, 5];
42026
42730
  case 5: return [2 /*return*/];
42027
42731
  }
@@ -42038,8 +42742,10 @@ var ShadowSpace = /** @class */ (function () {
42038
42742
  switch (_a.label) {
42039
42743
  case 0:
42040
42744
  relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
42745
+ logger("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5220\u9664: ".concat(relativePath));
42041
42746
  shadowEntry = this.state.files[relativePath];
42042
42747
  if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
42748
+ logger("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u5220\u9664\u7684\u6587\u4EF6: ".concat(relativePath));
42043
42749
  shadowEntry.remoteModified = false; // 清除标记
42044
42750
  return [4 /*yield*/, this.saveState()];
42045
42751
  case 1:
@@ -42058,12 +42764,6 @@ var ShadowSpace = /** @class */ (function () {
42058
42764
  });
42059
42765
  });
42060
42766
  };
42061
- /**
42062
- * 获取监听状态
42063
- */
42064
- ShadowSpace.prototype.isFileWatching = function () {
42065
- return this.isWatching;
42066
- };
42067
42767
  return ShadowSpace;
42068
42768
  }());
42069
42769
 
@@ -42316,22 +43016,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42316
43016
  changes = _a.sent();
42317
43017
  result = {
42318
43018
  spaceId: this.shadowSpace.getSpaceInfo().spaceId,
42319
- changes: changes.map(function (change) { return ({
42320
- id: change.id,
42321
- action: change.action,
42322
- path: change.path,
42323
- version: change.version,
42324
- timestamp: change.timestamp,
42325
- hasContent: !!change.diff.before || !!change.diff.after,
42326
- size: {
42327
- before: change.diff.before
42328
- ? Buffer.byteLength(change.diff.before, 'utf8')
42329
- : 0,
42330
- after: change.diff.after
42331
- ? Buffer.byteLength(change.diff.after, 'utf8')
42332
- : 0,
42333
- },
42334
- }); }),
43019
+ changes: changes,
42335
43020
  summary: {
42336
43021
  total: changes.length,
42337
43022
  added: changes.filter(function (c) { return c.action === 'add'; }).length,
@@ -42853,7 +43538,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42853
43538
  // `[ShadowSpace] 开始检测变更: 空间=${spaceId}, 编辑器文件=${safeEditorSnapshots.length}个`
42854
43539
  // );
42855
43540
  // 1. 🔥 先检测本地文件变更,更新影子空间状态,并获取本地变更列表(包括新增文件)
42856
- console.log("\n\uD83D\uDD0D [DEBUG] \u6B63\u5728\u68C0\u6D4B\u672C\u5730\u6587\u4EF6\u53D8\u66F4...");
43541
+ console.log('\n🔍 [DEBUG] 正在检测本地文件变更...');
42857
43542
  return [4 /*yield*/, this.shadowSpace.detectChanges()];
42858
43543
  case 1:
42859
43544
  localChanges = _a.sent();
@@ -42865,7 +43550,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42865
43550
  spaceSnapshots = _a.sent();
42866
43551
  console.log("\uD83D\uDD0D [DEBUG] getSpaceSnapshots \u8FD4\u56DE\u7ED3\u679C\u7C7B\u578B: ".concat(typeof spaceSnapshots));
42867
43552
  console.log("\uD83D\uDD0D [DEBUG] getSpaceSnapshots \u662F\u5426\u4E3A\u6570\u7EC4: ".concat(Array.isArray(spaceSnapshots)));
42868
- console.log("\uD83D\uDD0D [DEBUG] getSpaceSnapshots \u539F\u59CB\u7ED3\u679C:", spaceSnapshots);
43553
+ console.log('🔍 [DEBUG] getSpaceSnapshots 原始结果:', spaceSnapshots);
42869
43554
  // 🔍 友好的调试输出
42870
43555
  console.log('\n=== 影子空间变更检测调试 ===');
42871
43556
  console.log('📁 空间ID:', spaceId);
@@ -42874,19 +43559,19 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42874
43559
  spaceInfo = this.shadowSpace.getSpaceInfo();
42875
43560
  console.log('\n🏠 影子空间信息:');
42876
43561
  console.log(" \uD83D\uDCC2 \u9879\u76EE\u6839\u76EE\u5F55: ".concat(spaceInfo.projectRoot));
42877
- console.log(" \uD83D\uDCC1 \u7A7A\u95F4\u76EE\u5F55: ".concat(spaceInfo.spaceRoot));
43562
+ // console.log(` 📁 空间目录: ${spaceInfo.spaceRoot}`); // 属性不存在,注释掉
42878
43563
  console.log(" \uD83D\uDCCA \u6587\u4EF6\u6570\u91CF: ".concat(spaceInfo.fileCount));
42879
43564
  console.log(" \uD83D\uDCE6 \u603B\u5927\u5C0F: ".concat(spaceInfo.totalSize));
42880
43565
  console.log(" \uD83C\uDD94 \u7528\u6237ID: ".concat(spaceInfo.userId));
42881
43566
  console.log(" \u23F0 \u521B\u5EFA\u65F6\u95F4: ".concat(spaceInfo.createdAt));
42882
- console.log(" \u23F0 \u66F4\u65B0\u65F6\u95F4: ".concat(spaceInfo.updatedAt));
43567
+ console.log(" \u23F0 \u66F4\u65B0\u65F6\u95F4: ".concat(spaceInfo.lastUpdate)); // 修正属性名
42883
43568
  require('path');
42884
43569
  fs = require('fs-extra');
42885
- spaceDir = spaceInfo.spaceRoot;
43570
+ spaceDir = spaceInfo.projectRoot;
42886
43571
  return [4 /*yield*/, fs.pathExists(spaceDir)];
42887
43572
  case 3:
42888
43573
  spaceExists = _a.sent();
42889
- console.log("\n\uD83D\uDCC1 \u7A7A\u95F4\u76EE\u5F55\u68C0\u67E5:");
43574
+ console.log('\n📁 空间目录检查:');
42890
43575
  console.log(" \uD83D\uDCC2 \u8DEF\u5F84: ".concat(spaceDir));
42891
43576
  console.log(" \u2705 \u662F\u5426\u5B58\u5728: ".concat(spaceExists));
42892
43577
  if (!spaceExists) return [3 /*break*/, 7];
@@ -42951,7 +43636,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42951
43636
  }); });
42952
43637
  console.log("\uD83D\uDD0D [DEBUG] \u672C\u5730\u65B0\u589E\u6587\u4EF6\u6570\u91CF: ".concat(localAddChanges.length));
42953
43638
  if (localAddChanges.length > 0) {
42954
- console.log("\uD83D\uDD0D [DEBUG] \u672C\u5730\u65B0\u589E\u6587\u4EF6\u5217\u8868:", localAddChanges.map(function (c) { return c.path; }));
43639
+ console.log('🔍 [DEBUG] 本地新增文件列表:', localAddChanges.map(function (c) { return c.path; }));
42955
43640
  }
42956
43641
  changes = __spreadArray(__spreadArray([], __read(snapshotChanges), false), __read(localAddChanges), false);
42957
43642
  summary = {
@@ -43023,18 +43708,29 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
43023
43708
  ShadowSpaceCommandHandler.prototype.compareSnapshots = function (editorSnapshots, spaceSnapshots) {
43024
43709
  var _a, _b;
43025
43710
  return __awaiter(this, void 0, void 0, function () {
43026
- var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _c, path, editorFile, spaceFile, editorModify, spaceModify, spaceMap_1, spaceMap_1_1, _d, path, spaceFile, editorFile;
43711
+ var changes, normalizePath, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _c, path, editorFile, spaceFile, editorModify, spaceModify, spaceMap_1, spaceMap_1_1, _d, path, spaceFile, editorFile;
43027
43712
  var e_2, _e, e_3, _f;
43028
43713
  return __generator(this, function (_g) {
43029
43714
  changes = [];
43715
+ normalizePath = function (p) {
43716
+ // 统一替换反斜杠为正斜杠
43717
+ var normalized = p.replace(/\\/g, '/');
43718
+ // 去除开头的 ./
43719
+ if (normalized.startsWith('./'))
43720
+ normalized = normalized.substring(2);
43721
+ // 去除开头的 /
43722
+ if (normalized.startsWith('/'))
43723
+ normalized = normalized.substring(1);
43724
+ return normalized;
43725
+ };
43030
43726
  safeEditorSnapshots = Array.isArray(editorSnapshots)
43031
43727
  ? editorSnapshots
43032
43728
  : [];
43033
43729
  safeSpaceSnapshots = Array.isArray(spaceSnapshots)
43034
43730
  ? spaceSnapshots
43035
43731
  : [];
43036
- editorMap = new Map(safeEditorSnapshots.map(function (f) { return [f.path, f]; }));
43037
- spaceMap = new Map(safeSpaceSnapshots.map(function (f) { return [f.path, f]; }));
43732
+ editorMap = new Map(safeEditorSnapshots.map(function (f) { return [normalizePath(f.path), f]; }));
43733
+ spaceMap = new Map(safeSpaceSnapshots.map(function (f) { return [normalizePath(f.path), f]; }));
43038
43734
  try {
43039
43735
  // 检测编辑器的变更(新增、修改)
43040
43736
  for (editorMap_1 = __values(editorMap), editorMap_1_1 = editorMap_1.next(); !editorMap_1_1.done; editorMap_1_1 = editorMap_1.next()) {
@@ -43042,6 +43738,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
43042
43738
  spaceFile = spaceMap.get(path);
43043
43739
  if (!spaceFile) {
43044
43740
  // 编辑器新增的文件 → 推送到空间
43741
+ // 🔥 调试:打印路径标准化情况
43742
+ if (path.includes('TicketHistory')) {
43743
+ console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7F16\u8F91\u5668\u65B0\u589E: \"".concat(path, "\" (Original: \"").concat(editorFile.path, "\")"));
43744
+ }
43045
43745
  changes.push({
43046
43746
  action: 'add',
43047
43747
  path: path,
@@ -43065,8 +43765,8 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
43065
43765
  });
43066
43766
  // 🔥 关键逻辑:根据时间戳判断方向
43067
43767
  if (editorModify > spaceModify) {
43068
- // 编辑器更新 → 推送到空间
43069
- console.log("[ShadowSpace] \u2192 \u7F16\u8F91\u5668\u66F4\u65B0\uFF0C\u9700\u8981\u63A8\u9001: ".concat(path));
43768
+ // 编辑器更新 → 推送到空间 (Remote -> Local) => Pull
43769
+ console.log("[ShadowSpace] \u2B07\uFE0F \u8FDC\u7AEF\u66F4\u65B0 (\u9700\u62C9\u53D6): ".concat(path));
43070
43770
  changes.push({
43071
43771
  action: 'modify',
43072
43772
  path: path,
@@ -47772,411 +48472,140 @@ function executeShadowSpaceDebug(options) {
47772
48472
  });
47773
48473
  }
47774
48474
 
47775
- /**
47776
- * 统一的TSX/JSX验证器
47777
- * 同时支持CLI和编辑器使用
47778
- */
47779
- var UnifiedTSXValidator = /** @class */ (function () {
47780
- function UnifiedTSXValidator(debug) {
47781
- if (debug === void 0) { debug = false; }
47782
- this.debug = false;
47783
- this.debug = debug;
48475
+ var TSXComplianceChecker = /** @class */ (function () {
48476
+ function TSXComplianceChecker() {
47784
48477
  }
47785
48478
  /**
47786
- * 验证TSX文件内容
48479
+ * 使用 AST 检查 TSX 规范
47787
48480
  */
47788
- UnifiedTSXValidator.prototype.validate = function (content, filename) {
47789
- var _this = this;
47790
- if (filename === void 0) { filename = 'unknown.tsx'; }
47791
- this.content = content;
47792
- this.filename = filename;
48481
+ TSXComplianceChecker.checkTSXCompliance = function (content, filename) {
47793
48482
  var issues = [];
47794
48483
  try {
47795
- var ast_1 = parser$1.parse(content, {
48484
+ // 使用 Babel 解析 TSX 代码
48485
+ var ast = parser$1.parse(content, {
47796
48486
  sourceType: 'module',
47797
48487
  plugins: ['jsx', 'typescript', 'decorators-legacy', 'classProperties'],
47798
48488
  errorRecovery: true,
47799
- allowReturnOutsideFunction: true,
47800
48489
  });
47801
- this.log('AST解析完成');
47802
- // 执行所有检查,每个检查都包装在try-catch中
47803
- this.safeCheck('checkFileStructure', function () { return _this.checkFileStructure(ast_1, issues); });
47804
- this.safeCheck('checkComponentDefinition', function () { return _this.checkComponentDefinition(ast_1, issues); });
47805
- this.safeCheck('checkRenderMethod', function () { return _this.checkRenderMethod(ast_1, issues); });
47806
- this.safeCheck('checkVariableDeclarations', function () { return _this.checkVariableDeclarations(ast_1, issues); });
47807
- this.safeCheck('checkConditionalRendering', function () { return _this.checkConditionalRendering(ast_1, issues); });
47808
- this.safeCheck('checkListRendering', function () { return _this.checkListRendering(ast_1, issues); });
47809
- this.safeCheck('checkStyleUsage', function () { return _this.checkStyleUsage(ast_1, issues); });
47810
- this.safeCheck('checkStateManagement', function () { return _this.checkStateManagement(ast_1, issues); });
47811
- this.safeCheck('checkDataSourceUsage', function () { return _this.checkDataSourceUsage(ast_1, issues); });
47812
- this.safeCheck('checkTypeScriptSyntaxInMethods', function () { return _this.checkTypeScriptSyntaxInMethods(ast_1, issues); });
47813
- this.log("\u68C0\u67E5\u5B8C\u6210\uFF0C\u53D1\u73B0 ".concat(issues.length, " \u4E2A\u95EE\u9898"));
47814
- return {
47815
- isCompliant: issues.filter(function (issue) { return issue.type === 'error'; }).length === 0,
47816
- issues: issues,
47817
- };
48490
+ // 遍历 AST 进行检查
48491
+ traverse__default["default"](ast, {
48492
+ // 检查变量声明
48493
+ VariableDeclarator: function (path) {
48494
+ TSXComplianceChecker.checkVariableDeclaration(path, content, issues);
48495
+ },
48496
+ // 检查方法定义
48497
+ ClassMethod: function (path) {
48498
+ TSXComplianceChecker.checkMethodDefinition(path, content, issues);
48499
+ },
48500
+ // 检查 JSX 使用
48501
+ JSXElement: function (path) {
48502
+ TSXComplianceChecker.checkJSXUsage(path, content, issues);
48503
+ },
48504
+ // 检查类型注解
48505
+ TSTypeAnnotation: function (path) {
48506
+ TSXComplianceChecker.checkTypeAnnotation(path, content, issues);
48507
+ },
48508
+ });
48509
+ // 检查必需的结构
48510
+ this.checkRequiredStructures(ast, content, issues);
47818
48511
  }
47819
48512
  catch (error) {
47820
- this.log("\u89E3\u6790\u9519\u8BEF: ".concat(error.message));
47821
- return {
47822
- isCompliant: false,
47823
- issues: [{
47824
- type: 'error',
47825
- code: 'PARSE_ERROR',
47826
- message: "\u4EE3\u7801\u89E3\u6790\u5931\u8D25: ".concat(error.message),
47827
- suggestion: '检查代码语法是否正确',
47828
- line: 1,
47829
- column: 0,
47830
- }],
47831
- };
47832
- }
47833
- };
47834
- /**
47835
- * 检查文件结构
47836
- */
47837
- UnifiedTSXValidator.prototype.checkFileStructure = function (ast, issues) {
47838
- var _this = this;
47839
- this.log('开始检查文件结构');
47840
- var hasReactComponent = false;
47841
- traverse__default["default"](ast, {
47842
- ClassDeclaration: function (path) {
47843
- var _a;
47844
- var className = (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name;
47845
- _this.log("\u53D1\u73B0\u7C7B: ".concat(className));
47846
- // 检查是否有继承自React.Component的类(支持 extends Component 和 extends React.Component)
47847
- if (_this.isReactComponent(path.node.superClass)) {
47848
- hasReactComponent = true;
47849
- _this.log("\u53D1\u73B0React\u7EC4\u4EF6\u7C7B: ".concat(className));
47850
- }
47851
- },
47852
- });
47853
- // 不再强制要求Document类,只要有React组件类即可
47854
- if (!hasReactComponent) {
47855
- issues.push(this.createIssue('MISSING_REACT_COMPONENT', 'error', '缺少React组件类定义,必须定义一个继承自React.Component的类', '请定义组件类,如: class MyComponent extends React.Component 或 class MyComponent extends Component', 1));
48513
+ issues.push({
48514
+ type: 'error',
48515
+ code: 'PARSE_ERROR',
48516
+ message: "\u4EE3\u7801\u89E3\u6790\u5931\u8D25: ".concat(error.message),
48517
+ suggestion: '检查代码语法是否正确',
48518
+ });
47856
48519
  }
48520
+ return {
48521
+ isCompliant: issues.filter(function (issue) { return issue.type === 'error'; }).length === 0,
48522
+ issues: issues,
48523
+ };
47857
48524
  };
47858
48525
  /**
47859
- * 检查组件定义
47860
- */
47861
- UnifiedTSXValidator.prototype.checkComponentDefinition = function (ast, issues) {
47862
- var _this = this;
47863
- this.log('开始检查组件定义');
47864
- traverse__default["default"](ast, {
47865
- ClassDeclaration: function (path) {
47866
- var e_1, _a;
47867
- var _b;
47868
- // 检查所有继承自React.Component的类
47869
- if (_this.isReactComponent(path.node.superClass)) {
47870
- var className = (_b = path.node.id) === null || _b === void 0 ? void 0 : _b.name;
47871
- _this.log("\u68C0\u67E5React\u7EC4\u4EF6\u7C7B: ".concat(className));
47872
- // 检查render方法
47873
- var hasRender = false;
47874
- try {
47875
- for (var _c = __values(path.node.body.body), _d = _c.next(); !_d.done; _d = _c.next()) {
47876
- var member = _d.value;
47877
- if (member.type === 'ClassMethod' && member.key.name === 'render') {
47878
- hasRender = true;
47879
- }
47880
- // 检查constructor
47881
- if (member.type === 'ClassMethod' && member.key.name === 'constructor') {
47882
- issues.push(_this.createIssueFromNode('CONSTRUCTOR_NOT_ALLOWED', 'error', "".concat(className, "\u7C7B\u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528constructor"), '请使用state属性直接定义状态,使用componentDidMount进行初始化', member));
47883
- }
47884
- }
47885
- }
47886
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
47887
- finally {
47888
- try {
47889
- if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
47890
- }
47891
- finally { if (e_1) throw e_1.error; }
47892
- }
47893
- // 移除对state属性的强制检查,React组件可以不定义state
47894
- if (!hasRender) {
47895
- issues.push(_this.createIssueFromNode('MISSING_RENDER_METHOD', 'error', "".concat(className, "\u7C7B\u5FC5\u987B\u5B9A\u4E49render\u65B9\u6CD5"), '请添加: render() { return <View>...</View> }', path.node));
47896
- }
47897
- }
47898
- },
47899
- });
47900
- };
47901
- /**
47902
- * 检查render方法
47903
- */
47904
- UnifiedTSXValidator.prototype.checkRenderMethod = function (ast, issues) {
47905
- var _this = this;
47906
- this.log('开始检查render方法');
47907
- traverse__default["default"](ast, {
47908
- ClassMethod: function (path) {
47909
- var e_2, _a, e_3, _b;
47910
- if (path.node.key.name === 'render') {
47911
- var body = path.node.body.body;
47912
- try {
47913
- // 检查变量声明
47914
- for (var body_1 = __values(body), body_1_1 = body_1.next(); !body_1_1.done; body_1_1 = body_1.next()) {
47915
- var statement = body_1_1.value;
47916
- if (statement.type === 'VariableDeclaration') {
47917
- // 检查是否在事件处理函数中
47918
- if (!_this.isInEventHandler(path)) {
47919
- issues.push(_this.createIssueFromNode('RENDER_VARIABLE_DECLARATION', 'error', 'render方法中不允许声明变量', '直接使用this.state访问状态', statement));
47920
- }
47921
- }
47922
- // 检查函数声明
47923
- if (statement.type === 'FunctionDeclaration') {
47924
- issues.push(_this.createIssueFromNode('RENDER_FUNCTION_DECLARATION', 'error', 'render方法中不允许声明函数', '将函数声明移到render方法外部', statement));
47925
- }
47926
- // 检查if语句
47927
- if (statement.type === 'IfStatement') {
47928
- issues.push(_this.createIssueFromNode('RENDER_IF_STATEMENT', 'error', 'render方法中不允许使用if语句进行条件渲染', '请使用JSX中的条件渲染语法 {condition && <View>}', statement));
47929
- }
47930
- }
47931
- }
47932
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
47933
- finally {
47934
- try {
47935
- if (body_1_1 && !body_1_1.done && (_a = body_1.return)) _a.call(body_1);
47936
- }
47937
- finally { if (e_2) throw e_2.error; }
47938
- }
47939
- // 检查是否有return语句
47940
- var hasReturn = false;
47941
- try {
47942
- for (var body_2 = __values(body), body_2_1 = body_2.next(); !body_2_1.done; body_2_1 = body_2.next()) {
47943
- var statement = body_2_1.value;
47944
- if (statement.type === 'ReturnStatement') {
47945
- hasReturn = true;
47946
- break;
47947
- }
47948
- }
47949
- }
47950
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
47951
- finally {
47952
- try {
47953
- if (body_2_1 && !body_2_1.done && (_b = body_2.return)) _b.call(body_2);
47954
- }
47955
- finally { if (e_3) throw e_3.error; }
47956
- }
47957
- if (!hasReturn) {
47958
- issues.push(_this.createIssueFromNode('MISSING_RETURN', 'error', 'render方法必须返回JSX元素', '请在render方法末尾添加return语句', path.node));
47959
- }
47960
- }
47961
- },
47962
- });
47963
- };
47964
- /**
47965
- * 检查变量声明 - 兼容TSXComplianceChecker的逻辑
47966
- */
47967
- UnifiedTSXValidator.prototype.checkVariableDeclarations = function (ast, issues) {
47968
- var _this = this;
47969
- this.log('开始检查变量声明');
47970
- traverse__default["default"](ast, {
47971
- VariableDeclarator: function (path) {
47972
- // 检查是否在 render 方法中
47973
- var renderMethod = path.findParent(function (p) {
47974
- return p.isClassMethod() &&
47975
- t__namespace.isIdentifier(p.node.key) &&
47976
- p.node.key.name === 'render';
47977
- });
47978
- if (!renderMethod)
47979
- return;
47980
- // 检查是否在事件处理函数中
47981
- if (_this.isInEventHandler(path))
47982
- return;
47983
- // 检查是否在非JSX回调函数中
47984
- if (_this.isInNonJSXCallback(path))
47985
- return;
47986
- // 检查是否在返回JSX的回调函数中
47987
- if (_this.isInJSXCallback(path)) {
47988
- issues.push(_this.createIssueFromNode('CALLBACK_VARIABLE_DECLARATION', 'error', '返回JSX的回调函数中不能包含变量声明', '将变量声明移到回调函数外部,或使用内联表达式', path.node));
47989
- return;
47990
- }
47991
- // 其他在render方法中的变量声明都是错误的
47992
- issues.push(_this.createIssueFromNode('RENDER_VARIABLE_DECLARATION', 'error', 'render()方法中不能包含变量声明', '移除所有const/let/var声明,直接使用this.state.xxx', path.node));
47993
- },
47994
- });
47995
- };
47996
- /**
47997
- * 检查条件渲染
47998
- */
47999
- UnifiedTSXValidator.prototype.checkConditionalRendering = function (ast, issues) {
48000
- var _this = this;
48001
- this.log('开始检查条件渲染');
48002
- traverse__default["default"](ast, {
48003
- JSXExpressionContainer: function (path) {
48004
- var expression = path.node.expression;
48005
- if (expression.type === 'LogicalExpression') {
48006
- // 检查右侧是否包含JSX元素
48007
- var hasJSXInRight = _this.hasJSXInNode(expression.right);
48008
- if (hasJSXInRight && expression.operator !== '&&') {
48009
- issues.push(_this.createIssueFromNode('INVALID_CONDITIONAL_OPERATOR', 'error', '条件渲染必须使用&&运算符,不支持其他运算符', '请使用 && 运算符进行条件渲染', path.node));
48010
- }
48011
- if (hasJSXInRight && expression.left.type === 'Identifier') {
48012
- issues.push(_this.createIssueFromNode('VARIABLE_IN_CONDITIONAL', 'error', '条件渲染中不允许使用变量', '请直接使用this.state访问状态', path.node));
48013
- }
48014
- }
48015
- },
48016
- });
48017
- };
48018
- /**
48019
- * 检查列表渲染
48020
- */
48021
- UnifiedTSXValidator.prototype.checkListRendering = function (ast, issues) {
48022
- var _this = this;
48023
- this.log('开始检查列表渲染');
48024
- traverse__default["default"](ast, {
48025
- CallExpression: function (path) {
48026
- if (path.node.callee.type === 'MemberExpression' &&
48027
- path.node.callee.property.name === 'map') {
48028
- // 检查是否在render方法的JSX中使用
48029
- if (_this.isInRenderJSX(path)) {
48030
- var parent_1 = path.parentPath;
48031
- if (parent_1.node.type === 'VariableDeclaration') {
48032
- issues.push(_this.createIssueFromNode('LIST_RENDER_VARIABLE', 'error', '列表渲染中不允许使用变量', '请直接使用map方法渲染', path.node));
48033
- }
48034
- }
48035
- }
48036
- },
48037
- });
48038
- };
48039
- /**
48040
- * 检查样式使用
48041
- */
48042
- UnifiedTSXValidator.prototype.checkStyleUsage = function (ast, issues) {
48043
- var _this = this;
48044
- this.log('开始检查样式使用');
48045
- traverse__default["default"](ast, {
48046
- JSXAttribute: function (path) {
48047
- var _a;
48048
- if (path.node.name.name === 'inlineStyle') {
48049
- var parent_2 = path.parentPath.node;
48050
- var componentName = (_a = parent_2.name) === null || _a === void 0 ? void 0 : _a.name;
48051
- if (componentName !== 'View' && componentName !== 'Text') {
48052
- issues.push(_this.createIssueFromNode('INVALID_INLINE_STYLE', 'error', 'inlineStyle属性仅支持View和Text组件使用', '请检查组件类型或使用其他样式属性', path.node));
48053
- }
48054
- }
48055
- },
48056
- });
48057
- };
48058
- /**
48059
- * 检查状态管理
48526
+ * 检查变量声明
48060
48527
  */
48061
- UnifiedTSXValidator.prototype.checkStateManagement = function (ast, issues) {
48062
- var _this = this;
48063
- this.log('开始检查状态管理');
48064
- traverse__default["default"](ast, {
48065
- AssignmentExpression: function (path) {
48066
- if (_this.isDirectStateMutation(path.node.left)) {
48067
- issues.push(_this.createIssueFromNode('DIRECT_STATE_MUTATION', 'error', '不允许直接修改state', '请使用this.setState方法', path.node));
48068
- }
48069
- },
48070
- });
48528
+ TSXComplianceChecker.checkVariableDeclaration = function (path, content, issues) {
48529
+ // 现在的代码生成策略允许在 render 中声明变量(用于变量提升),
48530
+ // 也允许在 map 回调中声明变量(用于循环内部变量)。
48531
+ // 因此,不再对 render 方法内的变量声明进行限制。
48532
+ return;
48071
48533
  };
48072
48534
  /**
48073
- * 检查数据源使用
48535
+ * 检查是否在事件处理函数中
48074
48536
  */
48075
- UnifiedTSXValidator.prototype.checkDataSourceUsage = function (ast, issues) {
48076
- var _this = this;
48077
- this.log('开始检查数据源使用');
48078
- traverse__default["default"](ast, {
48079
- CallExpression: function (path) {
48080
- var _a;
48081
- if (_this.isDataSourceLoadCall(path.node)) {
48082
- var isInRender = false;
48083
- var isInCallback = false;
48084
- var currentPath = path;
48085
- while (currentPath) {
48086
- var node = currentPath.node;
48087
- if (node.type === 'ClassMethod' && ((_a = node.key) === null || _a === void 0 ? void 0 : _a.name) === 'render') {
48088
- isInRender = true;
48089
- }
48090
- if ((node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression')) {
48091
- var parentPath = currentPath.parentPath;
48092
- if ((parentPath === null || parentPath === void 0 ? void 0 : parentPath.node.type) === 'JSXExpressionContainer') {
48093
- isInCallback = true;
48094
- break;
48095
- }
48096
- }
48097
- currentPath = currentPath.parentPath;
48098
- }
48099
- if (isInRender && !isInCallback) {
48100
- issues.push(_this.createIssueFromNode('DATA_SOURCE_IN_RENDER', 'error', 'render方法中不允许直接调用数据源', '请在回调函数中调用数据源', path.node));
48101
- }
48102
- }
48103
- },
48104
- });
48105
- };
48106
- // ========== 辅助方法 ==========
48107
- UnifiedTSXValidator.prototype.isReactComponent = function (superClass) {
48108
- if (!superClass)
48109
- return false;
48110
- // 支持 extends React.Component
48111
- if (superClass.type === 'MemberExpression' &&
48112
- superClass.object.name === 'React' &&
48113
- superClass.property.name === 'Component') {
48114
- return true;
48115
- }
48116
- // 支持 extends Component 和 extends Component<IProps, IState>
48117
- // 泛型参数不会影响标识符本身的识别
48118
- if (superClass.type === 'Identifier' &&
48119
- superClass.name === 'Component') {
48120
- return true;
48121
- }
48122
- // 额外检查:如果父节点是TSExpressionWithTypeArguments,检查其expression
48123
- // 这种情况出现在 extends Component<IProps, IState> 中
48124
- if (superClass.type === 'TSExpressionWithTypeArguments' &&
48125
- superClass.expression &&
48126
- superClass.expression.type === 'Identifier' &&
48127
- superClass.expression.name === 'Component') {
48128
- return true;
48129
- }
48130
- return false;
48131
- };
48132
- UnifiedTSXValidator.prototype.isReactComponentSuperClass = function (path) {
48133
- var superClass = path.node.superClass;
48134
- return this.isReactComponent(superClass);
48135
- };
48136
- UnifiedTSXValidator.prototype.hasJSXInNode = function (node) {
48137
- if (!node)
48138
- return false;
48139
- if (node.type === 'JSXElement' || node.type === 'JSXFragment')
48140
- return true;
48141
- if (node.type === 'ConditionalExpression') {
48142
- return this.hasJSXInNode(node.consequent) || this.hasJSXInNode(node.alternate);
48143
- }
48144
- return false;
48145
- };
48146
- UnifiedTSXValidator.prototype.isInEventHandler = function (path) {
48537
+ TSXComplianceChecker.isInEventHandler = function (path) {
48538
+ // 查找父级 JSX 属性
48147
48539
  var jsxAttribute = path.findParent(function (p) { return p.isJSXAttribute(); });
48148
48540
  if (jsxAttribute && t__namespace.isJSXIdentifier(jsxAttribute.node.name)) {
48149
48541
  var attrName = jsxAttribute.node.name.name;
48542
+ // 检查是否是事件处理属性(onXxx)
48150
48543
  if (/^on[A-Z]/.test(attrName)) {
48151
48544
  return true;
48152
48545
  }
48153
48546
  }
48547
+ // 检查是否在 addEventListener 回调中
48548
+ var callExpression = path.findParent(function (p) { return p.isCallExpression(); });
48549
+ if (callExpression && t__namespace.isMemberExpression(callExpression.node.callee)) {
48550
+ var memberExpr = callExpression.node.callee;
48551
+ if (t__namespace.isIdentifier(memberExpr.property) &&
48552
+ memberExpr.property.name === 'addEventListener') {
48553
+ return true;
48554
+ }
48555
+ }
48154
48556
  return false;
48155
48557
  };
48156
- UnifiedTSXValidator.prototype.isInNonJSXCallback = function (path) {
48558
+ /**
48559
+ * 检查是否在非 JSX 返回的回调函数中
48560
+ */
48561
+ TSXComplianceChecker.isInNonJSXCallback = function (path) {
48562
+ // 查找父级函数
48157
48563
  var parentFunction = path.findParent(function (p) { return p.isArrowFunctionExpression() || p.isFunctionExpression(); });
48158
48564
  if (!parentFunction)
48159
48565
  return false;
48160
- var jsxAttribute = parentFunction.findParent(function (p) { return p.isJSXAttribute(); });
48566
+ // 检查是否在 JSX 属性回调中(如 beforeUpload, customRequest 等)
48567
+ var jsxAttribute = parentFunction.findParent(function (p) {
48568
+ return p.isJSXAttribute();
48569
+ });
48161
48570
  if (jsxAttribute && t__namespace.isJSXIdentifier(jsxAttribute.node.name)) {
48162
48571
  var attrName = jsxAttribute.node.name.name;
48572
+ // 这些属性通常不返回 JSX
48163
48573
  var nonJSXAttributes = [
48164
- 'beforeUpload', 'customRequest', 'onChange', 'onFinish',
48165
- 'onSubmit', 'onSuccess', 'onError', 'onProgress', 'request', 'dataHandler'
48574
+ 'beforeUpload',
48575
+ 'customRequest',
48576
+ 'onChange',
48577
+ 'onFinish',
48578
+ 'onSubmit',
48579
+ 'onSuccess',
48580
+ 'onError',
48581
+ 'onProgress',
48582
+ 'request',
48583
+ 'dataHandler',
48166
48584
  ];
48167
48585
  if (nonJSXAttributes.includes(attrName)) {
48168
48586
  return true;
48169
48587
  }
48170
48588
  }
48171
- return !this.functionReturnsJSX(parentFunction);
48589
+ // 检查函数是否返回 JSX
48590
+ var returnsJSX = this.functionReturnsJSX(parentFunction);
48591
+ // 如果不返回 JSX,则认为是非 JSX 回调
48592
+ return !returnsJSX;
48172
48593
  };
48173
- UnifiedTSXValidator.prototype.isInJSXCallback = function (path) {
48594
+ /**
48595
+ * 检查是否在返回 JSX 的回调函数中
48596
+ */
48597
+ TSXComplianceChecker.isInJSXCallback = function (path) {
48598
+ // 查找父级函数
48174
48599
  var parentFunction = path.findParent(function (p) { return p.isArrowFunctionExpression() || p.isFunctionExpression(); });
48175
48600
  if (!parentFunction)
48176
48601
  return false;
48602
+ // 检查函数是否返回 JSX
48177
48603
  return this.functionReturnsJSX(parentFunction);
48178
48604
  };
48179
- UnifiedTSXValidator.prototype.functionReturnsJSX = function (functionPath) {
48605
+ /**
48606
+ * 检查函数是否返回 JSX
48607
+ */
48608
+ TSXComplianceChecker.functionReturnsJSX = function (functionPath) {
48180
48609
  var returnsJSX = false;
48181
48610
  functionPath.traverse({
48182
48611
  ReturnStatement: function (path) {
@@ -48185,6 +48614,7 @@ var UnifiedTSXValidator = /** @class */ (function () {
48185
48614
  }
48186
48615
  },
48187
48616
  JSXElement: function (path) {
48617
+ // 如果函数体直接包含 JSX(箭头函数的隐式返回)
48188
48618
  if (path.parent === functionPath.node.body) {
48189
48619
  returnsJSX = true;
48190
48620
  }
@@ -48192,280 +48622,76 @@ var UnifiedTSXValidator = /** @class */ (function () {
48192
48622
  });
48193
48623
  return returnsJSX;
48194
48624
  };
48195
- UnifiedTSXValidator.prototype.isInRenderJSX = function (path) {
48196
- var isInRender = false;
48197
- var isInJSX = false;
48198
- var currentPath = path;
48199
- while (currentPath) {
48200
- if (currentPath.node.type === 'ClassMethod' && currentPath.node.key.name === 'render') {
48201
- isInRender = true;
48202
- }
48203
- if (currentPath.node.type === 'JSXExpressionContainer') {
48204
- isInJSX = true;
48205
- }
48206
- currentPath = currentPath.parentPath;
48207
- }
48208
- return isInRender && isInJSX;
48209
- };
48210
- UnifiedTSXValidator.prototype.isDirectStateMutation = function (left) {
48211
- return (left.type === 'MemberExpression' &&
48212
- left.object.type === 'MemberExpression' &&
48213
- left.object.object.type === 'ThisExpression' &&
48214
- left.object.property.name === 'state');
48215
- };
48216
- UnifiedTSXValidator.prototype.isDataSourceLoadCall = function (node) {
48217
- return (node.callee.type === 'MemberExpression' &&
48218
- node.callee.object.type === 'MemberExpression' &&
48219
- node.callee.object.object.type === 'MemberExpression' &&
48220
- node.callee.object.object.object.type === 'ThisExpression' &&
48221
- node.callee.object.object.property.name === 'dataSourceMap' &&
48222
- node.callee.property.name === 'load');
48223
- };
48224
- UnifiedTSXValidator.prototype.createIssueFromNode = function (code, type, message, suggestion, node) {
48225
- var loc = node.loc;
48226
- return {
48227
- type: type,
48228
- code: code,
48229
- message: message,
48230
- suggestion: suggestion,
48231
- line: loc ? loc.start.line : 1,
48232
- column: loc ? loc.start.column : 0,
48233
- };
48234
- };
48235
- UnifiedTSXValidator.prototype.createIssue = function (code, type, message, suggestion, line, column) {
48236
- if (column === void 0) { column = 0; }
48237
- return {
48238
- type: type,
48239
- code: code,
48240
- message: message,
48241
- suggestion: suggestion,
48242
- line: line,
48243
- column: column,
48244
- };
48245
- };
48246
48625
  /**
48247
- * 检查TypeScript语法在组件方法中
48626
+ * 检查方法定义
48248
48627
  */
48249
- UnifiedTSXValidator.prototype.checkTypeScriptSyntaxInMethods = function (ast, issues) {
48250
- var _this = this;
48251
- this.log('开始检查TypeScript语法在组件方法中');
48252
- // 找到React组件类并检查方法
48253
- traverse__default["default"](ast, {
48254
- ClassDeclaration: function (path) {
48255
- var _a;
48256
- if (_this.isReactComponent(path.node.superClass)) {
48257
- var className = (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name;
48258
- _this.log("\u68C0\u67E5TypeScript\u8BED\u6CD5\u5728\u7EC4\u4EF6\u7C7B: ".concat(className));
48259
- // 检查类中的所有方法
48260
- path.node.body.body.forEach(function (member) {
48261
- var _a;
48262
- if (member.type === 'ClassMethod') {
48263
- var methodName_1 = (_a = member.key) === null || _a === void 0 ? void 0 : _a.name;
48264
- // 跳过render方法的TypeScript语法检查(render方法本身已经单独处理)
48265
- if (methodName_1 === 'render')
48266
- return;
48267
- // 检查方法参数中的TypeScript语法
48268
- member.params.forEach(function (param, index) {
48269
- // 检查是否有类型注解
48270
- if (param.typeAnnotation) {
48271
- 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));
48272
- }
48273
- });
48274
- // 检查方法返回值的TypeScript语法
48275
- if (member.returnType) {
48276
- 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));
48277
- }
48278
- // 检查方法中是否包含JSX返回
48279
- if (_this.methodContainsJSX(member)) {
48280
- issues.push(_this.createIssueFromNode('METHOD_CONTAINS_JSX', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u4E0D\u80FD\u5305\u542B JSX \u8BED\u6CD5"), '只有 render() 方法可以包含 JSX,其他方法只处理逻辑', member));
48281
- }
48282
- // 检查方法体中的变量声明的TypeScript语法
48283
- // 直接遍历AST节点而不使用traverse
48284
- _this.checkVariableTypeAnnotationsInNode(member, methodName_1, issues);
48285
- }
48286
- });
48287
- }
48288
- },
48289
- });
48290
- };
48291
- /**
48292
- * 检查方法中是否包含JSX语法
48293
- */
48294
- UnifiedTSXValidator.prototype.methodContainsJSX = function (methodNode) {
48295
- var e_4, _a;
48296
- if (!methodNode || !methodNode.body)
48297
- return false;
48298
- var containsJSX = false;
48299
- var checkJSX = function (node) {
48300
- if (!node)
48628
+ TSXComplianceChecker.checkMethodDefinition = function (path, content, issues) {
48629
+ var node = path.node;
48630
+ // 跳过 render 方法和渲染相关方法
48631
+ if (t__namespace.isIdentifier(node.key)) {
48632
+ var methodName = node.key.name;
48633
+ var renderMethods = [
48634
+ 'render',
48635
+ 'renderItem',
48636
+ 'renderContent',
48637
+ 'renderHeader',
48638
+ 'renderFooter',
48639
+ ];
48640
+ if (renderMethods.includes(methodName))
48301
48641
  return;
48302
- if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
48303
- containsJSX = true;
48304
- return true; // 找到JSX,停止递归
48305
- }
48306
- // 递归检查子节点
48307
- for (var key in node) {
48308
- if (node[key] && typeof node[key] === 'object') {
48309
- if (checkJSX(node[key])) {
48310
- return true;
48311
- }
48312
- }
48313
- }
48314
- return false;
48315
- };
48316
- // 检查方法体中的所有语句
48317
- if (Array.isArray(methodNode.body.body)) {
48318
- try {
48319
- for (var _b = __values(methodNode.body.body), _c = _b.next(); !_c.done; _c = _b.next()) {
48320
- var statement = _c.value;
48321
- if (checkJSX(statement)) {
48322
- return true;
48323
- }
48324
- }
48325
- }
48326
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
48327
- finally {
48328
- try {
48329
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
48330
- }
48331
- finally { if (e_4) throw e_4.error; }
48332
- }
48333
- }
48334
- else if (methodNode.body) {
48335
- if (checkJSX(methodNode.body)) {
48336
- return true;
48337
- }
48338
- }
48339
- return containsJSX;
48340
- };
48341
- /**
48342
- * 递归检查节点中的变量类型注解
48343
- */
48344
- UnifiedTSXValidator.prototype.checkVariableTypeAnnotationsInNode = function (node, methodName, issues) {
48345
- var _this = this;
48346
- if (!node)
48347
- return;
48348
- // 如果是数组,遍历每个元素
48349
- if (Array.isArray(node)) {
48350
- node.forEach(function (item) { return _this.checkVariableTypeAnnotationsInNode(item, methodName, issues); });
48351
- return;
48352
- }
48353
- // 检查变量声明
48354
- if (node.type === 'VariableDeclaration') {
48355
- node.declarations.forEach(function (declaration) {
48356
- if (declaration.id && declaration.id.typeAnnotation) {
48357
- 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));
48358
- }
48642
+ // 检查方法中是否包含 JSX
48643
+ var containsJSX_1 = false;
48644
+ path.traverse({
48645
+ JSXElement: function () {
48646
+ containsJSX_1 = true;
48647
+ },
48359
48648
  });
48360
- }
48361
- // 递归检查子节点
48362
- if (node.body && Array.isArray(node.body)) {
48363
- node.body.forEach(function (child) { return _this.checkVariableTypeAnnotationsInNode(child, methodName, issues); });
48364
- }
48365
- else if (node.body) {
48366
- this.checkVariableTypeAnnotationsInNode(node.body, methodName, issues);
48367
- }
48368
- if (node.consequent) {
48369
- this.checkVariableTypeAnnotationsInNode(node.consequent, methodName, issues);
48370
- }
48371
- if (node.alternate) {
48372
- this.checkVariableTypeAnnotationsInNode(node.alternate, methodName, issues);
48373
- }
48374
- if (node.expression) {
48375
- this.checkVariableTypeAnnotationsInNode(node.expression, methodName, issues);
48649
+ if (containsJSX_1) {
48650
+ var _a = this.getLocation(path, content), line = _a.line, column = _a.column;
48651
+ var snippet = this.extractCodeSnippet(content, line);
48652
+ issues.push({
48653
+ type: 'error',
48654
+ code: 'METHOD_CONTAINS_JSX',
48655
+ message: "\u65B9\u6CD5 ".concat(methodName, " \u4E0D\u80FD\u5305\u542B JSX \u8BED\u6CD5"),
48656
+ suggestion: '只有 render() 方法可以包含 JSX,其他方法只处理逻辑',
48657
+ line: line,
48658
+ column: column,
48659
+ codeSnippet: snippet.snippet,
48660
+ snippetStartLine: snippet.startLine,
48661
+ snippetEndLine: snippet.endLine,
48662
+ });
48663
+ }
48376
48664
  }
48377
48665
  };
48378
48666
  /**
48379
- * 安全地执行检查方法,避免异常传播
48667
+ * 检查 JSX 使用
48380
48668
  */
48381
- UnifiedTSXValidator.prototype.safeCheck = function (methodName, checkFunction) {
48382
- try {
48383
- checkFunction();
48384
- }
48385
- catch (error) {
48386
- this.log("".concat(methodName, " \u68C0\u67E5\u65F6\u53D1\u751F\u9519\u8BEF: ").concat(error.message));
48387
- // 不抛出异常,只记录日志
48388
- }
48389
- };
48390
- UnifiedTSXValidator.prototype.log = function (message) {
48391
- if (this.debug) {
48392
- console.log("[UnifiedTSXValidator] ".concat(message));
48393
- }
48669
+ TSXComplianceChecker.checkJSXUsage = function (path, content, issues) {
48670
+ // 暂时不实现,专注于变量声明检查
48394
48671
  };
48395
48672
  /**
48396
- * 生成简化的错误信息(兼容编辑器使用)
48673
+ * 检查类型注解
48397
48674
  */
48398
- UnifiedTSXValidator.prototype.generateSimpleErrors = function (result) {
48399
- return result.issues
48400
- .filter(function (issue) { return issue.type === 'error'; })
48401
- .map(function (issue) {
48402
- var location = issue.line ? " (\u7B2C".concat(issue.line, "\u884C)") : '';
48403
- return "[".concat(issue.code, "] ").concat(issue.message).concat(location);
48404
- });
48675
+ TSXComplianceChecker.checkTypeAnnotation = function (path, content, issues) {
48676
+ // 暂时不实现,专注于变量声明检查
48405
48677
  };
48406
48678
  /**
48407
- * 生成详细报告(兼容CLI使用)
48679
+ * 检查必需的结构
48408
48680
  */
48409
- UnifiedTSXValidator.prototype.generateReport = function (result) {
48410
- var isCompliant = result.isCompliant, issues = result.issues;
48411
- var report = '=== TSX 规范检查报告 ===\n';
48412
- report += "\u6587\u4EF6: ".concat(this.filename, "\n");
48413
- if (isCompliant) {
48414
- report += '✅ 检查通过:文件符合 TSX 规范\n';
48415
- }
48416
- else {
48417
- var errorCount = issues.filter(function (issue) { return issue.type === 'error'; }).length;
48418
- report += "\u274C \u68C0\u67E5\u5931\u8D25\uFF1A\u53D1\u73B0 ".concat(errorCount, " \u4E2A\u9519\u8BEF\n\n");
48419
- report += '--- 问题详情 ---\n';
48420
- issues.forEach(function (issue, index) {
48421
- var icon = issue.type === 'error' ? '❌' : '⚠️';
48422
- report += "".concat(index + 1, ". ").concat(icon, " [").concat(issue.code, "] ").concat(issue.message, "\n");
48423
- if (issue.line) {
48424
- report += " \uD83D\uDCCD \u4F4D\u7F6E: \u7B2C ".concat(issue.line, " \u884C\n");
48425
- }
48426
- report += " \uD83D\uDCA1 \u5EFA\u8BAE: ".concat(issue.suggestion, "\n\n");
48427
- });
48428
- }
48429
- return report;
48681
+ TSXComplianceChecker.checkRequiredStructures = function (ast, content, issues) {
48682
+ // 这里可以添加对必需结构的检查
48683
+ // IProps, IState, Document 类等
48430
48684
  };
48431
- return UnifiedTSXValidator;
48432
- }());
48433
-
48434
- var TSXComplianceChecker = /** @class */ (function () {
48435
- function TSXComplianceChecker() {
48436
- }
48437
48685
  /**
48438
- * 使用统一验证器检查 TSX 规范
48686
+ * 获取节点在源码中的位置
48439
48687
  */
48440
- TSXComplianceChecker.checkTSXCompliance = function (content, filename) {
48441
- var _this = this;
48442
- try {
48443
- var result = this.validator.validate(content, filename);
48444
- // 转换为兼容的格式
48445
- var compliantIssues = result.issues.map(function (issue) { return (__assign(__assign({}, issue), {
48446
- // 为CLI添加代码片段
48447
- 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 })); });
48448
- return {
48449
- isCompliant: result.isCompliant,
48450
- issues: compliantIssues,
48451
- };
48452
- }
48453
- catch (error) {
48454
- // 捕获任何异常并返回合规结果,而不是让异常向上传播
48455
- return {
48456
- isCompliant: false,
48457
- issues: [{
48458
- type: 'error',
48459
- code: 'VALIDATION_ERROR',
48460
- message: "\u9A8C\u8BC1\u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF: ".concat(error.message),
48461
- suggestion: '请检查代码语法或联系开发团队',
48462
- line: 1,
48463
- column: 0,
48464
- }],
48465
- };
48466
- }
48688
+ TSXComplianceChecker.getLocation = function (path, content) {
48689
+ var loc = path.node.loc;
48690
+ return {
48691
+ line: loc ? loc.start.line : 1,
48692
+ column: loc ? loc.start.column : 0,
48693
+ };
48467
48694
  };
48468
- // 移除了所有旧的检查方法,现在使用UnifiedTSXValidator
48469
48695
  /**
48470
48696
  * 提取代码片段
48471
48697
  */
@@ -48487,33 +48713,34 @@ var TSXComplianceChecker = /** @class */ (function () {
48487
48713
  };
48488
48714
  };
48489
48715
  /**
48490
- * 生成检查报告(使用统一验证器)
48716
+ * 生成检查报告
48491
48717
  */
48492
48718
  TSXComplianceChecker.generateReport = function (result, filename) {
48493
- this.validator = new UnifiedTSXValidator(false);
48494
- return this.validator.generateReport(result);
48495
- };
48496
- /**
48497
- * 提取代码片段(保留原有逻辑)
48498
- */
48499
- TSXComplianceChecker.extractCodeSnippet = function (content, lineNumber, contextLines) {
48500
- if (contextLines === void 0) { contextLines = 3; }
48501
- var lines = content.split('\n');
48502
- var startLine = Math.max(1, lineNumber - contextLines);
48503
- var endLine = Math.min(lines.length, lineNumber + contextLines);
48504
- var snippetLines = [];
48505
- for (var i = startLine; i <= endLine; i++) {
48506
- var line = lines[i - 1] || '';
48507
- var prefix = i === lineNumber ? '>>> ' : ' ';
48508
- snippetLines.push("".concat(prefix).concat(i.toString().padStart(3), ": ").concat(line));
48719
+ var isCompliant = result.isCompliant, issues = result.issues;
48720
+ var report = '=== TSX 规范检查报告 ===\n';
48721
+ report += "\u6587\u4EF6: ".concat(filename, "\n");
48722
+ if (isCompliant) {
48723
+ report += '✅ 检查通过:文件符合 TSX 规范\n';
48509
48724
  }
48510
- return {
48511
- snippet: snippetLines.join('\n'),
48512
- startLine: startLine,
48513
- endLine: endLine,
48514
- };
48725
+ else {
48726
+ var errorCount = issues.filter(function (issue) { return issue.type === 'error'; }).length;
48727
+ report += "\u274C \u68C0\u67E5\u5931\u8D25\uFF1A\u53D1\u73B0 ".concat(errorCount, " \u4E2A\u9519\u8BEF\n\n");
48728
+ report += '--- 问题详情 ---\n';
48729
+ issues.forEach(function (issue, index) {
48730
+ var icon = issue.type === 'error' ? '❌' : '⚠️';
48731
+ report += "".concat(index + 1, ". ").concat(icon, " [").concat(issue.code, "] ").concat(issue.message, "\n");
48732
+ if (issue.line) {
48733
+ report += " \uD83D\uDCCD \u4F4D\u7F6E: \u7B2C ".concat(issue.line, " \u884C\n");
48734
+ }
48735
+ report += " \uD83D\uDCA1 \u5EFA\u8BAE: ".concat(issue.suggestion, "\n");
48736
+ if (issue.codeSnippet) {
48737
+ report += " \uD83D\uDCDD \u4EE3\u7801\u7247\u6BB5:\n".concat(issue.codeSnippet, "\n");
48738
+ }
48739
+ report += '\n';
48740
+ });
48741
+ }
48742
+ return report;
48515
48743
  };
48516
- TSXComplianceChecker.validator = new UnifiedTSXValidator(false);
48517
48744
  return TSXComplianceChecker;
48518
48745
  }());
48519
48746
 
@@ -48550,11 +48777,11 @@ function checkTSX(options) {
48550
48777
  '**/.next/**',
48551
48778
  ],
48552
48779
  absolute: false,
48553
- }, function (err, files) {
48780
+ }, function (err, validatedFiles) {
48554
48781
  if (err)
48555
48782
  reject(err);
48556
48783
  else
48557
- resolve(files || []);
48784
+ resolve(validatedFiles || []);
48558
48785
  });
48559
48786
  })];
48560
48787
  case 1:
@@ -50555,6 +50782,146 @@ function getToolName(tool) {
50555
50782
  return toolChoice ? toolChoice.name : tool;
50556
50783
  }
50557
50784
 
50785
+ function startShadowSync(options) {
50786
+ return __awaiter(this, void 0, void 0, function () {
50787
+ var userId, config, shadowSpace, result, changes, changes_1, changes_1_1, change, action, filePath, side, direction, content, remoteHash, content, err_1, e_1_1, error_1;
50788
+ var e_1, _a;
50789
+ return __generator(this, function (_b) {
50790
+ switch (_b.label) {
50791
+ case 0:
50792
+ // Set auth token globally for request utils
50793
+ updateAuthToken(options.authToken);
50794
+ userId = options.userId || 'unknown-user';
50795
+ config = {
50796
+ projectRoot: options.cwd ? path__default["default"].resolve(options.cwd) : process.cwd(),
50797
+ projectId: options.projectId,
50798
+ userId: userId,
50799
+ spaceId: options.spaceId || 'default',
50800
+ };
50801
+ shadowSpace = new ShadowSpace(config);
50802
+ if (options.verbose) {
50803
+ console.log('Starting shadow sync...');
50804
+ console.log("Project ID: ".concat(config.projectId));
50805
+ console.log("Space ID: ".concat(config.spaceId));
50806
+ console.log("User ID: ".concat(config.userId));
50807
+ }
50808
+ _b.label = 1;
50809
+ case 1:
50810
+ _b.trys.push([1, 26, , 27]);
50811
+ // 使用抽象后的通用同步逻辑
50812
+ // 调用 syncWithRemote({ dryRun: true }) 获取变更
50813
+ // 然后复用 ShadowSpace 的公共方法进行处理
50814
+ console.log('Checking for changes...');
50815
+ return [4 /*yield*/, shadowSpace.syncWithRemote({ dryRun: true })];
50816
+ case 2:
50817
+ result = _b.sent();
50818
+ changes = result.changes;
50819
+ if (!(changes.length === 0)) return [3 /*break*/, 3];
50820
+ console.log('Everything is up to date.');
50821
+ return [3 /*break*/, 25];
50822
+ case 3:
50823
+ console.log("Found ".concat(changes.length, " changes."));
50824
+ _b.label = 4;
50825
+ case 4:
50826
+ _b.trys.push([4, 21, 22, 23]);
50827
+ changes_1 = __values(changes), changes_1_1 = changes_1.next();
50828
+ _b.label = 5;
50829
+ case 5:
50830
+ if (!!changes_1_1.done) return [3 /*break*/, 20];
50831
+ change = changes_1_1.value;
50832
+ action = change.action, filePath = change.path, side = change.side;
50833
+ direction = side === 'editor' ? 'Remote->Local (Pull)' : 'Local->Remote (Push)';
50834
+ console.log("Processing ".concat(action, " ").concat(filePath, " (").concat(direction, ")..."));
50835
+ _b.label = 6;
50836
+ case 6:
50837
+ _b.trys.push([6, 18, , 19]);
50838
+ if (!(side === 'editor')) return [3 /*break*/, 14];
50839
+ if (!(action === 'delete')) return [3 /*break*/, 8];
50840
+ return [4 /*yield*/, shadowSpace.deleteFile(filePath)];
50841
+ case 7:
50842
+ _b.sent();
50843
+ console.log("Deleted local file: ".concat(filePath));
50844
+ return [3 /*break*/, 13];
50845
+ case 8: return [4 /*yield*/, shadowSpace.downloadRemoteFile(filePath)];
50846
+ case 9:
50847
+ content = _b.sent();
50848
+ remoteHash = change.editorHash;
50849
+ if (!remoteHash) return [3 /*break*/, 11];
50850
+ return [4 /*yield*/, shadowSpace.updateFileFromRemote(filePath, content, remoteHash)];
50851
+ case 10:
50852
+ _b.sent();
50853
+ console.log("Updated local file: ".concat(filePath, " (with remoteHash)"));
50854
+ return [3 /*break*/, 13];
50855
+ case 11: return [4 /*yield*/, shadowSpace.updateFile(filePath, content)];
50856
+ case 12:
50857
+ _b.sent();
50858
+ console.log("Updated local file: ".concat(filePath));
50859
+ _b.label = 13;
50860
+ case 13: return [3 /*break*/, 17];
50861
+ case 14:
50862
+ if (!(side === 'space')) return [3 /*break*/, 17];
50863
+ if (!(action === 'delete')) return [3 /*break*/, 15];
50864
+ console.warn("Skipping remote delete for: ".concat(filePath, " (Not supported)"));
50865
+ return [3 /*break*/, 17];
50866
+ case 15: return [4 /*yield*/, shadowSpace.getShadowContent(filePath)];
50867
+ case 16:
50868
+ content = _b.sent();
50869
+ if (content !== null) {
50870
+ // DryRun for Push
50871
+ console.log("[DryRun] Would upload remote file: ".concat(filePath));
50872
+ // 注意:在 DryRun 模式下,我们不能更新 remoteHash,因为没有真实上传,
50873
+ // 远端的 Hash 依然是旧的。如果现在更新了 remoteHash,下次比对就会出错。
50874
+ // 所以这里什么都不做。
50875
+ }
50876
+ else {
50877
+ console.error("Failed to read local content for: ".concat(filePath));
50878
+ }
50879
+ _b.label = 17;
50880
+ case 17: return [3 /*break*/, 19];
50881
+ case 18:
50882
+ err_1 = _b.sent();
50883
+ console.error("Failed to process ".concat(filePath, ":"), err_1);
50884
+ return [3 /*break*/, 19];
50885
+ case 19:
50886
+ changes_1_1 = changes_1.next();
50887
+ return [3 /*break*/, 5];
50888
+ case 20: return [3 /*break*/, 23];
50889
+ case 21:
50890
+ e_1_1 = _b.sent();
50891
+ e_1 = { error: e_1_1 };
50892
+ return [3 /*break*/, 23];
50893
+ case 22:
50894
+ try {
50895
+ if (changes_1_1 && !changes_1_1.done && (_a = changes_1.return)) _a.call(changes_1);
50896
+ }
50897
+ finally { if (e_1) throw e_1.error; }
50898
+ return [7 /*endfinally*/];
50899
+ case 23:
50900
+ // Save state after sync
50901
+ return [4 /*yield*/, shadowSpace.saveState()];
50902
+ case 24:
50903
+ // Save state after sync
50904
+ _b.sent();
50905
+ _b.label = 25;
50906
+ case 25: return [3 /*break*/, 27];
50907
+ case 26:
50908
+ error_1 = _b.sent();
50909
+ console.error('Shadow sync failed:', error_1);
50910
+ process.exit(1);
50911
+ return [3 /*break*/, 27];
50912
+ case 27:
50913
+ if (options.watch) {
50914
+ shadowSpace.startWatching();
50915
+ console.log('Watching for file changes...');
50916
+ // Keep process alive
50917
+ return [2 /*return*/, new Promise(function () { })];
50918
+ }
50919
+ return [2 /*return*/];
50920
+ }
50921
+ });
50922
+ });
50923
+ }
50924
+
50558
50925
  exports.ShadowSpace = ShadowSpace;
50559
50926
  exports.ShadowSpaceDebugger = ShadowSpaceDebugger;
50560
50927
  exports.TSXComplianceChecker = TSXComplianceChecker;
@@ -50579,6 +50946,7 @@ exports.releaseMaterial = releaseMaterial;
50579
50946
  exports.run = run;
50580
50947
  exports.startConnecting = startConnecting;
50581
50948
  exports.startProxy = startProxy;
50949
+ exports.startShadowSync = startShadowSync;
50582
50950
  exports.startWatching = startWatching;
50583
50951
  exports.stopConnecting = stopConnecting;
50584
50952
  exports.stopProxy = stopProxy;