@coze-arch/cli 0.0.11 → 0.0.12-alpha.e3bedc

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/cli.js CHANGED
@@ -4,7 +4,7 @@
4
4
  var commander = require('commander');
5
5
  var path = require('path');
6
6
  var fs = require('fs');
7
- var debug$2 = require('debug');
7
+ var debug = require('debug');
8
8
  var node_http = require('node:http');
9
9
  var node_https = require('node:https');
10
10
  var node_path = require('node:path');
@@ -15,6 +15,7 @@ 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 crypto = require('crypto');
18
19
  var fastGlob = require('fast-glob');
19
20
  var child_process = require('child_process');
20
21
  var addFormats = require('ajv-formats');
@@ -1491,7 +1492,7 @@ var browserClient = createBaseClient();
1491
1492
 
1492
1493
 
1493
1494
 
1494
- const log$7 = debug$2('slardar:transport');
1495
+ const log$7 = debug('slardar:transport');
1495
1496
  // eslint-disable-next-line @typescript-eslint/no-empty-function
1496
1497
  const noop = () => {};
1497
1498
 
@@ -1627,14 +1628,14 @@ function createNodeTransport() {
1627
1628
  };
1628
1629
  }
1629
1630
 
1630
- function _nullishCoalesce$8(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$l(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; }/**
1631
+ function _nullishCoalesce$9(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$o(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; }/**
1631
1632
  * Slardar CLI Reporter 主类
1632
1633
  * 封装 @slardar/base 的初始化和上报逻辑
1633
1634
  */
1634
1635
 
1635
1636
  // 创建 debug 实例
1636
1637
  // 使用方式: DEBUG=slardar:* your-cli-command
1637
- const log$6 = debug$2('slardar:reporter');
1638
+ const log$6 = debug('slardar:reporter');
1638
1639
 
1639
1640
  /**
1640
1641
  * Slardar CLI Reporter
@@ -1684,7 +1685,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1684
1685
  release: config.release,
1685
1686
  env: config.env,
1686
1687
  name: config.name,
1687
- useLocalConfig: _nullishCoalesce$8(config.useLocalConfig, () => ( false)), // 默认使用服务端配置
1688
+ useLocalConfig: _nullishCoalesce$9(config.useLocalConfig, () => ( false)), // 默认使用服务端配置
1688
1689
  domain: config.domain,
1689
1690
  // 设置本地采样率为 100%,确保事件不被过滤
1690
1691
  sample: {
@@ -1699,7 +1700,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1699
1700
  this.client.on('send', (ev) => {
1700
1701
  log$6(
1701
1702
  'send hook called for event: %s',
1702
- (_optionalChain$l([ev, 'optionalAccess', _ => _.ev_type]) ) || 'unknown',
1703
+ (_optionalChain$o([ev, 'optionalAccess', _ => _.ev_type]) ) || 'unknown',
1703
1704
  );
1704
1705
  });
1705
1706
 
@@ -1757,7 +1758,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1757
1758
  )
1758
1759
  : undefined;
1759
1760
 
1760
- _optionalChain$l([this, 'access', _2 => _2.client, 'access', _3 => _3.sendEvent, 'optionalCall', _4 => _4({
1761
+ _optionalChain$o([this, 'access', _2 => _2.client, 'access', _3 => _3.sendEvent, 'optionalCall', _4 => _4({
1761
1762
  name,
1762
1763
  metrics: cleanMetrics ,
1763
1764
  categories: cleanCategories ,
@@ -1828,7 +1829,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1828
1829
  log$6('Reporting JS error:', {
1829
1830
  name: error.name,
1830
1831
  message: error.message.slice(0, 100),
1831
- stack: _optionalChain$l([error, 'access', _5 => _5.stack, 'optionalAccess', _6 => _6.slice, 'call', _7 => _7(0, 200)]),
1832
+ stack: _optionalChain$o([error, 'access', _5 => _5.stack, 'optionalAccess', _6 => _6.slice, 'call', _7 => _7(0, 200)]),
1832
1833
  extra,
1833
1834
  source,
1834
1835
  });
@@ -1848,7 +1849,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1848
1849
  if (!this.ensureInitialized()) {
1849
1850
  return;
1850
1851
  }
1851
- _optionalChain$l([this, 'access', _8 => _8.client, 'access', _9 => _9.context, 'optionalAccess', _10 => _10.set, 'call', _11 => _11(key, value)]);
1852
+ _optionalChain$o([this, 'access', _8 => _8.client, 'access', _9 => _9.context, 'optionalAccess', _10 => _10.set, 'call', _11 => _11(key, value)]);
1852
1853
  }
1853
1854
 
1854
1855
  /**
@@ -1859,7 +1860,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1859
1860
  return;
1860
1861
  }
1861
1862
  log$6('Merging context:', context);
1862
- _optionalChain$l([this, 'access', _12 => _12.client, 'access', _13 => _13.context, 'optionalAccess', _14 => _14.merge, 'call', _15 => _15(context)]);
1863
+ _optionalChain$o([this, 'access', _12 => _12.client, 'access', _13 => _13.context, 'optionalAccess', _14 => _14.merge, 'call', _15 => _15(context)]);
1863
1864
  }
1864
1865
 
1865
1866
  /**
@@ -1869,7 +1870,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1869
1870
  if (!this.ensureInitialized()) {
1870
1871
  return;
1871
1872
  }
1872
- _optionalChain$l([this, 'access', _16 => _16.client, 'access', _17 => _17.context, 'optionalAccess', _18 => _18.delete, 'call', _19 => _19(key)]);
1873
+ _optionalChain$o([this, 'access', _16 => _16.client, 'access', _17 => _17.context, 'optionalAccess', _18 => _18.delete, 'call', _19 => _19(key)]);
1873
1874
  }
1874
1875
 
1875
1876
  /**
@@ -1879,7 +1880,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1879
1880
  if (!this.ensureInitialized()) {
1880
1881
  return;
1881
1882
  }
1882
- _optionalChain$l([this, 'access', _20 => _20.client, 'access', _21 => _21.context, 'optionalAccess', _22 => _22.clear, 'call', _23 => _23()]);
1883
+ _optionalChain$o([this, 'access', _20 => _20.client, 'access', _21 => _21.context, 'optionalAccess', _22 => _22.clear, 'call', _23 => _23()]);
1883
1884
  }
1884
1885
 
1885
1886
  /**
@@ -1916,7 +1917,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1916
1917
  return;
1917
1918
  }
1918
1919
  log$6('Flushing Slardar data...');
1919
- _optionalChain$l([this, 'access', _24 => _24.client, 'access', _25 => _25.getSender, 'optionalCall', _26 => _26(), 'optionalAccess', _27 => _27.flush, 'call', _28 => _28()]);
1920
+ _optionalChain$o([this, 'access', _24 => _24.client, 'access', _25 => _25.getSender, 'optionalCall', _26 => _26(), 'optionalAccess', _27 => _27.flush, 'call', _28 => _28()]);
1920
1921
  log$6('Waiting %dms for events to be sent...', waitMs);
1921
1922
  await new Promise(resolve => setTimeout(resolve, waitMs));
1922
1923
  log$6('Slardar data flushed');
@@ -1935,7 +1936,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1935
1936
  */
1936
1937
  const reporter = new SlardarCLIReporter();
1937
1938
 
1938
- function _optionalChain$k(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; }
1939
+ function _optionalChain$n(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; }
1939
1940
 
1940
1941
 
1941
1942
 
@@ -1995,11 +1996,11 @@ const EventBuilder = {
1995
1996
  name: CLI_EVENTS.CLI_COMMAND,
1996
1997
  categories: {
1997
1998
  command,
1998
- args: _optionalChain$k([options, 'optionalAccess', _ => _.args]),
1999
+ args: _optionalChain$n([options, 'optionalAccess', _ => _.args]),
1999
2000
  status: 'running' ,
2000
- ..._optionalChain$k([options, 'optionalAccess', _2 => _2.categories]),
2001
+ ..._optionalChain$n([options, 'optionalAccess', _2 => _2.categories]),
2001
2002
  },
2002
- metrics: _optionalChain$k([options, 'optionalAccess', _3 => _3.metrics]),
2003
+ metrics: _optionalChain$n([options, 'optionalAccess', _3 => _3.metrics]),
2003
2004
  };
2004
2005
  },
2005
2006
 
@@ -2020,13 +2021,13 @@ const EventBuilder = {
2020
2021
  name: CLI_EVENTS.CLI_COMMAND_COMPLETE,
2021
2022
  categories: {
2022
2023
  command,
2023
- args: _optionalChain$k([options, 'optionalAccess', _4 => _4.args]),
2024
+ args: _optionalChain$n([options, 'optionalAccess', _4 => _4.args]),
2024
2025
  status: success ? ('success' ) : ('fail' ),
2025
- ..._optionalChain$k([options, 'optionalAccess', _5 => _5.categories]),
2026
+ ..._optionalChain$n([options, 'optionalAccess', _5 => _5.categories]),
2026
2027
  },
2027
2028
  metrics: {
2028
2029
  duration,
2029
- ...(_optionalChain$k([options, 'optionalAccess', _6 => _6.errorCode]) && { errorCode: options.errorCode }),
2030
+ ...(_optionalChain$n([options, 'optionalAccess', _6 => _6.errorCode]) && { errorCode: options.errorCode }),
2030
2031
  },
2031
2032
  };
2032
2033
  },
@@ -2047,12 +2048,12 @@ const EventBuilder = {
2047
2048
  name: CLI_EVENTS.NETWORK_REQUEST,
2048
2049
  categories: {
2049
2050
  url,
2050
- method: _optionalChain$k([options, 'optionalAccess', _7 => _7.method]) || 'GET',
2051
- statusCode: _optionalChain$k([options, 'optionalAccess', _8 => _8.statusCode, 'optionalAccess', _9 => _9.toString, 'call', _10 => _10()]),
2052
- status: _optionalChain$k([options, 'optionalAccess', _11 => _11.success]) ? ('success' ) : ('fail' ),
2051
+ method: _optionalChain$n([options, 'optionalAccess', _7 => _7.method]) || 'GET',
2052
+ statusCode: _optionalChain$n([options, 'optionalAccess', _8 => _8.statusCode, 'optionalAccess', _9 => _9.toString, 'call', _10 => _10()]),
2053
+ status: _optionalChain$n([options, 'optionalAccess', _11 => _11.success]) ? ('success' ) : ('fail' ),
2053
2054
  },
2054
2055
  metrics: {
2055
- duration: _optionalChain$k([options, 'optionalAccess', _12 => _12.duration]),
2056
+ duration: _optionalChain$n([options, 'optionalAccess', _12 => _12.duration]),
2056
2057
  },
2057
2058
  };
2058
2059
  },
@@ -2074,11 +2075,11 @@ const EventBuilder = {
2074
2075
  categories: {
2075
2076
  operation,
2076
2077
  filePath,
2077
- status: _optionalChain$k([options, 'optionalAccess', _13 => _13.success]) ? ('success' ) : ('fail' ),
2078
+ status: _optionalChain$n([options, 'optionalAccess', _13 => _13.success]) ? ('success' ) : ('fail' ),
2078
2079
  },
2079
2080
  metrics: {
2080
- duration: _optionalChain$k([options, 'optionalAccess', _14 => _14.duration]),
2081
- fileSize: _optionalChain$k([options, 'optionalAccess', _15 => _15.fileSize]),
2081
+ duration: _optionalChain$n([options, 'optionalAccess', _14 => _14.duration]),
2082
+ fileSize: _optionalChain$n([options, 'optionalAccess', _15 => _15.fileSize]),
2082
2083
  },
2083
2084
  };
2084
2085
  },
@@ -2106,7 +2107,7 @@ const EventBuilder = {
2106
2107
  };
2107
2108
 
2108
2109
  var name = "@coze-arch/cli";
2109
- var version = "0.0.11";
2110
+ var version = "0.0.12-alpha.e3bedc";
2110
2111
  var description = "coze coding devtools cli";
2111
2112
  var license = "MIT";
2112
2113
  var author = "fanwenjie.fe@bytedance.com";
@@ -2212,11 +2213,11 @@ var packageJson = {
2212
2213
  cozePublishConfig: cozePublishConfig
2213
2214
  };
2214
2215
 
2215
- function _optionalChain$j(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; }/**
2216
+ function _optionalChain$m(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; }/**
2216
2217
  * Slardar 监控初始化和上报
2217
2218
  */
2218
2219
 
2219
- const log$5 = debug$2('slardar:cli');
2220
+ const log$5 = debug('slardar:cli');
2220
2221
 
2221
2222
  /**
2222
2223
  * 安全执行函数包装器
@@ -2315,11 +2316,11 @@ const reportCommandComplete = safeRun(
2315
2316
  ,
2316
2317
  ) => {
2317
2318
  const event = EventBuilder.cliCommandComplete(command, success, duration, {
2318
- args: _optionalChain$j([options, 'optionalAccess', _ => _.args]),
2319
- errorCode: _optionalChain$j([options, 'optionalAccess', _2 => _2.errorCode]),
2319
+ args: _optionalChain$m([options, 'optionalAccess', _ => _.args]),
2320
+ errorCode: _optionalChain$m([options, 'optionalAccess', _2 => _2.errorCode]),
2320
2321
  categories: {
2321
- ...(_optionalChain$j([options, 'optionalAccess', _3 => _3.errorMessage]) && { errorMessage: options.errorMessage }),
2322
- ..._optionalChain$j([options, 'optionalAccess', _4 => _4.categories]),
2322
+ ...(_optionalChain$m([options, 'optionalAccess', _3 => _3.errorMessage]) && { errorMessage: options.errorMessage }),
2323
+ ..._optionalChain$m([options, 'optionalAccess', _4 => _4.categories]),
2323
2324
  },
2324
2325
  });
2325
2326
  reporter.sendEvent(event.name, event.metrics, event.categories);
@@ -2378,7 +2379,7 @@ const flushSlardar = safeRun('flushSlardar', async () => {
2378
2379
  await reporter.flush();
2379
2380
  });
2380
2381
 
2381
- function _nullishCoalesce$7(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$i(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; }var LogLevel; (function (LogLevel) {
2382
+ function _nullishCoalesce$8(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$l(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; }var LogLevel; (function (LogLevel) {
2382
2383
  const ERROR = 0; LogLevel[LogLevel["ERROR"] = ERROR] = "ERROR";
2383
2384
  const WARN = 1; LogLevel[LogLevel["WARN"] = WARN] = "WARN";
2384
2385
  const SUCCESS = 2; LogLevel[LogLevel["SUCCESS"] = SUCCESS] = "SUCCESS";
@@ -2416,7 +2417,7 @@ class Logger {
2416
2417
 
2417
2418
  constructor(options = {}) {
2418
2419
  this.level = this.parseLogLevel(options.level);
2419
- this.useColor = _nullishCoalesce$7(options.useColor, () => ( this.isColorSupported()));
2420
+ this.useColor = _nullishCoalesce$8(options.useColor, () => ( this.isColorSupported()));
2420
2421
  this.prefix = options.prefix;
2421
2422
  }
2422
2423
 
@@ -2425,7 +2426,7 @@ class Logger {
2425
2426
  return level;
2426
2427
  }
2427
2428
 
2428
- const envLevel = _optionalChain$i([process, 'access', _ => _.env, 'access', _2 => _2.LOG_LEVEL, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]);
2429
+ const envLevel = _optionalChain$l([process, 'access', _ => _.env, 'access', _2 => _2.LOG_LEVEL, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]);
2429
2430
  if (envLevel && envLevel in LOG_LEVEL_MAP) {
2430
2431
  return LOG_LEVEL_MAP[envLevel];
2431
2432
  }
@@ -2437,7 +2438,7 @@ class Logger {
2437
2438
  // 简单检测:Node.js 环境且支持 TTY
2438
2439
  return (
2439
2440
  typeof process !== 'undefined' &&
2440
- _optionalChain$i([process, 'access', _5 => _5.stdout, 'optionalAccess', _6 => _6.isTTY]) === true &&
2441
+ _optionalChain$l([process, 'access', _5 => _5.stdout, 'optionalAccess', _6 => _6.isTTY]) === true &&
2441
2442
  process.env.NO_COLOR === undefined
2442
2443
  );
2443
2444
  }
@@ -2462,7 +2463,7 @@ class Logger {
2462
2463
 
2463
2464
  const icon = this.colorize(options.icon, options.color);
2464
2465
  const prefix = this.prefix ? `${icon} ${this.prefix}` : icon;
2465
- console.log(prefix, options.message, ...(_nullishCoalesce$7(options.args, () => ( []))));
2466
+ console.log(prefix, options.message, ...(_nullishCoalesce$8(options.args, () => ( []))));
2466
2467
  }
2467
2468
 
2468
2469
  error(message, ...args) {
@@ -3276,7 +3277,7 @@ const registerCommand$4 = program => {
3276
3277
  });
3277
3278
  };
3278
3279
 
3279
- function _optionalChain$h(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; }/* eslint-disable @typescript-eslint/no-explicit-any */
3280
+ function _optionalChain$k(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; }/* eslint-disable @typescript-eslint/no-explicit-any */
3280
3281
  // Safe JSON parsing utilities with type safety and error handling
3281
3282
  // Provides fallback values, validation, and error monitoring capabilities
3282
3283
 
@@ -3376,12 +3377,12 @@ function safeJsonParse(
3376
3377
  const parsed = JSON.parse(String(input));
3377
3378
 
3378
3379
  // Optional validation
3379
- if (_optionalChain$h([options, 'optionalAccess', _ => _.validate])) {
3380
+ if (_optionalChain$k([options, 'optionalAccess', _ => _.validate])) {
3380
3381
  if (options.validate(parsed)) {
3381
3382
  return parsed;
3382
3383
  } else {
3383
3384
  const validationError = new Error('JSON validation failed');
3384
- _optionalChain$h([options, 'access', _2 => _2.onError, 'optionalCall', _3 => _3(validationError, input)]);
3385
+ _optionalChain$k([options, 'access', _2 => _2.onError, 'optionalCall', _3 => _3(validationError, input)]);
3385
3386
 
3386
3387
  if (options.throwOnValidationError) {
3387
3388
  throw validationError;
@@ -3393,10 +3394,10 @@ function safeJsonParse(
3393
3394
  return parsed;
3394
3395
  } catch (error) {
3395
3396
  // Re-throw validation errors when throwOnValidationError is true
3396
- if (error instanceof Error && error.message === 'JSON validation failed' && _optionalChain$h([options, 'optionalAccess', _4 => _4.throwOnValidationError])) {
3397
+ if (error instanceof Error && error.message === 'JSON validation failed' && _optionalChain$k([options, 'optionalAccess', _4 => _4.throwOnValidationError])) {
3397
3398
  throw error;
3398
3399
  }
3399
- _optionalChain$h([options, 'optionalAccess', _5 => _5.onError, 'optionalCall', _6 => _6(error , input)]);
3400
+ _optionalChain$k([options, 'optionalAccess', _5 => _5.onError, 'optionalCall', _6 => _6(error , input)]);
3400
3401
  return defaultValue;
3401
3402
  }
3402
3403
  }
@@ -3436,7 +3437,7 @@ function isNode(node) {
3436
3437
  }
3437
3438
  const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;
3438
3439
 
3439
- function _optionalChain$g(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; }
3440
+ function _optionalChain$j(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; }
3440
3441
  const BREAK = Symbol('break visit');
3441
3442
  const SKIP = Symbol('skip children');
3442
3443
  const REMOVE = Symbol('remove node');
@@ -3549,15 +3550,15 @@ function callVisitor(key, node, visitor, path) {
3549
3550
  if (typeof visitor === 'function')
3550
3551
  return visitor(key, node, path);
3551
3552
  if (isMap(node))
3552
- return _optionalChain$g([visitor, 'access', _ => _.Map, 'optionalCall', _2 => _2(key, node, path)]);
3553
+ return _optionalChain$j([visitor, 'access', _ => _.Map, 'optionalCall', _2 => _2(key, node, path)]);
3553
3554
  if (isSeq(node))
3554
- return _optionalChain$g([visitor, 'access', _3 => _3.Seq, 'optionalCall', _4 => _4(key, node, path)]);
3555
+ return _optionalChain$j([visitor, 'access', _3 => _3.Seq, 'optionalCall', _4 => _4(key, node, path)]);
3555
3556
  if (isPair(node))
3556
- return _optionalChain$g([visitor, 'access', _5 => _5.Pair, 'optionalCall', _6 => _6(key, node, path)]);
3557
+ return _optionalChain$j([visitor, 'access', _5 => _5.Pair, 'optionalCall', _6 => _6(key, node, path)]);
3557
3558
  if (isScalar(node))
3558
- return _optionalChain$g([visitor, 'access', _7 => _7.Scalar, 'optionalCall', _8 => _8(key, node, path)]);
3559
+ return _optionalChain$j([visitor, 'access', _7 => _7.Scalar, 'optionalCall', _8 => _8(key, node, path)]);
3559
3560
  if (isAlias(node))
3560
- return _optionalChain$g([visitor, 'access', _9 => _9.Alias, 'optionalCall', _10 => _10(key, node, path)]);
3561
+ return _optionalChain$j([visitor, 'access', _9 => _9.Alias, 'optionalCall', _10 => _10(key, node, path)]);
3561
3562
  return undefined;
3562
3563
  }
3563
3564
  function replaceNode(key, path, node) {
@@ -3648,7 +3649,7 @@ function applyReviver(reviver, obj, key, val) {
3648
3649
  return reviver.call(obj, key, val);
3649
3650
  }
3650
3651
 
3651
- function _optionalChain$f(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; }
3652
+ function _optionalChain$i(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; }
3652
3653
  /**
3653
3654
  * Recursively convert any node or its contents to native JavaScript
3654
3655
  *
@@ -3678,7 +3679,7 @@ function toJS(value, arg, ctx) {
3678
3679
  ctx.onCreate(res);
3679
3680
  return res;
3680
3681
  }
3681
- if (typeof value === 'bigint' && !_optionalChain$f([ctx, 'optionalAccess', _ => _.keep]))
3682
+ if (typeof value === 'bigint' && !_optionalChain$i([ctx, 'optionalAccess', _ => _.keep]))
3682
3683
  return Number(value);
3683
3684
  return value;
3684
3685
  }
@@ -3716,7 +3717,7 @@ class NodeBase {
3716
3717
  }
3717
3718
  }
3718
3719
 
3719
- function _optionalChain$e(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; }
3720
+ function _optionalChain$h(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; }
3720
3721
  class Alias extends NodeBase {
3721
3722
  constructor(source) {
3722
3723
  super(ALIAS);
@@ -3733,7 +3734,7 @@ class Alias extends NodeBase {
3733
3734
  */
3734
3735
  resolve(doc, ctx) {
3735
3736
  let nodes;
3736
- if (_optionalChain$e([ctx, 'optionalAccess', _ => _.aliasResolveCache])) {
3737
+ if (_optionalChain$h([ctx, 'optionalAccess', _ => _.aliasResolveCache])) {
3737
3738
  nodes = ctx.aliasResolveCache;
3738
3739
  }
3739
3740
  else {
@@ -3772,7 +3773,7 @@ class Alias extends NodeBase {
3772
3773
  data = anchors.get(source);
3773
3774
  }
3774
3775
  /* istanbul ignore if */
3775
- if (_optionalChain$e([data, 'optionalAccess', _2 => _2.res]) === undefined) {
3776
+ if (_optionalChain$h([data, 'optionalAccess', _2 => _2.res]) === undefined) {
3776
3777
  const msg = 'This should not happen: Alias anchor was not resolved?';
3777
3778
  throw new ReferenceError(msg);
3778
3779
  }
@@ -3824,7 +3825,7 @@ function getAliasCount(doc, node, anchors) {
3824
3825
  return 1;
3825
3826
  }
3826
3827
 
3827
- function _optionalChain$d(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; }
3828
+ function _optionalChain$g(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; }
3828
3829
  const isScalarValue = (value) => !value || (typeof value !== 'function' && typeof value !== 'object');
3829
3830
  class Scalar extends NodeBase {
3830
3831
  constructor(value) {
@@ -3832,7 +3833,7 @@ class Scalar extends NodeBase {
3832
3833
  this.value = value;
3833
3834
  }
3834
3835
  toJSON(arg, ctx) {
3835
- return _optionalChain$d([ctx, 'optionalAccess', _ => _.keep]) ? this.value : toJS(this.value, arg, ctx);
3836
+ return _optionalChain$g([ctx, 'optionalAccess', _ => _.keep]) ? this.value : toJS(this.value, arg, ctx);
3836
3837
  }
3837
3838
  toString() {
3838
3839
  return String(this.value);
@@ -3844,17 +3845,17 @@ Scalar.PLAIN = 'PLAIN';
3844
3845
  Scalar.QUOTE_DOUBLE = 'QUOTE_DOUBLE';
3845
3846
  Scalar.QUOTE_SINGLE = 'QUOTE_SINGLE';
3846
3847
 
3847
- function _nullishCoalesce$6(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$c(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; }
3848
+ function _nullishCoalesce$7(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$f(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; }
3848
3849
  const defaultTagPrefix = 'tag:yaml.org,2002:';
3849
3850
  function findTagObject(value, tagName, tags) {
3850
3851
  if (tagName) {
3851
3852
  const match = tags.filter(t => t.tag === tagName);
3852
- const tagObj = _nullishCoalesce$6(match.find(t => !t.format), () => ( match[0]));
3853
+ const tagObj = _nullishCoalesce$7(match.find(t => !t.format), () => ( match[0]));
3853
3854
  if (!tagObj)
3854
3855
  throw new Error(`Tag ${tagName} not found`);
3855
3856
  return tagObj;
3856
3857
  }
3857
- return tags.find(t => _optionalChain$c([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(value)]) && !t.format);
3858
+ return tags.find(t => _optionalChain$f([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(value)]) && !t.format);
3858
3859
  }
3859
3860
  function createNode(value, tagName, ctx) {
3860
3861
  if (isDocument(value))
@@ -3862,7 +3863,7 @@ function createNode(value, tagName, ctx) {
3862
3863
  if (isNode(value))
3863
3864
  return value;
3864
3865
  if (isPair(value)) {
3865
- const map = _optionalChain$c([ctx, 'access', _3 => _3.schema, 'access', _4 => _4[MAP], 'access', _5 => _5.createNode, 'optionalCall', _6 => _6(ctx.schema, null, ctx)]);
3866
+ const map = _optionalChain$f([ctx, 'access', _3 => _3.schema, 'access', _4 => _4[MAP], 'access', _5 => _5.createNode, 'optionalCall', _6 => _6(ctx.schema, null, ctx)]);
3866
3867
  map.items.push(value);
3867
3868
  return map;
3868
3869
  }
@@ -3881,7 +3882,7 @@ function createNode(value, tagName, ctx) {
3881
3882
  if (aliasDuplicateObjects && value && typeof value === 'object') {
3882
3883
  ref = sourceObjects.get(value);
3883
3884
  if (ref) {
3884
- _nullishCoalesce$6(ref.anchor, () => ( (ref.anchor = onAnchor(value))));
3885
+ _nullishCoalesce$7(ref.anchor, () => ( (ref.anchor = onAnchor(value))));
3885
3886
  return new Alias(ref.anchor);
3886
3887
  }
3887
3888
  else {
@@ -3889,7 +3890,7 @@ function createNode(value, tagName, ctx) {
3889
3890
  sourceObjects.set(value, ref);
3890
3891
  }
3891
3892
  }
3892
- if (_optionalChain$c([tagName, 'optionalAccess', _7 => _7.startsWith, 'call', _8 => _8('!!')]))
3893
+ if (_optionalChain$f([tagName, 'optionalAccess', _7 => _7.startsWith, 'call', _8 => _8('!!')]))
3893
3894
  tagName = defaultTagPrefix + tagName.slice(2);
3894
3895
  let tagObj = findTagObject(value, tagName, schema.tags);
3895
3896
  if (!tagObj) {
@@ -3914,9 +3915,9 @@ function createNode(value, tagName, ctx) {
3914
3915
  onTagObj(tagObj);
3915
3916
  delete ctx.onTagObj;
3916
3917
  }
3917
- const node = _optionalChain$c([tagObj, 'optionalAccess', _9 => _9.createNode])
3918
+ const node = _optionalChain$f([tagObj, 'optionalAccess', _9 => _9.createNode])
3918
3919
  ? tagObj.createNode(ctx.schema, value, ctx)
3919
- : typeof _optionalChain$c([tagObj, 'optionalAccess', _10 => _10.nodeClass, 'optionalAccess', _11 => _11.from]) === 'function'
3920
+ : typeof _optionalChain$f([tagObj, 'optionalAccess', _10 => _10.nodeClass, 'optionalAccess', _11 => _11.from]) === 'function'
3920
3921
  ? tagObj.nodeClass.from(ctx.schema, value, ctx)
3921
3922
  : new Scalar(value);
3922
3923
  if (tagName)
@@ -4234,7 +4235,7 @@ function consumeMoreIndentedLines(text, i, indent) {
4234
4235
  return end;
4235
4236
  }
4236
4237
 
4237
- function _optionalChain$b(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; }
4238
+ function _optionalChain$e(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; }
4238
4239
  const getFoldOptions = (ctx, isBlock) => ({
4239
4240
  indentAtStart: isBlock ? ctx.indent.length : ctx.indentAtStart,
4240
4241
  lineWidth: ctx.options.lineWidth,
@@ -4519,9 +4520,9 @@ function plainString(item, ctx, onComment, onChompKeep) {
4519
4520
  // booleans get parsed with those types in v1.2 (e.g. '42', 'true' & '0.9e-3'),
4520
4521
  // and others in v1.1.
4521
4522
  if (actualString) {
4522
- const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && _optionalChain$b([tag, 'access', _ => _.test, 'optionalAccess', _2 => _2.test, 'call', _3 => _3(str)]);
4523
+ const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && _optionalChain$e([tag, 'access', _ => _.test, 'optionalAccess', _2 => _2.test, 'call', _3 => _3(str)]);
4523
4524
  const { compat, tags } = ctx.doc.schema;
4524
- if (tags.some(test) || _optionalChain$b([compat, 'optionalAccess', _4 => _4.some, 'call', _5 => _5(test)]))
4525
+ if (tags.some(test) || _optionalChain$e([compat, 'optionalAccess', _4 => _4.some, 'call', _5 => _5(test)]))
4525
4526
  return quotedString(value, ctx);
4526
4527
  }
4527
4528
  return implicitKey
@@ -4567,7 +4568,7 @@ function stringifyString(item, ctx, onComment, onChompKeep) {
4567
4568
  return res;
4568
4569
  }
4569
4570
 
4570
- function _nullishCoalesce$5(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$a(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; }
4571
+ function _nullishCoalesce$6(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$d(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; }
4571
4572
  function createStringifyContext(doc, options) {
4572
4573
  const opt = Object.assign({
4573
4574
  blockQuote: true,
@@ -4614,27 +4615,27 @@ function getTagObject(tags, item) {
4614
4615
  if (item.tag) {
4615
4616
  const match = tags.filter(t => t.tag === item.tag);
4616
4617
  if (match.length > 0)
4617
- return _nullishCoalesce$5(match.find(t => t.format === item.format), () => ( match[0]));
4618
+ return _nullishCoalesce$6(match.find(t => t.format === item.format), () => ( match[0]));
4618
4619
  }
4619
4620
  let tagObj = undefined;
4620
4621
  let obj;
4621
4622
  if (isScalar(item)) {
4622
4623
  obj = item.value;
4623
- let match = tags.filter(t => _optionalChain$a([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(obj)]));
4624
+ let match = tags.filter(t => _optionalChain$d([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(obj)]));
4624
4625
  if (match.length > 1) {
4625
4626
  const testMatch = match.filter(t => t.test);
4626
4627
  if (testMatch.length > 0)
4627
4628
  match = testMatch;
4628
4629
  }
4629
4630
  tagObj =
4630
- _nullishCoalesce$5(match.find(t => t.format === item.format), () => ( match.find(t => !t.format)));
4631
+ _nullishCoalesce$6(match.find(t => t.format === item.format), () => ( match.find(t => !t.format)));
4631
4632
  }
4632
4633
  else {
4633
4634
  obj = item;
4634
4635
  tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
4635
4636
  }
4636
4637
  if (!tagObj) {
4637
- const name = _nullishCoalesce$5(_optionalChain$a([obj, 'optionalAccess', _3 => _3.constructor, 'optionalAccess', _4 => _4.name]), () => ( (obj === null ? 'null' : typeof obj)));
4638
+ const name = _nullishCoalesce$6(_optionalChain$d([obj, 'optionalAccess', _3 => _3.constructor, 'optionalAccess', _4 => _4.name]), () => ( (obj === null ? 'null' : typeof obj)));
4638
4639
  throw new Error(`Tag not resolved for ${name} value`);
4639
4640
  }
4640
4641
  return tagObj;
@@ -4649,7 +4650,7 @@ function stringifyProps(node, tagObj, { anchors, doc }) {
4649
4650
  anchors.add(anchor);
4650
4651
  props.push(`&${anchor}`);
4651
4652
  }
4652
- const tag = _nullishCoalesce$5(node.tag, () => ( (tagObj.default ? null : tagObj.tag)));
4653
+ const tag = _nullishCoalesce$6(node.tag, () => ( (tagObj.default ? null : tagObj.tag)));
4653
4654
  if (tag)
4654
4655
  props.push(doc.directives.tagString(tag));
4655
4656
  return props.join(' ');
@@ -4660,7 +4661,7 @@ function stringify(item, ctx, onComment, onChompKeep) {
4660
4661
  if (isAlias(item)) {
4661
4662
  if (ctx.doc.directives)
4662
4663
  return item.toString(ctx);
4663
- if (_optionalChain$a([ctx, 'access', _5 => _5.resolvedAliases, 'optionalAccess', _6 => _6.has, 'call', _7 => _7(item)])) {
4664
+ if (_optionalChain$d([ctx, 'access', _5 => _5.resolvedAliases, 'optionalAccess', _6 => _6.has, 'call', _7 => _7(item)])) {
4664
4665
  throw new TypeError(`Cannot stringify circular structure without alias nodes`);
4665
4666
  }
4666
4667
  else {
@@ -4675,10 +4676,10 @@ function stringify(item, ctx, onComment, onChompKeep) {
4675
4676
  const node = isNode(item)
4676
4677
  ? item
4677
4678
  : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
4678
- _nullishCoalesce$5(tagObj, () => ( (tagObj = getTagObject(ctx.doc.schema.tags, node))));
4679
+ _nullishCoalesce$6(tagObj, () => ( (tagObj = getTagObject(ctx.doc.schema.tags, node))));
4679
4680
  const props = stringifyProps(node, tagObj, ctx);
4680
4681
  if (props.length > 0)
4681
- ctx.indentAtStart = (_nullishCoalesce$5(ctx.indentAtStart, () => ( 0))) + props.length + 1;
4682
+ ctx.indentAtStart = (_nullishCoalesce$6(ctx.indentAtStart, () => ( 0))) + props.length + 1;
4682
4683
  const str = typeof tagObj.stringify === 'function'
4683
4684
  ? tagObj.stringify(node, ctx, onComment, onChompKeep)
4684
4685
  : isScalar(node)
@@ -4691,7 +4692,7 @@ function stringify(item, ctx, onComment, onChompKeep) {
4691
4692
  : `${props}\n${ctx.indent}${str}`;
4692
4693
  }
4693
4694
 
4694
- function _nullishCoalesce$4(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
4695
+ function _nullishCoalesce$5(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
4695
4696
  function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
4696
4697
  const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
4697
4698
  let keyComment = (isNode(key) && key.comment) || null;
@@ -4801,7 +4802,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
4801
4802
  const vs0 = valueStr[0];
4802
4803
  const nl0 = valueStr.indexOf('\n');
4803
4804
  const hasNewline = nl0 !== -1;
4804
- const flow = _nullishCoalesce$4(_nullishCoalesce$4(ctx.inFlow, () => ( value.flow)), () => ( value.items.length === 0));
4805
+ const flow = _nullishCoalesce$5(_nullishCoalesce$5(ctx.inFlow, () => ( value.flow)), () => ( value.items.length === 0));
4805
4806
  if (hasNewline || !flow) {
4806
4807
  let hasPropsLine = false;
4807
4808
  if (hasNewline && (vs0 === '&' || vs0 === '!')) {
@@ -4842,7 +4843,7 @@ function warn(logLevel, warning) {
4842
4843
  }
4843
4844
  }
4844
4845
 
4845
- function _optionalChain$9(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; }
4846
+ function _optionalChain$c(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; }
4846
4847
  // If the value associated with a merge key is a single mapping node, each of
4847
4848
  // its key/value pairs is inserted into the current mapping, unless the key
4848
4849
  // already exists in it. If the value associated with the merge key is a
@@ -4866,7 +4867,7 @@ const isMergeKey = (ctx, key) => (merge.identify(key) ||
4866
4867
  (isScalar(key) &&
4867
4868
  (!key.type || key.type === Scalar.PLAIN) &&
4868
4869
  merge.identify(key.value))) &&
4869
- _optionalChain$9([ctx, 'optionalAccess', _ => _.doc, 'access', _2 => _2.schema, 'access', _3 => _3.tags, 'access', _4 => _4.some, 'call', _5 => _5(tag => tag.tag === merge.tag && tag.default)]);
4870
+ _optionalChain$c([ctx, 'optionalAccess', _ => _.doc, 'access', _2 => _2.schema, 'access', _3 => _3.tags, 'access', _4 => _4.some, 'call', _5 => _5(tag => tag.tag === merge.tag && tag.default)]);
4870
4871
  function addMergeToJSMap(ctx, map, value) {
4871
4872
  value = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
4872
4873
  if (isSeq(value))
@@ -4903,7 +4904,7 @@ function mergeValue(ctx, map, value) {
4903
4904
  return map;
4904
4905
  }
4905
4906
 
4906
- function _optionalChain$8(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; }
4907
+ function _optionalChain$b(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; }
4907
4908
  function addPairToJSMap(ctx, map, { key, value }) {
4908
4909
  if (isNode(key) && key.addToJSMap)
4909
4910
  key.addToJSMap(ctx, map, value);
@@ -4940,7 +4941,7 @@ function stringifyKey(key, jsKey, ctx) {
4940
4941
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
4941
4942
  if (typeof jsKey !== 'object')
4942
4943
  return String(jsKey);
4943
- if (isNode(key) && _optionalChain$8([ctx, 'optionalAccess', _ => _.doc])) {
4944
+ if (isNode(key) && _optionalChain$b([ctx, 'optionalAccess', _ => _.doc])) {
4944
4945
  const strCtx = createStringifyContext(ctx.doc, {});
4945
4946
  strCtx.anchors = new Set();
4946
4947
  for (const node of ctx.anchors.keys())
@@ -4960,7 +4961,7 @@ function stringifyKey(key, jsKey, ctx) {
4960
4961
  return JSON.stringify(jsKey);
4961
4962
  }
4962
4963
 
4963
- function _optionalChain$7(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; }
4964
+ function _optionalChain$a(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; }
4964
4965
  function createPair(key, value, ctx) {
4965
4966
  const k = createNode(key, undefined, ctx);
4966
4967
  const v = createNode(value, undefined, ctx);
@@ -4981,19 +4982,19 @@ class Pair {
4981
4982
  return new Pair(key, value);
4982
4983
  }
4983
4984
  toJSON(_, ctx) {
4984
- const pair = _optionalChain$7([ctx, 'optionalAccess', _2 => _2.mapAsMap]) ? new Map() : {};
4985
+ const pair = _optionalChain$a([ctx, 'optionalAccess', _2 => _2.mapAsMap]) ? new Map() : {};
4985
4986
  return addPairToJSMap(ctx, pair, this);
4986
4987
  }
4987
4988
  toString(ctx, onComment, onChompKeep) {
4988
- return _optionalChain$7([ctx, 'optionalAccess', _3 => _3.doc])
4989
+ return _optionalChain$a([ctx, 'optionalAccess', _3 => _3.doc])
4989
4990
  ? stringifyPair(this, ctx, onComment, onChompKeep)
4990
4991
  : JSON.stringify(this);
4991
4992
  }
4992
4993
  }
4993
4994
 
4994
- function _nullishCoalesce$3(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$6(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; }
4995
+ function _nullishCoalesce$4(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$9(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; }
4995
4996
  function stringifyCollection(collection, ctx, options) {
4996
- const flow = _nullishCoalesce$3(ctx.inFlow, () => ( collection.flow));
4997
+ const flow = _nullishCoalesce$4(ctx.inFlow, () => ( collection.flow));
4997
4998
  const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
4998
4999
  return stringify(collection, ctx, options);
4999
5000
  }
@@ -5085,7 +5086,7 @@ function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
5085
5086
  if (iv.commentBefore)
5086
5087
  reqNewline = true;
5087
5088
  }
5088
- else if (item.value == null && _optionalChain$6([ik, 'optionalAccess', _ => _.comment])) {
5089
+ else if (item.value == null && _optionalChain$9([ik, 'optionalAccess', _ => _.comment])) {
5089
5090
  comment = ik.comment;
5090
5091
  }
5091
5092
  }
@@ -5140,7 +5141,7 @@ function addCommentBefore({ indent, options: { commentString } }, lines, comment
5140
5141
  }
5141
5142
  }
5142
5143
 
5143
- function _nullishCoalesce$2(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$5(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; }
5144
+ function _nullishCoalesce$3(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$8(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; }
5144
5145
  function findPair(items, key) {
5145
5146
  const k = isScalar(key) ? key.value : key;
5146
5147
  for (const it of items) {
@@ -5201,12 +5202,12 @@ class YAMLMap extends Collection {
5201
5202
  _pair = pair;
5202
5203
  else if (!pair || typeof pair !== 'object' || !('key' in pair)) {
5203
5204
  // In TypeScript, this never happens.
5204
- _pair = new Pair(pair, _optionalChain$5([pair, 'optionalAccess', _2 => _2.value]));
5205
+ _pair = new Pair(pair, _optionalChain$8([pair, 'optionalAccess', _2 => _2.value]));
5205
5206
  }
5206
5207
  else
5207
5208
  _pair = new Pair(pair.key, pair.value);
5208
5209
  const prev = findPair(this.items, _pair.key);
5209
- const sortEntries = _optionalChain$5([this, 'access', _3 => _3.schema, 'optionalAccess', _4 => _4.sortMapEntries]);
5210
+ const sortEntries = _optionalChain$8([this, 'access', _3 => _3.schema, 'optionalAccess', _4 => _4.sortMapEntries]);
5210
5211
  if (prev) {
5211
5212
  if (!overwrite)
5212
5213
  throw new Error(`Key ${_pair.key} already set`);
@@ -5236,8 +5237,8 @@ class YAMLMap extends Collection {
5236
5237
  }
5237
5238
  get(key, keepScalar) {
5238
5239
  const it = findPair(this.items, key);
5239
- const node = _optionalChain$5([it, 'optionalAccess', _5 => _5.value]);
5240
- return _nullishCoalesce$2((!keepScalar && isScalar(node) ? node.value : node), () => ( undefined));
5240
+ const node = _optionalChain$8([it, 'optionalAccess', _5 => _5.value]);
5241
+ return _nullishCoalesce$3((!keepScalar && isScalar(node) ? node.value : node), () => ( undefined));
5241
5242
  }
5242
5243
  has(key) {
5243
5244
  return !!findPair(this.items, key);
@@ -5251,8 +5252,8 @@ class YAMLMap extends Collection {
5251
5252
  * @returns Instance of Type, Map, or Object
5252
5253
  */
5253
5254
  toJSON(_, ctx, Type) {
5254
- const map = Type ? new Type() : _optionalChain$5([ctx, 'optionalAccess', _6 => _6.mapAsMap]) ? new Map() : {};
5255
- if (_optionalChain$5([ctx, 'optionalAccess', _7 => _7.onCreate]))
5255
+ const map = Type ? new Type() : _optionalChain$8([ctx, 'optionalAccess', _6 => _6.mapAsMap]) ? new Map() : {};
5256
+ if (_optionalChain$8([ctx, 'optionalAccess', _7 => _7.onCreate]))
5256
5257
  ctx.onCreate(map);
5257
5258
  for (const item of this.items)
5258
5259
  addPairToJSMap(ctx, map, item);
@@ -5277,7 +5278,7 @@ class YAMLMap extends Collection {
5277
5278
  }
5278
5279
  }
5279
5280
 
5280
- function _optionalChain$4(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; }
5281
+ function _optionalChain$7(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; }
5281
5282
  class YAMLSeq extends Collection {
5282
5283
  static get tagName() {
5283
5284
  return 'tag:yaml.org,2002:seq';
@@ -5340,7 +5341,7 @@ class YAMLSeq extends Collection {
5340
5341
  }
5341
5342
  toJSON(_, ctx) {
5342
5343
  const seq = [];
5343
- if (_optionalChain$4([ctx, 'optionalAccess', _2 => _2.onCreate]))
5344
+ if (_optionalChain$7([ctx, 'optionalAccess', _2 => _2.onCreate]))
5344
5345
  ctx.onCreate(seq);
5345
5346
  let i = 0;
5346
5347
  for (const item of this.items)
@@ -5419,7 +5420,7 @@ function createPairs(schema, iterable, ctx) {
5419
5420
  return pairs;
5420
5421
  }
5421
5422
 
5422
- function _optionalChain$3(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; }
5423
+ function _optionalChain$6(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; }
5423
5424
  class YAMLOMap extends YAMLSeq {
5424
5425
  constructor() {
5425
5426
  super();
@@ -5438,7 +5439,7 @@ class YAMLOMap extends YAMLSeq {
5438
5439
  if (!ctx)
5439
5440
  return super.toJSON(_);
5440
5441
  const map = new Map();
5441
- if (_optionalChain$3([ctx, 'optionalAccess', _2 => _2.onCreate]))
5442
+ if (_optionalChain$6([ctx, 'optionalAccess', _2 => _2.onCreate]))
5442
5443
  ctx.onCreate(map);
5443
5444
  for (const pair of this.items) {
5444
5445
  let key, value;
@@ -5556,9 +5557,7 @@ const isDirExists = async (file) => {
5556
5557
  }
5557
5558
  };
5558
5559
 
5559
- // ABOUTME: Project type detection utility
5560
- // ABOUTME: Detect project type (Next.js, Vite, Nuxt, etc.) by analyzing project files
5561
-
5560
+ function _optionalChain$5(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; }// ABOUTME: Project type detection utility
5562
5561
 
5563
5562
  /**
5564
5563
  * 支持的项目类型枚举
@@ -5611,6 +5610,8 @@ var ProjectType; (function (ProjectType) {
5611
5610
 
5612
5611
 
5613
5612
 
5613
+
5614
+
5614
5615
 
5615
5616
 
5616
5617
 
@@ -5657,6 +5658,15 @@ const collectProjectInfo = async (
5657
5658
  }
5658
5659
  }
5659
5660
 
5661
+ const scripts = Object.entries(
5662
+ (_optionalChain$5([packageJson, 'optionalAccess', _ => _.scripts]) ) || {},
5663
+ ).reduce((acc, [name, script]) => {
5664
+ if (typeof script === 'string') {
5665
+ acc[name] = script;
5666
+ }
5667
+ return acc;
5668
+ }, {});
5669
+
5660
5670
  // 3. 检查可能的配置文件(并发检查)
5661
5671
  const configFileCandidates = [
5662
5672
  // Next.js
@@ -5690,13 +5700,29 @@ const collectProjectInfo = async (
5690
5700
  return {
5691
5701
  packageJson,
5692
5702
  dependencies,
5703
+ scripts,
5693
5704
  configFiles,
5694
5705
  };
5695
5706
  };
5696
5707
 
5708
+ const hasTaroDependency = (info) =>
5709
+ Array.from(info.dependencies).some(
5710
+ dep => dep === '@tarojs/taro' || dep.startsWith('@tarojs/'),
5711
+ );
5712
+
5713
+ const hasTaroConfigFile = (info) =>
5714
+ info.configFiles.has('config/index.js') || info.configFiles.has('config/index.ts');
5715
+
5716
+ const hasTaroScript = (info) =>
5717
+ Object.entries(info.scripts).some(
5718
+ ([name, script]) =>
5719
+ /^(build|dev|preview):(weapp|tt|h5)$/.test(name) ||
5720
+ /\btaro\s+build\b/.test(script),
5721
+ );
5722
+
5697
5723
  /**
5698
5724
  * 项目类型检测规则列表
5699
- * 按优先级排序:Next.js > Nuxt > Vite > Expo > Taro
5725
+ * 按优先级排序:Next.js > Nuxt > Taro > Vite > Expo
5700
5726
  */
5701
5727
  const DETECTION_RULES = [
5702
5728
  {
@@ -5717,6 +5743,12 @@ const DETECTION_RULES = [
5717
5743
  info.configFiles.has('nuxt.config.mjs'),
5718
5744
  reason: 'Found Nuxt dependencies or config files',
5719
5745
  },
5746
+ {
5747
+ type: ProjectType.TARO,
5748
+ check: info =>
5749
+ hasTaroDependency(info) || (hasTaroConfigFile(info) && hasTaroScript(info)),
5750
+ reason: 'Found Taro dependencies or config files with Taro scripts',
5751
+ },
5720
5752
  {
5721
5753
  type: ProjectType.VITE,
5722
5754
  check: info =>
@@ -5732,15 +5764,6 @@ const DETECTION_RULES = [
5732
5764
  info.dependencies.has('expo') || info.dependencies.has('react-native'),
5733
5765
  reason: 'Found Expo/React Native dependencies',
5734
5766
  },
5735
- {
5736
- type: ProjectType.TARO,
5737
- check: info =>
5738
- info.dependencies.has('@tarojs/taro') ||
5739
- info.dependencies.has('@tarojs/cli') ||
5740
- info.configFiles.has('config/index.js') ||
5741
- info.configFiles.has('config/index.ts'),
5742
- reason: 'Found Taro dependencies or config files',
5743
- },
5744
5767
  ];
5745
5768
 
5746
5769
  /**
@@ -5790,29 +5813,7 @@ const detectProjectType = async (
5790
5813
  };
5791
5814
  };
5792
5815
 
5793
- /**
5794
- * 检查项目是否为指定类型
5795
- *
5796
- * @param projectPath - 项目根目录的绝对路径
5797
- * @param expectedType - 期望的项目类型
5798
- * @returns 是否匹配
5799
- *
5800
- * @example
5801
- * ```typescript
5802
- * if (await isProjectType('/path/to/project', ProjectType.NEXTJS)) {
5803
- * console.log('This is a Next.js project');
5804
- * }
5805
- * ```
5806
- */
5807
- const isProjectType = async (
5808
- projectPath,
5809
- expectedType,
5810
- ) => {
5811
- const result = await detectProjectType(projectPath);
5812
- return result.detected && result.type === expectedType;
5813
- };
5814
-
5815
- function _optionalChain$2(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; }
5816
+ function _optionalChain$4(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; }
5816
5817
 
5817
5818
 
5818
5819
  /**
@@ -5853,6 +5854,17 @@ const parseConfigContent = (content) => {
5853
5854
  return null;
5854
5855
  };
5855
5856
 
5857
+ /**
5858
+ * 仅按 TOML 解析 .coze
5859
+ */
5860
+ const parseTomlConfigContent = (content) => {
5861
+ try {
5862
+ return toml.parse(content) ;
5863
+ } catch (e) {
5864
+ return null;
5865
+ }
5866
+ };
5867
+
5856
5868
  /**
5857
5869
  * 加载 .coze 配置文件
5858
5870
  *
@@ -5886,6 +5898,80 @@ const loadCozeConfig = async (
5886
5898
  return config;
5887
5899
  };
5888
5900
 
5901
+ /**
5902
+ * 读取 TOML 格式的 .coze 配置
5903
+ */
5904
+ const loadTomlCozeConfig = async (
5905
+ projectPath = process.cwd(),
5906
+ ) => {
5907
+ const cozeConfigPath = path.join(projectPath, '.coze');
5908
+
5909
+ let content;
5910
+ try {
5911
+ content = await fs$1.readFile(cozeConfigPath, 'utf-8');
5912
+ } catch (error) {
5913
+ throw new Error(
5914
+ `.coze config file not found in ${projectPath}\n` +
5915
+ 'Please ensure you are in a project directory initialized with coze-coding.\n' +
5916
+ `Error: ${error instanceof Error ? error.message : String(error)}`,
5917
+ );
5918
+ }
5919
+
5920
+ const config = parseTomlConfigContent(content);
5921
+ if (!config) {
5922
+ throw new Error(
5923
+ 'Failed to parse .coze config file as TOML.\n' +
5924
+ 'Please ensure the file is valid TOML format.',
5925
+ );
5926
+ }
5927
+
5928
+ return config;
5929
+ };
5930
+
5931
+ /**
5932
+ * 将 .coze 配置写回 TOML 文件
5933
+ */
5934
+ const saveTomlCozeConfig = async (
5935
+ config,
5936
+ projectPath = process.cwd(),
5937
+ ) => {
5938
+ const cozeConfigPath = path.join(projectPath, '.coze');
5939
+ const tempCozeConfigPath = path.join(
5940
+ projectPath,
5941
+ `.coze.tmp-${process.pid}-${Date.now()}`,
5942
+ );
5943
+ const content = toml.stringify(config );
5944
+
5945
+ try {
5946
+ await fs$1.writeFile(tempCozeConfigPath, content, 'utf-8');
5947
+ await fs$1.rename(tempCozeConfigPath, cozeConfigPath);
5948
+ } catch (error) {
5949
+ await fs$1.rm(tempCozeConfigPath, { force: true }).catch(() => undefined);
5950
+ throw error;
5951
+ }
5952
+ };
5953
+
5954
+ /**
5955
+ * 更新项目 patch 元数据并写回 .coze
5956
+ */
5957
+ const saveProjectPatchState = async (
5958
+ projectPath,
5959
+ state
5960
+
5961
+
5962
+
5963
+ ,
5964
+ ) => {
5965
+ const config = await loadTomlCozeConfig(projectPath);
5966
+ config.project = {
5967
+ ...(config.project || {}),
5968
+ template: state.template,
5969
+ version: state.version,
5970
+ appliedPatches: state.appliedPatches,
5971
+ };
5972
+ await saveTomlCozeConfig(config, projectPath);
5973
+ };
5974
+
5889
5975
  /**
5890
5976
  * 获取指定命令的配置
5891
5977
  *
@@ -5902,13 +5988,13 @@ const getCommandConfig = (
5902
5988
  // 根据命令名称映射到配置路径
5903
5989
  switch (commandName) {
5904
5990
  case 'dev':
5905
- commandConfig = _optionalChain$2([config, 'access', _ => _.dev, 'optionalAccess', _2 => _2.run]);
5991
+ commandConfig = _optionalChain$4([config, 'access', _ => _.dev, 'optionalAccess', _2 => _2.run]);
5906
5992
  break;
5907
5993
  case 'build':
5908
- commandConfig = _optionalChain$2([config, 'access', _3 => _3.deploy, 'optionalAccess', _4 => _4.build]);
5994
+ commandConfig = _optionalChain$4([config, 'access', _3 => _3.deploy, 'optionalAccess', _4 => _4.build]);
5909
5995
  break;
5910
5996
  case 'start':
5911
- commandConfig = _optionalChain$2([config, 'access', _5 => _5.deploy, 'optionalAccess', _6 => _6.run]);
5997
+ commandConfig = _optionalChain$4([config, 'access', _5 => _5.deploy, 'optionalAccess', _6 => _6.run]);
5912
5998
  break;
5913
5999
  default:
5914
6000
  throw new Error(`Unknown command: ${commandName}`);
@@ -5924,251 +6010,341 @@ const getCommandConfig = (
5924
6010
  return commandConfig;
5925
6011
  };
5926
6012
 
5927
- // ABOUTME: Fix rule to replace npx commands with pnpm in shell scripts (dev.sh, build.sh)
5928
- // ABOUTME: This fixes module resolution issues when using npx in certain project types
5929
- // ABOUTME: See: /Users/bytedance/Downloads/projects2/docs/npx-pnpm-module-resolution-issue.md
6013
+ const isDirectoryEmpty = async (projectPath) =>
6014
+ (await fs$1.readdir(projectPath)).length === 0;
5930
6015
 
6016
+ const detectTemplateKey = async (
6017
+ projectPath,
6018
+ ) => {
6019
+ const result = await detectProjectType(projectPath);
6020
+ if (!result.detected) {
6021
+ return null;
6022
+ }
5931
6023
 
6024
+ switch (result.type) {
6025
+ case ProjectType.NEXTJS:
6026
+ return 'nextjs';
6027
+ case ProjectType.VITE:
6028
+ return 'vite';
6029
+ case ProjectType.NUXT:
6030
+ return 'nuxt-vue';
6031
+ case ProjectType.EXPO:
6032
+ return 'expo';
6033
+ case ProjectType.TARO:
6034
+ return 'taro';
6035
+ default:
6036
+ return null;
6037
+ }
6038
+ };
5932
6039
 
5933
- const debug$1 = debug$2('coze-init:fix');
5934
-
5935
- /**
5936
- * 需要应用此修复的项目类型
5937
- */
5938
- const SUPPORTED_PROJECT_TYPES = [
5939
- ProjectType.NEXTJS,
5940
- ProjectType.VITE,
5941
- ProjectType.NUXT,
5942
- ] ;
5943
-
5944
- /**
5945
- * 需要处理的脚本文件列表
5946
- */
5947
- const SCRIPT_FILES = ['dev.sh', 'build.sh'] ;
5948
-
5949
- /**
5950
- * 脚本文件修改结果
5951
- */
5952
-
6040
+ function _optionalChain$3(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; }
5953
6041
 
5954
6042
 
6043
+ const PATCH_ID$2 = 'taro/update-pack-script-for-tt-build@0.0.13';
6044
+ const PACKAGE_JSON_FILE = 'package.json';
6045
+ const PACK_SCRIPT_FILE = '.cozeproj/scripts/pack.sh';
6046
+ const LEGACY_PACK_SCRIPT_HASHES = new Set([
6047
+ '987575c08e1c32ce7bc553e1668b3ad8faad5623343fd0d21fea34d39f25a56d',
6048
+ '5e1a1a745f165b09717ffa4b83caac19d03e79e42b273cdd5532df58ac08625d',
6049
+ ]);
6050
+ const TARGET_PACK_SCRIPT = `# pack.sh - 通过 PID 文件精确杀掉自己上次的构建进程
6051
+ WEAPP_PID_FILE="/tmp/coze-build_weapp.pid"
6052
+ TT_PID_FILE="/tmp/coze-build_tt.pid"
6053
+
6054
+ cleanup_previous_build() {
6055
+ PID_FILE="$1"
6056
+ BUILD_NAME="$2"
6057
+
6058
+ if [ -f "$PID_FILE" ]; then
6059
+ OLD_PID=$(cat "$PID_FILE")
6060
+ if kill -0 "$OLD_PID" 2>/dev/null; then
6061
+ echo "正在终止上次的 \${BUILD_NAME} 构建进程组 (PID: $OLD_PID)..."
6062
+ # kill 负数 PID = 杀掉整个进程组
6063
+ kill -9 -"$OLD_PID" 2>/dev/null
6064
+ sleep 1
6065
+ fi
6066
+ rm -f "$PID_FILE"
6067
+ fi
6068
+ }
5955
6069
 
6070
+ cleanup_previous_build "$WEAPP_PID_FILE" "weapp"
6071
+ cleanup_previous_build "$TT_PID_FILE" "tt"
5956
6072
 
6073
+ setsid sh -c 'export OUTPUT_ROOT=dist; pnpm build:weapp' &
6074
+ WEAPP_PID=$!
6075
+ echo "$WEAPP_PID" > "$WEAPP_PID_FILE"
5957
6076
 
6077
+ setsid sh -c 'export OUTPUT_ROOT=dist-tt; pnpm build:tt' &
6078
+ TT_PID=$!
6079
+ echo "$TT_PID" > "$TT_PID_FILE"
5958
6080
 
6081
+ echo "构建已并发启动 (weapp PID: $WEAPP_PID, tt PID: $TT_PID)"
5959
6082
 
6083
+ WEAPP_STATUS=0
6084
+ TT_STATUS=0
5960
6085
 
6086
+ wait "$WEAPP_PID" || WEAPP_STATUS=$?
6087
+ wait "$TT_PID" || TT_STATUS=$?
5961
6088
 
6089
+ rm -f "$WEAPP_PID_FILE" "$TT_PID_FILE"
5962
6090
 
6091
+ if [ "$WEAPP_STATUS" -ne 0 ]; then
6092
+ exit "$WEAPP_STATUS"
6093
+ fi
5963
6094
 
6095
+ if [ "$TT_STATUS" -ne 0 ]; then
6096
+ exit "$TT_STATUS"
6097
+ fi
6098
+ `;
5964
6099
 
5965
6100
 
5966
6101
 
5967
6102
 
5968
6103
 
6104
+ const getProjectPackScriptPath = (projectFolder) =>
6105
+ path.join(projectFolder, PACK_SCRIPT_FILE);
5969
6106
 
6107
+ const hashContent = (content) =>
6108
+ crypto.createHash('sha256').update(content).digest('hex');
5970
6109
 
5971
- /**
5972
- * 替换 shell 脚本中的 npx 为 pnpm
5973
- */
5974
- const replaceNpxInShellScript = async (
5975
- scriptPath,
6110
+ const readPackageScripts = async (
6111
+ projectFolder,
5976
6112
  ) => {
5977
- debug$1(`Reading script file: ${scriptPath}`);
5978
- const content = await fs$1.readFile(scriptPath, 'utf-8');
5979
- debug$1(`File content length: ${content.length} bytes`);
5980
-
5981
- const lines = content.split('\n');
5982
- debug$1(`Total lines: ${lines.length}`);
5983
-
5984
- const modifiedLines = [];
5985
- const fromLines = [];
5986
- const toLines = [];
5987
-
5988
- let hasChanges = false;
5989
-
5990
- for (let i = 0; i < lines.length; i++) {
5991
- const line = lines[i];
5992
- // 检查是否包含 npx 命令
5993
- // 匹配 npx 后面跟着空格和命令
5994
- const npxPattern = /\bnpx\s+/g;
5995
-
5996
- if (npxPattern.test(line)) {
5997
- debug$1(`Found npx at line ${i + 1}: ${line}`);
5998
- const originalLine = line;
5999
- // 替换所有 npx 为 pnpm
6000
- const newLine = line.replace(/\bnpx\s+/g, 'pnpm ');
6001
-
6002
- if (newLine !== originalLine) {
6003
- debug$1(` Replaced to: ${newLine}`);
6004
- modifiedLines.push(newLine);
6005
- fromLines.push(originalLine);
6006
- toLines.push(newLine);
6007
- hasChanges = true;
6008
- } else {
6009
- modifiedLines.push(line);
6010
- }
6011
- } else {
6012
- modifiedLines.push(line);
6013
- }
6113
+ const packageJsonPath = path.join(projectFolder, PACKAGE_JSON_FILE);
6114
+ if (!(await isFileExists(packageJsonPath))) {
6115
+ return null;
6014
6116
  }
6015
6117
 
6016
- if (hasChanges) {
6017
- debug$1(`Writing changes to ${scriptPath}`);
6018
- const newContent = modifiedLines.join('\n');
6019
- await fs$1.writeFile(scriptPath, newContent, 'utf-8');
6020
- } else {
6021
- debug$1(`No changes needed for ${scriptPath}`);
6022
- }
6118
+ const packageJsonContent = await fs$1.readFile(packageJsonPath, 'utf-8');
6119
+ const packageJson = safeJsonParse(packageJsonContent, null);
6023
6120
 
6024
- return { modified: hasChanges, from: fromLines, to: toLines };
6121
+ return _optionalChain$3([packageJson, 'optionalAccess', _ => _.scripts]) || null;
6025
6122
  };
6026
6123
 
6027
- /**
6028
- * 替换项目脚本目录中的 npx 为 pnpm
6029
- */
6030
- const replaceNpxWithPnpm = async (
6031
- projectFolder,
6032
- ) => {
6033
- const scriptsDir = path.join(projectFolder, 'scripts');
6034
- debug$1(`Checking scripts directory: ${scriptsDir}`);
6035
-
6036
- const changedFiles = [];
6037
-
6038
- // 检查 scripts 目录是否存在
6039
- const scriptsDirExists = await isDirExists(scriptsDir);
6040
- debug$1(`Scripts directory exists: ${scriptsDirExists}`);
6124
+ const hasBuildTtScript = async (projectFolder) => {
6125
+ const scripts = await readPackageScripts(projectFolder);
6126
+ return typeof _optionalChain$3([scripts, 'optionalAccess', _2 => _2['build:tt']]) === 'string';
6127
+ };
6041
6128
 
6042
- if (!scriptsDirExists) {
6043
- return { modified: false, changedFiles: [] };
6129
+ const hasLegacyPackScript = async (projectFolder) => {
6130
+ const packScriptPath = getProjectPackScriptPath(projectFolder);
6131
+ if (!(await isFileExists(packScriptPath))) {
6132
+ return false;
6044
6133
  }
6045
6134
 
6046
- // 处理每个脚本文件
6047
- for (const fileName of SCRIPT_FILES) {
6048
- const scriptPath = path.join(scriptsDir, fileName);
6049
- debug$1(`Checking script file: ${scriptPath}`);
6135
+ const content = await fs$1.readFile(packScriptPath, 'utf-8');
6136
+ return LEGACY_PACK_SCRIPT_HASHES.has(hashContent(content));
6137
+ };
6050
6138
 
6051
- const exists = await isFileExists(scriptPath);
6052
- debug$1(` File exists: ${exists}`);
6139
+ const patchTaroPackScript = {
6140
+ id: PATCH_ID$2,
6141
+ template: 'taro',
6142
+ operations: [
6143
+ {
6144
+ kind: 'file-patch',
6145
+ file: PACK_SCRIPT_FILE,
6146
+ description:
6147
+ 'Update legacy taro pack script to build weapp and tt outputs',
6148
+ },
6149
+ ],
6150
+ shouldApply: async context =>
6151
+ context.template === 'taro' &&
6152
+ (await hasBuildTtScript(context.projectFolder)) &&
6153
+ (await hasLegacyPackScript(context.projectFolder)),
6154
+ apply: async (context) => {
6155
+ if (context.template !== 'taro') {
6156
+ return {
6157
+ applied: false,
6158
+ patchId: PATCH_ID$2,
6159
+ message: 'Only applies to taro projects, skipping',
6160
+ };
6161
+ }
6053
6162
 
6054
- if (!exists) {
6055
- continue;
6163
+ if (!(await hasBuildTtScript(context.projectFolder))) {
6164
+ return {
6165
+ applied: false,
6166
+ patchId: PATCH_ID$2,
6167
+ message: 'package.json does not contain build:tt, skipping',
6168
+ };
6056
6169
  }
6057
6170
 
6058
- try {
6059
- const result = await replaceNpxInShellScript(scriptPath);
6060
-
6061
- if (result.modified) {
6062
- debug$1(` File was modified with ${result.from.length} change(s)`);
6063
- changedFiles.push({
6064
- fileName,
6065
- from: result.from,
6066
- to: result.to,
6067
- });
6068
- }
6069
- } catch (error) {
6070
- logger.error(`Failed to process ${fileName}:`, error);
6071
- debug$1(
6072
- ` Error: ${error instanceof Error ? error.message : String(error)}`,
6073
- );
6171
+ if (!(await hasLegacyPackScript(context.projectFolder))) {
6172
+ return {
6173
+ applied: false,
6174
+ patchId: PATCH_ID$2,
6175
+ message: 'pack.sh does not match legacy template hash, skipping',
6176
+ };
6074
6177
  }
6075
- }
6076
6178
 
6077
- debug$1(`Total files modified: ${changedFiles.length}`);
6179
+ const targetPath = getProjectPackScriptPath(context.projectFolder);
6180
+ await fs$1.writeFile(targetPath, TARGET_PACK_SCRIPT, 'utf-8');
6078
6181
 
6079
- return {
6080
- modified: changedFiles.length > 0,
6081
- changedFiles,
6082
- };
6182
+ logger.info(
6183
+ `Patched ${PACK_SCRIPT_FILE}: updated taro multi-target pack script`,
6184
+ );
6185
+
6186
+ return {
6187
+ applied: true,
6188
+ patchId: PATCH_ID$2,
6189
+ message: 'Updated legacy pack.sh to build weapp and tt targets',
6190
+ };
6191
+ },
6083
6192
  };
6084
6193
 
6085
- /**
6086
- * Fix 规则:将 scripts/ 目录下的 shell 脚本中的 npx 命令替换为 pnpm
6087
- *
6088
- * 背景:在某些项目类型(Next.js、Vite、Nuxt)中,使用 npx 可能会导致模块解析问题。
6089
- * 将 npx 替换为 pnpm 可以确保使用项目本地安装的依赖,避免版本冲突和解析错误。
6090
- */
6091
- const fixReplaceNpxWithPnpm = async context => {
6092
- const ruleName = 'replace-npx-with-pnpm';
6194
+ const PATCH_ID$1 = 'taro/add-agents-md@0.0.13';
6195
+ const AGENTS_FILE = 'AGENTS.md';
6196
+ const getTemplateAgentsPath = () =>
6197
+ path.join(getTemplatesDir(), 'taro', AGENTS_FILE);
6093
6198
 
6094
- debug$1(`Starting fix rule: ${ruleName}`);
6095
- debug$1(`Project folder: ${context.projectFolder}`);
6199
+ const getProjectAgentsPath = (projectFolder) =>
6200
+ path.join(projectFolder, AGENTS_FILE);
6096
6201
 
6097
- // 1. 检测项目类型
6098
- const projectDetection = await detectProjectType(context.projectFolder);
6099
- debug$1(`Project detection result: ${JSON.stringify(projectDetection)}`);
6202
+ const readTemplateAgentsContent = async () =>
6203
+ fs$1.readFile(getTemplateAgentsPath(), 'utf-8');
6100
6204
 
6101
- if (!projectDetection.detected) {
6102
- return {
6103
- ruleName,
6104
- applied: false,
6105
- message: 'Project type not detected, skipping',
6106
- };
6107
- }
6205
+ const patchTaroAgentsMd = {
6206
+ id: PATCH_ID$1,
6207
+ template: 'taro',
6208
+ operations: [
6209
+ {
6210
+ kind: 'create-file',
6211
+ file: AGENTS_FILE,
6212
+ description:
6213
+ 'Add template AGENTS.md to taro projects that do not have one',
6214
+ },
6215
+ ],
6216
+ shouldApply: async context =>
6217
+ context.template === 'taro' &&
6218
+ !(await isFileExists(getProjectAgentsPath(context.projectFolder))),
6219
+ apply: async (context) => {
6220
+ if (context.template !== 'taro') {
6221
+ return {
6222
+ applied: false,
6223
+ patchId: PATCH_ID$1,
6224
+ message: 'Only applies to taro projects, skipping',
6225
+ };
6226
+ }
6108
6227
 
6109
- // 2. 检查是否为支持的项目类型
6110
- const isSupportedType = (
6111
- SUPPORTED_PROJECT_TYPES
6112
- ).includes(projectDetection.type);
6228
+ const targetPath = getProjectAgentsPath(context.projectFolder);
6229
+ if (await isFileExists(targetPath)) {
6230
+ return {
6231
+ applied: false,
6232
+ patchId: PATCH_ID$1,
6233
+ message: 'AGENTS.md already exists, skipping',
6234
+ };
6235
+ }
6113
6236
 
6114
- debug$1(`Is supported type: ${isSupportedType}`);
6115
- debug$1(`Supported types: ${SUPPORTED_PROJECT_TYPES.join(', ')}`);
6237
+ const templateContent = await readTemplateAgentsContent();
6238
+ await fs$1.writeFile(targetPath, templateContent, 'utf-8');
6116
6239
 
6117
- if (!isSupportedType) {
6118
6240
  return {
6119
- ruleName,
6120
- applied: false,
6121
- message: 'Project type not supported for this fix, skipping',
6241
+ applied: true,
6242
+ patchId: PATCH_ID$1,
6243
+ message: 'Created AGENTS.md from taro template',
6122
6244
  };
6245
+ },
6246
+ };
6247
+
6248
+ const SCRIPT_FILES = ['dev.sh', 'build.sh'] ;
6249
+ const SUPPORTED_TEMPLATES = new Set(['nextjs', 'vite', 'nuxt-vue']);
6250
+
6251
+ const hasNpxInScripts = async (projectFolder) => {
6252
+ const scriptsDir = path.join(projectFolder, 'scripts');
6253
+ if (!(await isDirExists(scriptsDir))) {
6254
+ return false;
6123
6255
  }
6124
6256
 
6125
- logger.info(`Detected ${projectDetection.type} project`);
6257
+ for (const fileName of SCRIPT_FILES) {
6258
+ const scriptPath = path.join(scriptsDir, fileName);
6259
+ if (!(await isFileExists(scriptPath))) {
6260
+ continue;
6261
+ }
6126
6262
 
6127
- // 3. 执行替换
6128
- debug$1('Starting npx replacement...');
6129
- const replaceResult = await replaceNpxWithPnpm(context.projectFolder);
6263
+ const content = await fs$1.readFile(scriptPath, 'utf-8');
6264
+ if (/\bnpx\s+/.test(content)) {
6265
+ return true;
6266
+ }
6267
+ }
6268
+
6269
+ return false;
6270
+ };
6130
6271
 
6131
- if (!replaceResult.modified) {
6272
+ const applyReplaceNpxWithPnpm = async (
6273
+ context,
6274
+ patchId,
6275
+ ) => {
6276
+ const scriptsDir = path.join(context.projectFolder, 'scripts');
6277
+ let changedFiles = 0;
6278
+
6279
+ if (!(await isDirExists(scriptsDir))) {
6132
6280
  return {
6133
- ruleName,
6134
6281
  applied: false,
6135
- message: 'No npx commands found in shell scripts, skipping',
6282
+ patchId,
6283
+ message: 'scripts directory not found, skipping',
6136
6284
  };
6137
6285
  }
6138
6286
 
6139
- // 4. 输出修改信息
6140
- logger.success(
6141
- `Replaced npx with pnpm in ${replaceResult.changedFiles.length} file(s)`,
6142
- );
6287
+ for (const fileName of SCRIPT_FILES) {
6288
+ const scriptPath = path.join(scriptsDir, fileName);
6289
+ if (!(await isFileExists(scriptPath))) {
6290
+ continue;
6291
+ }
6143
6292
 
6144
- for (const file of replaceResult.changedFiles) {
6145
- logger.info(` scripts/${file.fileName}:`);
6146
- for (let i = 0; i < file.from.length; i++) {
6147
- logger.info(` - ${file.from[i]}`);
6148
- logger.info(` + ${file.to[i]}`);
6293
+ const content = await fs$1.readFile(scriptPath, 'utf-8');
6294
+ const nextContent = content.replace(/\bnpx\s+/g, 'pnpm ');
6295
+ if (nextContent === content) {
6296
+ continue;
6149
6297
  }
6298
+
6299
+ await fs$1.writeFile(scriptPath, nextContent, 'utf-8');
6300
+ changedFiles++;
6301
+ logger.info(`Patched scripts/${fileName}: replaced npx with pnpm`);
6150
6302
  }
6151
6303
 
6152
6304
  return {
6153
- ruleName,
6154
- applied: true,
6155
- message: `Successfully replaced npx with pnpm in ${replaceResult.changedFiles.length} file(s)`,
6305
+ applied: changedFiles > 0,
6306
+ patchId,
6307
+ message:
6308
+ changedFiles > 0
6309
+ ? `Replaced npx with pnpm in ${changedFiles} file(s)`
6310
+ : 'No npx commands found in shell scripts, skipping',
6156
6311
  };
6157
6312
  };
6158
6313
 
6159
- // ABOUTME: Fix rule to comment out problematic outputFileTracingRoot config in Next.js projects
6160
- // ABOUTME: This config can cause issues in monorepo environments and should be removed
6314
+ const createReplaceNpxWithPnpmPatch = (
6315
+ template,
6316
+ ) => ({
6317
+ id: `${template}/replace-npx-with-pnpm@0.0.13`,
6318
+ template,
6319
+ operations: [
6320
+ {
6321
+ kind: 'file-patch',
6322
+ file: 'scripts/dev.sh',
6323
+ description: 'Replace npx with pnpm in shell scripts',
6324
+ },
6325
+ {
6326
+ kind: 'file-patch',
6327
+ file: 'scripts/build.sh',
6328
+ description: 'Replace npx with pnpm in shell scripts',
6329
+ },
6330
+ ],
6331
+ shouldApply: async context =>
6332
+ SUPPORTED_TEMPLATES.has(context.template) &&
6333
+ (await hasNpxInScripts(context.projectFolder)),
6334
+ apply: async context =>
6335
+ applyReplaceNpxWithPnpm(
6336
+ context,
6337
+ `${template}/replace-npx-with-pnpm@0.0.13`,
6338
+ ),
6339
+ });
6161
6340
 
6341
+ const replaceNpxWithPnpmPatchNextjs =
6342
+ createReplaceNpxWithPnpmPatch('nextjs');
6343
+ const replaceNpxWithPnpmPatchVite =
6344
+ createReplaceNpxWithPnpmPatch('vite');
6345
+ const replaceNpxWithPnpmPatchNuxtVue =
6346
+ createReplaceNpxWithPnpmPatch('nuxt-vue');
6162
6347
 
6163
- /**
6164
- * 检查是否为 Next.js 项目
6165
- */
6166
- const isNextProject = async (projectFolder) =>
6167
- isProjectType(projectFolder, ProjectType.NEXTJS);
6168
-
6169
- /**
6170
- * 查找 Next.js 配置文件
6171
- */
6172
6348
  const findNextConfigFile = async (
6173
6349
  projectFolder,
6174
6350
  ) => {
@@ -6188,221 +6364,265 @@ const findNextConfigFile = async (
6188
6364
  return null;
6189
6365
  };
6190
6366
 
6191
- /**
6192
- * 注释掉 outputFileTracingRoot 配置
6193
- */
6194
- const commentOutOutputTracingRoot = async (
6367
+ const getUncommentedTracingRootLine = async (
6195
6368
  configPath,
6196
6369
  ) => {
6197
- let content = await fs$1.readFile(configPath, 'utf-8');
6198
- let modified = false;
6199
- let originalLine = null;
6200
-
6201
- // 匹配包含 outputFileTracingRoot 的行(尚未被注释的)
6202
- // 支持 path.resolve(...) 后面有空格,然后可选逗号
6203
- // 只匹配单行配置,不匹配跨多行的配置
6370
+ const content = await fs$1.readFile(configPath, 'utf-8');
6204
6371
  const pattern =
6205
6372
  /^(\s*)(outputFileTracingRoot:\s*path\.resolve\([^\n\r)]+\)\s*,?)\s*$/gm;
6206
6373
 
6207
6374
  const matches = content.match(pattern);
6375
+ return matches && matches.length > 0 ? matches[0].trim() : null;
6376
+ };
6208
6377
 
6209
- if (matches && matches.length > 0) {
6210
- originalLine = matches[0].trim();
6211
-
6212
- // 在匹配的行前添加 // 注释
6213
- content = content.replace(pattern, '$1// $2');
6214
- modified = true;
6378
+ const commentOutOutputTracingRoot = async (
6379
+ configPath,
6380
+ ) => {
6381
+ const content = await fs$1.readFile(configPath, 'utf-8');
6382
+ const pattern =
6383
+ /^(\s*)(outputFileTracingRoot:\s*path\.resolve\([^\n\r)]+\)\s*,?)\s*$/gm;
6384
+ const matches = content.match(pattern);
6215
6385
 
6216
- await fs$1.writeFile(configPath, content, 'utf-8');
6386
+ if (!matches || matches.length === 0) {
6387
+ return null;
6217
6388
  }
6218
6389
 
6219
- return { modified, originalLine };
6390
+ const originalLine = matches[0].trim();
6391
+ const nextContent = content.replace(pattern, '$1// $2');
6392
+ await fs$1.writeFile(configPath, nextContent, 'utf-8');
6393
+ return originalLine;
6220
6394
  };
6221
6395
 
6222
- /**
6223
- * Fix 规则:注释掉 Next.js 项目中的 outputFileTracingRoot 配置
6224
- * 这个配置在 monorepo 环境中可能会导致问题
6225
- */
6226
- const fixNextOutputTracingRoot = async context => {
6227
- const ruleName = 'next-output-tracing-root';
6396
+ const PATCH_ID = 'nextjs/next-output-tracing-root@0.0.13';
6228
6397
 
6229
- // 1. 检查是否为 Next.js 项目
6230
- if (!(await isNextProject(context.projectFolder))) {
6231
- return {
6232
- ruleName,
6233
- applied: false,
6234
- message: 'Not a Next.js project, skipping',
6235
- };
6236
- }
6398
+ const patchNextOutputTracingRoot = {
6399
+ id: PATCH_ID,
6400
+ template: 'nextjs',
6401
+ operations: [
6402
+ {
6403
+ kind: 'file-patch',
6404
+ file: 'next.config.ts',
6405
+ description: 'Comment out problematic outputFileTracingRoot config',
6406
+ },
6407
+ ],
6408
+ shouldApply: async context => {
6409
+ if (context.template !== 'nextjs') {
6410
+ return false;
6411
+ }
6237
6412
 
6238
- // 2. 查找 Next.js 配置文件
6239
- const configPath = await findNextConfigFile(context.projectFolder);
6413
+ const configPath = await findNextConfigFile(context.projectFolder);
6414
+ if (!configPath) {
6415
+ return false;
6416
+ }
6240
6417
 
6241
- if (!configPath) {
6242
- return {
6243
- ruleName,
6244
- applied: false,
6245
- message: 'Next.js config file not found, skipping',
6246
- };
6247
- }
6418
+ return (await getUncommentedTracingRootLine(configPath)) !== null;
6419
+ },
6420
+ apply: async (context) => {
6421
+ const configPath = await findNextConfigFile(context.projectFolder);
6422
+ if (!configPath) {
6423
+ return {
6424
+ applied: false,
6425
+ patchId: PATCH_ID,
6426
+ message: 'Next.js config file not found, skipping',
6427
+ };
6428
+ }
6248
6429
 
6249
- // 3. 注释掉 outputFileTracingRoot 配置
6250
- const { modified, originalLine } =
6251
- await commentOutOutputTracingRoot(configPath);
6430
+ const originalLine = await commentOutOutputTracingRoot(configPath);
6431
+ if (!originalLine) {
6432
+ return {
6433
+ applied: false,
6434
+ patchId: PATCH_ID,
6435
+ message: 'No outputFileTracingRoot config found, skipping',
6436
+ };
6437
+ }
6252
6438
 
6253
- if (modified && originalLine) {
6254
- logger.success(
6255
- `Commented out outputFileTracingRoot in ${configPath.split('/').pop()}`,
6439
+ logger.info(
6440
+ `Patched ${configPath.split('/').pop()}: commented out ${originalLine}`,
6256
6441
  );
6257
- logger.info(` Original: ${originalLine}`);
6258
6442
 
6259
6443
  return {
6260
- ruleName,
6261
6444
  applied: true,
6445
+ patchId: PATCH_ID,
6262
6446
  message: `Successfully commented out: ${originalLine}`,
6263
6447
  };
6448
+ },
6449
+ };
6450
+
6451
+ const patches = [
6452
+ replaceNpxWithPnpmPatchNextjs,
6453
+ replaceNpxWithPnpmPatchVite,
6454
+ replaceNpxWithPnpmPatchNuxtVue,
6455
+ patchNextOutputTracingRoot,
6456
+ patchTaroAgentsMd,
6457
+ patchTaroPackScript,
6458
+ ] ;
6459
+
6460
+ const getTemplatePatches = (
6461
+ template,
6462
+ ) =>
6463
+ patches.filter(patch => patch.template === template);
6464
+
6465
+ function _nullishCoalesce$2(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$2(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; }
6466
+ const DEFAULT_LEGACY_VERSION = 'legacy';
6467
+
6468
+ const loadExistingTomlConfig = async (
6469
+ projectFolder,
6470
+ ) => {
6471
+ try {
6472
+ await fs$1.access(path.resolve(projectFolder, '.coze'));
6473
+ } catch (e) {
6474
+ return null;
6264
6475
  }
6265
6476
 
6266
- return {
6267
- ruleName,
6268
- applied: false,
6269
- message: 'No outputFileTracingRoot config found, skipping',
6270
- };
6477
+ return loadTomlCozeConfig(projectFolder);
6271
6478
  };
6272
6479
 
6273
- /**
6274
- * 所有修复规则的数组
6275
- * 按顺序执行,新增规则直接添加到数组中
6276
- */
6277
- const rules = [
6278
- // Package manager fixes (should run first)
6279
- fixReplaceNpxWithPnpm,
6480
+ const writePatchState = async (
6481
+ projectFolder,
6482
+ config,
6483
+ state
6280
6484
 
6281
- // Next.js related fixes
6282
- fixNextOutputTracingRoot,
6283
6485
 
6284
- // Add more rules here
6285
- ] ;
6286
6486
 
6287
- // ABOUTME: Fix command for resolving legacy issues from previous project versions
6288
- // ABOUTME: Applies a series of fix rules defined in the fix-rules directory
6487
+ ,
6488
+ ) => {
6489
+ config.project = {
6490
+ ...(config.project || {}),
6491
+ template: state.template,
6492
+ version: state.version,
6493
+ appliedPatches: state.appliedPatches,
6494
+ };
6495
+
6496
+ await saveTomlCozeConfig(config, projectFolder);
6497
+ };
6498
+
6499
+ const getNextPatchState = (
6500
+ config,
6501
+ template,
6502
+ appliedPatches,
6503
+ patchId,
6289
6504
 
6290
6505
 
6291
- const debug = debug$2('coze-init:fix');
6292
6506
 
6293
- const JSON_INDENT_SPACES = 2;
6294
6507
 
6295
- // start_aigc
6296
- /**
6297
- * 执行 fix 命令的内部实现
6298
- */
6299
- const executeFix = async (
6508
+ ) => ({
6509
+ template,
6510
+ version: _optionalChain$2([config, 'access', _ => _.project, 'optionalAccess', _2 => _2.version]) || DEFAULT_LEGACY_VERSION,
6511
+ appliedPatches: [...appliedPatches, patchId],
6512
+ });
6513
+
6514
+ const executePatch = async (
6300
6515
  options = {},
6301
6516
  ) => {
6302
- try {
6303
- const cwd = process.cwd();
6304
- const projectFolder = options.directory
6305
- ? path.resolve(cwd, options.directory)
6306
- : cwd;
6517
+ const cwd = process.cwd();
6518
+ const projectFolder = options.directory
6519
+ ? path.resolve(cwd, options.directory)
6520
+ : cwd;
6307
6521
 
6308
- logger.info(`Running fix command on: ${projectFolder}`);
6309
- debug(`Current working directory: ${cwd}`);
6310
- logger.info(`Found ${rules.length} fix rule(s) to apply\n`);
6522
+ if (await isDirectoryEmpty(projectFolder)) {
6523
+ logger.info(`Patch skipped: ${projectFolder} is empty`);
6524
+ return;
6525
+ }
6311
6526
 
6312
- const context = {
6313
- cwd,
6314
- projectFolder,
6315
- };
6527
+ const config = await loadExistingTomlConfig(projectFolder);
6528
+ if (!config) {
6529
+ logger.info('Patch skipped: .coze file not found');
6530
+ return;
6531
+ }
6316
6532
 
6317
- debug(
6318
- `Fix context: ${JSON.stringify(context, null, JSON_INDENT_SPACES)}\n`,
6319
- );
6533
+ const template =
6534
+ _optionalChain$2([config, 'access', _3 => _3.project, 'optionalAccess', _4 => _4.template]) || (await detectTemplateKey(projectFolder));
6535
+
6536
+ if (!template) {
6537
+ logger.info('Patch skipped: template not detected');
6538
+ return;
6539
+ }
6320
6540
 
6321
- let appliedCount = 0;
6322
- let skippedCount = 0;
6323
- let errorCount = 0;
6541
+ const appliedPatches = [...(_optionalChain$2([config, 'access', _5 => _5.project, 'optionalAccess', _6 => _6.appliedPatches]) || [])];
6542
+ const projectVersion = _optionalChain$2([config, 'access', _7 => _7.project, 'optionalAccess', _8 => _8.version]);
6324
6543
 
6325
- // 依次执行所有修复规则
6326
- for (let i = 0; i < rules.length; i++) {
6327
- const rule = rules[i];
6328
- const ruleNumber = i + 1;
6544
+ const context = {
6545
+ cwd,
6546
+ projectFolder,
6547
+ template,
6548
+ projectVersion,
6549
+ appliedPatches,
6550
+ cozeConfig: config,
6551
+ };
6329
6552
 
6330
- try {
6331
- debug(`[${ruleNumber}/${rules.length}] Starting rule execution...`);
6553
+ const candidatePatches = getTemplatePatches(template).filter(
6554
+ patch => patch.disabled !== true && !appliedPatches.includes(patch.id),
6555
+ );
6332
6556
 
6333
- const startTime = Date.now();
6334
- const result = await Promise.resolve(rule(context));
6335
- const duration = Date.now() - startTime;
6557
+ const matchedPatches = [];
6558
+ for (const patch of candidatePatches) {
6559
+ if (await patch.shouldApply(context)) {
6560
+ matchedPatches.push(patch);
6561
+ }
6562
+ }
6336
6563
 
6337
- debug(`Rule execution completed in ${duration}ms`);
6338
- debug(`Result: ${JSON.stringify(result, null, JSON_INDENT_SPACES)}`);
6564
+ if (matchedPatches.length === 0) {
6565
+ logger.info('No patch matched current project state');
6566
+ return;
6567
+ }
6339
6568
 
6340
- if (result.applied) {
6341
- appliedCount++;
6342
- logger.success(`✓ ${result.ruleName}: ${result.message}`);
6569
+ if (options.dryRun) {
6570
+ logger.info(`Detected template: ${template}`);
6571
+ logger.info(`Current version: ${_nullishCoalesce$2(projectVersion, () => ( DEFAULT_LEGACY_VERSION))}`);
6572
+ logger.info(`Applied patches: ${appliedPatches.join(', ') || '(none)'}`);
6573
+ logger.info('Matched patches:');
6574
+ matchedPatches.forEach(patch => {
6575
+ logger.info(` - ${patch.id}`);
6576
+ patch.operations.forEach(operation => {
6577
+ if ('file' in operation) {
6578
+ logger.info(
6579
+ ` ${operation.kind}: ${operation.file} - ${operation.description}`,
6580
+ );
6343
6581
  } else {
6344
- skippedCount++;
6345
- logger.info(`○ ${result.ruleName}: ${result.message}`);
6582
+ logger.info(` ${operation.kind}: ${operation.description}`);
6346
6583
  }
6584
+ });
6585
+ });
6586
+ return;
6587
+ }
6347
6588
 
6348
- debug(''); // Empty line for readability
6349
- } catch (error) {
6350
- errorCount++;
6351
- const errorMessage =
6352
- error instanceof Error ? error.message : String(error);
6353
- logger.error(`✗ Rule execution failed: ${errorMessage}`);
6354
-
6355
- // 输出详细的错误堆栈信息(仅在 debug 模式下)
6356
- if (error instanceof Error && error.stack) {
6357
- debug(`Error stack trace:\n${error.stack}`);
6358
- }
6589
+ for (const patch of matchedPatches) {
6590
+ const result = await patch.apply({
6591
+ ...context,
6592
+ appliedPatches,
6593
+ });
6359
6594
 
6360
- debug(''); // Empty line for readability
6361
- }
6595
+ if (!result.applied) {
6596
+ logger.info(`○ ${patch.id}: ${result.message}`);
6597
+ continue;
6362
6598
  }
6363
6599
 
6364
- // 输出汇总信息
6365
- debug('\n=== Fix Command Summary ===');
6366
- logger.info(
6367
- `\nSummary: ${appliedCount} fixed, ${skippedCount} skipped, ${errorCount} errors, ${rules.length} total`,
6600
+ const nextState = getNextPatchState(
6601
+ config,
6602
+ template,
6603
+ appliedPatches,
6604
+ patch.id,
6368
6605
  );
6369
-
6370
- if (appliedCount > 0) {
6371
- logger.success('\nFixes applied successfully!');
6372
- } else if (errorCount > 0) {
6373
- logger.warn('\nSome fixes failed, check logs above for details');
6374
- } else {
6375
- logger.info('\nNo fixes needed');
6376
- }
6377
- } catch (error) {
6378
- logger.error('Failed to run fix command:');
6379
- logger.error(error instanceof Error ? error.message : String(error));
6380
-
6381
- // 输出详细的错误信息
6382
- if (error instanceof Error && error.stack) {
6383
- debug(`Error stack trace:\n${error.stack}`);
6384
- }
6385
-
6386
- process.exit(1);
6606
+ await writePatchState(projectFolder, config, nextState);
6607
+ appliedPatches.push(patch.id);
6608
+ logger.success(`✓ ${patch.id}: ${result.message}`);
6387
6609
  }
6388
6610
  };
6389
- // end_aigc
6390
6611
 
6391
- /**
6392
- * 注册 fix 命令到 program
6393
- */
6394
6612
  const registerCommand$3 = program => {
6395
6613
  program
6396
- .command('fix')
6397
- .description(
6398
- 'Fix legacy issues from previous versions (e.g., problematic configs)',
6399
- )
6614
+ .command('patch')
6615
+ .description('Apply template patches for existing projects')
6400
6616
  .argument(
6401
6617
  '[directory]',
6402
- 'Target directory to fix (defaults to current directory)',
6618
+ 'Target directory to patch (defaults to current directory)',
6403
6619
  )
6404
- .action(async (directory) => {
6405
- await executeFix({ directory });
6620
+ .option('--dry-run', 'Show matched patches without modifying files')
6621
+ .action(async (directory, command) => {
6622
+ await executePatch({
6623
+ directory,
6624
+ dryRun: _optionalChain$2([command, 'optionalAccess', _9 => _9.dryRun]),
6625
+ });
6406
6626
  });
6407
6627
  };
6408
6628
 
@@ -6500,12 +6720,12 @@ const executeRun = async (
6500
6720
  // 上报命令开始
6501
6721
  reportCommandStart(commandName, JSON.stringify(options), { projectType });
6502
6722
 
6503
- // 1. 对于 build 命令,先执行 fix 以确保项目配置正确
6723
+ // 1. 对于 build/dev 命令,先执行 patch 以确保项目配置正确
6504
6724
  if (['dev', 'build'].includes(commandName)) {
6505
- logger.info('\n🔧 Running fix command before build...\n');
6725
+ logger.info('\n🔧 Running patch command before execution...\n');
6506
6726
  const fixStartTime = Date.now();
6507
6727
  try {
6508
- await executeFix();
6728
+ await executePatch();
6509
6729
  // eslint-disable-next-line @coze-arch/no-empty-catch, @coze-arch/use-error-in-catch -- intentionally ignored
6510
6730
  } catch (_e) {
6511
6731
  // fix errors are intentionally ignored to allow the main command to proceed
@@ -6688,7 +6908,7 @@ const registerCommand$2 = program => {
6688
6908
 
6689
6909
 
6690
6910
 
6691
- const log$4 = debug$2('coze:routes:nuxt');
6911
+ const log$4 = debug('coze:routes:nuxt');
6692
6912
 
6693
6913
  /**
6694
6914
  * Convert Nuxt file path to route path
@@ -6928,7 +7148,7 @@ const scanNuxtRoutes = async (cwd) => {
6928
7148
 
6929
7149
 
6930
7150
 
6931
- const log$3 = debug$2('coze:routes:nextjs');
7151
+ const log$3 = debug('coze:routes:nextjs');
6932
7152
 
6933
7153
  /**
6934
7154
  * Convert Next.js file path to route path
@@ -7269,7 +7489,7 @@ const getOutputFilePath = (cwd, outputPath) =>
7269
7489
 
7270
7490
 
7271
7491
 
7272
- const log$2 = debug$2('coze:routes:detect');
7492
+ const log$2 = debug('coze:routes:detect');
7273
7493
 
7274
7494
  /**
7275
7495
  * Check if any of the specified files exist
@@ -7374,7 +7594,7 @@ const detectTemplate = (cwd) => {
7374
7594
  // ABOUTME: Orchestrates template detection, route scanning, and polling-based updates
7375
7595
 
7376
7596
 
7377
- const log$1 = debug$2('coze:routes:scanner');
7597
+ const log$1 = debug('coze:routes:scanner');
7378
7598
 
7379
7599
  /**
7380
7600
  * Scan routes based on template type
@@ -7475,7 +7695,7 @@ const scanRoutesOnce = async (
7475
7695
  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; }// Route manifest generation command
7476
7696
 
7477
7697
 
7478
- const log = debug$2('coze:routes');
7698
+ const log = debug('coze:routes');
7479
7699
 
7480
7700
  /**
7481
7701
  * Execute routes command implementation
@@ -8631,7 +8851,22 @@ const executeTemplateEngineStep = async ctx => {
8631
8851
  };
8632
8852
 
8633
8853
  /**
8634
- * 步骤2: 检查 package.json 是否存在
8854
+ * 步骤2: 写入 patch 项目元数据
8855
+ */
8856
+ const writePatchMetadataStep = async ctx => {
8857
+ if (!ctx.absoluteOutputPath) {
8858
+ return;
8859
+ }
8860
+
8861
+ await saveProjectPatchState(ctx.absoluteOutputPath, {
8862
+ template: ctx.templateName,
8863
+ version: packageJson.version,
8864
+ appliedPatches: [],
8865
+ });
8866
+ };
8867
+
8868
+ /**
8869
+ * 步骤3: 检查 package.json 是否存在
8635
8870
  */
8636
8871
  const checkPackageJsonStep = ctx => {
8637
8872
  if (!ctx.absoluteOutputPath) {
@@ -8643,7 +8878,7 @@ const checkPackageJsonStep = ctx => {
8643
8878
  };
8644
8879
 
8645
8880
  /**
8646
- * 步骤3: 安装依赖
8881
+ * 步骤4: 安装依赖
8647
8882
  */
8648
8883
  const installDependenciesStep = ctx => {
8649
8884
  if (!ctx.absoluteOutputPath) {
@@ -8691,7 +8926,7 @@ const installDependenciesStep = ctx => {
8691
8926
  };
8692
8927
 
8693
8928
  /**
8694
- * 步骤4: 执行完成钩子
8929
+ * 步骤5: 执行完成钩子
8695
8930
  */
8696
8931
  const executeCompleteHookStep = async ctx => {
8697
8932
  if (!ctx.absoluteOutputPath || !ctx.templateConfig || !ctx.context) {
@@ -8708,7 +8943,7 @@ const executeCompleteHookStep = async ctx => {
8708
8943
  };
8709
8944
 
8710
8945
  /**
8711
- * 步骤5: 初始化 Git 仓库
8946
+ * 步骤6: 初始化 Git 仓库
8712
8947
  */
8713
8948
  const gitInitStep = ctx => {
8714
8949
  if (!ctx.absoluteOutputPath) {
@@ -8724,7 +8959,7 @@ const gitInitStep = ctx => {
8724
8959
  };
8725
8960
 
8726
8961
  /**
8727
- * 步骤6: 提交 Git 变更
8962
+ * 步骤7: 提交 Git 变更
8728
8963
  */
8729
8964
  const gitCommitStep = ctx => {
8730
8965
  if (!ctx.absoluteOutputPath) {
@@ -8740,7 +8975,7 @@ const gitCommitStep = ctx => {
8740
8975
  };
8741
8976
 
8742
8977
  /**
8743
- * 步骤7: 启动开发服务器
8978
+ * 步骤8: 启动开发服务器
8744
8979
  */
8745
8980
  const startDevServerStep = ctx => {
8746
8981
  if (!ctx.absoluteOutputPath) {
@@ -8774,6 +9009,7 @@ const startDevServerStep = ctx => {
8774
9009
  */
8775
9010
  const initSteps = [
8776
9011
  executeTemplateEngineStep,
9012
+ writePatchMetadataStep,
8777
9013
  checkPackageJsonStep,
8778
9014
  installDependenciesStep,
8779
9015
  executeCompleteHookStep,