@coze-arch/cli 0.0.11 → 0.0.12-alpha.3cee6f

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.3cee6f";
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,456 @@ 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;
6015
+
6016
+ const detectTemplateKey = async (
6017
+ projectPath,
6018
+ ) => {
6019
+ const result = await detectProjectType(projectPath);
6020
+ if (!result.detected) {
6021
+ return null;
6022
+ }
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
+ };
6039
+
6040
+ const PATCH_FG_ENDPOINT =
6041
+ 'https://bytegate.zijieapi.com/api/v1/workspace/feature_gates/values?workspace=CozeCoding';
6042
+ const PATCH_FG_TIMEOUT_MS = 2000;
5930
6043
 
6044
+ const PATCH_FG_REQUEST_BODY = {
6045
+ byteGateClientUrl: 'https://bytegate.zijieapi.com',
6046
+ env: 'ONLINE',
6047
+ region: 'CN',
6048
+ workspace_name: 'CozeCoding',
6049
+ project_path: '/',
6050
+ };
5931
6051
 
5932
6052
 
5933
- const debug$1 = debug$2('coze-init:fix');
5934
6053
 
5935
- /**
5936
- * 需要应用此修复的项目类型
5937
- */
5938
- const SUPPORTED_PROJECT_TYPES = [
5939
- ProjectType.NEXTJS,
5940
- ProjectType.VITE,
5941
- ProjectType.NUXT,
5942
- ] ;
5943
6054
 
5944
- /**
5945
- * 需要处理的脚本文件列表
5946
- */
5947
- const SCRIPT_FILES = ['dev.sh', 'build.sh'] ;
5948
6055
 
5949
- /**
5950
- * 脚本文件修改结果
5951
- */
6056
+ const PATCH_CLI_FLAG = 'coding.arch.patch_cli';
6057
+ const PATCH_FLAGS_ENV_KEY = 'COZE_PATCH_FLAGS_JSON';
5952
6058
 
6059
+ const isFlagEnabled = (
6060
+ flags,
6061
+ flag,
6062
+ ) => flags[flag] === true;
5953
6063
 
6064
+ const loadPatchFlags = async () => {
6065
+ const envFlags = process.env[PATCH_FLAGS_ENV_KEY];
6066
+ if (envFlags) {
6067
+ const parsed = safeJsonParse(envFlags, null);
6068
+ if (!parsed) {
6069
+ throw new Error(`Invalid JSON in ${PATCH_FLAGS_ENV_KEY}`);
6070
+ }
6071
+ return Object.entries(parsed).reduce(
6072
+ (acc, [key, value]) => {
6073
+ if (typeof value === 'boolean') {
6074
+ acc[key] = value;
6075
+ }
6076
+ return acc;
6077
+ },
6078
+ {},
6079
+ );
6080
+ }
5954
6081
 
6082
+ const controller = new AbortController();
6083
+ const timeoutId = setTimeout(() => {
6084
+ controller.abort();
6085
+ }, PATCH_FG_TIMEOUT_MS);
5955
6086
 
6087
+ let response;
6088
+ try {
6089
+ response = await fetch(PATCH_FG_ENDPOINT, {
6090
+ method: 'POST',
6091
+ headers: {
6092
+ 'content-type': 'application/json',
6093
+ },
6094
+ body: JSON.stringify(PATCH_FG_REQUEST_BODY),
6095
+ signal: controller.signal,
6096
+ });
6097
+ } catch (error) {
6098
+ if (controller.signal.aborted) {
6099
+ throw new Error(
6100
+ `Failed to load patch flags: request timed out after ${PATCH_FG_TIMEOUT_MS}ms`,
6101
+ );
6102
+ }
6103
+ throw error;
6104
+ } finally {
6105
+ clearTimeout(timeoutId);
6106
+ }
5956
6107
 
6108
+ if (!response.ok) {
6109
+ throw new Error(`Failed to load patch flags: HTTP ${response.status}`);
6110
+ }
5957
6111
 
6112
+ const result = (await response.json())
5958
6113
 
6114
+ ;
5959
6115
 
6116
+ const values =
6117
+ 'data' in result && result.data && typeof result.data === 'object'
6118
+ ? result.data
6119
+ : result;
5960
6120
 
6121
+ if (!values || typeof values !== 'object') {
6122
+ throw new Error('Failed to load patch flags: invalid response shape');
6123
+ }
5961
6124
 
6125
+ return Object.entries(values).reduce(
6126
+ (acc, [key, value]) => {
6127
+ if (typeof value === 'boolean') {
6128
+ acc[key] = value;
6129
+ }
6130
+ return acc;
6131
+ },
6132
+ {},
6133
+ );
6134
+ };
5962
6135
 
6136
+ const byFlag = (flag) => {
6137
+ const predicate = ((context) =>
6138
+ !context.isFlagEnabled(flag)) ;
6139
+ Object.defineProperty(predicate, 'flag', {
6140
+ value: flag,
6141
+ enumerable: true,
6142
+ configurable: false,
6143
+ writable: false,
6144
+ });
6145
+ return predicate;
6146
+ };
5963
6147
 
6148
+ 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; }
6149
+ const PATCH_ID$2 = 'taro/update-pack-script-for-tt-build@0.0.13';
6150
+ const PACKAGE_JSON_FILE = 'package.json';
6151
+ const PACK_SCRIPT_FILE = '.cozeproj/scripts/pack.sh';
6152
+ const LEGACY_PACK_SCRIPT_HASHES = new Set([
6153
+ '987575c08e1c32ce7bc553e1668b3ad8faad5623343fd0d21fea34d39f25a56d',
6154
+ '5e1a1a745f165b09717ffa4b83caac19d03e79e42b273cdd5532df58ac08625d',
6155
+ ]);
6156
+ const TARGET_PACK_SCRIPT = `# pack.sh - 通过 PID 文件精确杀掉自己上次的构建进程
6157
+ WEAPP_PID_FILE="/tmp/coze-build_weapp.pid"
6158
+ TT_PID_FILE="/tmp/coze-build_tt.pid"
6159
+
6160
+ cleanup_previous_build() {
6161
+ PID_FILE="$1"
6162
+ BUILD_NAME="$2"
6163
+
6164
+ if [ -f "$PID_FILE" ]; then
6165
+ OLD_PID=$(cat "$PID_FILE")
6166
+ if kill -0 "$OLD_PID" 2>/dev/null; then
6167
+ echo "正在终止上次的 \${BUILD_NAME} 构建进程组 (PID: $OLD_PID)..."
6168
+ # kill 负数 PID = 杀掉整个进程组
6169
+ kill -9 -"$OLD_PID" 2>/dev/null
6170
+ sleep 1
6171
+ fi
6172
+ rm -f "$PID_FILE"
6173
+ fi
6174
+ }
5964
6175
 
6176
+ cleanup_previous_build "$WEAPP_PID_FILE" "weapp"
6177
+ cleanup_previous_build "$TT_PID_FILE" "tt"
5965
6178
 
6179
+ setsid sh -c 'export OUTPUT_ROOT=dist; pnpm build:weapp' &
6180
+ WEAPP_PID=$!
6181
+ echo "$WEAPP_PID" > "$WEAPP_PID_FILE"
5966
6182
 
6183
+ setsid sh -c 'export OUTPUT_ROOT=dist-tt; pnpm build:tt' &
6184
+ TT_PID=$!
6185
+ echo "$TT_PID" > "$TT_PID_FILE"
5967
6186
 
6187
+ echo "构建已并发启动 (weapp PID: $WEAPP_PID, tt PID: $TT_PID)"
5968
6188
 
6189
+ WEAPP_STATUS=0
6190
+ TT_STATUS=0
5969
6191
 
6192
+ wait "$WEAPP_PID" || WEAPP_STATUS=$?
6193
+ wait "$TT_PID" || TT_STATUS=$?
5970
6194
 
5971
- /**
5972
- * 替换 shell 脚本中的 npx 为 pnpm
5973
- */
5974
- const replaceNpxInShellScript = async (
5975
- scriptPath,
5976
- ) => {
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
- }
6014
- }
6195
+ rm -f "$WEAPP_PID_FILE" "$TT_PID_FILE"
6015
6196
 
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
- }
6197
+ if [ "$WEAPP_STATUS" -ne 0 ]; then
6198
+ exit "$WEAPP_STATUS"
6199
+ fi
6023
6200
 
6024
- return { modified: hasChanges, from: fromLines, to: toLines };
6025
- };
6201
+ if [ "$TT_STATUS" -ne 0 ]; then
6202
+ exit "$TT_STATUS"
6203
+ fi
6204
+ `;
6026
6205
 
6027
- /**
6028
- * 替换项目脚本目录中的 npx 为 pnpm
6029
- */
6030
- const replaceNpxWithPnpm = async (
6206
+
6207
+
6208
+
6209
+
6210
+ const getProjectPackScriptPath = (projectFolder) =>
6211
+ path.join(projectFolder, PACK_SCRIPT_FILE);
6212
+
6213
+ const hashContent = (content) =>
6214
+ crypto.createHash('sha256').update(content).digest('hex');
6215
+
6216
+ const readPackageScripts = async (
6031
6217
  projectFolder,
6032
6218
  ) => {
6033
- const scriptsDir = path.join(projectFolder, 'scripts');
6034
- debug$1(`Checking scripts directory: ${scriptsDir}`);
6219
+ const packageJsonPath = path.join(projectFolder, PACKAGE_JSON_FILE);
6220
+ if (!(await isFileExists(packageJsonPath))) {
6221
+ return null;
6222
+ }
6035
6223
 
6036
- const changedFiles = [];
6224
+ const packageJsonContent = await fs$1.readFile(packageJsonPath, 'utf-8');
6225
+ const packageJson = safeJsonParse(packageJsonContent, null);
6037
6226
 
6038
- // 检查 scripts 目录是否存在
6039
- const scriptsDirExists = await isDirExists(scriptsDir);
6040
- debug$1(`Scripts directory exists: ${scriptsDirExists}`);
6227
+ return _optionalChain$3([packageJson, 'optionalAccess', _ => _.scripts]) || null;
6228
+ };
6041
6229
 
6042
- if (!scriptsDirExists) {
6043
- return { modified: false, changedFiles: [] };
6230
+ const hasBuildTtScript = async (projectFolder) => {
6231
+ const scripts = await readPackageScripts(projectFolder);
6232
+ return typeof _optionalChain$3([scripts, 'optionalAccess', _2 => _2['build:tt']]) === 'string';
6233
+ };
6234
+
6235
+ const hasLegacyPackScript = async (projectFolder) => {
6236
+ const packScriptPath = getProjectPackScriptPath(projectFolder);
6237
+ if (!(await isFileExists(packScriptPath))) {
6238
+ return false;
6044
6239
  }
6045
6240
 
6046
- // 处理每个脚本文件
6047
- for (const fileName of SCRIPT_FILES) {
6048
- const scriptPath = path.join(scriptsDir, fileName);
6049
- debug$1(`Checking script file: ${scriptPath}`);
6241
+ const content = await fs$1.readFile(packScriptPath, 'utf-8');
6242
+ return LEGACY_PACK_SCRIPT_HASHES.has(hashContent(content));
6243
+ };
6050
6244
 
6051
- const exists = await isFileExists(scriptPath);
6052
- debug$1(` File exists: ${exists}`);
6245
+ const patchTaroPackScript = {
6246
+ id: PATCH_ID$2,
6247
+ template: 'taro',
6248
+ disabled: byFlag('coding.arch.patch_taro_update_pack_script_for_tt_build'),
6249
+ operations: [
6250
+ {
6251
+ kind: 'file-patch',
6252
+ file: PACK_SCRIPT_FILE,
6253
+ description:
6254
+ 'Update legacy taro pack script to build weapp and tt outputs',
6255
+ },
6256
+ ],
6257
+ shouldApply: async context =>
6258
+ context.template === 'taro' &&
6259
+ (await hasBuildTtScript(context.projectFolder)) &&
6260
+ (await hasLegacyPackScript(context.projectFolder)),
6261
+ apply: async (context) => {
6262
+ if (context.template !== 'taro') {
6263
+ return {
6264
+ applied: false,
6265
+ patchId: PATCH_ID$2,
6266
+ message: 'Only applies to taro projects, skipping',
6267
+ };
6268
+ }
6053
6269
 
6054
- if (!exists) {
6055
- continue;
6270
+ if (!(await hasBuildTtScript(context.projectFolder))) {
6271
+ return {
6272
+ applied: false,
6273
+ patchId: PATCH_ID$2,
6274
+ message: 'package.json does not contain build:tt, skipping',
6275
+ };
6056
6276
  }
6057
6277
 
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
- );
6278
+ if (!(await hasLegacyPackScript(context.projectFolder))) {
6279
+ return {
6280
+ applied: false,
6281
+ patchId: PATCH_ID$2,
6282
+ message: 'pack.sh does not match legacy template hash, skipping',
6283
+ };
6074
6284
  }
6075
- }
6076
6285
 
6077
- debug$1(`Total files modified: ${changedFiles.length}`);
6286
+ const targetPath = getProjectPackScriptPath(context.projectFolder);
6287
+ await fs$1.writeFile(targetPath, TARGET_PACK_SCRIPT, 'utf-8');
6078
6288
 
6079
- return {
6080
- modified: changedFiles.length > 0,
6081
- changedFiles,
6082
- };
6289
+ logger.info(
6290
+ `Patched ${PACK_SCRIPT_FILE}: updated taro multi-target pack script`,
6291
+ );
6292
+
6293
+ return {
6294
+ applied: true,
6295
+ patchId: PATCH_ID$2,
6296
+ message: 'Updated legacy pack.sh to build weapp and tt targets',
6297
+ };
6298
+ },
6083
6299
  };
6084
6300
 
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';
6301
+ const PATCH_ID$1 = 'taro/add-agents-md@0.0.13';
6302
+ const AGENTS_FILE = 'AGENTS.md';
6303
+ const getTemplateAgentsPath = () =>
6304
+ path.join(getTemplatesDir(), 'taro', AGENTS_FILE);
6093
6305
 
6094
- debug$1(`Starting fix rule: ${ruleName}`);
6095
- debug$1(`Project folder: ${context.projectFolder}`);
6306
+ const getProjectAgentsPath = (projectFolder) =>
6307
+ path.join(projectFolder, AGENTS_FILE);
6096
6308
 
6097
- // 1. 检测项目类型
6098
- const projectDetection = await detectProjectType(context.projectFolder);
6099
- debug$1(`Project detection result: ${JSON.stringify(projectDetection)}`);
6309
+ const readTemplateAgentsContent = async () =>
6310
+ fs$1.readFile(getTemplateAgentsPath(), 'utf-8');
6100
6311
 
6101
- if (!projectDetection.detected) {
6102
- return {
6103
- ruleName,
6104
- applied: false,
6105
- message: 'Project type not detected, skipping',
6106
- };
6107
- }
6312
+ const patchTaroAgentsMd = {
6313
+ id: PATCH_ID$1,
6314
+ template: 'taro',
6315
+ disabled: byFlag('coding.arch.patch_taro_add_agents_md'),
6316
+ operations: [
6317
+ {
6318
+ kind: 'create-file',
6319
+ file: AGENTS_FILE,
6320
+ description:
6321
+ 'Add template AGENTS.md to taro projects that do not have one',
6322
+ },
6323
+ ],
6324
+ shouldApply: async context =>
6325
+ context.template === 'taro' &&
6326
+ !(await isFileExists(getProjectAgentsPath(context.projectFolder))),
6327
+ apply: async (context) => {
6328
+ if (context.template !== 'taro') {
6329
+ return {
6330
+ applied: false,
6331
+ patchId: PATCH_ID$1,
6332
+ message: 'Only applies to taro projects, skipping',
6333
+ };
6334
+ }
6108
6335
 
6109
- // 2. 检查是否为支持的项目类型
6110
- const isSupportedType = (
6111
- SUPPORTED_PROJECT_TYPES
6112
- ).includes(projectDetection.type);
6336
+ const targetPath = getProjectAgentsPath(context.projectFolder);
6337
+ if (await isFileExists(targetPath)) {
6338
+ return {
6339
+ applied: false,
6340
+ patchId: PATCH_ID$1,
6341
+ message: 'AGENTS.md already exists, skipping',
6342
+ };
6343
+ }
6113
6344
 
6114
- debug$1(`Is supported type: ${isSupportedType}`);
6115
- debug$1(`Supported types: ${SUPPORTED_PROJECT_TYPES.join(', ')}`);
6345
+ const templateContent = await readTemplateAgentsContent();
6346
+ await fs$1.writeFile(targetPath, templateContent, 'utf-8');
6116
6347
 
6117
- if (!isSupportedType) {
6118
6348
  return {
6119
- ruleName,
6120
- applied: false,
6121
- message: 'Project type not supported for this fix, skipping',
6349
+ applied: true,
6350
+ patchId: PATCH_ID$1,
6351
+ message: 'Created AGENTS.md from taro template',
6122
6352
  };
6353
+ },
6354
+ };
6355
+
6356
+ const SCRIPT_FILES = ['dev.sh', 'build.sh'] ;
6357
+ const SUPPORTED_TEMPLATES = new Set(['nextjs', 'vite', 'nuxt-vue']);
6358
+
6359
+ const hasNpxInScripts = async (projectFolder) => {
6360
+ const scriptsDir = path.join(projectFolder, 'scripts');
6361
+ if (!(await isDirExists(scriptsDir))) {
6362
+ return false;
6123
6363
  }
6124
6364
 
6125
- logger.info(`Detected ${projectDetection.type} project`);
6365
+ for (const fileName of SCRIPT_FILES) {
6366
+ const scriptPath = path.join(scriptsDir, fileName);
6367
+ if (!(await isFileExists(scriptPath))) {
6368
+ continue;
6369
+ }
6370
+
6371
+ const content = await fs$1.readFile(scriptPath, 'utf-8');
6372
+ if (/\bnpx\s+/.test(content)) {
6373
+ return true;
6374
+ }
6375
+ }
6126
6376
 
6127
- // 3. 执行替换
6128
- debug$1('Starting npx replacement...');
6129
- const replaceResult = await replaceNpxWithPnpm(context.projectFolder);
6377
+ return false;
6378
+ };
6130
6379
 
6131
- if (!replaceResult.modified) {
6380
+ const applyReplaceNpxWithPnpm = async (
6381
+ context,
6382
+ patchId,
6383
+ ) => {
6384
+ const scriptsDir = path.join(context.projectFolder, 'scripts');
6385
+ let changedFiles = 0;
6386
+
6387
+ if (!(await isDirExists(scriptsDir))) {
6132
6388
  return {
6133
- ruleName,
6134
6389
  applied: false,
6135
- message: 'No npx commands found in shell scripts, skipping',
6390
+ patchId,
6391
+ message: 'scripts directory not found, skipping',
6136
6392
  };
6137
6393
  }
6138
6394
 
6139
- // 4. 输出修改信息
6140
- logger.success(
6141
- `Replaced npx with pnpm in ${replaceResult.changedFiles.length} file(s)`,
6142
- );
6395
+ for (const fileName of SCRIPT_FILES) {
6396
+ const scriptPath = path.join(scriptsDir, fileName);
6397
+ if (!(await isFileExists(scriptPath))) {
6398
+ continue;
6399
+ }
6143
6400
 
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]}`);
6401
+ const content = await fs$1.readFile(scriptPath, 'utf-8');
6402
+ const nextContent = content.replace(/\bnpx\s+/g, 'pnpm ');
6403
+ if (nextContent === content) {
6404
+ continue;
6149
6405
  }
6406
+
6407
+ await fs$1.writeFile(scriptPath, nextContent, 'utf-8');
6408
+ changedFiles++;
6409
+ logger.info(`Patched scripts/${fileName}: replaced npx with pnpm`);
6150
6410
  }
6151
6411
 
6152
6412
  return {
6153
- ruleName,
6154
- applied: true,
6155
- message: `Successfully replaced npx with pnpm in ${replaceResult.changedFiles.length} file(s)`,
6413
+ applied: changedFiles > 0,
6414
+ patchId,
6415
+ message:
6416
+ changedFiles > 0
6417
+ ? `Replaced npx with pnpm in ${changedFiles} file(s)`
6418
+ : 'No npx commands found in shell scripts, skipping',
6156
6419
  };
6157
6420
  };
6158
6421
 
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
6161
-
6422
+ const createReplaceNpxWithPnpmPatch = (
6423
+ template,
6424
+ ) => ({
6425
+ id: `${template}/replace-npx-with-pnpm@0.0.13`,
6426
+ template,
6427
+ disabled: byFlag(
6428
+ template === 'nextjs'
6429
+ ? 'coding.arch.patch_nextjs_replace_npx_with_pnpm'
6430
+ : template === 'vite'
6431
+ ? 'coding.arch.patch_vite_replace_npx_with_pnpm'
6432
+ : 'coding.arch.patch_nuxt_vue_replace_npx_with_pnpm',
6433
+ ),
6434
+ operations: [
6435
+ {
6436
+ kind: 'file-patch',
6437
+ file: 'scripts/dev.sh',
6438
+ description: 'Replace npx with pnpm in shell scripts',
6439
+ },
6440
+ {
6441
+ kind: 'file-patch',
6442
+ file: 'scripts/build.sh',
6443
+ description: 'Replace npx with pnpm in shell scripts',
6444
+ },
6445
+ ],
6446
+ shouldApply: async context =>
6447
+ SUPPORTED_TEMPLATES.has(context.template) &&
6448
+ (await hasNpxInScripts(context.projectFolder)),
6449
+ apply: async context =>
6450
+ applyReplaceNpxWithPnpm(
6451
+ context,
6452
+ `${template}/replace-npx-with-pnpm@0.0.13`,
6453
+ ),
6454
+ });
6162
6455
 
6163
- /**
6164
- * 检查是否为 Next.js 项目
6165
- */
6166
- const isNextProject = async (projectFolder) =>
6167
- isProjectType(projectFolder, ProjectType.NEXTJS);
6456
+ const replaceNpxWithPnpmPatchNextjs =
6457
+ createReplaceNpxWithPnpmPatch('nextjs');
6458
+ const replaceNpxWithPnpmPatchVite =
6459
+ createReplaceNpxWithPnpmPatch('vite');
6460
+ const replaceNpxWithPnpmPatchNuxtVue =
6461
+ createReplaceNpxWithPnpmPatch('nuxt-vue');
6168
6462
 
6169
- /**
6170
- * 查找 Next.js 配置文件
6171
- */
6172
6463
  const findNextConfigFile = async (
6173
6464
  projectFolder,
6174
6465
  ) => {
@@ -6188,222 +6479,351 @@ const findNextConfigFile = async (
6188
6479
  return null;
6189
6480
  };
6190
6481
 
6191
- /**
6192
- * 注释掉 outputFileTracingRoot 配置
6193
- */
6194
- const commentOutOutputTracingRoot = async (
6482
+ const getUncommentedTracingRootLine = async (
6195
6483
  configPath,
6196
6484
  ) => {
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
- // 只匹配单行配置,不匹配跨多行的配置
6485
+ const content = await fs$1.readFile(configPath, 'utf-8');
6204
6486
  const pattern =
6205
6487
  /^(\s*)(outputFileTracingRoot:\s*path\.resolve\([^\n\r)]+\)\s*,?)\s*$/gm;
6206
6488
 
6207
6489
  const matches = content.match(pattern);
6490
+ return matches && matches.length > 0 ? matches[0].trim() : null;
6491
+ };
6208
6492
 
6209
- if (matches && matches.length > 0) {
6210
- originalLine = matches[0].trim();
6211
-
6212
- // 在匹配的行前添加 // 注释
6213
- content = content.replace(pattern, '$1// $2');
6214
- modified = true;
6493
+ const commentOutOutputTracingRoot = async (
6494
+ configPath,
6495
+ ) => {
6496
+ const content = await fs$1.readFile(configPath, 'utf-8');
6497
+ const pattern =
6498
+ /^(\s*)(outputFileTracingRoot:\s*path\.resolve\([^\n\r)]+\)\s*,?)\s*$/gm;
6499
+ const matches = content.match(pattern);
6215
6500
 
6216
- await fs$1.writeFile(configPath, content, 'utf-8');
6501
+ if (!matches || matches.length === 0) {
6502
+ return null;
6217
6503
  }
6218
6504
 
6219
- return { modified, originalLine };
6505
+ const originalLine = matches[0].trim();
6506
+ const nextContent = content.replace(pattern, '$1// $2');
6507
+ await fs$1.writeFile(configPath, nextContent, 'utf-8');
6508
+ return originalLine;
6220
6509
  };
6221
6510
 
6222
- /**
6223
- * Fix 规则:注释掉 Next.js 项目中的 outputFileTracingRoot 配置
6224
- * 这个配置在 monorepo 环境中可能会导致问题
6225
- */
6226
- const fixNextOutputTracingRoot = async context => {
6227
- const ruleName = 'next-output-tracing-root';
6511
+ const PATCH_ID = 'nextjs/next-output-tracing-root@0.0.13';
6228
6512
 
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
- }
6513
+ const patchNextOutputTracingRoot = {
6514
+ id: PATCH_ID,
6515
+ template: 'nextjs',
6516
+ disabled: byFlag('coding.arch.patch_nextjs_next_output_tracing_root'),
6517
+ operations: [
6518
+ {
6519
+ kind: 'file-patch',
6520
+ file: 'next.config.ts',
6521
+ description: 'Comment out problematic outputFileTracingRoot config',
6522
+ },
6523
+ ],
6524
+ shouldApply: async context => {
6525
+ if (context.template !== 'nextjs') {
6526
+ return false;
6527
+ }
6237
6528
 
6238
- // 2. 查找 Next.js 配置文件
6239
- const configPath = await findNextConfigFile(context.projectFolder);
6529
+ const configPath = await findNextConfigFile(context.projectFolder);
6530
+ if (!configPath) {
6531
+ return false;
6532
+ }
6240
6533
 
6241
- if (!configPath) {
6242
- return {
6243
- ruleName,
6244
- applied: false,
6245
- message: 'Next.js config file not found, skipping',
6246
- };
6247
- }
6534
+ return (await getUncommentedTracingRootLine(configPath)) !== null;
6535
+ },
6536
+ apply: async (context) => {
6537
+ const configPath = await findNextConfigFile(context.projectFolder);
6538
+ if (!configPath) {
6539
+ return {
6540
+ applied: false,
6541
+ patchId: PATCH_ID,
6542
+ message: 'Next.js config file not found, skipping',
6543
+ };
6544
+ }
6248
6545
 
6249
- // 3. 注释掉 outputFileTracingRoot 配置
6250
- const { modified, originalLine } =
6251
- await commentOutOutputTracingRoot(configPath);
6546
+ const originalLine = await commentOutOutputTracingRoot(configPath);
6547
+ if (!originalLine) {
6548
+ return {
6549
+ applied: false,
6550
+ patchId: PATCH_ID,
6551
+ message: 'No outputFileTracingRoot config found, skipping',
6552
+ };
6553
+ }
6252
6554
 
6253
- if (modified && originalLine) {
6254
- logger.success(
6255
- `Commented out outputFileTracingRoot in ${configPath.split('/').pop()}`,
6555
+ logger.info(
6556
+ `Patched ${configPath.split('/').pop()}: commented out ${originalLine}`,
6256
6557
  );
6257
- logger.info(` Original: ${originalLine}`);
6258
6558
 
6259
6559
  return {
6260
- ruleName,
6261
6560
  applied: true,
6561
+ patchId: PATCH_ID,
6262
6562
  message: `Successfully commented out: ${originalLine}`,
6263
6563
  };
6264
- }
6265
-
6266
- return {
6267
- ruleName,
6268
- applied: false,
6269
- message: 'No outputFileTracingRoot config found, skipping',
6270
- };
6564
+ },
6271
6565
  };
6272
6566
 
6273
- /**
6274
- * 所有修复规则的数组
6275
- * 按顺序执行,新增规则直接添加到数组中
6276
- */
6277
- const rules = [
6278
- // Package manager fixes (should run first)
6279
- fixReplaceNpxWithPnpm,
6567
+ const patches = [
6568
+ replaceNpxWithPnpmPatchNextjs,
6569
+ replaceNpxWithPnpmPatchVite,
6570
+ replaceNpxWithPnpmPatchNuxtVue,
6571
+ patchNextOutputTracingRoot,
6572
+ patchTaroAgentsMd,
6573
+ patchTaroPackScript,
6574
+ ] ;
6280
6575
 
6281
- // Next.js related fixes
6282
- fixNextOutputTracingRoot,
6576
+ const getTemplatePatches = (
6577
+ template,
6578
+ ) =>
6579
+ patches.filter(patch => patch.template === template);
6283
6580
 
6284
- // Add more rules here
6285
- ] ;
6581
+ 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; }
6582
+ const DEFAULT_LEGACY_VERSION = 'legacy';
6286
6583
 
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
6584
+ const loadFlagsWithFallback = async () => {
6585
+ try {
6586
+ return await loadPatchFlags();
6587
+ } catch (error) {
6588
+ logger.warn(
6589
+ `Patch skipped: failed to load feature gates (${
6590
+ error instanceof Error ? error.message : String(error)
6591
+ })`,
6592
+ );
6593
+ return {};
6594
+ }
6595
+ };
6596
+
6597
+ const isPatchDisabled = (
6598
+ patch,
6599
+ context,
6600
+ ) =>
6601
+ typeof patch.disabled === 'function'
6602
+ ? patch.disabled(context)
6603
+ : patch.disabled === true;
6604
+
6605
+ const getPatchFlag = (patch) =>
6606
+ typeof patch.disabled === 'function' &&
6607
+ 'flag' in patch.disabled &&
6608
+ typeof (patch.disabled ).flag === 'string'
6609
+ ? (patch.disabled ).flag
6610
+ : null;
6611
+
6612
+ const showFlags = (
6613
+ template,
6614
+ flags,
6615
+ context,
6616
+ ) => {
6617
+ logger.info('Feature gates:');
6618
+ logger.info(
6619
+ ` ${PATCH_CLI_FLAG} = ${isFlagEnabled(flags, PATCH_CLI_FLAG) ? 'true' : 'false'}`,
6620
+ );
6289
6621
 
6622
+ const templatePatches = getTemplatePatches(template);
6623
+ if (templatePatches.length === 0) {
6624
+ logger.info(`No registered patches for template: ${template}`);
6625
+ return;
6626
+ }
6290
6627
 
6291
- const debug = debug$2('coze-init:fix');
6628
+ logger.info('Patch gates:');
6629
+ templatePatches.forEach(patch => {
6630
+ const flag = getPatchFlag(patch);
6631
+ if (!flag) {
6632
+ logger.info(` - ${patch.id}`);
6633
+ logger.info(' gate: (none)');
6634
+ return;
6635
+ }
6292
6636
 
6293
- const JSON_INDENT_SPACES = 2;
6637
+ const enabled = context.isFlagEnabled(flag);
6638
+ logger.info(` - ${patch.id}`);
6639
+ logger.info(` flag: ${flag}`);
6640
+ logger.info(` value: ${enabled ? 'true' : 'false'}`);
6641
+ logger.info(` status: ${enabled ? 'enabled' : 'disabled by flag'}`);
6642
+ });
6643
+ };
6294
6644
 
6295
- // start_aigc
6296
- /**
6297
- * 执行 fix 命令的内部实现
6298
- */
6299
- const executeFix = async (
6300
- options = {},
6645
+ const loadExistingTomlConfig = async (
6646
+ projectFolder,
6301
6647
  ) => {
6302
6648
  try {
6303
- const cwd = process.cwd();
6304
- const projectFolder = options.directory
6305
- ? path.resolve(cwd, options.directory)
6306
- : cwd;
6649
+ await fs$1.access(path.resolve(projectFolder, '.coze'));
6650
+ } catch (e) {
6651
+ return null;
6652
+ }
6307
6653
 
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`);
6654
+ return loadTomlCozeConfig(projectFolder);
6655
+ };
6311
6656
 
6312
- const context = {
6313
- cwd,
6314
- projectFolder,
6315
- };
6657
+ const writePatchState = async (
6658
+ projectFolder,
6659
+ config,
6660
+ state
6316
6661
 
6317
- debug(
6318
- `Fix context: ${JSON.stringify(context, null, JSON_INDENT_SPACES)}\n`,
6319
- );
6320
6662
 
6321
- let appliedCount = 0;
6322
- let skippedCount = 0;
6323
- let errorCount = 0;
6324
6663
 
6325
- // 依次执行所有修复规则
6326
- for (let i = 0; i < rules.length; i++) {
6327
- const rule = rules[i];
6328
- const ruleNumber = i + 1;
6664
+ ,
6665
+ ) => {
6666
+ config.project = {
6667
+ ...(config.project || {}),
6668
+ template: state.template,
6669
+ version: state.version,
6670
+ appliedPatches: state.appliedPatches,
6671
+ };
6329
6672
 
6330
- try {
6331
- debug(`[${ruleNumber}/${rules.length}] Starting rule execution...`);
6673
+ await saveTomlCozeConfig(config, projectFolder);
6674
+ };
6332
6675
 
6333
- const startTime = Date.now();
6334
- const result = await Promise.resolve(rule(context));
6335
- const duration = Date.now() - startTime;
6676
+ const getNextPatchState = (
6677
+ config,
6678
+ template,
6679
+ appliedPatches,
6680
+ patchId,
6336
6681
 
6337
- debug(`Rule execution completed in ${duration}ms`);
6338
- debug(`Result: ${JSON.stringify(result, null, JSON_INDENT_SPACES)}`);
6339
6682
 
6340
- if (result.applied) {
6341
- appliedCount++;
6342
- logger.success(`✓ ${result.ruleName}: ${result.message}`);
6343
- } else {
6344
- skippedCount++;
6345
- logger.info(`○ ${result.ruleName}: ${result.message}`);
6346
- }
6347
6683
 
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
6684
 
6355
- // 输出详细的错误堆栈信息(仅在 debug 模式下)
6356
- if (error instanceof Error && error.stack) {
6357
- debug(`Error stack trace:\n${error.stack}`);
6358
- }
6685
+ ) => ({
6686
+ template,
6687
+ version: _optionalChain$2([config, 'access', _ => _.project, 'optionalAccess', _2 => _2.version]) || DEFAULT_LEGACY_VERSION,
6688
+ appliedPatches: [...appliedPatches, patchId],
6689
+ });
6359
6690
 
6360
- debug(''); // Empty line for readability
6361
- }
6362
- }
6691
+ const executePatch = async (
6692
+ options = {},
6693
+ ) => {
6694
+ const cwd = process.cwd();
6695
+ const projectFolder = options.directory
6696
+ ? path.resolve(cwd, options.directory)
6697
+ : cwd;
6363
6698
 
6364
- // 输出汇总信息
6365
- debug('\n=== Fix Command Summary ===');
6366
- logger.info(
6367
- `\nSummary: ${appliedCount} fixed, ${skippedCount} skipped, ${errorCount} errors, ${rules.length} total`,
6368
- );
6699
+ if (await isDirectoryEmpty(projectFolder)) {
6700
+ logger.info(`Patch skipped: ${projectFolder} is empty`);
6701
+ return;
6702
+ }
6369
6703
 
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');
6704
+ const config = await loadExistingTomlConfig(projectFolder);
6705
+ if (!config) {
6706
+ logger.info('Patch skipped: .coze file not found');
6707
+ return;
6708
+ }
6709
+
6710
+ const template =
6711
+ _optionalChain$2([config, 'access', _3 => _3.project, 'optionalAccess', _4 => _4.template]) || (await detectTemplateKey(projectFolder));
6712
+
6713
+ if (!template) {
6714
+ logger.info('Patch skipped: template not detected');
6715
+ return;
6716
+ }
6717
+
6718
+ const appliedPatches = [...(_optionalChain$2([config, 'access', _5 => _5.project, 'optionalAccess', _6 => _6.appliedPatches]) || [])];
6719
+ const projectVersion = _optionalChain$2([config, 'access', _7 => _7.project, 'optionalAccess', _8 => _8.version]);
6720
+ const flags = await loadFlagsWithFallback();
6721
+
6722
+ const context = {
6723
+ cwd,
6724
+ projectFolder,
6725
+ template,
6726
+ projectVersion,
6727
+ appliedPatches,
6728
+ cozeConfig: config,
6729
+ flags,
6730
+ isFlagEnabled: flag => isFlagEnabled(flags, flag),
6731
+ };
6732
+
6733
+ if (options.showFlags) {
6734
+ showFlags(template, flags, context);
6735
+ return;
6736
+ }
6737
+
6738
+ if (!context.isFlagEnabled(PATCH_CLI_FLAG)) {
6739
+ logger.info(`Patch skipped: feature gate ${PATCH_CLI_FLAG} is disabled`);
6740
+ return;
6741
+ }
6742
+
6743
+ const candidatePatches = getTemplatePatches(template).filter(patch => {
6744
+ if (isPatchDisabled(patch, context)) {
6745
+ return false;
6376
6746
  }
6377
- } catch (error) {
6378
- logger.error('Failed to run fix command:');
6379
- logger.error(error instanceof Error ? error.message : String(error));
6747
+ return !appliedPatches.includes(patch.id);
6748
+ });
6380
6749
 
6381
- // 输出详细的错误信息
6382
- if (error instanceof Error && error.stack) {
6383
- debug(`Error stack trace:\n${error.stack}`);
6750
+ const matchedPatches = [];
6751
+ for (const patch of candidatePatches) {
6752
+ if (await patch.shouldApply(context)) {
6753
+ matchedPatches.push(patch);
6384
6754
  }
6755
+ }
6385
6756
 
6386
- process.exit(1);
6757
+ if (matchedPatches.length === 0) {
6758
+ logger.info('No patch matched current project state');
6759
+ return;
6760
+ }
6761
+
6762
+ if (options.dryRun) {
6763
+ logger.info(`Detected template: ${template}`);
6764
+ logger.info(`Current version: ${_nullishCoalesce$2(projectVersion, () => ( DEFAULT_LEGACY_VERSION))}`);
6765
+ logger.info(`Applied patches: ${appliedPatches.join(', ') || '(none)'}`);
6766
+ logger.info('Matched patches:');
6767
+ matchedPatches.forEach(patch => {
6768
+ logger.info(` - ${patch.id}`);
6769
+ patch.operations.forEach(operation => {
6770
+ if ('file' in operation) {
6771
+ logger.info(
6772
+ ` ${operation.kind}: ${operation.file} - ${operation.description}`,
6773
+ );
6774
+ } else {
6775
+ logger.info(` ${operation.kind}: ${operation.description}`);
6776
+ }
6777
+ });
6778
+ });
6779
+ return;
6780
+ }
6781
+
6782
+ for (const patch of matchedPatches) {
6783
+ const result = await patch.apply({
6784
+ ...context,
6785
+ appliedPatches,
6786
+ });
6787
+
6788
+ if (!result.applied) {
6789
+ logger.info(`○ ${patch.id}: ${result.message}`);
6790
+ continue;
6791
+ }
6792
+
6793
+ const nextState = getNextPatchState(
6794
+ config,
6795
+ template,
6796
+ appliedPatches,
6797
+ patch.id,
6798
+ );
6799
+ await writePatchState(projectFolder, config, nextState);
6800
+ appliedPatches.push(patch.id);
6801
+ logger.success(`✓ ${patch.id}: ${result.message}`);
6387
6802
  }
6388
6803
  };
6389
- // end_aigc
6390
6804
 
6391
- /**
6392
- * 注册 fix 命令到 program
6393
- */
6394
6805
  const registerCommand$3 = program => {
6395
6806
  program
6396
- .command('fix')
6397
- .description(
6398
- 'Fix legacy issues from previous versions (e.g., problematic configs)',
6399
- )
6807
+ .command('patch')
6808
+ .description('Apply template patches for existing projects')
6400
6809
  .argument(
6401
6810
  '[directory]',
6402
- 'Target directory to fix (defaults to current directory)',
6811
+ 'Target directory to patch (defaults to current directory)',
6403
6812
  )
6404
- .action(async (directory) => {
6405
- await executeFix({ directory });
6406
- });
6813
+ .option('--dry-run', 'Show matched patches without modifying files')
6814
+ .option('--show-flags', 'Show feature gate status for this template')
6815
+ .action(
6816
+ async (
6817
+ directory,
6818
+ command,
6819
+ ) => {
6820
+ await executePatch({
6821
+ directory,
6822
+ dryRun: _optionalChain$2([command, 'optionalAccess', _9 => _9.dryRun]),
6823
+ showFlags: _optionalChain$2([command, 'optionalAccess', _10 => _10.showFlags]),
6824
+ });
6825
+ },
6826
+ );
6407
6827
  };
6408
6828
 
6409
6829
  function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$1(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; }
@@ -6500,12 +6920,12 @@ const executeRun = async (
6500
6920
  // 上报命令开始
6501
6921
  reportCommandStart(commandName, JSON.stringify(options), { projectType });
6502
6922
 
6503
- // 1. 对于 build 命令,先执行 fix 以确保项目配置正确
6923
+ // 1. 对于 build/dev 命令,先执行 patch 以确保项目配置正确
6504
6924
  if (['dev', 'build'].includes(commandName)) {
6505
- logger.info('\n🔧 Running fix command before build...\n');
6925
+ logger.info('\n🔧 Running patch command before execution...\n');
6506
6926
  const fixStartTime = Date.now();
6507
6927
  try {
6508
- await executeFix();
6928
+ await executePatch();
6509
6929
  // eslint-disable-next-line @coze-arch/no-empty-catch, @coze-arch/use-error-in-catch -- intentionally ignored
6510
6930
  } catch (_e) {
6511
6931
  // fix errors are intentionally ignored to allow the main command to proceed
@@ -6688,7 +7108,7 @@ const registerCommand$2 = program => {
6688
7108
 
6689
7109
 
6690
7110
 
6691
- const log$4 = debug$2('coze:routes:nuxt');
7111
+ const log$4 = debug('coze:routes:nuxt');
6692
7112
 
6693
7113
  /**
6694
7114
  * Convert Nuxt file path to route path
@@ -6928,7 +7348,7 @@ const scanNuxtRoutes = async (cwd) => {
6928
7348
 
6929
7349
 
6930
7350
 
6931
- const log$3 = debug$2('coze:routes:nextjs');
7351
+ const log$3 = debug('coze:routes:nextjs');
6932
7352
 
6933
7353
  /**
6934
7354
  * Convert Next.js file path to route path
@@ -7269,7 +7689,7 @@ const getOutputFilePath = (cwd, outputPath) =>
7269
7689
 
7270
7690
 
7271
7691
 
7272
- const log$2 = debug$2('coze:routes:detect');
7692
+ const log$2 = debug('coze:routes:detect');
7273
7693
 
7274
7694
  /**
7275
7695
  * Check if any of the specified files exist
@@ -7374,7 +7794,7 @@ const detectTemplate = (cwd) => {
7374
7794
  // ABOUTME: Orchestrates template detection, route scanning, and polling-based updates
7375
7795
 
7376
7796
 
7377
- const log$1 = debug$2('coze:routes:scanner');
7797
+ const log$1 = debug('coze:routes:scanner');
7378
7798
 
7379
7799
  /**
7380
7800
  * Scan routes based on template type
@@ -7475,7 +7895,7 @@ const scanRoutesOnce = async (
7475
7895
  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
7896
 
7477
7897
 
7478
- const log = debug$2('coze:routes');
7898
+ const log = debug('coze:routes');
7479
7899
 
7480
7900
  /**
7481
7901
  * Execute routes command implementation
@@ -8631,7 +9051,22 @@ const executeTemplateEngineStep = async ctx => {
8631
9051
  };
8632
9052
 
8633
9053
  /**
8634
- * 步骤2: 检查 package.json 是否存在
9054
+ * 步骤2: 写入 patch 项目元数据
9055
+ */
9056
+ const writePatchMetadataStep = async ctx => {
9057
+ if (!ctx.absoluteOutputPath) {
9058
+ return;
9059
+ }
9060
+
9061
+ await saveProjectPatchState(ctx.absoluteOutputPath, {
9062
+ template: ctx.templateName,
9063
+ version: packageJson.version,
9064
+ appliedPatches: [],
9065
+ });
9066
+ };
9067
+
9068
+ /**
9069
+ * 步骤3: 检查 package.json 是否存在
8635
9070
  */
8636
9071
  const checkPackageJsonStep = ctx => {
8637
9072
  if (!ctx.absoluteOutputPath) {
@@ -8643,7 +9078,7 @@ const checkPackageJsonStep = ctx => {
8643
9078
  };
8644
9079
 
8645
9080
  /**
8646
- * 步骤3: 安装依赖
9081
+ * 步骤4: 安装依赖
8647
9082
  */
8648
9083
  const installDependenciesStep = ctx => {
8649
9084
  if (!ctx.absoluteOutputPath) {
@@ -8691,7 +9126,7 @@ const installDependenciesStep = ctx => {
8691
9126
  };
8692
9127
 
8693
9128
  /**
8694
- * 步骤4: 执行完成钩子
9129
+ * 步骤5: 执行完成钩子
8695
9130
  */
8696
9131
  const executeCompleteHookStep = async ctx => {
8697
9132
  if (!ctx.absoluteOutputPath || !ctx.templateConfig || !ctx.context) {
@@ -8708,7 +9143,7 @@ const executeCompleteHookStep = async ctx => {
8708
9143
  };
8709
9144
 
8710
9145
  /**
8711
- * 步骤5: 初始化 Git 仓库
9146
+ * 步骤6: 初始化 Git 仓库
8712
9147
  */
8713
9148
  const gitInitStep = ctx => {
8714
9149
  if (!ctx.absoluteOutputPath) {
@@ -8724,7 +9159,7 @@ const gitInitStep = ctx => {
8724
9159
  };
8725
9160
 
8726
9161
  /**
8727
- * 步骤6: 提交 Git 变更
9162
+ * 步骤7: 提交 Git 变更
8728
9163
  */
8729
9164
  const gitCommitStep = ctx => {
8730
9165
  if (!ctx.absoluteOutputPath) {
@@ -8740,7 +9175,7 @@ const gitCommitStep = ctx => {
8740
9175
  };
8741
9176
 
8742
9177
  /**
8743
- * 步骤7: 启动开发服务器
9178
+ * 步骤8: 启动开发服务器
8744
9179
  */
8745
9180
  const startDevServerStep = ctx => {
8746
9181
  if (!ctx.absoluteOutputPath) {
@@ -8774,6 +9209,7 @@ const startDevServerStep = ctx => {
8774
9209
  */
8775
9210
  const initSteps = [
8776
9211
  executeTemplateEngineStep,
9212
+ writePatchMetadataStep,
8777
9213
  checkPackageJsonStep,
8778
9214
  installDependenciesStep,
8779
9215
  executeCompleteHookStep,