@coze-arch/cli 0.0.5-alpha.6339fe → 0.0.6
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/lib/__templates__/nuxt-vue/nuxt.config.ts +0 -13
- package/lib/__templates__/taro/components.md +1686 -0
- package/lib/__templates__/taro/eslint.config.mjs +8 -2
- package/lib/__templates__/taro/package.json +1 -1
- package/lib/__templates__/taro/pnpm-lock.yaml +5 -5
- package/lib/__templates__/taro/src/app.tsx +6 -1
- package/lib/__templates__/taro/src/components/ui/accordion.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/calendar.tsx +4 -4
- package/lib/__templates__/taro/src/components/ui/carousel.tsx +2 -2
- package/lib/__templates__/taro/src/components/ui/command.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/context-menu.tsx +3 -3
- package/lib/__templates__/taro/src/components/ui/dialog.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +3 -3
- package/lib/__templates__/taro/src/components/ui/input-otp.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/menubar.tsx +3 -3
- package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +2 -0
- package/lib/__templates__/taro/src/components/ui/pagination.tsx +3 -3
- package/lib/__templates__/taro/src/components/ui/resizable.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/select.tsx +4 -4
- package/lib/__templates__/taro/src/components/ui/sheet.tsx +1 -1
- package/lib/__templates__/taro/src/components/ui/toast.tsx +1 -1
- package/lib/__templates__/taro/types/lucide.d.ts +6 -0
- package/lib/cli.js +122 -968
- package/package.json +1 -2
package/lib/cli.js
CHANGED
|
@@ -15,7 +15,6 @@ var fs$1 = require('fs/promises');
|
|
|
15
15
|
var os = require('os');
|
|
16
16
|
var jsYaml = require('js-yaml');
|
|
17
17
|
var toml = require('@iarna/toml');
|
|
18
|
-
var fastGlob = require('fast-glob');
|
|
19
18
|
var child_process = require('child_process');
|
|
20
19
|
var addFormats = require('ajv-formats');
|
|
21
20
|
var Ajv = require('ajv');
|
|
@@ -1491,7 +1490,7 @@ var browserClient = createBaseClient();
|
|
|
1491
1490
|
|
|
1492
1491
|
|
|
1493
1492
|
|
|
1494
|
-
const log$
|
|
1493
|
+
const log$2 = debug('slardar:transport');
|
|
1495
1494
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
1496
1495
|
const noop = () => {};
|
|
1497
1496
|
|
|
@@ -1511,22 +1510,22 @@ const noop = () => {};
|
|
|
1511
1510
|
function makeRequest(options) {
|
|
1512
1511
|
const { url, method, data, success = noop, fail = noop, getResponseText = noop } = options;
|
|
1513
1512
|
|
|
1514
|
-
log$
|
|
1513
|
+
log$2('Making %s request to %s', method, url);
|
|
1515
1514
|
if (data) {
|
|
1516
|
-
log$
|
|
1515
|
+
log$2('Request data: %s', data.slice(0, 200));
|
|
1517
1516
|
}
|
|
1518
1517
|
|
|
1519
1518
|
// 检查 URL 是否有效
|
|
1520
1519
|
if (!url || typeof url !== 'string') {
|
|
1521
1520
|
const error = new Error(`Invalid URL: ${url}`);
|
|
1522
|
-
log$
|
|
1521
|
+
log$2('Invalid URL provided: %o', url);
|
|
1523
1522
|
fail(error);
|
|
1524
1523
|
return;
|
|
1525
1524
|
}
|
|
1526
1525
|
|
|
1527
1526
|
try {
|
|
1528
1527
|
const urlObj = new URL(url);
|
|
1529
|
-
log$
|
|
1528
|
+
log$2('Parsed URL - protocol: %s, hostname: %s, port: %s, path: %s',
|
|
1530
1529
|
urlObj.protocol, urlObj.hostname, urlObj.port, urlObj.pathname);
|
|
1531
1530
|
|
|
1532
1531
|
const isHttps = urlObj.protocol === 'https:';
|
|
@@ -1544,34 +1543,34 @@ function makeRequest(options) {
|
|
|
1544
1543
|
},
|
|
1545
1544
|
},
|
|
1546
1545
|
res => {
|
|
1547
|
-
log$
|
|
1546
|
+
log$2('Response callback triggered: status=%s', res.statusCode);
|
|
1548
1547
|
let responseText = '';
|
|
1549
1548
|
|
|
1550
1549
|
res.on('data', chunk => {
|
|
1551
|
-
log$
|
|
1550
|
+
log$2('Response data chunk received: %s bytes', chunk.length);
|
|
1552
1551
|
responseText += chunk.toString();
|
|
1553
1552
|
});
|
|
1554
1553
|
|
|
1555
1554
|
res.on('end', () => {
|
|
1556
|
-
log$
|
|
1557
|
-
log$
|
|
1555
|
+
log$2('Response end event fired');
|
|
1556
|
+
log$2('Response received: status=%s, body=%s', res.statusCode, responseText.slice(0, 200));
|
|
1558
1557
|
getResponseText(responseText);
|
|
1559
1558
|
|
|
1560
1559
|
try {
|
|
1561
1560
|
if (res.statusCode && res.statusCode >= 400) {
|
|
1562
|
-
log$
|
|
1561
|
+
log$2('Request failed with status %s: %s', res.statusCode, responseText);
|
|
1563
1562
|
fail(new Error(responseText || res.statusMessage || 'Request failed'));
|
|
1564
1563
|
} else if (responseText) {
|
|
1565
1564
|
// eslint-disable-next-line no-restricted-syntax -- Parsing trusted Slardar API responses
|
|
1566
1565
|
const result = JSON.parse(responseText);
|
|
1567
|
-
log$
|
|
1566
|
+
log$2('Request succeeded');
|
|
1568
1567
|
success(result);
|
|
1569
1568
|
} else {
|
|
1570
|
-
log$
|
|
1569
|
+
log$2('Request succeeded with empty response');
|
|
1571
1570
|
success({});
|
|
1572
1571
|
}
|
|
1573
1572
|
} catch (e) {
|
|
1574
|
-
log$
|
|
1573
|
+
log$2('Failed to parse response: %s', (e ).message);
|
|
1575
1574
|
fail(e );
|
|
1576
1575
|
}
|
|
1577
1576
|
});
|
|
@@ -1579,12 +1578,12 @@ function makeRequest(options) {
|
|
|
1579
1578
|
);
|
|
1580
1579
|
|
|
1581
1580
|
req.on('error', err => {
|
|
1582
|
-
log$
|
|
1581
|
+
log$2('Request error: %s', err.message);
|
|
1583
1582
|
fail(err);
|
|
1584
1583
|
});
|
|
1585
1584
|
|
|
1586
1585
|
req.on('timeout', () => {
|
|
1587
|
-
log$
|
|
1586
|
+
log$2('Request timeout');
|
|
1588
1587
|
req.destroy();
|
|
1589
1588
|
fail(new Error('Request timeout'));
|
|
1590
1589
|
});
|
|
@@ -1595,7 +1594,7 @@ function makeRequest(options) {
|
|
|
1595
1594
|
|
|
1596
1595
|
req.end();
|
|
1597
1596
|
} catch (e) {
|
|
1598
|
-
log$
|
|
1597
|
+
log$2('Exception during request: %s', (e ).message);
|
|
1599
1598
|
fail(e );
|
|
1600
1599
|
}
|
|
1601
1600
|
}
|
|
@@ -1606,14 +1605,14 @@ function makeRequest(options) {
|
|
|
1606
1605
|
function createNodeTransport() {
|
|
1607
1606
|
return {
|
|
1608
1607
|
get(options) {
|
|
1609
|
-
log$
|
|
1608
|
+
log$2('Transport GET called: %s', options.url);
|
|
1610
1609
|
makeRequest({
|
|
1611
1610
|
method: 'GET',
|
|
1612
1611
|
...options,
|
|
1613
1612
|
});
|
|
1614
1613
|
},
|
|
1615
1614
|
post({ url, data }) {
|
|
1616
|
-
log$
|
|
1615
|
+
log$2('Transport POST called: %s', url);
|
|
1617
1616
|
makeRequest({
|
|
1618
1617
|
method: 'POST',
|
|
1619
1618
|
url,
|
|
@@ -1634,7 +1633,7 @@ function _nullishCoalesce$3(lhs, rhsFn) { if (lhs != null) { return lhs; } else
|
|
|
1634
1633
|
|
|
1635
1634
|
// 创建 debug 实例
|
|
1636
1635
|
// 使用方式: DEBUG=slardar:* your-cli-command
|
|
1637
|
-
const log$
|
|
1636
|
+
const log$1 = debug('slardar:reporter');
|
|
1638
1637
|
|
|
1639
1638
|
/**
|
|
1640
1639
|
* Slardar CLI Reporter
|
|
@@ -1659,12 +1658,12 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1659
1658
|
*/
|
|
1660
1659
|
setup(config) {
|
|
1661
1660
|
if (this.initialized) {
|
|
1662
|
-
log$
|
|
1661
|
+
log$1('Already initialized, skipping setup');
|
|
1663
1662
|
return;
|
|
1664
1663
|
}
|
|
1665
1664
|
|
|
1666
1665
|
try {
|
|
1667
|
-
log$
|
|
1666
|
+
log$1('Initializing Slardar with config:', {
|
|
1668
1667
|
bid: config.bid,
|
|
1669
1668
|
release: config.release,
|
|
1670
1669
|
env: config.env,
|
|
@@ -1697,7 +1696,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1697
1696
|
|
|
1698
1697
|
// 添加 send 钩子来追踪事件上报
|
|
1699
1698
|
this.client.on('send', (ev) => {
|
|
1700
|
-
log$
|
|
1699
|
+
log$1(
|
|
1701
1700
|
'send hook called for event: %s',
|
|
1702
1701
|
(_optionalChain$6([ev, 'optionalAccess', _ => _.ev_type]) ) || 'unknown',
|
|
1703
1702
|
);
|
|
@@ -1705,9 +1704,9 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1705
1704
|
|
|
1706
1705
|
this.client.start();
|
|
1707
1706
|
this.initialized = true;
|
|
1708
|
-
log$
|
|
1707
|
+
log$1('Slardar initialized successfully');
|
|
1709
1708
|
} catch (error) {
|
|
1710
|
-
log$
|
|
1709
|
+
log$1('Failed to initialize:', error);
|
|
1711
1710
|
}
|
|
1712
1711
|
}
|
|
1713
1712
|
|
|
@@ -1716,7 +1715,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1716
1715
|
*/
|
|
1717
1716
|
ensureInitialized() {
|
|
1718
1717
|
if (!this.initialized) {
|
|
1719
|
-
log$
|
|
1718
|
+
log$1('Not initialized, call setup() first');
|
|
1720
1719
|
return false;
|
|
1721
1720
|
}
|
|
1722
1721
|
return true;
|
|
@@ -1738,7 +1737,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1738
1737
|
}
|
|
1739
1738
|
|
|
1740
1739
|
try {
|
|
1741
|
-
log$
|
|
1740
|
+
log$1('Sending event:', { name, metrics, categories });
|
|
1742
1741
|
|
|
1743
1742
|
// 过滤掉 undefined 值以满足 Slardar 类型要求
|
|
1744
1743
|
const cleanMetrics = metrics
|
|
@@ -1763,7 +1762,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1763
1762
|
categories: cleanCategories ,
|
|
1764
1763
|
})]);
|
|
1765
1764
|
} catch (error) {
|
|
1766
|
-
log$
|
|
1765
|
+
log$1('Failed to send event:', error);
|
|
1767
1766
|
}
|
|
1768
1767
|
}
|
|
1769
1768
|
|
|
@@ -1783,7 +1782,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1783
1782
|
}
|
|
1784
1783
|
|
|
1785
1784
|
try {
|
|
1786
|
-
log$
|
|
1785
|
+
log$1('Sending log:', { level, message, extra });
|
|
1787
1786
|
// 使用 sendEvent 发送日志事件
|
|
1788
1787
|
this.sendEvent('cli_log', undefined, {
|
|
1789
1788
|
level,
|
|
@@ -1791,7 +1790,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1791
1790
|
...extra,
|
|
1792
1791
|
});
|
|
1793
1792
|
} catch (error) {
|
|
1794
|
-
log$
|
|
1793
|
+
log$1('Failed to send log:', error);
|
|
1795
1794
|
}
|
|
1796
1795
|
}
|
|
1797
1796
|
|
|
@@ -1825,7 +1824,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1825
1824
|
},
|
|
1826
1825
|
};
|
|
1827
1826
|
|
|
1828
|
-
log$
|
|
1827
|
+
log$1('Reporting JS error:', {
|
|
1829
1828
|
name: error.name,
|
|
1830
1829
|
message: error.message.slice(0, 100),
|
|
1831
1830
|
stack: _optionalChain$6([error, 'access', _5 => _5.stack, 'optionalAccess', _6 => _6.slice, 'call', _7 => _7(0, 200)]),
|
|
@@ -1835,9 +1834,9 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1835
1834
|
|
|
1836
1835
|
// 使用 Slardar 的 js_error 事件类型,这样会显示在 JS 错误总览页面
|
|
1837
1836
|
this.client.report(errorEvent);
|
|
1838
|
-
log$
|
|
1837
|
+
log$1('JS error reported successfully');
|
|
1839
1838
|
} catch (err) {
|
|
1840
|
-
log$
|
|
1839
|
+
log$1('Failed to report error:', err);
|
|
1841
1840
|
}
|
|
1842
1841
|
}
|
|
1843
1842
|
|
|
@@ -1858,7 +1857,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1858
1857
|
if (!this.ensureInitialized()) {
|
|
1859
1858
|
return;
|
|
1860
1859
|
}
|
|
1861
|
-
log$
|
|
1860
|
+
log$1('Merging context:', context);
|
|
1862
1861
|
_optionalChain$6([this, 'access', _12 => _12.client, 'access', _13 => _13.context, 'optionalAccess', _14 => _14.merge, 'call', _15 => _15(context)]);
|
|
1863
1862
|
}
|
|
1864
1863
|
|
|
@@ -1895,7 +1894,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1895
1894
|
}
|
|
1896
1895
|
|
|
1897
1896
|
try {
|
|
1898
|
-
log$
|
|
1897
|
+
log$1('Updating config:', config);
|
|
1899
1898
|
this.client.config({
|
|
1900
1899
|
userId: config.userId,
|
|
1901
1900
|
release: config.release,
|
|
@@ -1903,7 +1902,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1903
1902
|
env: config.env,
|
|
1904
1903
|
});
|
|
1905
1904
|
} catch (error) {
|
|
1906
|
-
log$
|
|
1905
|
+
log$1('Failed to update config:', error);
|
|
1907
1906
|
}
|
|
1908
1907
|
}
|
|
1909
1908
|
|
|
@@ -1915,11 +1914,11 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
|
|
|
1915
1914
|
if (!this.ensureInitialized()) {
|
|
1916
1915
|
return;
|
|
1917
1916
|
}
|
|
1918
|
-
log$
|
|
1917
|
+
log$1('Flushing Slardar data...');
|
|
1919
1918
|
_optionalChain$6([this, 'access', _24 => _24.client, 'access', _25 => _25.getSender, 'optionalCall', _26 => _26(), 'optionalAccess', _27 => _27.flush, 'call', _28 => _28()]);
|
|
1920
|
-
log$
|
|
1919
|
+
log$1('Waiting %dms for events to be sent...', waitMs);
|
|
1921
1920
|
await new Promise(resolve => setTimeout(resolve, waitMs));
|
|
1922
|
-
log$
|
|
1921
|
+
log$1('Slardar data flushed');
|
|
1923
1922
|
}
|
|
1924
1923
|
|
|
1925
1924
|
/**
|
|
@@ -2106,7 +2105,7 @@ const EventBuilder = {
|
|
|
2106
2105
|
};
|
|
2107
2106
|
|
|
2108
2107
|
var name = "@coze-arch/cli";
|
|
2109
|
-
var version = "0.0.
|
|
2108
|
+
var version = "0.0.6";
|
|
2110
2109
|
var description = "coze coding devtools cli";
|
|
2111
2110
|
var license = "MIT";
|
|
2112
2111
|
var author = "fanwenjie.fe@bytedance.com";
|
|
@@ -2146,7 +2145,6 @@ var dependencies = {
|
|
|
2146
2145
|
commander: "~12.1.0",
|
|
2147
2146
|
debug: "^4.3.7",
|
|
2148
2147
|
ejs: "^3.1.10",
|
|
2149
|
-
"fast-glob": "^3.3.3",
|
|
2150
2148
|
"js-yaml": "^4.1.0",
|
|
2151
2149
|
minimist: "^1.2.5",
|
|
2152
2150
|
shelljs: "^0.10.0"
|
|
@@ -2211,7 +2209,7 @@ function _optionalChain$4(ops) { let lastAccessLHS = undefined; let value = ops[
|
|
|
2211
2209
|
* Slardar 监控初始化和上报
|
|
2212
2210
|
*/
|
|
2213
2211
|
|
|
2214
|
-
const log
|
|
2212
|
+
const log = debug('slardar:cli');
|
|
2215
2213
|
|
|
2216
2214
|
/**
|
|
2217
2215
|
* 安全执行函数包装器
|
|
@@ -2224,18 +2222,18 @@ function safeRun(
|
|
|
2224
2222
|
) {
|
|
2225
2223
|
return ((...args) => {
|
|
2226
2224
|
try {
|
|
2227
|
-
log
|
|
2225
|
+
log('Calling Slardar function: %s', name);
|
|
2228
2226
|
const result = fn(...args);
|
|
2229
2227
|
|
|
2230
2228
|
// 如果是 Promise,处理异步错误
|
|
2231
2229
|
if (result instanceof Promise) {
|
|
2232
2230
|
return result
|
|
2233
2231
|
.then(res => {
|
|
2234
|
-
log
|
|
2232
|
+
log('Slardar function %s completed', name);
|
|
2235
2233
|
return res;
|
|
2236
2234
|
})
|
|
2237
2235
|
.catch(error => {
|
|
2238
|
-
log
|
|
2236
|
+
log(
|
|
2239
2237
|
'Slardar function %s failed: %s',
|
|
2240
2238
|
name,
|
|
2241
2239
|
(error ).message,
|
|
@@ -2244,11 +2242,11 @@ function safeRun(
|
|
|
2244
2242
|
});
|
|
2245
2243
|
}
|
|
2246
2244
|
|
|
2247
|
-
log
|
|
2245
|
+
log('Slardar function %s completed', name);
|
|
2248
2246
|
return result;
|
|
2249
2247
|
} catch (error) {
|
|
2250
2248
|
// Slardar 上报失败不应影响 CLI 正常运行,但要记录错误
|
|
2251
|
-
log
|
|
2249
|
+
log('Slardar function %s failed: %s', name, (error ).message);
|
|
2252
2250
|
}
|
|
2253
2251
|
}) ;
|
|
2254
2252
|
}
|
|
@@ -2812,76 +2810,6 @@ const registerCommand$4 = program => {
|
|
|
2812
2810
|
});
|
|
2813
2811
|
};
|
|
2814
2812
|
|
|
2815
|
-
// ABOUTME: Temporary paths utility for Coze CLI
|
|
2816
|
-
// ABOUTME: Provides centralized management of temporary directories and files
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
/**
|
|
2820
|
-
* Base Coze directory in user's home
|
|
2821
|
-
* Used for storing CLI-related temporary files, logs, and cache
|
|
2822
|
-
* Default: ~/.coze
|
|
2823
|
-
*/
|
|
2824
|
-
const COZE_HOME_DIR = '.coze';
|
|
2825
|
-
|
|
2826
|
-
/**
|
|
2827
|
-
* Logs directory name
|
|
2828
|
-
* Default: .coze-logs
|
|
2829
|
-
*/
|
|
2830
|
-
const LOGS_DIR = '.coze-logs';
|
|
2831
|
-
|
|
2832
|
-
/**
|
|
2833
|
-
* Get the Coze home directory path
|
|
2834
|
-
* Can be customized via COZE_HOME environment variable
|
|
2835
|
-
*
|
|
2836
|
-
* @returns Absolute path to Coze home directory (default: ~/.coze)
|
|
2837
|
-
*/
|
|
2838
|
-
const getCozeHome = () =>
|
|
2839
|
-
process.env.COZE_HOME || path.join(os.homedir(), COZE_HOME_DIR);
|
|
2840
|
-
|
|
2841
|
-
/**
|
|
2842
|
-
* Get the logs directory path
|
|
2843
|
-
* Can be customized via COZE_LOG_DIR environment variable
|
|
2844
|
-
*
|
|
2845
|
-
* @returns Absolute path to logs directory (default: ~/.coze-logs)
|
|
2846
|
-
*/
|
|
2847
|
-
const getCozeLogsDir = () =>
|
|
2848
|
-
process.env.COZE_LOG_DIR || path.join(os.homedir(), LOGS_DIR);
|
|
2849
|
-
|
|
2850
|
-
/**
|
|
2851
|
-
* Get path for a specific file/directory within Coze home
|
|
2852
|
-
*
|
|
2853
|
-
* @param relativePath - Relative path within Coze home directory
|
|
2854
|
-
* @returns Absolute path to the file/directory
|
|
2855
|
-
*
|
|
2856
|
-
* @example
|
|
2857
|
-
* ```ts
|
|
2858
|
-
* // Get routes file path
|
|
2859
|
-
* const routesPath = getCozeFilePath('routes.json');
|
|
2860
|
-
* // Returns: ~/.coze/routes.json
|
|
2861
|
-
*
|
|
2862
|
-
* // Get cache directory
|
|
2863
|
-
* const cacheDir = getCozeFilePath('cache');
|
|
2864
|
-
* // Returns: ~/.coze/cache
|
|
2865
|
-
* ```
|
|
2866
|
-
*/
|
|
2867
|
-
const getCozeFilePath = (relativePath) =>
|
|
2868
|
-
path.join(getCozeHome(), relativePath);
|
|
2869
|
-
|
|
2870
|
-
/**
|
|
2871
|
-
* Get path for a log file
|
|
2872
|
-
*
|
|
2873
|
-
* @param filename - Log file name
|
|
2874
|
-
* @returns Absolute path to the log file
|
|
2875
|
-
*
|
|
2876
|
-
* @example
|
|
2877
|
-
* ```ts
|
|
2878
|
-
* const devLog = getCozeLogPath('dev.log');
|
|
2879
|
-
* // Returns: ~/.coze-logs/dev.log
|
|
2880
|
-
* ```
|
|
2881
|
-
*/
|
|
2882
|
-
const getCozeLogPath = (filename) =>
|
|
2883
|
-
path.join(getCozeLogsDir(), filename);
|
|
2884
|
-
|
|
2885
2813
|
// ABOUTME: This file implements the update command for coze CLI
|
|
2886
2814
|
// ABOUTME: It wraps pnpm update/install to update package dependencies with logging support
|
|
2887
2815
|
|
|
@@ -2892,22 +2820,29 @@ const getCozeLogPath = (filename) =>
|
|
|
2892
2820
|
*/
|
|
2893
2821
|
const LOG_FILE_NAME$1 = 'update.log';
|
|
2894
2822
|
|
|
2823
|
+
/**
|
|
2824
|
+
* 获取日志目录
|
|
2825
|
+
* 优先使用环境变量 COZE_LOG_DIR,否则使用 ~/.coze-logs
|
|
2826
|
+
*/
|
|
2827
|
+
const getLogDir$1 = () =>
|
|
2828
|
+
process.env.COZE_LOG_DIR || path.join(os.homedir(), '.coze-logs');
|
|
2829
|
+
|
|
2895
2830
|
/**
|
|
2896
2831
|
* 解析日志文件路径
|
|
2897
2832
|
* - 如果是绝对路径,直接使用
|
|
2898
|
-
* - 如果是相对路径,基于
|
|
2899
|
-
* -
|
|
2833
|
+
* - 如果是相对路径,基于 getLogDir() + 相对路径
|
|
2834
|
+
* - 如果为空,使用 getLogDir() + LOG_FILE_NAME
|
|
2900
2835
|
*/
|
|
2901
2836
|
const resolveLogFilePath$1 = (logFile) => {
|
|
2902
2837
|
if (!logFile) {
|
|
2903
|
-
return
|
|
2838
|
+
return path.join(getLogDir$1(), LOG_FILE_NAME$1);
|
|
2904
2839
|
}
|
|
2905
2840
|
|
|
2906
2841
|
if (path.isAbsolute(logFile)) {
|
|
2907
2842
|
return logFile;
|
|
2908
2843
|
}
|
|
2909
2844
|
|
|
2910
|
-
return
|
|
2845
|
+
return path.join(getLogDir$1(), logFile);
|
|
2911
2846
|
};
|
|
2912
2847
|
|
|
2913
2848
|
/**
|
|
@@ -3081,7 +3016,6 @@ const handleUpdateError = (
|
|
|
3081
3016
|
/**
|
|
3082
3017
|
* 执行 update 命令的内部实现
|
|
3083
3018
|
*/
|
|
3084
|
-
// eslint-disable-next-line max-lines-per-function
|
|
3085
3019
|
const executeUpdate = (
|
|
3086
3020
|
packageName,
|
|
3087
3021
|
options
|
|
@@ -3695,805 +3629,35 @@ const registerCommand$2 = program => {
|
|
|
3695
3629
|
});
|
|
3696
3630
|
};
|
|
3697
3631
|
|
|
3698
|
-
// ABOUTME: Nuxt route scanner
|
|
3699
|
-
// ABOUTME: Scans Nuxt file-based routing structure to extract page and server routes
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
const log$3 = debug('coze:route-scanner:nuxt');
|
|
3705
|
-
|
|
3706
|
-
/**
|
|
3707
|
-
* Convert Nuxt file path to route path
|
|
3708
|
-
* Examples:
|
|
3709
|
-
* - app/pages/index.vue -> /
|
|
3710
|
-
* - pages/index.vue -> /
|
|
3711
|
-
* - app/pages/blog/index.vue -> /blog
|
|
3712
|
-
* - pages/blog/[id].vue -> /blog/[id]
|
|
3713
|
-
* - server/api/users.ts -> /api/users
|
|
3714
|
-
* - server/routes/webhook.ts -> /webhook
|
|
3715
|
-
*/
|
|
3716
|
-
const nuxtFilePathToRoute = (
|
|
3717
|
-
filePath,
|
|
3718
|
-
type,
|
|
3719
|
-
) => {
|
|
3720
|
-
let route;
|
|
3721
|
-
|
|
3722
|
-
if (type === 'page') {
|
|
3723
|
-
// Remove pages prefix (supports both app/pages/ and pages/) and .vue extension
|
|
3724
|
-
route = filePath
|
|
3725
|
-
.replace(/^app\/pages\//, '')
|
|
3726
|
-
.replace(/^pages\//, '')
|
|
3727
|
-
.replace(/\.vue$/, '')
|
|
3728
|
-
.replace(/\/index$/, ''); // Remove trailing /index
|
|
3729
|
-
|
|
3730
|
-
// Handle index.vue at root (becomes empty string)
|
|
3731
|
-
if (route === 'index') {
|
|
3732
|
-
return '/';
|
|
3733
|
-
}
|
|
3734
|
-
} else {
|
|
3735
|
-
// API routes
|
|
3736
|
-
if (filePath.startsWith('server/api/')) {
|
|
3737
|
-
route = `/api/${filePath
|
|
3738
|
-
.replace(/^server\/api\//, '')
|
|
3739
|
-
.replace(/\.(ts|js)$/, '')}`;
|
|
3740
|
-
} else {
|
|
3741
|
-
// server/routes
|
|
3742
|
-
route = `/${filePath
|
|
3743
|
-
.replace(/^server\/routes\//, '')
|
|
3744
|
-
.replace(/\.(ts|js)$/, '')}`;
|
|
3745
|
-
}
|
|
3746
|
-
}
|
|
3747
|
-
|
|
3748
|
-
// Handle root route
|
|
3749
|
-
if (route === '' || route === '/') {
|
|
3750
|
-
return '/';
|
|
3751
|
-
}
|
|
3752
|
-
|
|
3753
|
-
// Ensure leading slash
|
|
3754
|
-
if (!route.startsWith('/')) {
|
|
3755
|
-
route = `/${route}`;
|
|
3756
|
-
}
|
|
3757
|
-
|
|
3758
|
-
return route;
|
|
3759
|
-
};
|
|
3760
|
-
|
|
3761
|
-
/**
|
|
3762
|
-
* Normalize Nuxt route path to standard format
|
|
3763
|
-
* Converts Nuxt dynamic segments to standard format:
|
|
3764
|
-
* - [id] -> :id
|
|
3765
|
-
* - [...slug] -> :slug*
|
|
3766
|
-
*/
|
|
3767
|
-
const normalizeRoutePath$1 = (routePath) =>
|
|
3768
|
-
routePath
|
|
3769
|
-
.replace(/\[\.\.\.(\w+)\]/g, ':$1*') // [...slug] -> :slug*
|
|
3770
|
-
.replace(/\[(\w+)\]/g, ':$1'); // [id] -> :id
|
|
3771
|
-
/**
|
|
3772
|
-
* Extract dynamic parameter names from route path
|
|
3773
|
-
*/
|
|
3774
|
-
const extractParams$1 = (routePath) => {
|
|
3775
|
-
const params = [];
|
|
3776
|
-
const patterns = [
|
|
3777
|
-
/\[\.\.\.(\w+)\]/g, // [...slug]
|
|
3778
|
-
/\[(\w+)\]/g, // [id]
|
|
3779
|
-
];
|
|
3780
|
-
|
|
3781
|
-
patterns.forEach(pattern => {
|
|
3782
|
-
const matches = routePath.matchAll(pattern);
|
|
3783
|
-
for (const match of matches) {
|
|
3784
|
-
params.push(match[1]);
|
|
3785
|
-
}
|
|
3786
|
-
});
|
|
3787
|
-
|
|
3788
|
-
return params;
|
|
3789
|
-
};
|
|
3790
|
-
|
|
3791
|
-
/**
|
|
3792
|
-
* Scan Nuxt routes from pages and server directories
|
|
3793
|
-
*
|
|
3794
|
-
* Scans for:
|
|
3795
|
-
* - app/pages/**\/*.vue OR pages/**\/*.vue - Page routes (both structures supported)
|
|
3796
|
-
* - server/api/**\/*.{ts,js} - API routes
|
|
3797
|
-
* - server/routes/**\/*.{ts,js} - Server routes
|
|
3798
|
-
*
|
|
3799
|
-
* Excludes:
|
|
3800
|
-
* - app/layouts/, layouts/ - Layout components (NOT routes)
|
|
3801
|
-
* - app.vue, error.vue - Special files (NOT regular routes)
|
|
3802
|
-
*
|
|
3803
|
-
* @param cwd - Current working directory
|
|
3804
|
-
* @returns List of detected routes
|
|
3805
|
-
*/
|
|
3806
|
-
const scanNuxtRoutes = async (cwd) => {
|
|
3807
|
-
log$3('Scanning Nuxt routes in:', cwd);
|
|
3808
|
-
const routes = [];
|
|
3809
|
-
|
|
3810
|
-
// Scan page routes - support both app/pages/ and pages/ directories
|
|
3811
|
-
const pageFiles = await fastGlob.glob(['{app/,}pages/**/*.vue'], {
|
|
3812
|
-
cwd,
|
|
3813
|
-
ignore: [
|
|
3814
|
-
'**/node_modules/**',
|
|
3815
|
-
'**/.nuxt/**',
|
|
3816
|
-
'**/dist/**',
|
|
3817
|
-
'**/.output/**',
|
|
3818
|
-
// Exclude layouts directory (not routes)
|
|
3819
|
-
'**/layouts/**',
|
|
3820
|
-
'app/layouts/**',
|
|
3821
|
-
// Exclude special files
|
|
3822
|
-
'app.vue',
|
|
3823
|
-
'error.vue',
|
|
3824
|
-
],
|
|
3825
|
-
onlyFiles: true,
|
|
3826
|
-
followSymbolicLinks: false,
|
|
3827
|
-
});
|
|
3828
|
-
|
|
3829
|
-
log$3('Found %d page files', pageFiles.length);
|
|
3830
|
-
|
|
3831
|
-
routes.push(
|
|
3832
|
-
...pageFiles.map(file => {
|
|
3833
|
-
const routePath = nuxtFilePathToRoute(file, 'page');
|
|
3834
|
-
const isDynamic = routePath.includes('[');
|
|
3835
|
-
const params = extractParams$1(routePath);
|
|
3836
|
-
|
|
3837
|
-
return {
|
|
3838
|
-
path: normalizeRoutePath$1(routePath),
|
|
3839
|
-
rawPath: routePath,
|
|
3840
|
-
dynamic: isDynamic,
|
|
3841
|
-
params,
|
|
3842
|
-
type: 'page' ,
|
|
3843
|
-
file,
|
|
3844
|
-
framework: 'nuxt' ,
|
|
3845
|
-
};
|
|
3846
|
-
}),
|
|
3847
|
-
);
|
|
3848
|
-
|
|
3849
|
-
// Scan API routes
|
|
3850
|
-
const apiFiles = await fastGlob.glob('server/api/**/*.{ts,js}', {
|
|
3851
|
-
cwd,
|
|
3852
|
-
ignore: ['**/node_modules/**', '**/dist/**', '**/.output/**'],
|
|
3853
|
-
onlyFiles: true,
|
|
3854
|
-
followSymbolicLinks: false,
|
|
3855
|
-
});
|
|
3856
|
-
|
|
3857
|
-
log$3('Found %d API files', apiFiles.length);
|
|
3858
|
-
|
|
3859
|
-
routes.push(
|
|
3860
|
-
...apiFiles.map(file => {
|
|
3861
|
-
const routePath = nuxtFilePathToRoute(file, 'api');
|
|
3862
|
-
const isDynamic = routePath.includes('[');
|
|
3863
|
-
const params = extractParams$1(routePath);
|
|
3864
|
-
|
|
3865
|
-
return {
|
|
3866
|
-
path: normalizeRoutePath$1(routePath),
|
|
3867
|
-
rawPath: routePath,
|
|
3868
|
-
dynamic: isDynamic,
|
|
3869
|
-
params,
|
|
3870
|
-
type: 'api' ,
|
|
3871
|
-
file,
|
|
3872
|
-
framework: 'nuxt' ,
|
|
3873
|
-
};
|
|
3874
|
-
}),
|
|
3875
|
-
);
|
|
3876
|
-
|
|
3877
|
-
// Scan server routes
|
|
3878
|
-
const serverRouteFiles = await fastGlob.glob('server/routes/**/*.{ts,js}', {
|
|
3879
|
-
cwd,
|
|
3880
|
-
ignore: ['**/node_modules/**', '**/dist/**', '**/.output/**'],
|
|
3881
|
-
onlyFiles: true,
|
|
3882
|
-
followSymbolicLinks: false,
|
|
3883
|
-
});
|
|
3884
|
-
|
|
3885
|
-
log$3('Found %d server route files', serverRouteFiles.length);
|
|
3886
|
-
|
|
3887
|
-
routes.push(
|
|
3888
|
-
...serverRouteFiles.map(file => {
|
|
3889
|
-
const routePath = nuxtFilePathToRoute(file, 'api');
|
|
3890
|
-
const isDynamic = routePath.includes('[');
|
|
3891
|
-
const params = extractParams$1(routePath);
|
|
3892
|
-
|
|
3893
|
-
return {
|
|
3894
|
-
path: normalizeRoutePath$1(routePath),
|
|
3895
|
-
rawPath: routePath,
|
|
3896
|
-
dynamic: isDynamic,
|
|
3897
|
-
params,
|
|
3898
|
-
type: 'api' ,
|
|
3899
|
-
file,
|
|
3900
|
-
framework: 'nuxt' ,
|
|
3901
|
-
};
|
|
3902
|
-
}),
|
|
3903
|
-
);
|
|
3904
|
-
|
|
3905
|
-
log$3('Total routes found: %d', routes.length);
|
|
3906
|
-
return routes;
|
|
3907
|
-
};
|
|
3908
|
-
|
|
3909
|
-
// ABOUTME: Next.js route scanner
|
|
3910
|
-
// ABOUTME: Scans Next.js App Router file structure to extract routes
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
const log$2 = debug('coze:route-scanner:nextjs');
|
|
3916
|
-
|
|
3917
|
-
/**
|
|
3918
|
-
* Convert Next.js file path to route path
|
|
3919
|
-
* Examples:
|
|
3920
|
-
* - src/app/page.tsx -> /
|
|
3921
|
-
* - src/app/blog/page.tsx -> /blog
|
|
3922
|
-
* - src/app/blog/[id]/page.tsx -> /blog/[id]
|
|
3923
|
-
* - src/app/api/users/route.ts -> /api/users
|
|
3924
|
-
*/
|
|
3925
|
-
const filePathToRoute = (filePath) => {
|
|
3926
|
-
// Remove src/app prefix and file extension
|
|
3927
|
-
let route = filePath
|
|
3928
|
-
.replace(/^src\/app/, '')
|
|
3929
|
-
.replace(/\/(page|route|layout)\.(tsx?|jsx?)$/, '');
|
|
3930
|
-
|
|
3931
|
-
// Handle root route
|
|
3932
|
-
if (route === '' || route === '/') {
|
|
3933
|
-
return '/';
|
|
3934
|
-
}
|
|
3935
|
-
|
|
3936
|
-
// Ensure leading slash
|
|
3937
|
-
if (!route.startsWith('/')) {
|
|
3938
|
-
route = `/${route}`;
|
|
3939
|
-
}
|
|
3940
|
-
|
|
3941
|
-
return route;
|
|
3942
|
-
};
|
|
3943
|
-
|
|
3944
|
-
/**
|
|
3945
|
-
* Normalize route path to standard format
|
|
3946
|
-
* Converts Next.js dynamic segments to standard format:
|
|
3947
|
-
* - [id] -> :id
|
|
3948
|
-
* - [...slug] -> :slug*
|
|
3949
|
-
* - [[...slug]] -> :slug*?
|
|
3950
|
-
*/
|
|
3951
|
-
const normalizeRoutePath = (routePath) =>
|
|
3952
|
-
routePath
|
|
3953
|
-
.replace(/\[\[\.\.\.(\w+)\]\]/g, ':$1*?') // [[...slug]] -> :slug*?
|
|
3954
|
-
.replace(/\[\.\.\.(\w+)\]/g, ':$1*') // [...slug] -> :slug*
|
|
3955
|
-
.replace(/\[(\w+)\]/g, ':$1'); // [id] -> :id
|
|
3956
|
-
/**
|
|
3957
|
-
* Extract dynamic parameter names from route path
|
|
3958
|
-
* Note: Uses Set to avoid duplicates when patterns overlap (e.g., [[...slug]])
|
|
3959
|
-
*/
|
|
3960
|
-
const extractParams = (routePath) => {
|
|
3961
|
-
const paramsSet = new Set();
|
|
3962
|
-
const patterns = [
|
|
3963
|
-
/\[\[\.\.\.(\w+)\]\]/g, // [[...slug]]
|
|
3964
|
-
/\[\.\.\.(\w+)\]/g, // [...slug]
|
|
3965
|
-
/\[(\w+)\]/g, // [id]
|
|
3966
|
-
];
|
|
3967
|
-
|
|
3968
|
-
patterns.forEach(pattern => {
|
|
3969
|
-
const matches = routePath.matchAll(pattern);
|
|
3970
|
-
for (const match of matches) {
|
|
3971
|
-
paramsSet.add(match[1]);
|
|
3972
|
-
}
|
|
3973
|
-
});
|
|
3974
|
-
|
|
3975
|
-
return Array.from(paramsSet);
|
|
3976
|
-
};
|
|
3977
|
-
|
|
3978
|
-
/**
|
|
3979
|
-
* Determine route type based on file name
|
|
3980
|
-
*/
|
|
3981
|
-
const getRouteType = (filePath) => {
|
|
3982
|
-
if (filePath.includes('/route.')) {
|
|
3983
|
-
return 'api';
|
|
3984
|
-
}
|
|
3985
|
-
return 'page';
|
|
3986
|
-
};
|
|
3987
|
-
|
|
3988
|
-
/**
|
|
3989
|
-
* Scan Next.js routes from src/app directory
|
|
3990
|
-
*
|
|
3991
|
-
* Scans for:
|
|
3992
|
-
* - page.tsx/jsx/ts/js - Page routes
|
|
3993
|
-
* - route.ts/js - API routes
|
|
3994
|
-
*
|
|
3995
|
-
* Note: layout.tsx, loading.tsx, error.tsx are NOT routes, they are UI components
|
|
3996
|
-
*
|
|
3997
|
-
* @param cwd - Current working directory
|
|
3998
|
-
* @returns List of detected routes
|
|
3999
|
-
*/
|
|
4000
|
-
const scanNextjsRoutes = async (cwd) => {
|
|
4001
|
-
log$2('Scanning Next.js routes in:', cwd);
|
|
4002
|
-
|
|
4003
|
-
// Scan for page and route files only (NOT layout, loading, error, etc.)
|
|
4004
|
-
const files = await fastGlob.glob('src/app/**/{page,route}.{tsx,ts,jsx,js}', {
|
|
4005
|
-
cwd,
|
|
4006
|
-
ignore: [
|
|
4007
|
-
'**/node_modules/**',
|
|
4008
|
-
'**/.next/**',
|
|
4009
|
-
'**/dist/**',
|
|
4010
|
-
'**/build/**',
|
|
4011
|
-
'**/.turbo/**',
|
|
4012
|
-
],
|
|
4013
|
-
onlyFiles: true,
|
|
4014
|
-
followSymbolicLinks: false,
|
|
4015
|
-
});
|
|
4016
|
-
|
|
4017
|
-
log$2('Found %d files', files.length);
|
|
4018
|
-
|
|
4019
|
-
return files.map(file => {
|
|
4020
|
-
log$2('Processing file:', file);
|
|
4021
|
-
const routePath = filePathToRoute(file);
|
|
4022
|
-
const isDynamic = routePath.includes('[');
|
|
4023
|
-
const params = extractParams(routePath);
|
|
4024
|
-
|
|
4025
|
-
return {
|
|
4026
|
-
path: normalizeRoutePath(routePath),
|
|
4027
|
-
rawPath: routePath,
|
|
4028
|
-
dynamic: isDynamic,
|
|
4029
|
-
params,
|
|
4030
|
-
type: getRouteType(file),
|
|
4031
|
-
file,
|
|
4032
|
-
framework: 'nextjs',
|
|
4033
|
-
};
|
|
4034
|
-
});
|
|
4035
|
-
};
|
|
4036
|
-
|
|
4037
|
-
// ABOUTME: Route manifest file writer
|
|
4038
|
-
// ABOUTME: Writes route data to JSON file with proper formatting and directory creation
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
/**
|
|
4044
|
-
* Calculate route statistics
|
|
4045
|
-
*/
|
|
4046
|
-
const calculateStats = (routes) => {
|
|
4047
|
-
const dynamic = routes.filter(r => r.dynamic).length;
|
|
4048
|
-
const staticCount = routes.length - dynamic;
|
|
4049
|
-
|
|
4050
|
-
return {
|
|
4051
|
-
total: routes.length,
|
|
4052
|
-
dynamic,
|
|
4053
|
-
static: staticCount,
|
|
4054
|
-
};
|
|
4055
|
-
};
|
|
4056
|
-
|
|
4057
|
-
/**
|
|
4058
|
-
* Resolve output file path
|
|
4059
|
-
* - Relative path: resolve based on cwd
|
|
4060
|
-
* - Absolute path: use as-is
|
|
4061
|
-
*/
|
|
4062
|
-
const resolveOutputPath = (cwd, outputPath) =>
|
|
4063
|
-
path.isAbsolute(outputPath) ? outputPath : path.join(cwd, outputPath);
|
|
4064
|
-
|
|
4065
|
-
/**
|
|
4066
|
-
* Ensure parent directory exists
|
|
4067
|
-
* Handles edge cases like existing files with same name
|
|
4068
|
-
*/
|
|
4069
|
-
const ensureDir$1 = (filePath) => {
|
|
4070
|
-
const dir = path.dirname(filePath);
|
|
4071
|
-
|
|
4072
|
-
// If directory already exists, verify it's actually a directory
|
|
4073
|
-
if (fs.existsSync(dir)) {
|
|
4074
|
-
const stats = fs.statSync(dir);
|
|
4075
|
-
if (!stats.isDirectory()) {
|
|
4076
|
-
throw new Error(`Path exists but is not a directory: ${dir}`);
|
|
4077
|
-
}
|
|
4078
|
-
return; // Directory exists and is valid
|
|
4079
|
-
}
|
|
4080
|
-
|
|
4081
|
-
// Create directory with recursive option (equivalent to mkdir -p)
|
|
4082
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
4083
|
-
};
|
|
4084
|
-
|
|
4085
|
-
// JSON.stringify indent size
|
|
4086
|
-
const JSON_INDENT = 2;
|
|
4087
|
-
|
|
4088
|
-
/**
|
|
4089
|
-
* Write route manifest to JSON file
|
|
4090
|
-
*
|
|
4091
|
-
* @param cwd - Current working directory (not used when outputPath is absolute)
|
|
4092
|
-
* @param routes - List of routes to write
|
|
4093
|
-
* @param templateType - Framework type
|
|
4094
|
-
* @param outputPath - Output file path (absolute or relative to cwd)
|
|
4095
|
-
*/
|
|
4096
|
-
const writeRoutesFile = (
|
|
4097
|
-
cwd,
|
|
4098
|
-
routes,
|
|
4099
|
-
templateType,
|
|
4100
|
-
outputPath,
|
|
4101
|
-
) => {
|
|
4102
|
-
try {
|
|
4103
|
-
const resolvedPath = resolveOutputPath(cwd, outputPath);
|
|
4104
|
-
|
|
4105
|
-
// Ensure parent directory exists
|
|
4106
|
-
ensureDir$1(resolvedPath);
|
|
4107
|
-
|
|
4108
|
-
// Build manifest
|
|
4109
|
-
const manifest = {
|
|
4110
|
-
framework: templateType,
|
|
4111
|
-
generatedAt: new Date().toISOString(),
|
|
4112
|
-
routes,
|
|
4113
|
-
stats: calculateStats(routes),
|
|
4114
|
-
};
|
|
4115
|
-
|
|
4116
|
-
// Write to file with pretty formatting
|
|
4117
|
-
fs.writeFileSync(
|
|
4118
|
-
resolvedPath,
|
|
4119
|
-
JSON.stringify(manifest, null, JSON_INDENT),
|
|
4120
|
-
'utf-8',
|
|
4121
|
-
);
|
|
4122
|
-
} catch (error) {
|
|
4123
|
-
// Wrap error with context for better debugging
|
|
4124
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4125
|
-
throw new Error(`Failed to write routes file: ${errorMessage}`);
|
|
4126
|
-
}
|
|
4127
|
-
};
|
|
4128
|
-
|
|
4129
|
-
/**
|
|
4130
|
-
* Get the absolute path of the output file
|
|
4131
|
-
* Useful for logging and testing
|
|
4132
|
-
*/
|
|
4133
|
-
const getOutputFilePath = (cwd, outputPath) =>
|
|
4134
|
-
resolveOutputPath(cwd, outputPath);
|
|
4135
|
-
|
|
4136
|
-
// ABOUTME: Template type detection logic
|
|
4137
|
-
// ABOUTME: Detects framework type by checking config files and package.json dependencies
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
const log$1 = debug('coze:route-scanner:detect');
|
|
4143
|
-
|
|
4144
|
-
/**
|
|
4145
|
-
* Check if any of the specified files exist
|
|
4146
|
-
*/
|
|
4147
|
-
const hasFile = (cwd, ...files) =>
|
|
4148
|
-
files.some(file => fs.existsSync(path.join(cwd, file)));
|
|
4149
|
-
|
|
4150
|
-
/**
|
|
4151
|
-
* Detect template type by checking config files and package.json dependencies
|
|
4152
|
-
*
|
|
4153
|
-
* Detection rules (priority order):
|
|
4154
|
-
* 1. Next.js (highest) - has `next` dependency + next.config.{js,mjs,ts}
|
|
4155
|
-
* 2. Nuxt - has `nuxt` dependency + nuxt.config.{ts,js,mjs}
|
|
4156
|
-
* 3. Vite (lowest) - has `vite` + `express` dependencies + vite.config.{ts,js,mjs}
|
|
4157
|
-
*
|
|
4158
|
-
* @param cwd - Current working directory
|
|
4159
|
-
* @returns Template type or null if detection fails
|
|
4160
|
-
*/
|
|
4161
|
-
const detectTemplate = (cwd) => {
|
|
4162
|
-
log$1('Detecting template type in:', cwd);
|
|
4163
|
-
|
|
4164
|
-
const pkgPath = path.join(cwd, 'package.json');
|
|
4165
|
-
|
|
4166
|
-
if (!fs.existsSync(pkgPath)) {
|
|
4167
|
-
log$1('package.json not found');
|
|
4168
|
-
return null;
|
|
4169
|
-
}
|
|
4170
|
-
|
|
4171
|
-
try {
|
|
4172
|
-
const pkgContent = fs.readFileSync(pkgPath, 'utf-8');
|
|
4173
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
4174
|
-
const pkg = JSON.parse(pkgContent)
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
;
|
|
4178
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4179
|
-
log$1('Dependencies found:', Object.keys(deps).join(', '));
|
|
4180
|
-
|
|
4181
|
-
// 1. Next.js - highest priority
|
|
4182
|
-
const hasNextDep = !!deps.next;
|
|
4183
|
-
const hasNextConfig = hasFile(
|
|
4184
|
-
cwd,
|
|
4185
|
-
'next.config.js',
|
|
4186
|
-
'next.config.mjs',
|
|
4187
|
-
'next.config.ts',
|
|
4188
|
-
);
|
|
4189
|
-
log$1('Next.js check - dependency:', hasNextDep, 'config:', hasNextConfig);
|
|
4190
|
-
|
|
4191
|
-
if (hasNextDep && hasNextConfig) {
|
|
4192
|
-
log$1('✓ Detected: nextjs');
|
|
4193
|
-
return 'nextjs';
|
|
4194
|
-
}
|
|
4195
|
-
|
|
4196
|
-
// 2. Nuxt - second priority
|
|
4197
|
-
const hasNuxtDep = !!deps.nuxt;
|
|
4198
|
-
const hasNuxtConfig = hasFile(
|
|
4199
|
-
cwd,
|
|
4200
|
-
'nuxt.config.ts',
|
|
4201
|
-
'nuxt.config.js',
|
|
4202
|
-
'nuxt.config.mjs',
|
|
4203
|
-
);
|
|
4204
|
-
log$1('Nuxt check - dependency:', hasNuxtDep, 'config:', hasNuxtConfig);
|
|
4205
|
-
|
|
4206
|
-
if (hasNuxtDep && hasNuxtConfig) {
|
|
4207
|
-
log$1('✓ Detected: nuxt');
|
|
4208
|
-
return 'nuxt';
|
|
4209
|
-
}
|
|
4210
|
-
|
|
4211
|
-
// 3. Vite - lowest priority (requires both vite and express)
|
|
4212
|
-
const hasViteDep = !!deps.vite;
|
|
4213
|
-
const hasExpressDep = !!deps.express;
|
|
4214
|
-
const hasViteConfig = hasFile(
|
|
4215
|
-
cwd,
|
|
4216
|
-
'vite.config.ts',
|
|
4217
|
-
'vite.config.js',
|
|
4218
|
-
'vite.config.mjs',
|
|
4219
|
-
);
|
|
4220
|
-
log$1(
|
|
4221
|
-
'Vite check - vite dep:',
|
|
4222
|
-
hasViteDep,
|
|
4223
|
-
'express dep:',
|
|
4224
|
-
hasExpressDep,
|
|
4225
|
-
'config:',
|
|
4226
|
-
hasViteConfig,
|
|
4227
|
-
);
|
|
4228
|
-
|
|
4229
|
-
if (hasViteDep && hasExpressDep && hasViteConfig) {
|
|
4230
|
-
log$1('✓ Detected: vite');
|
|
4231
|
-
return 'vite';
|
|
4232
|
-
}
|
|
4233
|
-
|
|
4234
|
-
log$1('✗ No template detected');
|
|
4235
|
-
return null;
|
|
4236
|
-
} catch (error) {
|
|
4237
|
-
// Invalid package.json or other errors
|
|
4238
|
-
log$1('Error during detection:', error);
|
|
4239
|
-
return null;
|
|
4240
|
-
}
|
|
4241
|
-
};
|
|
4242
|
-
|
|
4243
|
-
// ABOUTME: Route scanner main entry point
|
|
4244
|
-
// ABOUTME: Orchestrates template detection, route scanning, and polling-based updates
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
const log = debug('coze:route-scanner:main');
|
|
4248
|
-
|
|
4249
|
-
// Polling interval in milliseconds (500ms to balance responsiveness and performance)
|
|
4250
|
-
const POLLING_INTERVAL_MS = 500;
|
|
4251
|
-
|
|
4252
|
-
// Store polling interval for cleanup
|
|
4253
|
-
let pollingInterval = null;
|
|
4254
|
-
let previousRoutesHash = null;
|
|
4255
|
-
|
|
4256
|
-
/**
|
|
4257
|
-
* Scan routes based on template type
|
|
4258
|
-
*/
|
|
4259
|
-
const scanRoutes = async (
|
|
4260
|
-
cwd,
|
|
4261
|
-
templateType,
|
|
4262
|
-
) => {
|
|
4263
|
-
switch (templateType) {
|
|
4264
|
-
case 'nextjs':
|
|
4265
|
-
return scanNextjsRoutes(cwd);
|
|
4266
|
-
case 'nuxt':
|
|
4267
|
-
return scanNuxtRoutes(cwd);
|
|
4268
|
-
case 'vite':
|
|
4269
|
-
return [];
|
|
4270
|
-
default:
|
|
4271
|
-
return [];
|
|
4272
|
-
}
|
|
4273
|
-
};
|
|
4274
|
-
|
|
4275
|
-
/**
|
|
4276
|
-
* Generate a simple hash for routes to detect changes
|
|
4277
|
-
*/
|
|
4278
|
-
const hashRoutes = (routes) =>
|
|
4279
|
-
routes
|
|
4280
|
-
.map(r => `${r.file}:${r.type}`)
|
|
4281
|
-
.sort()
|
|
4282
|
-
.join('|');
|
|
4283
|
-
|
|
4284
|
-
/**
|
|
4285
|
-
* Detect and validate template type
|
|
4286
|
-
* @returns Template type or null if invalid/unsupported
|
|
4287
|
-
*/
|
|
4288
|
-
const detectAndValidateTemplate = (cwd) => {
|
|
4289
|
-
log('Detecting template type');
|
|
4290
|
-
const templateType = detectTemplate(cwd);
|
|
4291
|
-
|
|
4292
|
-
if (!templateType) {
|
|
4293
|
-
log('No template type detected');
|
|
4294
|
-
logger.warn('Unable to detect template type, skipping route scanning');
|
|
4295
|
-
return null;
|
|
4296
|
-
}
|
|
4297
|
-
|
|
4298
|
-
log('Template detected:', templateType);
|
|
4299
|
-
|
|
4300
|
-
if (templateType === 'vite') {
|
|
4301
|
-
log('Skipping Vite template - not supported');
|
|
4302
|
-
return null;
|
|
4303
|
-
}
|
|
4304
|
-
|
|
4305
|
-
return templateType;
|
|
4306
|
-
};
|
|
4307
|
-
|
|
4308
|
-
/**
|
|
4309
|
-
* Perform initial route scan and write to file
|
|
4310
|
-
*/
|
|
4311
|
-
const performInitialScan = async (
|
|
4312
|
-
cwd,
|
|
4313
|
-
templateType,
|
|
4314
|
-
outputPath,
|
|
4315
|
-
) => {
|
|
4316
|
-
log('Starting route scanning');
|
|
4317
|
-
log('Performing initial scan');
|
|
4318
|
-
const routes = await scanRoutes(cwd, templateType);
|
|
4319
|
-
log('Initial scan found %d routes', routes.length);
|
|
4320
|
-
|
|
4321
|
-
log('Writing routes to file:', outputPath);
|
|
4322
|
-
writeRoutesFile(cwd, routes, templateType, outputPath);
|
|
4323
|
-
|
|
4324
|
-
const outputFilePath = getOutputFilePath(cwd, outputPath);
|
|
4325
|
-
log('Routes written to: %s (%d routes)', outputFilePath, routes.length);
|
|
4326
|
-
|
|
4327
|
-
return routes;
|
|
4328
|
-
};
|
|
4329
|
-
|
|
4330
|
-
/**
|
|
4331
|
-
* Setup polling interval to detect route changes
|
|
4332
|
-
*/
|
|
4333
|
-
const setupPolling = (
|
|
4334
|
-
cwd,
|
|
4335
|
-
templateType,
|
|
4336
|
-
outputPath,
|
|
4337
|
-
initialRoutes,
|
|
4338
|
-
) => {
|
|
4339
|
-
previousRoutesHash = hashRoutes(initialRoutes);
|
|
4340
|
-
log('Starting periodic route scanning (every 500ms)');
|
|
4341
|
-
log('About to call setInterval...');
|
|
4342
|
-
|
|
4343
|
-
pollingInterval = setInterval(async () => {
|
|
4344
|
-
try {
|
|
4345
|
-
log('Polling cycle started...');
|
|
4346
|
-
const updatedRoutes = await scanRoutes(cwd, templateType);
|
|
4347
|
-
const newHash = hashRoutes(updatedRoutes);
|
|
4348
|
-
log('Scanned %d routes, hash: %s vs %s', updatedRoutes.length, newHash, previousRoutesHash);
|
|
4349
|
-
|
|
4350
|
-
if (newHash !== previousRoutesHash) {
|
|
4351
|
-
log('Routes changed, updating file');
|
|
4352
|
-
writeRoutesFile(cwd, updatedRoutes, templateType, outputPath);
|
|
4353
|
-
previousRoutesHash = newHash;
|
|
4354
|
-
log('Routes updated (%d routes)', updatedRoutes.length);
|
|
4355
|
-
logger.info(`🔄 Routes updated (${updatedRoutes.length} routes)`);
|
|
4356
|
-
}
|
|
4357
|
-
} catch (pollingError) {
|
|
4358
|
-
log('Polling error:', pollingError);
|
|
4359
|
-
}
|
|
4360
|
-
}, POLLING_INTERVAL_MS);
|
|
4361
|
-
|
|
4362
|
-
log('setInterval called, returned interval ID:', pollingInterval);
|
|
4363
|
-
log('pollingInterval type:', typeof pollingInterval);
|
|
4364
|
-
log('Route polling started (checking every %dms)', POLLING_INTERVAL_MS);
|
|
4365
|
-
|
|
4366
|
-
// Test if interval is actually working by logging after 1 second
|
|
4367
|
-
setTimeout(() => {
|
|
4368
|
-
log('setTimeout test fired after 1 second - event loop is working');
|
|
4369
|
-
}, 1000);
|
|
4370
|
-
};
|
|
4371
|
-
|
|
4372
|
-
/**
|
|
4373
|
-
* Register cleanup handlers for process termination signals
|
|
4374
|
-
* Note: Do NOT listen to 'exit' event because the CLI parent process
|
|
4375
|
-
* exits normally after spawning the dev server child process
|
|
4376
|
-
*/
|
|
4377
|
-
const registerCleanupHandlers = () => {
|
|
4378
|
-
const cleanup = () => {
|
|
4379
|
-
if (pollingInterval) {
|
|
4380
|
-
log('Cleaning up polling interval on process termination');
|
|
4381
|
-
clearInterval(pollingInterval);
|
|
4382
|
-
pollingInterval = null;
|
|
4383
|
-
previousRoutesHash = null;
|
|
4384
|
-
}
|
|
4385
|
-
};
|
|
4386
|
-
|
|
4387
|
-
// Only handle termination signals, not normal exit
|
|
4388
|
-
process.on('SIGINT', cleanup);
|
|
4389
|
-
process.on('SIGTERM', cleanup);
|
|
4390
|
-
};
|
|
4391
|
-
|
|
4392
|
-
/**
|
|
4393
|
-
* Clean up existing polling interval
|
|
4394
|
-
*/
|
|
4395
|
-
const cleanupExistingInterval = () => {
|
|
4396
|
-
if (pollingInterval) {
|
|
4397
|
-
log('Clearing existing polling interval before starting new one');
|
|
4398
|
-
clearInterval(pollingInterval);
|
|
4399
|
-
pollingInterval = null;
|
|
4400
|
-
previousRoutesHash = null;
|
|
4401
|
-
}
|
|
4402
|
-
};
|
|
4403
|
-
|
|
4404
|
-
/**
|
|
4405
|
-
* Start route scanning and polling
|
|
4406
|
-
*
|
|
4407
|
-
* Workflow:
|
|
4408
|
-
* 1. Detect template type (Next.js/Nuxt/Vite)
|
|
4409
|
-
* 2. If Vite, skip scanning (too simple, not worth resources)
|
|
4410
|
-
* 3. Perform initial route scan
|
|
4411
|
-
* 4. Write routes to JSON file
|
|
4412
|
-
* 5. Start periodic polling (every 500ms) to detect route changes
|
|
4413
|
-
*
|
|
4414
|
-
* Note: Uses polling instead of file watching to avoid EMFILE errors
|
|
4415
|
-
*
|
|
4416
|
-
* @param cwd - Current working directory
|
|
4417
|
-
* @param options - Scanning options (output path, etc.)
|
|
4418
|
-
*/
|
|
4419
|
-
const startRouteScanning = async (
|
|
4420
|
-
cwd,
|
|
4421
|
-
options = {},
|
|
4422
|
-
) => {
|
|
4423
|
-
cleanupExistingInterval();
|
|
4424
|
-
|
|
4425
|
-
try {
|
|
4426
|
-
log('startRouteScanning called with cwd:', cwd, 'options:', options);
|
|
4427
|
-
// Default output to ~/.coze/routes.json (user home), can be overridden via options or env var
|
|
4428
|
-
// Using user home avoids conflict with project .coze config file
|
|
4429
|
-
const defaultOutputPath =
|
|
4430
|
-
process.env.COZE_ROUTES_OUTPUT || getCozeFilePath('routes.json');
|
|
4431
|
-
const { outputPath = defaultOutputPath } = options;
|
|
4432
|
-
|
|
4433
|
-
// Step 1: Detect and validate template
|
|
4434
|
-
const templateType = detectAndValidateTemplate(cwd);
|
|
4435
|
-
if (!templateType) {
|
|
4436
|
-
return;
|
|
4437
|
-
}
|
|
4438
|
-
|
|
4439
|
-
// Step 2: Perform initial scan
|
|
4440
|
-
const routes = await performInitialScan(cwd, templateType, outputPath);
|
|
4441
|
-
|
|
4442
|
-
// Step 3: Check if polling is enabled
|
|
4443
|
-
const enablePolling = process.env.COZE_ROUTES_WATCH !== 'false';
|
|
4444
|
-
if (!enablePolling) {
|
|
4445
|
-
log('Route polling disabled via COZE_ROUTES_WATCH=false');
|
|
4446
|
-
return;
|
|
4447
|
-
}
|
|
4448
|
-
|
|
4449
|
-
// Step 4: Setup polling and cleanup handlers
|
|
4450
|
-
log('About to call setupPolling...');
|
|
4451
|
-
setupPolling(cwd, templateType, outputPath, routes);
|
|
4452
|
-
log('setupPolling completed');
|
|
4453
|
-
|
|
4454
|
-
log('About to call registerCleanupHandlers...');
|
|
4455
|
-
registerCleanupHandlers();
|
|
4456
|
-
log('registerCleanupHandlers completed');
|
|
4457
|
-
|
|
4458
|
-
log('startRouteScanning function about to return');
|
|
4459
|
-
} catch (error) {
|
|
4460
|
-
log('ERROR CAUGHT in startRouteScanning:', error);
|
|
4461
|
-
cleanupExistingInterval();
|
|
4462
|
-
|
|
4463
|
-
// Silently handle all errors - route scanning should never break dev server
|
|
4464
|
-
log('Route scanning error:', error);
|
|
4465
|
-
logger.warn(
|
|
4466
|
-
'⚠️ Route scanning skipped due to error (dev server continues normally)',
|
|
4467
|
-
);
|
|
4468
|
-
|
|
4469
|
-
if (process.env.DEBUG) {
|
|
4470
|
-
logger.warn(error instanceof Error ? error.message : String(error));
|
|
4471
|
-
}
|
|
4472
|
-
}
|
|
4473
|
-
};
|
|
4474
|
-
|
|
4475
3632
|
function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
4476
3633
|
/**
|
|
4477
3634
|
* 日志文件名常量
|
|
4478
3635
|
*/
|
|
4479
3636
|
const LOG_FILE_NAME = 'dev.log';
|
|
4480
3637
|
|
|
3638
|
+
/**
|
|
3639
|
+
* 获取日志目录
|
|
3640
|
+
* 优先使用环境变量 COZE_LOG_DIR,否则使用 ~/.coze-logs
|
|
3641
|
+
*/
|
|
3642
|
+
const getLogDir = () =>
|
|
3643
|
+
process.env.COZE_LOG_DIR || path.join(os.homedir(), '.coze-logs');
|
|
3644
|
+
|
|
4481
3645
|
/**
|
|
4482
3646
|
* 解析日志文件路径
|
|
4483
3647
|
* - 如果是绝对路径,直接使用
|
|
4484
|
-
* - 如果是相对路径,基于
|
|
4485
|
-
* -
|
|
3648
|
+
* - 如果是相对路径,基于 getLogDir() + 相对路径
|
|
3649
|
+
* - 如果为空,使用 getLogDir() + LOG_FILE_NAME
|
|
4486
3650
|
*/
|
|
4487
3651
|
const resolveLogFilePath = (logFile) => {
|
|
4488
3652
|
if (!logFile) {
|
|
4489
|
-
return
|
|
3653
|
+
return path.join(getLogDir(), LOG_FILE_NAME);
|
|
4490
3654
|
}
|
|
4491
3655
|
|
|
4492
3656
|
if (path.isAbsolute(logFile)) {
|
|
4493
3657
|
return logFile;
|
|
4494
3658
|
}
|
|
4495
3659
|
|
|
4496
|
-
return
|
|
3660
|
+
return path.join(getLogDir(), logFile);
|
|
4497
3661
|
};
|
|
4498
3662
|
|
|
4499
3663
|
/**
|
|
@@ -4539,21 +3703,15 @@ const executeRun = async (
|
|
|
4539
3703
|
logger.info('');
|
|
4540
3704
|
}
|
|
4541
3705
|
|
|
4542
|
-
// 2.
|
|
4543
|
-
// Note: startRouteScanning handles all errors internally and never throws
|
|
4544
|
-
if (commandName === 'dev') {
|
|
4545
|
-
await startRouteScanning(process.cwd());
|
|
4546
|
-
}
|
|
4547
|
-
|
|
4548
|
-
// 3. 加载 .coze 配置
|
|
3706
|
+
// 2. 加载 .coze 配置
|
|
4549
3707
|
const config = await loadCozeConfig();
|
|
4550
3708
|
const commandArgs = getCommandConfig(config, commandName);
|
|
4551
3709
|
|
|
4552
|
-
//
|
|
3710
|
+
// 3. 准备日志
|
|
4553
3711
|
const logFilePath = resolveLogFilePath(options.logFile);
|
|
4554
3712
|
const logStream = createLogStream(logFilePath);
|
|
4555
3713
|
|
|
4556
|
-
//
|
|
3714
|
+
// 4. 执行命令
|
|
4557
3715
|
const commandString = commandArgs.join(' ');
|
|
4558
3716
|
|
|
4559
3717
|
logger.info(`Executing: ${commandString}`);
|
|
@@ -4580,76 +3738,72 @@ const executeRun = async (
|
|
|
4580
3738
|
logStream.write(data);
|
|
4581
3739
|
})]);
|
|
4582
3740
|
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
childProcess.on('close', (code, signal) => {
|
|
4586
|
-
logStream.end();
|
|
4587
|
-
|
|
4588
|
-
if (code !== 0) {
|
|
4589
|
-
const errorMessage = `Command exited with code ${_nullishCoalesce$1(code, () => ( 'unknown'))}${signal ? ` and signal ${signal}` : ''}`;
|
|
4590
|
-
logger.error(errorMessage);
|
|
4591
|
-
logger.error(`Check log file for details: ${logFilePath}`);
|
|
4592
|
-
|
|
4593
|
-
// 上报命令失败
|
|
4594
|
-
reportError(new Error(errorMessage), {
|
|
4595
|
-
command: commandName,
|
|
4596
|
-
exitCode: String(_nullishCoalesce$1(code, () => ( 'unknown'))),
|
|
4597
|
-
signal: _nullishCoalesce$1(signal, () => ( 'none')),
|
|
4598
|
-
logFile: logFilePath,
|
|
4599
|
-
});
|
|
4600
|
-
reportCommandComplete(commandName, false, Date.now() - cmdStartTime, {
|
|
4601
|
-
args: JSON.stringify(options),
|
|
4602
|
-
errorCode: _nullishCoalesce$1(code, () => ( 1)),
|
|
4603
|
-
errorMessage,
|
|
4604
|
-
});
|
|
4605
|
-
flushSlardar()
|
|
4606
|
-
.then(() => {
|
|
4607
|
-
process.exit(code || 1);
|
|
4608
|
-
})
|
|
4609
|
-
.catch(() => {
|
|
4610
|
-
// Catch any errors in the promise chain to prevent unhandled rejections
|
|
4611
|
-
process.exit(code || 1);
|
|
4612
|
-
});
|
|
4613
|
-
} else {
|
|
4614
|
-
logger.success('Command completed successfully');
|
|
4615
|
-
logger.info(`Log file: ${logFilePath}`);
|
|
4616
|
-
|
|
4617
|
-
// 上报命令成功
|
|
4618
|
-
reportCommandComplete(commandName, true, Date.now() - cmdStartTime, {
|
|
4619
|
-
args: JSON.stringify(options),
|
|
4620
|
-
});
|
|
4621
|
-
// flush 由 main 函数统一处理
|
|
4622
|
-
resolve();
|
|
4623
|
-
}
|
|
4624
|
-
});
|
|
3741
|
+
childProcess.on('close', (code, signal) => {
|
|
3742
|
+
logStream.end();
|
|
4625
3743
|
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
logger.error(
|
|
4629
|
-
|
|
4630
|
-
logger.error(`Stack trace:\n${error.stack}`);
|
|
4631
|
-
}
|
|
4632
|
-
logStream.end();
|
|
3744
|
+
if (code !== 0) {
|
|
3745
|
+
const errorMessage = `Command exited with code ${_nullishCoalesce$1(code, () => ( 'unknown'))}${signal ? ` and signal ${signal}` : ''}`;
|
|
3746
|
+
logger.error(errorMessage);
|
|
3747
|
+
logger.error(`Check log file for details: ${logFilePath}`);
|
|
4633
3748
|
|
|
4634
|
-
//
|
|
4635
|
-
reportError(
|
|
3749
|
+
// 上报命令失败
|
|
3750
|
+
reportError(new Error(errorMessage), {
|
|
4636
3751
|
command: commandName,
|
|
4637
|
-
|
|
3752
|
+
exitCode: String(_nullishCoalesce$1(code, () => ( 'unknown'))),
|
|
3753
|
+
signal: _nullishCoalesce$1(signal, () => ( 'none')),
|
|
3754
|
+
logFile: logFilePath,
|
|
4638
3755
|
});
|
|
4639
3756
|
reportCommandComplete(commandName, false, Date.now() - cmdStartTime, {
|
|
4640
3757
|
args: JSON.stringify(options),
|
|
4641
|
-
errorCode: 1,
|
|
4642
|
-
errorMessage
|
|
3758
|
+
errorCode: _nullishCoalesce$1(code, () => ( 1)),
|
|
3759
|
+
errorMessage,
|
|
4643
3760
|
});
|
|
4644
3761
|
flushSlardar()
|
|
4645
3762
|
.then(() => {
|
|
4646
|
-
process.exit(1);
|
|
3763
|
+
process.exit(code || 1);
|
|
4647
3764
|
})
|
|
4648
3765
|
.catch(() => {
|
|
4649
3766
|
// Catch any errors in the promise chain to prevent unhandled rejections
|
|
4650
|
-
process.exit(1);
|
|
3767
|
+
process.exit(code || 1);
|
|
4651
3768
|
});
|
|
3769
|
+
} else {
|
|
3770
|
+
logger.success('Command completed successfully');
|
|
3771
|
+
logger.info(`Log file: ${logFilePath}`);
|
|
3772
|
+
|
|
3773
|
+
// 上报命令成功
|
|
3774
|
+
reportCommandComplete(commandName, true, Date.now() - cmdStartTime, {
|
|
3775
|
+
args: JSON.stringify(options),
|
|
3776
|
+
});
|
|
3777
|
+
// flush 由 main 函数统一处理
|
|
3778
|
+
}
|
|
3779
|
+
});
|
|
3780
|
+
|
|
3781
|
+
childProcess.on('error', (error) => {
|
|
3782
|
+
logger.error('Failed to execute command:');
|
|
3783
|
+
logger.error(`Error: ${error.message}`);
|
|
3784
|
+
if (error.stack) {
|
|
3785
|
+
logger.error(`Stack trace:\n${error.stack}`);
|
|
3786
|
+
}
|
|
3787
|
+
logStream.end();
|
|
3788
|
+
|
|
3789
|
+
// 上报错误
|
|
3790
|
+
reportError(error, {
|
|
3791
|
+
command: commandName,
|
|
3792
|
+
type: 'child_process_error',
|
|
4652
3793
|
});
|
|
3794
|
+
reportCommandComplete(commandName, false, Date.now() - cmdStartTime, {
|
|
3795
|
+
args: JSON.stringify(options),
|
|
3796
|
+
errorCode: 1,
|
|
3797
|
+
errorMessage: error.message,
|
|
3798
|
+
});
|
|
3799
|
+
flushSlardar()
|
|
3800
|
+
.then(() => {
|
|
3801
|
+
process.exit(1);
|
|
3802
|
+
})
|
|
3803
|
+
.catch(() => {
|
|
3804
|
+
// Catch any errors in the promise chain to prevent unhandled rejections
|
|
3805
|
+
process.exit(1);
|
|
3806
|
+
});
|
|
4653
3807
|
});
|
|
4654
3808
|
} catch (error) {
|
|
4655
3809
|
const err = error instanceof Error ? error : new Error(String(error));
|