@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.
- package/.gitignore +1 -0
- package/bin/main.js +45 -0
- package/dist/index.js +1277 -909
- package/package.json +1 -1
- package/tests/test-app/.appthen/shadow-space-100001-test-app-e99876b1.json +1406 -0
- package/tests/test-app/.appthen/shadow-space-unknown-user-test-app-e99876b1.json +1060 -0
- package/tests/test-app/.appthen/space-config.json +8 -0
- package/tests/test-app/docs/AI-Workflow.flow +112 -0
- package/tests/test-app/docs/Logic-1.flow +16 -0
- package/tests/test-app/docs/Logic.flow +16 -0
- package/tests/test-app/docs/Project-Blueprint-1.flow +119 -0
- package/tests/test-app/docs/Project-Blueprint.flow +119 -0
- package/tests/test-app/docs/README.md +3 -0
- package/tests/test-app/docs/claude.md +194 -0
- package/tests/test-app/docs/page_requirement_analysis.md +149 -0
- 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
- package/tests/test-app/src/apis/AddTodoPost.api.ts +42 -0
- package/tests/test-app/src/apis/DeleteTodoPost.api.ts +32 -0
- package/tests/test-app/src/apis/GetListPost.api.ts +38 -0
- package/tests/test-app/src/apis/TicketAttachmentUploadPost.api.ts +42 -0
- package/tests/test-app/src/apis/UpdateTodoPost.api.ts +46 -0
- package/tests/test-app/src/app.css +15 -0
- package/tests/test-app/src/cloud_functions/ticket|attachment|upload.node.ts +86 -0
- package/tests/test-app/src/cloud_functions/ticket|comment|add.node.ts +65 -0
- package/tests/test-app/src/cloud_functions/types|entity|Ticket.node.ts +88 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketAttachment.node.ts +70 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketCategory.node.ts +56 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketComment.node.ts +62 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketHistory.node.ts +74 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketPriority.node.ts +68 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketStatus.node.ts +63 -0
- package/tests/test-app/src/cloud_functions/types|models|CreateTicketParams.node.ts +20 -0
- package/tests/test-app/src/cloud_functions/types|models|TicketListParams.node.ts +30 -0
- package/tests/test-app/src/cloud_functions/types|models|UpdateTicketParams.node.ts +22 -0
- package/tests/test-app/src/components/Button.js +11 -0
- package/tests/test-app/src/components/MouduleDemoNzp.tsx +40 -0
- package/tests/test-app/src/components/Timeline.tsx +145 -0
- package/tests/test-app/src/index.ts +2 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketCommentAddPost.api.ts +48 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketCreatePost.api.ts +52 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketDeleteDelete.api.ts +39 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketDetailGet.api.ts +39 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketListGet.api.ts +61 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketUpdatePut.api.ts +57 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorFaultListGet.ts +76 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorListGet.ts +76 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorOperationRecordsGet.ts +284 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorStatisticsGet.ts +96 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/category|list.node.ts +40 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/priority|list.node.ts +26 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/status|list.node.ts +26 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|create.node.ts +54 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|delete.node.ts +55 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|detail.node.ts +65 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|list.node.ts +85 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|update.node.ts +73 -0
- package/tests/test-app/src/modules/work_order_module/data_model/Ticket.m.ts +85 -0
- package/tests/test-app/src/modules/work_order_module/data_model/TicketCategory.m.ts +53 -0
- package/tests/test-app/src/modules/work_order_module/data_model/TicketStatus.m.ts +60 -0
- 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
- 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
- package/tests/test-app/src/pages/SLAManagement.tsx +668 -0
- package/tests/test-app/src/pages/TicketCreate.tsx +27 -0
- package/tests/test-app/src/pages/TicketDetail.tsx +27 -0
- package/tests/test-app/src/pages/TicketList.tsx +27 -0
- package/tests/test-app/src/pages/TicketManagementPage.tsx +1238 -0
- package/tests/test-app/src/pages/VisualAIIDEUpgrade.tsx +245 -0
- package/tests/test-app/src/pages/appthen_guide/ComponentTreeUnderstanding.tsx +26 -0
- package/tests/test-app/src/pages/appthen_guide/DataBindingLearning.tsx +26 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout.tsx +155 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout10.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout2.tsx +156 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout3.tsx +156 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout4.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout5.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout6.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout7.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout8.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout9.tsx +157 -0
- package/tests/test-app/src/pages/back-end/backgroundManagementSystem.css +5 -0
- package/tests/test-app/src/pages/back-end/backgroundManagementSystem.tsx +1745 -0
- package/tests/test-app/src/pages/component/WorkOrderCard.tsx +140 -0
- package/tests/test-app/src/pages/cover.tsx +42 -0
- package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.css +181 -0
- package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.tsx +225 -0
- package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.css +181 -0
- package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.tsx +138 -0
- package/tests/test-app/src/pages/data_dashboard/component_library/BlueBrightGreenBorder.tsx +47 -0
- package/tests/test-app/src/pages/data_dashboard/component_library/FullScreenContainer.tsx +133 -0
- package/tests/test-app/src/pages/description_of_mock_interface.md +32 -0
- package/tests/test-app/src/pages/digitalLargeScreen.css +181 -0
- package/tests/test-app/src/pages/digitalLargeScreen.tsx +1417 -0
- package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.css +3 -0
- package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.tsx +362 -0
- package/tests/test-app/src/pages/mobile_terminal/WorkOrderHomepage.tsx +337 -0
- package/tests/test-app/src/pages/mobile_terminal/newWorkOrder.tsx +224 -0
- package/tests/test-app/src/pages/mobile_terminal/tabbar.tsx +67 -0
- package/tests/test-app/src/pages/mobile_terminal/uiHandsOnPractice.tsx +638 -0
- package/tests/test-app/src/pages/mobile_terminal/workOrderDetails.tsx +346 -0
- package/tests/test-app/src/pages/mobile_terminal/workOrderPage.tsx +345 -0
- package/tests/test-app/src/pages/testPage.css +3 -0
- package/tests/test-app/src/pages/testPage.tsx +158 -0
- package/tests/test-app/src/pages/web_version/website.css +205 -0
- package/tests/test-app/src/pages/web_version/website.tsx +1066 -0
- package/tests/test-app/src/pages//345/276/205/345/212/236.apidoc.json +336 -0
- package/tests/test-app/src/project.json +1120 -0
- package/tests/test-app/src/store/global.store.ts +10 -0
- package/tests/test-app/src/types/CreateTicketParams.m.ts +20 -0
- package/tests/test-app/src/types/SLAPolicy.ts +50 -0
- package/tests/test-app/src/types/Ticket.ts +68 -0
- package/tests/test-app/src/types/TicketAttachment.m.ts +67 -0
- package/tests/test-app/src/types/TicketComment.m.ts +59 -0
- package/tests/test-app/src/types/TicketEvaluation.ts +44 -0
- package/tests/test-app/src/types/TicketHistory.m.ts +71 -0
- package/tests/test-app/src/types/TicketListParams.m.ts +30 -0
- package/tests/test-app/src/types/TicketPriority.m.ts +65 -0
- package/tests/test-app/src/types/TicketRecord.ts +47 -0
- package/tests/test-app/src/types/TrainDoor.ts +284 -0
- package/tests/test-app/src/types/UpdateTicketParams.m.ts +22 -0
- package/tests/test-app/src/utils/__afterRequest.util.ts +3 -0
- package/tests/test-app/src/utils/__beforeRequest.util.ts +10 -0
- 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
|
|
2808
|
+
var hasFlag = (flag, argv) => {
|
|
2809
|
+
argv = argv || process.argv;
|
|
2809
2810
|
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
|
|
2810
|
-
const
|
|
2811
|
-
const
|
|
2812
|
-
return
|
|
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
|
|
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
|
-
|
|
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 =
|
|
2827
|
+
forceColor = true;
|
|
2828
2828
|
}
|
|
2829
|
-
|
|
2830
2829
|
if ('FORCE_COLOR' in env) {
|
|
2831
|
-
|
|
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(
|
|
2854
|
-
if (forceColor ===
|
|
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 (
|
|
2861
|
+
if (stream && !stream.isTTY && forceColor !== true) {
|
|
2869
2862
|
return 0;
|
|
2870
2863
|
}
|
|
2871
2864
|
|
|
2872
|
-
const min = forceColor
|
|
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
|
-
//
|
|
2880
|
-
//
|
|
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'
|
|
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
|
|
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:
|
|
2943
|
-
stderr:
|
|
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);
|
|
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://
|
|
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://
|
|
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
|
|
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 (
|
|
40979
|
-
switch (
|
|
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
|
-
|
|
40990
|
+
_k.label = 1;
|
|
40983
40991
|
case 1:
|
|
40984
|
-
|
|
40992
|
+
_k.trys.push([1, 16, 17, 18]);
|
|
40985
40993
|
_a = __values(Object.entries(this.state.files)), _b = _a.next();
|
|
40986
|
-
|
|
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
|
-
|
|
40999
|
+
_k.label = 3;
|
|
40992
41000
|
case 3:
|
|
40993
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 = (
|
|
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
|
-
|
|
41048
|
+
_k.label = 10;
|
|
41041
41049
|
case 10: return [3 /*break*/, 14];
|
|
41042
41050
|
case 11:
|
|
41043
|
-
error_2 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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,
|
|
41116
|
-
var
|
|
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,
|
|
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*/,
|
|
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*/,
|
|
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*/,
|
|
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
|
|
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 (
|
|
41212
|
+
finally { if (e_6) throw e_6.error; }
|
|
41157
41213
|
return [7 /*endfinally*/];
|
|
41158
|
-
case
|
|
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,
|
|
41264
|
-
var
|
|
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
|
-
|
|
41315
|
-
|
|
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 (
|
|
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
|
|
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 (
|
|
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 (
|
|
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
|
|
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 (
|
|
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 (
|
|
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,
|
|
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
|
-
|
|
41510
|
-
console.warn('[ShadowSpace] 保存空间配置失败:',
|
|
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,
|
|
41523
|
-
var
|
|
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
|
-
|
|
41576
|
-
|
|
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 (
|
|
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
|
-
|
|
41587
|
-
console.warn('[ShadowSpace] 迁移旧状态文件失败:',
|
|
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,
|
|
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
|
-
|
|
41615
|
-
console.warn("\u65E0\u6CD5\u83B7\u53D6\u5F71\u5B50\u5185\u5BB9: ".concat(filePath),
|
|
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()
|
|
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
|
|
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(/^[
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
41710
|
-
console.error("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u5931\u8D25: ".concat(fullPath),
|
|
41711
|
-
throw
|
|
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,
|
|
41720
|
-
var
|
|
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
|
-
|
|
41732
|
-
|
|
42505
|
+
globPromise = util$3.promisify(glob__default["default"]);
|
|
42506
|
+
return [4 /*yield*/, globPromise(pattern, options)];
|
|
41733
42507
|
case 1:
|
|
41734
|
-
_b.
|
|
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
|
-
|
|
41739
|
-
|
|
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
|
-
|
|
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
|
|
42524
|
+
case 5:
|
|
41748
42525
|
content = _b.sent();
|
|
41749
42526
|
return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
|
|
41750
|
-
case
|
|
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*/,
|
|
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*/,
|
|
41765
|
-
case
|
|
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 (
|
|
42551
|
+
finally { if (e_17) throw e_17.error; }
|
|
41775
42552
|
return [7 /*endfinally*/];
|
|
41776
|
-
case
|
|
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, ,
|
|
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*/,
|
|
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*/,
|
|
41831
|
-
case
|
|
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))
|
|
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,
|
|
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
|
-
|
|
41985
|
-
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath),
|
|
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,
|
|
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
|
-
|
|
42024
|
-
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath),
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
43567
|
+
console.log(" \u23F0 \u66F4\u65B0\u65F6\u95F4: ".concat(spaceInfo.lastUpdate)); // 修正属性名
|
|
42883
43568
|
require('path');
|
|
42884
43569
|
fs = require('fs-extra');
|
|
42885
|
-
spaceDir = spaceInfo.
|
|
43570
|
+
spaceDir = spaceInfo.projectRoot;
|
|
42886
43571
|
return [4 /*yield*/, fs.pathExists(spaceDir)];
|
|
42887
43572
|
case 3:
|
|
42888
43573
|
spaceExists = _a.sent();
|
|
42889
|
-
console.log(
|
|
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(
|
|
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] \
|
|
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
|
-
|
|
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
|
-
*
|
|
48479
|
+
* 使用 AST 检查 TSX 规范
|
|
47787
48480
|
*/
|
|
47788
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47802
|
-
|
|
47803
|
-
|
|
47804
|
-
|
|
47805
|
-
|
|
47806
|
-
|
|
47807
|
-
|
|
47808
|
-
|
|
47809
|
-
|
|
47810
|
-
|
|
47811
|
-
|
|
47812
|
-
|
|
47813
|
-
|
|
47814
|
-
|
|
47815
|
-
|
|
47816
|
-
|
|
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
|
-
|
|
47821
|
-
|
|
47822
|
-
|
|
47823
|
-
|
|
47824
|
-
|
|
47825
|
-
|
|
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
|
-
|
|
48062
|
-
|
|
48063
|
-
|
|
48064
|
-
|
|
48065
|
-
|
|
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
|
-
|
|
48076
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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',
|
|
48165
|
-
'
|
|
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
|
-
|
|
48589
|
+
// 检查函数是否返回 JSX
|
|
48590
|
+
var returnsJSX = this.functionReturnsJSX(parentFunction);
|
|
48591
|
+
// 如果不返回 JSX,则认为是非 JSX 回调
|
|
48592
|
+
return !returnsJSX;
|
|
48172
48593
|
};
|
|
48173
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
48626
|
+
* 检查方法定义
|
|
48248
48627
|
*/
|
|
48249
|
-
|
|
48250
|
-
var
|
|
48251
|
-
|
|
48252
|
-
|
|
48253
|
-
|
|
48254
|
-
|
|
48255
|
-
|
|
48256
|
-
|
|
48257
|
-
|
|
48258
|
-
|
|
48259
|
-
|
|
48260
|
-
|
|
48261
|
-
|
|
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
|
-
|
|
48303
|
-
|
|
48304
|
-
|
|
48305
|
-
|
|
48306
|
-
|
|
48307
|
-
|
|
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
|
-
|
|
48363
|
-
|
|
48364
|
-
|
|
48365
|
-
|
|
48366
|
-
|
|
48367
|
-
|
|
48368
|
-
|
|
48369
|
-
|
|
48370
|
-
|
|
48371
|
-
|
|
48372
|
-
|
|
48373
|
-
|
|
48374
|
-
|
|
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
|
-
|
|
48382
|
-
|
|
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
|
-
|
|
48399
|
-
|
|
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
|
-
*
|
|
48679
|
+
* 检查必需的结构
|
|
48408
48680
|
*/
|
|
48409
|
-
|
|
48410
|
-
|
|
48411
|
-
|
|
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
|
-
*
|
|
48686
|
+
* 获取节点在源码中的位置
|
|
48439
48687
|
*/
|
|
48440
|
-
TSXComplianceChecker.
|
|
48441
|
-
var
|
|
48442
|
-
|
|
48443
|
-
|
|
48444
|
-
|
|
48445
|
-
|
|
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
|
-
|
|
48494
|
-
|
|
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
|
-
|
|
48511
|
-
|
|
48512
|
-
|
|
48513
|
-
|
|
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,
|
|
48780
|
+
}, function (err, validatedFiles) {
|
|
48554
48781
|
if (err)
|
|
48555
48782
|
reject(err);
|
|
48556
48783
|
else
|
|
48557
|
-
resolve(
|
|
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;
|