@appthen/cli 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/main.js +41 -0
- package/dist/index.js +2369 -438
- package/package.json +7 -4
- package/dist/TSXComplianceChecker-AST.js +0 -321
- package/dist/TSXComplianceChecker.js +0 -683
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var prettier = require('prettier');
|
|
|
29
29
|
var fs$2 = require('fs-extra');
|
|
30
30
|
var io = require('socket.io-client');
|
|
31
31
|
var fs$3 = require('fs/promises');
|
|
32
|
+
var chokidar = require('chokidar');
|
|
32
33
|
var whatwgUrl = require('whatwg-url');
|
|
33
34
|
|
|
34
35
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -80,6 +81,7 @@ var fs__default$1 = /*#__PURE__*/_interopDefaultLegacy(fs$2);
|
|
|
80
81
|
var fs__namespace$1 = /*#__PURE__*/_interopNamespace(fs$2);
|
|
81
82
|
var io__default = /*#__PURE__*/_interopDefaultLegacy(io);
|
|
82
83
|
var fs__default$2 = /*#__PURE__*/_interopDefaultLegacy(fs$3);
|
|
84
|
+
var chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);
|
|
83
85
|
var whatwgUrl__default = /*#__PURE__*/_interopDefaultLegacy(whatwgUrl);
|
|
84
86
|
|
|
85
87
|
/******************************************************************************
|
|
@@ -285,6 +287,9 @@ function removeDir(_path) {
|
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
289
|
|
|
290
|
+
let urlAlphabet =
|
|
291
|
+
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
|
|
292
|
+
|
|
288
293
|
const POOL_SIZE_MULTIPLIER = 128;
|
|
289
294
|
let pool, poolOffset;
|
|
290
295
|
let fillPool = bytes => {
|
|
@@ -319,6 +324,14 @@ let customRandom = (alphabet, defaultSize, getRandom) => {
|
|
|
319
324
|
};
|
|
320
325
|
let customAlphabet = (alphabet, size = 21) =>
|
|
321
326
|
customRandom(alphabet, size, random);
|
|
327
|
+
let nanoid$1 = (size = 21) => {
|
|
328
|
+
fillPool((size -= 0));
|
|
329
|
+
let id = '';
|
|
330
|
+
for (let i = poolOffset - size; i < poolOffset; i++) {
|
|
331
|
+
id += urlAlphabet[pool[i] & 63];
|
|
332
|
+
}
|
|
333
|
+
return id
|
|
334
|
+
};
|
|
322
335
|
|
|
323
336
|
require('base-64').encode;
|
|
324
337
|
var svgToBase64 = function (svgString) {
|
|
@@ -329,49 +342,127 @@ var svgToBase64 = function (svgString) {
|
|
|
329
342
|
var alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
330
343
|
var nanoid = customAlphabet(alphabet, 6);
|
|
331
344
|
/**
|
|
332
|
-
*
|
|
345
|
+
* 文件名管理器,确保全局唯一性
|
|
346
|
+
*/
|
|
347
|
+
var FileNameManager = /** @class */ (function () {
|
|
348
|
+
function FileNameManager() {
|
|
349
|
+
this.usedNames = new Set();
|
|
350
|
+
this.usedIdentifiers = new Set();
|
|
351
|
+
this.nameCounters = new Map();
|
|
352
|
+
this.identifierCounters = new Map();
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 生成唯一的文件名
|
|
356
|
+
* @param baseName 基础文件名
|
|
357
|
+
* @param extension 文件扩展名(包含点号,如 '.png')
|
|
358
|
+
* @returns 唯一的文件名
|
|
359
|
+
*/
|
|
360
|
+
FileNameManager.prototype.generateUniqueFileName = function (baseName, extension) {
|
|
361
|
+
var cleanBaseName = this.sanitizeFileName(baseName);
|
|
362
|
+
var finalName = "".concat(cleanBaseName).concat(extension);
|
|
363
|
+
// 如果名称已存在,使用计数器生成唯一名称
|
|
364
|
+
if (this.usedNames.has(finalName.toLowerCase())) {
|
|
365
|
+
var counter = (this.nameCounters.get(cleanBaseName) || 0) + 1;
|
|
366
|
+
this.nameCounters.set(cleanBaseName, counter);
|
|
367
|
+
finalName = "".concat(cleanBaseName, "_").concat(counter).concat(extension);
|
|
368
|
+
// 如果计数器名称仍然存在,使用 nanoid 确保唯一性
|
|
369
|
+
while (this.usedNames.has(finalName.toLowerCase())) {
|
|
370
|
+
finalName = "".concat(cleanBaseName, "_").concat(counter, "_").concat(nanoid(4)).concat(extension);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
this.usedNames.add(finalName.toLowerCase());
|
|
374
|
+
return finalName;
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* 生成唯一的 JavaScript 标识符名称
|
|
378
|
+
* @param baseName 基础标识符名
|
|
379
|
+
* @returns 唯一的标识符名称
|
|
380
|
+
*/
|
|
381
|
+
FileNameManager.prototype.generateUniqueIdentifier = function (baseName) {
|
|
382
|
+
var cleanBaseName = this.sanitizeIdentifier(baseName);
|
|
383
|
+
var finalName = cleanBaseName;
|
|
384
|
+
// 如果标识符已存在,使用计数器生成唯一名称
|
|
385
|
+
if (this.usedIdentifiers.has(finalName.toLowerCase())) {
|
|
386
|
+
var counter = (this.identifierCounters.get(cleanBaseName) || 0) + 1;
|
|
387
|
+
this.identifierCounters.set(cleanBaseName, counter);
|
|
388
|
+
finalName = "".concat(cleanBaseName, "_").concat(counter);
|
|
389
|
+
// 如果计数器名称仍然存在,使用 nanoid 确保唯一性
|
|
390
|
+
while (this.usedIdentifiers.has(finalName.toLowerCase())) {
|
|
391
|
+
finalName = "".concat(cleanBaseName, "_").concat(counter, "_").concat(nanoid(4));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
this.usedIdentifiers.add(finalName.toLowerCase());
|
|
395
|
+
return finalName;
|
|
396
|
+
};
|
|
397
|
+
/**
|
|
398
|
+
* 清理文件名,移除无效字符
|
|
399
|
+
* @param rawName 原始文件名
|
|
400
|
+
* @returns 清理后的文件名
|
|
401
|
+
*/
|
|
402
|
+
FileNameManager.prototype.sanitizeFileName = function (rawName) {
|
|
403
|
+
if (!rawName)
|
|
404
|
+
return "file_".concat(nanoid(6));
|
|
405
|
+
var cleaned = rawName
|
|
406
|
+
// 移除或替换无效的文件名字符
|
|
407
|
+
.replace(/[<>:"/\\|?*]/g, '') // 移除文件系统不允许的字符
|
|
408
|
+
.replace(/\s+/g, '_') // 空格替换为下划线
|
|
409
|
+
.replace(/[^\w\-_.]/g, '') // 只保留字母、数字、下划线、连字符和点
|
|
410
|
+
.replace(/_{2,}/g, '_') // 多个连续下划线替换为单个
|
|
411
|
+
.replace(/^[_-]+|[_-]+$/g, '') // 移除开头和结尾的下划线和连字符
|
|
412
|
+
.substring(0, 30); // 限制长度
|
|
413
|
+
return cleaned || "file_".concat(nanoid(6));
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* 清理JavaScript标识符,确保符合变量命名规范
|
|
417
|
+
* @param rawName 原始标识符名
|
|
418
|
+
* @returns 清理后的标识符名
|
|
419
|
+
*/
|
|
420
|
+
FileNameManager.prototype.sanitizeIdentifier = function (rawName) {
|
|
421
|
+
if (!rawName)
|
|
422
|
+
return "id_".concat(nanoid(6));
|
|
423
|
+
var cleaned = rawName
|
|
424
|
+
// 移除或替换无效的标识符字符
|
|
425
|
+
.replace(/[^\w]/g, '_') // 只保留字母、数字、下划线
|
|
426
|
+
.replace(/_{2,}/g, '_') // 多个连续下划线替换为单个
|
|
427
|
+
.replace(/^[_\d]+|[_]+$/g, '') // 移除开头的数字和下划线,结尾的下划线
|
|
428
|
+
.substring(0, 30); // 限制长度
|
|
429
|
+
return cleaned || "id_".concat(nanoid(6));
|
|
430
|
+
};
|
|
431
|
+
/**
|
|
432
|
+
* 重置管理器状态
|
|
433
|
+
*/
|
|
434
|
+
FileNameManager.prototype.reset = function () {
|
|
435
|
+
this.usedNames.clear();
|
|
436
|
+
this.usedIdentifiers.clear();
|
|
437
|
+
this.nameCounters.clear();
|
|
438
|
+
this.identifierCounters.clear();
|
|
439
|
+
};
|
|
440
|
+
return FileNameManager;
|
|
441
|
+
}());
|
|
442
|
+
// 全局文件名管理器实例
|
|
443
|
+
var fileNameManager = new FileNameManager();
|
|
444
|
+
/**
|
|
445
|
+
* 清理文件名,移除无效字符(保持向后兼容)
|
|
333
446
|
* @param rawName 原始文件名
|
|
334
447
|
* @returns 清理后的文件名
|
|
335
448
|
*/
|
|
336
449
|
function sanitizeFileName(rawName) {
|
|
337
|
-
|
|
338
|
-
return '';
|
|
339
|
-
return rawName
|
|
340
|
-
// 移除或替换无效的文件名字符
|
|
341
|
-
.replace(/[<>:"/\\|?*]/g, '') // 移除文件系统不允许的字符
|
|
342
|
-
.replace(/\s+/g, '_') // 空格替换为下划线
|
|
343
|
-
.replace(/[^\w\-_.]/g, '') // 只保留字母、数字、下划线、连字符和点
|
|
344
|
-
.replace(/_{2,}/g, '_') // 多个连续下划线替换为单个
|
|
345
|
-
.replace(/^[_-]+|[_-]+$/g, '') // 移除开头和结尾的下划线和连字符
|
|
346
|
-
.substring(0, 50) // 限制长度
|
|
347
|
-
|| "fallback_".concat(nanoid(6)); // 如果清理后为空,使用fallback名称
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* 清理JavaScript标识符,确保符合变量命名规范
|
|
351
|
-
* @param rawName 原始标识符名
|
|
352
|
-
* @returns 清理后的标识符名
|
|
353
|
-
*/
|
|
354
|
-
function sanitizeIdentifier(rawName) {
|
|
355
|
-
if (!rawName)
|
|
356
|
-
return "id_".concat(nanoid(6));
|
|
357
|
-
return rawName
|
|
358
|
-
// 移除或替换无效的标识符字符
|
|
359
|
-
.replace(/[^\w]/g, '_') // 只保留字母、数字、下划线
|
|
360
|
-
.replace(/_{2,}/g, '_') // 多个连续下划线替换为单个
|
|
361
|
-
.replace(/^[_\d]+|[_]+$/g, '') // 移除开头的数字和下划线,结尾的下划线
|
|
362
|
-
.substring(0, 30) // 限制长度
|
|
363
|
-
|| "id_".concat(nanoid(6)); // 如果清理后为空,使用fallback名称
|
|
450
|
+
return fileNameManager['sanitizeFileName'](rawName);
|
|
364
451
|
}
|
|
365
452
|
var transformJsx = function (file, solution, outputPath) {
|
|
366
453
|
// const componentsDeps: string[] = [];
|
|
367
454
|
var images = [];
|
|
368
455
|
var svgs = [];
|
|
456
|
+
// 重置文件名管理器,确保每次转换都从干净状态开始
|
|
457
|
+
fileNameManager.reset();
|
|
369
458
|
// 全局数据相关状态追踪
|
|
370
459
|
var hasGlobalDataDecorator = false;
|
|
371
460
|
var usesGlobalData = false;
|
|
372
461
|
var classDeclarationPath = null;
|
|
373
462
|
// 简单判断组件还是页面
|
|
374
|
-
var componentType = file.path.includes('/src/components/')
|
|
463
|
+
var componentType = file.path.includes('/src/components/')
|
|
464
|
+
? 'Component'
|
|
465
|
+
: 'Page';
|
|
375
466
|
var source = fs__namespace.readFileSync(file.path + '/' + file.fileName, 'utf-8');
|
|
376
467
|
// 检测源码中是否使用了 this.globalData
|
|
377
468
|
if (source.includes('this.globalData')) {
|
|
@@ -401,7 +492,8 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
401
492
|
var decorators = path.node.decorators;
|
|
402
493
|
if (decorators) {
|
|
403
494
|
var hasGlobalDataDec = decorators.some(function (decorator) {
|
|
404
|
-
if (t__namespace.isDecorator(decorator) &&
|
|
495
|
+
if (t__namespace.isDecorator(decorator) &&
|
|
496
|
+
t__namespace.isIdentifier(decorator.expression)) {
|
|
405
497
|
return decorator.expression.name === 'GlobalDataDecorator';
|
|
406
498
|
}
|
|
407
499
|
return false;
|
|
@@ -462,12 +554,18 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
462
554
|
body.splice(lastImportIndex + 2, 0, importDeclaration);
|
|
463
555
|
}
|
|
464
556
|
if (componentType === 'Page' && solution === 'vite') {
|
|
465
|
-
var importDeclaration = t__namespace.importDeclaration([
|
|
557
|
+
var importDeclaration = t__namespace.importDeclaration([
|
|
558
|
+
t__namespace.importSpecifier(t__namespace.identifier('withRouter'), t__namespace.identifier('withRouter')),
|
|
559
|
+
], t__namespace.stringLiteral('@/utils/router'));
|
|
466
560
|
body.splice(lastImportIndex + (haveChildren ? 3 : 2), 0, importDeclaration);
|
|
467
561
|
}
|
|
468
562
|
if (usesGlobalData && !hasGlobalDataDecorator) {
|
|
469
|
-
var globalDataImport = t__namespace.importDeclaration([
|
|
470
|
-
|
|
563
|
+
var globalDataImport = t__namespace.importDeclaration([
|
|
564
|
+
t__namespace.importSpecifier(t__namespace.identifier('GlobalDataDecorator'), t__namespace.identifier('GlobalDataDecorator')),
|
|
565
|
+
], t__namespace.stringLiteral('@/utils'));
|
|
566
|
+
body.splice(lastImportIndex +
|
|
567
|
+
(haveChildren ? 3 : 2) +
|
|
568
|
+
(componentType === 'Page' && solution === 'vite' ? 1 : 0), 0, globalDataImport);
|
|
471
569
|
}
|
|
472
570
|
},
|
|
473
571
|
ImportDeclaration: function (path) {
|
|
@@ -540,7 +638,7 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
540
638
|
if (nodePath.parent.name.name === 'AtIcon' &&
|
|
541
639
|
nodePath.node.name.name === 'svg' &&
|
|
542
640
|
((_a = nodePath.node) === null || _a === void 0 ? void 0 : _a.value.type) === 'StringLiteral') {
|
|
543
|
-
var
|
|
641
|
+
var fileName = '';
|
|
544
642
|
var color = '';
|
|
545
643
|
if (Array.isArray(nodePath.container)) {
|
|
546
644
|
var valueNode = nodePath.container.find(function (item) { return item.name.name === 'value'; });
|
|
@@ -549,25 +647,18 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
549
647
|
// @ts-ignore
|
|
550
648
|
)) === null || _b === void 0 ? void 0 : _b.value) === null || _c === void 0 ? void 0 : _c.value) || '';
|
|
551
649
|
if (valueNode) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
// fileName =
|
|
555
|
-
// (classNameArr.length > 0
|
|
556
|
-
// ? classNameArr[classNameArr.length - 1]
|
|
557
|
-
// : fileName) + '.png';
|
|
650
|
+
var baseName = "svg_".concat(((_d = valueNode === null || valueNode === void 0 ? void 0 : valueNode.value) === null || _d === void 0 ? void 0 : _d.value) || nanoid(6));
|
|
651
|
+
fileName = fileNameManager.generateUniqueFileName(baseName, '');
|
|
558
652
|
}
|
|
559
653
|
}
|
|
560
|
-
if (!
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
// 文件名去重
|
|
564
|
-
if (svgs.findIndex(function (item) { return item.fileName === fileName_1; }) > -1) {
|
|
565
|
-
fileName_1 = "".concat(fileName_1, "_").concat(nanoid(6));
|
|
654
|
+
if (!fileName) {
|
|
655
|
+
var baseName = "svg_".concat(nanoid(6));
|
|
656
|
+
fileName = fileNameManager.generateUniqueFileName(baseName, '');
|
|
566
657
|
}
|
|
567
658
|
// 替换
|
|
568
659
|
var node = nodePath.node;
|
|
569
660
|
var svgStr = node.value.value;
|
|
570
|
-
if (
|
|
661
|
+
if (fileName && svgStr) {
|
|
571
662
|
// 替换颜色
|
|
572
663
|
if (svgStr && color) {
|
|
573
664
|
svgStr = svgStr.replace(/currentColor/g, color);
|
|
@@ -577,54 +668,50 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
577
668
|
svgStr = svgStr.replace(/width="100%"/g, '');
|
|
578
669
|
svgStr = svgStr.replace(/height="100%"/g, '');
|
|
579
670
|
}
|
|
580
|
-
nodePath.replaceWith(t__namespace.jsxAttribute(t__namespace.jsxIdentifier('svg'), t__namespace.jsxExpressionContainer(t__namespace.memberExpression(t__namespace.identifier('ICONS'), t__namespace.stringLiteral(
|
|
671
|
+
nodePath.replaceWith(t__namespace.jsxAttribute(t__namespace.jsxIdentifier('svg'), t__namespace.jsxExpressionContainer(t__namespace.memberExpression(t__namespace.identifier('ICONS'), t__namespace.stringLiteral(fileName), true))));
|
|
581
672
|
svgs.push({
|
|
582
673
|
svgStr: svgStr,
|
|
583
|
-
fileName:
|
|
674
|
+
fileName: fileName,
|
|
584
675
|
});
|
|
585
676
|
}
|
|
586
677
|
}
|
|
587
678
|
if (nodePath.parent.name.name === 'Image' &&
|
|
588
679
|
nodePath.node.name.name === 'src' &&
|
|
589
680
|
((_e = nodePath.node) === null || _e === void 0 ? void 0 : _e.value.type) === 'StringLiteral') {
|
|
590
|
-
var
|
|
681
|
+
var fileName = '';
|
|
591
682
|
if (Array.isArray(nodePath.container)) {
|
|
592
683
|
var classNameNode = nodePath.container.find(function (item) { return item.name.name === 'className'; });
|
|
593
684
|
if (classNameNode) {
|
|
594
685
|
var rawClassName = (_f = classNameNode === null || classNameNode === void 0 ? void 0 : classNameNode.value) === null || _f === void 0 ? void 0 : _f.value;
|
|
595
686
|
if (rawClassName) {
|
|
596
687
|
// 处理 Tailwind CSS 类名和其他复杂类名
|
|
597
|
-
|
|
598
|
-
var classNameArr =
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
688
|
+
var cleanedName = sanitizeFileName(rawClassName);
|
|
689
|
+
var classNameArr = cleanedName.split('__');
|
|
690
|
+
var baseName = classNameArr.length > 0
|
|
691
|
+
? classNameArr[classNameArr.length - 1]
|
|
692
|
+
: cleanedName;
|
|
693
|
+
fileName = fileNameManager.generateUniqueFileName(baseName, '.png');
|
|
603
694
|
}
|
|
604
695
|
}
|
|
605
696
|
}
|
|
606
697
|
// 如果没有从className获取到有效文件名,使用随机名称
|
|
607
|
-
if (!
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
// 文件名去重
|
|
611
|
-
if (images.findIndex(function (item) { return item.fileName === fileName_2.toLowerCase(); }) >
|
|
612
|
-
-1) {
|
|
613
|
-
fileName_2 = "r".concat(images.length, "_").concat(fileName_2.toLowerCase());
|
|
698
|
+
if (!fileName) {
|
|
699
|
+
var baseName = "image_".concat(nanoid(6));
|
|
700
|
+
fileName = fileNameManager.generateUniqueFileName(baseName, '.png');
|
|
614
701
|
}
|
|
615
702
|
// 替换
|
|
616
703
|
var node = nodePath.node;
|
|
617
704
|
var imageSrc = node.value.value;
|
|
618
|
-
var staticFileName =
|
|
619
|
-
var staticInentifierName = "static_".concat(
|
|
620
|
-
if (
|
|
705
|
+
var staticFileName = fileName.toLowerCase();
|
|
706
|
+
var staticInentifierName = fileNameManager.generateUniqueIdentifier("static_".concat(staticFileName.split('.')[0]));
|
|
707
|
+
if (fileName && imageSrc) {
|
|
621
708
|
var func = t__namespace.jSXExpressionContainer(t__namespace.identifier(staticInentifierName));
|
|
622
709
|
// const func = t.jSXExpressionContainer(
|
|
623
710
|
// t.callExpression(t.identifier('require'), [
|
|
624
711
|
// t.stringLiteral(`./images/${staticFileName}`),
|
|
625
712
|
// ])
|
|
626
713
|
// );
|
|
627
|
-
nodePath.node.value =
|
|
714
|
+
nodePath.node.value = fileName ? func : null;
|
|
628
715
|
images.push({
|
|
629
716
|
url: imageSrc,
|
|
630
717
|
fileName: staticFileName,
|
|
@@ -674,10 +761,12 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
674
761
|
if (componentType === 'Page' && solution === 'vite') {
|
|
675
762
|
var declaration = path.node.declaration;
|
|
676
763
|
// @ts-ignore
|
|
677
|
-
var withRouterCall = t__namespace.callExpression(t__namespace.identifier('withRouter'), [
|
|
764
|
+
var withRouterCall = t__namespace.callExpression(t__namespace.identifier('withRouter'), [
|
|
765
|
+
declaration,
|
|
766
|
+
]);
|
|
678
767
|
path.node.declaration = withRouterCall;
|
|
679
768
|
}
|
|
680
|
-
}
|
|
769
|
+
},
|
|
681
770
|
});
|
|
682
771
|
// 处理装饰器自动添加
|
|
683
772
|
if (usesGlobalData && !hasGlobalDataDecorator && classDeclarationPath) {
|
|
@@ -730,7 +819,7 @@ var transformJsx = function (file, solution, outputPath) {
|
|
|
730
819
|
var base64String = svgToBase64(node.value);
|
|
731
820
|
path.replaceWith(t__namespace.stringLiteral(base64String));
|
|
732
821
|
}
|
|
733
|
-
}
|
|
822
|
+
},
|
|
734
823
|
});
|
|
735
824
|
if (isHaveSvg_1)
|
|
736
825
|
code = generate__default["default"](astTree).code;
|
|
@@ -19537,7 +19626,7 @@ var createDataSourceCode = function (dataSourceConfig) {
|
|
|
19537
19626
|
},
|
|
19538
19627
|
}), ";\n");
|
|
19539
19628
|
}
|
|
19540
|
-
var code = "\n// \u517C\u5BB9\u6027\uFF1A\u4FDD\u7559\u65E7\u7684\u5168\u5C40\u6570\u636E API\uFF0C\u4F46\u4F7F\u7528\u65B0\u7684\u5168\u5C40\u6570\u636E\u5B58\u50A8\nimport { globalDataStore } from './globalData';\n".concat(dataSourceConfigCode, "\n// \u517C\u5BB9\u65E7\u7248\u672C\u7684 API\nexport const setGlobalData = (key, value) => globalDataStore.set(key, value);\nexport const getGlobalData = (key) => globalDataStore.get(key);\nexport const reloadGlobalData = (key, options) => globalDataStore.
|
|
19629
|
+
var code = "\n// \u517C\u5BB9\u6027\uFF1A\u4FDD\u7559\u65E7\u7684\u5168\u5C40\u6570\u636E API\uFF0C\u4F46\u4F7F\u7528\u65B0\u7684\u5168\u5C40\u6570\u636E\u5B58\u50A8\nimport { globalDataStore } from './globalData';\n".concat(dataSourceConfigCode, "\n// \u517C\u5BB9\u65E7\u7248\u672C\u7684 API\nexport const setGlobalData = (key, value) => globalDataStore.set(key, value);\nexport const getGlobalData = (key) => globalDataStore.get(key);\nexport const reloadGlobalData = (key, options) => globalDataStore.loadDataSource(key, options);\nexport const globalDataSourceMap = globalDataStore.dataSourceMap;\n ");
|
|
19541
19630
|
return code;
|
|
19542
19631
|
};
|
|
19543
19632
|
function wrapAsFunction$1(value, scope) {
|
|
@@ -19702,7 +19791,10 @@ var transformUtils = function (file, schema, project, solution, outputPath) {
|
|
|
19702
19791
|
globalFunctionNames.add('getGlobalData');
|
|
19703
19792
|
globalFunctionNames.add('reloadGlobalData');
|
|
19704
19793
|
globalFunctionNames.add('globalDataSourceMap');
|
|
19705
|
-
|
|
19794
|
+
globalFunctionNames.add('renderComponent');
|
|
19795
|
+
globalFunctionNames.add('showComponentModal');
|
|
19796
|
+
globalFunctionNames.add('dataSource');
|
|
19797
|
+
globalFunctionNames.add('_');
|
|
19706
19798
|
body.splice(1, 0, t__namespace.importDeclaration(Array.from(utilsFunctionNames)
|
|
19707
19799
|
.filter(function (name) {
|
|
19708
19800
|
return !globalFunctionNames.has(name) &&
|
|
@@ -19711,9 +19803,7 @@ var transformUtils = function (file, schema, project, solution, outputPath) {
|
|
|
19711
19803
|
})
|
|
19712
19804
|
.map(function (name) {
|
|
19713
19805
|
return t__namespace.importSpecifier(t__namespace.identifier(name), t__namespace.identifier(name));
|
|
19714
|
-
}), t__namespace.stringLiteral(solution === 'vite'
|
|
19715
|
-
? '@appthen/utils'
|
|
19716
|
-
: 'cross-ui/utils')));
|
|
19806
|
+
}), t__namespace.stringLiteral(solution === 'vite' ? '@appthen/utils' : 'cross-ui/utils')));
|
|
19717
19807
|
body.splice(2, 0, t__namespace.importDeclaration(['requestHandle'].map(function (name) {
|
|
19718
19808
|
return t__namespace.importSpecifier(t__namespace.identifier(name), t__namespace.identifier(name));
|
|
19719
19809
|
}), t__namespace.stringLiteral('./dataSource')));
|
|
@@ -19739,7 +19829,9 @@ var transformUtils = function (file, schema, project, solution, outputPath) {
|
|
|
19739
19829
|
// 创建 VariableDeclarator 节点,表示 const Fuck = constants.Fuck
|
|
19740
19830
|
var variableDeclarator = t__namespace.variableDeclarator(t__namespace.identifier(util.name), memberExpression);
|
|
19741
19831
|
// 创建 VariableDeclaration 节点,表示 const Fuck 的声明
|
|
19742
|
-
var variableDeclaration = t__namespace.variableDeclaration('const', [
|
|
19832
|
+
var variableDeclaration = t__namespace.variableDeclaration('const', [
|
|
19833
|
+
variableDeclarator,
|
|
19834
|
+
]);
|
|
19743
19835
|
// 创建 ExportNamedDeclaration 节点,表示 export const Fuck
|
|
19744
19836
|
var exportNamedDeclaration = t__namespace.exportNamedDeclaration(variableDeclaration);
|
|
19745
19837
|
body.splice(4 + index, 0, exportNamedDeclaration);
|
|
@@ -19794,7 +19886,8 @@ var transformUtils = function (file, schema, project, solution, outputPath) {
|
|
|
19794
19886
|
if (extendsCodes.length > 0) {
|
|
19795
19887
|
code = extendsCodes.join('\n') + '\n' + code;
|
|
19796
19888
|
}
|
|
19797
|
-
code =
|
|
19889
|
+
code =
|
|
19890
|
+
"import {\n addPortal,\n removePortal,\n registerPartalComponent,\n showComponentModal,\n renderComponentPortal,\n renderComponent\n} from '@appthen/react';\n\nexport {\n addPortal,\n removePortal,\n registerPartalComponent,\n showComponentModal,\n renderComponentPortal,\n renderComponent,\n} from '@appthen/react';\n" + code;
|
|
19798
19891
|
fs__namespace.writeFileSync(file.path + '/' + file.fileName, code);
|
|
19799
19892
|
return { code: code };
|
|
19800
19893
|
};
|
|
@@ -32909,30 +33002,21 @@ var createRouter = function (project) {
|
|
|
32909
33002
|
if (!router || ((_a = router.routes) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
32910
33003
|
return;
|
|
32911
33004
|
}
|
|
32912
|
-
|
|
32913
|
-
|
|
32914
|
-
//
|
|
32915
|
-
|
|
32916
|
-
|
|
32917
|
-
|
|
32918
|
-
|
|
32919
|
-
|
|
32920
|
-
|
|
32921
|
-
|
|
32922
|
-
|
|
32923
|
-
|
|
32924
|
-
|
|
32925
|
-
|
|
32926
|
-
// redirect: '/admin/fuck',
|
|
32927
|
-
// },
|
|
32928
|
-
// {
|
|
32929
|
-
// path: '/antdBackgroundManagementSystem',
|
|
32930
|
-
// page: 'antdBackgroundManagementSystem',
|
|
32931
|
-
// },
|
|
32932
|
-
// ],
|
|
32933
|
-
// };
|
|
33005
|
+
console.log('router: ', router.routes[0]);
|
|
33006
|
+
console.log('🔍 原始路由数据:', JSON.stringify(router.routes, null, 2));
|
|
33007
|
+
// 保存调试数据到文件
|
|
33008
|
+
var fs = require('fs');
|
|
33009
|
+
try {
|
|
33010
|
+
fs.writeFileSync('./router-debug.json', JSON.stringify({
|
|
33011
|
+
routes: router.routes,
|
|
33012
|
+
timestamp: new Date().toISOString(),
|
|
33013
|
+
}, null, 2));
|
|
33014
|
+
console.log('📝 路由调试数据已保存到 router-debug.json');
|
|
33015
|
+
}
|
|
33016
|
+
catch (error) {
|
|
33017
|
+
console.log('⚠️ 无法保存调试数据:', error.message);
|
|
33018
|
+
}
|
|
32934
33019
|
var allPages = [];
|
|
32935
|
-
// const routeElements: any[] = [];
|
|
32936
33020
|
// 遍历router.routes,生成路由
|
|
32937
33021
|
var checkRoutes = function (routes) {
|
|
32938
33022
|
routes.forEach(function (route) {
|
|
@@ -32945,7 +33029,8 @@ var createRouter = function (project) {
|
|
|
32945
33029
|
});
|
|
32946
33030
|
};
|
|
32947
33031
|
checkRoutes(router.routes);
|
|
32948
|
-
|
|
33032
|
+
// 处理路由结构,正确处理布局和嵌套路由
|
|
33033
|
+
var routeElements = processRoutesWithLayout(router.routes);
|
|
32949
33034
|
var fileLazyImports = allPages.map(function (_) {
|
|
32950
33035
|
return createLazyImport(_, "./pages/".concat(_));
|
|
32951
33036
|
});
|
|
@@ -32954,6 +33039,68 @@ var createRouter = function (project) {
|
|
|
32954
33039
|
routeElements: routeElements,
|
|
32955
33040
|
};
|
|
32956
33041
|
};
|
|
33042
|
+
// 处理路由结构,正确处理布局和嵌套路由
|
|
33043
|
+
function processRoutesWithLayout(routes) {
|
|
33044
|
+
var e_1, _a, e_2, _b;
|
|
33045
|
+
var result = [];
|
|
33046
|
+
console.log('🔧 开始处理路由结构...');
|
|
33047
|
+
try {
|
|
33048
|
+
for (var routes_1 = __values(routes), routes_1_1 = routes_1.next(); !routes_1_1.done; routes_1_1 = routes_1.next()) {
|
|
33049
|
+
var route = routes_1_1.value;
|
|
33050
|
+
console.log("\uD83D\uDCCD \u5904\u7406\u8DEF\u7531: ".concat(route.path, ", page: ").concat(route.page));
|
|
33051
|
+
// 检查是否为独立路由
|
|
33052
|
+
if (route.noLayout) {
|
|
33053
|
+
console.log(" \uD83D\uDEAA \u72EC\u7ACB\u8DEF\u7531");
|
|
33054
|
+
var routeElement = createNestedRoutesWithLayout(route);
|
|
33055
|
+
result.push(routeElement);
|
|
33056
|
+
continue;
|
|
33057
|
+
}
|
|
33058
|
+
// 检查是否为布局组件(有 children)
|
|
33059
|
+
var isLayoutRoute = route.children && route.children.length > 0;
|
|
33060
|
+
if (isLayoutRoute) {
|
|
33061
|
+
console.log(" \uD83C\uDFE0 \u8BC6\u522B\u4E3A\u5E03\u5C40\u8DEF\u7531\uFF0C\u5B50\u8DEF\u7531\u6570\u91CF: ".concat(route.children.length));
|
|
33062
|
+
// 创建布局路由,包含子路由
|
|
33063
|
+
var layoutChildren = route.children
|
|
33064
|
+
.filter(function (child) { return !child.noLayout; }) // 过滤掉 noLayout 的子路由
|
|
33065
|
+
.map(function (child) { return createNestedRoutesWithLayout(child); });
|
|
33066
|
+
var layoutElement = createNestedRoutesWithLayout(route, layoutChildren);
|
|
33067
|
+
result.push(layoutElement);
|
|
33068
|
+
// 处理 noLayout 的子路由,作为独立路由
|
|
33069
|
+
var independentChildren = route.children.filter(function (child) { return child.noLayout; });
|
|
33070
|
+
try {
|
|
33071
|
+
for (var independentChildren_1 = (e_2 = void 0, __values(independentChildren)), independentChildren_1_1 = independentChildren_1.next(); !independentChildren_1_1.done; independentChildren_1_1 = independentChildren_1.next()) {
|
|
33072
|
+
var independentChild = independentChildren_1_1.value;
|
|
33073
|
+
console.log(" \uD83D\uDEAA \u5904\u7406\u72EC\u7ACB\u5B50\u8DEF\u7531: ".concat(independentChild.path));
|
|
33074
|
+
var childElement = createNestedRoutesWithLayout(independentChild);
|
|
33075
|
+
result.push(childElement);
|
|
33076
|
+
}
|
|
33077
|
+
}
|
|
33078
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
33079
|
+
finally {
|
|
33080
|
+
try {
|
|
33081
|
+
if (independentChildren_1_1 && !independentChildren_1_1.done && (_b = independentChildren_1.return)) _b.call(independentChildren_1);
|
|
33082
|
+
}
|
|
33083
|
+
finally { if (e_2) throw e_2.error; }
|
|
33084
|
+
}
|
|
33085
|
+
}
|
|
33086
|
+
else {
|
|
33087
|
+
// 普通路由
|
|
33088
|
+
console.log(" \uD83D\uDCC4 \u5904\u7406\u666E\u901A\u8DEF\u7531");
|
|
33089
|
+
var routeElement = createNestedRoutesWithLayout(route);
|
|
33090
|
+
result.push(routeElement);
|
|
33091
|
+
}
|
|
33092
|
+
}
|
|
33093
|
+
}
|
|
33094
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
33095
|
+
finally {
|
|
33096
|
+
try {
|
|
33097
|
+
if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
|
|
33098
|
+
}
|
|
33099
|
+
finally { if (e_1) throw e_1.error; }
|
|
33100
|
+
}
|
|
33101
|
+
console.log("\u2705 \u8DEF\u7531\u5904\u7406\u5B8C\u6210\uFF0C\u751F\u6210 ".concat(result.length, " \u4E2A\u8DEF\u7531\u5143\u7D20"));
|
|
33102
|
+
return result;
|
|
33103
|
+
}
|
|
32957
33104
|
// Create a component with lazy loading
|
|
32958
33105
|
function createLazyImport(varName, source) {
|
|
32959
33106
|
var _varName = varName.slice(0, 1).toUpperCase() + varName.slice(1);
|
|
@@ -32965,17 +33112,18 @@ function createLazyImport(varName, source) {
|
|
|
32965
33112
|
}
|
|
32966
33113
|
// const indexLazyImport = createLazyImport('index', './pages/index');
|
|
32967
33114
|
// 助手函数,用于创建<Route> JSX元素
|
|
32968
|
-
function createRoute(path, componentName, exact, children) {
|
|
33115
|
+
function createRoute(path, componentName, exact, children, isLayout) {
|
|
32969
33116
|
if (exact === void 0) { exact = false; }
|
|
32970
33117
|
if (children === void 0) { children = null; }
|
|
33118
|
+
if (isLayout === void 0) { isLayout = false; }
|
|
32971
33119
|
var props = [
|
|
32972
33120
|
t__namespace.jsxAttribute(t__namespace.jsxIdentifier('path'), t__namespace.stringLiteral(path)),
|
|
32973
33121
|
];
|
|
32974
33122
|
if (exact) {
|
|
32975
33123
|
props.push(t__namespace.jsxAttribute(t__namespace.jsxIdentifier('exact')));
|
|
32976
33124
|
}
|
|
32977
|
-
var openingElement = t__namespace.jsxOpeningElement(t__namespace.jsxIdentifier('Route'), props, !children);
|
|
32978
|
-
if (!componentName && !children) {
|
|
33125
|
+
var openingElement = t__namespace.jsxOpeningElement(t__namespace.jsxIdentifier('Route'), props, !children && !isLayout);
|
|
33126
|
+
if (!componentName && !children && !isLayout) {
|
|
32979
33127
|
return t__namespace.jsxElement(openingElement, t__namespace.jsxClosingElement(t__namespace.jsxIdentifier('Route')), [], false);
|
|
32980
33128
|
}
|
|
32981
33129
|
// 添加component属性如果存在
|
|
@@ -33001,21 +33149,61 @@ function codeToAST(code) {
|
|
|
33001
33149
|
return null;
|
|
33002
33150
|
}
|
|
33003
33151
|
}
|
|
33004
|
-
//
|
|
33005
|
-
function
|
|
33006
|
-
|
|
33007
|
-
|
|
33008
|
-
children = route.children.map(function (childRoute) {
|
|
33009
|
-
return createNestedRoutes(childRoute);
|
|
33010
|
-
});
|
|
33011
|
-
}
|
|
33152
|
+
// 新的路由创建函数,处理实际的数据格式
|
|
33153
|
+
function createNestedRoutesWithLayout(route, children) {
|
|
33154
|
+
console.log(" \uD83D\uDD27 \u521B\u5EFA\u8DEF\u7531\u5143\u7D20: ".concat(route.path, ", page: ").concat(route.page));
|
|
33155
|
+
// 处理重定向路由
|
|
33012
33156
|
if (route.redirect) {
|
|
33157
|
+
console.log(" \u21AA\uFE0F \u91CD\u5B9A\u5411\u8DEF\u7531: ".concat(route.path, " -> ").concat(route.redirect));
|
|
33013
33158
|
return codeToAST("<Route path=\"".concat(route.path, "\" element={<Navigate to=\"").concat(route.redirect, "\"/>}></Route>"));
|
|
33014
|
-
// return createRedirect(route.redirect);
|
|
33015
33159
|
}
|
|
33016
|
-
|
|
33160
|
+
// 如果传入了 children,说明这是一个布局路由
|
|
33161
|
+
if (children && children.length > 0) {
|
|
33162
|
+
console.log(" \uD83C\uDFE0 \u5E03\u5C40\u8DEF\u7531\uFF0C\u5305\u542B ".concat(children.length, " \u4E2A\u5B50\u8DEF\u7531"));
|
|
33163
|
+
return createRoute(route.path, route.page || '', route.exact, children, true // isLayout = true
|
|
33164
|
+
);
|
|
33165
|
+
}
|
|
33166
|
+
// 普通页面路由
|
|
33167
|
+
console.log(" \uD83D\uDCC4 \u666E\u901A\u9875\u9762\u8DEF\u7531");
|
|
33168
|
+
return createRoute(route.path, route.page || '', route.exact, null, false);
|
|
33017
33169
|
}
|
|
33018
33170
|
|
|
33171
|
+
/**
|
|
33172
|
+
* 创建详细的错误信息,包含代码片段和位置信息
|
|
33173
|
+
*/
|
|
33174
|
+
function createDetailedError(error, context) {
|
|
33175
|
+
var operation = context.operation, _a = context.filePath, filePath = _a === void 0 ? './src/App.jsx' : _a, code = context.code, suggestion = context.suggestion;
|
|
33176
|
+
var errorMessage = "".concat(operation, "\u5931\u8D25: ").concat(error.message);
|
|
33177
|
+
if (error.loc) {
|
|
33178
|
+
errorMessage += " (\u7B2C".concat(error.loc.line, "\u884C\u7B2C").concat(error.loc.column, "\u5217)");
|
|
33179
|
+
}
|
|
33180
|
+
console.error("\u274C ".concat(operation, "\u5931\u8D25:"), {
|
|
33181
|
+
filePath: filePath,
|
|
33182
|
+
error: error.message,
|
|
33183
|
+
type: error.name || 'Error',
|
|
33184
|
+
position: error.loc
|
|
33185
|
+
? "\u7B2C".concat(error.loc.line, "\u884C\u7B2C").concat(error.loc.column, "\u5217")
|
|
33186
|
+
: '未知位置',
|
|
33187
|
+
snippet: error.loc && code
|
|
33188
|
+
? (function () {
|
|
33189
|
+
var lines = code.split('\n');
|
|
33190
|
+
var errorLine = error.loc.line - 1;
|
|
33191
|
+
var start = Math.max(0, errorLine - 2);
|
|
33192
|
+
var end = Math.min(lines.length, errorLine + 3);
|
|
33193
|
+
return lines
|
|
33194
|
+
.slice(start, end)
|
|
33195
|
+
.map(function (line, index) {
|
|
33196
|
+
var lineNum = start + index + 1;
|
|
33197
|
+
var marker = lineNum === error.loc.line ? '>>> ' : ' ';
|
|
33198
|
+
return "".concat(marker).concat(lineNum.toString().padStart(3), ": ").concat(line);
|
|
33199
|
+
})
|
|
33200
|
+
.join('\n');
|
|
33201
|
+
})()
|
|
33202
|
+
: '无法获取代码片段',
|
|
33203
|
+
suggestion: suggestion || '请检查代码语法和结构是否正确',
|
|
33204
|
+
});
|
|
33205
|
+
return new Error(errorMessage);
|
|
33206
|
+
}
|
|
33019
33207
|
function manageImports(ast, imports) {
|
|
33020
33208
|
// 记录需要处理的导入名称和包
|
|
33021
33209
|
var targetImports = new Map(imports.map(function (imp) { return [imp.name, imp]; }));
|
|
@@ -33049,14 +33237,16 @@ function manageImports(ast, imports) {
|
|
|
33049
33237
|
}
|
|
33050
33238
|
// 移除原有的目标包导入声明
|
|
33051
33239
|
path.remove();
|
|
33052
|
-
}
|
|
33240
|
+
},
|
|
33053
33241
|
});
|
|
33054
33242
|
// 添加新的导入到对应的包
|
|
33055
33243
|
imports.forEach(function (imp) {
|
|
33056
33244
|
if (!packageImports.has(imp.from)) {
|
|
33057
33245
|
packageImports.set(imp.from, new Set());
|
|
33058
33246
|
}
|
|
33059
|
-
packageImports
|
|
33247
|
+
packageImports
|
|
33248
|
+
.get(imp.from)
|
|
33249
|
+
.add(t__namespace.importSpecifier(t__namespace.identifier(imp.as || imp.name), t__namespace.identifier(imp.name)));
|
|
33060
33250
|
});
|
|
33061
33251
|
// 第二遍:添加新的导入
|
|
33062
33252
|
traverse__default["default"](ast, {
|
|
@@ -33066,21 +33256,49 @@ function manageImports(ast, imports) {
|
|
|
33066
33256
|
var _b = __read(_a, 2), source = _b[0], specifiers = _b[1];
|
|
33067
33257
|
if (specifiers.size > 0) {
|
|
33068
33258
|
// 找到第一个导入声明
|
|
33069
|
-
var firstImport = path.node.body.find(function (node) {
|
|
33070
|
-
|
|
33259
|
+
var firstImport = path.node.body.find(function (node) {
|
|
33260
|
+
return t__namespace.isImportDeclaration(node);
|
|
33261
|
+
});
|
|
33262
|
+
var insertIndex = firstImport
|
|
33263
|
+
? path.node.body.indexOf(firstImport)
|
|
33264
|
+
: 0;
|
|
33071
33265
|
path.node.body.splice(insertIndex, 0, t__namespace.importDeclaration(Array.from(specifiers), t__namespace.stringLiteral(source)));
|
|
33072
33266
|
}
|
|
33073
33267
|
});
|
|
33074
|
-
}
|
|
33268
|
+
},
|
|
33075
33269
|
});
|
|
33076
33270
|
}
|
|
33077
33271
|
var createAppFile = function (project, solution, outputPath) {
|
|
33078
|
-
var _a, _b, _c, _d;
|
|
33079
|
-
var appFile
|
|
33080
|
-
var astTree
|
|
33081
|
-
|
|
33082
|
-
|
|
33083
|
-
}
|
|
33272
|
+
var _a, _b, _c, _d, _e;
|
|
33273
|
+
var appFile;
|
|
33274
|
+
var astTree;
|
|
33275
|
+
try {
|
|
33276
|
+
appFile = fs__namespace.readFileSync('./src/App.jsx', 'utf8');
|
|
33277
|
+
}
|
|
33278
|
+
catch (error) {
|
|
33279
|
+
console.error('❌ 读取 App.jsx 文件失败:', {
|
|
33280
|
+
filePath: './src/App.jsx',
|
|
33281
|
+
error: error.message,
|
|
33282
|
+
suggestion: '请确保 src/App.jsx 文件存在且可读',
|
|
33283
|
+
});
|
|
33284
|
+
throw new Error("\u65E0\u6CD5\u8BFB\u53D6 App.jsx \u6587\u4EF6: ".concat(error.message));
|
|
33285
|
+
}
|
|
33286
|
+
try {
|
|
33287
|
+
astTree = parser__namespace.parse("".concat(appFile), {
|
|
33288
|
+
sourceType: 'module',
|
|
33289
|
+
plugins: ['jsx', 'typescript', 'decorators-legacy'],
|
|
33290
|
+
});
|
|
33291
|
+
}
|
|
33292
|
+
catch (error) {
|
|
33293
|
+
throw createDetailedError(error, {
|
|
33294
|
+
operation: 'App.jsx 文件解析',
|
|
33295
|
+
code: appFile,
|
|
33296
|
+
suggestion: '请检查 App.jsx 文件的语法是否正确,特别注意:\n' +
|
|
33297
|
+
'- 是否有未闭合的标签或括号\n' +
|
|
33298
|
+
'- 是否有未完成的变量声明(const/let/var)\n' +
|
|
33299
|
+
'- 是否有语法错误的 JSX 表达式',
|
|
33300
|
+
});
|
|
33301
|
+
}
|
|
33084
33302
|
astTree.program.body = astTree.program.body.filter(function (item) {
|
|
33085
33303
|
var _a, _b, _c, _d;
|
|
33086
33304
|
var isPageFile = item.type === 'VariableDeclaration' &&
|
|
@@ -33089,110 +33307,167 @@ var createAppFile = function (project, solution, outputPath) {
|
|
|
33089
33307
|
return !isPageFile;
|
|
33090
33308
|
});
|
|
33091
33309
|
// 添加路由
|
|
33092
|
-
|
|
33093
|
-
|
|
33094
|
-
|
|
33095
|
-
|
|
33096
|
-
|
|
33097
|
-
|
|
33098
|
-
|
|
33099
|
-
|
|
33100
|
-
|
|
33101
|
-
|
|
33102
|
-
|
|
33103
|
-
|
|
33104
|
-
|
|
33105
|
-
|
|
33106
|
-
node.
|
|
33107
|
-
|
|
33108
|
-
|
|
33310
|
+
try {
|
|
33311
|
+
var router = createRouter(project);
|
|
33312
|
+
if (router) {
|
|
33313
|
+
var fileLazyImports_1 = router.fileLazyImports, routeElements_1 = router.routeElements;
|
|
33314
|
+
traverse__default["default"](astTree, {
|
|
33315
|
+
Program: function (nodePath) {
|
|
33316
|
+
var body = nodePath.node.body;
|
|
33317
|
+
var componentIndex = body.findIndex(function (item) { return item.type === 'ExportDefaultDeclaration'; });
|
|
33318
|
+
body.splice.apply(body, __spreadArray([componentIndex, 0], __read(fileLazyImports_1), false));
|
|
33319
|
+
},
|
|
33320
|
+
JSXElement: function (nodePath) {
|
|
33321
|
+
var _a, _b;
|
|
33322
|
+
var node = nodePath.node;
|
|
33323
|
+
// @ts-ignore
|
|
33324
|
+
if (((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'Routes') {
|
|
33325
|
+
node.children = routeElements_1;
|
|
33326
|
+
}
|
|
33327
|
+
},
|
|
33328
|
+
});
|
|
33329
|
+
console.log('✅ 路由配置已添加');
|
|
33330
|
+
}
|
|
33331
|
+
}
|
|
33332
|
+
catch (error) {
|
|
33333
|
+
console.error('❌ 路由处理失败:', {
|
|
33334
|
+
error: error.message,
|
|
33335
|
+
type: error.name || 'RouterError',
|
|
33336
|
+
suggestion: '请检查项目配置中的路由信息是否正确',
|
|
33109
33337
|
});
|
|
33338
|
+
throw new Error("\u8DEF\u7531\u5904\u7406\u5931\u8D25: ".concat(error.message));
|
|
33110
33339
|
}
|
|
33111
33340
|
// 增加全局配置
|
|
33112
33341
|
var schema = project.schema;
|
|
33113
33342
|
var config = schema.config;
|
|
33114
33343
|
if ((_a = config === null || config === void 0 ? void 0 : config.layout) === null || _a === void 0 ? void 0 : _a.componentName) {
|
|
33115
|
-
|
|
33116
|
-
|
|
33117
|
-
.
|
|
33118
|
-
|
|
33119
|
-
|
|
33120
|
-
|
|
33121
|
-
|
|
33122
|
-
else if (typeof props_1[k] === 'number') {
|
|
33123
|
-
valueStr = "".concat(props_1[k]);
|
|
33124
|
-
}
|
|
33125
|
-
else if (typeof props_1[k] === 'object') {
|
|
33126
|
-
valueStr = "{".concat(JSON.stringify(props_1[k]), "}");
|
|
33127
|
-
}
|
|
33128
|
-
return "".concat(k, "=").concat(valueStr);
|
|
33129
|
-
})
|
|
33130
|
-
.join('\n'), "\n ><AntdApp></AntdApp></").concat(componentName, ">\n ");
|
|
33131
|
-
var layoutAstNode = codeToAST(code_1);
|
|
33132
|
-
var elNode_1 = layoutAstNode.expression;
|
|
33133
|
-
/**
|
|
33134
|
-
* 找到 AntdApp 下的 HashRouter 节点
|
|
33135
|
-
*/
|
|
33136
|
-
var routerNode_1;
|
|
33137
|
-
traverse__default["default"](astTree, {
|
|
33138
|
-
JSXElement: function (nodePath) {
|
|
33139
|
-
var _a, _b;
|
|
33140
|
-
var node = nodePath.node;
|
|
33141
|
-
// @ts-ignore
|
|
33142
|
-
if (((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'HashRouter') {
|
|
33143
|
-
routerNode_1 = nodePath;
|
|
33344
|
+
try {
|
|
33345
|
+
var _f = config.layout, componentName = _f.componentName, props_1 = _f.props;
|
|
33346
|
+
var code = "\n <".concat(componentName, "\n ").concat(Object.keys(props_1 || {})
|
|
33347
|
+
.map(function (k) {
|
|
33348
|
+
var valueStr = '';
|
|
33349
|
+
if (typeof props_1[k] === 'string') {
|
|
33350
|
+
valueStr = "'".concat(props_1[k], "'");
|
|
33144
33351
|
}
|
|
33145
|
-
|
|
33146
|
-
|
|
33147
|
-
|
|
33148
|
-
|
|
33149
|
-
|
|
33150
|
-
|
|
33151
|
-
|
|
33152
|
-
|
|
33153
|
-
|
|
33154
|
-
|
|
33155
|
-
|
|
33156
|
-
|
|
33352
|
+
else if (typeof props_1[k] === 'number') {
|
|
33353
|
+
valueStr = "".concat(props_1[k]);
|
|
33354
|
+
}
|
|
33355
|
+
else if (typeof props_1[k] === 'object') {
|
|
33356
|
+
valueStr = "{".concat(JSON.stringify(props_1[k]), "}");
|
|
33357
|
+
}
|
|
33358
|
+
return "".concat(k, "=").concat(valueStr);
|
|
33359
|
+
})
|
|
33360
|
+
.join('\n'), "\n ><AntdApp></AntdApp></").concat(componentName, ">\n ");
|
|
33361
|
+
var layoutAstNode = codeToAST(code);
|
|
33362
|
+
var elNode_1 = layoutAstNode.expression;
|
|
33363
|
+
/**
|
|
33364
|
+
* 找到 AntdApp 下的 HashRouter 节点
|
|
33365
|
+
*/
|
|
33366
|
+
var routerNode_1;
|
|
33367
|
+
traverse__default["default"](astTree, {
|
|
33368
|
+
JSXElement: function (nodePath) {
|
|
33369
|
+
var _a, _b;
|
|
33370
|
+
var node = nodePath.node;
|
|
33371
|
+
// @ts-ignore
|
|
33372
|
+
if (((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'HashRouter') {
|
|
33373
|
+
routerNode_1 = nodePath;
|
|
33157
33374
|
}
|
|
33158
|
-
|
|
33159
|
-
|
|
33160
|
-
|
|
33375
|
+
},
|
|
33376
|
+
});
|
|
33377
|
+
var once_1 = false;
|
|
33378
|
+
traverse__default["default"](astTree, {
|
|
33379
|
+
JSXElement: function (nodePath) {
|
|
33380
|
+
var _a, _b, _c, _d;
|
|
33381
|
+
var node = nodePath.node;
|
|
33382
|
+
// @ts-ignore
|
|
33383
|
+
if (((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'ConfigProvider' && !once_1) {
|
|
33384
|
+
if (appFile.includes('<AntdApp>') && routerNode_1) {
|
|
33385
|
+
// @ts-ignore
|
|
33386
|
+
elNode_1.children[0].children = routerNode_1.parent.children;
|
|
33387
|
+
}
|
|
33388
|
+
else {
|
|
33389
|
+
// @ts-ignore
|
|
33390
|
+
elNode_1.children[0].children = node.children;
|
|
33391
|
+
}
|
|
33392
|
+
nodePath.replaceWith(elNode_1);
|
|
33393
|
+
once_1 = true;
|
|
33161
33394
|
}
|
|
33162
|
-
nodePath.replaceWith(elNode_1);
|
|
33163
|
-
once_1 = true;
|
|
33164
|
-
}
|
|
33165
|
-
// @ts-ignore
|
|
33166
|
-
if (((_d = (_c = node.openingElement) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.name) === 'HashRouter' && !once_1) {
|
|
33167
33395
|
// @ts-ignore
|
|
33168
|
-
|
|
33169
|
-
|
|
33170
|
-
|
|
33171
|
-
|
|
33172
|
-
|
|
33173
|
-
|
|
33396
|
+
if (((_d = (_c = node.openingElement) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.name) === 'HashRouter' && !once_1) {
|
|
33397
|
+
// @ts-ignore
|
|
33398
|
+
elNode_1.children[0].children = [node];
|
|
33399
|
+
nodePath.replaceWith(elNode_1);
|
|
33400
|
+
once_1 = true;
|
|
33401
|
+
}
|
|
33402
|
+
},
|
|
33403
|
+
});
|
|
33404
|
+
console.log('✅ 布局配置已添加');
|
|
33405
|
+
}
|
|
33406
|
+
catch (error) {
|
|
33407
|
+
console.error('❌ 布局配置处理失败:', {
|
|
33408
|
+
error: error.message,
|
|
33409
|
+
type: error.name || 'LayoutError',
|
|
33410
|
+
componentName: (_b = config === null || config === void 0 ? void 0 : config.layout) === null || _b === void 0 ? void 0 : _b.componentName,
|
|
33411
|
+
suggestion: '请检查布局组件配置是否正确,包括组件名称和属性',
|
|
33412
|
+
});
|
|
33413
|
+
throw new Error("\u5E03\u5C40\u914D\u7F6E\u5904\u7406\u5931\u8D25: ".concat(error.message));
|
|
33414
|
+
}
|
|
33174
33415
|
}
|
|
33175
33416
|
// 处理导入语句
|
|
33176
|
-
if ((
|
|
33177
|
-
|
|
33178
|
-
|
|
33179
|
-
|
|
33180
|
-
|
|
33181
|
-
|
|
33182
|
-
|
|
33183
|
-
|
|
33184
|
-
|
|
33185
|
-
|
|
33186
|
-
|
|
33187
|
-
|
|
33188
|
-
|
|
33189
|
-
|
|
33190
|
-
|
|
33191
|
-
|
|
33417
|
+
if ((_e = (_d = (_c = project.schema) === null || _c === void 0 ? void 0 : _c.config) === null || _d === void 0 ? void 0 : _d.layout) === null || _e === void 0 ? void 0 : _e.componentName) {
|
|
33418
|
+
try {
|
|
33419
|
+
var requiredImports = [
|
|
33420
|
+
{
|
|
33421
|
+
name: 'App',
|
|
33422
|
+
as: 'AntdApp',
|
|
33423
|
+
from: 'antd',
|
|
33424
|
+
priority: 2,
|
|
33425
|
+
protected: true, // App 必须从 antd 导入
|
|
33426
|
+
},
|
|
33427
|
+
{
|
|
33428
|
+
name: 'ConfigProvider',
|
|
33429
|
+
from: '@appthen/antd',
|
|
33430
|
+
priority: 1,
|
|
33431
|
+
},
|
|
33432
|
+
];
|
|
33433
|
+
manageImports(astTree, requiredImports);
|
|
33434
|
+
console.log('✅ 导入语句已处理');
|
|
33435
|
+
}
|
|
33436
|
+
catch (error) {
|
|
33437
|
+
console.error('❌ 导入语句处理失败:', {
|
|
33438
|
+
error: error.message,
|
|
33439
|
+
type: error.name || 'ImportError',
|
|
33440
|
+
suggestion: '请检查导入配置是否正确,确保相关包已安装',
|
|
33441
|
+
});
|
|
33442
|
+
throw new Error("\u5BFC\u5165\u8BED\u53E5\u5904\u7406\u5931\u8D25: ".concat(error.message));
|
|
33443
|
+
}
|
|
33444
|
+
}
|
|
33445
|
+
var generatedCode;
|
|
33446
|
+
try {
|
|
33447
|
+
var result = generate__default["default"](astTree);
|
|
33448
|
+
generatedCode = result.code;
|
|
33449
|
+
}
|
|
33450
|
+
catch (error) {
|
|
33451
|
+
console.error('❌ 代码生成失败:', {
|
|
33452
|
+
error: error.message,
|
|
33453
|
+
type: error.name || 'GenerateError',
|
|
33454
|
+
suggestion: '请检查 AST 结构是否正确,可能是在处理过程中产生了无效的 AST 节点',
|
|
33455
|
+
});
|
|
33456
|
+
throw new Error("\u4EE3\u7801\u751F\u6210\u5931\u8D25: ".concat(error.message));
|
|
33457
|
+
}
|
|
33458
|
+
try {
|
|
33459
|
+
// 删除之前的字符串处理逻辑
|
|
33460
|
+
fs__namespace.writeFileSync('./src/App.jsx', generatedCode, 'utf8');
|
|
33461
|
+
console.log('✅ App.jsx 文件已成功更新');
|
|
33462
|
+
}
|
|
33463
|
+
catch (error) {
|
|
33464
|
+
console.error('❌ 写入 App.jsx 文件失败:', {
|
|
33465
|
+
filePath: './src/App.jsx',
|
|
33466
|
+
error: error.message,
|
|
33467
|
+
suggestion: '请确保有写入权限,且磁盘空间充足',
|
|
33468
|
+
});
|
|
33469
|
+
throw new Error("\u5199\u5165 App.jsx \u6587\u4EF6\u5931\u8D25: ".concat(error.message));
|
|
33192
33470
|
}
|
|
33193
|
-
var code = generate__default["default"](astTree).code;
|
|
33194
|
-
// 删除之前的字符串处理逻辑
|
|
33195
|
-
fs__namespace.writeFileSync('./src/App.jsx', code, 'utf8');
|
|
33196
33471
|
};
|
|
33197
33472
|
|
|
33198
33473
|
var writePackageJSON = function (packageJSON) {
|
|
@@ -36715,11 +36990,11 @@ var lastTimeKey$1 = '$__cacheTime';
|
|
|
36715
36990
|
* @returns {Promise<number>} 错误码
|
|
36716
36991
|
*/
|
|
36717
36992
|
function run(args, options) {
|
|
36718
|
-
var _a, _b, _c, _d;
|
|
36993
|
+
var _a, _b, _c, _d, _e, _f;
|
|
36719
36994
|
return __awaiter(this, void 0, void 0, function () {
|
|
36720
|
-
var cacheDirPath, keyCacheDirPath, currentLastTimeKey, cacheTime, afterTime, result, schema, project, documents, componentDocs, packageJSON, projectDocuments, projectDocumentNames_1, subPageDocumentNames_1, clientType, isWeb, solution, outputPath_1, builder, envInfoItem, generatedSourceCodes, publisher, subPageRoot_1, subPagePath, subPagePathIsExist, getPageUrl_1, transformFilePath, existFiles, existSubFiles,
|
|
36721
|
-
return __generator(this, function (
|
|
36722
|
-
switch (
|
|
36995
|
+
var cacheDirPath, keyCacheDirPath, currentLastTimeKey, cacheTime, afterTime, result, schema, project, documents, componentDocs, packageJSON, projectDocuments, projectDocumentNames_1, subPageDocumentNames_1, clientType, isWeb, solution, outputPath_1, builder, envInfoItem, schemaStr, generatedSourceCodes, publisher, subPageRoot_1, subPagePath, subPagePathIsExist, getPageUrl_1, transformFilePath, existFiles, existSubFiles, _g, files, syncMap, _loop_1, i, indexPage_1, indexPageUrl_1, globalStyle, globalStyleWithoutFirstLine, globalStyle, globalStyleWithoutFirstLine, appContent, appContentWithImport, utilsFilePath, portalImportCode, haveUpdate, installCmd, e_1;
|
|
36996
|
+
return __generator(this, function (_h) {
|
|
36997
|
+
switch (_h.label) {
|
|
36723
36998
|
case 0:
|
|
36724
36999
|
cacheDirPath = path__default["default"].join(os__default["default"].homedir(), '.cache', 'mengti_temp');
|
|
36725
37000
|
keyCacheDirPath = path__default["default"].join(os__default["default"].homedir(), '.cache', 'mengti_translate');
|
|
@@ -36728,9 +37003,9 @@ function run(args, options) {
|
|
|
36728
37003
|
removeDir(keyCacheDirPath);
|
|
36729
37004
|
}
|
|
36730
37005
|
currentLastTimeKey = path__default["default"].join(process.cwd() + '/' + (options.output || '')) + lastTimeKey$1;
|
|
36731
|
-
|
|
37006
|
+
_h.label = 1;
|
|
36732
37007
|
case 1:
|
|
36733
|
-
|
|
37008
|
+
_h.trys.push([1, 15, , 16]);
|
|
36734
37009
|
cacheTime = cache$1.getKey(currentLastTimeKey);
|
|
36735
37010
|
console.log('[最后同步时间] ', cacheTime ? new Date(Number(cacheTime)).toLocaleString() : '无');
|
|
36736
37011
|
afterTime = cacheTime && !options.clear ? Number(cacheTime) : 0;
|
|
@@ -36746,13 +37021,16 @@ function run(args, options) {
|
|
|
36746
37021
|
afterTime: afterTime,
|
|
36747
37022
|
})];
|
|
36748
37023
|
case 2:
|
|
36749
|
-
result =
|
|
37024
|
+
result = _h.sent();
|
|
36750
37025
|
console.log('[INFO] 项目下载完成... ');
|
|
36751
37026
|
schema = result.schema;
|
|
37027
|
+
console.log('🔍 原始路由数据:',
|
|
37028
|
+
// @ts-ignore
|
|
37029
|
+
JSON.stringify((_a = schema.router) === null || _a === void 0 ? void 0 : _a.routes, null, 2));
|
|
36752
37030
|
project = result.project, documents = result.documents, componentDocs = result.componentDocs, packageJSON = result.packageJSON;
|
|
36753
37031
|
projectDocuments = project.documents || [];
|
|
36754
37032
|
projectDocumentNames_1 = projectDocuments.map(function (_) { return _.fileName; });
|
|
36755
|
-
subPageDocumentNames_1 = ((
|
|
37033
|
+
subPageDocumentNames_1 = ((_b = project.appConfig) === null || _b === void 0 ? void 0 : _b.subPages) || [];
|
|
36756
37034
|
clientType = options.frame || (project === null || project === void 0 ? void 0 : project.type);
|
|
36757
37035
|
isWeb = clientType === 'web';
|
|
36758
37036
|
solution = isWeb ? 'vite' : 'taro';
|
|
@@ -36761,7 +37039,7 @@ function run(args, options) {
|
|
|
36761
37039
|
return [4 /*yield*/, updateProjectTemplate(solution)];
|
|
36762
37040
|
case 3:
|
|
36763
37041
|
// 更新项目模板
|
|
36764
|
-
|
|
37042
|
+
_h.sent();
|
|
36765
37043
|
console.log('[INFO] 项目模板更新完成... ');
|
|
36766
37044
|
// 检查是否有文件需要更新
|
|
36767
37045
|
if (!project || documents.length === 0) {
|
|
@@ -36777,20 +37055,21 @@ function run(args, options) {
|
|
|
36777
37055
|
console.log('[INFO] 创建项目构建器... ');
|
|
36778
37056
|
// 处理环境配置
|
|
36779
37057
|
if (options.env) {
|
|
36780
|
-
envInfoItem = (
|
|
37058
|
+
envInfoItem = (_d = (_c = project.envInfo) === null || _c === void 0 ? void 0 : _c.list) === null || _d === void 0 ? void 0 : _d.find(function (_) { return _.alias === options.env; });
|
|
36781
37059
|
if (envInfoItem) {
|
|
36782
37060
|
schema.constants = __assign(__assign({}, schema.constants), getPureValue(envInfoItem.data));
|
|
36783
37061
|
}
|
|
36784
37062
|
}
|
|
36785
37063
|
console.log('[INFO] 处理环境配置... ');
|
|
36786
|
-
|
|
37064
|
+
schemaStr = JSON.stringify((_e = schema.componentsTree) === null || _e === void 0 ? void 0 : _e.slice(0, 20).map(function (item) { return item.fileName; }));
|
|
37065
|
+
console.log('schemaStr: ', schemaStr);
|
|
36787
37066
|
// const isHaveCheckicon = schemaStr.indexOf('icon.style');
|
|
36788
37067
|
// console.log('isHaveCheck', schemaStr.slice(isHaveCheckicon - 20000, isHaveCheckicon + 20000));
|
|
36789
37068
|
// 生成代码
|
|
36790
37069
|
console.log('[INFO] 开始生成代码... ');
|
|
36791
|
-
return [4 /*yield*/, builder.generateProject(schema)];
|
|
37070
|
+
return [4 /*yield*/, builder.generateProject(JSON.parse(JSON.stringify(schema)))];
|
|
36792
37071
|
case 4:
|
|
36793
|
-
generatedSourceCodes =
|
|
37072
|
+
generatedSourceCodes = _h.sent();
|
|
36794
37073
|
console.log('[INFO] 代码生成完成... ');
|
|
36795
37074
|
generatedSourceCodes.files = generatedSourceCodes.files.filter(function (item) { return item.ext === 'css' || item.ext === 'jsx'; });
|
|
36796
37075
|
console.log('[INFO] 过滤代码... ');
|
|
@@ -36807,7 +37086,7 @@ function run(args, options) {
|
|
|
36807
37086
|
createProjectFolder: false,
|
|
36808
37087
|
})];
|
|
36809
37088
|
case 5:
|
|
36810
|
-
|
|
37089
|
+
_h.sent();
|
|
36811
37090
|
console.log('[INFO] 代码生成完成... ');
|
|
36812
37091
|
if (!fs.existsSync("./".concat(outputPath_1, "/"))) {
|
|
36813
37092
|
fs.mkdirSync("./".concat(outputPath_1, "/"), {
|
|
@@ -36833,27 +37112,29 @@ function run(args, options) {
|
|
|
36833
37112
|
return "".concat(pagesPath, "/").concat(file.name, "/index");
|
|
36834
37113
|
};
|
|
36835
37114
|
transformFilePath = function (file) {
|
|
36836
|
-
if (subPageRoot_1 &&
|
|
37115
|
+
if (subPageRoot_1 &&
|
|
37116
|
+
file.path.includes('pages') &&
|
|
37117
|
+
subPageDocumentNames_1.includes(file.name)) {
|
|
36837
37118
|
return file.path.replace('pages', subPageRoot_1);
|
|
36838
37119
|
}
|
|
36839
37120
|
return file.path;
|
|
36840
37121
|
};
|
|
36841
37122
|
return [4 /*yield*/, getAllFile("./".concat(outputPath_1, "/"))];
|
|
36842
37123
|
case 6:
|
|
36843
|
-
existFiles =
|
|
37124
|
+
existFiles = _h.sent();
|
|
36844
37125
|
if (!subPagePathIsExist) return [3 /*break*/, 8];
|
|
36845
37126
|
return [4 /*yield*/, getAllFile(subPagePath)];
|
|
36846
37127
|
case 7:
|
|
36847
|
-
|
|
37128
|
+
_g = _h.sent();
|
|
36848
37129
|
return [3 /*break*/, 9];
|
|
36849
37130
|
case 8:
|
|
36850
|
-
|
|
36851
|
-
|
|
37131
|
+
_g = [];
|
|
37132
|
+
_h.label = 9;
|
|
36852
37133
|
case 9:
|
|
36853
|
-
existSubFiles =
|
|
37134
|
+
existSubFiles = _g;
|
|
36854
37135
|
return [4 /*yield*/, getAllFile(cacheDirPath + '/')];
|
|
36855
37136
|
case 10:
|
|
36856
|
-
files =
|
|
37137
|
+
files = _h.sent();
|
|
36857
37138
|
syncMap = {
|
|
36858
37139
|
components: existFiles
|
|
36859
37140
|
.filter(function (_) { return ['tsx', 'jsx'].includes(_.ext) && _.path.includes('components'); })
|
|
@@ -36905,12 +37186,17 @@ function run(args, options) {
|
|
|
36905
37186
|
.map(function (_) { return getPageUrl_1(_, subPageRoot_1); }),
|
|
36906
37187
|
};
|
|
36907
37188
|
_loop_1 = function (i) {
|
|
36908
|
-
var file, fileName_1, extName, cssFilePath, cssStr, doc,
|
|
36909
|
-
return __generator(this, function (
|
|
36910
|
-
switch (
|
|
37189
|
+
var file, fileName_1, extName, cssFilePath, cssStr, doc, _j, code, images, svgs, configJsCode, iconsFile, iconsConsts, index, svg, index, image, e_2, realFilePath;
|
|
37190
|
+
return __generator(this, function (_k) {
|
|
37191
|
+
switch (_k.label) {
|
|
36911
37192
|
case 0:
|
|
36912
37193
|
file = files[i];
|
|
36913
|
-
|
|
37194
|
+
if (process.env.DEV) {
|
|
37195
|
+
console.log('[BUILD FILE]', file);
|
|
37196
|
+
}
|
|
37197
|
+
else {
|
|
37198
|
+
console.log('[BUILD FILE]', file.name);
|
|
37199
|
+
}
|
|
36914
37200
|
if (!!file.path.includes('/BasicLayout/')) return [3 /*break*/, 10];
|
|
36915
37201
|
fileName_1 = file.name;
|
|
36916
37202
|
extName = file.ext;
|
|
@@ -36919,8 +37205,8 @@ function run(args, options) {
|
|
|
36919
37205
|
if (!(file.fileName === 'utils.js')) return [3 /*break*/, 2];
|
|
36920
37206
|
return [4 /*yield*/, transformUtils(file, schema, project, solution)];
|
|
36921
37207
|
case 1:
|
|
36922
|
-
|
|
36923
|
-
|
|
37208
|
+
_k.sent();
|
|
37209
|
+
_k.label = 2;
|
|
36924
37210
|
case 2:
|
|
36925
37211
|
if (extName === 'css' || extName === 'scss') {
|
|
36926
37212
|
cssFilePath = file.path + '/' + file.fileName;
|
|
@@ -36945,15 +37231,18 @@ function run(args, options) {
|
|
|
36945
37231
|
}
|
|
36946
37232
|
if (!(extName === 'jsx' || extName === 'tsx')) return [3 /*break*/, 10];
|
|
36947
37233
|
doc = documents.concat(componentDocs).find(function (_) {
|
|
37234
|
+
console.log('fileName: ', fileName_1, _.fileName);
|
|
36948
37235
|
return _.fileName.toLowerCase() === fileName_1.toLowerCase();
|
|
36949
37236
|
});
|
|
36950
37237
|
// 判断是否是页面
|
|
36951
37238
|
if ((doc === null || doc === void 0 ? void 0 : doc.type) === 'Page') {
|
|
36952
|
-
if (!syncMap.pages.includes(fileName_1) &&
|
|
37239
|
+
if (!syncMap.pages.includes(fileName_1) &&
|
|
37240
|
+
!subPageDocumentNames_1.includes(fileName_1)) {
|
|
36953
37241
|
syncMap.pages.push(fileName_1);
|
|
36954
37242
|
syncMap.pageUrls.push(getPageUrl_1(file));
|
|
36955
37243
|
}
|
|
36956
|
-
if (!syncMap.subPages.includes(fileName_1) &&
|
|
37244
|
+
if (!syncMap.subPages.includes(fileName_1) &&
|
|
37245
|
+
subPageDocumentNames_1.includes(fileName_1)) {
|
|
36957
37246
|
syncMap.subPages.push(fileName_1);
|
|
36958
37247
|
syncMap.subPageUrls.push(getPageUrl_1(file, subPageRoot_1));
|
|
36959
37248
|
}
|
|
@@ -36966,7 +37255,7 @@ function run(args, options) {
|
|
|
36966
37255
|
}
|
|
36967
37256
|
return [4 /*yield*/, transformJsx(file, solution, outputPath_1)];
|
|
36968
37257
|
case 3:
|
|
36969
|
-
|
|
37258
|
+
_j = _k.sent(), code = _j.code, images = _j.images, svgs = _j.svgs;
|
|
36970
37259
|
console.log('[BUILD SUCCESS]', file.name);
|
|
36971
37260
|
// 写入暂存文件夹
|
|
36972
37261
|
fs.writeFileSync(file.path + '/' + file.fileName, code);
|
|
@@ -37012,30 +37301,32 @@ function run(args, options) {
|
|
|
37012
37301
|
.join('\n'));
|
|
37013
37302
|
}
|
|
37014
37303
|
index = 0;
|
|
37015
|
-
|
|
37304
|
+
_k.label = 4;
|
|
37016
37305
|
case 4:
|
|
37017
37306
|
if (!(index < images.length)) return [3 /*break*/, 9];
|
|
37018
37307
|
image = images[index];
|
|
37019
37308
|
if (!(image.url && image.fileName)) return [3 /*break*/, 8];
|
|
37020
|
-
|
|
37309
|
+
_k.label = 5;
|
|
37021
37310
|
case 5:
|
|
37022
|
-
|
|
37311
|
+
_k.trys.push([5, 7, , 8]);
|
|
37023
37312
|
if (!fs.existsSync(file.path + '/images')) {
|
|
37024
37313
|
fs.mkdirSync(file.path + '/images');
|
|
37025
37314
|
}
|
|
37026
37315
|
return [4 /*yield*/, downloadFile(image.url, file.path + '/images/' + image.fileName)];
|
|
37027
37316
|
case 6:
|
|
37028
|
-
|
|
37317
|
+
_k.sent();
|
|
37029
37318
|
return [3 /*break*/, 8];
|
|
37030
37319
|
case 7:
|
|
37031
|
-
e_2 =
|
|
37320
|
+
e_2 = _k.sent();
|
|
37032
37321
|
console.log('[downloadFile Error] ', e_2);
|
|
37033
37322
|
return [3 /*break*/, 8];
|
|
37034
37323
|
case 8:
|
|
37035
37324
|
index++;
|
|
37036
37325
|
return [3 /*break*/, 4];
|
|
37037
37326
|
case 9:
|
|
37038
|
-
realFilePath = "./".concat(subPageDocumentNames_1.includes(file.name)
|
|
37327
|
+
realFilePath = "./".concat(subPageDocumentNames_1.includes(file.name)
|
|
37328
|
+
? outputPath_1 === null || outputPath_1 === void 0 ? void 0 : outputPath_1.replace('pages', subPageRoot_1)
|
|
37329
|
+
: outputPath_1, "/").concat(file.name);
|
|
37039
37330
|
if ((doc === null || doc === void 0 ? void 0 : doc.type) === 'Component') {
|
|
37040
37331
|
realFilePath = "./".concat(outputPath_1, "/components/").concat(file.name);
|
|
37041
37332
|
}
|
|
@@ -37043,32 +37334,35 @@ function run(args, options) {
|
|
|
37043
37334
|
if (fs.existsSync(realFilePath)) {
|
|
37044
37335
|
removeDir(realFilePath);
|
|
37045
37336
|
}
|
|
37337
|
+
console.log('realFilePath: ', realFilePath, doc === null || doc === void 0 ? void 0 : doc.fileName, doc === null || doc === void 0 ? void 0 : doc.type);
|
|
37046
37338
|
if ((doc === null || doc === void 0 ? void 0 : doc.type) === 'Page') {
|
|
37047
|
-
|
|
37339
|
+
console.log('realFilePath: ', realFilePath);
|
|
37340
|
+
fs.copySync("".concat(cacheDirPath, "/src/pages/").concat(file.name), realFilePath.replace(file.name, doc.fileName));
|
|
37048
37341
|
}
|
|
37049
37342
|
if ((doc === null || doc === void 0 ? void 0 : doc.type) === 'Component') {
|
|
37050
|
-
|
|
37343
|
+
console.log('realFilePath1: ', realFilePath);
|
|
37344
|
+
fs.copySync("".concat(cacheDirPath, "/src/components/").concat(file.name), realFilePath.replace(file.name, doc.fileName));
|
|
37051
37345
|
}
|
|
37052
|
-
|
|
37346
|
+
_k.label = 10;
|
|
37053
37347
|
case 10: return [2 /*return*/];
|
|
37054
37348
|
}
|
|
37055
37349
|
});
|
|
37056
37350
|
};
|
|
37057
37351
|
i = 0;
|
|
37058
|
-
|
|
37352
|
+
_h.label = 11;
|
|
37059
37353
|
case 11:
|
|
37060
37354
|
if (!(i < files.length)) return [3 /*break*/, 14];
|
|
37061
37355
|
return [5 /*yield**/, _loop_1(i)];
|
|
37062
37356
|
case 12:
|
|
37063
|
-
|
|
37064
|
-
|
|
37357
|
+
_h.sent();
|
|
37358
|
+
_h.label = 13;
|
|
37065
37359
|
case 13:
|
|
37066
37360
|
i++;
|
|
37067
37361
|
return [3 /*break*/, 11];
|
|
37068
37362
|
case 14:
|
|
37069
37363
|
// 更新同步时间
|
|
37070
37364
|
cache$1.setKey(currentLastTimeKey, String(Date.now()));
|
|
37071
|
-
indexPage_1 = (
|
|
37365
|
+
indexPage_1 = (_f = project.appConfig) === null || _f === void 0 ? void 0 : _f.indexPage;
|
|
37072
37366
|
if (indexPage_1) {
|
|
37073
37367
|
// 首页排序
|
|
37074
37368
|
syncMap.pages = syncMap.pages.sort(function (a, b) {
|
|
@@ -37120,11 +37414,21 @@ function run(args, options) {
|
|
|
37120
37414
|
fs.writeFileSync('./src/app.tsx', appContentWithImport);
|
|
37121
37415
|
}
|
|
37122
37416
|
}
|
|
37417
|
+
utilsFilePath = "".concat(cacheDirPath, "/src/utils.js");
|
|
37418
|
+
if (process.env.DEV) {
|
|
37419
|
+
console.log('[utilsFilePath]', utilsFilePath);
|
|
37420
|
+
}
|
|
37123
37421
|
// 生成 utils & constants
|
|
37124
|
-
fs.copyFileSync(
|
|
37422
|
+
fs.copyFileSync(utilsFilePath, './src/utils/utils.js');
|
|
37125
37423
|
fs.copyFileSync("".concat(cacheDirPath, "/src/constants.js"), './src/utils/constants.js');
|
|
37424
|
+
if (process.env.DEV) {
|
|
37425
|
+
console.log('[Start CreatePartalImport]');
|
|
37426
|
+
}
|
|
37126
37427
|
portalImportCode = createPartalImport(project, outputPath_1, solution);
|
|
37127
37428
|
fs.writeFileSync('./src/utils/portal.js', portalImportCode);
|
|
37429
|
+
if (process.env.DEV) {
|
|
37430
|
+
console.log('[End CreatePartalImport]');
|
|
37431
|
+
}
|
|
37128
37432
|
if (!isWeb) {
|
|
37129
37433
|
// 小程序配置
|
|
37130
37434
|
genAppConfig(options.frame || project.type, project, syncMap);
|
|
@@ -37132,6 +37436,9 @@ function run(args, options) {
|
|
|
37132
37436
|
else {
|
|
37133
37437
|
createAppFile(project);
|
|
37134
37438
|
}
|
|
37439
|
+
if (process.env.DEV) {
|
|
37440
|
+
console.log('[End GenAppConfig]');
|
|
37441
|
+
}
|
|
37135
37442
|
haveUpdate = writePackageJSON(packageJSON);
|
|
37136
37443
|
if (haveUpdate) {
|
|
37137
37444
|
console.log('[INFO] package.json 文件已更新,将重新安装依赖');
|
|
@@ -37146,7 +37453,7 @@ function run(args, options) {
|
|
|
37146
37453
|
console.log("[INFO ".concat(new Date().toLocaleString(), "] \u4EE3\u7801\u589E\u91CF\u540C\u6B65\u5B8C\u6210"));
|
|
37147
37454
|
return [2 /*return*/, 0];
|
|
37148
37455
|
case 15:
|
|
37149
|
-
e_1 =
|
|
37456
|
+
e_1 = _h.sent();
|
|
37150
37457
|
console.log(chalk__default["default"].red(getErrorMessage(e_1) || "Unexpected error: ".concat(e_1)));
|
|
37151
37458
|
// 保存缓存
|
|
37152
37459
|
cache$1.removeKey(currentLastTimeKey);
|
|
@@ -40385,6 +40692,10 @@ function regExpEscape (s) {
|
|
|
40385
40692
|
var ShadowSpace = /** @class */ (function () {
|
|
40386
40693
|
function ShadowSpace(config) {
|
|
40387
40694
|
this.contentCache = new Map(); // 内容缓存
|
|
40695
|
+
// 🆕 文件监听相关
|
|
40696
|
+
this.watcher = null;
|
|
40697
|
+
this.changeListeners = new Set();
|
|
40698
|
+
this.isWatching = false;
|
|
40388
40699
|
this.config = __assign({ spaceId: 'default', ignorePatterns: [
|
|
40389
40700
|
'node_modules/**',
|
|
40390
40701
|
'.git/**',
|
|
@@ -40425,6 +40736,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40425
40736
|
'.php',
|
|
40426
40737
|
'.rb',
|
|
40427
40738
|
'.swift',
|
|
40739
|
+
'.flow',
|
|
40740
|
+
'.draw',
|
|
40428
40741
|
'.kt',
|
|
40429
40742
|
'.data', // 添加 .data 扩展名支持
|
|
40430
40743
|
] }, config);
|
|
@@ -40504,7 +40817,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40504
40817
|
ShadowSpace.prototype.syncFromEditor = function (projectFiles) {
|
|
40505
40818
|
var _a;
|
|
40506
40819
|
return __awaiter(this, void 0, void 0, function () {
|
|
40507
|
-
var newFiles, projectFiles_1, projectFiles_1_1, file,
|
|
40820
|
+
var newFiles, projectFiles_1, projectFiles_1_1, file, size, now, fullPath, writtenContent, localHash, remoteHash, e_1_1, _b, _c, _d, filePath, fileEntry, allFiles, totalFilesCount, totalSizeSum;
|
|
40508
40821
|
var e_1, _e, e_2, _f;
|
|
40509
40822
|
return __generator(this, function (_g) {
|
|
40510
40823
|
switch (_g.label) {
|
|
@@ -40513,61 +40826,69 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40513
40826
|
newFiles = {};
|
|
40514
40827
|
_g.label = 1;
|
|
40515
40828
|
case 1:
|
|
40516
|
-
_g.trys.push([1,
|
|
40829
|
+
_g.trys.push([1, 7, 8, 9]);
|
|
40517
40830
|
projectFiles_1 = __values(projectFiles), projectFiles_1_1 = projectFiles_1.next();
|
|
40518
40831
|
_g.label = 2;
|
|
40519
40832
|
case 2:
|
|
40520
|
-
if (!!projectFiles_1_1.done) return [3 /*break*/,
|
|
40833
|
+
if (!!projectFiles_1_1.done) return [3 /*break*/, 6];
|
|
40521
40834
|
file = projectFiles_1_1.value;
|
|
40522
40835
|
if (this.shouldIgnoreFile(file.path)) {
|
|
40523
40836
|
console.log("[ShadowSpace] \u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(file.path));
|
|
40524
|
-
return [3 /*break*/,
|
|
40837
|
+
return [3 /*break*/, 5];
|
|
40525
40838
|
}
|
|
40526
|
-
localHash = this.calculateHash(file.content);
|
|
40527
40839
|
size = Buffer.byteLength(file.content, 'utf8');
|
|
40528
40840
|
now = Date.now();
|
|
40529
40841
|
// 记录空内容文件
|
|
40530
40842
|
if (file.content === '') {
|
|
40531
40843
|
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7A7A\u5185\u5BB9\u6587\u4EF6: ".concat(file.path, " (size: ").concat(size, ")"));
|
|
40532
40844
|
}
|
|
40845
|
+
// 写入本地文件
|
|
40846
|
+
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40847
|
+
case 3:
|
|
40848
|
+
// 写入本地文件
|
|
40849
|
+
_g.sent();
|
|
40850
|
+
fullPath = path__default["default"].join(this.config.projectRoot, file.path);
|
|
40851
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
40852
|
+
case 4:
|
|
40853
|
+
writtenContent = _g.sent();
|
|
40854
|
+
localHash = this.calculateHash(writtenContent);
|
|
40855
|
+
remoteHash = file.hash || localHash;
|
|
40533
40856
|
newFiles[file.path] = {
|
|
40534
40857
|
path: file.path,
|
|
40535
40858
|
hash: localHash,
|
|
40536
|
-
remoteHash:
|
|
40859
|
+
remoteHash: remoteHash,
|
|
40537
40860
|
size: size,
|
|
40538
40861
|
lastSyncTime: now,
|
|
40539
40862
|
lastModified: file.modify || now,
|
|
40540
40863
|
version: ((_a = this.state.files[file.path]) === null || _a === void 0 ? void 0 : _a.version) + 1 || 1,
|
|
40541
40864
|
mtime: now,
|
|
40865
|
+
remoteModified: true,
|
|
40866
|
+
remoteModifiedTime: now,
|
|
40542
40867
|
};
|
|
40543
40868
|
console.log("[ShadowSpace] \u540C\u6B65\u6587\u4EF6: ".concat(file.path), {
|
|
40869
|
+
remoteHash: remoteHash.substring(0, 16),
|
|
40544
40870
|
localHash: localHash.substring(0, 16),
|
|
40545
|
-
remoteHash: (file.hash || localHash).substring(0, 16),
|
|
40546
40871
|
size: size,
|
|
40872
|
+
version: newFiles[file.path].version,
|
|
40547
40873
|
});
|
|
40548
|
-
// 写入本地文件
|
|
40549
|
-
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40550
|
-
case 3:
|
|
40551
|
-
// 写入本地文件
|
|
40552
|
-
_g.sent();
|
|
40553
40874
|
// 缓存内容用于diff
|
|
40554
|
-
this.contentCache.set(file.path,
|
|
40555
|
-
_g.label =
|
|
40556
|
-
case
|
|
40875
|
+
this.contentCache.set(file.path, writtenContent);
|
|
40876
|
+
_g.label = 5;
|
|
40877
|
+
case 5:
|
|
40557
40878
|
projectFiles_1_1 = projectFiles_1.next();
|
|
40558
40879
|
return [3 /*break*/, 2];
|
|
40559
|
-
case
|
|
40560
|
-
case
|
|
40880
|
+
case 6: return [3 /*break*/, 9];
|
|
40881
|
+
case 7:
|
|
40561
40882
|
e_1_1 = _g.sent();
|
|
40562
40883
|
e_1 = { error: e_1_1 };
|
|
40563
|
-
return [3 /*break*/,
|
|
40564
|
-
case
|
|
40884
|
+
return [3 /*break*/, 9];
|
|
40885
|
+
case 8:
|
|
40565
40886
|
try {
|
|
40566
40887
|
if (projectFiles_1_1 && !projectFiles_1_1.done && (_e = projectFiles_1.return)) _e.call(projectFiles_1);
|
|
40567
40888
|
}
|
|
40568
40889
|
finally { if (e_1) throw e_1.error; }
|
|
40569
40890
|
return [7 /*endfinally*/];
|
|
40570
|
-
case
|
|
40891
|
+
case 9:
|
|
40571
40892
|
try {
|
|
40572
40893
|
// 合并文件记录,而不是替换
|
|
40573
40894
|
for (_b = __values(Object.entries(newFiles)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
@@ -40593,11 +40914,11 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40593
40914
|
console.log("[ShadowSpace] \u66F4\u65B0\u540E\u7684\u6587\u4EF6\u7EDF\u8BA1:", {
|
|
40594
40915
|
totalFiles: totalFilesCount,
|
|
40595
40916
|
totalSize: totalSizeSum,
|
|
40596
|
-
fileList: Object.keys(this.state.files),
|
|
40917
|
+
// fileList: Object.keys(this.state.files),
|
|
40597
40918
|
});
|
|
40598
40919
|
this.state.lastUpdateTime = Date.now();
|
|
40599
40920
|
return [4 /*yield*/, this.saveState()];
|
|
40600
|
-
case
|
|
40921
|
+
case 10:
|
|
40601
40922
|
_g.sent();
|
|
40602
40923
|
console.log("\u5F71\u5B50\u7A7A\u95F4\u540C\u6B65\u5B8C\u6210: ".concat(this.state.metadata.totalFiles, " \u4E2A\u6587\u4EF6"));
|
|
40603
40924
|
return [2 /*return*/];
|
|
@@ -40696,54 +41017,62 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40696
41017
|
* 检测本地文件系统与影子空间的差异
|
|
40697
41018
|
*/
|
|
40698
41019
|
ShadowSpace.prototype.detectChanges = function () {
|
|
41020
|
+
var _a;
|
|
40699
41021
|
return __awaiter(this, void 0, void 0, function () {
|
|
40700
|
-
var changes,
|
|
40701
|
-
var e_3,
|
|
40702
|
-
return __generator(this, function (
|
|
40703
|
-
switch (
|
|
41022
|
+
var changes, _b, _c, _d, filePath, shadowEntry, localFilePath, localContent, localHash, _e, _f, _g, shadowContent, _h, _j, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
|
|
41023
|
+
var e_3, _k, _l, _m, e_4, _o;
|
|
41024
|
+
return __generator(this, function (_p) {
|
|
41025
|
+
switch (_p.label) {
|
|
40704
41026
|
case 0:
|
|
40705
41027
|
changes = [];
|
|
40706
|
-
|
|
41028
|
+
_p.label = 1;
|
|
40707
41029
|
case 1:
|
|
40708
|
-
|
|
40709
|
-
|
|
40710
|
-
|
|
41030
|
+
_p.trys.push([1, 16, 17, 18]);
|
|
41031
|
+
_b = __values(Object.entries(this.state.files)), _c = _b.next();
|
|
41032
|
+
_p.label = 2;
|
|
40711
41033
|
case 2:
|
|
40712
|
-
if (!!
|
|
40713
|
-
|
|
41034
|
+
if (!!_c.done) return [3 /*break*/, 15];
|
|
41035
|
+
_d = __read(_c.value, 2), filePath = _d[0], shadowEntry = _d[1];
|
|
40714
41036
|
localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
|
|
40715
|
-
|
|
41037
|
+
_p.label = 3;
|
|
40716
41038
|
case 3:
|
|
40717
|
-
|
|
41039
|
+
_p.trys.push([3, 11, , 14]);
|
|
40718
41040
|
return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
|
|
40719
41041
|
case 4:
|
|
40720
|
-
localContent =
|
|
41042
|
+
localContent = _p.sent();
|
|
40721
41043
|
localHash = this.calculateHash(localContent);
|
|
40722
41044
|
if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
|
|
41045
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(filePath), {
|
|
41046
|
+
localHash: localHash.substring(0, 16),
|
|
41047
|
+
shadowHash: shadowEntry.hash.substring(0, 16),
|
|
41048
|
+
remoteHash: ((_a = shadowEntry.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41049
|
+
remoteModified: shadowEntry.remoteModified || false,
|
|
41050
|
+
version: shadowEntry.version,
|
|
41051
|
+
});
|
|
40723
41052
|
if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
|
|
40724
41053
|
// 如果是远程修改,先更新影子空间记录并清除远程修改标记
|
|
40725
41054
|
console.log("\u68C0\u6D4B\u5230\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u53D8\u5316: ".concat(filePath));
|
|
40726
41055
|
// 更新影子空间记录
|
|
40727
|
-
|
|
40728
|
-
|
|
40729
|
-
|
|
40730
|
-
|
|
41056
|
+
_e = this.state.files;
|
|
41057
|
+
_f = filePath;
|
|
41058
|
+
_g = [__assign({}, shadowEntry)];
|
|
41059
|
+
_l = { hash: localHash };
|
|
40731
41060
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
40732
41061
|
case 5:
|
|
40733
|
-
|
|
41062
|
+
_l.size = (_p.sent()).size, _l.lastSyncTime = Date.now(), _l.version = shadowEntry.version + 1;
|
|
40734
41063
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
40735
41064
|
case 6:
|
|
40736
41065
|
// 更新影子空间记录
|
|
40737
|
-
|
|
41066
|
+
_e[_f] = __assign.apply(void 0, _g.concat([(_l.mtime = (_p.sent()).mtimeMs, _l.remoteModified = false, _l)]));
|
|
40738
41067
|
// 如果本地内容与最初的远程内容不同,则认为是本地修改
|
|
40739
41068
|
// 这里我们简化处理:任何在远程修改基础上的本地变化都视为本地修改
|
|
40740
41069
|
console.log("\u6587\u4EF6 ".concat(filePath, " \u5728\u8FDC\u7A0B\u4FEE\u6539\u57FA\u7840\u4E0A\u53D1\u751F\u4E86\u672C\u5730\u53D8\u5316\uFF0C\u6807\u8BB0\u4E3A\u672C\u5730\u4FEE\u6539"));
|
|
40741
|
-
|
|
41070
|
+
_p.label = 7;
|
|
40742
41071
|
case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
40743
41072
|
case 8:
|
|
40744
|
-
shadowContent =
|
|
40745
|
-
|
|
40746
|
-
|
|
41073
|
+
shadowContent = _p.sent();
|
|
41074
|
+
_j = (_h = changes).push;
|
|
41075
|
+
_m = {
|
|
40747
41076
|
id: this.generateId(),
|
|
40748
41077
|
action: 'modify',
|
|
40749
41078
|
path: filePath,
|
|
@@ -40751,21 +41080,21 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40751
41080
|
};
|
|
40752
41081
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
40753
41082
|
case 9:
|
|
40754
|
-
|
|
40755
|
-
|
|
41083
|
+
_j.apply(_h, [(_m.timestamp = (_p.sent()).mtime.getTime(),
|
|
41084
|
+
_m.diff = {
|
|
40756
41085
|
before: shadowContent,
|
|
40757
41086
|
after: localContent,
|
|
40758
41087
|
},
|
|
40759
|
-
|
|
40760
|
-
|
|
40761
|
-
|
|
41088
|
+
_m.projectId = this.state.projectId,
|
|
41089
|
+
_m)]);
|
|
41090
|
+
_p.label = 10;
|
|
40762
41091
|
case 10: return [3 /*break*/, 14];
|
|
40763
41092
|
case 11:
|
|
40764
|
-
error_2 =
|
|
41093
|
+
error_2 = _p.sent();
|
|
40765
41094
|
if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
|
|
40766
41095
|
return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
40767
41096
|
case 12:
|
|
40768
|
-
shadowContent =
|
|
41097
|
+
shadowContent = _p.sent();
|
|
40769
41098
|
changes.push({
|
|
40770
41099
|
id: this.generateId(),
|
|
40771
41100
|
action: 'delete',
|
|
@@ -40778,25 +41107,25 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40778
41107
|
},
|
|
40779
41108
|
projectId: this.state.projectId,
|
|
40780
41109
|
});
|
|
40781
|
-
|
|
41110
|
+
_p.label = 13;
|
|
40782
41111
|
case 13: return [3 /*break*/, 14];
|
|
40783
41112
|
case 14:
|
|
40784
|
-
|
|
41113
|
+
_c = _b.next();
|
|
40785
41114
|
return [3 /*break*/, 2];
|
|
40786
41115
|
case 15: return [3 /*break*/, 18];
|
|
40787
41116
|
case 16:
|
|
40788
|
-
e_3_1 =
|
|
41117
|
+
e_3_1 = _p.sent();
|
|
40789
41118
|
e_3 = { error: e_3_1 };
|
|
40790
41119
|
return [3 /*break*/, 18];
|
|
40791
41120
|
case 17:
|
|
40792
41121
|
try {
|
|
40793
|
-
if (
|
|
41122
|
+
if (_c && !_c.done && (_k = _b.return)) _k.call(_b);
|
|
40794
41123
|
}
|
|
40795
41124
|
finally { if (e_3) throw e_3.error; }
|
|
40796
41125
|
return [7 /*endfinally*/];
|
|
40797
41126
|
case 18: return [4 /*yield*/, this.scanLocalFiles()];
|
|
40798
41127
|
case 19:
|
|
40799
|
-
localFiles =
|
|
41128
|
+
localFiles = _p.sent();
|
|
40800
41129
|
try {
|
|
40801
41130
|
for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
|
|
40802
41131
|
localFile = localFiles_1_1.value;
|
|
@@ -40819,7 +41148,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40819
41148
|
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
40820
41149
|
finally {
|
|
40821
41150
|
try {
|
|
40822
|
-
if (localFiles_1_1 && !localFiles_1_1.done && (
|
|
41151
|
+
if (localFiles_1_1 && !localFiles_1_1.done && (_o = localFiles_1.return)) _o.call(localFiles_1);
|
|
40823
41152
|
}
|
|
40824
41153
|
finally { if (e_4) throw e_4.error; }
|
|
40825
41154
|
}
|
|
@@ -40949,38 +41278,40 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40949
41278
|
* 当编辑器通过WebSocket修改文件后调用此方法
|
|
40950
41279
|
*/
|
|
40951
41280
|
ShadowSpace.prototype.markAsRemoteModified = function (filePaths) {
|
|
41281
|
+
var _a;
|
|
40952
41282
|
return __awaiter(this, void 0, void 0, function () {
|
|
40953
|
-
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, error_4, e_6_1;
|
|
40954
|
-
var e_6,
|
|
40955
|
-
return __generator(this, function (
|
|
40956
|
-
switch (
|
|
41283
|
+
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_4, e_6_1;
|
|
41284
|
+
var e_6, _b;
|
|
41285
|
+
return __generator(this, function (_c) {
|
|
41286
|
+
switch (_c.label) {
|
|
40957
41287
|
case 0:
|
|
40958
41288
|
now = Date.now();
|
|
40959
41289
|
hasChanges = false;
|
|
40960
|
-
|
|
41290
|
+
_c.label = 1;
|
|
40961
41291
|
case 1:
|
|
40962
|
-
|
|
41292
|
+
_c.trys.push([1, 9, 10, 11]);
|
|
40963
41293
|
filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
|
|
40964
|
-
|
|
41294
|
+
_c.label = 2;
|
|
40965
41295
|
case 2:
|
|
40966
41296
|
if (!!filePaths_1_1.done) return [3 /*break*/, 8];
|
|
40967
41297
|
filePath = filePaths_1_1.value;
|
|
40968
41298
|
fullPath = path__default["default"].resolve(this.config.projectRoot, filePath);
|
|
40969
|
-
|
|
41299
|
+
_c.label = 3;
|
|
40970
41300
|
case 3:
|
|
40971
|
-
|
|
41301
|
+
_c.trys.push([3, 6, , 7]);
|
|
40972
41302
|
return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
|
|
40973
41303
|
case 4:
|
|
40974
|
-
stats =
|
|
41304
|
+
stats = _c.sent();
|
|
40975
41305
|
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
40976
41306
|
case 5:
|
|
40977
|
-
content =
|
|
41307
|
+
content = _c.sent();
|
|
40978
41308
|
hash = this.calculateHash(content);
|
|
40979
41309
|
existingFile = this.state.files[filePath];
|
|
41310
|
+
remoteHash = (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash;
|
|
40980
41311
|
this.state.files[filePath] = {
|
|
40981
41312
|
path: filePath,
|
|
40982
41313
|
hash: hash,
|
|
40983
|
-
remoteHash:
|
|
41314
|
+
remoteHash: remoteHash,
|
|
40984
41315
|
size: stats.size,
|
|
40985
41316
|
lastSyncTime: now,
|
|
40986
41317
|
lastModified: now,
|
|
@@ -40990,10 +41321,16 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40990
41321
|
remoteModifiedTime: now,
|
|
40991
41322
|
};
|
|
40992
41323
|
hasChanges = true;
|
|
40993
|
-
console.log("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath
|
|
41324
|
+
console.log("[ShadowSpace] \u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath), {
|
|
41325
|
+
版本: this.state.files[filePath].version,
|
|
41326
|
+
hash: hash.substring(0, 16),
|
|
41327
|
+
remoteHash: remoteHash.substring(0, 16),
|
|
41328
|
+
旧remoteHash: ((_a = existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41329
|
+
remoteHashChanged: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) !== remoteHash,
|
|
41330
|
+
});
|
|
40994
41331
|
return [3 /*break*/, 7];
|
|
40995
41332
|
case 6:
|
|
40996
|
-
error_4 =
|
|
41333
|
+
error_4 = _c.sent();
|
|
40997
41334
|
console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"), error_4);
|
|
40998
41335
|
return [3 /*break*/, 7];
|
|
40999
41336
|
case 7:
|
|
@@ -41001,12 +41338,12 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41001
41338
|
return [3 /*break*/, 2];
|
|
41002
41339
|
case 8: return [3 /*break*/, 11];
|
|
41003
41340
|
case 9:
|
|
41004
|
-
e_6_1 =
|
|
41341
|
+
e_6_1 = _c.sent();
|
|
41005
41342
|
e_6 = { error: e_6_1 };
|
|
41006
41343
|
return [3 /*break*/, 11];
|
|
41007
41344
|
case 10:
|
|
41008
41345
|
try {
|
|
41009
|
-
if (filePaths_1_1 && !filePaths_1_1.done && (
|
|
41346
|
+
if (filePaths_1_1 && !filePaths_1_1.done && (_b = filePaths_1.return)) _b.call(filePaths_1);
|
|
41010
41347
|
}
|
|
41011
41348
|
finally { if (e_6) throw e_6.error; }
|
|
41012
41349
|
return [7 /*endfinally*/];
|
|
@@ -41015,9 +41352,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41015
41352
|
this.updateMetadata();
|
|
41016
41353
|
return [4 /*yield*/, this.saveState()];
|
|
41017
41354
|
case 12:
|
|
41018
|
-
|
|
41355
|
+
_c.sent();
|
|
41019
41356
|
console.log("\u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
|
|
41020
|
-
|
|
41357
|
+
_c.label = 13;
|
|
41021
41358
|
case 13: return [2 /*return*/];
|
|
41022
41359
|
}
|
|
41023
41360
|
});
|
|
@@ -41320,44 +41657,27 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41320
41657
|
return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
41321
41658
|
};
|
|
41322
41659
|
ShadowSpace.prototype.shouldIgnoreFile = function (filePath) {
|
|
41660
|
+
// console.log(`[ShadowSpace] shouldIgnoreFile 检查: "${filePath}"`);
|
|
41323
41661
|
var e_10, _a;
|
|
41324
|
-
console.log("[ShadowSpace] shouldIgnoreFile \u68C0\u67E5: ".concat(filePath), {
|
|
41325
|
-
ignorePatterns: this.config.ignorePatterns,
|
|
41326
|
-
includeExtensions: this.config.includeExtensions,
|
|
41327
|
-
});
|
|
41328
41662
|
// 特殊处理:过滤掉特定的系统文件
|
|
41329
41663
|
var fileName = filePath.split('/').pop() || '';
|
|
41330
41664
|
if (fileName === '.dirty_files.json') {
|
|
41331
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41332
41665
|
return true;
|
|
41333
41666
|
}
|
|
41334
41667
|
if (fileName === 'assets.json') {
|
|
41335
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41336
41668
|
return true;
|
|
41337
41669
|
}
|
|
41338
41670
|
if (fileName === 'project.json') {
|
|
41339
|
-
console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41340
41671
|
return true;
|
|
41341
41672
|
}
|
|
41342
41673
|
if (fileName.endsWith('.doc')) {
|
|
41343
|
-
console.log("[ShadowSpace] .doc\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
|
|
41344
41674
|
return true;
|
|
41345
41675
|
}
|
|
41346
|
-
//
|
|
41676
|
+
// 🔥 目录白名单检查:简化逻辑,允许 src/ 和 docs/ 下的所有文件
|
|
41677
|
+
var isInSrc = filePath.startsWith('src/');
|
|
41347
41678
|
var isInDocs = filePath.startsWith('docs/');
|
|
41348
|
-
var isInSrcPages = filePath.startsWith('src/pages/');
|
|
41349
|
-
var isInSrcModules = filePath.startsWith('src/modules/');
|
|
41350
|
-
var isInSrcTypes = filePath.startsWith('src/types/');
|
|
41351
|
-
var isInSrcUtils = filePath.startsWith('src/utils/');
|
|
41352
|
-
var isInSrcComponents = filePath.startsWith('src/components/');
|
|
41353
41679
|
var isRootConfig = filePath.match(/^[^\/]+\.(json|md|yml|yaml|toml|js|ts|py|go|rs)$/);
|
|
41354
|
-
if (!isInDocs &&
|
|
41355
|
-
!isInSrcPages &&
|
|
41356
|
-
!isInSrcModules &&
|
|
41357
|
-
!isInSrcTypes &&
|
|
41358
|
-
!isInSrcUtils &&
|
|
41359
|
-
!isInSrcComponents &&
|
|
41360
|
-
!isRootConfig) {
|
|
41680
|
+
if (!isInSrc && !isInDocs && !isRootConfig) {
|
|
41361
41681
|
console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u767D\u540D\u5355\u76EE\u5F55\u4E2D: ".concat(filePath));
|
|
41362
41682
|
return true;
|
|
41363
41683
|
}
|
|
@@ -41392,7 +41712,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41392
41712
|
return true;
|
|
41393
41713
|
}
|
|
41394
41714
|
}
|
|
41395
|
-
console.log(
|
|
41715
|
+
// console.log(`[ShadowSpace] 文件通过忽略检查: ${filePath}`);
|
|
41396
41716
|
return false;
|
|
41397
41717
|
};
|
|
41398
41718
|
ShadowSpace.prototype.writeLocalFile = function (filePath, content) {
|
|
@@ -41557,15 +41877,328 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41557
41877
|
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
41558
41878
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
41559
41879
|
};
|
|
41880
|
+
// ==================== 🆕 文件监听功能 ====================
|
|
41881
|
+
/**
|
|
41882
|
+
* 启动文件监听
|
|
41883
|
+
*/
|
|
41884
|
+
ShadowSpace.prototype.startWatching = function () {
|
|
41885
|
+
var _this = this;
|
|
41886
|
+
if (this.isWatching) {
|
|
41887
|
+
console.log('[ShadowSpace] 文件监听已经在运行中');
|
|
41888
|
+
return;
|
|
41889
|
+
}
|
|
41890
|
+
console.log('[ShadowSpace] 启动文件监听...');
|
|
41891
|
+
console.log('[ShadowSpace] 监听目录:', this.config.projectRoot);
|
|
41892
|
+
try {
|
|
41893
|
+
// 🔥 使用轮询模式 + ignored 函数过滤
|
|
41894
|
+
this.watcher = chokidar__default["default"].watch(this.config.projectRoot, {
|
|
41895
|
+
ignored: function (filePath) {
|
|
41896
|
+
var relativePath = path__default["default"].relative(_this.config.projectRoot, filePath);
|
|
41897
|
+
// 忽略根目录本身
|
|
41898
|
+
if (!relativePath || relativePath === '.') {
|
|
41899
|
+
return true;
|
|
41900
|
+
}
|
|
41901
|
+
// 使用白名单过滤
|
|
41902
|
+
return _this.shouldIgnoreFile(relativePath);
|
|
41903
|
+
},
|
|
41904
|
+
persistent: true,
|
|
41905
|
+
ignoreInitial: true,
|
|
41906
|
+
usePolling: true,
|
|
41907
|
+
interval: 2000,
|
|
41908
|
+
binaryInterval: 3000,
|
|
41909
|
+
depth: 99,
|
|
41910
|
+
awaitWriteFinish: {
|
|
41911
|
+
stabilityThreshold: 500,
|
|
41912
|
+
pollInterval: 100,
|
|
41913
|
+
},
|
|
41914
|
+
});
|
|
41915
|
+
console.log('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
|
|
41916
|
+
}
|
|
41917
|
+
catch (error) {
|
|
41918
|
+
console.error('[ShadowSpace] 创建文件监听器失败:', error);
|
|
41919
|
+
return;
|
|
41920
|
+
}
|
|
41921
|
+
this.watcher
|
|
41922
|
+
.on('change', function (filePath) {
|
|
41923
|
+
_this.onFileChanged(filePath);
|
|
41924
|
+
})
|
|
41925
|
+
.on('add', function (filePath) {
|
|
41926
|
+
_this.onFileAdded(filePath);
|
|
41927
|
+
})
|
|
41928
|
+
.on('unlink', function (filePath) {
|
|
41929
|
+
_this.onFileDeleted(filePath);
|
|
41930
|
+
})
|
|
41931
|
+
.on('error', function (error) {
|
|
41932
|
+
console.error('[ShadowSpace] 文件监听错误:', error);
|
|
41933
|
+
})
|
|
41934
|
+
.on('ready', function () {
|
|
41935
|
+
_this.isWatching = true;
|
|
41936
|
+
console.log('[ShadowSpace] 文件监听已启动,正在监听:', _this.config.projectRoot);
|
|
41937
|
+
console.log('[ShadowSpace] 监听配置: 轮询模式 (interval: 2s)');
|
|
41938
|
+
});
|
|
41939
|
+
};
|
|
41940
|
+
/**
|
|
41941
|
+
* 停止文件监听
|
|
41942
|
+
*/
|
|
41943
|
+
ShadowSpace.prototype.stopWatching = function () {
|
|
41944
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41945
|
+
return __generator(this, function (_a) {
|
|
41946
|
+
switch (_a.label) {
|
|
41947
|
+
case 0:
|
|
41948
|
+
if (!this.isWatching || !this.watcher) {
|
|
41949
|
+
console.log('[ShadowSpace] 文件监听未运行');
|
|
41950
|
+
return [2 /*return*/];
|
|
41951
|
+
}
|
|
41952
|
+
console.log('[ShadowSpace] 停止文件监听...');
|
|
41953
|
+
return [4 /*yield*/, this.watcher.close()];
|
|
41954
|
+
case 1:
|
|
41955
|
+
_a.sent();
|
|
41956
|
+
this.watcher = null;
|
|
41957
|
+
this.isWatching = false;
|
|
41958
|
+
console.log('[ShadowSpace] 文件监听已停止');
|
|
41959
|
+
return [2 /*return*/];
|
|
41960
|
+
}
|
|
41961
|
+
});
|
|
41962
|
+
});
|
|
41963
|
+
};
|
|
41964
|
+
/**
|
|
41965
|
+
* 添加变更事件监听器
|
|
41966
|
+
*/
|
|
41967
|
+
ShadowSpace.prototype.addChangeListener = function (listener) {
|
|
41968
|
+
this.changeListeners.add(listener);
|
|
41969
|
+
};
|
|
41970
|
+
/**
|
|
41971
|
+
* 移除变更事件监听器
|
|
41972
|
+
*/
|
|
41973
|
+
ShadowSpace.prototype.removeChangeListener = function (listener) {
|
|
41974
|
+
this.changeListeners.delete(listener);
|
|
41975
|
+
};
|
|
41976
|
+
/**
|
|
41977
|
+
* 触发变更事件
|
|
41978
|
+
*/
|
|
41979
|
+
ShadowSpace.prototype.emitChangeEvent = function (event) {
|
|
41980
|
+
console.log('[ShadowSpace] 触发变更事件:', event);
|
|
41981
|
+
this.changeListeners.forEach(function (listener) {
|
|
41982
|
+
try {
|
|
41983
|
+
listener(event);
|
|
41984
|
+
}
|
|
41985
|
+
catch (error) {
|
|
41986
|
+
console.error('[ShadowSpace] 变更事件监听器执行失败:', error);
|
|
41987
|
+
}
|
|
41988
|
+
});
|
|
41989
|
+
};
|
|
41990
|
+
/**
|
|
41991
|
+
* 文件变更处理
|
|
41992
|
+
*/
|
|
41993
|
+
ShadowSpace.prototype.onFileChanged = function (filePath) {
|
|
41994
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
41995
|
+
var relativePath, shadowEntry, content, hash, stats, error_13;
|
|
41996
|
+
return __generator(this, function (_a) {
|
|
41997
|
+
switch (_a.label) {
|
|
41998
|
+
case 0:
|
|
41999
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42000
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(relativePath));
|
|
42001
|
+
shadowEntry = this.state.files[relativePath];
|
|
42002
|
+
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42003
|
+
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42004
|
+
shadowEntry.remoteModified = false; // 清除标记
|
|
42005
|
+
return [4 /*yield*/, this.saveState()];
|
|
42006
|
+
case 1:
|
|
42007
|
+
_a.sent();
|
|
42008
|
+
return [2 /*return*/];
|
|
42009
|
+
case 2:
|
|
42010
|
+
_a.trys.push([2, 5, , 6]);
|
|
42011
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
|
|
42012
|
+
case 3:
|
|
42013
|
+
content = _a.sent();
|
|
42014
|
+
hash = this.calculateHash(content);
|
|
42015
|
+
return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
|
|
42016
|
+
case 4:
|
|
42017
|
+
stats = _a.sent();
|
|
42018
|
+
// 🔑 推送变更事件
|
|
42019
|
+
this.emitChangeEvent({
|
|
42020
|
+
path: relativePath,
|
|
42021
|
+
action: 'modify',
|
|
42022
|
+
timestamp: Date.now(),
|
|
42023
|
+
source: 'local',
|
|
42024
|
+
hash: hash,
|
|
42025
|
+
size: stats.size,
|
|
42026
|
+
});
|
|
42027
|
+
return [3 /*break*/, 6];
|
|
42028
|
+
case 5:
|
|
42029
|
+
error_13 = _a.sent();
|
|
42030
|
+
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath), error_13);
|
|
42031
|
+
return [3 /*break*/, 6];
|
|
42032
|
+
case 6: return [2 /*return*/];
|
|
42033
|
+
}
|
|
42034
|
+
});
|
|
42035
|
+
});
|
|
42036
|
+
};
|
|
42037
|
+
/**
|
|
42038
|
+
* 文件新增处理
|
|
42039
|
+
*/
|
|
42040
|
+
ShadowSpace.prototype.onFileAdded = function (filePath) {
|
|
42041
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42042
|
+
var relativePath, content, hash, stats, error_14;
|
|
42043
|
+
return __generator(this, function (_a) {
|
|
42044
|
+
switch (_a.label) {
|
|
42045
|
+
case 0:
|
|
42046
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42047
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u65B0\u589E: ".concat(relativePath));
|
|
42048
|
+
_a.label = 1;
|
|
42049
|
+
case 1:
|
|
42050
|
+
_a.trys.push([1, 4, , 5]);
|
|
42051
|
+
return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
|
|
42052
|
+
case 2:
|
|
42053
|
+
content = _a.sent();
|
|
42054
|
+
hash = this.calculateHash(content);
|
|
42055
|
+
return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
|
|
42056
|
+
case 3:
|
|
42057
|
+
stats = _a.sent();
|
|
42058
|
+
// 🔑 推送变更事件
|
|
42059
|
+
this.emitChangeEvent({
|
|
42060
|
+
path: relativePath,
|
|
42061
|
+
action: 'add',
|
|
42062
|
+
timestamp: Date.now(),
|
|
42063
|
+
source: 'local',
|
|
42064
|
+
hash: hash,
|
|
42065
|
+
size: stats.size,
|
|
42066
|
+
});
|
|
42067
|
+
return [3 /*break*/, 5];
|
|
42068
|
+
case 4:
|
|
42069
|
+
error_14 = _a.sent();
|
|
42070
|
+
console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath), error_14);
|
|
42071
|
+
return [3 /*break*/, 5];
|
|
42072
|
+
case 5: return [2 /*return*/];
|
|
42073
|
+
}
|
|
42074
|
+
});
|
|
42075
|
+
});
|
|
42076
|
+
};
|
|
42077
|
+
/**
|
|
42078
|
+
* 文件删除处理
|
|
42079
|
+
*/
|
|
42080
|
+
ShadowSpace.prototype.onFileDeleted = function (filePath) {
|
|
42081
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42082
|
+
var relativePath, shadowEntry;
|
|
42083
|
+
return __generator(this, function (_a) {
|
|
42084
|
+
switch (_a.label) {
|
|
42085
|
+
case 0:
|
|
42086
|
+
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42087
|
+
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5220\u9664: ".concat(relativePath));
|
|
42088
|
+
shadowEntry = this.state.files[relativePath];
|
|
42089
|
+
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42090
|
+
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u5220\u9664\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42091
|
+
shadowEntry.remoteModified = false; // 清除标记
|
|
42092
|
+
return [4 /*yield*/, this.saveState()];
|
|
42093
|
+
case 1:
|
|
42094
|
+
_a.sent();
|
|
42095
|
+
return [2 /*return*/];
|
|
42096
|
+
case 2:
|
|
42097
|
+
// 🔑 推送变更事件
|
|
42098
|
+
this.emitChangeEvent({
|
|
42099
|
+
path: relativePath,
|
|
42100
|
+
action: 'delete',
|
|
42101
|
+
timestamp: Date.now(),
|
|
42102
|
+
source: 'local',
|
|
42103
|
+
});
|
|
42104
|
+
return [2 /*return*/];
|
|
42105
|
+
}
|
|
42106
|
+
});
|
|
42107
|
+
});
|
|
42108
|
+
};
|
|
42109
|
+
/**
|
|
42110
|
+
* 获取监听状态
|
|
42111
|
+
*/
|
|
42112
|
+
ShadowSpace.prototype.isFileWatching = function () {
|
|
42113
|
+
return this.isWatching;
|
|
42114
|
+
};
|
|
41560
42115
|
return ShadowSpace;
|
|
41561
42116
|
}());
|
|
41562
42117
|
|
|
42118
|
+
/**
|
|
42119
|
+
* 变更聚合器
|
|
42120
|
+
* 将短时间内的多个文件变更聚合为一次批量推送,减少网络开销
|
|
42121
|
+
*/
|
|
42122
|
+
var ChangeAggregator = /** @class */ (function () {
|
|
42123
|
+
function ChangeAggregator(spaceId, userId, handler, debounceMs) {
|
|
42124
|
+
if (debounceMs === void 0) { debounceMs = 500; }
|
|
42125
|
+
this.pendingChanges = new Map();
|
|
42126
|
+
this.timer = null;
|
|
42127
|
+
this.spaceId = spaceId;
|
|
42128
|
+
this.userId = userId;
|
|
42129
|
+
this.handler = handler;
|
|
42130
|
+
this.debounceMs = debounceMs;
|
|
42131
|
+
}
|
|
42132
|
+
/**
|
|
42133
|
+
* 添加变更
|
|
42134
|
+
*/
|
|
42135
|
+
ChangeAggregator.prototype.addChange = function (change) {
|
|
42136
|
+
var _this = this;
|
|
42137
|
+
console.log("[ChangeAggregator] \u6DFB\u52A0\u53D8\u66F4: ".concat(change.path, " (").concat(change.action, ")"));
|
|
42138
|
+
// 使用文件路径作为 key,相同文件的多次变更只保留最后一次
|
|
42139
|
+
this.pendingChanges.set(change.path, change);
|
|
42140
|
+
// 防抖:重置定时器
|
|
42141
|
+
if (this.timer) {
|
|
42142
|
+
clearTimeout(this.timer);
|
|
42143
|
+
}
|
|
42144
|
+
this.timer = setTimeout(function () {
|
|
42145
|
+
_this.flush();
|
|
42146
|
+
}, this.debounceMs);
|
|
42147
|
+
};
|
|
42148
|
+
/**
|
|
42149
|
+
* 立即推送所有待处理的变更
|
|
42150
|
+
*/
|
|
42151
|
+
ChangeAggregator.prototype.flush = function () {
|
|
42152
|
+
if (this.pendingChanges.size === 0) {
|
|
42153
|
+
return;
|
|
42154
|
+
}
|
|
42155
|
+
var changes = Array.from(this.pendingChanges.values());
|
|
42156
|
+
this.pendingChanges.clear();
|
|
42157
|
+
if (this.timer) {
|
|
42158
|
+
clearTimeout(this.timer);
|
|
42159
|
+
this.timer = null;
|
|
42160
|
+
}
|
|
42161
|
+
console.log("[ChangeAggregator] \u63A8\u9001\u6279\u91CF\u53D8\u66F4: ".concat(changes.length, " \u4E2A\u6587\u4EF6"));
|
|
42162
|
+
// 调用处理器
|
|
42163
|
+
try {
|
|
42164
|
+
this.handler({
|
|
42165
|
+
spaceId: this.spaceId,
|
|
42166
|
+
userId: this.userId,
|
|
42167
|
+
changes: changes,
|
|
42168
|
+
timestamp: Date.now(),
|
|
42169
|
+
});
|
|
42170
|
+
}
|
|
42171
|
+
catch (error) {
|
|
42172
|
+
console.error('[ChangeAggregator] 批量变更处理失败:', error);
|
|
42173
|
+
}
|
|
42174
|
+
};
|
|
42175
|
+
/**
|
|
42176
|
+
* 清理资源
|
|
42177
|
+
*/
|
|
42178
|
+
ChangeAggregator.prototype.destroy = function () {
|
|
42179
|
+
if (this.timer) {
|
|
42180
|
+
clearTimeout(this.timer);
|
|
42181
|
+
this.timer = null;
|
|
42182
|
+
}
|
|
42183
|
+
this.pendingChanges.clear();
|
|
42184
|
+
};
|
|
42185
|
+
/**
|
|
42186
|
+
* 获取待处理变更数量
|
|
42187
|
+
*/
|
|
42188
|
+
ChangeAggregator.prototype.getPendingCount = function () {
|
|
42189
|
+
return this.pendingChanges.size;
|
|
42190
|
+
};
|
|
42191
|
+
return ChangeAggregator;
|
|
42192
|
+
}());
|
|
42193
|
+
|
|
41563
42194
|
/**
|
|
41564
42195
|
* 影子空间WebSocket指令处理器
|
|
41565
42196
|
*/
|
|
41566
42197
|
var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
41567
42198
|
function ShadowSpaceCommandHandler(shadowSpace, socketStore) {
|
|
41568
42199
|
this.currentUserId = null;
|
|
42200
|
+
// 🆕 变更聚合器
|
|
42201
|
+
this.changeAggregator = null;
|
|
41569
42202
|
this.shadowSpace = shadowSpace;
|
|
41570
42203
|
this.socketStore = socketStore;
|
|
41571
42204
|
}
|
|
@@ -41580,11 +42213,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41580
42213
|
* 处理WebSocket消息
|
|
41581
42214
|
*/
|
|
41582
42215
|
ShadowSpaceCommandHandler.prototype.handleMessage = function (data) {
|
|
41583
|
-
var _a, _b, _c, _d, _e, _f;
|
|
42216
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
41584
42217
|
return __awaiter(this, void 0, void 0, function () {
|
|
41585
|
-
var action, messageId, message, spaceInfo, requestSpaceId, result,
|
|
41586
|
-
return __generator(this, function (
|
|
41587
|
-
switch (
|
|
42218
|
+
var action, messageId, message, spaceInfo, requestSpaceId, result, _h, error_1, errorMessage;
|
|
42219
|
+
return __generator(this, function (_j) {
|
|
42220
|
+
switch (_j.label) {
|
|
41588
42221
|
case 0:
|
|
41589
42222
|
action = data.action, messageId = data.messageId, message = data.message;
|
|
41590
42223
|
console.log("[ShadowSpaceCommandHandler] \u6536\u5230\u6D88\u606F: ".concat(action), {
|
|
@@ -41610,12 +42243,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41610
42243
|
// 不发送响应,让其他CLI实例处理
|
|
41611
42244
|
return [2 /*return*/];
|
|
41612
42245
|
}
|
|
41613
|
-
|
|
42246
|
+
_j.label = 1;
|
|
41614
42247
|
case 1:
|
|
41615
|
-
|
|
42248
|
+
_j.trys.push([1, 28, , 29]);
|
|
41616
42249
|
result = void 0;
|
|
41617
|
-
|
|
41618
|
-
switch (
|
|
42250
|
+
_h = action;
|
|
42251
|
+
switch (_h) {
|
|
41619
42252
|
case 'shadow-space-get-changes': return [3 /*break*/, 2];
|
|
41620
42253
|
case 'shadow-space-get-file-content': return [3 /*break*/, 4];
|
|
41621
42254
|
case 'shadow-space-get-files-content': return [3 /*break*/, 6];
|
|
@@ -41627,12 +42260,13 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41627
42260
|
case 'shadow-space-mark-remote-modified': return [3 /*break*/, 18];
|
|
41628
42261
|
case 'shadow-space-clear-remote-flags': return [3 /*break*/, 20];
|
|
41629
42262
|
case 'shadow-space-detect-changes': return [3 /*break*/, 22];
|
|
42263
|
+
case 'shadow-space-discard-changes': return [3 /*break*/, 24];
|
|
41630
42264
|
}
|
|
41631
|
-
return [3 /*break*/,
|
|
42265
|
+
return [3 /*break*/, 26];
|
|
41632
42266
|
case 2: return [4 /*yield*/, this.getChanges()];
|
|
41633
42267
|
case 3:
|
|
41634
|
-
result =
|
|
41635
|
-
return [3 /*break*/,
|
|
42268
|
+
result = _j.sent();
|
|
42269
|
+
return [3 /*break*/, 27];
|
|
41636
42270
|
case 4:
|
|
41637
42271
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message:', JSON.stringify(message, null, 2));
|
|
41638
42272
|
console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message.path:', message.path);
|
|
@@ -41640,57 +42274,61 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41640
42274
|
return [4 /*yield*/, this.getFileContent(((_c = message.message) === null || _c === void 0 ? void 0 : _c.path) || message.path)];
|
|
41641
42275
|
case 5:
|
|
41642
42276
|
// 🆕 修复:路径在 message.message.path 中
|
|
41643
|
-
result =
|
|
41644
|
-
return [3 /*break*/,
|
|
42277
|
+
result = _j.sent();
|
|
42278
|
+
return [3 /*break*/, 27];
|
|
41645
42279
|
case 6: return [4 /*yield*/, this.getFilesContent(((_d = message.message) === null || _d === void 0 ? void 0 : _d.paths) || message.paths)];
|
|
41646
42280
|
case 7:
|
|
41647
42281
|
// 🆕 修复:路径在 message.message.paths 中
|
|
41648
|
-
result =
|
|
41649
|
-
return [3 /*break*/,
|
|
42282
|
+
result = _j.sent();
|
|
42283
|
+
return [3 /*break*/, 27];
|
|
41650
42284
|
case 8: return [4 /*yield*/, this.applyChanges(message.changes)];
|
|
41651
42285
|
case 9:
|
|
41652
|
-
result =
|
|
41653
|
-
return [3 /*break*/,
|
|
42286
|
+
result = _j.sent();
|
|
42287
|
+
return [3 /*break*/, 27];
|
|
41654
42288
|
case 10: return [4 /*yield*/, this.resetShadowSpace()];
|
|
41655
42289
|
case 11:
|
|
41656
|
-
result =
|
|
41657
|
-
return [3 /*break*/,
|
|
42290
|
+
result = _j.sent();
|
|
42291
|
+
return [3 /*break*/, 27];
|
|
41658
42292
|
case 12: return [4 /*yield*/, this.getSpaceInfo()];
|
|
41659
42293
|
case 13:
|
|
41660
|
-
result =
|
|
41661
|
-
return [3 /*break*/,
|
|
42294
|
+
result = _j.sent();
|
|
42295
|
+
return [3 /*break*/, 27];
|
|
41662
42296
|
case 14: return [4 /*yield*/, this.syncFromEditor(message.message.files)];
|
|
41663
42297
|
case 15:
|
|
41664
|
-
result =
|
|
41665
|
-
return [3 /*break*/,
|
|
42298
|
+
result = _j.sent();
|
|
42299
|
+
return [3 /*break*/, 27];
|
|
41666
42300
|
case 16: return [4 /*yield*/, this.deleteFile(message.filePath)];
|
|
41667
42301
|
case 17:
|
|
41668
|
-
result =
|
|
41669
|
-
return [3 /*break*/,
|
|
42302
|
+
result = _j.sent();
|
|
42303
|
+
return [3 /*break*/, 27];
|
|
41670
42304
|
case 18: return [4 /*yield*/, this.markRemoteModified(message.filePaths)];
|
|
41671
42305
|
case 19:
|
|
41672
|
-
result =
|
|
41673
|
-
return [3 /*break*/,
|
|
42306
|
+
result = _j.sent();
|
|
42307
|
+
return [3 /*break*/, 27];
|
|
41674
42308
|
case 20: return [4 /*yield*/, this.clearRemoteFlags(message.filePaths)];
|
|
41675
42309
|
case 21:
|
|
41676
|
-
result =
|
|
41677
|
-
return [3 /*break*/,
|
|
42310
|
+
result = _j.sent();
|
|
42311
|
+
return [3 /*break*/, 27];
|
|
41678
42312
|
case 22: return [4 /*yield*/, this.detectEditorChanges(((_e = message.message) === null || _e === void 0 ? void 0 : _e.spaceId) || message.spaceId, ((_f = message.message) === null || _f === void 0 ? void 0 : _f.files) || message.files)];
|
|
41679
42313
|
case 23:
|
|
41680
|
-
result =
|
|
41681
|
-
return [3 /*break*/,
|
|
41682
|
-
case 24:
|
|
42314
|
+
result = _j.sent();
|
|
42315
|
+
return [3 /*break*/, 27];
|
|
42316
|
+
case 24: return [4 /*yield*/, this.discardChanges(((_g = message.message) === null || _g === void 0 ? void 0 : _g.filePaths) || message.filePaths)];
|
|
41683
42317
|
case 25:
|
|
42318
|
+
result = _j.sent();
|
|
42319
|
+
return [3 /*break*/, 27];
|
|
42320
|
+
case 26: throw new Error("Unknown shadow space action: ".concat(action));
|
|
42321
|
+
case 27:
|
|
41684
42322
|
// 发送成功响应
|
|
41685
42323
|
this.sendResponse(action, messageId, true, result);
|
|
41686
|
-
return [3 /*break*/,
|
|
41687
|
-
case
|
|
41688
|
-
error_1 =
|
|
42324
|
+
return [3 /*break*/, 29];
|
|
42325
|
+
case 28:
|
|
42326
|
+
error_1 = _j.sent();
|
|
41689
42327
|
errorMessage = error_1 instanceof Error ? error_1.message : String(error_1);
|
|
41690
42328
|
console.error("Shadow space command error [".concat(action, "]:"), errorMessage);
|
|
41691
42329
|
this.sendResponse(action, messageId, false, undefined, errorMessage);
|
|
41692
|
-
return [3 /*break*/,
|
|
41693
|
-
case
|
|
42330
|
+
return [3 /*break*/, 29];
|
|
42331
|
+
case 29: return [2 /*return*/];
|
|
41694
42332
|
}
|
|
41695
42333
|
});
|
|
41696
42334
|
});
|
|
@@ -41959,9 +42597,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41959
42597
|
return __awaiter(this, void 0, void 0, function () {
|
|
41960
42598
|
var info;
|
|
41961
42599
|
return __generator(this, function (_a) {
|
|
41962
|
-
console.log('[ShadowSpace] 获取空间信息...');
|
|
41963
42600
|
info = this.shadowSpace.getSpaceInfo();
|
|
41964
|
-
console.log(
|
|
42601
|
+
// console.log(
|
|
42602
|
+
// `[ShadowSpace] 空间信息: ${info.fileCount} 个文件, ${info.totalSize}`
|
|
42603
|
+
// );
|
|
41965
42604
|
return [2 /*return*/, info];
|
|
41966
42605
|
});
|
|
41967
42606
|
});
|
|
@@ -41971,14 +42610,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41971
42610
|
*/
|
|
41972
42611
|
ShadowSpaceCommandHandler.prototype.syncFromEditor = function (files) {
|
|
41973
42612
|
return __awaiter(this, void 0, void 0, function () {
|
|
41974
|
-
var
|
|
42613
|
+
var result;
|
|
41975
42614
|
return __generator(this, function (_a) {
|
|
41976
42615
|
switch (_a.label) {
|
|
41977
42616
|
case 0:
|
|
41978
42617
|
console.log('[ShadowSpace] syncFromEditor 接收到的参数:', {
|
|
41979
42618
|
filesType: typeof files,
|
|
41980
42619
|
isArray: Array.isArray(files),
|
|
41981
|
-
filesValue: files,
|
|
42620
|
+
// filesValue: files,
|
|
41982
42621
|
filesLength: files === null || files === void 0 ? void 0 : files.length,
|
|
41983
42622
|
});
|
|
41984
42623
|
if (!Array.isArray(files)) {
|
|
@@ -41988,11 +42627,6 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
41988
42627
|
return [4 /*yield*/, this.shadowSpace.syncFromEditor(files)];
|
|
41989
42628
|
case 1:
|
|
41990
42629
|
_a.sent();
|
|
41991
|
-
filePaths = files.map(function (f) { return f.path; });
|
|
41992
|
-
return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
|
|
41993
|
-
case 2:
|
|
41994
|
-
_a.sent();
|
|
41995
|
-
console.log("[ShadowSpace] \u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
|
|
41996
42630
|
result = {
|
|
41997
42631
|
message: 'Sync from editor completed',
|
|
41998
42632
|
fileCount: files.length,
|
|
@@ -42128,10 +42762,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42128
42762
|
var actualMessage = (data === null || data === void 0 ? void 0 : data.message) || data;
|
|
42129
42763
|
var actualMessageId = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.messageId;
|
|
42130
42764
|
var actualAction = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.action;
|
|
42131
|
-
console.log(
|
|
42765
|
+
// console.log(
|
|
42766
|
+
// `[ShadowSpace] 检查响应: action=${actualAction}, messageId=${actualMessageId}, 期望=${messageId}`
|
|
42767
|
+
// );
|
|
42132
42768
|
if (actualMessageId === messageId &&
|
|
42133
42769
|
actualAction === 'editor-state-response') {
|
|
42134
|
-
console.log(
|
|
42770
|
+
// console.log(`[ShadowSpace] 收到编辑器状态响应`);
|
|
42135
42771
|
clearTimeout(timeout);
|
|
42136
42772
|
if ((_a = actualMessage.message) === null || _a === void 0 ? void 0 : _a.success) {
|
|
42137
42773
|
resolve(actualMessage.message.data);
|
|
@@ -42149,7 +42785,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42149
42785
|
originalOnMessage(data);
|
|
42150
42786
|
}
|
|
42151
42787
|
};
|
|
42152
|
-
console.log(
|
|
42788
|
+
// console.log(
|
|
42789
|
+
// `[ShadowSpace] 临时监听器已设置,发送编辑器状态请求: ${messageId}`
|
|
42790
|
+
// );
|
|
42153
42791
|
// 发送请求
|
|
42154
42792
|
_this.socketStore.sendMessage({
|
|
42155
42793
|
action: 'request-editor-state',
|
|
@@ -42160,7 +42798,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42160
42798
|
});
|
|
42161
42799
|
// 恢复原始处理器(在超时时间之后)
|
|
42162
42800
|
setTimeout(function () {
|
|
42163
|
-
console.log(
|
|
42801
|
+
// console.log(`[ShadowSpace] 恢复原始监听器: ${messageId}`);
|
|
42164
42802
|
_this.socketStore.onmsg = originalOnMessage;
|
|
42165
42803
|
}, 31000);
|
|
42166
42804
|
})];
|
|
@@ -42172,23 +42810,20 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42172
42810
|
*/
|
|
42173
42811
|
ShadowSpaceCommandHandler.prototype.detectEditorChanges = function (spaceId, editorSnapshots) {
|
|
42174
42812
|
return __awaiter(this, void 0, void 0, function () {
|
|
42175
|
-
var safeEditorSnapshots, spaceSnapshots,
|
|
42813
|
+
var safeEditorSnapshots, spaceSnapshots, changes, summary, error_2;
|
|
42176
42814
|
return __generator(this, function (_a) {
|
|
42177
42815
|
switch (_a.label) {
|
|
42178
42816
|
case 0:
|
|
42179
42817
|
_a.trys.push([0, 3, , 4]);
|
|
42180
|
-
console.log('editorSnapshots: ', editorSnapshots);
|
|
42181
42818
|
safeEditorSnapshots = Array.isArray(editorSnapshots)
|
|
42182
42819
|
? editorSnapshots
|
|
42183
42820
|
: [];
|
|
42184
|
-
console.log("[ShadowSpace] \u5F00\u59CB\u68C0\u6D4B\u53D8\u66F4: \u7A7A\u95F4=".concat(spaceId, ", \u7F16\u8F91\u5668\u6587\u4EF6=").concat(safeEditorSnapshots.length, "\u4E2A"));
|
|
42185
42821
|
return [4 /*yield*/, this.shadowSpace.getSpaceSnapshots(spaceId)];
|
|
42186
42822
|
case 1:
|
|
42187
42823
|
spaceSnapshots = _a.sent();
|
|
42188
|
-
|
|
42824
|
+
Array.isArray(spaceSnapshots)
|
|
42189
42825
|
? spaceSnapshots.length
|
|
42190
42826
|
: 0;
|
|
42191
|
-
console.log("[ShadowSpace] \u7A7A\u95F4\u5FEB\u7167: ".concat(snapshotCount, "\u4E2A\u6587\u4EF6"));
|
|
42192
42827
|
return [4 /*yield*/, this.compareSnapshots(safeEditorSnapshots, spaceSnapshots)];
|
|
42193
42828
|
case 2:
|
|
42194
42829
|
changes = _a.sent();
|
|
@@ -42197,7 +42832,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42197
42832
|
needPush: changes.filter(function (c) { return c.side === 'editor'; }).length,
|
|
42198
42833
|
needPull: changes.filter(function (c) { return c.side === 'space'; }).length,
|
|
42199
42834
|
};
|
|
42200
|
-
console.log(
|
|
42835
|
+
// console.log(
|
|
42836
|
+
// `[ShadowSpace] 变更检测完成: 总计${summary.total}个变更, 需推送${summary.needPush}个, 需拉取${summary.needPull}个`
|
|
42837
|
+
// );
|
|
42201
42838
|
return [2 /*return*/, {
|
|
42202
42839
|
success: true,
|
|
42203
42840
|
data: {
|
|
@@ -42224,10 +42861,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42224
42861
|
* 比对编辑器和空间快照
|
|
42225
42862
|
*/
|
|
42226
42863
|
ShadowSpaceCommandHandler.prototype.compareSnapshots = function (editorSnapshots, spaceSnapshots) {
|
|
42864
|
+
var _a, _b, _c;
|
|
42227
42865
|
return __awaiter(this, void 0, void 0, function () {
|
|
42228
|
-
var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1,
|
|
42229
|
-
var e_2,
|
|
42230
|
-
return __generator(this, function (
|
|
42866
|
+
var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _d, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _e, path, spaceFile, editorFile;
|
|
42867
|
+
var e_2, _f, e_3, _g;
|
|
42868
|
+
return __generator(this, function (_h) {
|
|
42231
42869
|
changes = [];
|
|
42232
42870
|
safeEditorSnapshots = Array.isArray(editorSnapshots)
|
|
42233
42871
|
? editorSnapshots
|
|
@@ -42240,7 +42878,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42240
42878
|
try {
|
|
42241
42879
|
// 检测编辑器的变更(新增、修改)
|
|
42242
42880
|
for (editorMap_1 = __values(editorMap), editorMap_1_1 = editorMap_1.next(); !editorMap_1_1.done; editorMap_1_1 = editorMap_1.next()) {
|
|
42243
|
-
|
|
42881
|
+
_d = __read(editorMap_1_1.value, 2), path = _d[0], editorFile = _d[1];
|
|
42244
42882
|
spaceFile = spaceMap.get(path);
|
|
42245
42883
|
if (!spaceFile) {
|
|
42246
42884
|
// 编辑器新增的文件
|
|
@@ -42257,9 +42895,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42257
42895
|
else if (editorFile.hash !== spaceFile.remoteHash) {
|
|
42258
42896
|
// 编辑器修改的文件(基于云端哈希比对)
|
|
42259
42897
|
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7F16\u8F91\u5668\u4FEE\u6539: ".concat(path), {
|
|
42260
|
-
editorHash: editorFile.hash,
|
|
42261
|
-
spaceRemoteHash: spaceFile.remoteHash,
|
|
42262
|
-
spaceLocalHash: spaceFile.hash,
|
|
42898
|
+
editorHash: (_a = editorFile.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
|
|
42899
|
+
spaceRemoteHash: (_b = spaceFile.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
|
|
42900
|
+
spaceLocalHash: (_c = spaceFile.hash) === null || _c === void 0 ? void 0 : _c.substring(0, 16),
|
|
42901
|
+
editorHashFull: editorFile.hash,
|
|
42902
|
+
spaceRemoteHashFull: spaceFile.remoteHash,
|
|
42263
42903
|
});
|
|
42264
42904
|
changes.push({
|
|
42265
42905
|
action: 'modify',
|
|
@@ -42276,14 +42916,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42276
42916
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
42277
42917
|
finally {
|
|
42278
42918
|
try {
|
|
42279
|
-
if (editorMap_1_1 && !editorMap_1_1.done && (
|
|
42919
|
+
if (editorMap_1_1 && !editorMap_1_1.done && (_f = editorMap_1.return)) _f.call(editorMap_1);
|
|
42280
42920
|
}
|
|
42281
42921
|
finally { if (e_2) throw e_2.error; }
|
|
42282
42922
|
}
|
|
42283
42923
|
try {
|
|
42284
42924
|
// 检测空间的变更(删除、空间独有的修改)
|
|
42285
42925
|
for (spaceMap_1 = __values(spaceMap), spaceMap_1_1 = spaceMap_1.next(); !spaceMap_1_1.done; spaceMap_1_1 = spaceMap_1.next()) {
|
|
42286
|
-
|
|
42926
|
+
_e = __read(spaceMap_1_1.value, 2), path = _e[0], spaceFile = _e[1];
|
|
42287
42927
|
editorFile = editorMap.get(path);
|
|
42288
42928
|
if (!editorFile) {
|
|
42289
42929
|
// 空间独有的文件(编辑器已删除)
|
|
@@ -42303,7 +42943,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42303
42943
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
42304
42944
|
finally {
|
|
42305
42945
|
try {
|
|
42306
|
-
if (spaceMap_1_1 && !spaceMap_1_1.done && (
|
|
42946
|
+
if (spaceMap_1_1 && !spaceMap_1_1.done && (_g = spaceMap_1.return)) _g.call(spaceMap_1);
|
|
42307
42947
|
}
|
|
42308
42948
|
finally { if (e_3) throw e_3.error; }
|
|
42309
42949
|
}
|
|
@@ -42311,12 +42951,132 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42311
42951
|
});
|
|
42312
42952
|
});
|
|
42313
42953
|
};
|
|
42954
|
+
/**
|
|
42955
|
+
* 放弃本地变更
|
|
42956
|
+
* 将影子空间的状态更新为编辑器的版本,不再提示这些文件有变更
|
|
42957
|
+
*/
|
|
42958
|
+
ShadowSpaceCommandHandler.prototype.discardChanges = function (filePaths) {
|
|
42959
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42960
|
+
var editorState, editorFiles;
|
|
42961
|
+
return __generator(this, function (_a) {
|
|
42962
|
+
switch (_a.label) {
|
|
42963
|
+
case 0:
|
|
42964
|
+
if (!filePaths || filePaths.length === 0) {
|
|
42965
|
+
throw new Error('No file paths provided');
|
|
42966
|
+
}
|
|
42967
|
+
console.log("[ShadowSpace] \u653E\u5F03\u53D8\u66F4: ".concat(filePaths.length, " \u4E2A\u6587\u4EF6"));
|
|
42968
|
+
return [4 /*yield*/, this.requestEditorState()];
|
|
42969
|
+
case 1:
|
|
42970
|
+
editorState = _a.sent();
|
|
42971
|
+
if (!editorState || !editorState.files) {
|
|
42972
|
+
throw new Error('Failed to get editor state');
|
|
42973
|
+
}
|
|
42974
|
+
editorFiles = editorState.files.filter(function (f) {
|
|
42975
|
+
return filePaths.includes(f.path);
|
|
42976
|
+
});
|
|
42977
|
+
console.log("[ShadowSpace] \u4ECE\u7F16\u8F91\u5668\u83B7\u53D6\u5230 ".concat(editorFiles.length, " \u4E2A\u6587\u4EF6"));
|
|
42978
|
+
if (editorFiles.length === 0) {
|
|
42979
|
+
throw new Error('No matching files found in editor');
|
|
42980
|
+
}
|
|
42981
|
+
// 同步到影子空间(覆盖本地变更)
|
|
42982
|
+
return [4 /*yield*/, this.shadowSpace.syncFromEditor(editorFiles)];
|
|
42983
|
+
case 2:
|
|
42984
|
+
// 同步到影子空间(覆盖本地变更)
|
|
42985
|
+
_a.sent();
|
|
42986
|
+
// 标记为远程修改,避免再次检测
|
|
42987
|
+
return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
|
|
42988
|
+
case 3:
|
|
42989
|
+
// 标记为远程修改,避免再次检测
|
|
42990
|
+
_a.sent();
|
|
42991
|
+
console.log("[ShadowSpace] \u6210\u529F\u653E\u5F03 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u7684\u53D8\u66F4"));
|
|
42992
|
+
return [2 /*return*/, {
|
|
42993
|
+
message: 'Changes discarded successfully',
|
|
42994
|
+
fileCount: filePaths.length,
|
|
42995
|
+
discardedFiles: filePaths,
|
|
42996
|
+
timestamp: Date.now(),
|
|
42997
|
+
}];
|
|
42998
|
+
}
|
|
42999
|
+
});
|
|
43000
|
+
});
|
|
43001
|
+
};
|
|
42314
43002
|
/**
|
|
42315
43003
|
* 生成消息ID
|
|
42316
43004
|
*/
|
|
42317
43005
|
ShadowSpaceCommandHandler.prototype.generateMessageId = function () {
|
|
42318
43006
|
return "msg_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
42319
43007
|
};
|
|
43008
|
+
// ==================== 🆕 文件监听功能 ====================
|
|
43009
|
+
/**
|
|
43010
|
+
* 启动文件监听
|
|
43011
|
+
*/
|
|
43012
|
+
ShadowSpaceCommandHandler.prototype.startFileWatching = function () {
|
|
43013
|
+
var _this = this;
|
|
43014
|
+
if (!this.currentUserId) {
|
|
43015
|
+
console.error('[ShadowSpace] 无法启动文件监听:用户ID未设置');
|
|
43016
|
+
return;
|
|
43017
|
+
}
|
|
43018
|
+
var spaceInfo = this.shadowSpace.getSpaceInfo();
|
|
43019
|
+
console.log('[ShadowSpace] 启动文件监听和变更聚合...');
|
|
43020
|
+
// 创建变更聚合器
|
|
43021
|
+
this.changeAggregator = new ChangeAggregator(spaceInfo.spaceId, spaceInfo.userId, function (event) { return _this.handleBatchChange(event); }, 500 // 500ms 防抖
|
|
43022
|
+
);
|
|
43023
|
+
// 添加变更监听器
|
|
43024
|
+
this.shadowSpace.addChangeListener(function (change) {
|
|
43025
|
+
if (_this.changeAggregator) {
|
|
43026
|
+
_this.changeAggregator.addChange(change);
|
|
43027
|
+
}
|
|
43028
|
+
});
|
|
43029
|
+
// 启动文件监听
|
|
43030
|
+
this.shadowSpace.startWatching();
|
|
43031
|
+
console.log('[ShadowSpace] 文件监听和变更聚合已启动');
|
|
43032
|
+
};
|
|
43033
|
+
/**
|
|
43034
|
+
* 停止文件监听
|
|
43035
|
+
*/
|
|
43036
|
+
ShadowSpaceCommandHandler.prototype.stopFileWatching = function () {
|
|
43037
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
43038
|
+
return __generator(this, function (_a) {
|
|
43039
|
+
switch (_a.label) {
|
|
43040
|
+
case 0:
|
|
43041
|
+
console.log('[ShadowSpace] 停止文件监听和变更聚合...');
|
|
43042
|
+
// 停止文件监听
|
|
43043
|
+
return [4 /*yield*/, this.shadowSpace.stopWatching()];
|
|
43044
|
+
case 1:
|
|
43045
|
+
// 停止文件监听
|
|
43046
|
+
_a.sent();
|
|
43047
|
+
// 销毁变更聚合器
|
|
43048
|
+
if (this.changeAggregator) {
|
|
43049
|
+
this.changeAggregator.destroy();
|
|
43050
|
+
this.changeAggregator = null;
|
|
43051
|
+
}
|
|
43052
|
+
console.log('[ShadowSpace] 文件监听和变更聚合已停止');
|
|
43053
|
+
return [2 /*return*/];
|
|
43054
|
+
}
|
|
43055
|
+
});
|
|
43056
|
+
});
|
|
43057
|
+
};
|
|
43058
|
+
/**
|
|
43059
|
+
* 处理批量变更
|
|
43060
|
+
*/
|
|
43061
|
+
ShadowSpaceCommandHandler.prototype.handleBatchChange = function (event) {
|
|
43062
|
+
console.log("[ShadowSpace] \u63A8\u9001\u6279\u91CF\u53D8\u66F4\u4E8B\u4EF6: ".concat(event.changes.length, " \u4E2A\u6587\u4EF6"));
|
|
43063
|
+
// 推送批量变更事件到编辑器
|
|
43064
|
+
this.socketStore.sendMessage({
|
|
43065
|
+
action: 'shadow-space-batch-changed',
|
|
43066
|
+
message: {
|
|
43067
|
+
spaceId: event.spaceId,
|
|
43068
|
+
userId: event.userId,
|
|
43069
|
+
changes: event.changes,
|
|
43070
|
+
timestamp: event.timestamp,
|
|
43071
|
+
},
|
|
43072
|
+
});
|
|
43073
|
+
};
|
|
43074
|
+
/**
|
|
43075
|
+
* 获取监听状态
|
|
43076
|
+
*/
|
|
43077
|
+
ShadowSpaceCommandHandler.prototype.isWatching = function () {
|
|
43078
|
+
return this.shadowSpace.isFileWatching();
|
|
43079
|
+
};
|
|
42320
43080
|
return ShadowSpaceCommandHandler;
|
|
42321
43081
|
}());
|
|
42322
43082
|
|
|
@@ -42456,11 +43216,31 @@ function startConnecting(options) {
|
|
|
42456
43216
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u5904\u7406\u5668\u5DF2\u521D\u59CB\u5316\uFF0C\u57FA\u7840\u76EE\u5F55: ").concat(fileOperationConfig.baseDir));
|
|
42457
43217
|
shadowSpace_1 = null;
|
|
42458
43218
|
shadowSpaceHandler_1 = null;
|
|
42459
|
-
cleanup_1 = function () {
|
|
42460
|
-
|
|
42461
|
-
|
|
42462
|
-
|
|
42463
|
-
|
|
43219
|
+
cleanup_1 = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
43220
|
+
return __generator(this, function (_a) {
|
|
43221
|
+
switch (_a.label) {
|
|
43222
|
+
case 0:
|
|
43223
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6B63\u5728\u6E05\u7406..."));
|
|
43224
|
+
if (!shadowSpaceHandler_1) return [3 /*break*/, 4];
|
|
43225
|
+
_a.label = 1;
|
|
43226
|
+
case 1:
|
|
43227
|
+
_a.trys.push([1, 3, , 4]);
|
|
43228
|
+
return [4 /*yield*/, shadowSpaceHandler_1.stopFileWatching()];
|
|
43229
|
+
case 2:
|
|
43230
|
+
_a.sent();
|
|
43231
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u505C\u6B62"));
|
|
43232
|
+
return [3 /*break*/, 4];
|
|
43233
|
+
case 3:
|
|
43234
|
+
_a.sent();
|
|
43235
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u505C\u6B62\u6587\u4EF6\u76D1\u542C\u5931\u8D25:"));
|
|
43236
|
+
return [3 /*break*/, 4];
|
|
43237
|
+
case 4:
|
|
43238
|
+
removePidFile();
|
|
43239
|
+
process.exit(0);
|
|
43240
|
+
return [2 /*return*/];
|
|
43241
|
+
}
|
|
43242
|
+
});
|
|
43243
|
+
}); };
|
|
42464
43244
|
process.on('SIGINT', cleanup_1);
|
|
42465
43245
|
process.on('SIGTERM', cleanup_1);
|
|
42466
43246
|
process.on('uncaughtException', function (error) {
|
|
@@ -42492,6 +43272,9 @@ function startConnecting(options) {
|
|
|
42492
43272
|
// 初始化影子空间指令处理器
|
|
42493
43273
|
shadowSpaceHandler_1 = new ShadowSpaceCommandHandler(shadowSpace_1, currentSocket);
|
|
42494
43274
|
shadowSpaceHandler_1.setCurrentUserId(account);
|
|
43275
|
+
// 🆕 启动文件监听
|
|
43276
|
+
shadowSpaceHandler_1.startFileWatching();
|
|
43277
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u542F\u52A8"));
|
|
42495
43278
|
return [3 /*break*/, 3];
|
|
42496
43279
|
case 2:
|
|
42497
43280
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u8DF3\u8FC7\u5F71\u5B50\u7A7A\u95F4\u521D\u59CB\u5316\uFF08\u672A\u542F\u7528workspace\u6A21\u5F0F\uFF09"));
|
|
@@ -42517,13 +43300,11 @@ function startConnecting(options) {
|
|
|
42517
43300
|
}, 5000);
|
|
42518
43301
|
},
|
|
42519
43302
|
onmsg: function (data) { return __awaiter(_this, void 0, void 0, function () {
|
|
42520
|
-
var action, message, extracted, normalizedData, result, _a,
|
|
43303
|
+
var action, message, extracted, normalizedData, result, _a, error_3, error_4, userId, current, cwd, type, change, filePath;
|
|
42521
43304
|
var _b, _c;
|
|
42522
43305
|
return __generator(this, function (_d) {
|
|
42523
43306
|
switch (_d.label) {
|
|
42524
43307
|
case 0:
|
|
42525
|
-
// if (DEV_MODE) {
|
|
42526
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6536\u5230\u6D88\u606F: ").concat(JSON.stringify(data)));
|
|
42527
43308
|
if (data === null || data === void 0 ? void 0 : data.action) {
|
|
42528
43309
|
// 直接格式
|
|
42529
43310
|
action = data.action;
|
|
@@ -42596,8 +43377,8 @@ function startConnecting(options) {
|
|
|
42596
43377
|
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u5DF2\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ").concat(message.message.path));
|
|
42597
43378
|
return [3 /*break*/, 11];
|
|
42598
43379
|
case 10:
|
|
42599
|
-
|
|
42600
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(
|
|
43380
|
+
error_3 = _d.sent();
|
|
43381
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(error_3));
|
|
42601
43382
|
return [3 /*break*/, 11];
|
|
42602
43383
|
case 11: return [3 /*break*/, 23];
|
|
42603
43384
|
case 12: return [4 /*yield*/, fileHandler_1.readFile(message.path, message.encoding)];
|
|
@@ -42639,13 +43420,13 @@ function startConnecting(options) {
|
|
|
42639
43420
|
});
|
|
42640
43421
|
return [3 /*break*/, 25];
|
|
42641
43422
|
case 24:
|
|
42642
|
-
|
|
42643
|
-
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(
|
|
43423
|
+
error_4 = _d.sent();
|
|
43424
|
+
log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(error_4));
|
|
42644
43425
|
currentSocket === null || currentSocket === void 0 ? void 0 : currentSocket.sendMessage({
|
|
42645
43426
|
action: "".concat(action, "-response"),
|
|
42646
43427
|
message: {
|
|
42647
43428
|
success: false,
|
|
42648
|
-
error:
|
|
43429
|
+
error: error_4 instanceof Error ? error_4.message : String(error_4),
|
|
42649
43430
|
},
|
|
42650
43431
|
});
|
|
42651
43432
|
return [3 /*break*/, 25];
|
|
@@ -48004,6 +48785,1155 @@ function cleanupOldLogs(logDir, debugDir) {
|
|
|
48004
48785
|
});
|
|
48005
48786
|
}
|
|
48006
48787
|
|
|
48788
|
+
/**
|
|
48789
|
+
* AI 工具配置
|
|
48790
|
+
*/
|
|
48791
|
+
var AI_TOOLS = [
|
|
48792
|
+
{
|
|
48793
|
+
name: '🤖 Claude Code (Anthropic 官方)',
|
|
48794
|
+
value: 'claude-code',
|
|
48795
|
+
description: '支持 Hooks 和 TSX 检查器',
|
|
48796
|
+
},
|
|
48797
|
+
{
|
|
48798
|
+
name: '🎯 Cursor (AI-first IDE)',
|
|
48799
|
+
value: 'cursor',
|
|
48800
|
+
description: '支持 Rules 和自定义指令',
|
|
48801
|
+
},
|
|
48802
|
+
{
|
|
48803
|
+
name: '🌊 Windsurf (Codeium)',
|
|
48804
|
+
value: 'windsurf',
|
|
48805
|
+
description: '支持 Cascade 配置',
|
|
48806
|
+
},
|
|
48807
|
+
{
|
|
48808
|
+
name: '☁️ 阿里云 Coder',
|
|
48809
|
+
value: 'coder',
|
|
48810
|
+
description: '支持模板配置',
|
|
48811
|
+
},
|
|
48812
|
+
{
|
|
48813
|
+
name: '🔧 Augment (VSCode 插件)',
|
|
48814
|
+
value: 'augment',
|
|
48815
|
+
description: '支持上下文配置',
|
|
48816
|
+
},
|
|
48817
|
+
{
|
|
48818
|
+
name: '⏭️ 其他 / 跳过',
|
|
48819
|
+
value: 'other',
|
|
48820
|
+
description: '只生成基础配置',
|
|
48821
|
+
},
|
|
48822
|
+
];
|
|
48823
|
+
|
|
48824
|
+
/**
|
|
48825
|
+
* 基础生成器 - 生成通用的 Space 配置文件
|
|
48826
|
+
*/
|
|
48827
|
+
var BaseGenerator = /** @class */ (function () {
|
|
48828
|
+
function BaseGenerator(cwd, config, verbose) {
|
|
48829
|
+
this.cwd = cwd;
|
|
48830
|
+
this.config = config;
|
|
48831
|
+
this.verbose = verbose;
|
|
48832
|
+
}
|
|
48833
|
+
/**
|
|
48834
|
+
* 生成基础配置文件
|
|
48835
|
+
*/
|
|
48836
|
+
BaseGenerator.prototype.generate = function (skipPrompts) {
|
|
48837
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48838
|
+
var files, appthenDir, configFile, gitignoreFile, promptFiles, error_1;
|
|
48839
|
+
return __generator(this, function (_a) {
|
|
48840
|
+
switch (_a.label) {
|
|
48841
|
+
case 0:
|
|
48842
|
+
files = [];
|
|
48843
|
+
_a.label = 1;
|
|
48844
|
+
case 1:
|
|
48845
|
+
_a.trys.push([1, 6, , 7]);
|
|
48846
|
+
appthenDir = path__namespace.join(this.cwd, '.appthen');
|
|
48847
|
+
this.ensureDirectory(appthenDir);
|
|
48848
|
+
return [4 /*yield*/, this.createSpaceConfig(appthenDir)];
|
|
48849
|
+
case 2:
|
|
48850
|
+
configFile = _a.sent();
|
|
48851
|
+
files.push(configFile);
|
|
48852
|
+
return [4 /*yield*/, this.createGitignore(appthenDir)];
|
|
48853
|
+
case 3:
|
|
48854
|
+
gitignoreFile = _a.sent();
|
|
48855
|
+
files.push(gitignoreFile);
|
|
48856
|
+
if (!!skipPrompts) return [3 /*break*/, 5];
|
|
48857
|
+
return [4 /*yield*/, this.createPrompts(appthenDir)];
|
|
48858
|
+
case 4:
|
|
48859
|
+
promptFiles = _a.sent();
|
|
48860
|
+
files.push.apply(files, __spreadArray([], __read(promptFiles), false));
|
|
48861
|
+
_a.label = 5;
|
|
48862
|
+
case 5: return [2 /*return*/, {
|
|
48863
|
+
success: true,
|
|
48864
|
+
files: files,
|
|
48865
|
+
message: 'Base configuration created successfully',
|
|
48866
|
+
}];
|
|
48867
|
+
case 6:
|
|
48868
|
+
error_1 = _a.sent();
|
|
48869
|
+
return [2 /*return*/, {
|
|
48870
|
+
success: false,
|
|
48871
|
+
files: [],
|
|
48872
|
+
error: error_1.message,
|
|
48873
|
+
}];
|
|
48874
|
+
case 7: return [2 /*return*/];
|
|
48875
|
+
}
|
|
48876
|
+
});
|
|
48877
|
+
});
|
|
48878
|
+
};
|
|
48879
|
+
/**
|
|
48880
|
+
* 确保目录存在
|
|
48881
|
+
*/
|
|
48882
|
+
BaseGenerator.prototype.ensureDirectory = function (dir) {
|
|
48883
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
48884
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
48885
|
+
if (this.verbose) {
|
|
48886
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(dir));
|
|
48887
|
+
}
|
|
48888
|
+
}
|
|
48889
|
+
};
|
|
48890
|
+
/**
|
|
48891
|
+
* 创建 space-config.json
|
|
48892
|
+
*/
|
|
48893
|
+
BaseGenerator.prototype.createSpaceConfig = function (appthenDir) {
|
|
48894
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48895
|
+
var configPath, configContent;
|
|
48896
|
+
return __generator(this, function (_a) {
|
|
48897
|
+
configPath = path__namespace.join(appthenDir, 'space-config.json');
|
|
48898
|
+
configContent = __assign(__assign({}, this.config), {
|
|
48899
|
+
// 添加一些额外的配置
|
|
48900
|
+
settings: {
|
|
48901
|
+
autoSync: true,
|
|
48902
|
+
watchPatterns: ['src/**/*', 'docs/**/*'],
|
|
48903
|
+
ignorePatterns: [
|
|
48904
|
+
'node_modules/**',
|
|
48905
|
+
'dist/**',
|
|
48906
|
+
'build/**',
|
|
48907
|
+
'.git/**',
|
|
48908
|
+
'*.log',
|
|
48909
|
+
],
|
|
48910
|
+
} });
|
|
48911
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(configContent, null, 2));
|
|
48912
|
+
if (this.verbose) {
|
|
48913
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
48914
|
+
}
|
|
48915
|
+
return [2 /*return*/, configPath];
|
|
48916
|
+
});
|
|
48917
|
+
});
|
|
48918
|
+
};
|
|
48919
|
+
/**
|
|
48920
|
+
* 创建 .gitignore
|
|
48921
|
+
*/
|
|
48922
|
+
BaseGenerator.prototype.createGitignore = function (appthenDir) {
|
|
48923
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48924
|
+
var gitignorePath, gitignoreContent;
|
|
48925
|
+
return __generator(this, function (_a) {
|
|
48926
|
+
gitignorePath = path__namespace.join(appthenDir, '.gitignore');
|
|
48927
|
+
gitignoreContent = "# Shadow Space \u6587\u4EF6\nshadow-space-*.json\n\n# \u65E5\u5FD7\u6587\u4EF6\n*.log\n\n# \u4E34\u65F6\u6587\u4EF6\n*.tmp\n.DS_Store\n\n# \u7F16\u8F91\u5668\u914D\u7F6E\uFF08\u53EF\u9009\uFF09\n# .vscode/\n# .idea/\n";
|
|
48928
|
+
fs__namespace.writeFileSync(gitignorePath, gitignoreContent);
|
|
48929
|
+
if (this.verbose) {
|
|
48930
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA .gitignore: ".concat(gitignorePath));
|
|
48931
|
+
}
|
|
48932
|
+
return [2 /*return*/, gitignorePath];
|
|
48933
|
+
});
|
|
48934
|
+
});
|
|
48935
|
+
};
|
|
48936
|
+
/**
|
|
48937
|
+
* 创建提示词目录和文件
|
|
48938
|
+
*/
|
|
48939
|
+
BaseGenerator.prototype.createPrompts = function (appthenDir) {
|
|
48940
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48941
|
+
var files, promptsDir, readmeFile, templateFiles;
|
|
48942
|
+
return __generator(this, function (_a) {
|
|
48943
|
+
switch (_a.label) {
|
|
48944
|
+
case 0:
|
|
48945
|
+
files = [];
|
|
48946
|
+
promptsDir = path__namespace.join(appthenDir, 'prompts');
|
|
48947
|
+
this.ensureDirectory(promptsDir);
|
|
48948
|
+
return [4 /*yield*/, this.createPromptsReadme(promptsDir)];
|
|
48949
|
+
case 1:
|
|
48950
|
+
readmeFile = _a.sent();
|
|
48951
|
+
files.push(readmeFile);
|
|
48952
|
+
return [4 /*yield*/, this.copyTemplateFiles(promptsDir)];
|
|
48953
|
+
case 2:
|
|
48954
|
+
templateFiles = _a.sent();
|
|
48955
|
+
files.push.apply(files, __spreadArray([], __read(templateFiles), false));
|
|
48956
|
+
return [2 /*return*/, files];
|
|
48957
|
+
}
|
|
48958
|
+
});
|
|
48959
|
+
});
|
|
48960
|
+
};
|
|
48961
|
+
/**
|
|
48962
|
+
* 创建提示词 README
|
|
48963
|
+
*/
|
|
48964
|
+
BaseGenerator.prototype.createPromptsReadme = function (promptsDir) {
|
|
48965
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48966
|
+
var readmePath, readmeContent;
|
|
48967
|
+
return __generator(this, function (_a) {
|
|
48968
|
+
readmePath = path__namespace.join(promptsDir, 'README.md');
|
|
48969
|
+
readmeContent = "# Agent+ Space \u63D0\u793A\u8BCD\n\n\u8FD9\u4E2A\u76EE\u5F55\u5305\u542B\u4E86\u7528\u4E8E AI \u7F16\u7801\u5DE5\u5177\u7684\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u5E2E\u52A9 AI \u7406\u89E3\u9879\u76EE\u89C4\u8303\u5E76\u751F\u6210\u7B26\u5408\u8981\u6C42\u7684\u4EE3\u7801\u3002\n\n## \uD83D\uDCDA \u63D0\u793A\u8BCD\u6587\u4EF6\u8BF4\u660E\n\n### \u6838\u5FC3\u6587\u6863\n\n1. **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357 \u2B50\n - \u9879\u76EE\u6982\u8FF0\u548C\u7ED3\u6784\n - \u5F00\u53D1\u89C4\u8303\u548C\u6D41\u7A0B\n - \u5FEB\u901F\u5F00\u59CB\u6307\u5357\n - \u6700\u4F73\u5B9E\u8DF5\n\n2. **tsx-generation.md** - TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303 \u2B50\u2B50\u2B50\n - \u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\u8981\u6C42\n - \u4E25\u683C\u7684 render() \u65B9\u6CD5\u7EA6\u675F\n - TypeScript \u8BED\u6CD5\u9650\u5236\n - JSX \u4F4D\u7F6E\u9650\u5236\n - \u5B8C\u6574\u793A\u4F8B\u4EE3\u7801\n - \u5E38\u89C1\u9519\u8BEF\u548C\u4FEE\u590D\n\n3. **decision-tree.md** - AI \u51B3\u7B56\u6811 \u2B50\u2B50\n - \u5E2E\u52A9 AI \u505A\u51FA\u6B63\u786E\u51B3\u7B56\n - \u5173\u952E\u51B3\u7B56\u70B9\u8BF4\u660E\n - \u5E38\u89C1\u9519\u8BEF\u51B3\u7B56\u5206\u6790\n - \u62D2\u7EDD\u751F\u6210\u7684\u6807\u51C6\u54CD\u5E94\n\n4. **validation-checklist.md** - \u9A8C\u8BC1\u6E05\u5355 \u2B50\u2B50\n - \u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6D41\u7A0B\n - 8 \u4E2A\u9636\u6BB5\u7684\u68C0\u67E5\u9879\n - \u5E38\u89C1\u9519\u8BEF\u68C0\u67E5\n - \u9A8C\u8BC1\u5DE5\u5177\u4F7F\u7528\n\n5. **code-review.md** - \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n - \u5BA1\u67E5\u68C0\u67E5\u6E05\u5355\n - \u5E38\u89C1\u95EE\u9898\u8BC6\u522B\n - \u53CD\u9988\u6A21\u677F\n\n6. **refactoring.md** - \u91CD\u6784\u6307\u5357\n - \u91CD\u6784\u539F\u5219\n - \u5E38\u89C1\u91CD\u6784\u6A21\u5F0F\n - \u6027\u80FD\u4F18\u5316\u6280\u5DE7\n\n## \uD83D\uDE80 \u4F7F\u7528\u65B9\u6CD5\n\n### \u5BF9\u4E8E\u5F00\u53D1\u8005\n\n1. **\u9996\u6B21\u5F00\u53D1\u524D**\uFF1A\u9605\u8BFB `project-guide.md` \u4E86\u89E3\u9879\u76EE\u6982\u51B5\n2. **\u7F16\u5199 TSX \u4EE3\u7801\u524D**\uFF1A\u8BE6\u7EC6\u9605\u8BFB `tsx-generation.md`\n3. **\u4EE3\u7801\u9A8C\u8BC1**\uFF1A\u4F7F\u7528 `validation-checklist.md` \u8FDB\u884C\u81EA\u67E5\n4. **\u4EE3\u7801\u5BA1\u67E5**\uFF1A\u53C2\u8003 `code-review.md` \u8FDB\u884C\u5BA1\u67E5\n\n### \u5BF9\u4E8E AI \u5DE5\u5177\n\n\u6839\u636E\u4F60\u4F7F\u7528\u7684 AI \u5DE5\u5177\uFF0C\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230\u5BF9\u5E94\u7684\u914D\u7F6E\u4E2D\uFF1A\n\n#### Claude Code\n\u5728\u5BF9\u8BDD\u4E2D\u76F4\u63A5\u5F15\u7528\u8FD9\u4E9B\u63D0\u793A\u8BCD\uFF0C\u6216\u8005\u6DFB\u52A0\u5230\u9879\u76EE\u7684 `.claude/` \u914D\u7F6E\u4E2D\u3002\n\n#### Cursor\n\u5C06\u63D0\u793A\u8BCD\u5185\u5BB9\u6DFB\u52A0\u5230 `.cursor/rules.md` \u6587\u4EF6\u4E2D\u3002\n\n#### Windsurf\n\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230 Cascade \u914D\u7F6E\u4E2D\u3002\n\n#### \u963F\u91CC\u4E91 Coder\n\u5728 Coder \u7684\u8BBE\u7F6E\u4E2D\u6DFB\u52A0\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002\n\n#### Augment\n\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230 `.augment/context/` \u76EE\u5F55\u4E2D\u3002\n\n## \u26A0\uFE0F \u91CD\u8981\u63D0\u793A\n\n### TSX \u4EE3\u7801\u5FC5\u987B\u7B26\u5408\u89C4\u8303\n- \u4E0D\u7B26\u5408\u89C4\u8303\u7684\u4EE3\u7801\u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\n- \u5FC5\u987B\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\n- \u7981\u6B62\u4F7F\u7528\u6807\u51C6\u7684 lint/format \u5DE5\u5177\n\n### AI \u5DE5\u5177\u914D\u7F6E\n- \u5C06\u8FD9\u4E9B\u63D0\u793A\u8BCD\u6587\u4EF6\u6DFB\u52A0\u5230 AI \u5DE5\u5177\u7684\u4E0A\u4E0B\u6587\u4E2D\n- \u786E\u4FDD AI \u7406\u89E3\u5E76\u9075\u5B88\u6240\u6709\u7EA6\u675F\n- \u5F53\u4E0D\u786E\u5B9A\u65F6\uFF0CAI \u5E94\u8BE5\u62D2\u7EDD\u751F\u6210\u800C\u4E0D\u662F\u5192\u9669\n\n## \uD83D\uDEE0\uFE0F \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\n\n\u4F60\u53EF\u4EE5\u6839\u636E\u9879\u76EE\u9700\u6C42\u6DFB\u52A0\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6587\u4EF6\uFF1A\n\n- `api-design.md`: API \u8BBE\u8BA1\u89C4\u8303\n- `testing.md`: \u6D4B\u8BD5\u7F16\u5199\u6307\u5357\n- `styling.md`: \u6837\u5F0F\u7F16\u5199\u89C4\u8303\n- `performance.md`: \u6027\u80FD\u4F18\u5316\u6307\u5357\n- `backend-guide.md`: \u540E\u7AEF\u5F00\u53D1\u6307\u5357\uFF08midwayjs\uFF09\n\n## \uD83D\uDD04 \u66F4\u65B0\u63D0\u793A\u8BCD\n\n\u63D0\u793A\u8BCD\u4F1A\u968F\u7740\u9879\u76EE\u89C4\u8303\u7684\u6F14\u8FDB\u800C\u66F4\u65B0\uFF1A\n- \u5B9A\u671F\u68C0\u67E5\u5E76\u66F4\u65B0\u8FD9\u4E9B\u6587\u4EF6\n- \u6839\u636E\u5B9E\u9645\u95EE\u9898\u8865\u5145\u65B0\u7684\u89C4\u5219\n- \u8BB0\u5F55\u5E38\u89C1\u9519\u8BEF\u548C\u89E3\u51B3\u65B9\u6848\n\n## \uD83D\uDCAC \u53CD\u9988\u548C\u6539\u8FDB\n\n\u5982\u679C\u4F60\u53D1\u73B0\u63D0\u793A\u8BCD\u6709\u95EE\u9898\u6216\u6709\u6539\u8FDB\u5EFA\u8BAE\uFF1A\n- \u5728\u9879\u76EE\u4E2D\u521B\u5EFA Issue\n- \u76F4\u63A5\u4FEE\u6539\u63D0\u793A\u8BCD\u6587\u4EF6\u5E76\u63D0\u4EA4 PR\n- \u4E0E\u56E2\u961F\u5206\u4EAB\u4F60\u7684\u7ECF\u9A8C\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01** \uD83C\uDFAF\n";
|
|
48970
|
+
fs__namespace.writeFileSync(readmePath, readmeContent);
|
|
48971
|
+
if (this.verbose) {
|
|
48972
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u63D0\u793A\u8BCD README: ".concat(readmePath));
|
|
48973
|
+
}
|
|
48974
|
+
return [2 /*return*/, readmePath];
|
|
48975
|
+
});
|
|
48976
|
+
});
|
|
48977
|
+
};
|
|
48978
|
+
/**
|
|
48979
|
+
* 复制模板文件到提示词目录
|
|
48980
|
+
*/
|
|
48981
|
+
BaseGenerator.prototype.copyTemplateFiles = function (promptsDir) {
|
|
48982
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
48983
|
+
var files, projectGuidePath, projectGuideContent, tsxGenerationPath, tsxGenerationContent, decisionTreePath, decisionTreeContent, validationPath, validationContent, codeReviewPath, codeReviewContent, refactoringPath, refactoringContent;
|
|
48984
|
+
return __generator(this, function (_a) {
|
|
48985
|
+
files = [];
|
|
48986
|
+
projectGuidePath = path__namespace.join(promptsDir, 'project-guide.md');
|
|
48987
|
+
projectGuideContent = this.getProjectGuideTemplate();
|
|
48988
|
+
fs__namespace.writeFileSync(projectGuidePath, projectGuideContent);
|
|
48989
|
+
files.push(projectGuidePath);
|
|
48990
|
+
if (this.verbose) {
|
|
48991
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: project-guide.md");
|
|
48992
|
+
}
|
|
48993
|
+
tsxGenerationPath = path__namespace.join(promptsDir, 'tsx-generation.md');
|
|
48994
|
+
tsxGenerationContent = this.getTsxGenerationTemplate();
|
|
48995
|
+
fs__namespace.writeFileSync(tsxGenerationPath, tsxGenerationContent);
|
|
48996
|
+
files.push(tsxGenerationPath);
|
|
48997
|
+
if (this.verbose) {
|
|
48998
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: tsx-generation.md");
|
|
48999
|
+
}
|
|
49000
|
+
decisionTreePath = path__namespace.join(promptsDir, 'decision-tree.md');
|
|
49001
|
+
decisionTreeContent = this.getDecisionTreeTemplate();
|
|
49002
|
+
fs__namespace.writeFileSync(decisionTreePath, decisionTreeContent);
|
|
49003
|
+
files.push(decisionTreePath);
|
|
49004
|
+
if (this.verbose) {
|
|
49005
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: decision-tree.md");
|
|
49006
|
+
}
|
|
49007
|
+
validationPath = path__namespace.join(promptsDir, 'validation-checklist.md');
|
|
49008
|
+
validationContent = this.getValidationChecklistTemplate();
|
|
49009
|
+
fs__namespace.writeFileSync(validationPath, validationContent);
|
|
49010
|
+
files.push(validationPath);
|
|
49011
|
+
if (this.verbose) {
|
|
49012
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: validation-checklist.md");
|
|
49013
|
+
}
|
|
49014
|
+
codeReviewPath = path__namespace.join(promptsDir, 'code-review.md');
|
|
49015
|
+
codeReviewContent = this.getCodeReviewTemplate();
|
|
49016
|
+
fs__namespace.writeFileSync(codeReviewPath, codeReviewContent);
|
|
49017
|
+
files.push(codeReviewPath);
|
|
49018
|
+
if (this.verbose) {
|
|
49019
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: code-review.md");
|
|
49020
|
+
}
|
|
49021
|
+
refactoringPath = path__namespace.join(promptsDir, 'refactoring.md');
|
|
49022
|
+
refactoringContent = this.getRefactoringTemplate();
|
|
49023
|
+
fs__namespace.writeFileSync(refactoringPath, refactoringContent);
|
|
49024
|
+
files.push(refactoringPath);
|
|
49025
|
+
if (this.verbose) {
|
|
49026
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: refactoring.md");
|
|
49027
|
+
}
|
|
49028
|
+
return [2 /*return*/, files];
|
|
49029
|
+
});
|
|
49030
|
+
});
|
|
49031
|
+
};
|
|
49032
|
+
/**
|
|
49033
|
+
* 获取项目开发总指南模板内容
|
|
49034
|
+
*/
|
|
49035
|
+
BaseGenerator.prototype.getProjectGuideTemplate = function () {
|
|
49036
|
+
return "# Appthen \u9879\u76EE\u5F00\u53D1\u89C4\u8303\n\n## \uD83D\uDCCB \u9879\u76EE\u6982\u8FF0\n\n\u672C\u9879\u76EE\u662F **Appthen \u4F4E\u4EE3\u7801\u5E73\u53F0**\uFF0C\u652F\u6301\u7528\u9AD8\u4EE3\u7801\u5F00\u53D1\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u7684 React \u9875\u9762\u548C\u7EC4\u4EF6\u3002\n\n### \u9879\u76EE\u7ED3\u6784\n\n- **app/** - \u524D\u7AEF\u4EE3\u7801\uFF08\u540C\u6B65\u81EA\u4F4E\u4EE3\u7801\u4EA7\u54C1 Appthen\uFF09\n - \u4F7F\u7528\u7279\u6B8A\u89C4\u8303\u7684 TSX \u5B9E\u73B0 React \u9875\u9762\u548C\u7EC4\u4EF6\n - \u4EE3\u7801\u4F1A\u88AB\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u89E3\u6790\u548C\u5BFC\u5165\n- **server/** - \u540E\u7AEF\u4EE3\u7801\uFF08\u57FA\u4E8E cool-admin \u548C midwayjs\uFF09\n - \u4F7F\u7528 midwayjs \u6846\u67B6\u5F00\u53D1\u540E\u7AEF\u670D\u52A1\n - \u63D0\u4F9B\u63A5\u53E3\u3001\u6570\u636E\u5B57\u6BB5\u3001\u4E1A\u52A1\u6D41\u7A0B\u7B49\u4FE1\u606F\n\n---\n\n## \uD83D\uDEA8 \u91CD\u8981\uFF1A\u5F00\u53D1\u524D\u5FC5\u8BFB\n\n### \u524D\u7AEF\u5F00\u53D1\u89C4\u8303\n\n**[\u5173\u952E] \u5F00\u53D1 React \u9875\u9762\u548C\u7EC4\u4EF6\uFF08TSX \u6587\u4EF6\uFF09\u65F6\uFF1A**\n\n1. **\u5FC5\u987B\u5148\u9605\u8BFB** `.appthen/prompts/tsx-generation.md`\n - \u4E86\u89E3\u7279\u6B8A\u7684 TSX \u8BED\u6CD5\u89C4\u8303\n - \u4E25\u683C\u9075\u5B88\u975E\u5E38\u89C4\u7684 TSX/JSX \u8BED\u6CD5\u8981\u6C42\n\n2. **\u5FC5\u987B\u8FDB\u884C\u9A8C\u8BC1**\n - \u8BFB\u5199 TSX \u6587\u4EF6\u540E\uFF0C\u8C03\u7528\u547D\u4EE4\u9A8C\u8BC1\u8BED\u6CD5\uFF1A\n ```bash\n appthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n ```\n - \u5982\u4E0D\u7B26\u5408\u89C4\u8303\uFF0C\u6839\u636E\u9A8C\u8BC1\u7ED3\u679C\u8FDB\u884C\u4FEE\u6B63\n\n3. **\u7981\u6B62\u4F7F\u7528\u6807\u51C6\u5DE5\u5177**\n - \u274C \u4E0D\u8981\u8FD0\u884C `eslint`\u3001`prettier`\u3001`tsc` \u7B49\u6807\u51C6\u5DE5\u5177\n - \u274C \u8FD9\u4E9B\u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A TSX \u8BED\u6CD5\n - \u2705 \u53EA\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\n\n---\n\n## \uD83C\uDFAF \u4E1A\u52A1\u5F00\u53D1\u6D41\u7A0B\n\n### 1. \u83B7\u53D6\u63A5\u53E3\u4FE1\u606F\n\n\u4ECE server \u7AEF\u83B7\u53D6\u63A5\u53E3\u5BF9\u63A5\u6240\u9700\u7684\u76F8\u5173\u4FE1\u606F\uFF1A\n- \u63A5\u53E3\u5730\u5740\u548C\u53C2\u6570\n- \u6570\u636E\u5B57\u6BB5\u5B9A\u4E49\n- \u4E1A\u52A1\u6D41\u7A0B\u8BF4\u660E\n\n### 2. \u5F00\u53D1\u524D\u7AEF\u754C\u9762\n\n\u6839\u636E\u63A5\u53E3\u4FE1\u606F\u5F00\u53D1\u524D\u7AEF\u754C\u9762\uFF1A\n- \u4F7F\u7528 TSX \u7279\u6B8A\u8BED\u6CD5\n- \u9075\u5B88\u4E25\u683C\u7684 render() \u65B9\u6CD5\u7EA6\u675F\n- \u4F7F\u7528 @DataSource \u88C5\u9970\u5668\u5BF9\u63A5\u63A5\u53E3\n\n### 3. \u9A8C\u8BC1\u548C\u6D4B\u8BD5\n\n- \u4F7F\u7528 `appthen check-tsx` \u9A8C\u8BC1\u8BED\u6CD5\n- \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n- \u786E\u4FDD\u529F\u80FD\u6B63\u5E38\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - TSX \u4EE3\u7801\u751F\u6210\u5B8C\u6574\u89C4\u8303\n- **decision-tree.md** - AI \u51B3\u7B56\u6811\uFF08\u5E2E\u52A9 AI \u505A\u51FA\u6B63\u786E\u51B3\u7B56\uFF09\n- **validation-checklist.md** - \u4EE3\u7801\u9A8C\u8BC1\u6E05\u5355\n- **code-review.md** - \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n- **refactoring.md** - \u4EE3\u7801\u91CD\u6784\u6307\u5357\n\n---\n\n## \u26A0\uFE0F \u7279\u522B\u6CE8\u610F\n\n### TSX \u8BED\u6CD5\u7684\u7279\u6B8A\u6027\n\n\u6211\u4EEC\u7684 TSX \u8BED\u6CD5\u4E0E\u6807\u51C6 React/TypeScript \u4E0D\u540C\uFF1A\n\n1. **render() \u65B9\u6CD5\u7EA6\u675F**\n - \u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\n - \u4E0D\u80FD\u6709\u4EFB\u4F55\u903B\u8F91\u8BED\u53E5\n - \u53EA\u80FD\u76F4\u63A5\u8BBF\u95EE this.state \u548C this.props\n\n2. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - \u65B9\u6CD5\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\n - \u4E0D\u80FD\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component\uFF09\n\n3. **JSX \u4F4D\u7F6E\u9650\u5236**\n - \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\n - \u5176\u4ED6\u65B9\u6CD5\u548C\u5C5E\u6027\u4E0D\u80FD\u6709 JSX\n\n### \u4E3A\u4EC0\u4E48\u6709\u8FD9\u4E9B\u9650\u5236\uFF1F\n\n\u8FD9\u4E9B\u9650\u5236\u662F\u4E3A\u4E86\u8BA9\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u80FD\u591F\uFF1A\n- \u89E3\u6790\u548C\u7406\u89E3\u4EE3\u7801\u7ED3\u6784\n- \u63D0\u53D6\u6570\u636E\u6A21\u578B\u548C\u63A5\u53E3\u5B9A\u4E49\n- \u5728\u53EF\u89C6\u5316\u7F16\u8F91\u5668\u4E2D\u7F16\u8F91\n- \u751F\u6210\u7B26\u5408\u89C4\u8303\u7684\u4EE3\u7801\n\n**\u8FDD\u53CD\u89C4\u8303 = \u65E0\u6CD5\u5BFC\u5165\u4F4E\u4EE3\u7801\u7CFB\u7EDF\uFF01**\n\n---\n\n## \uD83D\uDE80 \u5FEB\u901F\u5F00\u59CB\n\n### \u521B\u5EFA\u65B0\u9875\u9762\n\n```bash\n# 1. \u67E5\u770B TSX \u751F\u6210\u89C4\u8303\ncat .appthen/prompts/tsx-generation.md\n\n# 2. \u521B\u5EFA\u9875\u9762\u6587\u4EF6\n# \u4F7F\u7528 AI \u5DE5\u5177\u751F\u6210\uFF0C\u786E\u4FDD\u9075\u5B88\u89C4\u8303\n\n# 3. \u9A8C\u8BC1\u8BED\u6CD5\nappthen check-tsx -f \"app/src/pages/NewPage.tsx\"\n\n# 4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n# \u6839\u636E\u9A8C\u8BC1\u7ED3\u679C\u4FEE\u6B63\u4EE3\u7801\n\n# 5. \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n```\n\n### \u4FEE\u6539\u73B0\u6709\u9875\u9762\n\n```bash\n# 1. \u67E5\u770B\u73B0\u6709\u4EE3\u7801\ncat app/src/pages/ExistingPage.tsx\n\n# 2. \u4FEE\u6539\u4EE3\u7801\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n\n# 3. \u9A8C\u8BC1\u8BED\u6CD5\nappthen check-tsx -f \"app/src/pages/ExistingPage.tsx\"\n\n# 4. \u6D4B\u8BD5\u529F\u80FD\n```\n\n---\n\n## \uD83D\uDCA1 \u6700\u4F73\u5B9E\u8DF5\n\n1. **\u59CB\u7EC8\u5148\u9605\u8BFB\u89C4\u8303** - \u4E0D\u8981\u51ED\u7ECF\u9A8C\u5199\u4EE3\u7801\n2. **\u9891\u7E41\u9A8C\u8BC1** - \u6BCF\u6B21\u4FEE\u6539\u540E\u90FD\u8FD0\u884C check-tsx\n3. **\u53C2\u8003\u793A\u4F8B** - \u67E5\u770B\u73B0\u6709\u9875\u9762\u7684\u5B9E\u73B0\u65B9\u5F0F\n4. **\u4F7F\u7528 AI \u8F85\u52A9** - \u8BA9 AI \u9075\u5B88\u89C4\u8303\u751F\u6210\u4EE3\u7801\n5. **\u6D4B\u8BD5\u5BFC\u5165** - \u786E\u4FDD\u80FD\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u6B63\u5E38\u5BFC\u5165\n\n---\n\n## \uD83C\uDD98 \u9047\u5230\u95EE\u9898\uFF1F\n\n1. **\u8BED\u6CD5\u9A8C\u8BC1\u5931\u8D25** \u2192 \u67E5\u770B validation-checklist.md\n2. **\u4E0D\u77E5\u9053\u5982\u4F55\u5B9E\u73B0** \u2192 \u67E5\u770B tsx-generation.md \u4E2D\u7684\u793A\u4F8B\n3. **AI \u751F\u6210\u9519\u8BEF\u4EE3\u7801** \u2192 \u67E5\u770B decision-tree.md \u4E86\u89E3 AI \u51B3\u7B56\u6D41\u7A0B\n4. **\u9700\u8981\u91CD\u6784\u4EE3\u7801** \u2192 \u67E5\u770B refactoring.md\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01** \uD83C\uDFAF\n";
|
|
49037
|
+
};
|
|
49038
|
+
/**
|
|
49039
|
+
* 获取 TSX 生成模板内容
|
|
49040
|
+
*/
|
|
49041
|
+
BaseGenerator.prototype.getTsxGenerationTemplate = function () {
|
|
49042
|
+
return "# TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303\n\n\u751F\u6210\u7B26\u5408\u5E73\u53F0\u89C4\u8303\u7684 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u9075\u5FAA\u4EE5\u4E0B\u89C4\u5219\uFF1A\n\n## 1. \u6587\u4EF6\u7ED3\u6784\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n## 2. \u5173\u952E\u89C4\u5219\n\n- \u2705 \u5FC5\u987B\u5305\u542B JSDoc \u5143\u6570\u636E\u6CE8\u91CA\n- \u2705 \u4F7F\u7528 class IProps \u548C class IState\n- \u2705 render() \u65B9\u6CD5\u53EA\u5305\u542B return \u8BED\u53E5\n- \u2705 \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n- \u274C \u907F\u514D\u5728 render() \u4E2D\u4F7F\u7528\u4E09\u5143\u8868\u8FBE\u5F0F\n- \u274C \u907F\u514D\u5728\u65B9\u6CD5\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n\n\u8BE6\u7EC6\u89C4\u8303\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
|
|
49043
|
+
};
|
|
49044
|
+
/**
|
|
49045
|
+
* 获取决策树模板内容
|
|
49046
|
+
*/
|
|
49047
|
+
BaseGenerator.prototype.getDecisionTreeTemplate = function () {
|
|
49048
|
+
return "# AI \u51B3\u7B56\u6811 - TSX \u4EE3\u7801\u751F\u6210\u51B3\u7B56\u6307\u5357\n\n## \uD83C\uDFAF \u76EE\u7684\n\n\u5E2E\u52A9 AI \u5728\u751F\u6210 TSX \u4EE3\u7801\u65F6\u505A\u51FA\u6B63\u786E\u7684\u51B3\u7B56\uFF0C\u907F\u514D\u5E38\u89C1\u9519\u8BEF\u3002\n\n---\n\n## \uD83D\uDCCA \u51B3\u7B56\u6D41\u7A0B\u56FE\n\n```\n\u7528\u6237\u8BF7\u6C42\n \u2193\n\u662F\u5426\u6D89\u53CA TSX \u6587\u4EF6\uFF1F\n \u251C\u2500 \u5426 \u2192 \u6B63\u5E38\u5904\u7406\n \u2514\u2500 \u662F \u2192 \u8FDB\u5165 TSX \u51B3\u7B56\u6D41\u7A0B\n \u2193\n \u662F\u5426\u662F\"\u521B\u5EFA\u9875\u9762/\u7EC4\u4EF6\"\uFF1F\n \u251C\u2500 \u662F \u2192 [\u9AD8\u5EA6\u8B66\u6212] \u8FDB\u5165\u9875\u9762/\u7EC4\u4EF6\u751F\u6210\u6D41\u7A0B\n \u2502 \u2193\n \u2502 \u6267\u884C\u9884\u751F\u6210\u9A8C\u8BC1\u6E05\u5355\n \u2502 \u2193\n \u2502 \u6240\u6709\u68C0\u67E5\u901A\u8FC7\uFF1F\n \u2502 \u251C\u2500 \u5426 \u2192 \u62D2\u7EDD\u751F\u6210\uFF0C\u8FD4\u56DE\u9519\u8BEF\u63D0\u793A\n \u2502 \u2514\u2500 \u662F \u2192 \u751F\u6210\u5B8C\u6574 TSX \u6587\u4EF6\n \u2502 \u2193\n \u2502 \u5305\u542B\u6240\u6709\u5FC5\u9700\u7ED3\u6784\uFF1F\n \u2502 \u251C\u2500 \u5426 \u2192 \u62D2\u7EDD\u751F\u6210\n \u2502 \u2514\u2500 \u662F \u2192 \u8FD4\u56DE\u4EE3\u7801\n \u2502\n \u2514\u2500 \u5426 \u2192 \u662F\u5426\u4FEE\u6539\u73B0\u6709 TSX\uFF1F\n \u251C\u2500 \u662F \u2192 \u68C0\u67E5\u4FEE\u6539\u5185\u5BB9\n \u2502 \u2193\n \u2502 \u662F\u5426\u4FEE\u6539 render() \u65B9\u6CD5\uFF1F\n \u2502 \u251C\u2500 \u662F \u2192 [\u9AD8\u5EA6\u8B66\u6212] \u68C0\u67E5\u7EA6\u675F\n \u2502 \u2502 \u2193\n \u2502 \u2502 \u662F\u5426\u8FDD\u53CD\u7EA6\u675F\uFF1F\n \u2502 \u2502 \u251C\u2500 \u662F \u2192 \u62D2\u7EDD\u4FEE\u6539\n \u2502 \u2502 \u2514\u2500 \u5426 \u2192 \u5141\u8BB8\u4FEE\u6539\n \u2502 \u2514\u2500 \u5426 \u2192 \u6B63\u5E38\u4FEE\u6539\n \u2502\n \u2514\u2500 \u5426 \u2192 \u5176\u4ED6\u64CD\u4F5C\uFF08\u67E5\u770B\u3001\u5206\u6790\u7B49\uFF09\n```\n\n---\n\n## \uD83D\uDEA8 \u5173\u952E\u51B3\u7B56\u70B9\n\n### \u51B3\u7B56\u70B9 1\uFF1A\u8BC6\u522B TSX \u64CD\u4F5C\n\n**\u89E6\u53D1\u8BCD\u6C47\uFF1A**\n- \"\u521B\u5EFA\u9875\u9762\" / \"\u751F\u6210\u9875\u9762\" / \"\u5199\u4E2A\u9875\u9762\"\n- \"\u521B\u5EFA\u7EC4\u4EF6\" / \"\u751F\u6210\u7EC4\u4EF6\" / \"\u5199\u4E2A\u7EC4\u4EF6\"\n- \"\u4FEE\u6539 XXX.tsx\" / \"\u66F4\u65B0\u9875\u9762\"\n- \"\u6DFB\u52A0\u529F\u80FD\u5230\u9875\u9762\"\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5305\u542B\u4EE5\u4E0A\u8BCD\u6C47 \u2192 \u8FDB\u5165 TSX \u51B3\u7B56\u6D41\u7A0B\n- \u5426\u5219 \u2192 \u6B63\u5E38\u5904\u7406\n\n---\n\n### \u51B3\u7B56\u70B9 2\uFF1A\u9875\u9762/\u7EC4\u4EF6\u751F\u6210\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u7528\u6237\u660E\u786E\u8981\u6C42\"\u521B\u5EFA\"\u6216\"\u751F\u6210\"\n- \u6CA1\u6709\u6307\u5B9A\u73B0\u6709\u6587\u4EF6\n\n**\u51B3\u7B56\uFF1A**\n- \u662F\u9875\u9762/\u7EC4\u4EF6\u751F\u6210 \u2192 \u6267\u884C\u5B8C\u6574\u9A8C\u8BC1\u6E05\u5355\n- \u5426 \u2192 \u8FDB\u5165\u4E0B\u4E00\u4E2A\u51B3\u7B56\u70B9\n\n**\u5FC5\u987B\u6267\u884C\u7684\u68C0\u67E5\uFF1A**\n1. \u2705 \u6211\u662F\u5426\u8981\u751F\u6210\u5B8C\u6574\u7684 TSX \u6587\u4EF6\uFF1F\n2. \u2705 \u6211\u662F\u5426\u5305\u542B\u4E86\u6240\u6709\u5FC5\u9700\u7ED3\u6784\uFF1F\n3. \u2705 \u6211\u662F\u5426\u9075\u5B88\u4E86 render() \u65B9\u6CD5\u7EA6\u675F\uFF1F\n4. \u2705 \u6211\u662F\u5426\u907F\u514D\u4E86 TypeScript \u7C7B\u578B\u6CE8\u89E3\uFF1F\n5. \u2705 \u6211\u662F\u5426\u53EA\u5728 render() \u4E2D\u4F7F\u7528 JSX\uFF1F\n\n**\u5982\u679C\u4EFB\u4F55\u4E00\u9879\u4E0D\u786E\u5B9A \u2192 \u62D2\u7EDD\u751F\u6210\uFF01**\n\n---\n\n### \u51B3\u7B56\u70B9 3\uFF1Arender() \u65B9\u6CD5\u4FEE\u6539\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4FEE\u6539\u6D89\u53CA render() \u65B9\u6CD5\u5185\u90E8\n\n**\u51B3\u7B56\uFF1A**\n- \u662F render() \u4FEE\u6539 \u2192 \u6267\u884C\u4E25\u683C\u7EA6\u675F\u68C0\u67E5\n- \u5426 \u2192 \u6B63\u5E38\u4FEE\u6539\n\n**\u4E25\u683C\u7EA6\u675F\u68C0\u67E5\uFF1A**\n1. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u53D8\u91CF\u58F0\u660E\uFF1F \u2192 \u62D2\u7EDD\n2. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u89E3\u6784\u8D4B\u503C\uFF1F \u2192 \u62D2\u7EDD\n3. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u903B\u8F91\u8BED\u53E5\uFF1F \u2192 \u62D2\u7EDD\n4. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u51FD\u6570\u8C03\u7528\uFF1F \u2192 \u62D2\u7EDD\n5. \u2705 \u662F\u5426\u53EA\u662F\u4FEE\u6539 JSX \u7ED3\u6784\uFF1F \u2192 \u5141\u8BB8\n6. \u2705 \u662F\u5426\u53EA\u662F\u4FEE\u6539 this.state \u8BBF\u95EE\uFF1F \u2192 \u5141\u8BB8\n\n---\n\n### \u51B3\u7B56\u70B9 4\uFF1ATypeScript \u8BED\u6CD5\u4F7F\u7528\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4EE3\u7801\u4E2D\u662F\u5426\u4F7F\u7528\u4E86 TypeScript \u8BED\u6CD5\n\n**\u51B3\u7B56\u89C4\u5219\uFF1A**\n\n| \u4F4D\u7F6E | \u5141\u8BB8\u7684 TS \u8BED\u6CD5 | \u7981\u6B62\u7684 TS \u8BED\u6CD5 |\n|------|---------------|---------------|\n| IProps \u63A5\u53E3 | \u2705 string?, number?, any[] | \u274C \u6CDB\u578B Array<T> |\n| IState \u7C7B | \u2705 string?, number?, any[] | \u274C \u6CDB\u578B Array<T> |\n| defaultProps | \u2705 \u7EAF JS \u503C | \u274C \u4EFB\u4F55\u7C7B\u578B\u6CE8\u89E3 |\n| \u7C7B\u65B9\u6CD5 | \u274C \u4EFB\u4F55\u7C7B\u578B\u6CE8\u89E3 | \u274C \u53C2\u6570\u7C7B\u578B\u3001\u8FD4\u56DE\u7C7B\u578B |\n| render() | \u274C \u4EFB\u4F55 TS \u8BED\u6CD5 | \u274C \u6240\u6709 TS \u8BED\u6CD5 |\n| React.Component | \u2705 <IProps, IState> | \u274C \u5176\u4ED6\u6CDB\u578B |\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5728\u7981\u6B62\u4F4D\u7F6E\u4F7F\u7528 TS \u8BED\u6CD5 \u2192 \u62D2\u7EDD\n- \u5982\u679C\u5728\u5141\u8BB8\u4F4D\u7F6E\u6B63\u786E\u4F7F\u7528 \u2192 \u5141\u8BB8\n\n---\n\n### \u51B3\u7B56\u70B9 5\uFF1AJSX \u4F4D\u7F6E\u68C0\u67E5\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4EE3\u7801\u4E2D\u662F\u5426\u5728\u975E render() \u4F4D\u7F6E\u4F7F\u7528 JSX\n\n**\u51B3\u7B56\u89C4\u5219\uFF1A**\n\n| \u4F4D\u7F6E | \u662F\u5426\u5141\u8BB8 JSX | \u793A\u4F8B |\n|------|-------------|------|\n| render() \u65B9\u6CD5 | \u2705 \u5141\u8BB8 | `return <div>...</div>` |\n| \u5176\u4ED6\u65B9\u6CD5 | \u274C \u7981\u6B62 | `handleClick() { return <div>...</div>; }` |\n| \u7C7B\u5C5E\u6027 | \u274C \u7981\u6B62 | `item = <div>...</div>` |\n| \u7BAD\u5934\u51FD\u6570\u5C5E\u6027 | \u274C \u7981\u6B62 | `renderItem = () => <div>...</div>` |\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5728\u7981\u6B62\u4F4D\u7F6E\u4F7F\u7528 JSX \u2192 \u62D2\u7EDD\n- \u5982\u679C\u53EA\u5728 render() \u4E2D\u4F7F\u7528 \u2192 \u5141\u8BB8\n\n---\n\n## \uD83D\uDEE1\uFE0F \u5B89\u5168\u68C0\u67E5\u6E05\u5355\n\n### \u751F\u6210\u4EE3\u7801\u524D\u5FC5\u987B\u56DE\u7B54\u7684\u95EE\u9898\uFF1A\n\n1. **\u7ED3\u6784\u5B8C\u6574\u6027**\n - [ ] \u662F\u5426\u5305\u542B JSDoc \u5143\u6570\u636E\u6CE8\u91CA\uFF1F\n - [ ] \u662F\u5426\u5305\u542B IProps \u63A5\u53E3\uFF1F\n - [ ] \u662F\u5426\u5305\u542B IState \u7C7B\uFF1F\n - [ ] \u662F\u5426\u5305\u542B Document \u7C7B\uFF1F\n - [ ] \u662F\u5426\u5305\u542B export default\uFF1F\n\n2. **render() \u65B9\u6CD5\u7EA6\u675F**\n - [ ] render() \u7B2C\u4E00\u884C\u662F return ( \u5417\uFF1F\n - [ ] render() \u5185\u90E8\u6CA1\u6709\u53D8\u91CF\u58F0\u660E\u5417\uFF1F\n - [ ] render() \u5185\u90E8\u6CA1\u6709\u903B\u8F91\u8BED\u53E5\u5417\uFF1F\n - [ ] render() \u53EA\u8BBF\u95EE this.state/this.props \u5417\uFF1F\n\n3. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u53D8\u91CF\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u6CA1\u6709\u4F7F\u7528\u6CDB\u578B\uFF08\u9664 React.Component\uFF09\u5417\uFF1F\n\n4. **JSX \u4F4D\u7F6E\u9650\u5236**\n - [ ] JSX \u53EA\u5728 render() \u65B9\u6CD5\u4E2D\u5417\uFF1F\n - [ ] \u5176\u4ED6\u65B9\u6CD5\u6CA1\u6709 JSX \u5417\uFF1F\n - [ ] \u7C7B\u5C5E\u6027\u6CA1\u6709 JSX \u5417\uFF1F\n\n5. **\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168**\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528\u53EF\u9009\u94FE ?. \u5417\uFF1F\n - [ ] \u6570\u7EC4\u8BBF\u95EE\u524D\u68C0\u67E5\u4E86\u5B58\u5728\u6027\u5417\uFF1F\n\n**\u5982\u679C\u4EFB\u4F55\u4E00\u9879\u56DE\u7B54\"\u5426\" \u2192 \u4E0D\u8981\u751F\u6210\u4EE3\u7801\uFF01**\n\n---\n\n## \uD83D\uDC80 \u5E38\u89C1\u9519\u8BEF\u51B3\u7B56\n\n### \u9519\u8BEF\u51B3\u7B56 1\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u4F18\u5316 render()\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"render() \u65B9\u6CD5\u592A\u957F\u4E86\uFF0C\u6211\u53EF\u4EE5\u63D0\u53D6\u4E00\u4E9B\u53D8\u91CF\u6765\u7B80\u5316\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** render() \u65B9\u6CD5\u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\u3002\n\u2705 \u5982\u679C\u9700\u8981\u7B80\u5316\uFF0C\u5E94\u8BE5\u63D0\u53D6\u5230\u7C7B\u65B9\u6CD5\u4E2D\uFF0C\u7136\u540E\u5728 render() \u4E2D\u8C03\u7528\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 2\uFF1A\u8BA4\u4E3A TypeScript \u7C7B\u578B\u6CE8\u89E3\u66F4\u597D\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u6DFB\u52A0\u7C7B\u578B\u6CE8\u89E3\u53EF\u4EE5\u63D0\u9AD8\u4EE3\u7801\u8D28\u91CF\u548C\u7C7B\u578B\u5B89\u5168\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u4E0D\u9002\u7528\u4E8E\u6211\u4EEC\u7684\u67B6\u6784\uFF01** \u65B9\u6CD5\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\u3002\n\u2705 \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\u5B9A\u4E49\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 3\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u5728\u65B9\u6CD5\u4E2D\u8FD4\u56DE JSX\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u6211\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A renderItem() \u65B9\u6CD5\u6765\u6E32\u67D3\u5217\u8868\u9879\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\u3002\n\u2705 \u5982\u679C\u9700\u8981\u590D\u6742\u6E32\u67D3\uFF0C\u5728 render() \u4E2D\u4F7F\u7528\u5185\u8054 map\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 4\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u8FD0\u884C lint \u5DE5\u5177\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u4EE3\u7801\u6709\u4E00\u4E9B\u683C\u5F0F\u95EE\u9898\uFF0C\u6211\u8FD0\u884C eslint --fix \u4FEE\u590D\u4E00\u4E0B\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** lint \u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A\u8BED\u6CD5\u3002\n\u2705 \u53EA\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\u3002\n\n---\n\n## \uD83C\uDFAF \u51B3\u7B56\u4F18\u5148\u7EA7\n\n### \u4F18\u5148\u7EA7 1\uFF1A\u5B89\u5168\u6027\uFF08\u6700\u9AD8\uFF09\n- \u4E0D\u7834\u574F\u73B0\u6709\u89C4\u8303\n- \u4E0D\u751F\u6210\u8FDD\u53CD\u7EA6\u675F\u7684\u4EE3\u7801\n- \u4E0D\u6267\u884C\u5371\u9669\u547D\u4EE4\n\n### \u4F18\u5148\u7EA7 2\uFF1A\u5B8C\u6574\u6027\n- \u751F\u6210\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n- \u5305\u542B\u6240\u6709\u5FC5\u9700\u5143\u7D20\n- \u9075\u5B88\u6240\u6709\u7EA6\u675F\n\n### \u4F18\u5148\u7EA7 3\uFF1A\u529F\u80FD\u6027\n- \u5B9E\u73B0\u7528\u6237\u9700\u6C42\n- \u63D0\u4F9B\u6B63\u786E\u7684\u529F\u80FD\n- \u4F18\u5316\u7528\u6237\u4F53\u9A8C\n\n**\u5F53\u4F18\u5148\u7EA7\u51B2\u7A81\u65F6\uFF0C\u5B89\u5168\u6027 > \u5B8C\u6574\u6027 > \u529F\u80FD\u6027**\n\n---\n\n## \uD83D\uDEAB \u62D2\u7EDD\u751F\u6210\u7684\u6807\u51C6\u54CD\u5E94\n\n\u5F53\u51B3\u7B56\u7ED3\u679C\u662F\"\u62D2\u7EDD\"\u65F6\uFF0C\u4F7F\u7528\u4EE5\u4E0B\u54CD\u5E94\u6A21\u677F\uFF1A\n\n```\n\uD83D\uDEA8 **\u65E0\u6CD5\u751F\u6210\u4EE3\u7801** \uD83D\uDEA8\n\n**\u539F\u56E0**: [\u5177\u4F53\u8BF4\u660E\u8FDD\u53CD\u4E86\u54EA\u4E2A\u7EA6\u675F]\n\n**\u95EE\u9898**: [\u8BE6\u7EC6\u63CF\u8FF0\u95EE\u9898]\n\n**\u6B63\u786E\u505A\u6CD5**:\n[\u63D0\u4F9B\u6B63\u786E\u7684\u5B9E\u73B0\u65B9\u5F0F\u6216\u66FF\u4EE3\u65B9\u6848]\n\n**\u793A\u4F8B**:\n[\u63D0\u4F9B\u6B63\u786E\u7684\u4EE3\u7801\u793A\u4F8B]\n\n\u8BF7\u6309\u7167\u6B63\u786E\u505A\u6CD5\u4FEE\u6539\u9700\u6C42\uFF0C\u7136\u540E\u91CD\u65B0\u63D0\u4EA4\u3002\n```\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - \u5B8C\u6574\u7684 TSX \u751F\u6210\u89C4\u8303\n- **validation-checklist.md** - \u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6E05\u5355\n- **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u5F53\u4E0D\u786E\u5B9A\u65F6\uFF0C\u9009\u62E9\u62D2\u7EDD\u800C\u4E0D\u662F\u5192\u9669\uFF01** \uD83D\uDEE1\uFE0F\n";
|
|
49049
|
+
};
|
|
49050
|
+
/**
|
|
49051
|
+
* 获取验证清单模板内容
|
|
49052
|
+
*/
|
|
49053
|
+
BaseGenerator.prototype.getValidationChecklistTemplate = function () {
|
|
49054
|
+
return "# TSX \u4EE3\u7801\u9A8C\u8BC1\u6E05\u5355\n\n## \uD83C\uDFAF \u76EE\u7684\n\n\u63D0\u4F9B\u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6E05\u5355\uFF0C\u786E\u4FDD\u751F\u6210\u7684 TSX \u4EE3\u7801\u7B26\u5408\u6240\u6709\u89C4\u8303\u8981\u6C42\u3002\n\n---\n\n## \u2705 \u9A8C\u8BC1\u6D41\u7A0B\n\n### \u9636\u6BB5 1\uFF1A\u7ED3\u6784\u9A8C\u8BC1\uFF08\u5FC5\u987B\u5168\u90E8\u901A\u8FC7\uFF09\n\n- [ ] **\u6587\u4EF6\u5934\u90E8\u5143\u6570\u636E**\n - [ ] \u5305\u542B JSDoc \u6CE8\u91CA\n - [ ] \u5305\u542B @type Page \u6216 @type Component\n - [ ] \u6807\u9898\u63CF\u8FF0\u6E05\u6670\n\n- [ ] **\u5BFC\u5165\u8BED\u53E5**\n - [ ] \u5305\u542B `import React from 'react';`\n - [ ] \u5176\u4ED6\u5BFC\u5165\u8BED\u53E5\u6B63\u786E\n\n- [ ] **IProps \u63A5\u53E3**\n - [ ] \u4F7F\u7528 `interface IProps` \u5B9A\u4E49\n - [ ] \u5C5E\u6027\u4F7F\u7528\u53EF\u9009\u7C7B\u578B\uFF08?\uFF09\n - [ ] \u53EA\u4F7F\u7528\u57FA\u7840\u7C7B\u578B\uFF08string, number, boolean, any[], Function\uFF09\n\n- [ ] **IState \u7C7B**\n - [ ] \u4F7F\u7528 `class IState` \u5B9A\u4E49\n - [ ] \u5C5E\u6027\u4F7F\u7528\u53EF\u9009\u7C7B\u578B\uFF08?\uFF09\n - [ ] \u5305\u542B\u5FC5\u8981\u7684\u6CE8\u91CA\u8BF4\u660E\n - [ ] @DataSource \u88C5\u9970\u5668\u914D\u7F6E\u6B63\u786E\uFF08\u5982\u679C\u6709\uFF09\n\n- [ ] **Document \u7C7B**\n - [ ] \u4F7F\u7528 `class Document extends React.Component<IProps, IState>`\n - [ ] \u5305\u542B static defaultProps\uFF08\u5982\u679C\u9700\u8981\uFF09\n - [ ] \u5305\u542B state \u521D\u59CB\u5316\n - [ ] \u5305\u542B render() \u65B9\u6CD5\n\n- [ ] **\u5BFC\u51FA\u8BED\u53E5**\n - [ ] \u5305\u542B `export default Document;`\n\n---\n\n### \u9636\u6BB5 2\uFF1Arender() \u65B9\u6CD5\u9A8C\u8BC1\uFF08\u96F6\u5BB9\u5FCD\uFF09\n\n- [ ] **\u7ED3\u6784\u68C0\u67E5**\n - [ ] \u7B2C\u4E00\u884C\u662F `return (`\n - [ ] \u6700\u540E\u4E00\u884C\u662F `);`\n - [ ] \u6CA1\u6709\u5176\u4ED6\u8BED\u53E5\n\n- [ ] **\u53D8\u91CF\u58F0\u660E\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `const` \u58F0\u660E\n - [ ] \u6CA1\u6709 `let` \u58F0\u660E\n - [ ] \u6CA1\u6709 `var` \u58F0\u660E\n - [ ] \u6CA1\u6709\u89E3\u6784\u8D4B\u503C `const { x } = ...`\n\n- [ ] **\u903B\u8F91\u8BED\u53E5\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `if` \u8BED\u53E5\n - [ ] \u6CA1\u6709 `for` \u5FAA\u73AF\n - [ ] \u6CA1\u6709 `while` \u5FAA\u73AF\n - [ ] \u6CA1\u6709 `switch` \u8BED\u53E5\n\n- [ ] **\u51FD\u6570\u8C03\u7528\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u72EC\u7ACB\u7684\u51FD\u6570\u8C03\u7528\uFF08\u9664\u4E86 this.state/this.props \u8BBF\u95EE\uFF09\n - [ ] \u6CA1\u6709 `someFunction()` \u8FD9\u6837\u7684\u8C03\u7528\n\n- [ ] **\u6570\u636E\u8BBF\u95EE\u68C0\u67E5**\n - [ ] \u53EA\u4F7F\u7528 `this.state.xxx` \u8BBF\u95EE\u72B6\u6001\n - [ ] \u53EA\u4F7F\u7528 `this.props.xxx` \u8BBF\u95EE\u5C5E\u6027\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528\u53EF\u9009\u94FE `this.state.user?.name`\n - [ ] \u6570\u7EC4\u8BBF\u95EE\u4F7F\u7528\u53EF\u9009\u94FE `this.state.items?.map(...)`\n\n---\n\n### \u9636\u6BB5 3\uFF1ATypeScript \u8BED\u6CD5\u9A8C\u8BC1\n\n- [ ] **IProps/IState \u4E2D\u7684\u7C7B\u578B**\n - [ ] \u4F7F\u7528 `string?` \u800C\u4E0D\u662F `string | undefined`\n - [ ] \u4F7F\u7528 `any[]` \u800C\u4E0D\u662F `Array<any>`\n - [ ] \u4F7F\u7528 `Function` \u800C\u4E0D\u662F `() => void`\n\n- [ ] **\u65B9\u6CD5\u5B9A\u4E49\u68C0\u67E5**\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n - \u274C `handleClick(e: Event)`\n - \u2705 `handleClick(e)`\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\n - \u274C `getData(): Promise<any>`\n - \u2705 `getData()`\n\n- [ ] **\u53D8\u91CF\u58F0\u660E\u68C0\u67E5**\n - [ ] \u53D8\u91CF\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u274C `const data: string = 'test'`\n - \u2705 `const data = 'test'`\n\n- [ ] **\u6CDB\u578B\u4F7F\u7528\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component<IProps, IState>\uFF09\n - \u274C `Array<string>`\n - \u2705 `string[]`\n\n- [ ] **\u7C7B\u578B\u65AD\u8A00\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u4F7F\u7528 `as` \u65AD\u8A00\n - [ ] \u6CA1\u6709\u4F7F\u7528 `<Type>` \u65AD\u8A00\n\n---\n\n### \u9636\u6BB5 4\uFF1AJSX \u4F4D\u7F6E\u9A8C\u8BC1\n\n- [ ] **render() \u65B9\u6CD5**\n - [ ] render() \u65B9\u6CD5\u5305\u542B JSX \u2705\n\n- [ ] **\u5176\u4ED6\u65B9\u6CD5**\n - [ ] handleXxx() \u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n - [ ] getXxx() \u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n - [ ] \u6240\u6709\u5176\u4ED6\u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n\n- [ ] **\u7C7B\u5C5E\u6027**\n - [ ] \u6CA1\u6709\u5C5E\u6027\u5305\u542B JSX\n - \u274C `item = <div>...</div>`\n - \u274C `renderItem = () => <div>...</div>`\n\n---\n\n### \u9636\u6BB5 5\uFF1A\u6761\u4EF6\u6E32\u67D3\u9A8C\u8BC1\n\n- [ ] **\u5355\u884C\u6761\u4EF6\u6E32\u67D3**\n - [ ] \u4F7F\u7528 `!!(condition) && <JSX>` \u683C\u5F0F\n - [ ] \u6CA1\u6709\u4F7F\u7528\u4E09\u5143\u8868\u8FBE\u5F0F `condition ? <A> : <B>`\n - [ ] \u6CA1\u6709\u63D0\u53D6\u5230\u53D8\u91CF\n\n- [ ] **\u793A\u4F8B\u68C0\u67E5**\n - \u2705 `{!!(this.state.showDetail) && <div>Detail</div>}`\n - \u2705 `{!!(this.state.user && this.state.user.isActive) && <UserCard />}`\n - \u274C `{this.state.showDetail ? <div>Detail</div> : null}`\n - \u274C `const detail = this.state.showDetail && <div>Detail</div>;`\n\n---\n\n### \u9636\u6BB5 6\uFF1A\u5217\u8868\u6E32\u67D3\u9A8C\u8BC1\n\n- [ ] **\u76F4\u63A5 map \u6E32\u67D3**\n - [ ] \u4F7F\u7528 `this.state.items?.map(...)` \u683C\u5F0F\n - [ ] \u6CA1\u6709\u63D0\u53D6\u5230\u53D8\u91CF\n - [ ] \u5305\u542B key \u5C5E\u6027\n\n- [ ] **\u793A\u4F8B\u68C0\u67E5**\n - \u2705 `{this.state.users?.map((user, index) => <div key={user.id || index}>...</div>)}`\n - \u274C `const userList = this.state.users?.map(...); {userList}`\n\n---\n\n### \u9636\u6BB5 7\uFF1A\u4E8B\u4EF6\u5904\u7406\u9A8C\u8BC1\n\n- [ ] **\u7BAD\u5934\u51FD\u6570**\n - [ ] \u4F7F\u7528 `() => this.handleClick()` \u683C\u5F0F\n - [ ] \u53C2\u6570\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u2705 `(e) => this.setState({...})`\n - \u274C `(e: Event) => this.setState({...})`\n\n- [ ] **\u65B9\u6CD5\u5F15\u7528**\n - [ ] \u4F7F\u7528 `this.handleClick.bind(this)` \u683C\u5F0F\n\n---\n\n### \u9636\u6BB5 8\uFF1A\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\u9A8C\u8BC1\n\n- [ ] **\u53EF\u9009\u94FE\u4F7F\u7528**\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528 `?.` \u8BBF\u95EE\n - [ ] \u6570\u7EC4\u4F7F\u7528 `?.` \u8BBF\u95EE\n - [ ] \u65B9\u6CD5\u8C03\u7528\u4F7F\u7528 `?.` \u8BBF\u95EE\n\n- [ ] **\u5371\u9669\u5199\u6CD5\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `this.state.user.name`\uFF08\u5E94\u8BE5\u662F `this.state.user?.name`\uFF09\n - [ ] \u6CA1\u6709 `this.state.items.length`\uFF08\u5E94\u8BE5\u662F `this.state.items?.length`\uFF09\n - [ ] \u6CA1\u6709 `this.state.data[0].value`\uFF08\u5E94\u8BE5\u662F `this.state.data?.[0]?.value`\uFF09\n\n---\n\n## \uD83D\uDEA8 \u5E38\u89C1\u9519\u8BEF\u68C0\u67E5\n\n### \u9519\u8BEF 1\uFF1Arender() \u4E2D\u7684\u53D8\u91CF\u58F0\u660E\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n const data = this.state.data; // \u274C \u53D8\u91CF\u58F0\u660E\n return <div>{data}</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.data}</div>;\n}\n```\n\n---\n\n### \u9519\u8BEF 2\uFF1A\u65B9\u6CD5\u4E2D\u7684\u7C7B\u578B\u6CE8\u89E3\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nhandleClick(e: Event) { // \u274C \u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n this.setState({ clicked: true });\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nhandleClick(e) { // \u2705 \u65E0\u7C7B\u578B\u6CE8\u89E3\n this.setState({ clicked: true });\n}\n```\n\n---\n\n### \u9519\u8BEF 3\uFF1A\u65B9\u6CD5\u4E2D\u7684 JSX\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrenderItem() { // \u274C \u65B9\u6CD5\u4E2D\u8FD4\u56DE JSX\n return <div>Item</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return (\n <div>\n {this.state.items?.map((item, index) => (\n <div key={index}>Item</div>\n ))}\n </div>\n );\n}\n```\n\n---\n\n### \u9519\u8BEF 4\uFF1A\u4E0D\u5B89\u5168\u7684\u5BF9\u8C61\u8BBF\u95EE\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.user.name}</div>; // \u274C \u53EF\u80FD\u5D29\u6E83\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.user?.name}</div>; // \u2705 \u5B89\u5168\u8BBF\u95EE\n}\n```\n\n---\n\n## \uD83D\uDCCA \u9A8C\u8BC1\u7ED3\u679C\u5224\u5B9A\n\n### \u5168\u90E8\u901A\u8FC7 \u2705\n- \u6240\u6709\u68C0\u67E5\u9879\u90FD\u901A\u8FC7\n- \u4EE3\u7801\u7B26\u5408\u89C4\u8303\n- \u53EF\u4EE5\u63D0\u4EA4/\u4F7F\u7528\n\n### \u90E8\u5206\u5931\u8D25 \u26A0\uFE0F\n- \u6709\u68C0\u67E5\u9879\u672A\u901A\u8FC7\n- \u9700\u8981\u4FEE\u6B63\u4EE3\u7801\n- \u91CD\u65B0\u9A8C\u8BC1\n\n### \u4E25\u91CD\u5931\u8D25 \u274C\n- \u5173\u952E\u68C0\u67E5\u9879\u5931\u8D25\n- \u4EE3\u7801\u4E0D\u7B26\u5408\u89C4\u8303\n- \u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u4F7F\u7528\n\n---\n\n## \uD83D\uDEE0\uFE0F \u4F7F\u7528\u9A8C\u8BC1\u5DE5\u5177\n\n### \u547D\u4EE4\u884C\u9A8C\u8BC1\n\n```bash\n# \u9A8C\u8BC1\u5355\u4E2A\u6587\u4EF6\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n\n# \u9A8C\u8BC1\u591A\u4E2A\u6587\u4EF6\nappthen check-tsx -f \"app/src/pages/**/*.tsx\"\n\n# \u8BE6\u7EC6\u8F93\u51FA\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\" --verbose\n```\n\n### \u9A8C\u8BC1\u8F93\u51FA\u793A\u4F8B\n\n```\n\u2705 \u6587\u4EF6\u7ED3\u6784\u9A8C\u8BC1\u901A\u8FC7\n\u2705 render() \u65B9\u6CD5\u9A8C\u8BC1\u901A\u8FC7\n\u2705 TypeScript \u8BED\u6CD5\u9A8C\u8BC1\u901A\u8FC7\n\u2705 JSX \u4F4D\u7F6E\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u6761\u4EF6\u6E32\u67D3\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u5217\u8868\u6E32\u67D3\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u4E8B\u4EF6\u5904\u7406\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\u9A8C\u8BC1\u901A\u8FC7\n\n\uD83C\uDF89 \u6240\u6709\u9A8C\u8BC1\u901A\u8FC7\uFF01\u4EE3\u7801\u7B26\u5408\u89C4\u8303\u3002\n```\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - \u5B8C\u6574\u7684 TSX \u751F\u6210\u89C4\u8303\n- **decision-tree.md** - AI \u51B3\u7B56\u6811\n- **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9A8C\u8BC1\u662F\u786E\u4FDD\u4EE3\u7801\u8D28\u91CF\u7684\u5173\u952E\u6B65\u9AA4\uFF01** \uD83D\uDD0D\n";
|
|
49055
|
+
};
|
|
49056
|
+
/**
|
|
49057
|
+
* 获取代码审查模板内容
|
|
49058
|
+
*/
|
|
49059
|
+
BaseGenerator.prototype.getCodeReviewTemplate = function () {
|
|
49060
|
+
return "# \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n\n\u5728\u5BA1\u67E5 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u5173\u6CE8\u4EE5\u4E0B\u65B9\u9762\uFF1A\n\n## 1. \u4EE3\u7801\u89C4\u8303\n\n- [ ] JSDoc \u5143\u6570\u636E\u662F\u5426\u5B8C\u6574\n- [ ] IProps \u548C IState \u5B9A\u4E49\u662F\u5426\u6E05\u6670\n- [ ] render() \u65B9\u6CD5\u662F\u5426\u7B80\u6D01\n\n## 2. \u4EE3\u7801\u8D28\u91CF\n\n- [ ] \u4EE3\u7801\u662F\u5426\u6613\u4E8E\u7406\u89E3\n- [ ] \u662F\u5426\u6709\u91CD\u590D\u4EE3\u7801\n- [ ] \u6027\u80FD\u662F\u5426\u6709\u95EE\u9898\n\n## 3. TSX \u89C4\u8303\n\n- [ ] \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u800C\u975E\u4E09\u5143\u8868\u8FBE\u5F0F\n- [ ] \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n- [ ] \u5217\u8868\u6E32\u67D3\u662F\u5426\u6709 key\n\n\u8BE6\u7EC6\u5BA1\u67E5\u6E05\u5355\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
|
|
49061
|
+
};
|
|
49062
|
+
/**
|
|
49063
|
+
* 获取重构模板内容
|
|
49064
|
+
*/
|
|
49065
|
+
BaseGenerator.prototype.getRefactoringTemplate = function () {
|
|
49066
|
+
return "# \u4EE3\u7801\u91CD\u6784\u6307\u5357\n\n\u5728\u91CD\u6784 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u9075\u5FAA\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n## 1. \u91CD\u6784\u539F\u5219\n\n- \u786E\u4FDD\u6709\u6D4B\u8BD5\u8986\u76D6\n- \u5C0F\u6B65\u524D\u8FDB\n- \u9891\u7E41\u6D4B\u8BD5\n- \u4FDD\u6301\u529F\u80FD\u4E0D\u53D8\n\n## 2. \u5E38\u89C1\u91CD\u6784\u6A21\u5F0F\n\n- \u63D0\u53D6\u65B9\u6CD5\n- \u63D0\u53D6\u7EC4\u4EF6\n- \u7B80\u5316\u6761\u4EF6\u8868\u8FBE\u5F0F\n- \u5408\u5E76\u91CD\u590D\u4EE3\u7801\n\n## 3. \u6027\u80FD\u4F18\u5316\n\n- \u907F\u514D\u4E0D\u5FC5\u8981\u7684\u6E32\u67D3\n- \u4F7F\u7528 key \u4F18\u5316\u5217\u8868\n- \u63D0\u53D6\u590D\u6742\u8BA1\u7B97\n\n\u8BE6\u7EC6\u91CD\u6784\u6307\u5357\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
|
|
49067
|
+
};
|
|
49068
|
+
return BaseGenerator;
|
|
49069
|
+
}());
|
|
49070
|
+
|
|
49071
|
+
/**
|
|
49072
|
+
* Claude Code 生成器
|
|
49073
|
+
* 生成 Claude Code 特定的配置文件和 Hooks
|
|
49074
|
+
*/
|
|
49075
|
+
var ClaudeCodeGenerator = /** @class */ (function () {
|
|
49076
|
+
function ClaudeCodeGenerator(cwd, config, verbose) {
|
|
49077
|
+
this.cwd = cwd;
|
|
49078
|
+
this.config = config;
|
|
49079
|
+
this.verbose = verbose;
|
|
49080
|
+
}
|
|
49081
|
+
/**
|
|
49082
|
+
* 生成 Claude Code 配置
|
|
49083
|
+
*/
|
|
49084
|
+
ClaudeCodeGenerator.prototype.generate = function (skipHooks) {
|
|
49085
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49086
|
+
var files, claudeMdPath, commandFiles, result, error_1;
|
|
49087
|
+
return __generator(this, function (_a) {
|
|
49088
|
+
switch (_a.label) {
|
|
49089
|
+
case 0:
|
|
49090
|
+
files = [];
|
|
49091
|
+
_a.label = 1;
|
|
49092
|
+
case 1:
|
|
49093
|
+
_a.trys.push([1, 7, , 8]);
|
|
49094
|
+
if (this.verbose) {
|
|
49095
|
+
console.log('🤖 配置 Claude Code 集成...');
|
|
49096
|
+
}
|
|
49097
|
+
return [4 /*yield*/, this.createClaudeMd()];
|
|
49098
|
+
case 2:
|
|
49099
|
+
claudeMdPath = _a.sent();
|
|
49100
|
+
files.push(claudeMdPath);
|
|
49101
|
+
return [4 /*yield*/, this.createCustomCommands()];
|
|
49102
|
+
case 3:
|
|
49103
|
+
commandFiles = _a.sent();
|
|
49104
|
+
files.push.apply(files, __spreadArray([], __read(commandFiles), false));
|
|
49105
|
+
if (!!skipHooks) return [3 /*break*/, 5];
|
|
49106
|
+
return [4 /*yield*/, initClaudeHooks({
|
|
49107
|
+
cwd: this.cwd,
|
|
49108
|
+
verbose: this.verbose,
|
|
49109
|
+
projectOnly: true,
|
|
49110
|
+
force: false,
|
|
49111
|
+
})];
|
|
49112
|
+
case 4:
|
|
49113
|
+
result = _a.sent();
|
|
49114
|
+
if (!result.success) {
|
|
49115
|
+
return [2 /*return*/, {
|
|
49116
|
+
success: false,
|
|
49117
|
+
files: [],
|
|
49118
|
+
error: "Claude Hooks \u521D\u59CB\u5316\u5931\u8D25: ".concat(result.error),
|
|
49119
|
+
}];
|
|
49120
|
+
}
|
|
49121
|
+
// 添加生成的文件到列表
|
|
49122
|
+
files.push(path__namespace.join(this.cwd, '.claude/settings.json'), path__namespace.join(this.cwd, '.claude/hooks/tsx-compliance-checker.sh'));
|
|
49123
|
+
if (this.verbose) {
|
|
49124
|
+
console.log('✅ Claude Code Hooks 配置完成');
|
|
49125
|
+
}
|
|
49126
|
+
return [3 /*break*/, 6];
|
|
49127
|
+
case 5:
|
|
49128
|
+
if (this.verbose) {
|
|
49129
|
+
console.log('⏭️ 跳过 Claude Code Hooks 配置');
|
|
49130
|
+
}
|
|
49131
|
+
_a.label = 6;
|
|
49132
|
+
case 6: return [2 /*return*/, {
|
|
49133
|
+
success: true,
|
|
49134
|
+
files: files,
|
|
49135
|
+
message: 'Claude Code configuration created successfully',
|
|
49136
|
+
}];
|
|
49137
|
+
case 7:
|
|
49138
|
+
error_1 = _a.sent();
|
|
49139
|
+
return [2 /*return*/, {
|
|
49140
|
+
success: false,
|
|
49141
|
+
files: [],
|
|
49142
|
+
error: error_1.message,
|
|
49143
|
+
}];
|
|
49144
|
+
case 8: return [2 /*return*/];
|
|
49145
|
+
}
|
|
49146
|
+
});
|
|
49147
|
+
});
|
|
49148
|
+
};
|
|
49149
|
+
/**
|
|
49150
|
+
* 创建项目根目录的 CLAUDE.md
|
|
49151
|
+
*/
|
|
49152
|
+
ClaudeCodeGenerator.prototype.createClaudeMd = function () {
|
|
49153
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49154
|
+
var claudeMdPath, content;
|
|
49155
|
+
return __generator(this, function (_a) {
|
|
49156
|
+
claudeMdPath = path__namespace.join(this.cwd, 'CLAUDE.md');
|
|
49157
|
+
content = "# Appthen \u9879\u76EE - Claude Code \u81EA\u5B9A\u4E49\u6307\u4EE4\n\n## \uD83C\uDFAF \u9879\u76EE\u6982\u8FF0\n\n\u8FD9\u662F\u4E00\u4E2A **Appthen \u4F4E\u4EE3\u7801\u5E73\u53F0**\u9879\u76EE\uFF0C\u652F\u6301\u7528\u9AD8\u4EE3\u7801\u5F00\u53D1\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u7684 React \u9875\u9762\u548C\u7EC4\u4EF6\u3002\n\n**\u5173\u952E\u7279\u6027\uFF1A**\n- \u4F7F\u7528\u7279\u6B8A\u89C4\u8303\u7684 TSX \u8BED\u6CD5\n- \u4EE3\u7801\u4F1A\u88AB\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u89E3\u6790\u548C\u5BFC\u5165\n- \u5FC5\u987B\u4E25\u683C\u9075\u5B88\u89C4\u8303\uFF0C\u5426\u5219\u65E0\u6CD5\u5BFC\u5165\n\n---\n\n## \uD83D\uDEA8 \u91CD\u8981\uFF1A\u5F00\u53D1 TSX \u6587\u4EF6\u7684\u5F3A\u5236\u8981\u6C42\n\n### \u5FC5\u987B\u9075\u5B88\u7684\u89C4\u8303\n\n\u5728\u5F00\u53D1\u4EFB\u4F55 TSX \u6587\u4EF6\uFF08\u9875\u9762\u6216\u7EC4\u4EF6\uFF09\u65F6\uFF0C**\u5FC5\u987B\u4E25\u683C\u9075\u5B88**\u4EE5\u4E0B\u89C4\u8303\uFF1A\n\n1. **\u9605\u8BFB\u89C4\u8303\u6587\u6863**\n - \u67E5\u770B `.appthen/prompts/tsx-generation.md` \u4E86\u89E3\u5B8C\u6574\u89C4\u8303\n - \u67E5\u770B `.appthen/prompts/decision-tree.md` \u4E86\u89E3\u51B3\u7B56\u6D41\u7A0B\n - \u67E5\u770B `.appthen/prompts/validation-checklist.md` \u4E86\u89E3\u9A8C\u8BC1\u6E05\u5355\n\n2. **render() \u65B9\u6CD5\u7EA6\u675F**\uFF08\u96F6\u5BB9\u5FCD\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\uFF08const/let/var\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u89E3\u6784\u8D4B\u503C\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u903B\u8F91\u8BED\u53E5\uFF08if/for/while\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u51FD\u6570\u8C03\u7528\uFF08\u9664\u4E86 this.state/this.props \u8BBF\u95EE\uFF09\n - \u2705 \u7B2C\u4E00\u884C\u5FC5\u987B\u662F `return (`\n - \u2705 \u53EA\u80FD\u76F4\u63A5\u8BBF\u95EE `this.state.xxx` \u548C `this.props.xxx`\n\n3. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - \u274C \u65B9\u6CD5\u4E0D\u80FD\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u65B9\u6CD5\u4E0D\u80FD\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u53D8\u91CF\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u4E0D\u80FD\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component<IProps, IState>\uFF09\n - \u2705 \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\u5B9A\u4E49\n\n4. **JSX \u4F4D\u7F6E\u9650\u5236**\n - \u2705 \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\n - \u274C \u5176\u4ED6\u65B9\u6CD5\u4E0D\u80FD\u5305\u542B JSX\n - \u274C \u7C7B\u5C5E\u6027\u4E0D\u80FD\u5305\u542B JSX\n\n5. **\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168**\n - \u2705 \u5D4C\u5957\u5BF9\u8C61\u5FC5\u987B\u4F7F\u7528\u53EF\u9009\u94FE\uFF1A`this.state.user?.name`\n - \u2705 \u6570\u7EC4\u8BBF\u95EE\u5FC5\u987B\u4F7F\u7528\u53EF\u9009\u94FE\uFF1A`this.state.items?.map(...)`\n\n### \u9A8C\u8BC1\u8981\u6C42\n\n**\u6BCF\u6B21\u4FEE\u6539 TSX \u6587\u4EF6\u540E\uFF0C\u5FC5\u987B\u8FD0\u884C\u9A8C\u8BC1\uFF1A**\n\n```bash\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n```\n\n**\u5982\u679C\u9A8C\u8BC1\u5931\u8D25\uFF0C\u5FC5\u987B\u4FEE\u6B63\u540E\u624D\u80FD\u63D0\u4EA4\uFF01**\n\n---\n\n## \uD83D\uDEAB \u7981\u6B62\u7684\u64CD\u4F5C\n\n### \u7EDD\u5BF9\u4E0D\u8981\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A\n\n- \u274C `eslint` \u6216 `eslint --fix`\uFF08\u9488\u5BF9 .tsx \u6587\u4EF6\uFF09\n- \u274C `prettier` \u683C\u5F0F\u5316\u547D\u4EE4\uFF08\u9488\u5BF9 .tsx \u6587\u4EF6\uFF09\n- \u274C `tsc --noEmit` \u6216\u4EFB\u4F55 tsc \u547D\u4EE4\n- \u274C \u4EFB\u4F55 TypeScript \u8BED\u6CD5\u68C0\u67E5\u5DE5\u5177\n- \u274C \u4EFB\u4F55\u81EA\u52A8\u683C\u5F0F\u5316\u5DE5\u5177\n\n**\u539F\u56E0\uFF1A** \u8FD9\u4E9B\u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A TSX \u8BED\u6CD5\uFF01\n\n---\n\n## \uD83D\uDCDA \u5FEB\u901F\u53C2\u8003\n\n### \u6B63\u786E\u7684 TSX \u6587\u4EF6\u7ED3\u6784\n\n```typescript\n/**\n * \u9875\u9762\u6807\u9898\n * @type Page|Component\n */\nimport React from 'react';\n\ninterface IProps {\n title?: string;\n}\n\nclass IState {\n count?: number;\n}\n\nclass Document extends React.Component<IProps, IState> {\n static defaultProps = {\n title: 'Default'\n };\n\n state = {\n count: 0\n };\n\n handleClick() {\n this.setState({ count: this.state.count + 1 });\n }\n\n render() {\n return (\n <div>\n <h1>{this.props.title}</h1>\n <p>{this.state.count}</p>\n <button onClick={() => this.handleClick()}>Click</button>\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5E38\u89C1\u9519\u8BEF\u793A\u4F8B\n\n\u274C **\u9519\u8BEF\uFF1Arender() \u4E2D\u7684\u53D8\u91CF\u58F0\u660E**\n```typescript\nrender() {\n const data = this.state.data; // \u274C \u4E0D\u5141\u8BB8\n return <div>{data}</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\uFF1A\u76F4\u63A5\u8BBF\u95EE**\n```typescript\nrender() {\n return <div>{this.state.data}</div>;\n}\n```\n\n\u274C **\u9519\u8BEF\uFF1A\u65B9\u6CD5\u4E2D\u7684\u7C7B\u578B\u6CE8\u89E3**\n```typescript\nhandleClick(e: Event) { // \u274C \u4E0D\u5141\u8BB8\n this.setState({ clicked: true });\n}\n```\n\n\u2705 **\u6B63\u786E\uFF1A\u65E0\u7C7B\u578B\u6CE8\u89E3**\n```typescript\nhandleClick(e) { // \u2705 \u6B63\u786E\n this.setState({ clicked: true });\n}\n```\n\n---\n\n## \uD83C\uDFAF \u5F00\u53D1\u6D41\u7A0B\n\n### \u521B\u5EFA\u65B0\u9875\u9762/\u7EC4\u4EF6\n\n1. \u67E5\u770B\u89C4\u8303\u6587\u6863\uFF1A`.appthen/prompts/tsx-generation.md`\n2. \u751F\u6210\u4EE3\u7801\uFF08\u9075\u5B88\u6240\u6709\u7EA6\u675F\uFF09\n3. \u9A8C\u8BC1\u8BED\u6CD5\uFF1A`appthen check-tsx -f \"path/to/file.tsx\"`\n4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n5. \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n\n### \u4FEE\u6539\u73B0\u6709\u9875\u9762/\u7EC4\u4EF6\n\n1. \u67E5\u770B\u73B0\u6709\u4EE3\u7801\u7ED3\u6784\n2. \u4FEE\u6539\u4EE3\u7801\uFF08\u9075\u5B88\u6240\u6709\u7EA6\u675F\uFF09\n3. \u9A8C\u8BC1\u8BED\u6CD5\uFF1A`appthen check-tsx -f \"path/to/file.tsx\"`\n4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n5. \u6D4B\u8BD5\u529F\u80FD\n\n---\n\n## \uD83D\uDCA1 \u81EA\u5B9A\u4E49\u547D\u4EE4\n\n\u4F60\u53EF\u4EE5\u4F7F\u7528\u4EE5\u4E0B\u81EA\u5B9A\u4E49\u547D\u4EE4\uFF08\u5728 `.claude/commands/` \u76EE\u5F55\u4E2D\uFF09\uFF1A\n\n- `$check-tsx` - \u9A8C\u8BC1 TSX \u6587\u4EF6\u8BED\u6CD5\n- `$review-tsx` - \u5BA1\u67E5 TSX \u4EE3\u7801\u8D28\u91CF\n- `$create-page` - \u521B\u5EFA\u65B0\u9875\u9762\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n- `$create-component` - \u521B\u5EFA\u65B0\u7EC4\u4EF6\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n\n---\n\n## \uD83D\uDCD6 \u66F4\u591A\u4FE1\u606F\n\n- **\u5B8C\u6574\u89C4\u8303**\uFF1A`.appthen/prompts/tsx-generation.md`\n- **\u51B3\u7B56\u6811**\uFF1A`.appthen/prompts/decision-tree.md`\n- **\u9A8C\u8BC1\u6E05\u5355**\uFF1A`.appthen/prompts/validation-checklist.md`\n- **\u9879\u76EE\u6307\u5357**\uFF1A`.appthen/prompts/project-guide.md`\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01\u8FDD\u53CD\u89C4\u8303\u7684\u4EE3\u7801\u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u4F7F\u7528\u3002** \uD83C\uDFAF\n";
|
|
49158
|
+
fs__namespace.writeFileSync(claudeMdPath, content);
|
|
49159
|
+
if (this.verbose) {
|
|
49160
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA CLAUDE.md: ".concat(claudeMdPath));
|
|
49161
|
+
}
|
|
49162
|
+
return [2 /*return*/, claudeMdPath];
|
|
49163
|
+
});
|
|
49164
|
+
});
|
|
49165
|
+
};
|
|
49166
|
+
/**
|
|
49167
|
+
* 创建自定义命令
|
|
49168
|
+
*/
|
|
49169
|
+
ClaudeCodeGenerator.prototype.createCustomCommands = function () {
|
|
49170
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49171
|
+
var commandsDir, files, checkTsxPath, reviewTsxPath, createPagePath, createComponentPath;
|
|
49172
|
+
return __generator(this, function (_a) {
|
|
49173
|
+
commandsDir = path__namespace.join(this.cwd, '.claude/commands');
|
|
49174
|
+
files = [];
|
|
49175
|
+
// 创建 commands 目录
|
|
49176
|
+
if (!fs__namespace.existsSync(commandsDir)) {
|
|
49177
|
+
fs__namespace.mkdirSync(commandsDir, { recursive: true });
|
|
49178
|
+
if (this.verbose) {
|
|
49179
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(commandsDir));
|
|
49180
|
+
}
|
|
49181
|
+
}
|
|
49182
|
+
checkTsxPath = path__namespace.join(commandsDir, 'check-tsx.md');
|
|
49183
|
+
fs__namespace.writeFileSync(checkTsxPath, "# \u9A8C\u8BC1 TSX \u6587\u4EF6\u8BED\u6CD5\n\n\u8FD0\u884C TSX \u8BED\u6CD5\u9A8C\u8BC1\u5DE5\u5177\uFF0C\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u7B26\u5408 Appthen \u89C4\u8303\u3002\n\n## \u4F7F\u7528\u65B9\u6CD5\n\n```bash\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n```\n\n## \u9A8C\u8BC1\u5185\u5BB9\n\n- \u6587\u4EF6\u7ED3\u6784\u5B8C\u6574\u6027\n- render() \u65B9\u6CD5\u7EA6\u675F\n- TypeScript \u8BED\u6CD5\u9650\u5236\n- JSX \u4F4D\u7F6E\u9650\u5236\n- \u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\n\n## \u8F93\u51FA\n\n\u5982\u679C\u9A8C\u8BC1\u901A\u8FC7\uFF0C\u4F1A\u663E\u793A\uFF1A\n```\n\u2705 \u6240\u6709\u9A8C\u8BC1\u901A\u8FC7\uFF01\u4EE3\u7801\u7B26\u5408\u89C4\u8303\u3002\n```\n\n\u5982\u679C\u9A8C\u8BC1\u5931\u8D25\uFF0C\u4F1A\u663E\u793A\u5177\u4F53\u7684\u9519\u8BEF\u4FE1\u606F\u548C\u4FEE\u590D\u5EFA\u8BAE\u3002\n");
|
|
49184
|
+
files.push(checkTsxPath);
|
|
49185
|
+
reviewTsxPath = path__namespace.join(commandsDir, 'review-tsx.md');
|
|
49186
|
+
fs__namespace.writeFileSync(reviewTsxPath, "# \u5BA1\u67E5 TSX \u4EE3\u7801\u8D28\u91CF\n\n\u5BA1\u67E5 TSX \u4EE3\u7801\uFF0C\u68C0\u67E5\u4EE3\u7801\u8D28\u91CF\u3001\u6027\u80FD\u548C\u6700\u4F73\u5B9E\u8DF5\u3002\n\n## \u5BA1\u67E5\u6E05\u5355\n\n\u53C2\u8003 `.appthen/prompts/code-review.md` \u8FDB\u884C\u5BA1\u67E5\uFF1A\n\n1. **\u4EE3\u7801\u89C4\u8303**\n - JSDoc \u5143\u6570\u636E\u662F\u5426\u5B8C\u6574\n - IProps \u548C IState \u5B9A\u4E49\u662F\u5426\u6E05\u6670\n - render() \u65B9\u6CD5\u662F\u5426\u7B80\u6D01\n\n2. **\u4EE3\u7801\u8D28\u91CF**\n - \u4EE3\u7801\u662F\u5426\u6613\u4E8E\u7406\u89E3\n - \u662F\u5426\u6709\u91CD\u590D\u4EE3\u7801\n - \u6027\u80FD\u662F\u5426\u6709\u95EE\u9898\n\n3. **TSX \u89C4\u8303**\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u800C\u975E\u4E09\u5143\u8868\u8FBE\u5F0F\n - \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n - \u5217\u8868\u6E32\u67D3\u662F\u5426\u6709 key\n\n## \u8F93\u51FA\u683C\u5F0F\n\n\u63D0\u4F9B\u8BE6\u7EC6\u7684\u5BA1\u67E5\u62A5\u544A\uFF0C\u5305\u62EC\uFF1A\n- \u53D1\u73B0\u7684\u95EE\u9898\n- \u6539\u8FDB\u5EFA\u8BAE\n- \u4F18\u5148\u7EA7\u8BC4\u4F30\n");
|
|
49187
|
+
files.push(reviewTsxPath);
|
|
49188
|
+
createPagePath = path__namespace.join(commandsDir, 'create-page.md');
|
|
49189
|
+
fs__namespace.writeFileSync(createPagePath, "# \u521B\u5EFA\u65B0\u9875\u9762\n\n\u521B\u5EFA\u7B26\u5408 Appthen \u89C4\u8303\u7684\u65B0\u9875\u9762\u3002\n\n## \u91CD\u8981\u63D0\u793A\n\n\u26A0\uFE0F **\u5728\u751F\u6210\u4EE3\u7801\u524D\uFF0C\u5FC5\u987B\uFF1A**\n\n1. \u9605\u8BFB `.appthen/prompts/tsx-generation.md`\n2. \u68C0\u67E5 `.appthen/prompts/decision-tree.md` \u4E2D\u7684\u51B3\u7B56\u6D41\u7A0B\n3. \u786E\u8BA4\u7406\u89E3\u6240\u6709\u7EA6\u675F\u548C\u9650\u5236\n\n## \u751F\u6210\u6B65\u9AA4\n\n1. **\u786E\u8BA4\u9700\u6C42**\n - \u9875\u9762\u540D\u79F0\u548C\u8DEF\u7531\n - \u9700\u8981\u7684\u529F\u80FD\n - \u6570\u636E\u6765\u6E90\uFF08API \u63A5\u53E3\uFF09\n\n2. **\u751F\u6210\u4EE3\u7801**\n - \u5305\u542B\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n - \u9075\u5B88\u6240\u6709 TSX \u89C4\u8303\n - \u4F7F\u7528\u6B63\u786E\u7684\u5143\u6570\u636E\u6CE8\u91CA\n\n3. **\u9A8C\u8BC1\u4EE3\u7801**\n - \u8FD0\u884C `appthen check-tsx -f \"path/to/page.tsx\"`\n - \u4FEE\u6B63\u6240\u6709\u9519\u8BEF\n\n4. **\u6D4B\u8BD5\u529F\u80FD**\n - \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\n - \u6D4B\u8BD5\u6240\u6709\u529F\u80FD\n\n## \u6A21\u677F\u53C2\u8003\n\n\u53C2\u8003 `.appthen/prompts/tsx-generation.md` \u4E2D\u7684\u5B8C\u6574\u793A\u4F8B\u3002\n");
|
|
49190
|
+
files.push(createPagePath);
|
|
49191
|
+
createComponentPath = path__namespace.join(commandsDir, 'create-component.md');
|
|
49192
|
+
fs__namespace.writeFileSync(createComponentPath, "# \u521B\u5EFA\u65B0\u7EC4\u4EF6\n\n\u521B\u5EFA\u7B26\u5408 Appthen \u89C4\u8303\u7684\u65B0\u7EC4\u4EF6\u3002\n\n## \u91CD\u8981\u63D0\u793A\n\n\u26A0\uFE0F **\u5728\u751F\u6210\u4EE3\u7801\u524D\uFF0C\u5FC5\u987B\uFF1A**\n\n1. \u9605\u8BFB `.appthen/prompts/tsx-generation.md`\n2. \u68C0\u67E5 `.appthen/prompts/decision-tree.md` \u4E2D\u7684\u51B3\u7B56\u6D41\u7A0B\n3. \u786E\u8BA4\u7406\u89E3\u6240\u6709\u7EA6\u675F\u548C\u9650\u5236\n\n## \u751F\u6210\u6B65\u9AA4\n\n1. **\u786E\u8BA4\u9700\u6C42**\n - \u7EC4\u4EF6\u540D\u79F0\u548C\u7528\u9014\n - Props \u5B9A\u4E49\n - State \u5B9A\u4E49\uFF08\u5982\u679C\u9700\u8981\uFF09\n\n2. **\u751F\u6210\u4EE3\u7801**\n - \u5305\u542B\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n - \u9075\u5B88\u6240\u6709 TSX \u89C4\u8303\n - \u4F7F\u7528 @type Component \u5143\u6570\u636E\n\n3. **\u9A8C\u8BC1\u4EE3\u7801**\n - \u8FD0\u884C `appthen check-tsx -f \"path/to/component.tsx\"`\n - \u4FEE\u6B63\u6240\u6709\u9519\u8BEF\n\n4. **\u6D4B\u8BD5\u529F\u80FD**\n - \u5728\u9875\u9762\u4E2D\u4F7F\u7528\u7EC4\u4EF6\n - \u6D4B\u8BD5\u6240\u6709 Props \u548C\u4EA4\u4E92\n\n## \u7EC4\u4EF6 vs \u9875\u9762\n\n- **\u9875\u9762**\uFF1A\u4F7F\u7528 @type Page\uFF0C\u53EF\u4EE5\u901A\u8FC7 URL \u8BBF\u95EE\n- **\u7EC4\u4EF6**\uFF1A\u4F7F\u7528 @type Component\uFF0C\u53EF\u590D\u7528\u7684 UI \u5355\u5143\n\n## \u6A21\u677F\u53C2\u8003\n\n\u53C2\u8003 `.appthen/prompts/tsx-generation.md` \u4E2D\u7684\u5B8C\u6574\u793A\u4F8B\u3002\n");
|
|
49193
|
+
files.push(createComponentPath);
|
|
49194
|
+
if (this.verbose) {
|
|
49195
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u547D\u4EE4: ".concat(files.length, " \u4E2A\u6587\u4EF6"));
|
|
49196
|
+
}
|
|
49197
|
+
return [2 /*return*/, files];
|
|
49198
|
+
});
|
|
49199
|
+
});
|
|
49200
|
+
};
|
|
49201
|
+
return ClaudeCodeGenerator;
|
|
49202
|
+
}());
|
|
49203
|
+
|
|
49204
|
+
/**
|
|
49205
|
+
* Cursor 生成器
|
|
49206
|
+
* 生成 Cursor 特定的配置文件
|
|
49207
|
+
*/
|
|
49208
|
+
var CursorGenerator = /** @class */ (function () {
|
|
49209
|
+
function CursorGenerator(cwd, config, verbose) {
|
|
49210
|
+
this.cwd = cwd;
|
|
49211
|
+
this.config = config;
|
|
49212
|
+
this.verbose = verbose;
|
|
49213
|
+
}
|
|
49214
|
+
/**
|
|
49215
|
+
* 生成 Cursor 配置
|
|
49216
|
+
*/
|
|
49217
|
+
CursorGenerator.prototype.generate = function () {
|
|
49218
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49219
|
+
var files, cursorDir, rulesFile, promptsDir, instructionsFile, error_1;
|
|
49220
|
+
return __generator(this, function (_a) {
|
|
49221
|
+
switch (_a.label) {
|
|
49222
|
+
case 0:
|
|
49223
|
+
files = [];
|
|
49224
|
+
_a.label = 1;
|
|
49225
|
+
case 1:
|
|
49226
|
+
_a.trys.push([1, 4, , 5]);
|
|
49227
|
+
if (this.verbose) {
|
|
49228
|
+
console.log('🎯 配置 Cursor 集成...');
|
|
49229
|
+
}
|
|
49230
|
+
cursorDir = path__namespace.join(this.cwd, '.cursor');
|
|
49231
|
+
if (!fs__namespace.existsSync(cursorDir)) {
|
|
49232
|
+
fs__namespace.mkdirSync(cursorDir, { recursive: true });
|
|
49233
|
+
if (this.verbose) {
|
|
49234
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(cursorDir));
|
|
49235
|
+
}
|
|
49236
|
+
}
|
|
49237
|
+
return [4 /*yield*/, this.createRulesFile(cursorDir)];
|
|
49238
|
+
case 2:
|
|
49239
|
+
rulesFile = _a.sent();
|
|
49240
|
+
files.push(rulesFile);
|
|
49241
|
+
promptsDir = path__namespace.join(cursorDir, 'prompts');
|
|
49242
|
+
if (!fs__namespace.existsSync(promptsDir)) {
|
|
49243
|
+
fs__namespace.mkdirSync(promptsDir, { recursive: true });
|
|
49244
|
+
}
|
|
49245
|
+
return [4 /*yield*/, this.createCustomInstructions(promptsDir)];
|
|
49246
|
+
case 3:
|
|
49247
|
+
instructionsFile = _a.sent();
|
|
49248
|
+
files.push(instructionsFile);
|
|
49249
|
+
if (this.verbose) {
|
|
49250
|
+
console.log('✅ Cursor 配置完成');
|
|
49251
|
+
}
|
|
49252
|
+
return [2 /*return*/, {
|
|
49253
|
+
success: true,
|
|
49254
|
+
files: files,
|
|
49255
|
+
message: 'Cursor configuration created successfully',
|
|
49256
|
+
}];
|
|
49257
|
+
case 4:
|
|
49258
|
+
error_1 = _a.sent();
|
|
49259
|
+
return [2 /*return*/, {
|
|
49260
|
+
success: false,
|
|
49261
|
+
files: [],
|
|
49262
|
+
error: error_1.message,
|
|
49263
|
+
}];
|
|
49264
|
+
case 5: return [2 /*return*/];
|
|
49265
|
+
}
|
|
49266
|
+
});
|
|
49267
|
+
});
|
|
49268
|
+
};
|
|
49269
|
+
/**
|
|
49270
|
+
* 创建 Cursor Rules 文件
|
|
49271
|
+
*/
|
|
49272
|
+
CursorGenerator.prototype.createRulesFile = function (cursorDir) {
|
|
49273
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49274
|
+
var rulesPath, rulesContent;
|
|
49275
|
+
return __generator(this, function (_a) {
|
|
49276
|
+
rulesPath = path__namespace.join(cursorDir, 'rules.md');
|
|
49277
|
+
rulesContent = "# Cursor Rules for ".concat(this.config.projectName, "\n\n## TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303\n\n### \u6587\u4EF6\u7ED3\u6784\u8981\u6C42\n\n\u6240\u6709 TSX \u6587\u4EF6\u5FC5\u987B\u9075\u5FAA\u4EE5\u4E0B\u7ED3\u6784\uFF1A\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5173\u952E\u89C4\u5219\n\n1. **\u5FC5\u987B\u5305\u542B JSDoc \u5143\u6570\u636E**\n - \u4F7F\u7528 `@type Page` \u6216 `@type Component`\n - \u4F7F\u7528 `@description` \u63CF\u8FF0\u7EC4\u4EF6\u7528\u9014\n\n2. **\u4F7F\u7528 class \u5B9A\u4E49\u63A5\u53E3**\n - Props: `class IProps { }`\n - State: `class IState { }`\n\n3. **render() \u65B9\u6CD5\u89C4\u8303**\n - \u53EA\u5305\u542B `return` \u8BED\u53E5\u548C JSX\n - \u4E0D\u5305\u542B\u590D\u6742\u903B\u8F91\n - \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n\n4. **\u6761\u4EF6\u6E32\u67D3**\n - \u2705 \u4F7F\u7528: `{condition && <Component />}`\n - \u274C \u907F\u514D: `{condition ? <A /> : <B />}`\n\n5. **\u53EF\u9009\u94FE**\n - \u2705 \u4F7F\u7528: `user?.profile?.name`\n - \u274C \u907F\u514D: `user.profile.name`\n\n6. **\u7C7B\u578B\u6CE8\u89E3**\n - \u274C \u4E0D\u8981\u5728\u65B9\u6CD5\u53C2\u6570\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n - \u7C7B\u578B\u4FE1\u606F\u5E94\u8BE5\u5728 IProps \u548C IState \u4E2D\u5B9A\u4E49\n\n### \u4EE3\u7801\u793A\u4F8B\n\n```typescript\n/**\n * @type Page\n * @description \u7528\u6237\u5217\u8868\u9875\u9762\n */\n\nimport React from 'react';\n\nclass IProps {\n users: Array<{ id: string; name: string }>;\n onUserClick: (userId: string) => void;\n}\n\nclass IState {\n loading: boolean;\n searchText: string;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n searchText: '',\n };\n }\n\n getFilteredUsers() {\n const { users } = this.props;\n const { searchText } = this.state;\n \n if (!searchText) return users;\n \n return users.filter(u =>\n u?.name?.toLowerCase().includes(searchText.toLowerCase())\n );\n }\n\n render() {\n const { onUserClick } = this.props;\n const { loading, searchText } = this.state;\n const filteredUsers = this.getFilteredUsers();\n\n return (\n <div>\n <input\n value={searchText}\n onChange={(e) => this.setState({ searchText: e.target.value })}\n />\n \n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {!loading && filteredUsers.length === 0 && (\n <div>\u6682\u65E0\u6570\u636E</div>\n )}\n \n {!loading && filteredUsers.length > 0 && (\n <ul>\n {filteredUsers.map(user => (\n <li key={user.id} onClick={() => onUserClick(user.id)}>\n {user?.name}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u9879\u76EE\u7279\u5B9A\u89C4\u5219\n\n- \u9879\u76EE\u540D\u79F0: ").concat(this.config.projectName, "\n- \u7A7A\u95F4ID: ").concat(this.config.spaceId, "\n- \u521B\u5EFA\u65F6\u95F4: ").concat(this.config.createdAt, "\n\n## \u66F4\u591A\u4FE1\u606F\n\n\u8BE6\u7EC6\u7684\u63D0\u793A\u8BCD\u548C\u89C4\u8303\u8BF7\u67E5\u770B `.appthen/prompts/` \u76EE\u5F55\u3002\n");
|
|
49278
|
+
fs__namespace.writeFileSync(rulesPath, rulesContent);
|
|
49279
|
+
if (this.verbose) {
|
|
49280
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Cursor Rules: ".concat(rulesPath));
|
|
49281
|
+
}
|
|
49282
|
+
return [2 /*return*/, rulesPath];
|
|
49283
|
+
});
|
|
49284
|
+
});
|
|
49285
|
+
};
|
|
49286
|
+
/**
|
|
49287
|
+
* 创建自定义指令文件
|
|
49288
|
+
*/
|
|
49289
|
+
CursorGenerator.prototype.createCustomInstructions = function (promptsDir) {
|
|
49290
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49291
|
+
var instructionsPath, instructionsContent;
|
|
49292
|
+
return __generator(this, function (_a) {
|
|
49293
|
+
instructionsPath = path__namespace.join(promptsDir, 'custom-instructions.md');
|
|
49294
|
+
instructionsContent = "# Custom Instructions for ".concat(this.config.projectName, "\n\n## \u4EE3\u7801\u751F\u6210\u6307\u4EE4\n\n\u5F53\u751F\u6210 TSX \u4EE3\u7801\u65F6\uFF1A\n\n1. \u59CB\u7EC8\u9075\u5FAA `.cursor/rules.md` \u4E2D\u5B9A\u4E49\u7684\u89C4\u8303\n2. \u786E\u4FDD\u5305\u542B\u5B8C\u6574\u7684 JSDoc \u5143\u6570\u636E\n3. \u4F7F\u7528 class \u5B9A\u4E49 IProps \u548C IState\n4. render() \u65B9\u6CD5\u4FDD\u6301\u7B80\u6D01\n5. \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n6. \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n\n## \u4EE3\u7801\u5BA1\u67E5\u6307\u4EE4\n\n\u5F53\u5BA1\u67E5\u4EE3\u7801\u65F6\uFF1A\n\n1. \u68C0\u67E5\u662F\u5426\u7B26\u5408 TSX \u89C4\u8303\n2. \u8BC6\u522B\u6F5C\u5728\u7684\u6027\u80FD\u95EE\u9898\n3. \u68C0\u67E5\u8FB9\u754C\u60C5\u51B5\u5904\u7406\n4. \u9A8C\u8BC1\u9519\u8BEF\u5904\u7406\u903B\u8F91\n5. \u8BC4\u4F30\u4EE3\u7801\u53EF\u7EF4\u62A4\u6027\n\n## \u91CD\u6784\u6307\u4EE4\n\n\u5F53\u91CD\u6784\u4EE3\u7801\u65F6\uFF1A\n\n1. \u4FDD\u6301\u529F\u80FD\u4E0D\u53D8\n2. \u63D0\u53D6\u91CD\u590D\u4EE3\u7801\n3. \u7B80\u5316\u590D\u6742\u903B\u8F91\n4. \u63D0\u9AD8\u4EE3\u7801\u53EF\u8BFB\u6027\n5. \u4F18\u5316\u6027\u80FD\n\n## \u53C2\u8003\u8D44\u6599\n\n- TSX \u751F\u6210\u89C4\u8303: `.appthen/prompts/tsx-generation.md`\n- \u4EE3\u7801\u5BA1\u67E5\u6307\u5357: `.appthen/prompts/code-review.md`\n- \u91CD\u6784\u6307\u5357: `.appthen/prompts/refactoring.md`\n");
|
|
49295
|
+
fs__namespace.writeFileSync(instructionsPath, instructionsContent);
|
|
49296
|
+
if (this.verbose) {
|
|
49297
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u6307\u4EE4: ".concat(instructionsPath));
|
|
49298
|
+
}
|
|
49299
|
+
return [2 /*return*/, instructionsPath];
|
|
49300
|
+
});
|
|
49301
|
+
});
|
|
49302
|
+
};
|
|
49303
|
+
return CursorGenerator;
|
|
49304
|
+
}());
|
|
49305
|
+
|
|
49306
|
+
/**
|
|
49307
|
+
* Windsurf 生成器
|
|
49308
|
+
* 生成 Windsurf (Codeium) 特定的配置文件
|
|
49309
|
+
*/
|
|
49310
|
+
var WindsurfGenerator = /** @class */ (function () {
|
|
49311
|
+
function WindsurfGenerator(cwd, config, verbose) {
|
|
49312
|
+
this.cwd = cwd;
|
|
49313
|
+
this.config = config;
|
|
49314
|
+
this.verbose = verbose;
|
|
49315
|
+
}
|
|
49316
|
+
/**
|
|
49317
|
+
* 生成 Windsurf 配置
|
|
49318
|
+
*/
|
|
49319
|
+
WindsurfGenerator.prototype.generate = function () {
|
|
49320
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49321
|
+
var files, windsurfDir, cascadeFile, rulesFile, error_1;
|
|
49322
|
+
return __generator(this, function (_a) {
|
|
49323
|
+
switch (_a.label) {
|
|
49324
|
+
case 0:
|
|
49325
|
+
files = [];
|
|
49326
|
+
_a.label = 1;
|
|
49327
|
+
case 1:
|
|
49328
|
+
_a.trys.push([1, 4, , 5]);
|
|
49329
|
+
if (this.verbose) {
|
|
49330
|
+
console.log('🌊 配置 Windsurf 集成...');
|
|
49331
|
+
}
|
|
49332
|
+
windsurfDir = path__namespace.join(this.cwd, '.windsurf');
|
|
49333
|
+
if (!fs__namespace.existsSync(windsurfDir)) {
|
|
49334
|
+
fs__namespace.mkdirSync(windsurfDir, { recursive: true });
|
|
49335
|
+
if (this.verbose) {
|
|
49336
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(windsurfDir));
|
|
49337
|
+
}
|
|
49338
|
+
}
|
|
49339
|
+
return [4 /*yield*/, this.createCascadeConfig(windsurfDir)];
|
|
49340
|
+
case 2:
|
|
49341
|
+
cascadeFile = _a.sent();
|
|
49342
|
+
files.push(cascadeFile);
|
|
49343
|
+
return [4 /*yield*/, this.createRulesFile(windsurfDir)];
|
|
49344
|
+
case 3:
|
|
49345
|
+
rulesFile = _a.sent();
|
|
49346
|
+
files.push(rulesFile);
|
|
49347
|
+
if (this.verbose) {
|
|
49348
|
+
console.log('✅ Windsurf 配置完成');
|
|
49349
|
+
}
|
|
49350
|
+
return [2 /*return*/, {
|
|
49351
|
+
success: true,
|
|
49352
|
+
files: files,
|
|
49353
|
+
message: 'Windsurf configuration created successfully',
|
|
49354
|
+
}];
|
|
49355
|
+
case 4:
|
|
49356
|
+
error_1 = _a.sent();
|
|
49357
|
+
return [2 /*return*/, {
|
|
49358
|
+
success: false,
|
|
49359
|
+
files: [],
|
|
49360
|
+
error: error_1.message,
|
|
49361
|
+
}];
|
|
49362
|
+
case 5: return [2 /*return*/];
|
|
49363
|
+
}
|
|
49364
|
+
});
|
|
49365
|
+
});
|
|
49366
|
+
};
|
|
49367
|
+
/**
|
|
49368
|
+
* 创建 Cascade 配置文件
|
|
49369
|
+
*/
|
|
49370
|
+
WindsurfGenerator.prototype.createCascadeConfig = function (windsurfDir) {
|
|
49371
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49372
|
+
var cascadePath, cascadeConfig;
|
|
49373
|
+
return __generator(this, function (_a) {
|
|
49374
|
+
cascadePath = path__namespace.join(windsurfDir, 'cascade.json');
|
|
49375
|
+
cascadeConfig = {
|
|
49376
|
+
name: this.config.projectName,
|
|
49377
|
+
description: "Agent+ Space configuration for ".concat(this.config.projectName),
|
|
49378
|
+
version: '1.0.0',
|
|
49379
|
+
rules: {
|
|
49380
|
+
tsx: {
|
|
49381
|
+
enabled: true,
|
|
49382
|
+
strictMode: true,
|
|
49383
|
+
checkMetadata: true,
|
|
49384
|
+
checkClassDefinitions: true,
|
|
49385
|
+
checkRenderMethod: true,
|
|
49386
|
+
enforceConditionalRendering: true,
|
|
49387
|
+
enforceOptionalChaining: true,
|
|
49388
|
+
},
|
|
49389
|
+
},
|
|
49390
|
+
prompts: {
|
|
49391
|
+
codeGeneration: '.appthen/prompts/tsx-generation.md',
|
|
49392
|
+
codeReview: '.appthen/prompts/code-review.md',
|
|
49393
|
+
refactoring: '.appthen/prompts/refactoring.md',
|
|
49394
|
+
},
|
|
49395
|
+
workspace: {
|
|
49396
|
+
root: this.cwd,
|
|
49397
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49398
|
+
exclude: [
|
|
49399
|
+
'node_modules/**',
|
|
49400
|
+
'dist/**',
|
|
49401
|
+
'build/**',
|
|
49402
|
+
'.git/**',
|
|
49403
|
+
'*.log',
|
|
49404
|
+
],
|
|
49405
|
+
},
|
|
49406
|
+
};
|
|
49407
|
+
fs__namespace.writeFileSync(cascadePath, JSON.stringify(cascadeConfig, null, 2));
|
|
49408
|
+
if (this.verbose) {
|
|
49409
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Cascade \u914D\u7F6E: ".concat(cascadePath));
|
|
49410
|
+
}
|
|
49411
|
+
return [2 /*return*/, cascadePath];
|
|
49412
|
+
});
|
|
49413
|
+
});
|
|
49414
|
+
};
|
|
49415
|
+
/**
|
|
49416
|
+
* 创建 Rules 文件
|
|
49417
|
+
*/
|
|
49418
|
+
WindsurfGenerator.prototype.createRulesFile = function (windsurfDir) {
|
|
49419
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49420
|
+
var rulesPath, rulesContent;
|
|
49421
|
+
return __generator(this, function (_a) {
|
|
49422
|
+
rulesPath = path__namespace.join(windsurfDir, 'rules.md');
|
|
49423
|
+
rulesContent = "# Windsurf Rules for ".concat(this.config.projectName, "\n\n## TSX \u4EE3\u7801\u89C4\u8303\n\n### \u57FA\u672C\u8981\u6C42\n\n1. **\u6587\u4EF6\u7ED3\u6784**\n - JSDoc \u5143\u6570\u636E\u6CE8\u91CA\uFF08@type, @description\uFF09\n - class IProps \u548C class IState \u5B9A\u4E49\n - class Document extends React.Component\n - render() \u65B9\u6CD5\u53EA\u5305\u542B return \u8BED\u53E5\n\n2. **\u6761\u4EF6\u6E32\u67D3**\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\n - \u907F\u514D\u4E09\u5143\u8868\u8FBE\u5F0F\n\n3. **\u5BF9\u8C61\u8BBF\u95EE**\n - \u4F7F\u7528\u53EF\u9009\u94FE\uFF08?.\uFF09\n - \u907F\u514D\u76F4\u63A5\u5C5E\u6027\u8BBF\u95EE\n\n### \u4EE3\u7801\u751F\u6210\u6A21\u677F\n\n```typescript\n/**\n * @type Page|Component\n * @description [\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u6700\u4F73\u5B9E\u8DF5\n\n- \u4FDD\u6301 render() \u65B9\u6CD5\u7B80\u6D01\n- \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n- \u4F7F\u7528\u6709\u610F\u4E49\u7684\u53D8\u91CF\u540D\n- \u6DFB\u52A0\u5FC5\u8981\u7684\u6CE8\u91CA\n- \u5904\u7406\u8FB9\u754C\u60C5\u51B5\n\n### \u53C2\u8003\u8D44\u6599\n\n\u8BE6\u7EC6\u89C4\u8303\u8BF7\u67E5\u770B\uFF1A\n- `.appthen/prompts/tsx-generation.md`\n- `.appthen/prompts/code-review.md`\n- `.appthen/prompts/refactoring.md`\n\n## \u9879\u76EE\u4FE1\u606F\n\n- \u9879\u76EE: ").concat(this.config.projectName, "\n- \u7A7A\u95F4ID: ").concat(this.config.spaceId, "\n- \u5DE5\u5177: Windsurf (Codeium)\n");
|
|
49424
|
+
fs__namespace.writeFileSync(rulesPath, rulesContent);
|
|
49425
|
+
if (this.verbose) {
|
|
49426
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA Rules \u6587\u4EF6: ".concat(rulesPath));
|
|
49427
|
+
}
|
|
49428
|
+
return [2 /*return*/, rulesPath];
|
|
49429
|
+
});
|
|
49430
|
+
});
|
|
49431
|
+
};
|
|
49432
|
+
return WindsurfGenerator;
|
|
49433
|
+
}());
|
|
49434
|
+
|
|
49435
|
+
/**
|
|
49436
|
+
* 阿里云 Coder 生成器
|
|
49437
|
+
* 生成阿里云 Coder 特定的配置文件
|
|
49438
|
+
*/
|
|
49439
|
+
var CoderGenerator = /** @class */ (function () {
|
|
49440
|
+
function CoderGenerator(cwd, config, verbose) {
|
|
49441
|
+
this.cwd = cwd;
|
|
49442
|
+
this.config = config;
|
|
49443
|
+
this.verbose = verbose;
|
|
49444
|
+
}
|
|
49445
|
+
/**
|
|
49446
|
+
* 生成阿里云 Coder 配置
|
|
49447
|
+
*/
|
|
49448
|
+
CoderGenerator.prototype.generate = function () {
|
|
49449
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49450
|
+
var files, coderDir, configFile, templatesDir, templateFile, error_1;
|
|
49451
|
+
return __generator(this, function (_a) {
|
|
49452
|
+
switch (_a.label) {
|
|
49453
|
+
case 0:
|
|
49454
|
+
files = [];
|
|
49455
|
+
_a.label = 1;
|
|
49456
|
+
case 1:
|
|
49457
|
+
_a.trys.push([1, 4, , 5]);
|
|
49458
|
+
if (this.verbose) {
|
|
49459
|
+
console.log('☁️ 配置阿里云 Coder 集成...');
|
|
49460
|
+
}
|
|
49461
|
+
coderDir = path__namespace.join(this.cwd, '.coder');
|
|
49462
|
+
if (!fs__namespace.existsSync(coderDir)) {
|
|
49463
|
+
fs__namespace.mkdirSync(coderDir, { recursive: true });
|
|
49464
|
+
if (this.verbose) {
|
|
49465
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(coderDir));
|
|
49466
|
+
}
|
|
49467
|
+
}
|
|
49468
|
+
return [4 /*yield*/, this.createConfig(coderDir)];
|
|
49469
|
+
case 2:
|
|
49470
|
+
configFile = _a.sent();
|
|
49471
|
+
files.push(configFile);
|
|
49472
|
+
templatesDir = path__namespace.join(coderDir, 'templates');
|
|
49473
|
+
if (!fs__namespace.existsSync(templatesDir)) {
|
|
49474
|
+
fs__namespace.mkdirSync(templatesDir, { recursive: true });
|
|
49475
|
+
}
|
|
49476
|
+
return [4 /*yield*/, this.createTsxTemplate(templatesDir)];
|
|
49477
|
+
case 3:
|
|
49478
|
+
templateFile = _a.sent();
|
|
49479
|
+
files.push(templateFile);
|
|
49480
|
+
if (this.verbose) {
|
|
49481
|
+
console.log('✅ 阿里云 Coder 配置完成');
|
|
49482
|
+
}
|
|
49483
|
+
return [2 /*return*/, {
|
|
49484
|
+
success: true,
|
|
49485
|
+
files: files,
|
|
49486
|
+
message: 'Coder configuration created successfully',
|
|
49487
|
+
}];
|
|
49488
|
+
case 4:
|
|
49489
|
+
error_1 = _a.sent();
|
|
49490
|
+
return [2 /*return*/, {
|
|
49491
|
+
success: false,
|
|
49492
|
+
files: [],
|
|
49493
|
+
error: error_1.message,
|
|
49494
|
+
}];
|
|
49495
|
+
case 5: return [2 /*return*/];
|
|
49496
|
+
}
|
|
49497
|
+
});
|
|
49498
|
+
});
|
|
49499
|
+
};
|
|
49500
|
+
/**
|
|
49501
|
+
* 创建配置文件
|
|
49502
|
+
*/
|
|
49503
|
+
CoderGenerator.prototype.createConfig = function (coderDir) {
|
|
49504
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49505
|
+
var configPath, config;
|
|
49506
|
+
return __generator(this, function (_a) {
|
|
49507
|
+
configPath = path__namespace.join(coderDir, 'config.json');
|
|
49508
|
+
config = {
|
|
49509
|
+
projectName: this.config.projectName,
|
|
49510
|
+
spaceId: this.config.spaceId,
|
|
49511
|
+
version: '1.0.0',
|
|
49512
|
+
codeGeneration: {
|
|
49513
|
+
tsx: {
|
|
49514
|
+
enabled: true,
|
|
49515
|
+
template: 'templates/tsx-template.md',
|
|
49516
|
+
rules: {
|
|
49517
|
+
requireMetadata: true,
|
|
49518
|
+
requireClassDefinitions: true,
|
|
49519
|
+
enforceRenderStructure: true,
|
|
49520
|
+
useConditionalOperator: true,
|
|
49521
|
+
useOptionalChaining: true,
|
|
49522
|
+
},
|
|
49523
|
+
},
|
|
49524
|
+
},
|
|
49525
|
+
prompts: {
|
|
49526
|
+
generation: '../.appthen/prompts/tsx-generation.md',
|
|
49527
|
+
review: '../.appthen/prompts/code-review.md',
|
|
49528
|
+
refactoring: '../.appthen/prompts/refactoring.md',
|
|
49529
|
+
},
|
|
49530
|
+
workspace: {
|
|
49531
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49532
|
+
exclude: [
|
|
49533
|
+
'node_modules/**',
|
|
49534
|
+
'dist/**',
|
|
49535
|
+
'build/**',
|
|
49536
|
+
'.git/**',
|
|
49537
|
+
'*.log',
|
|
49538
|
+
],
|
|
49539
|
+
},
|
|
49540
|
+
};
|
|
49541
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
49542
|
+
if (this.verbose) {
|
|
49543
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49544
|
+
}
|
|
49545
|
+
return [2 /*return*/, configPath];
|
|
49546
|
+
});
|
|
49547
|
+
});
|
|
49548
|
+
};
|
|
49549
|
+
/**
|
|
49550
|
+
* 创建 TSX 模板
|
|
49551
|
+
*/
|
|
49552
|
+
CoderGenerator.prototype.createTsxTemplate = function (templatesDir) {
|
|
49553
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49554
|
+
var templatePath, templateContent;
|
|
49555
|
+
return __generator(this, function (_a) {
|
|
49556
|
+
templatePath = path__namespace.join(templatesDir, 'tsx-template.md');
|
|
49557
|
+
templateContent = "# TSX \u4EE3\u7801\u6A21\u677F - ".concat(this.config.projectName, "\n\n## \u57FA\u7840\u6A21\u677F\n\n```typescript\n/**\n * @type [Page|Component]\n * @description [\u7EC4\u4EF6\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // TODO: \u5B9A\u4E49 Props\n}\n\nclass IState {\n // TODO: \u5B9A\u4E49 State\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n // TODO: \u521D\u59CB\u5316 State\n };\n }\n\n render() {\n return (\n <div>\n {/* TODO: \u5B9E\u73B0 JSX */}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u9875\u9762\u6A21\u677F\n\n```typescript\n/**\n * @type Page\n * @description [\u9875\u9762\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // \u9875\u9762 Props\n}\n\nclass IState {\n loading: boolean;\n data: any;\n error: string | null;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n data: null,\n error: null,\n };\n }\n\n componentDidMount() {\n this.loadData();\n }\n\n async loadData() {\n this.setState({ loading: true, error: null });\n \n try {\n // TODO: \u52A0\u8F7D\u6570\u636E\n const data = await fetchData();\n this.setState({ data, loading: false });\n } catch (error) {\n this.setState({ error: error.message, loading: false });\n }\n }\n\n render() {\n const { loading, data, error } = this.state;\n\n return (\n <div className=\"page\">\n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {error && <div className=\"error\">{error}</div>}\n \n {!loading && !error && data && (\n <div className=\"content\">\n {/* TODO: \u6E32\u67D3\u6570\u636E */}\n </div>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u7EC4\u4EF6\u6A21\u677F\n\n```typescript\n/**\n * @type Component\n * @description [\u7EC4\u4EF6\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // \u7EC4\u4EF6 Props\n}\n\nclass IState {\n // \u7EC4\u4EF6 State\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n const { } = this.props;\n \n return (\n <div className=\"component\">\n {/* TODO: \u5B9E\u73B0\u7EC4\u4EF6 */}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u4F7F\u7528\u8BF4\u660E\n\n1. \u9009\u62E9\u5408\u9002\u7684\u6A21\u677F\uFF08\u57FA\u7840/\u9875\u9762/\u7EC4\u4EF6\uFF09\n2. \u66FF\u6362 TODO \u6CE8\u91CA\u4E2D\u7684\u5185\u5BB9\n3. \u786E\u4FDD\u9075\u5FAA TSX \u89C4\u8303\uFF1A\n - \u5305\u542B JSDoc \u5143\u6570\u636E\n - \u4F7F\u7528 class \u5B9A\u4E49 IProps \u548C IState\n - render() \u53EA\u5305\u542B return \u8BED\u53E5\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n - \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n\n## \u53C2\u8003\u8D44\u6599\n\n- \u8BE6\u7EC6\u89C4\u8303: `.appthen/prompts/tsx-generation.md`\n- \u4EE3\u7801\u5BA1\u67E5: `.appthen/prompts/code-review.md`\n- \u91CD\u6784\u6307\u5357: `.appthen/prompts/refactoring.md`\n");
|
|
49558
|
+
fs__namespace.writeFileSync(templatePath, templateContent);
|
|
49559
|
+
if (this.verbose) {
|
|
49560
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA TSX \u6A21\u677F: ".concat(templatePath));
|
|
49561
|
+
}
|
|
49562
|
+
return [2 /*return*/, templatePath];
|
|
49563
|
+
});
|
|
49564
|
+
});
|
|
49565
|
+
};
|
|
49566
|
+
return CoderGenerator;
|
|
49567
|
+
}());
|
|
49568
|
+
|
|
49569
|
+
/**
|
|
49570
|
+
* Augment 生成器
|
|
49571
|
+
* 生成 Augment (VSCode 插件) 特定的配置文件
|
|
49572
|
+
*/
|
|
49573
|
+
var AugmentGenerator = /** @class */ (function () {
|
|
49574
|
+
function AugmentGenerator(cwd, config, verbose) {
|
|
49575
|
+
this.cwd = cwd;
|
|
49576
|
+
this.config = config;
|
|
49577
|
+
this.verbose = verbose;
|
|
49578
|
+
}
|
|
49579
|
+
/**
|
|
49580
|
+
* 生成 Augment 配置
|
|
49581
|
+
*/
|
|
49582
|
+
AugmentGenerator.prototype.generate = function () {
|
|
49583
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49584
|
+
var files, augmentDir, configFile, contextDir, contextFile, error_1;
|
|
49585
|
+
return __generator(this, function (_a) {
|
|
49586
|
+
switch (_a.label) {
|
|
49587
|
+
case 0:
|
|
49588
|
+
files = [];
|
|
49589
|
+
_a.label = 1;
|
|
49590
|
+
case 1:
|
|
49591
|
+
_a.trys.push([1, 4, , 5]);
|
|
49592
|
+
if (this.verbose) {
|
|
49593
|
+
console.log('🔧 配置 Augment 集成...');
|
|
49594
|
+
}
|
|
49595
|
+
augmentDir = path__namespace.join(this.cwd, '.augment');
|
|
49596
|
+
if (!fs__namespace.existsSync(augmentDir)) {
|
|
49597
|
+
fs__namespace.mkdirSync(augmentDir, { recursive: true });
|
|
49598
|
+
if (this.verbose) {
|
|
49599
|
+
console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(augmentDir));
|
|
49600
|
+
}
|
|
49601
|
+
}
|
|
49602
|
+
return [4 /*yield*/, this.createConfig(augmentDir)];
|
|
49603
|
+
case 2:
|
|
49604
|
+
configFile = _a.sent();
|
|
49605
|
+
files.push(configFile);
|
|
49606
|
+
contextDir = path__namespace.join(augmentDir, 'context');
|
|
49607
|
+
if (!fs__namespace.existsSync(contextDir)) {
|
|
49608
|
+
fs__namespace.mkdirSync(contextDir, { recursive: true });
|
|
49609
|
+
}
|
|
49610
|
+
return [4 /*yield*/, this.createProjectContext(contextDir)];
|
|
49611
|
+
case 3:
|
|
49612
|
+
contextFile = _a.sent();
|
|
49613
|
+
files.push(contextFile);
|
|
49614
|
+
if (this.verbose) {
|
|
49615
|
+
console.log('✅ Augment 配置完成');
|
|
49616
|
+
}
|
|
49617
|
+
return [2 /*return*/, {
|
|
49618
|
+
success: true,
|
|
49619
|
+
files: files,
|
|
49620
|
+
message: 'Augment configuration created successfully',
|
|
49621
|
+
}];
|
|
49622
|
+
case 4:
|
|
49623
|
+
error_1 = _a.sent();
|
|
49624
|
+
return [2 /*return*/, {
|
|
49625
|
+
success: false,
|
|
49626
|
+
files: [],
|
|
49627
|
+
error: error_1.message,
|
|
49628
|
+
}];
|
|
49629
|
+
case 5: return [2 /*return*/];
|
|
49630
|
+
}
|
|
49631
|
+
});
|
|
49632
|
+
});
|
|
49633
|
+
};
|
|
49634
|
+
/**
|
|
49635
|
+
* 创建配置文件
|
|
49636
|
+
*/
|
|
49637
|
+
AugmentGenerator.prototype.createConfig = function (augmentDir) {
|
|
49638
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49639
|
+
var configPath, config;
|
|
49640
|
+
return __generator(this, function (_a) {
|
|
49641
|
+
configPath = path__namespace.join(augmentDir, 'config.json');
|
|
49642
|
+
config = {
|
|
49643
|
+
projectName: this.config.projectName,
|
|
49644
|
+
spaceId: this.config.spaceId,
|
|
49645
|
+
version: '1.0.0',
|
|
49646
|
+
context: {
|
|
49647
|
+
enabled: true,
|
|
49648
|
+
files: ['context/project-context.md'],
|
|
49649
|
+
prompts: [
|
|
49650
|
+
'../.appthen/prompts/tsx-generation.md',
|
|
49651
|
+
'../.appthen/prompts/code-review.md',
|
|
49652
|
+
'../.appthen/prompts/refactoring.md',
|
|
49653
|
+
],
|
|
49654
|
+
},
|
|
49655
|
+
codeGeneration: {
|
|
49656
|
+
tsx: {
|
|
49657
|
+
enabled: true,
|
|
49658
|
+
strictMode: true,
|
|
49659
|
+
autoFormat: true,
|
|
49660
|
+
},
|
|
49661
|
+
},
|
|
49662
|
+
workspace: {
|
|
49663
|
+
include: ['src/**/*', 'docs/**/*'],
|
|
49664
|
+
exclude: [
|
|
49665
|
+
'node_modules/**',
|
|
49666
|
+
'dist/**',
|
|
49667
|
+
'build/**',
|
|
49668
|
+
'.git/**',
|
|
49669
|
+
'*.log',
|
|
49670
|
+
],
|
|
49671
|
+
},
|
|
49672
|
+
};
|
|
49673
|
+
fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
49674
|
+
if (this.verbose) {
|
|
49675
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49676
|
+
}
|
|
49677
|
+
return [2 /*return*/, configPath];
|
|
49678
|
+
});
|
|
49679
|
+
});
|
|
49680
|
+
};
|
|
49681
|
+
/**
|
|
49682
|
+
* 创建项目上下文文件
|
|
49683
|
+
*/
|
|
49684
|
+
AugmentGenerator.prototype.createProjectContext = function (contextDir) {
|
|
49685
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49686
|
+
var contextPath, contextContent;
|
|
49687
|
+
return __generator(this, function (_a) {
|
|
49688
|
+
contextPath = path__namespace.join(contextDir, 'project-context.md');
|
|
49689
|
+
contextContent = "# Project Context - ".concat(this.config.projectName, "\n\n## \u9879\u76EE\u4FE1\u606F\n\n- **\u9879\u76EE\u540D\u79F0**: ").concat(this.config.projectName, "\n- **\u7A7A\u95F4ID**: ").concat(this.config.spaceId, "\n- **\u521B\u5EFA\u65F6\u95F4**: ").concat(this.config.createdAt, "\n- **AI \u5DE5\u5177**: Augment (VSCode)\n\n## TSX \u4EE3\u7801\u89C4\u8303\n\n### \u6587\u4EF6\u7ED3\u6784\n\n\u6240\u6709 TSX \u6587\u4EF6\u5FC5\u987B\u9075\u5FAA\u4EE5\u4E0B\u7ED3\u6784\uFF1A\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5173\u952E\u89C4\u5219\n\n1. **JSDoc \u5143\u6570\u636E**\n - \u5FC5\u987B\u5305\u542B `@type` \u548C `@description`\n - `@type` \u503C\u4E3A `Page` \u6216 `Component`\n\n2. **\u7C7B\u5B9A\u4E49**\n - \u4F7F\u7528 `class IProps` \u5B9A\u4E49 Props\n - \u4F7F\u7528 `class IState` \u5B9A\u4E49 State\n - \u7EC4\u4EF6\u7C7B\u7EE7\u627F `React.Component<IProps, IState>`\n\n3. **render() \u65B9\u6CD5**\n - \u53EA\u5305\u542B `return` \u8BED\u53E5\u548C JSX\n - \u4E0D\u5305\u542B\u590D\u6742\u903B\u8F91\n - \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n\n4. **\u6761\u4EF6\u6E32\u67D3**\n - \u2705 \u4F7F\u7528: `{condition && <Component />}`\n - \u274C \u907F\u514D: `{condition ? <A /> : <B />}`\n\n5. **\u5BF9\u8C61\u8BBF\u95EE**\n - \u2705 \u4F7F\u7528: `user?.profile?.name`\n - \u274C \u907F\u514D: `user.profile.name`\n\n6. **\u7C7B\u578B\u6CE8\u89E3**\n - \u274C \u4E0D\u8981\u5728\u65B9\u6CD5\u53C2\u6570\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n - \u7C7B\u578B\u4FE1\u606F\u5728 IProps \u548C IState \u4E2D\u5B9A\u4E49\n\n### \u4EE3\u7801\u793A\u4F8B\n\n```typescript\n/**\n * @type Page\n * @description \u7528\u6237\u5217\u8868\u9875\u9762\n */\n\nimport React from 'react';\n\nclass IProps {\n users: Array<{ id: string; name: string }>;\n}\n\nclass IState {\n loading: boolean;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n };\n }\n\n render() {\n const { users } = this.props;\n const { loading } = this.state;\n\n return (\n <div>\n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {!loading && users.length === 0 && (\n <div>\u6682\u65E0\u6570\u636E</div>\n )}\n \n {!loading && users.length > 0 && (\n <ul>\n {users.map(user => (\n <li key={user.id}>{user?.name}</li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u5F00\u53D1\u5DE5\u4F5C\u6D41\n\n1. **\u4EE3\u7801\u751F\u6210**\n - \u4F7F\u7528 Augment \u751F\u6210\u7B26\u5408\u89C4\u8303\u7684 TSX \u4EE3\u7801\n - \u53C2\u8003 `.appthen/prompts/tsx-generation.md`\n\n2. **\u4EE3\u7801\u5BA1\u67E5**\n - \u68C0\u67E5\u662F\u5426\u7B26\u5408 TSX \u89C4\u8303\n - \u53C2\u8003 `.appthen/prompts/code-review.md`\n\n3. **\u4EE3\u7801\u91CD\u6784**\n - \u63D0\u53D6\u91CD\u590D\u4EE3\u7801\n - \u7B80\u5316\u590D\u6742\u903B\u8F91\n - \u53C2\u8003 `.appthen/prompts/refactoring.md`\n\n## \u53C2\u8003\u8D44\u6599\n\n- **TSX \u751F\u6210\u89C4\u8303**: `.appthen/prompts/tsx-generation.md`\n- **\u4EE3\u7801\u5BA1\u67E5\u6307\u5357**: `.appthen/prompts/code-review.md`\n- **\u91CD\u6784\u6307\u5357**: `.appthen/prompts/refactoring.md`\n\n## \u6CE8\u610F\u4E8B\u9879\n\n- \u59CB\u7EC8\u9075\u5FAA TSX \u89C4\u8303\n- \u4FDD\u6301\u4EE3\u7801\u7B80\u6D01\u6613\u8BFB\n- \u5904\u7406\u8FB9\u754C\u60C5\u51B5\n- \u6DFB\u52A0\u5FC5\u8981\u7684\u6CE8\u91CA\n- \u4F7F\u7528\u6709\u610F\u4E49\u7684\u53D8\u91CF\u540D\n");
|
|
49690
|
+
fs__namespace.writeFileSync(contextPath, contextContent);
|
|
49691
|
+
if (this.verbose) {
|
|
49692
|
+
console.log("\uD83D\uDCDD \u521B\u5EFA\u9879\u76EE\u4E0A\u4E0B\u6587: ".concat(contextPath));
|
|
49693
|
+
}
|
|
49694
|
+
return [2 /*return*/, contextPath];
|
|
49695
|
+
});
|
|
49696
|
+
});
|
|
49697
|
+
};
|
|
49698
|
+
return AugmentGenerator;
|
|
49699
|
+
}());
|
|
49700
|
+
|
|
49701
|
+
/**
|
|
49702
|
+
* 初始化 Agent+ Space
|
|
49703
|
+
*/
|
|
49704
|
+
function initSpace(options) {
|
|
49705
|
+
if (options === void 0) { options = {}; }
|
|
49706
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49707
|
+
var _a, force, _b, verbose, _c, cwd, _d, skipPrompts, _e, skipHooks, configPath, tool, projectName, spaceId, spaceConfig, baseGenerator, baseResult, toolResult, allFiles, error_1;
|
|
49708
|
+
return __generator(this, function (_f) {
|
|
49709
|
+
switch (_f.label) {
|
|
49710
|
+
case 0:
|
|
49711
|
+
_a = options.force, force = _a === void 0 ? false : _a, _b = options.verbose, verbose = _b === void 0 ? false : _b, _c = options.cwd, cwd = _c === void 0 ? process.cwd() : _c, _d = options.skipPrompts, skipPrompts = _d === void 0 ? false : _d, _e = options.skipHooks, skipHooks = _e === void 0 ? false : _e;
|
|
49712
|
+
_f.label = 1;
|
|
49713
|
+
case 1:
|
|
49714
|
+
_f.trys.push([1, 6, , 7]);
|
|
49715
|
+
configPath = path__namespace.join(cwd, '.appthen/space-config.json');
|
|
49716
|
+
if (fs__namespace.existsSync(configPath) && !force) {
|
|
49717
|
+
console.log('');
|
|
49718
|
+
console.log('⚠️ Space 已经初始化');
|
|
49719
|
+
console.log(" \u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
|
|
49720
|
+
console.log('');
|
|
49721
|
+
console.log('💡 提示:');
|
|
49722
|
+
console.log(' - 使用 --force 强制重新初始化');
|
|
49723
|
+
console.log(' - 使用 appthen connect 连接到编辑器');
|
|
49724
|
+
console.log('');
|
|
49725
|
+
return [2 /*return*/, { success: false, error: 'Already initialized' }];
|
|
49726
|
+
}
|
|
49727
|
+
tool = options.tool;
|
|
49728
|
+
if (!!tool) return [3 /*break*/, 3];
|
|
49729
|
+
return [4 /*yield*/, promptForTool()];
|
|
49730
|
+
case 2:
|
|
49731
|
+
tool = _f.sent();
|
|
49732
|
+
_f.label = 3;
|
|
49733
|
+
case 3:
|
|
49734
|
+
projectName = options.name || path__namespace.basename(cwd);
|
|
49735
|
+
spaceId = "".concat(projectName, "-").concat(nanoid$1(8));
|
|
49736
|
+
spaceConfig = {
|
|
49737
|
+
spaceId: spaceId,
|
|
49738
|
+
projectId: options.projectId,
|
|
49739
|
+
projectName: projectName,
|
|
49740
|
+
projectRoot: cwd,
|
|
49741
|
+
tool: tool,
|
|
49742
|
+
createdAt: new Date().toISOString(),
|
|
49743
|
+
version: '1.0.0',
|
|
49744
|
+
};
|
|
49745
|
+
console.log('');
|
|
49746
|
+
console.log('🚀 初始化 Agent+ Space...');
|
|
49747
|
+
console.log('');
|
|
49748
|
+
if (verbose) {
|
|
49749
|
+
console.log(" \u5DE5\u5177: ".concat(getToolName(tool)));
|
|
49750
|
+
console.log(" \u9879\u76EE: ".concat(projectName));
|
|
49751
|
+
console.log(" \u7A7A\u95F4ID: ".concat(spaceId));
|
|
49752
|
+
console.log('');
|
|
49753
|
+
}
|
|
49754
|
+
baseGenerator = new BaseGenerator(cwd, spaceConfig, verbose);
|
|
49755
|
+
return [4 /*yield*/, baseGenerator.generate(skipPrompts)];
|
|
49756
|
+
case 4:
|
|
49757
|
+
baseResult = _f.sent();
|
|
49758
|
+
if (!baseResult.success) {
|
|
49759
|
+
console.error('❌ 基础配置生成失败:', baseResult.error);
|
|
49760
|
+
return [2 /*return*/, baseResult];
|
|
49761
|
+
}
|
|
49762
|
+
return [4 /*yield*/, generateToolSpecificFiles(tool, cwd, spaceConfig, verbose, skipHooks)];
|
|
49763
|
+
case 5:
|
|
49764
|
+
toolResult = _f.sent();
|
|
49765
|
+
if (!toolResult.success) {
|
|
49766
|
+
console.error('❌ 工具配置生成失败:', toolResult.error);
|
|
49767
|
+
return [2 /*return*/, toolResult];
|
|
49768
|
+
}
|
|
49769
|
+
// 7. 输出成功信息
|
|
49770
|
+
console.log('');
|
|
49771
|
+
console.log('🎉 Agent+ Space 初始化完成!');
|
|
49772
|
+
console.log('');
|
|
49773
|
+
console.log('📋 已创建的文件:');
|
|
49774
|
+
allFiles = __spreadArray(__spreadArray([], __read(baseResult.files), false), __read(toolResult.files), false);
|
|
49775
|
+
allFiles.forEach(function (file) {
|
|
49776
|
+
var relativePath = path__namespace.relative(cwd, file);
|
|
49777
|
+
console.log(" \u2713 ".concat(relativePath));
|
|
49778
|
+
});
|
|
49779
|
+
console.log('');
|
|
49780
|
+
console.log('🚀 下一步:');
|
|
49781
|
+
console.log(" cd ".concat(cwd));
|
|
49782
|
+
console.log(' appthen connect');
|
|
49783
|
+
console.log('');
|
|
49784
|
+
console.log('📖 更多信息:');
|
|
49785
|
+
console.log(' - 查看 .appthen/prompts/README.md 了解提示词使用');
|
|
49786
|
+
if (tool === 'claude-code') {
|
|
49787
|
+
console.log(' - 查看 .claude/settings.json 了解 Hooks 配置');
|
|
49788
|
+
}
|
|
49789
|
+
else if (tool === 'cursor') {
|
|
49790
|
+
console.log(' - 查看 .cursor/rules.md 了解 Cursor Rules');
|
|
49791
|
+
}
|
|
49792
|
+
else if (tool === 'windsurf') {
|
|
49793
|
+
console.log(' - 查看 .windsurf/cascade.json 了解 Cascade 配置');
|
|
49794
|
+
}
|
|
49795
|
+
else if (tool === 'coder') {
|
|
49796
|
+
console.log(' - 查看 .coder/config.json 了解配置选项');
|
|
49797
|
+
}
|
|
49798
|
+
else if (tool === 'augment') {
|
|
49799
|
+
console.log(' - 查看 .augment/context/project-context.md 了解项目上下文');
|
|
49800
|
+
}
|
|
49801
|
+
console.log('');
|
|
49802
|
+
return [2 /*return*/, {
|
|
49803
|
+
success: true,
|
|
49804
|
+
message: 'Space initialized successfully',
|
|
49805
|
+
spaceId: spaceId,
|
|
49806
|
+
files: allFiles,
|
|
49807
|
+
}];
|
|
49808
|
+
case 6:
|
|
49809
|
+
error_1 = _f.sent();
|
|
49810
|
+
console.error('');
|
|
49811
|
+
console.error('❌ 初始化失败:', error_1.message);
|
|
49812
|
+
console.error('');
|
|
49813
|
+
if (verbose) {
|
|
49814
|
+
console.error('错误详情:', error_1);
|
|
49815
|
+
}
|
|
49816
|
+
return [2 /*return*/, {
|
|
49817
|
+
success: false,
|
|
49818
|
+
error: error_1.message,
|
|
49819
|
+
}];
|
|
49820
|
+
case 7: return [2 /*return*/];
|
|
49821
|
+
}
|
|
49822
|
+
});
|
|
49823
|
+
});
|
|
49824
|
+
}
|
|
49825
|
+
/**
|
|
49826
|
+
* 提示用户选择 AI 工具
|
|
49827
|
+
*/
|
|
49828
|
+
function promptForTool() {
|
|
49829
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49830
|
+
var inquirer, answer;
|
|
49831
|
+
return __generator(this, function (_a) {
|
|
49832
|
+
switch (_a.label) {
|
|
49833
|
+
case 0:
|
|
49834
|
+
_a.trys.push([0, 3, , 4]);
|
|
49835
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('inquirer')); })];
|
|
49836
|
+
case 1:
|
|
49837
|
+
inquirer = _a.sent();
|
|
49838
|
+
return [4 /*yield*/, inquirer.default.prompt([
|
|
49839
|
+
{
|
|
49840
|
+
type: 'list',
|
|
49841
|
+
name: 'tool',
|
|
49842
|
+
message: '请选择你使用的 AI 编码工具:',
|
|
49843
|
+
choices: AI_TOOLS.map(function (tool) { return ({
|
|
49844
|
+
name: tool.name,
|
|
49845
|
+
value: tool.value,
|
|
49846
|
+
}); }),
|
|
49847
|
+
},
|
|
49848
|
+
])];
|
|
49849
|
+
case 2:
|
|
49850
|
+
answer = _a.sent();
|
|
49851
|
+
return [2 /*return*/, answer.tool];
|
|
49852
|
+
case 3:
|
|
49853
|
+
_a.sent();
|
|
49854
|
+
// 如果 inquirer 不可用,提供友好的错误提示
|
|
49855
|
+
console.log('');
|
|
49856
|
+
console.log('⚠️ 无法启动交互式选择');
|
|
49857
|
+
console.log('');
|
|
49858
|
+
console.log('💡 请使用 --tool 参数指定 AI 工具:');
|
|
49859
|
+
console.log('');
|
|
49860
|
+
console.log(' appthen init-space --tool claude-code # Claude Code');
|
|
49861
|
+
console.log(' appthen init-space --tool cursor # Cursor');
|
|
49862
|
+
console.log(' appthen init-space --tool windsurf # Windsurf');
|
|
49863
|
+
console.log(' appthen init-space --tool coder # 阿里云 Coder');
|
|
49864
|
+
console.log(' appthen init-space --tool augment # Augment');
|
|
49865
|
+
console.log(' appthen init-space --tool other # 其他/跳过');
|
|
49866
|
+
console.log('');
|
|
49867
|
+
throw new Error('需要指定 --tool 参数');
|
|
49868
|
+
case 4: return [2 /*return*/];
|
|
49869
|
+
}
|
|
49870
|
+
});
|
|
49871
|
+
});
|
|
49872
|
+
}
|
|
49873
|
+
/**
|
|
49874
|
+
* 根据工具生成特定文件
|
|
49875
|
+
*/
|
|
49876
|
+
function generateToolSpecificFiles(tool, cwd, config, verbose, skipHooks) {
|
|
49877
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49878
|
+
var _a, generator, generator, generator, generator, generator;
|
|
49879
|
+
return __generator(this, function (_b) {
|
|
49880
|
+
switch (_b.label) {
|
|
49881
|
+
case 0:
|
|
49882
|
+
_a = tool;
|
|
49883
|
+
switch (_a) {
|
|
49884
|
+
case 'claude-code': return [3 /*break*/, 1];
|
|
49885
|
+
case 'cursor': return [3 /*break*/, 3];
|
|
49886
|
+
case 'windsurf': return [3 /*break*/, 5];
|
|
49887
|
+
case 'coder': return [3 /*break*/, 7];
|
|
49888
|
+
case 'augment': return [3 /*break*/, 9];
|
|
49889
|
+
case 'other': return [3 /*break*/, 11];
|
|
49890
|
+
}
|
|
49891
|
+
return [3 /*break*/, 11];
|
|
49892
|
+
case 1:
|
|
49893
|
+
generator = new ClaudeCodeGenerator(cwd, config, verbose);
|
|
49894
|
+
return [4 /*yield*/, generator.generate(skipHooks)];
|
|
49895
|
+
case 2: return [2 /*return*/, _b.sent()];
|
|
49896
|
+
case 3:
|
|
49897
|
+
generator = new CursorGenerator(cwd, config, verbose);
|
|
49898
|
+
return [4 /*yield*/, generator.generate()];
|
|
49899
|
+
case 4: return [2 /*return*/, _b.sent()];
|
|
49900
|
+
case 5:
|
|
49901
|
+
generator = new WindsurfGenerator(cwd, config, verbose);
|
|
49902
|
+
return [4 /*yield*/, generator.generate()];
|
|
49903
|
+
case 6: return [2 /*return*/, _b.sent()];
|
|
49904
|
+
case 7:
|
|
49905
|
+
generator = new CoderGenerator(cwd, config, verbose);
|
|
49906
|
+
return [4 /*yield*/, generator.generate()];
|
|
49907
|
+
case 8: return [2 /*return*/, _b.sent()];
|
|
49908
|
+
case 9:
|
|
49909
|
+
generator = new AugmentGenerator(cwd, config, verbose);
|
|
49910
|
+
return [4 /*yield*/, generator.generate()];
|
|
49911
|
+
case 10: return [2 /*return*/, _b.sent()];
|
|
49912
|
+
case 11:
|
|
49913
|
+
{
|
|
49914
|
+
// 只生成基础配置,不生成工具特定文件
|
|
49915
|
+
if (verbose) {
|
|
49916
|
+
console.log('⏭️ 跳过工具特定配置');
|
|
49917
|
+
}
|
|
49918
|
+
return [2 /*return*/, {
|
|
49919
|
+
success: true,
|
|
49920
|
+
files: [],
|
|
49921
|
+
message: 'No tool-specific configuration generated',
|
|
49922
|
+
}];
|
|
49923
|
+
}
|
|
49924
|
+
case 12: return [2 /*return*/];
|
|
49925
|
+
}
|
|
49926
|
+
});
|
|
49927
|
+
});
|
|
49928
|
+
}
|
|
49929
|
+
/**
|
|
49930
|
+
* 获取工具的显示名称
|
|
49931
|
+
*/
|
|
49932
|
+
function getToolName(tool) {
|
|
49933
|
+
var toolChoice = AI_TOOLS.find(function (t) { return t.value === tool; });
|
|
49934
|
+
return toolChoice ? toolChoice.name : tool;
|
|
49935
|
+
}
|
|
49936
|
+
|
|
48007
49937
|
exports.ShadowSpace = ShadowSpace;
|
|
48008
49938
|
exports.ShadowSpaceDebugger = ShadowSpaceDebugger;
|
|
48009
49939
|
exports.TSXComplianceChecker = TSXComplianceChecker;
|
|
@@ -48022,6 +49952,7 @@ exports.generateFixSuggestions = generateFixSuggestions;
|
|
|
48022
49952
|
exports.getPureValue = getPureValue;
|
|
48023
49953
|
exports.initClaudeHooks = initClaudeHooks;
|
|
48024
49954
|
exports.initSolution = initSolution;
|
|
49955
|
+
exports.initSpace = initSpace;
|
|
48025
49956
|
exports.isFileCompliant = isFileCompliant;
|
|
48026
49957
|
exports.releaseMaterial = releaseMaterial;
|
|
48027
49958
|
exports.run = run;
|