@coze-arch/cli 0.0.35 → 0.0.36-alpha.844e20

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.
Files changed (58) hide show
  1. package/README.md +11 -0
  2. package/docs/deploy.md +168 -0
  3. package/lib/__templates__/phaser/.coze +13 -0
  4. package/lib/__templates__/phaser/README.md +37 -0
  5. package/lib/__templates__/phaser/_gitignore +22 -0
  6. package/lib/__templates__/phaser/_npmrc +14 -0
  7. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  8. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  9. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  10. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  11. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  12. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  13. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  14. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  15. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  16. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  17. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  18. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  19. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  20. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  21. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  22. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  23. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  24. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  25. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  26. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  27. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  28. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  29. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  30. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  31. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/manifest.json +11 -0
  32. package/lib/__templates__/phaser/debug-runtime/flow-graph.json +20 -0
  33. package/lib/__templates__/phaser/index.html +12 -0
  34. package/lib/__templates__/phaser/package.json +31 -0
  35. package/lib/__templates__/phaser/pnpm-lock.yaml +661 -0
  36. package/lib/__templates__/phaser/scripts/build.sh +8 -0
  37. package/lib/__templates__/phaser/scripts/dev.sh +11 -0
  38. package/lib/__templates__/phaser/scripts/prepare.sh +7 -0
  39. package/lib/__templates__/phaser/scripts/start.sh +11 -0
  40. package/lib/__templates__/phaser/scripts/validate.sh +7 -0
  41. package/lib/__templates__/phaser/src/assets.ts +15 -0
  42. package/lib/__templates__/phaser/src/global.d.ts +36 -0
  43. package/lib/__templates__/phaser/src/main.ts +28 -0
  44. package/lib/__templates__/phaser/src/scene/BootScene.ts +209 -0
  45. package/lib/__templates__/phaser/src/scene/DevLoadingScene.ts +66 -0
  46. package/lib/__templates__/phaser/src/style.css +28 -0
  47. package/lib/__templates__/phaser/src/types.ts +32 -0
  48. package/lib/__templates__/phaser/src/utils/asset-loader.ts +319 -0
  49. package/lib/__templates__/phaser/src/utils/index.ts +2 -0
  50. package/lib/__templates__/phaser/src/utils/mark-editable.ts +6 -0
  51. package/lib/__templates__/phaser/template.config.js +43 -0
  52. package/lib/__templates__/phaser/tsconfig.json +23 -0
  53. package/lib/__templates__/phaser/vite.config.ts +96 -0
  54. package/lib/__templates__/templates.json +25 -0
  55. package/lib/cli.js +3335 -196
  56. package/lib/deploy/package-project.js +220 -0
  57. package/lib/deploy/package-project.py +165 -0
  58. package/package.json +5 -4
package/lib/cli.js CHANGED
@@ -14,7 +14,7 @@ var perf_hooks = require('perf_hooks');
14
14
  var fs$1 = require('fs/promises');
15
15
  var os = require('os');
16
16
  var jsYaml = require('js-yaml');
17
- var toml = require('@iarna/toml');
17
+ var TOML = require('@iarna/toml');
18
18
  var crypto = require('crypto');
19
19
  var fastGlob = require('fast-glob');
20
20
  var child_process = require('child_process');
@@ -23,6 +23,12 @@ var Ajv = require('ajv');
23
23
  var minimist = require('minimist');
24
24
  var changeCase = require('change-case');
25
25
  var ejs = require('ejs');
26
+ var node_crypto = require('node:crypto');
27
+ var node_os = require('node:os');
28
+ var promises = require('node:fs/promises');
29
+ var node_child_process = require('node:child_process');
30
+ var node_util = require('node:util');
31
+ var node_stream = require('node:stream');
26
32
 
27
33
  /**
28
34
  * 读取 templates.json 配置
@@ -1628,7 +1634,7 @@ function createNodeTransport() {
1628
1634
  };
1629
1635
  }
1630
1636
 
1631
- function _nullishCoalesce$a(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$t(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; }/**
1637
+ function _nullishCoalesce$d(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }/**
1632
1638
  * Slardar CLI Reporter 主类
1633
1639
  * 封装 @slardar/base 的初始化和上报逻辑
1634
1640
  */
@@ -1685,7 +1691,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1685
1691
  release: config.release,
1686
1692
  env: config.env,
1687
1693
  name: config.name,
1688
- useLocalConfig: _nullishCoalesce$a(config.useLocalConfig, () => ( false)), // 默认使用服务端配置
1694
+ useLocalConfig: _nullishCoalesce$d(config.useLocalConfig, () => ( false)), // 默认使用服务端配置
1689
1695
  domain: config.domain,
1690
1696
  // 设置本地采样率为 100%,确保事件不被过滤
1691
1697
  sample: {
@@ -1700,7 +1706,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1700
1706
  this.client.on('send', (ev) => {
1701
1707
  log$6(
1702
1708
  'send hook called for event: %s',
1703
- (_optionalChain$t([ev, 'optionalAccess', _ => _.ev_type]) ) || 'unknown',
1709
+ (_optionalChain$E([ev, 'optionalAccess', _ => _.ev_type]) ) || 'unknown',
1704
1710
  );
1705
1711
  });
1706
1712
 
@@ -1758,7 +1764,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1758
1764
  )
1759
1765
  : undefined;
1760
1766
 
1761
- _optionalChain$t([this, 'access', _2 => _2.client, 'access', _3 => _3.sendEvent, 'optionalCall', _4 => _4({
1767
+ _optionalChain$E([this, 'access', _2 => _2.client, 'access', _3 => _3.sendEvent, 'optionalCall', _4 => _4({
1762
1768
  name,
1763
1769
  metrics: cleanMetrics ,
1764
1770
  categories: cleanCategories ,
@@ -1829,7 +1835,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1829
1835
  log$6('Reporting JS error:', {
1830
1836
  name: error.name,
1831
1837
  message: error.message.slice(0, 100),
1832
- stack: _optionalChain$t([error, 'access', _5 => _5.stack, 'optionalAccess', _6 => _6.slice, 'call', _7 => _7(0, 200)]),
1838
+ stack: _optionalChain$E([error, 'access', _5 => _5.stack, 'optionalAccess', _6 => _6.slice, 'call', _7 => _7(0, 200)]),
1833
1839
  extra,
1834
1840
  source,
1835
1841
  });
@@ -1849,7 +1855,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1849
1855
  if (!this.ensureInitialized()) {
1850
1856
  return;
1851
1857
  }
1852
- _optionalChain$t([this, 'access', _8 => _8.client, 'access', _9 => _9.context, 'optionalAccess', _10 => _10.set, 'call', _11 => _11(key, value)]);
1858
+ _optionalChain$E([this, 'access', _8 => _8.client, 'access', _9 => _9.context, 'optionalAccess', _10 => _10.set, 'call', _11 => _11(key, value)]);
1853
1859
  }
1854
1860
 
1855
1861
  /**
@@ -1860,7 +1866,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1860
1866
  return;
1861
1867
  }
1862
1868
  log$6('Merging context:', context);
1863
- _optionalChain$t([this, 'access', _12 => _12.client, 'access', _13 => _13.context, 'optionalAccess', _14 => _14.merge, 'call', _15 => _15(context)]);
1869
+ _optionalChain$E([this, 'access', _12 => _12.client, 'access', _13 => _13.context, 'optionalAccess', _14 => _14.merge, 'call', _15 => _15(context)]);
1864
1870
  }
1865
1871
 
1866
1872
  /**
@@ -1870,7 +1876,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1870
1876
  if (!this.ensureInitialized()) {
1871
1877
  return;
1872
1878
  }
1873
- _optionalChain$t([this, 'access', _16 => _16.client, 'access', _17 => _17.context, 'optionalAccess', _18 => _18.delete, 'call', _19 => _19(key)]);
1879
+ _optionalChain$E([this, 'access', _16 => _16.client, 'access', _17 => _17.context, 'optionalAccess', _18 => _18.delete, 'call', _19 => _19(key)]);
1874
1880
  }
1875
1881
 
1876
1882
  /**
@@ -1880,7 +1886,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1880
1886
  if (!this.ensureInitialized()) {
1881
1887
  return;
1882
1888
  }
1883
- _optionalChain$t([this, 'access', _20 => _20.client, 'access', _21 => _21.context, 'optionalAccess', _22 => _22.clear, 'call', _23 => _23()]);
1889
+ _optionalChain$E([this, 'access', _20 => _20.client, 'access', _21 => _21.context, 'optionalAccess', _22 => _22.clear, 'call', _23 => _23()]);
1884
1890
  }
1885
1891
 
1886
1892
  /**
@@ -1917,7 +1923,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1917
1923
  return;
1918
1924
  }
1919
1925
  log$6('Flushing Slardar data...');
1920
- _optionalChain$t([this, 'access', _24 => _24.client, 'access', _25 => _25.getSender, 'optionalCall', _26 => _26(), 'optionalAccess', _27 => _27.flush, 'call', _28 => _28()]);
1926
+ _optionalChain$E([this, 'access', _24 => _24.client, 'access', _25 => _25.getSender, 'optionalCall', _26 => _26(), 'optionalAccess', _27 => _27.flush, 'call', _28 => _28()]);
1921
1927
  log$6('Waiting %dms for events to be sent...', waitMs);
1922
1928
  await new Promise(resolve => setTimeout(resolve, waitMs));
1923
1929
  log$6('Slardar data flushed');
@@ -1936,7 +1942,7 @@ class SlardarCLIReporter {constructor() { SlardarCLIReporter.prototype.__init.ca
1936
1942
  */
1937
1943
  const reporter = new SlardarCLIReporter();
1938
1944
 
1939
- function _optionalChain$s(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; }
1945
+ 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; }
1940
1946
 
1941
1947
 
1942
1948
 
@@ -1996,11 +2002,11 @@ const EventBuilder = {
1996
2002
  name: CLI_EVENTS.CLI_COMMAND,
1997
2003
  categories: {
1998
2004
  command,
1999
- args: _optionalChain$s([options, 'optionalAccess', _ => _.args]),
2005
+ args: _optionalChain$D([options, 'optionalAccess', _ => _.args]),
2000
2006
  status: 'running' ,
2001
- ..._optionalChain$s([options, 'optionalAccess', _2 => _2.categories]),
2007
+ ..._optionalChain$D([options, 'optionalAccess', _2 => _2.categories]),
2002
2008
  },
2003
- metrics: _optionalChain$s([options, 'optionalAccess', _3 => _3.metrics]),
2009
+ metrics: _optionalChain$D([options, 'optionalAccess', _3 => _3.metrics]),
2004
2010
  };
2005
2011
  },
2006
2012
 
@@ -2021,13 +2027,13 @@ const EventBuilder = {
2021
2027
  name: CLI_EVENTS.CLI_COMMAND_COMPLETE,
2022
2028
  categories: {
2023
2029
  command,
2024
- args: _optionalChain$s([options, 'optionalAccess', _4 => _4.args]),
2030
+ args: _optionalChain$D([options, 'optionalAccess', _4 => _4.args]),
2025
2031
  status: success ? ('success' ) : ('fail' ),
2026
- ..._optionalChain$s([options, 'optionalAccess', _5 => _5.categories]),
2032
+ ..._optionalChain$D([options, 'optionalAccess', _5 => _5.categories]),
2027
2033
  },
2028
2034
  metrics: {
2029
2035
  duration,
2030
- ...(_optionalChain$s([options, 'optionalAccess', _6 => _6.errorCode]) && { errorCode: options.errorCode }),
2036
+ ...(_optionalChain$D([options, 'optionalAccess', _6 => _6.errorCode]) && { errorCode: options.errorCode }),
2031
2037
  },
2032
2038
  };
2033
2039
  },
@@ -2048,12 +2054,12 @@ const EventBuilder = {
2048
2054
  name: CLI_EVENTS.NETWORK_REQUEST,
2049
2055
  categories: {
2050
2056
  url,
2051
- method: _optionalChain$s([options, 'optionalAccess', _7 => _7.method]) || 'GET',
2052
- statusCode: _optionalChain$s([options, 'optionalAccess', _8 => _8.statusCode, 'optionalAccess', _9 => _9.toString, 'call', _10 => _10()]),
2053
- status: _optionalChain$s([options, 'optionalAccess', _11 => _11.success]) ? ('success' ) : ('fail' ),
2057
+ method: _optionalChain$D([options, 'optionalAccess', _7 => _7.method]) || 'GET',
2058
+ statusCode: _optionalChain$D([options, 'optionalAccess', _8 => _8.statusCode, 'optionalAccess', _9 => _9.toString, 'call', _10 => _10()]),
2059
+ status: _optionalChain$D([options, 'optionalAccess', _11 => _11.success]) ? ('success' ) : ('fail' ),
2054
2060
  },
2055
2061
  metrics: {
2056
- duration: _optionalChain$s([options, 'optionalAccess', _12 => _12.duration]),
2062
+ duration: _optionalChain$D([options, 'optionalAccess', _12 => _12.duration]),
2057
2063
  },
2058
2064
  };
2059
2065
  },
@@ -2075,11 +2081,11 @@ const EventBuilder = {
2075
2081
  categories: {
2076
2082
  operation,
2077
2083
  filePath,
2078
- status: _optionalChain$s([options, 'optionalAccess', _13 => _13.success]) ? ('success' ) : ('fail' ),
2084
+ status: _optionalChain$D([options, 'optionalAccess', _13 => _13.success]) ? ('success' ) : ('fail' ),
2079
2085
  },
2080
2086
  metrics: {
2081
- duration: _optionalChain$s([options, 'optionalAccess', _14 => _14.duration]),
2082
- fileSize: _optionalChain$s([options, 'optionalAccess', _15 => _15.fileSize]),
2087
+ duration: _optionalChain$D([options, 'optionalAccess', _14 => _14.duration]),
2088
+ fileSize: _optionalChain$D([options, 'optionalAccess', _15 => _15.fileSize]),
2083
2089
  },
2084
2090
  };
2085
2091
  },
@@ -2107,7 +2113,7 @@ const EventBuilder = {
2107
2113
  };
2108
2114
 
2109
2115
  var name = "@coze-arch/cli";
2110
- var version = "0.0.35";
2116
+ var version = "0.0.36-alpha.844e20";
2111
2117
  var description = "coze coding devtools cli";
2112
2118
  var license = "MIT";
2113
2119
  var author = "fanwenjie.fe@bytedance.com";
@@ -2119,6 +2125,7 @@ var bin = {
2119
2125
  var files = [
2120
2126
  "lib",
2121
2127
  "bin",
2128
+ "docs/deploy.md",
2122
2129
  "lib/**/.npmrc",
2123
2130
  "!**/*.tsbuildinfo",
2124
2131
  "!**/*.map",
@@ -2155,7 +2162,9 @@ var dependencies = {
2155
2162
  "fast-glob": "^3.3.3",
2156
2163
  "js-yaml": "^4.2.0",
2157
2164
  minimist: "^1.2.8",
2158
- shelljs: "^0.10.0"
2165
+ pnpm: "9.0.0",
2166
+ shelljs: "^0.10.0",
2167
+ tar: "^7.5.22"
2159
2168
  };
2160
2169
  var devDependencies = {
2161
2170
  "@coze-arch/cli-logger": "workspace:*",
@@ -2167,7 +2176,6 @@ var devDependencies = {
2167
2176
  "@coze-arch/ts-config": "workspace:*",
2168
2177
  "@coze-arch/vitest-config": "workspace:*",
2169
2178
  "@coze-coding/lambda": "workspace:*",
2170
- "@emnapi/runtime": "^1.11.1",
2171
2179
  "@inquirer/prompts": "^3.2.0",
2172
2180
  "@rollup/plugin-commonjs": "^28.0.2",
2173
2181
  "@rollup/plugin-json": "~6.1.0",
@@ -2186,7 +2194,6 @@ var devDependencies = {
2186
2194
  playwright: "~1.61.1",
2187
2195
  rollup: "^4.60.1",
2188
2196
  sucrase: "^3.35.1",
2189
- "tree-kill": "^1.2.2",
2190
2197
  tsx: "^4.23.11",
2191
2198
  vitest: "~4.1.10"
2192
2199
  };
@@ -2216,7 +2223,7 @@ var packageJson = {
2216
2223
  cozePublishConfig: cozePublishConfig
2217
2224
  };
2218
2225
 
2219
- function _optionalChain$r(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; }/**
2226
+ 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; }/**
2220
2227
  * Slardar 监控初始化和上报
2221
2228
  */
2222
2229
 
@@ -2319,11 +2326,11 @@ const reportCommandComplete = safeRun(
2319
2326
  ,
2320
2327
  ) => {
2321
2328
  const event = EventBuilder.cliCommandComplete(command, success, duration, {
2322
- args: _optionalChain$r([options, 'optionalAccess', _ => _.args]),
2323
- errorCode: _optionalChain$r([options, 'optionalAccess', _2 => _2.errorCode]),
2329
+ args: _optionalChain$C([options, 'optionalAccess', _ => _.args]),
2330
+ errorCode: _optionalChain$C([options, 'optionalAccess', _2 => _2.errorCode]),
2324
2331
  categories: {
2325
- ...(_optionalChain$r([options, 'optionalAccess', _3 => _3.errorMessage]) && { errorMessage: options.errorMessage }),
2326
- ..._optionalChain$r([options, 'optionalAccess', _4 => _4.categories]),
2332
+ ...(_optionalChain$C([options, 'optionalAccess', _3 => _3.errorMessage]) && { errorMessage: options.errorMessage }),
2333
+ ..._optionalChain$C([options, 'optionalAccess', _4 => _4.categories]),
2327
2334
  },
2328
2335
  });
2329
2336
  reporter.sendEvent(event.name, event.metrics, event.categories);
@@ -2382,7 +2389,7 @@ const flushSlardar = safeRun('flushSlardar', async () => {
2382
2389
  await reporter.flush();
2383
2390
  });
2384
2391
 
2385
- function _nullishCoalesce$9(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$q(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) {
2392
+ function _nullishCoalesce$c(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }var LogLevel; (function (LogLevel) {
2386
2393
  const ERROR = 0; LogLevel[LogLevel["ERROR"] = ERROR] = "ERROR";
2387
2394
  const WARN = 1; LogLevel[LogLevel["WARN"] = WARN] = "WARN";
2388
2395
  const SUCCESS = 2; LogLevel[LogLevel["SUCCESS"] = SUCCESS] = "SUCCESS";
@@ -2420,7 +2427,7 @@ class Logger {
2420
2427
 
2421
2428
  constructor(options = {}) {
2422
2429
  this.level = this.parseLogLevel(options.level);
2423
- this.useColor = _nullishCoalesce$9(options.useColor, () => ( this.isColorSupported()));
2430
+ this.useColor = _nullishCoalesce$c(options.useColor, () => ( this.isColorSupported()));
2424
2431
  this.prefix = options.prefix;
2425
2432
  }
2426
2433
 
@@ -2429,7 +2436,7 @@ class Logger {
2429
2436
  return level;
2430
2437
  }
2431
2438
 
2432
- const envLevel = _optionalChain$q([process, 'access', _ => _.env, 'access', _2 => _2.LOG_LEVEL, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]);
2439
+ const envLevel = _optionalChain$B([process, 'access', _ => _.env, 'access', _2 => _2.LOG_LEVEL, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]);
2433
2440
  if (envLevel && envLevel in LOG_LEVEL_MAP) {
2434
2441
  // envLevel 已通过 `in` 检查确认为 LOG_LEVEL_MAP 的键;
2435
2442
  // 显式判空以满足 noUncheckedIndexedAccess,运行时行为不变
@@ -2446,7 +2453,7 @@ class Logger {
2446
2453
  // 简单检测:Node.js 环境且支持 TTY
2447
2454
  return (
2448
2455
  typeof process !== 'undefined' &&
2449
- _optionalChain$q([process, 'access', _5 => _5.stdout, 'optionalAccess', _6 => _6.isTTY]) === true &&
2456
+ _optionalChain$B([process, 'access', _5 => _5.stdout, 'optionalAccess', _6 => _6.isTTY]) === true &&
2450
2457
  process.env.NO_COLOR === undefined
2451
2458
  );
2452
2459
  }
@@ -2471,7 +2478,7 @@ class Logger {
2471
2478
 
2472
2479
  const icon = this.colorize(options.icon, options.color);
2473
2480
  const prefix = this.prefix ? `${icon} ${this.prefix}` : icon;
2474
- console.log(prefix, options.message, ...(_nullishCoalesce$9(options.args, () => ( []))));
2481
+ console.log(prefix, options.message, ...(_nullishCoalesce$c(options.args, () => ( []))));
2475
2482
  }
2476
2483
 
2477
2484
  error(message, ...args) {
@@ -2816,7 +2823,7 @@ const executeWarmup = async (options) => {
2816
2823
  /**
2817
2824
  * 注册 warmup 命令到 program
2818
2825
  */
2819
- const registerCommand$6 = program => {
2826
+ const registerCommand$7 = program => {
2820
2827
  program
2821
2828
  .command('warmup')
2822
2829
  .description('Pre-install dependencies for templates to speed up init')
@@ -3228,7 +3235,7 @@ const executeUpdate = (
3228
3235
  /**
3229
3236
  * 注册 update 命令到 program
3230
3237
  */
3231
- const registerCommand$5 = program => {
3238
+ const registerCommand$6 = program => {
3232
3239
  program
3233
3240
  .command('update <package>')
3234
3241
  .description('Update a package dependency')
@@ -3254,7 +3261,7 @@ const registerCommand$5 = program => {
3254
3261
  });
3255
3262
  };
3256
3263
 
3257
- function _optionalChain$p(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; }// Safe JSON parsing utilities with type safety and error handling
3264
+ 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; }// Safe JSON parsing utilities with type safety and error handling
3258
3265
  // Provides fallback values, validation, and error monitoring capabilities
3259
3266
 
3260
3267
  /**
@@ -3354,12 +3361,12 @@ function safeJsonParse(
3354
3361
  const parsed = JSON.parse(String(input));
3355
3362
 
3356
3363
  // Optional validation
3357
- if (_optionalChain$p([options, 'optionalAccess', _ => _.validate])) {
3364
+ if (_optionalChain$A([options, 'optionalAccess', _ => _.validate])) {
3358
3365
  if (options.validate(parsed)) {
3359
3366
  return parsed;
3360
3367
  } else {
3361
3368
  const validationError = new Error('JSON validation failed');
3362
- _optionalChain$p([options, 'access', _2 => _2.onError, 'optionalCall', _3 => _3(validationError, input)]);
3369
+ _optionalChain$A([options, 'access', _2 => _2.onError, 'optionalCall', _3 => _3(validationError, input)]);
3363
3370
 
3364
3371
  if (options.throwOnValidationError) {
3365
3372
  throw validationError;
@@ -3371,10 +3378,10 @@ function safeJsonParse(
3371
3378
  return parsed;
3372
3379
  } catch (error) {
3373
3380
  // Re-throw validation errors when throwOnValidationError is true
3374
- if (error instanceof Error && error.message === 'JSON validation failed' && _optionalChain$p([options, 'optionalAccess', _4 => _4.throwOnValidationError])) {
3381
+ if (error instanceof Error && error.message === 'JSON validation failed' && _optionalChain$A([options, 'optionalAccess', _4 => _4.throwOnValidationError])) {
3375
3382
  throw error;
3376
3383
  }
3377
- _optionalChain$p([options, 'optionalAccess', _5 => _5.onError, 'optionalCall', _6 => _6(error , input)]);
3384
+ _optionalChain$A([options, 'optionalAccess', _5 => _5.onError, 'optionalCall', _6 => _6(error , input)]);
3378
3385
  return defaultValue;
3379
3386
  }
3380
3387
  }
@@ -3414,7 +3421,7 @@ function isNode(node) {
3414
3421
  }
3415
3422
  const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;
3416
3423
 
3417
- 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; }
3424
+ function _optionalChain$z(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; }
3418
3425
  const BREAK = Symbol('break visit');
3419
3426
  const SKIP = Symbol('skip children');
3420
3427
  const REMOVE = Symbol('remove node');
@@ -3527,15 +3534,15 @@ function callVisitor(key, node, visitor, path) {
3527
3534
  if (typeof visitor === 'function')
3528
3535
  return visitor(key, node, path);
3529
3536
  if (isMap(node))
3530
- return _optionalChain$o([visitor, 'access', _ => _.Map, 'optionalCall', _2 => _2(key, node, path)]);
3537
+ return _optionalChain$z([visitor, 'access', _ => _.Map, 'optionalCall', _2 => _2(key, node, path)]);
3531
3538
  if (isSeq(node))
3532
- return _optionalChain$o([visitor, 'access', _3 => _3.Seq, 'optionalCall', _4 => _4(key, node, path)]);
3539
+ return _optionalChain$z([visitor, 'access', _3 => _3.Seq, 'optionalCall', _4 => _4(key, node, path)]);
3533
3540
  if (isPair(node))
3534
- return _optionalChain$o([visitor, 'access', _5 => _5.Pair, 'optionalCall', _6 => _6(key, node, path)]);
3541
+ return _optionalChain$z([visitor, 'access', _5 => _5.Pair, 'optionalCall', _6 => _6(key, node, path)]);
3535
3542
  if (isScalar(node))
3536
- return _optionalChain$o([visitor, 'access', _7 => _7.Scalar, 'optionalCall', _8 => _8(key, node, path)]);
3543
+ return _optionalChain$z([visitor, 'access', _7 => _7.Scalar, 'optionalCall', _8 => _8(key, node, path)]);
3537
3544
  if (isAlias(node))
3538
- return _optionalChain$o([visitor, 'access', _9 => _9.Alias, 'optionalCall', _10 => _10(key, node, path)]);
3545
+ return _optionalChain$z([visitor, 'access', _9 => _9.Alias, 'optionalCall', _10 => _10(key, node, path)]);
3539
3546
  return undefined;
3540
3547
  }
3541
3548
  function replaceNode(key, path, node) {
@@ -3626,7 +3633,7 @@ function applyReviver(reviver, obj, key, val) {
3626
3633
  return reviver.call(obj, key, val);
3627
3634
  }
3628
3635
 
3629
- 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; }
3636
+ function _optionalChain$y(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; }
3630
3637
  /**
3631
3638
  * Recursively convert any node or its contents to native JavaScript
3632
3639
  *
@@ -3656,7 +3663,7 @@ function toJS(value, arg, ctx) {
3656
3663
  ctx.onCreate(res);
3657
3664
  return res;
3658
3665
  }
3659
- if (typeof value === 'bigint' && !_optionalChain$n([ctx, 'optionalAccess', _ => _.keep]))
3666
+ if (typeof value === 'bigint' && !_optionalChain$y([ctx, 'optionalAccess', _ => _.keep]))
3660
3667
  return Number(value);
3661
3668
  return value;
3662
3669
  }
@@ -3694,7 +3701,7 @@ class NodeBase {
3694
3701
  }
3695
3702
  }
3696
3703
 
3697
- 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; }
3704
+ function _optionalChain$x(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; }
3698
3705
  class Alias extends NodeBase {
3699
3706
  constructor(source) {
3700
3707
  super(ALIAS);
@@ -3710,10 +3717,10 @@ class Alias extends NodeBase {
3710
3717
  * instance of the `source` anchor before this node.
3711
3718
  */
3712
3719
  resolve(doc, ctx) {
3713
- if (_optionalChain$m([ctx, 'optionalAccess', _ => _.maxAliasCount]) === 0)
3720
+ if (_optionalChain$x([ctx, 'optionalAccess', _ => _.maxAliasCount]) === 0)
3714
3721
  throw new ReferenceError('Alias resolution is disabled');
3715
3722
  let nodes;
3716
- if (_optionalChain$m([ctx, 'optionalAccess', _2 => _2.aliasResolveCache])) {
3723
+ if (_optionalChain$x([ctx, 'optionalAccess', _2 => _2.aliasResolveCache])) {
3717
3724
  nodes = ctx.aliasResolveCache;
3718
3725
  }
3719
3726
  else {
@@ -3752,7 +3759,7 @@ class Alias extends NodeBase {
3752
3759
  data = anchors.get(source);
3753
3760
  }
3754
3761
  /* istanbul ignore if */
3755
- if (_optionalChain$m([data, 'optionalAccess', _3 => _3.res]) === undefined) {
3762
+ if (_optionalChain$x([data, 'optionalAccess', _3 => _3.res]) === undefined) {
3756
3763
  const msg = 'This should not happen: Alias anchor was not resolved?';
3757
3764
  throw new ReferenceError(msg);
3758
3765
  }
@@ -3804,7 +3811,7 @@ function getAliasCount(doc, node, anchors) {
3804
3811
  return 1;
3805
3812
  }
3806
3813
 
3807
- 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; }
3814
+ function _optionalChain$w(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; }
3808
3815
  const isScalarValue = (value) => !value || (typeof value !== 'function' && typeof value !== 'object');
3809
3816
  class Scalar extends NodeBase {
3810
3817
  constructor(value) {
@@ -3812,7 +3819,7 @@ class Scalar extends NodeBase {
3812
3819
  this.value = value;
3813
3820
  }
3814
3821
  toJSON(arg, ctx) {
3815
- return _optionalChain$l([ctx, 'optionalAccess', _ => _.keep]) ? this.value : toJS(this.value, arg, ctx);
3822
+ return _optionalChain$w([ctx, 'optionalAccess', _ => _.keep]) ? this.value : toJS(this.value, arg, ctx);
3816
3823
  }
3817
3824
  toString() {
3818
3825
  return String(this.value);
@@ -3824,17 +3831,17 @@ Scalar.PLAIN = 'PLAIN';
3824
3831
  Scalar.QUOTE_DOUBLE = 'QUOTE_DOUBLE';
3825
3832
  Scalar.QUOTE_SINGLE = 'QUOTE_SINGLE';
3826
3833
 
3827
- function _nullishCoalesce$8(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }
3834
+ function _nullishCoalesce$b(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$v(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
3835
  const defaultTagPrefix = 'tag:yaml.org,2002:';
3829
3836
  function findTagObject(value, tagName, tags) {
3830
3837
  if (tagName) {
3831
3838
  const match = tags.filter(t => t.tag === tagName);
3832
- const tagObj = _nullishCoalesce$8(match.find(t => !t.format), () => ( match[0]));
3839
+ const tagObj = _nullishCoalesce$b(match.find(t => !t.format), () => ( match[0]));
3833
3840
  if (!tagObj)
3834
3841
  throw new Error(`Tag ${tagName} not found`);
3835
3842
  return tagObj;
3836
3843
  }
3837
- return tags.find(t => _optionalChain$k([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(value)]) && !t.format);
3844
+ return tags.find(t => _optionalChain$v([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(value)]) && !t.format);
3838
3845
  }
3839
3846
  function createNode(value, tagName, ctx) {
3840
3847
  if (isDocument(value))
@@ -3842,7 +3849,7 @@ function createNode(value, tagName, ctx) {
3842
3849
  if (isNode(value))
3843
3850
  return value;
3844
3851
  if (isPair(value)) {
3845
- const map = _optionalChain$k([ctx, 'access', _3 => _3.schema, 'access', _4 => _4[MAP], 'access', _5 => _5.createNode, 'optionalCall', _6 => _6(ctx.schema, null, ctx)]);
3852
+ const map = _optionalChain$v([ctx, 'access', _3 => _3.schema, 'access', _4 => _4[MAP], 'access', _5 => _5.createNode, 'optionalCall', _6 => _6(ctx.schema, null, ctx)]);
3846
3853
  map.items.push(value);
3847
3854
  return map;
3848
3855
  }
@@ -3861,7 +3868,7 @@ function createNode(value, tagName, ctx) {
3861
3868
  if (aliasDuplicateObjects && value && typeof value === 'object') {
3862
3869
  ref = sourceObjects.get(value);
3863
3870
  if (ref) {
3864
- _nullishCoalesce$8(ref.anchor, () => ( (ref.anchor = onAnchor(value))));
3871
+ _nullishCoalesce$b(ref.anchor, () => ( (ref.anchor = onAnchor(value))));
3865
3872
  return new Alias(ref.anchor);
3866
3873
  }
3867
3874
  else {
@@ -3869,7 +3876,7 @@ function createNode(value, tagName, ctx) {
3869
3876
  sourceObjects.set(value, ref);
3870
3877
  }
3871
3878
  }
3872
- if (_optionalChain$k([tagName, 'optionalAccess', _7 => _7.startsWith, 'call', _8 => _8('!!')]))
3879
+ if (_optionalChain$v([tagName, 'optionalAccess', _7 => _7.startsWith, 'call', _8 => _8('!!')]))
3873
3880
  tagName = defaultTagPrefix + tagName.slice(2);
3874
3881
  let tagObj = findTagObject(value, tagName, schema.tags);
3875
3882
  if (!tagObj) {
@@ -3894,9 +3901,9 @@ function createNode(value, tagName, ctx) {
3894
3901
  onTagObj(tagObj);
3895
3902
  delete ctx.onTagObj;
3896
3903
  }
3897
- const node = _optionalChain$k([tagObj, 'optionalAccess', _9 => _9.createNode])
3904
+ const node = _optionalChain$v([tagObj, 'optionalAccess', _9 => _9.createNode])
3898
3905
  ? tagObj.createNode(ctx.schema, value, ctx)
3899
- : typeof _optionalChain$k([tagObj, 'optionalAccess', _10 => _10.nodeClass, 'optionalAccess', _11 => _11.from]) === 'function'
3906
+ : typeof _optionalChain$v([tagObj, 'optionalAccess', _10 => _10.nodeClass, 'optionalAccess', _11 => _11.from]) === 'function'
3900
3907
  ? tagObj.nodeClass.from(ctx.schema, value, ctx)
3901
3908
  : new Scalar(value);
3902
3909
  if (tagName)
@@ -4214,7 +4221,7 @@ function consumeMoreIndentedLines(text, i, indent) {
4214
4221
  return end;
4215
4222
  }
4216
4223
 
4217
- 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; }
4224
+ function _optionalChain$u(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; }
4218
4225
  const getFoldOptions = (ctx, isBlock) => ({
4219
4226
  indentAtStart: isBlock ? ctx.indent.length : ctx.indentAtStart,
4220
4227
  lineWidth: ctx.options.lineWidth,
@@ -4499,9 +4506,9 @@ function plainString(item, ctx, onComment, onChompKeep) {
4499
4506
  // booleans get parsed with those types in v1.2 (e.g. '42', 'true' & '0.9e-3'),
4500
4507
  // and others in v1.1.
4501
4508
  if (actualString) {
4502
- const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && _optionalChain$j([tag, 'access', _ => _.test, 'optionalAccess', _2 => _2.test, 'call', _3 => _3(str)]);
4509
+ const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && _optionalChain$u([tag, 'access', _ => _.test, 'optionalAccess', _2 => _2.test, 'call', _3 => _3(str)]);
4503
4510
  const { compat, tags } = ctx.doc.schema;
4504
- if (tags.some(test) || _optionalChain$j([compat, 'optionalAccess', _4 => _4.some, 'call', _5 => _5(test)]))
4511
+ if (tags.some(test) || _optionalChain$u([compat, 'optionalAccess', _4 => _4.some, 'call', _5 => _5(test)]))
4505
4512
  return quotedString(value, ctx);
4506
4513
  }
4507
4514
  return implicitKey
@@ -4547,7 +4554,7 @@ function stringifyString(item, ctx, onComment, onChompKeep) {
4547
4554
  return res;
4548
4555
  }
4549
4556
 
4550
- 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; }
4557
+ function _nullishCoalesce$a(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$t(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; }
4551
4558
  function createStringifyContext(doc, options) {
4552
4559
  const opt = Object.assign({
4553
4560
  blockQuote: true,
@@ -4594,27 +4601,27 @@ function getTagObject(tags, item) {
4594
4601
  if (item.tag) {
4595
4602
  const match = tags.filter(t => t.tag === item.tag);
4596
4603
  if (match.length > 0)
4597
- return _nullishCoalesce$7(match.find(t => t.format === item.format), () => ( match[0]));
4604
+ return _nullishCoalesce$a(match.find(t => t.format === item.format), () => ( match[0]));
4598
4605
  }
4599
4606
  let tagObj = undefined;
4600
4607
  let obj;
4601
4608
  if (isScalar(item)) {
4602
4609
  obj = item.value;
4603
- let match = tags.filter(t => _optionalChain$i([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(obj)]));
4610
+ let match = tags.filter(t => _optionalChain$t([t, 'access', _ => _.identify, 'optionalCall', _2 => _2(obj)]));
4604
4611
  if (match.length > 1) {
4605
4612
  const testMatch = match.filter(t => t.test);
4606
4613
  if (testMatch.length > 0)
4607
4614
  match = testMatch;
4608
4615
  }
4609
4616
  tagObj =
4610
- _nullishCoalesce$7(match.find(t => t.format === item.format), () => ( match.find(t => !t.format)));
4617
+ _nullishCoalesce$a(match.find(t => t.format === item.format), () => ( match.find(t => !t.format)));
4611
4618
  }
4612
4619
  else {
4613
4620
  obj = item;
4614
4621
  tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
4615
4622
  }
4616
4623
  if (!tagObj) {
4617
- const name = _nullishCoalesce$7(_optionalChain$i([obj, 'optionalAccess', _3 => _3.constructor, 'optionalAccess', _4 => _4.name]), () => ( (obj === null ? 'null' : typeof obj)));
4624
+ const name = _nullishCoalesce$a(_optionalChain$t([obj, 'optionalAccess', _3 => _3.constructor, 'optionalAccess', _4 => _4.name]), () => ( (obj === null ? 'null' : typeof obj)));
4618
4625
  throw new Error(`Tag not resolved for ${name} value`);
4619
4626
  }
4620
4627
  return tagObj;
@@ -4629,7 +4636,7 @@ function stringifyProps(node, tagObj, { anchors, doc }) {
4629
4636
  anchors.add(anchor);
4630
4637
  props.push(`&${anchor}`);
4631
4638
  }
4632
- const tag = _nullishCoalesce$7(node.tag, () => ( (tagObj.default ? null : tagObj.tag)));
4639
+ const tag = _nullishCoalesce$a(node.tag, () => ( (tagObj.default ? null : tagObj.tag)));
4633
4640
  if (tag)
4634
4641
  props.push(doc.directives.tagString(tag));
4635
4642
  return props.join(' ');
@@ -4640,7 +4647,7 @@ function stringify(item, ctx, onComment, onChompKeep) {
4640
4647
  if (isAlias(item)) {
4641
4648
  if (ctx.doc.directives)
4642
4649
  return item.toString(ctx);
4643
- if (_optionalChain$i([ctx, 'access', _5 => _5.resolvedAliases, 'optionalAccess', _6 => _6.has, 'call', _7 => _7(item)])) {
4650
+ if (_optionalChain$t([ctx, 'access', _5 => _5.resolvedAliases, 'optionalAccess', _6 => _6.has, 'call', _7 => _7(item)])) {
4644
4651
  throw new TypeError(`Cannot stringify circular structure without alias nodes`);
4645
4652
  }
4646
4653
  else {
@@ -4655,10 +4662,10 @@ function stringify(item, ctx, onComment, onChompKeep) {
4655
4662
  const node = isNode(item)
4656
4663
  ? item
4657
4664
  : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
4658
- _nullishCoalesce$7(tagObj, () => ( (tagObj = getTagObject(ctx.doc.schema.tags, node))));
4665
+ _nullishCoalesce$a(tagObj, () => ( (tagObj = getTagObject(ctx.doc.schema.tags, node))));
4659
4666
  const props = stringifyProps(node, tagObj, ctx);
4660
4667
  if (props.length > 0)
4661
- ctx.indentAtStart = (_nullishCoalesce$7(ctx.indentAtStart, () => ( 0))) + props.length + 1;
4668
+ ctx.indentAtStart = (_nullishCoalesce$a(ctx.indentAtStart, () => ( 0))) + props.length + 1;
4662
4669
  const str = typeof tagObj.stringify === 'function'
4663
4670
  ? tagObj.stringify(node, ctx, onComment, onChompKeep)
4664
4671
  : isScalar(node)
@@ -4671,7 +4678,7 @@ function stringify(item, ctx, onComment, onChompKeep) {
4671
4678
  : `${props}\n${ctx.indent}${str}`;
4672
4679
  }
4673
4680
 
4674
- function _nullishCoalesce$6(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
4681
+ function _nullishCoalesce$9(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
4675
4682
  function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
4676
4683
  const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
4677
4684
  let keyComment = (isNode(key) && key.comment) || null;
@@ -4781,7 +4788,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
4781
4788
  const vs0 = valueStr[0];
4782
4789
  const nl0 = valueStr.indexOf('\n');
4783
4790
  const hasNewline = nl0 !== -1;
4784
- const flow = _nullishCoalesce$6(_nullishCoalesce$6(ctx.inFlow, () => ( value.flow)), () => ( value.items.length === 0));
4791
+ const flow = _nullishCoalesce$9(_nullishCoalesce$9(ctx.inFlow, () => ( value.flow)), () => ( value.items.length === 0));
4785
4792
  if (hasNewline || !flow) {
4786
4793
  let hasPropsLine = false;
4787
4794
  if (hasNewline && (vs0 === '&' || vs0 === '!')) {
@@ -4822,7 +4829,7 @@ function warn(logLevel, warning) {
4822
4829
  }
4823
4830
  }
4824
4831
 
4825
- 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; }
4832
+ function _optionalChain$s(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; }
4826
4833
  // If the value associated with a merge key is a single mapping node, each of
4827
4834
  // its key/value pairs is inserted into the current mapping, unless the key
4828
4835
  // already exists in it. If the value associated with the merge key is a
@@ -4846,7 +4853,7 @@ const isMergeKey = (ctx, key) => (merge.identify(key) ||
4846
4853
  (isScalar(key) &&
4847
4854
  (!key.type || key.type === Scalar.PLAIN) &&
4848
4855
  merge.identify(key.value))) &&
4849
- _optionalChain$h([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)]);
4856
+ _optionalChain$s([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)]);
4850
4857
  function addMergeToJSMap(ctx, map, value) {
4851
4858
  const source = resolveAliasValue(ctx, value);
4852
4859
  if (isSeq(source))
@@ -4886,7 +4893,7 @@ function resolveAliasValue(ctx, value) {
4886
4893
  return ctx && isAlias(value) ? value.resolve(ctx.doc, ctx) : value;
4887
4894
  }
4888
4895
 
4889
- 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; }
4896
+ function _optionalChain$r(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; }
4890
4897
  function addPairToJSMap(ctx, map, { key, value }) {
4891
4898
  if (isNode(key) && key.addToJSMap)
4892
4899
  key.addToJSMap(ctx, map, value);
@@ -4923,7 +4930,7 @@ function stringifyKey(key, jsKey, ctx) {
4923
4930
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
4924
4931
  if (typeof jsKey !== 'object')
4925
4932
  return String(jsKey);
4926
- if (isNode(key) && _optionalChain$g([ctx, 'optionalAccess', _ => _.doc])) {
4933
+ if (isNode(key) && _optionalChain$r([ctx, 'optionalAccess', _ => _.doc])) {
4927
4934
  const strCtx = createStringifyContext(ctx.doc, {});
4928
4935
  strCtx.anchors = new Set();
4929
4936
  for (const node of ctx.anchors.keys())
@@ -4943,7 +4950,7 @@ function stringifyKey(key, jsKey, ctx) {
4943
4950
  return JSON.stringify(jsKey);
4944
4951
  }
4945
4952
 
4946
- 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; }
4953
+ function _optionalChain$q(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; }
4947
4954
  function createPair(key, value, ctx) {
4948
4955
  const k = createNode(key, undefined, ctx);
4949
4956
  const v = createNode(value, undefined, ctx);
@@ -4964,19 +4971,19 @@ class Pair {
4964
4971
  return new Pair(key, value);
4965
4972
  }
4966
4973
  toJSON(_, ctx) {
4967
- const pair = _optionalChain$f([ctx, 'optionalAccess', _2 => _2.mapAsMap]) ? new Map() : {};
4974
+ const pair = _optionalChain$q([ctx, 'optionalAccess', _2 => _2.mapAsMap]) ? new Map() : {};
4968
4975
  return addPairToJSMap(ctx, pair, this);
4969
4976
  }
4970
4977
  toString(ctx, onComment, onChompKeep) {
4971
- return _optionalChain$f([ctx, 'optionalAccess', _3 => _3.doc])
4978
+ return _optionalChain$q([ctx, 'optionalAccess', _3 => _3.doc])
4972
4979
  ? stringifyPair(this, ctx, onComment, onChompKeep)
4973
4980
  : JSON.stringify(this);
4974
4981
  }
4975
4982
  }
4976
4983
 
4977
- function _nullishCoalesce$5(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }
4984
+ function _nullishCoalesce$8(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$p(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; }
4978
4985
  function stringifyCollection(collection, ctx, options) {
4979
- const flow = _nullishCoalesce$5(ctx.inFlow, () => ( collection.flow));
4986
+ const flow = _nullishCoalesce$8(ctx.inFlow, () => ( collection.flow));
4980
4987
  const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
4981
4988
  return stringify(collection, ctx, options);
4982
4989
  }
@@ -5068,7 +5075,7 @@ function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
5068
5075
  if (iv.commentBefore)
5069
5076
  reqNewline = true;
5070
5077
  }
5071
- else if (item.value == null && _optionalChain$e([ik, 'optionalAccess', _ => _.comment])) {
5078
+ else if (item.value == null && _optionalChain$p([ik, 'optionalAccess', _ => _.comment])) {
5072
5079
  comment = ik.comment;
5073
5080
  }
5074
5081
  }
@@ -5123,7 +5130,7 @@ function addCommentBefore({ indent, options: { commentString } }, lines, comment
5123
5130
  }
5124
5131
  }
5125
5132
 
5126
- function _nullishCoalesce$4(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; }
5133
+ function _nullishCoalesce$7(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; }
5127
5134
  function findPair(items, key) {
5128
5135
  const k = isScalar(key) ? key.value : key;
5129
5136
  for (const it of items) {
@@ -5184,12 +5191,12 @@ class YAMLMap extends Collection {
5184
5191
  _pair = pair;
5185
5192
  else if (!pair || typeof pair !== 'object' || !('key' in pair)) {
5186
5193
  // In TypeScript, this never happens.
5187
- _pair = new Pair(pair, _optionalChain$d([pair, 'optionalAccess', _2 => _2.value]));
5194
+ _pair = new Pair(pair, _optionalChain$o([pair, 'optionalAccess', _2 => _2.value]));
5188
5195
  }
5189
5196
  else
5190
5197
  _pair = new Pair(pair.key, pair.value);
5191
5198
  const prev = findPair(this.items, _pair.key);
5192
- const sortEntries = _optionalChain$d([this, 'access', _3 => _3.schema, 'optionalAccess', _4 => _4.sortMapEntries]);
5199
+ const sortEntries = _optionalChain$o([this, 'access', _3 => _3.schema, 'optionalAccess', _4 => _4.sortMapEntries]);
5193
5200
  if (prev) {
5194
5201
  if (!overwrite)
5195
5202
  throw new Error(`Key ${_pair.key} already set`);
@@ -5219,8 +5226,8 @@ class YAMLMap extends Collection {
5219
5226
  }
5220
5227
  get(key, keepScalar) {
5221
5228
  const it = findPair(this.items, key);
5222
- const node = _optionalChain$d([it, 'optionalAccess', _5 => _5.value]);
5223
- return _nullishCoalesce$4((!keepScalar && isScalar(node) ? node.value : node), () => ( undefined));
5229
+ const node = _optionalChain$o([it, 'optionalAccess', _5 => _5.value]);
5230
+ return _nullishCoalesce$7((!keepScalar && isScalar(node) ? node.value : node), () => ( undefined));
5224
5231
  }
5225
5232
  has(key) {
5226
5233
  return !!findPair(this.items, key);
@@ -5234,8 +5241,8 @@ class YAMLMap extends Collection {
5234
5241
  * @returns Instance of Type, Map, or Object
5235
5242
  */
5236
5243
  toJSON(_, ctx, Type) {
5237
- const map = Type ? new Type() : _optionalChain$d([ctx, 'optionalAccess', _6 => _6.mapAsMap]) ? new Map() : {};
5238
- if (_optionalChain$d([ctx, 'optionalAccess', _7 => _7.onCreate]))
5244
+ const map = Type ? new Type() : _optionalChain$o([ctx, 'optionalAccess', _6 => _6.mapAsMap]) ? new Map() : {};
5245
+ if (_optionalChain$o([ctx, 'optionalAccess', _7 => _7.onCreate]))
5239
5246
  ctx.onCreate(map);
5240
5247
  for (const item of this.items)
5241
5248
  addPairToJSMap(ctx, map, item);
@@ -5260,7 +5267,7 @@ class YAMLMap extends Collection {
5260
5267
  }
5261
5268
  }
5262
5269
 
5263
- 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; }
5270
+ 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; }
5264
5271
  class YAMLSeq extends Collection {
5265
5272
  static get tagName() {
5266
5273
  return 'tag:yaml.org,2002:seq';
@@ -5323,7 +5330,7 @@ class YAMLSeq extends Collection {
5323
5330
  }
5324
5331
  toJSON(_, ctx) {
5325
5332
  const seq = [];
5326
- if (_optionalChain$c([ctx, 'optionalAccess', _2 => _2.onCreate]))
5333
+ if (_optionalChain$n([ctx, 'optionalAccess', _2 => _2.onCreate]))
5327
5334
  ctx.onCreate(seq);
5328
5335
  let i = 0;
5329
5336
  for (const item of this.items)
@@ -5402,7 +5409,7 @@ function createPairs(schema, iterable, ctx) {
5402
5409
  return pairs;
5403
5410
  }
5404
5411
 
5405
- 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; }
5412
+ 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; }
5406
5413
  class YAMLOMap extends YAMLSeq {
5407
5414
  constructor() {
5408
5415
  super();
@@ -5421,7 +5428,7 @@ class YAMLOMap extends YAMLSeq {
5421
5428
  if (!ctx)
5422
5429
  return super.toJSON(_);
5423
5430
  const map = new Map();
5424
- if (_optionalChain$b([ctx, 'optionalAccess', _2 => _2.onCreate]))
5431
+ if (_optionalChain$m([ctx, 'optionalAccess', _2 => _2.onCreate]))
5425
5432
  ctx.onCreate(map);
5426
5433
  for (const pair of this.items) {
5427
5434
  let key, value;
@@ -5539,7 +5546,7 @@ const isDirExists = async (file) => {
5539
5546
  }
5540
5547
  };
5541
5548
 
5542
- 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; }// ABOUTME: Project type detection utility
5549
+ 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; }// ABOUTME: Project type detection utility
5543
5550
 
5544
5551
  /**
5545
5552
  * 支持的项目类型枚举
@@ -5641,7 +5648,7 @@ const collectProjectInfo = async (
5641
5648
  }
5642
5649
 
5643
5650
  const scripts = Object.entries(
5644
- (_optionalChain$a([packageJson, 'optionalAccess', _ => _.scripts]) ) || {},
5651
+ (_optionalChain$l([packageJson, 'optionalAccess', _ => _.scripts]) ) || {},
5645
5652
  ).reduce((acc, [name, script]) => {
5646
5653
  if (typeof script === 'string') {
5647
5654
  acc[name] = script;
@@ -5795,7 +5802,7 @@ const detectProjectType = async (
5795
5802
  };
5796
5803
  };
5797
5804
 
5798
- 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; }
5805
+ 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; }
5799
5806
 
5800
5807
 
5801
5808
  /**
@@ -5807,7 +5814,7 @@ function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[
5807
5814
  const parseConfigContent = (content) => {
5808
5815
  // 1. 尝试 TOML 格式 (默认)
5809
5816
  try {
5810
- const config = toml.parse(content);
5817
+ const config = TOML.parse(content);
5811
5818
  return config ;
5812
5819
  } catch (error) {
5813
5820
  // TOML 解析失败,继续尝试其他格式
@@ -5841,7 +5848,7 @@ const parseConfigContent = (content) => {
5841
5848
  */
5842
5849
  const parseTomlConfigContent = (content) => {
5843
5850
  try {
5844
- return toml.parse(content) ;
5851
+ return TOML.parse(content) ;
5845
5852
  } catch (e) {
5846
5853
  return null;
5847
5854
  }
@@ -5922,7 +5929,7 @@ const saveTomlCozeConfig = async (
5922
5929
  projectPath,
5923
5930
  `.coze.tmp-${process.pid}-${Date.now()}`,
5924
5931
  );
5925
- const content = toml.stringify(config );
5932
+ const content = TOML.stringify(config );
5926
5933
 
5927
5934
  try {
5928
5935
  await fs$1.writeFile(tempCozeConfigPath, content, 'utf-8');
@@ -5969,16 +5976,16 @@ const getCommandConfig = (
5969
5976
 
5970
5977
  switch (commandName) {
5971
5978
  case 'dev':
5972
- commandConfig = _optionalChain$9([config, 'access', _ => _.dev, 'optionalAccess', _2 => _2.run]);
5979
+ commandConfig = _optionalChain$k([config, 'access', _ => _.dev, 'optionalAccess', _2 => _2.run]);
5973
5980
  break;
5974
5981
  case 'build':
5975
- commandConfig = _optionalChain$9([config, 'access', _3 => _3.deploy, 'optionalAccess', _4 => _4.build]);
5982
+ commandConfig = _optionalChain$k([config, 'access', _3 => _3.deploy, 'optionalAccess', _4 => _4.build]);
5976
5983
  break;
5977
5984
  case 'start':
5978
- commandConfig = _optionalChain$9([config, 'access', _5 => _5.deploy, 'optionalAccess', _6 => _6.run]);
5985
+ commandConfig = _optionalChain$k([config, 'access', _5 => _5.deploy, 'optionalAccess', _6 => _6.run]);
5979
5986
  break;
5980
5987
  case 'validate':
5981
- commandConfig = _optionalChain$9([config, 'access', _7 => _7.dev, 'optionalAccess', _8 => _8.validate]);
5988
+ commandConfig = _optionalChain$k([config, 'access', _7 => _7.dev, 'optionalAccess', _8 => _8.validate]);
5982
5989
  break;
5983
5990
  default:
5984
5991
  throw new Error(`Unknown command: ${commandName}`);
@@ -6129,7 +6136,7 @@ const byFlag = (flag) => {
6129
6136
  return predicate;
6130
6137
  };
6131
6138
 
6132
- 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; }
6139
+ 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; }
6133
6140
 
6134
6141
 
6135
6142
 
@@ -6160,7 +6167,7 @@ echo "Validate passed!"
6160
6167
  * @returns
6161
6168
  */
6162
6169
  const isCozeValid$3 = (cozeConfig) => {
6163
- if (_optionalChain$8([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6170
+ if (_optionalChain$j([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6164
6171
  logger.info('[patch-expo-validate] NOT APPLY: dev.validate exists');
6165
6172
  return false;
6166
6173
  }
@@ -6305,7 +6312,7 @@ const patchExpoValidate = {
6305
6312
  },
6306
6313
  };
6307
6314
 
6308
- 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; }
6315
+ 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; }
6309
6316
 
6310
6317
 
6311
6318
 
@@ -6338,7 +6345,7 @@ echo "Validate passed!"
6338
6345
  * @returns
6339
6346
  */
6340
6347
  const isCozeValid$2 = (cozeConfig) => {
6341
- if (_optionalChain$7([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6348
+ if (_optionalChain$i([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6342
6349
  logger.info('[patch-nextjs-validate] NOT APPLY: dev.validate exists');
6343
6350
  return false;
6344
6351
  }
@@ -6486,7 +6493,7 @@ const patchNextjsValidate = {
6486
6493
  },
6487
6494
  };
6488
6495
 
6489
- 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; }
6496
+ 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; }
6490
6497
 
6491
6498
  const PATCH_ID$5 = 'nextjs/validate-concurrently@0.0.30';
6492
6499
  const PACKAGE_JSON_FILE$3 = 'package.json';
@@ -6519,7 +6526,7 @@ const readPackageJson = async (projectFolder) => {
6519
6526
  };
6520
6527
 
6521
6528
  const getTargetValidateScript = (packageJson) => {
6522
- const validateScript = _optionalChain$6([packageJson, 'access', _ => _.scripts, 'optionalAccess', _2 => _2.validate]);
6529
+ const validateScript = _optionalChain$h([packageJson, 'access', _ => _.scripts, 'optionalAccess', _2 => _2.validate]);
6523
6530
  if (typeof validateScript !== 'string') {
6524
6531
  return null;
6525
6532
  }
@@ -6536,7 +6543,7 @@ const getTargetValidateScript = (packageJson) => {
6536
6543
 
6537
6544
  const canStackAfterNextjsValidatePatch = async (context, packageJson) => {
6538
6545
  const scripts = packageJson.scripts || {};
6539
- if (typeof scripts.validate !== 'undefined' || typeof scripts['ts-check'] !== 'string' || _optionalChain$6([context, 'access', _3 => _3.cozeConfig, 'access', _4 => _4.dev, 'optionalAccess', _5 => _5.validate])) {
6546
+ if (typeof scripts.validate !== 'undefined' || typeof scripts['ts-check'] !== 'string' || _optionalChain$h([context, 'access', _3 => _3.cozeConfig, 'access', _4 => _4.dev, 'optionalAccess', _5 => _5.validate])) {
6540
6547
  return false;
6541
6548
  }
6542
6549
 
@@ -6605,7 +6612,7 @@ const patchNextjsValidateConcurrently = {
6605
6612
  apply: patchPackageJson$2,
6606
6613
  };
6607
6614
 
6608
- 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; }
6615
+ 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; }
6609
6616
 
6610
6617
 
6611
6618
 
@@ -6638,7 +6645,7 @@ echo "Validate passed!"
6638
6645
  * @returns
6639
6646
  */
6640
6647
  const isCozeValid$1 = (cozeConfig) => {
6641
- if (_optionalChain$5([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6648
+ if (_optionalChain$g([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6642
6649
  logger.info('[patch-vite-validate] NOT APPLY: dev.validate exists');
6643
6650
  return false;
6644
6651
  }
@@ -6783,7 +6790,7 @@ const patchViteValidate = {
6783
6790
  },
6784
6791
  };
6785
6792
 
6786
- 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; }
6793
+ 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; }
6787
6794
 
6788
6795
 
6789
6796
 
@@ -6820,7 +6827,7 @@ echo "Validate passed!"
6820
6827
  * @returns
6821
6828
  */
6822
6829
  const isCozeValid = (cozeConfig) => {
6823
- if (_optionalChain$4([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6830
+ if (_optionalChain$f([cozeConfig, 'access', _ => _.dev, 'optionalAccess', _2 => _2.validate])) {
6824
6831
  logger.info('[patch-taro-validate] NOT APPLY: dev.validate exists');
6825
6832
  return false;
6826
6833
  }
@@ -6969,7 +6976,7 @@ const patchTaroValidate = {
6969
6976
  },
6970
6977
  };
6971
6978
 
6972
- 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; }
6979
+ 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; }
6973
6980
  const PATCH_ID$2 = 'taro/update-pack-script-for-tt-build@0.0.13';
6974
6981
  const PACKAGE_JSON_FILE = 'package.json';
6975
6982
  const PACK_SCRIPT_FILE = '.cozeproj/scripts/pack.sh';
@@ -7048,12 +7055,12 @@ const readPackageScripts = async (
7048
7055
  const packageJsonContent = await fs$1.readFile(packageJsonPath, 'utf-8');
7049
7056
  const packageJson = safeJsonParse(packageJsonContent, null);
7050
7057
 
7051
- return _optionalChain$3([packageJson, 'optionalAccess', _ => _.scripts]) || null;
7058
+ return _optionalChain$e([packageJson, 'optionalAccess', _ => _.scripts]) || null;
7052
7059
  };
7053
7060
 
7054
7061
  const hasBuildTtScript = async (projectFolder) => {
7055
7062
  const scripts = await readPackageScripts(projectFolder);
7056
- return typeof _optionalChain$3([scripts, 'optionalAccess', _2 => _2['build:tt']]) === 'string';
7063
+ return typeof _optionalChain$e([scripts, 'optionalAccess', _2 => _2['build:tt']]) === 'string';
7057
7064
  };
7058
7065
 
7059
7066
  const hasLegacyPackScript = async (projectFolder) => {
@@ -7407,7 +7414,7 @@ const getTemplatePatches = (
7407
7414
  ) =>
7408
7415
  patches.filter(patch => patch.template === template);
7409
7416
 
7410
- function _nullishCoalesce$3(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; }
7417
+ 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; }
7411
7418
  const DEFAULT_LEGACY_VERSION = 'legacy';
7412
7419
 
7413
7420
  const loadFlagsWithFallback = async () => {
@@ -7513,7 +7520,7 @@ const getNextPatchState = (
7513
7520
 
7514
7521
  ) => ({
7515
7522
  template,
7516
- version: _optionalChain$2([config, 'access', _ => _.project, 'optionalAccess', _2 => _2.version]) || DEFAULT_LEGACY_VERSION,
7523
+ version: _optionalChain$d([config, 'access', _ => _.project, 'optionalAccess', _2 => _2.version]) || DEFAULT_LEGACY_VERSION,
7517
7524
  appliedPatches: [...appliedPatches, patchId],
7518
7525
  });
7519
7526
 
@@ -7537,15 +7544,15 @@ const executePatch = async (
7537
7544
  }
7538
7545
 
7539
7546
  const template =
7540
- _optionalChain$2([config, 'access', _3 => _3.project, 'optionalAccess', _4 => _4.template]) || (await detectTemplateKey(projectFolder));
7547
+ _optionalChain$d([config, 'access', _3 => _3.project, 'optionalAccess', _4 => _4.template]) || (await detectTemplateKey(projectFolder));
7541
7548
 
7542
7549
  if (!template) {
7543
7550
  logger.info('Patch skipped: template not detected');
7544
7551
  return;
7545
7552
  }
7546
7553
 
7547
- const appliedPatches = [...(_optionalChain$2([config, 'access', _5 => _5.project, 'optionalAccess', _6 => _6.appliedPatches]) || [])];
7548
- const projectVersion = _optionalChain$2([config, 'access', _7 => _7.project, 'optionalAccess', _8 => _8.version]);
7554
+ const appliedPatches = [...(_optionalChain$d([config, 'access', _5 => _5.project, 'optionalAccess', _6 => _6.appliedPatches]) || [])];
7555
+ const projectVersion = _optionalChain$d([config, 'access', _7 => _7.project, 'optionalAccess', _8 => _8.version]);
7549
7556
  const flags = await loadFlagsWithFallback();
7550
7557
 
7551
7558
  const context = {
@@ -7590,7 +7597,7 @@ const executePatch = async (
7590
7597
 
7591
7598
  if (options.dryRun) {
7592
7599
  logger.info(`Detected template: ${template}`);
7593
- logger.info(`Current version: ${_nullishCoalesce$3(projectVersion, () => ( DEFAULT_LEGACY_VERSION))}`);
7600
+ logger.info(`Current version: ${_nullishCoalesce$6(projectVersion, () => ( DEFAULT_LEGACY_VERSION))}`);
7594
7601
  logger.info(`Applied patches: ${appliedPatches.join(', ') || '(none)'}`);
7595
7602
  logger.info('Matched patches:');
7596
7603
  matchedPatches.forEach(patch => {
@@ -7631,7 +7638,7 @@ const executePatch = async (
7631
7638
  }
7632
7639
  };
7633
7640
 
7634
- const registerCommand$4 = program => {
7641
+ const registerCommand$5 = program => {
7635
7642
  program
7636
7643
  .command('patch')
7637
7644
  .description('Apply template patches for existing projects')
@@ -7648,14 +7655,14 @@ const registerCommand$4 = program => {
7648
7655
  ) => {
7649
7656
  await executePatch({
7650
7657
  directory,
7651
- dryRun: _optionalChain$2([command, 'optionalAccess', _9 => _9.dryRun]),
7652
- showFlags: _optionalChain$2([command, 'optionalAccess', _10 => _10.showFlags]),
7658
+ dryRun: _optionalChain$d([command, 'optionalAccess', _9 => _9.dryRun]),
7659
+ showFlags: _optionalChain$d([command, 'optionalAccess', _10 => _10.showFlags]),
7653
7660
  });
7654
7661
  },
7655
7662
  );
7656
7663
  };
7657
7664
 
7658
- function _nullishCoalesce$2(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; }
7665
+ function _nullishCoalesce$5(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; }
7659
7666
  const d$1 = debug('coze-init-cli:run');
7660
7667
 
7661
7668
  /**
@@ -7786,12 +7793,12 @@ const executeRun = async (commandName, options = {}) => {
7786
7793
  }
7787
7794
 
7788
7795
  // 将输出同时写入控制台和日志文件
7789
- _optionalChain$1([childProcess, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.on, 'call', _3 => _3('data', (data) => {
7796
+ _optionalChain$c([childProcess, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.on, 'call', _3 => _3('data', (data) => {
7790
7797
  process.stdout.write(data);
7791
7798
  logStream.write(data);
7792
7799
  })]);
7793
7800
 
7794
- _optionalChain$1([childProcess, 'access', _4 => _4.stderr, 'optionalAccess', _5 => _5.on, 'call', _6 => _6('data', (data) => {
7801
+ _optionalChain$c([childProcess, 'access', _4 => _4.stderr, 'optionalAccess', _5 => _5.on, 'call', _6 => _6('data', (data) => {
7795
7802
  process.stderr.write(data);
7796
7803
  logStream.write(data);
7797
7804
  })]);
@@ -7804,7 +7811,7 @@ const executeRun = async (commandName, options = {}) => {
7804
7811
  const buildDuration = Date.now() - buildStartTime;
7805
7812
 
7806
7813
  if (code !== 0) {
7807
- const errorMessage = `Command exited with code ${_nullishCoalesce$2(code, () => ( 'unknown'))}${signal ? ` and signal ${signal}` : ''}`;
7814
+ const errorMessage = `Command exited with code ${_nullishCoalesce$5(code, () => ( 'unknown'))}${signal ? ` and signal ${signal}` : ''}`;
7808
7815
  logger.error(errorMessage);
7809
7816
  logger.error(`Check log file for details: ${logFilePath}`);
7810
7817
 
@@ -7816,12 +7823,12 @@ const executeRun = async (commandName, options = {}) => {
7816
7823
  categories: {
7817
7824
  fixDuration: String(fixDuration),
7818
7825
  buildDuration: String(buildDuration),
7819
- exitCode: String(_nullishCoalesce$2(code, () => ( 'unknown'))),
7826
+ exitCode: String(_nullishCoalesce$5(code, () => ( 'unknown'))),
7820
7827
  projectType,
7821
7828
  },
7822
7829
  errorContext: {
7823
- exitCode: String(_nullishCoalesce$2(code, () => ( 'unknown'))),
7824
- signal: _nullishCoalesce$2(signal, () => ( 'none')),
7830
+ exitCode: String(_nullishCoalesce$5(code, () => ( 'unknown'))),
7831
+ signal: _nullishCoalesce$5(signal, () => ( 'none')),
7825
7832
  logFile: logFilePath,
7826
7833
  projectType,
7827
7834
  },
@@ -7897,7 +7904,7 @@ const executeRun = async (commandName, options = {}) => {
7897
7904
  /**
7898
7905
  * 注册 dev/build/start 命令到 program
7899
7906
  */
7900
- const registerCommand$3 = program => {
7907
+ const registerCommand$4 = program => {
7901
7908
  // dev 命令
7902
7909
  program
7903
7910
  .command('dev')
@@ -8735,7 +8742,7 @@ const scanRoutesOnce = async (
8735
8742
  }
8736
8743
  };
8737
8744
 
8738
- 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
8745
+ 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; }// Route manifest generation command
8739
8746
 
8740
8747
 
8741
8748
  const log = debug('coze:routes');
@@ -8823,7 +8830,7 @@ const executeRoutes = async (
8823
8830
  /**
8824
8831
  * Register routes command to program
8825
8832
  */
8826
- const registerCommand$2 = program => {
8833
+ const registerCommand$3 = program => {
8827
8834
  program
8828
8835
  .command('routes')
8829
8836
  .description('Generate routes manifest for the current project')
@@ -8836,11 +8843,11 @@ const registerCommand$2 = program => {
8836
8843
  'Output file path (defaults to ~/.coze/routes.json)',
8837
8844
  )
8838
8845
  .action(async (directory, options) => {
8839
- await executeRoutes({ directory, output: _optionalChain([options, 'optionalAccess', _ => _.output]) });
8846
+ await executeRoutes({ directory, output: _optionalChain$b([options, 'optionalAccess', _ => _.output]) });
8840
8847
  });
8841
8848
  };
8842
8849
 
8843
- function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
8850
+ function _nullishCoalesce$4(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
8844
8851
 
8845
8852
 
8846
8853
  const d = debug('coze-init-cli:check-bins');
@@ -8897,7 +8904,7 @@ const checkBins = async (cwd, fix) => {
8897
8904
 
8898
8905
  const bins =
8899
8906
  typeof depPkg.bin === 'string'
8900
- ? { [_nullishCoalesce$1(depName.split('/').pop(), () => ( depName))]: depPkg.bin }
8907
+ ? { [_nullishCoalesce$4(depName.split('/').pop(), () => ( depName))]: depPkg.bin }
8901
8908
  : depPkg.bin;
8902
8909
 
8903
8910
  d('%s declares bins: %o', depName, Object.keys(bins));
@@ -8947,7 +8954,7 @@ const checkBins = async (cwd, fix) => {
8947
8954
  d('pnpm i --force completed');
8948
8955
  };
8949
8956
 
8950
- const registerCommand$1 = program => {
8957
+ const registerCommand$2 = program => {
8951
8958
  program
8952
8959
  .command('check-bins')
8953
8960
  .description(
@@ -9841,7 +9848,7 @@ const execute = async (
9841
9848
  };
9842
9849
  };
9843
9850
 
9844
- function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
9851
+ function _nullishCoalesce$3(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
9845
9852
  /**
9846
9853
  * 运行 pnpm install
9847
9854
  */
@@ -9962,8 +9969,8 @@ const runDev = (projectPath) => {
9962
9969
  // 获取当前 CLI 的可执行文件路径
9963
9970
  // process.argv[0] 是 node,process.argv[1] 是 CLI 入口文件
9964
9971
  // 二者在 CLI 运行时必然存在,兜底空串仅为满足类型收窄,运行时不会命中
9965
- const nodeBin = _nullishCoalesce(process.argv[0], () => ( ''));
9966
- const cliPath = _nullishCoalesce(process.argv[1], () => ( ''));
9972
+ const nodeBin = _nullishCoalesce$3(process.argv[0], () => ( ''));
9973
+ const cliPath = _nullishCoalesce$3(process.argv[1], () => ( ''));
9967
9974
 
9968
9975
  try {
9969
9976
  // 使用通用的后台执行函数启动开发服务器
@@ -10033,7 +10040,7 @@ const executeTemplateEngineStep = async ctx => {
10033
10040
  templateName: ctx.templateName,
10034
10041
  outputPath: ctx.outputPath,
10035
10042
  command: ctx.command,
10036
- force: _nullishCoalesce(ctx.options.force, () => ( false)),
10043
+ force: _nullishCoalesce$3(ctx.options.force, () => ( false)),
10037
10044
  });
10038
10045
 
10039
10046
  // 保存结果到上下文
@@ -10292,7 +10299,7 @@ const executeInit = async (
10292
10299
  /**
10293
10300
  * 注册 init 命令到 program
10294
10301
  */
10295
- const registerCommand = program => {
10302
+ const registerCommand$1 = program => {
10296
10303
  program
10297
10304
  .command('init')
10298
10305
  .description('Initialize a new project from a template')
@@ -10310,64 +10317,3196 @@ const registerCommand = program => {
10310
10317
  .allowUnknownOption() // 允许透传参数
10311
10318
  .action(async (directory, options, command) => {
10312
10319
  // 位置参数优先级高于 --output 选项
10313
- const outputPath = _nullishCoalesce(directory, () => ( options.output));
10320
+ const outputPath = _nullishCoalesce$3(directory, () => ( options.output));
10314
10321
  // Always use force mode - overwrite existing files without conflict check
10315
10322
  const force = true;
10316
10323
  await executeInit({ ...options, output: outputPath, force }, command);
10317
10324
  });
10318
10325
  };
10319
10326
 
10320
- const commands = [
10321
- registerCommand,
10322
- registerCommand$3,
10323
- registerCommand$6,
10324
- registerCommand$4,
10325
- registerCommand$5,
10326
- registerCommand$2,
10327
- registerCommand$1,
10328
- ];
10327
+ const deployCommands = new WeakSet();
10329
10328
 
10330
- const main = async () => {
10331
- // 初始化 Slardar 监控
10332
- initSlardar();
10329
+ const markDeployCommand = (command) => {
10330
+ deployCommands.add(command);
10331
+ return command;
10332
+ };
10333
10333
 
10334
- // 监听未捕获的异常
10335
- process.on('uncaughtException', async (error) => {
10336
- reportError(error, {
10337
- type: 'uncaughtException',
10338
- context: 'global',
10334
+ const findDeployCommand = (command) => {
10335
+ let current = command;
10336
+ while (current) {
10337
+ if (deployCommands.has(current)) {
10338
+ return current;
10339
+ }
10340
+ current = current.parent;
10341
+ }
10342
+ throw new Error('Unable to resolve the coze-dev deploy command context.');
10343
+ };
10344
+
10345
+ class CliError extends Error {
10346
+ constructor(
10347
+ message,
10348
+ code = 'DEPLOY_CLI_ERROR',
10349
+ details,
10350
+ ) {
10351
+ super(message);this.code = code;this.details = details; this.name = 'CliError';
10352
+ }
10353
+ }
10354
+
10355
+ const toErrorPayload = (error) => {
10356
+ if (error instanceof CliError) {
10357
+ return { code: error.code, message: error.message, details: error.details };
10358
+ }
10359
+ return {
10360
+ code: 'INTERNAL_ERROR',
10361
+ message: error instanceof Error ? error.message : String(error),
10362
+ };
10363
+ };
10364
+
10365
+ const APPLICATION_TYPES = new Set([
10366
+ 'service',
10367
+ 'pages',
10368
+ 'mini_program',
10369
+ ]);
10370
+
10371
+ const PAGES_SERVICE_TYPE = 3;
10372
+
10373
+ const inferApplicationTypeFromProjectType = (
10374
+ projectType,
10375
+ ) => {
10376
+ switch (projectType) {
10377
+ case 'miniapp':
10378
+ case 'miniprogram':
10379
+ return 'mini_program';
10380
+ case undefined:
10381
+ case '':
10382
+ return undefined;
10383
+ default:
10384
+ return 'service';
10385
+ }
10386
+ };
10387
+
10388
+ const parseApplicationType = (
10389
+ value,
10390
+ ) => {
10391
+ if (!value) {
10392
+ return undefined;
10393
+ }
10394
+ if (!APPLICATION_TYPES.has(value )) {
10395
+ throw new CliError(
10396
+ `Unsupported application type ${value}; expected service, pages, or mini_program.`,
10397
+ 'INVALID_APPLICATION_TYPE',
10398
+ );
10399
+ }
10400
+ return value ;
10401
+ };
10402
+
10403
+ const withRequestedApplicationType = (
10404
+ config,
10405
+ requestedType,
10406
+ hasApplication = false,
10407
+ ) => {
10408
+ if (!requestedType) {
10409
+ return config;
10410
+ }
10411
+ if (hasApplication && config.application_type !== requestedType) {
10412
+ throw new CliError(
10413
+ `Application type mismatch: the application is ${config.application_type}, but ${requestedType} was requested.`,
10414
+ 'APPLICATION_TYPE_MISMATCH',
10415
+ );
10416
+ }
10417
+ if (requestedType !== 'pages') {
10418
+ if (config.application_type !== requestedType) {
10419
+ throw new CliError(
10420
+ `Application type mismatch: server resolved ${config.application_type}, but ${requestedType} was requested.`,
10421
+ 'APPLICATION_TYPE_MISMATCH',
10422
+ );
10423
+ }
10424
+ return config;
10425
+ }
10426
+ return {
10427
+ ...config,
10428
+ application_type: 'pages',
10429
+ deploy_config: {
10430
+ ...config.deploy_config,
10431
+ service_type: PAGES_SERVICE_TYPE,
10432
+ computer_id: undefined,
10433
+ },
10434
+ };
10435
+ };
10436
+
10437
+ 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; }
10438
+
10439
+ const DEFAULT_CONFIG = {
10440
+ apiBaseUrl: 'https://code.coze.cn/',
10441
+ openApiBaseUrl: 'https://api.coze.cn',
10442
+ clientId: '95438868623436343239609434490626.app.coze',
10443
+ };
10444
+
10445
+ const getSharedConfigPath = () =>
10446
+ node_path.join(node_os.homedir(), '.coze', 'cli', 'config.json');
10447
+
10448
+ const getLegacyConfigPath = () => node_path.join(node_os.homedir(), '.coze', 'config.json');
10449
+
10450
+ const isRecord$3 = (value) =>
10451
+ typeof value === 'object' && value !== null && !Array.isArray(value);
10452
+
10453
+ const readJson = async (path) => {
10454
+ try {
10455
+ const parsed = safeJsonParse(await promises.readFile(path, 'utf8'), undefined);
10456
+ return isRecord$3(parsed) ? parsed : undefined;
10457
+ } catch (error) {
10458
+ if ((error ).code === 'ENOENT') {
10459
+ return undefined;
10460
+ }
10461
+ throw new CliError(`Unable to read config ${path}: ${String(error)}`, 'CONFIG_INVALID');
10462
+ }
10463
+ };
10464
+
10465
+ const configuredPath = (options) =>
10466
+ _optionalChain$a([options, 'optionalAccess', _ => _.config]) || process.env.COZE_CONFIG_FILE;
10467
+
10468
+ const loadConfig = async (options = {}) => {
10469
+ const customPath = configuredPath(options);
10470
+ const globalConfig = customPath
10471
+ ? await readJson(node_path.resolve(customPath))
10472
+ : (await readJson(getSharedConfigPath())) || (await readJson(getLegacyConfigPath()));
10473
+ const environmentAccessToken = process.env.COZE_API_TOKEN;
10474
+ const config = {
10475
+ ...DEFAULT_CONFIG,
10476
+ ...globalConfig,
10477
+ ...(environmentAccessToken
10478
+ ? {
10479
+ accessToken: environmentAccessToken,
10480
+ // COZE_API_TOKEN is a fixed runtime credential. Never combine it with
10481
+ // refresh metadata left by an earlier OAuth login in config.json.
10482
+ refreshToken: undefined,
10483
+ tokenExpiresAt: undefined,
10484
+ }
10485
+ : {}),
10486
+ ...(process.env.COZE_ORG_ID ? { organizationId: process.env.COZE_ORG_ID } : {}),
10487
+ ...(process.env.COZE_SPACE_ID ? { spaceId: process.env.COZE_SPACE_ID } : {}),
10488
+ ...(process.env.COZE_PROJECT_ID ? { projectId: process.env.COZE_PROJECT_ID } : {}),
10489
+ ...(options.orgId ? { organizationId: options.orgId } : {}),
10490
+ ...(options.spaceId ? { spaceId: options.spaceId } : {}),
10491
+ ...(options.apiBaseUrl ? { apiBaseUrl: options.apiBaseUrl } : {}),
10492
+ };
10493
+ return config;
10494
+ };
10495
+
10496
+ const saveSharedConfig = async (
10497
+ patch,
10498
+ options = {},
10499
+ ) => {
10500
+ const target = node_path.resolve(configuredPath(options) || getSharedConfigPath());
10501
+ const existing = (await readJson(target)) || {};
10502
+ const temp = node_path.join(node_path.dirname(target), `.config-${node_crypto.randomUUID()}.tmp`);
10503
+ await promises.mkdir(node_path.dirname(target), { recursive: true });
10504
+ try {
10505
+ await promises.writeFile(temp, `${JSON.stringify({ ...existing, ...patch }, null, 2)}\n`, {
10506
+ encoding: 'utf8',
10507
+ mode: 0o600,
10339
10508
  });
10340
- await flushSlardar();
10341
- process.exit(1);
10509
+ await promises.rename(temp, target);
10510
+ } finally {
10511
+ await promises.rm(temp, { force: true });
10512
+ }
10513
+ };
10514
+
10515
+ const FIVE_MINUTES = 5 * 60 * 1000;
10516
+
10517
+
10518
+
10519
+
10520
+
10521
+
10522
+
10523
+ const resolveExpiry = (expiresIn) =>
10524
+ expiresIn > 946684800 ? expiresIn * 1000 : Date.now() + expiresIn * 1000;
10525
+
10526
+ const parseJson = async (response) => {
10527
+ const text = await response.text();
10528
+ if (!text) {
10529
+ return {};
10530
+ }
10531
+ const parsed = safeJsonParse(text, {});
10532
+ return typeof parsed === 'object' && parsed !== null
10533
+ ? (parsed )
10534
+ : {};
10535
+ };
10536
+
10537
+ const isRecord$2 = (value) =>
10538
+ typeof value === 'object' && value !== null && !Array.isArray(value);
10539
+
10540
+ const getCurrentUser = async (
10541
+ config,
10542
+ options,
10543
+ ) => {
10544
+ const token = await getAccessToken(config, options);
10545
+ const response = await fetch(new URL('/v1/users/me', config.openApiBaseUrl), {
10546
+ headers: { authorization: `Bearer ${token}` },
10342
10547
  });
10548
+ const payload = await parseJson(response);
10549
+ if (!response.ok) {
10550
+ throw new CliError(
10551
+ typeof payload.msg === 'string'
10552
+ ? payload.msg
10553
+ : 'Unable to validate the current login. Run `coze-dev deploy auth login` again.',
10554
+ response.status === 401 ? 'AUTH_REQUIRED' : 'AUTH_STATUS_FAILED',
10555
+ { status: response.status },
10556
+ );
10557
+ }
10558
+ return isRecord$2(payload.data) ? payload.data : payload;
10559
+ };
10343
10560
 
10344
- // 监听未处理的 Promise rejection
10345
- process.on('unhandledRejection', async (reason) => {
10346
- const error = reason instanceof Error ? reason : new Error(String(reason));
10347
- reportError(error, {
10348
- type: 'unhandledRejection',
10349
- context: 'global',
10350
- });
10351
- await flushSlardar();
10352
- process.exit(1);
10561
+ const clearAuthPatch = {
10562
+ accessToken: undefined,
10563
+ refreshToken: undefined,
10564
+ tokenExpiresAt: undefined,
10565
+ organizationId: undefined,
10566
+ enterpriseId: undefined,
10567
+ spaceId: undefined,
10568
+ projectId: undefined,
10569
+ };
10570
+
10571
+ const getAccessToken = async (
10572
+ config,
10573
+ options,
10574
+ ) => {
10575
+ if (!config.accessToken) {
10576
+ throw new CliError(
10577
+ 'No shared login found. Run `coze-dev deploy auth login` first.',
10578
+ 'AUTH_REQUIRED',
10579
+ );
10580
+ }
10581
+ if (!config.refreshToken || !config.tokenExpiresAt) {
10582
+ return config.accessToken;
10583
+ }
10584
+ if (Date.now() < config.tokenExpiresAt - FIVE_MINUTES) {
10585
+ return config.accessToken;
10586
+ }
10587
+
10588
+ const response = await fetch(
10589
+ new URL('/api/permission/oauth2/token', config.openApiBaseUrl),
10590
+ {
10591
+ method: 'POST',
10592
+ headers: { 'content-type': 'application/json' },
10593
+ body: JSON.stringify({
10594
+ grant_type: 'refresh_token',
10595
+ client_id: config.clientId,
10596
+ refresh_token: config.refreshToken,
10597
+ }),
10598
+ },
10599
+ );
10600
+ const payload = await parseJson(response);
10601
+ if (!response.ok || typeof payload.access_token !== 'string') {
10602
+ throw new CliError(
10603
+ typeof payload.error_description === 'string'
10604
+ ? payload.error_description
10605
+ : 'Shared login has expired. Run `coze-dev deploy auth login` again.',
10606
+ 'AUTH_REFRESH_FAILED',
10607
+ );
10608
+ }
10609
+ const token = payload ;
10610
+ const patch = {
10611
+ accessToken: token.access_token,
10612
+ refreshToken: token.refresh_token || config.refreshToken,
10613
+ tokenExpiresAt: resolveExpiry(token.expires_in),
10614
+ };
10615
+ Object.assign(config, patch);
10616
+ await saveSharedConfig(patch, options);
10617
+ return token.access_token;
10618
+ };
10619
+
10620
+ const saveOAuthToken = async (
10621
+ config,
10622
+ options,
10623
+ token,
10624
+ ) => {
10625
+ const patch = {
10626
+ accessToken: token.access_token,
10627
+ refreshToken: token.refresh_token,
10628
+ tokenExpiresAt: resolveExpiry(token.expires_in),
10629
+ organizationId: undefined,
10630
+ enterpriseId: undefined,
10631
+ spaceId: undefined,
10632
+ projectId: undefined,
10633
+ };
10634
+ Object.assign(config, patch);
10635
+ await saveSharedConfig(patch, options);
10636
+ };
10637
+
10638
+ const logout = async (
10639
+ config,
10640
+ options,
10641
+ ) => {
10642
+ Object.assign(config, clearAuthPatch);
10643
+ await saveSharedConfig(clearAuthPatch, options);
10644
+ };
10645
+
10646
+ const getAuthStatus = async (
10647
+ config,
10648
+ options,
10649
+ ) => {
10650
+ if (!config.accessToken) {
10651
+ return { logged_in: false };
10652
+ }
10653
+ const user = await getCurrentUser(config, options);
10654
+ return {
10655
+ logged_in: true,
10656
+ user,
10657
+ token_expires_at: config.tokenExpiresAt
10658
+ ? new Date(config.tokenExpiresAt).toISOString()
10659
+ : 'Never (PAT)',
10660
+ };
10661
+ };
10662
+
10663
+ const DEFAULT_POLL_INTERVAL_MS = 5000;
10664
+ const SLOW_DOWN_INCREMENT_MS = 5000;
10665
+
10666
+ const isRecord$1 = (value) =>
10667
+ typeof value === 'object' && value !== null && !Array.isArray(value);
10668
+
10669
+ const readPayload = async (response) => {
10670
+ const text = await response.text();
10671
+ const payload = safeJsonParse(text, {});
10672
+ return isRecord$1(payload) ? payload : {};
10673
+ };
10674
+
10675
+ const post = async (
10676
+ baseUrl,
10677
+ path,
10678
+ body,
10679
+ ) => {
10680
+ const response = await fetch(new URL(path, baseUrl), {
10681
+ method: 'POST',
10682
+ headers: { 'content-type': 'application/json' },
10683
+ body: JSON.stringify(body),
10353
10684
  });
10685
+ return { payload: await readPayload(response), response };
10686
+ };
10354
10687
 
10355
- const program = new commander.Command();
10688
+ const requireString = (
10689
+ payload,
10690
+ key,
10691
+ ) => {
10692
+ const value = payload[key];
10693
+ if (typeof value !== 'string' || !value) {
10694
+ throw new CliError(`OAuth response returned no ${key}.`, 'INVALID_AUTH_RESPONSE');
10695
+ }
10696
+ return value;
10697
+ };
10356
10698
 
10357
- program
10358
- .name('coze-dev')
10359
- .description(
10360
- 'Coze Coding CLI - Project template engine for frontend stacks',
10361
- )
10362
- .version(packageJson.version);
10699
+ const requireNumber = (
10700
+ payload,
10701
+ key,
10702
+ ) => {
10703
+ const value = Number(payload[key]);
10704
+ if (!Number.isFinite(value) || value <= 0) {
10705
+ throw new CliError(`OAuth response returned no ${key}.`, 'INVALID_AUTH_RESPONSE');
10706
+ }
10707
+ return value;
10708
+ };
10363
10709
 
10364
- commands.forEach(initCmd => initCmd(program));
10710
+ const requestDeviceCode = async (config) => {
10711
+ const { payload, response } = await post(
10712
+ config.openApiBaseUrl,
10713
+ '/api/permission/oauth2/device/code',
10714
+ { client_id: config.clientId },
10715
+ );
10716
+ if (!response.ok) {
10717
+ throw new CliError(
10718
+ typeof payload.error_description === 'string'
10719
+ ? payload.error_description
10720
+ : 'Unable to start OAuth login.',
10721
+ 'AUTH_LOGIN_FAILED',
10722
+ { status: response.status },
10723
+ );
10724
+ }
10725
+ return {
10726
+ device_code: requireString(payload, 'device_code'),
10727
+ user_code: requireString(payload, 'user_code'),
10728
+ verification_uri: requireString(payload, 'verification_uri'),
10729
+ expires_in: requireNumber(payload, 'expires_in'),
10730
+ interval:
10731
+ typeof payload.interval === 'number' && payload.interval > 0
10732
+ ? payload.interval
10733
+ : undefined,
10734
+ };
10735
+ };
10365
10736
 
10366
- // help 输出中添加模板信息
10367
- program.addHelpText('after', generateTemplatesHelpText());
10737
+ const buildVerificationUrl = (deviceCode) => {
10738
+ const url = new URL(deviceCode.verification_uri);
10739
+ url.searchParams.set('user_code', deviceCode.user_code);
10740
+ return url.toString();
10741
+ };
10368
10742
 
10369
- // 使用 parseAsync 等待命令执行完成
10370
- await program.parseAsync(process.argv);
10743
+ const openBrowser = (url) => {
10744
+ const command =
10745
+ process.platform === 'darwin'
10746
+ ? 'open'
10747
+ : process.platform === 'win32'
10748
+ ? 'cmd'
10749
+ : 'xdg-open';
10750
+ const args = process.platform === 'win32' ? ['/c', 'start', '""', url] : [url];
10751
+ try {
10752
+ const child = node_child_process.spawn(command, args, { detached: true, stdio: 'ignore' });
10753
+ child.on('error', () => undefined);
10754
+ child.unref();
10755
+ } catch (error) {
10756
+ }
10757
+ };
10758
+
10759
+ const sleep = async (milliseconds) =>
10760
+ new Promise(resolve => setTimeout(resolve, milliseconds));
10761
+
10762
+ const pollToken = async (
10763
+ config,
10764
+ deviceCode,
10765
+ ) => {
10766
+ const expiresAt = Date.now() + deviceCode.expires_in * 1000;
10767
+ let interval = (deviceCode.interval || DEFAULT_POLL_INTERVAL_MS / 1000) * 1000;
10768
+ while (Date.now() < expiresAt) {
10769
+ const { payload, response } = await post(
10770
+ config.openApiBaseUrl,
10771
+ '/api/permission/oauth2/token',
10772
+ {
10773
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
10774
+ client_id: config.clientId,
10775
+ device_code: deviceCode.device_code,
10776
+ },
10777
+ );
10778
+ if (response.ok) {
10779
+ return {
10780
+ access_token: requireString(payload, 'access_token'),
10781
+ refresh_token: requireString(payload, 'refresh_token'),
10782
+ expires_in: requireNumber(payload, 'expires_in'),
10783
+ };
10784
+ }
10785
+ if (payload.error === 'authorization_pending') {
10786
+ await sleep(interval);
10787
+ continue;
10788
+ }
10789
+ if (payload.error === 'slow_down') {
10790
+ interval += SLOW_DOWN_INCREMENT_MS;
10791
+ await sleep(interval);
10792
+ continue;
10793
+ }
10794
+ throw new CliError(
10795
+ typeof payload.error_description === 'string'
10796
+ ? payload.error_description
10797
+ : 'OAuth authorization failed.',
10798
+ 'AUTH_LOGIN_FAILED',
10799
+ { oauth_error: payload.error, status: response.status },
10800
+ );
10801
+ }
10802
+ throw new CliError('OAuth authorization expired. Please try again.', 'AUTH_LOGIN_EXPIRED');
10803
+ };
10804
+
10805
+ const loginWithOAuth = async (
10806
+ config,
10807
+ options,
10808
+ callbacks,
10809
+ ) => {
10810
+ const deviceCode = await requestDeviceCode(config);
10811
+ const verificationUrl = buildVerificationUrl(deviceCode);
10812
+ callbacks.onVerification(verificationUrl);
10813
+ openBrowser(verificationUrl);
10814
+ await saveOAuthToken(config, options, await pollToken(config, deviceCode));
10815
+ };
10816
+
10817
+ 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; }
10818
+
10819
+
10820
+
10821
+
10822
+
10823
+
10824
+
10825
+
10826
+
10827
+
10828
+
10829
+
10830
+
10831
+
10832
+
10833
+
10834
+
10835
+ const API_PREFIX = '/api/coding/deployment/v2';
10836
+ const CREATE_PROJECT_PATH = '/api/ideserver_api/project/create_vibe_project';
10837
+ const LIST_SPACES_PATH = '/api/playground_api/space/list';
10838
+ const ENCRYPT_PROJECT_SECRET_PATH =
10839
+ '/api/permission_api/project_secret/encrypt_project_secret';
10840
+ const MAX_MESSAGE_LENGTH = 512;
10841
+
10842
+ const isRecord = (value) =>
10843
+ typeof value === 'object' && value !== null && !Array.isArray(value);
10844
+
10845
+
10846
+
10847
+
10848
+
10849
+
10850
+
10851
+ const parseResponse = async (response) => {
10852
+ const text = await response.text();
10853
+ if (!text) {
10854
+ return { payload: {}, text, validJson: true };
10855
+ }
10856
+ const invalid = Symbol('invalid-json');
10857
+ const parsed = safeJsonParse(text, invalid);
10858
+ return parsed === invalid
10859
+ ? { payload: undefined, text, validJson: false }
10860
+ : { payload: parsed, text, validJson: true };
10861
+ };
10862
+
10863
+
10864
+
10865
+
10866
+
10867
+
10868
+
10869
+
10870
+
10871
+ const responseExcerpt = (text) => {
10872
+ const compact = text.replace(/\s+/gu, ' ').trim();
10873
+ return compact ? compact.slice(0, MAX_MESSAGE_LENGTH) : undefined;
10874
+ };
10875
+
10876
+ const unwrap = (
10877
+ payload,
10878
+ expectedKey,
10879
+ responseMetadata,
10880
+ ) => {
10881
+ const root = isRecord(payload) ? payload : undefined;
10882
+ const first = isRecord(_optionalChain$9([root, 'optionalAccess', _ => _.data])) ? root.data : undefined;
10883
+ const second = isRecord(_optionalChain$9([first, 'optionalAccess', _2 => _2.data])) ? first.data : undefined;
10884
+ const envelope = [root, first].find(candidate => candidate && 'code' in candidate);
10885
+ if (_optionalChain$9([envelope, 'optionalAccess', _3 => _3.code]) !== undefined && Number(envelope.code) !== 0) {
10886
+ throw new CliError(
10887
+ typeof envelope.msg === 'string'
10888
+ ? envelope.msg.slice(0, MAX_MESSAGE_LENGTH)
10889
+ : 'The deployment request was rejected.',
10890
+ 'API_REJECTED',
10891
+ { business_code: envelope.code, ...responseMetadata },
10892
+ );
10893
+ }
10894
+ if (!expectedKey) {
10895
+ return (second || first || root || {}) ;
10896
+ }
10897
+ const matched = [second, first, root].find(
10898
+ candidate => candidate && expectedKey in candidate,
10899
+ );
10900
+ if (!matched) {
10901
+ throw new CliError(
10902
+ `Deployment API returned no ${expectedKey}.`,
10903
+ 'INVALID_RESPONSE',
10904
+ );
10905
+ }
10906
+ return matched ;
10907
+ };
10908
+
10909
+ class DeployApiClient {
10910
+ constructor(
10911
+ config,
10912
+ globalOptions,
10913
+ ) {this.config = config;this.globalOptions = globalOptions;}
10914
+
10915
+ debug(message) {
10916
+ if (this.globalOptions.debug) {
10917
+ process.stderr.write(`[debug] [api] ${message}\n`);
10918
+ }
10919
+ }
10920
+
10921
+ async post(
10922
+ path,
10923
+ body,
10924
+ expectedKey,
10925
+ useApiPrefix = true,
10926
+ ) {
10927
+ const token = await getAccessToken(this.config, this.globalOptions);
10928
+ const headers = {
10929
+ authorization: `Bearer ${token}`,
10930
+ 'content-type': 'application/json',
10931
+ 'agw-js-conv': 'str',
10932
+ 'x-request-from-coze-cli': '1',
10933
+ };
10934
+ if (this.config.organizationId) {
10935
+ headers['x-coze-account'] = this.config.organizationId;
10936
+ }
10937
+ const lane = _optionalChain$9([this, 'access', _4 => _4.globalOptions, 'access', _5 => _5.lane, 'optionalAccess', _6 => _6.trim, 'call', _7 => _7()]) || _optionalChain$9([this, 'access', _8 => _8.config, 'access', _9 => _9.xTTEnv, 'optionalAccess', _10 => _10.trim, 'call', _11 => _11()]);
10938
+ if (lane) {
10939
+ headers['x-use-ppe'] = '1';
10940
+ headers['x-tt-env'] = lane;
10941
+ }
10942
+ const requestUrl = new URL(
10943
+ `${useApiPrefix ? API_PREFIX : ''}${path}`,
10944
+ this.config.apiBaseUrl,
10945
+ );
10946
+ this.debug(
10947
+ `POST ${requestUrl.toString()}${lane ? ` lane=${lane}` : ''}`,
10948
+ );
10949
+ const response = await fetch(
10950
+ requestUrl,
10951
+ { method: 'POST', headers, body: JSON.stringify(body) },
10952
+ );
10953
+ const responseMetadata = {
10954
+ status: response.status,
10955
+ status_text: response.statusText,
10956
+ log_id: response.headers.get('x-tt-logid') || undefined,
10957
+ request_path: requestUrl.pathname,
10958
+ content_type: response.headers.get('content-type') || undefined,
10959
+ };
10960
+ this.debug(
10961
+ `${response.status} ${response.statusText} ${requestUrl.pathname}` +
10962
+ `${responseMetadata.log_id ? ` log_id=${responseMetadata.log_id}` : ' log_id=unavailable'}`,
10963
+ );
10964
+ const { payload, text, validJson } = await parseResponse(response);
10965
+ if (!response.ok) {
10966
+ const root = isRecord(payload) ? payload : undefined;
10967
+ throw new CliError(
10968
+ typeof _optionalChain$9([root, 'optionalAccess', _12 => _12.msg]) === 'string'
10969
+ ? root.msg.slice(0, MAX_MESSAGE_LENGTH)
10970
+ : `Deployment API failed: ${response.status} ${response.statusText}` +
10971
+ `${validJson ? '' : '; response was not JSON'}`,
10972
+ response.status === 401 ? 'AUTH_REQUIRED' : 'HTTP_ERROR',
10973
+ {
10974
+ ...responseMetadata,
10975
+ response_excerpt: responseExcerpt(text),
10976
+ },
10977
+ );
10978
+ }
10979
+ if (!validJson) {
10980
+ throw new CliError(
10981
+ `Deployment API returned invalid JSON (${response.status}).`,
10982
+ 'INVALID_RESPONSE',
10983
+ {
10984
+ ...responseMetadata,
10985
+ response_excerpt: responseExcerpt(text),
10986
+ },
10987
+ );
10988
+ }
10989
+ return unwrap(payload, expectedKey, responseMetadata);
10990
+ }
10991
+
10992
+ createDeploymentProject(body) {
10993
+ return this.post(
10994
+ CREATE_PROJECT_PATH,
10995
+ body,
10996
+ 'project_id',
10997
+ false,
10998
+ );
10999
+ }
11000
+
11001
+ listSpaces(body
11002
+
11003
+
11004
+
11005
+
11006
+ ) {
11007
+ return this.post(
11008
+ LIST_SPACES_PATH,
11009
+ body,
11010
+ 'bot_space_list',
11011
+ false,
11012
+ );
11013
+ }
11014
+
11015
+ encryptProjectSecret(projectId, secrets) {
11016
+ return this.post(
11017
+ ENCRYPT_PROJECT_SECRET_PATH,
11018
+ {
11019
+ project_id: projectId,
11020
+ encrypt_secrets: {
11021
+ secrets,
11022
+ cred_providers: [],
11023
+ },
11024
+ },
11025
+ 'sealed_secrets',
11026
+ false,
11027
+ );
11028
+ }
11029
+
11030
+ // 列当前登录用户名下的 Application,跨 Project。服务端从登录态取 user_id,
11031
+ // 请求体里只有分页参数(deploy_app/list 已去掉 project_id / user_id 两个寻址入参)。
11032
+ listApplications(body) {
11033
+ return this.post(
11034
+ '/deploy_app/list', body, 'items',
11035
+ );
11036
+ }
11037
+
11038
+ getApplication(appId) {
11039
+ return this.post('/deploy_app/get', { app_id: appId }, 'app_id');
11040
+ }
11041
+
11042
+ updateApplication(body) {
11043
+ return this.post('/deploy_app/update', body, 'app_id');
11044
+ }
11045
+
11046
+ // 删除 Application:服务端只接受 **Stopped** 状态,其余状态会带上当前状态报错(先 stop 再 delete)。
11047
+ // 已删除的再删一次是幂等成功。
11048
+ deleteApplication(appId) {
11049
+ return this.post('/deploy_app/delete', { app_id: appId });
11050
+ }
11051
+
11052
+ getDeployConfig(body
11053
+
11054
+
11055
+
11056
+
11057
+
11058
+ ) {
11059
+ return this.post('/deploy_config/get', body, 'deploy_config');
11060
+ }
11061
+
11062
+ createDeployHistory(body) {
11063
+ return this.post('/deploy_history/create', body, 'app_id');
11064
+ }
11065
+
11066
+ preDeployUpload(body
11067
+
11068
+
11069
+ ) {
11070
+ return this.post('/deploy_history/pre_upload', body, 'upload_url');
11071
+ }
11072
+
11073
+ getDeployHistory(body) {
11074
+ return this.post('/deploy_history/get', body, 'deploy_history_id');
11075
+ }
11076
+
11077
+ listDeployHistory(body) {
11078
+ return this.post
11079
+
11080
+
11081
+
11082
+ ('/deploy_history/list', body, 'deploy_history_list');
11083
+ }
11084
+
11085
+ getOnlineDeployHistory(appId) {
11086
+ return this.post(
11087
+ '/deploy_history/get_online', { app_id: appId }, 'deploy_history_list',
11088
+ );
11089
+ }
11090
+
11091
+ checkRollbackDatabase(body) {
11092
+ return this.post(
11093
+ '/deploy_history/check_rollback_database', body, 'is_rollback_possible',
11094
+ );
11095
+ }
11096
+
11097
+ cancelDeployHistory(body) {
11098
+ return this.post('/deploy_history/cancel', body);
11099
+ }
11100
+
11101
+ rollbackDeployHistory(body
11102
+
11103
+
11104
+
11105
+ ) {
11106
+ return this.post(
11107
+ '/deploy_history/rollback', body, 'new_deploy_history_id',
11108
+ );
11109
+ }
11110
+
11111
+ stopApplication(appId) {
11112
+ return this.post('/application/stop', { app_id: appId });
11113
+ }
11114
+
11115
+ resumeApplication(appId) {
11116
+ return this.post('/application/resume', { app_id: appId });
11117
+ }
11118
+
11119
+ // 暂停是可逆的:只把线上 Unit 从 Ready 改成 Paused,函数留着,可被 resume 推回 Ready。
11120
+ // stop 会连函数一起删、落到 Stopped,只能靠重新部署恢复 —— resume 配对的是 pause,不是 stop。
11121
+ pauseApplication(appId) {
11122
+ return this.post('/application/pause', { app_id: appId });
11123
+ }
11124
+
11125
+ // PV / UV。入参是 app_id,但服务端反查 project_id 后按 **Project** 聚合 —— 埋点链路只有
11126
+ // project 维度,同一 Project 下多个 Application 拿到的是同一份数据。
11127
+ getUserAnalyticsMetrics(body) {
11128
+ return this.post(
11129
+ '/metrics/user_analytics/get', body, 'charts',
11130
+ );
11131
+ }
11132
+
11133
+ getBuildLog(body) {
11134
+ return this.post('/deploy_history/log', body, 'log');
11135
+ }
11136
+
11137
+ searchRuntimeLog(body) {
11138
+ return this.post(
11139
+ '/runtime_log/search', body, 'logs',
11140
+ );
11141
+ }
11142
+
11143
+ getRuntimeLogCount(appId) {
11144
+ return this.post(
11145
+ '/runtime_log/count', { app_id: appId }, 'limit',
11146
+ );
11147
+ }
11148
+
11149
+ getDeployCount(appId) {
11150
+ return this.post(
11151
+ '/deploy_history/get_count', { app_id: appId }, 'success_count',
11152
+ );
11153
+ }
11154
+
11155
+ getApplicationMetrics(body) {
11156
+ return this.post(
11157
+ '/metrics/get', body, 'charts',
11158
+ );
11159
+ }
11160
+
11161
+ getHostedUsageMonthly(body) {
11162
+ return this.post(
11163
+ '/hosted_usage/monthly', body, 'summary',
11164
+ );
11165
+ }
11166
+
11167
+ listDomains(appId, unitType) {
11168
+ return this.post(
11169
+ '/domain/list', {
11170
+ app_id: appId,
11171
+ ...(unitType === undefined ? {} : { unit_type: unitType }),
11172
+ }, 'items',
11173
+ );
11174
+ }
11175
+
11176
+ createDomain(body) {
11177
+ return this.post('/domain/create', body, 'domain');
11178
+ }
11179
+
11180
+ // 改的是系统分配的 <prefix>.coze.site 里的 prefix,不是 createDomain 加进来的自定义域名 ——
11181
+ // 那类域名服务端只提供 create/delete,域名串本身不可改。
11182
+ updateDefaultDomainPrefix(body) {
11183
+ return this.post
11184
+
11185
+
11186
+
11187
+
11188
+ ('/domain/update_default_prefix', body, 'new_domain_host_canonical');
11189
+ }
11190
+
11191
+ getMiniProgramAuthStatus(body) {
11192
+ return this.post
11193
+
11194
+
11195
+
11196
+
11197
+ ('/api/coding/deployment/auth/status', body, 'is_authorized', false);
11198
+ }
11199
+
11200
+ bindMiniProgramAuth(body
11201
+
11202
+
11203
+
11204
+
11205
+
11206
+ ) {
11207
+ return this.post
11208
+
11209
+
11210
+
11211
+
11212
+
11213
+
11214
+ ('/api/coding/deployment/auth/bind', body, 'bind_status', false);
11215
+ }
11216
+
11217
+ submitMiniProgramAuthCode(body
11218
+
11219
+
11220
+
11221
+
11222
+
11223
+ ) {
11224
+ return this.post(
11225
+ '/api/coding/deployment/auth/submit_code', body, undefined, false,
11226
+ );
11227
+ }
11228
+
11229
+ unbindMiniProgramAuth(body) {
11230
+ return this.post(
11231
+ '/api/coding/deployment/auth/unbind', body, undefined, false,
11232
+ );
11233
+ }
11234
+ }
11235
+
11236
+ const textValue = (value) => {
11237
+ if (typeof value === 'string') {
11238
+ return value;
11239
+ }
11240
+ return JSON.stringify(value, null, 2);
11241
+ };
11242
+
11243
+ class Output {
11244
+ constructor(
11245
+ format,
11246
+ debugEnabled = false,
11247
+ ) {this.format = format;this.debugEnabled = debugEnabled;}
11248
+
11249
+ print(value) {
11250
+ process.stdout.write(
11251
+ this.format === 'json'
11252
+ ? `${JSON.stringify(value, null, 2)}\n`
11253
+ : `${textValue(value)}\n`,
11254
+ );
11255
+ }
11256
+
11257
+ info(message) {
11258
+ if (this.format === 'text') {
11259
+ process.stderr.write(`${message}\n`);
11260
+ }
11261
+ }
11262
+
11263
+ notice(message) {
11264
+ process.stderr.write(`${message}\n`);
11265
+ }
11266
+
11267
+ warn(message) {
11268
+ process.stderr.write(`Warning: ${message}\n`);
11269
+ }
11270
+
11271
+ debug(message) {
11272
+ if (this.debugEnabled) {
11273
+ process.stderr.write(`[debug] ${message}\n`);
11274
+ }
11275
+ }
11276
+ }
11277
+
11278
+ const runtimes = new WeakMap();
11279
+
11280
+ const getRuntime = async (command) => {
11281
+ const deploy = findDeployCommand(command);
11282
+ let runtime = runtimes.get(deploy);
11283
+ if (!runtime) {
11284
+ runtime = (async () => {
11285
+ const options = deploy.opts();
11286
+ const config = await loadConfig(options);
11287
+ return {
11288
+ client: new DeployApiClient(config, options),
11289
+ config,
11290
+ cwd: process.cwd(),
11291
+ globalOptions: options,
11292
+ output: new Output(options.format || 'json', options.debug),
11293
+ };
11294
+ })();
11295
+ runtimes.set(deploy, runtime);
11296
+ }
11297
+ return runtime;
11298
+ };
11299
+
11300
+ const PRIVACY_POLICY_URL = 'https://docs.coze.cn/guides/privacy';
11301
+ const TERMS_OF_SERVICE_URL = 'https://docs.coze.cn/guides/terms-of-service';
11302
+
11303
+ const registerAuth = (program) => {
11304
+ const auth = program.command('auth').description('Manage deployment CLI authentication');
11305
+
11306
+ auth
11307
+ .command('login')
11308
+ .description('Login with Coze OAuth and save shared credentials')
11309
+ .action(async (_options, command) => {
11310
+ const runtime = await getRuntime(command);
11311
+ await loginWithOAuth(runtime.config, runtime.globalOptions, {
11312
+ onVerification: url => {
11313
+ runtime.output.notice(
11314
+ [
11315
+ 'Open this URL to authorize coze-dev deploy:',
11316
+ url,
11317
+ `Privacy Policy: ${PRIVACY_POLICY_URL}`,
11318
+ `Terms of Service: ${TERMS_OF_SERVICE_URL}`,
11319
+ ].join('\n'),
11320
+ );
11321
+ },
11322
+ });
11323
+ runtime.output.print({ success: true, logged_in: true, method: 'OAuth' });
11324
+ });
11325
+
11326
+ auth
11327
+ .command('status')
11328
+ .description('Check and refresh the current shared login')
11329
+ .action(async (_options, command) => {
11330
+ const runtime = await getRuntime(command);
11331
+ runtime.output.print(await getAuthStatus(runtime.config, runtime.globalOptions));
11332
+ });
11333
+
11334
+ auth
11335
+ .command('logout')
11336
+ .description('Clear shared credentials and account context')
11337
+ .action(async (_options, command) => {
11338
+ const runtime = await getRuntime(command);
11339
+ await logout(runtime.config, runtime.globalOptions);
11340
+ runtime.output.print({ success: true, logged_out: true });
11341
+ });
11342
+ };
11343
+
11344
+ const execFileAsync = node_util.promisify(node_child_process.execFile);
11345
+
11346
+ const registerContext = (program) => {
11347
+ const context = program.command('context').description('Show or update deployment context');
11348
+ context.command('show').action(async (_options, command) => {
11349
+ const runtime = await getRuntime(command);
11350
+ runtime.output.print({
11351
+ organization_id: runtime.config.organizationId,
11352
+ space_id: runtime.config.spaceId,
11353
+ project_id: runtime.config.projectId,
11354
+ lane: runtime.globalOptions.lane || runtime.config.xTTEnv,
11355
+ config_path: runtime.globalOptions.config || getSharedConfigPath(),
11356
+ });
11357
+ });
11358
+ context
11359
+ .command('use')
11360
+ .option('--space-id <spaceId>', 'Default Space ID')
11361
+ .option('--project-id <projectId>', 'Default Project ID')
11362
+ .action(async (options, command) => {
11363
+ const runtime = await getRuntime(command);
11364
+ await saveSharedConfig(
11365
+ {
11366
+ ...(options.spaceId ? { spaceId: options.spaceId } : {}),
11367
+ ...(options.projectId ? { projectId: options.projectId } : {}),
11368
+ },
11369
+ runtime.globalOptions,
11370
+ );
11371
+ runtime.output.print({
11372
+ space_id: options.spaceId || runtime.config.spaceId,
11373
+ project_id: options.projectId || runtime.config.projectId,
11374
+ });
11375
+ });
11376
+ };
11377
+
11378
+ const registerDoctor = (program) => {
11379
+ program
11380
+ .command('doctor')
11381
+ .description('Check deployment CLI prerequisites and shared login')
11382
+ .action(async (_options, command) => {
11383
+ const runtime = await getRuntime(command);
11384
+ let gitAvailable = true;
11385
+ try {
11386
+ await execFileAsync('git', ['--version']);
11387
+ } catch (e) {
11388
+ gitAvailable = false;
11389
+ }
11390
+ runtime.output.print({
11391
+ ok: gitAvailable && Boolean(runtime.config.accessToken),
11392
+ git: gitAvailable ? 'ok' : 'missing',
11393
+ login: runtime.config.accessToken ? 'reused' : 'missing',
11394
+ login_config: runtime.globalOptions.config || getSharedConfigPath(),
11395
+ project_id: runtime.config.projectId || 'not configured',
11396
+ });
11397
+ });
11398
+ };
11399
+
11400
+ 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; }
11401
+
11402
+
11403
+
11404
+
11405
+
11406
+
11407
+
11408
+
11409
+
11410
+
11411
+
11412
+
11413
+
11414
+
11415
+
11416
+
11417
+
11418
+
11419
+
11420
+
11421
+
11422
+
11423
+
11424
+
11425
+
11426
+
11427
+
11428
+
11429
+
11430
+ const getDeployParentOptions = (command) =>
11431
+ _optionalChain$8([command, 'access', _ => _.parent, 'optionalAccess', _2 => _2.opts, 'call', _3 => _3()]) || {};
11432
+
11433
+ const getDeployAppIdOption = (
11434
+ options,
11435
+ command,
11436
+ ) => options.appId || getDeployParentOptions(command).appId;
11437
+
11438
+ const getCreateDeployConfig = (config) => ({
11439
+ deploy_config: {
11440
+ cpu: config.deploy_config.cpu,
11441
+ memory_mb: config.deploy_config.memory_mb,
11442
+ max_instance: config.deploy_config.max_instance,
11443
+ max_concurrency: config.deploy_config.max_concurrency,
11444
+ },
11445
+ service_type: config.deploy_config.service_type,
11446
+ ...(config.deploy_config.computer_id
11447
+ ? { computer_id: config.deploy_config.computer_id }
11448
+ : {}),
11449
+ });
11450
+
11451
+ const DEPLOY_STATUS = {
11452
+ pending: 1,
11453
+ running: 2,
11454
+ succeeded: 3,
11455
+ failed: 4,
11456
+ canceled: 5,
11457
+ interrupted: 6,
11458
+ preDeploy: 7,
11459
+ } ;
11460
+
11461
+ const STATUS_NAMES = {
11462
+ [DEPLOY_STATUS.pending]: 'Pending',
11463
+ [DEPLOY_STATUS.running]: 'Running',
11464
+ [DEPLOY_STATUS.succeeded]: 'Succeeded',
11465
+ [DEPLOY_STATUS.failed]: 'Failed',
11466
+ [DEPLOY_STATUS.canceled]: 'Canceled',
11467
+ [DEPLOY_STATUS.interrupted]: 'Interrupted',
11468
+ [DEPLOY_STATUS.preDeploy]: 'WaitingForUpload',
11469
+ };
11470
+
11471
+ const TERMINAL_STATUSES = new Set([
11472
+ DEPLOY_STATUS.succeeded,
11473
+ DEPLOY_STATUS.failed,
11474
+ DEPLOY_STATUS.canceled,
11475
+ DEPLOY_STATUS.interrupted,
11476
+ ]);
11477
+
11478
+ const getDeployStatusText = (status) =>
11479
+ status ? STATUS_NAMES[status] || 'Unknown' : 'Unknown';
11480
+
11481
+ 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; }
11482
+
11483
+ const formatDeployDetails = (history) =>
11484
+ (_optionalChain$7([history, 'optionalAccess', _ => _.deploy_detail]) || []).map(detail => ({
11485
+ target: detail.target,
11486
+ status: getDeployStatusText(detail.status),
11487
+ deploy_log_key: detail.deploy_log_key,
11488
+ deploy_log_url: detail.deploy_log_url,
11489
+ }));
11490
+
11491
+ const getDeployLogKeys = (history) =>
11492
+ [...new Set(
11493
+ (history.deploy_detail || [])
11494
+ .map(detail => _optionalChain$7([detail, 'access', _2 => _2.deploy_log_key, 'optionalAccess', _3 => _3.trim, 'call', _4 => _4()]))
11495
+ .filter((key) => Boolean(key)),
11496
+ )];
11497
+
11498
+ const normalizePositiveId = (value) => {
11499
+ const normalized = value === undefined ? '' : String(value).trim();
11500
+ return /^[1-9]\d*$/.test(normalized) ? normalized : undefined;
11501
+ };
11502
+
11503
+ const resolveDeployHistoryId = (
11504
+ deployHistoryId,
11505
+ previousDeployHistoryId,
11506
+ ) =>
11507
+ normalizePositiveId(deployHistoryId) || normalizePositiveId(previousDeployHistoryId);
11508
+
11509
+ 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; }
11510
+
11511
+ const SOURCE_SNAPSHOT_BYTES = 20;
11512
+
11513
+ const isId = (value) =>
11514
+ typeof value === 'string' && /^\d+$/u.test(value);
11515
+
11516
+
11517
+ const resolveAppId = async (cwd, appId) => {
11518
+ const explicit = _optionalChain$6([appId, 'optionalAccess', _ => _.trim, 'call', _2 => _2()]);
11519
+ if (explicit) {
11520
+ return explicit;
11521
+ }
11522
+ try {
11523
+ return (await readProjectMetadata(node_path.resolve(cwd))).appId;
11524
+ } catch (error) {
11525
+ if ((error ).code === 'COZE_FILE_NOT_FOUND') {
11526
+ return undefined;
11527
+ }
11528
+ throw error;
11529
+ }
11530
+ };
11531
+
11532
+ const requireAppId = async (cwd, appId) => {
11533
+ const resolved = await resolveAppId(cwd, appId);
11534
+ if (!resolved) {
11535
+ throw new CliError(
11536
+ 'Application ID is required. Pass --app-id or use a directory whose .coze [project] contains app_id.',
11537
+ 'APP_ID_REQUIRED',
11538
+ );
11539
+ }
11540
+ return resolved;
11541
+ };
11542
+
11543
+ const resolveSourceSnapshot = (sourceRootInput) => {
11544
+ const sourceRoot = node_path.resolve(sourceRootInput);
11545
+ const commitHash = node_crypto.randomBytes(SOURCE_SNAPSHOT_BYTES).toString('hex');
11546
+ return { commitHash, sourceRoot };
11547
+ };
11548
+
11549
+ const readProjectMetadata = async (
11550
+ sourceRoot,
11551
+ ) => {
11552
+ let cozeFileContent = '';
11553
+ try {
11554
+ cozeFileContent = await promises.readFile(node_path.join(sourceRoot, '.coze'), 'utf8');
11555
+ } catch (error) {
11556
+ if ((error ).code === 'ENOENT') {
11557
+ throw new CliError(
11558
+ `No .coze file found in ${sourceRoot}.`,
11559
+ 'COZE_FILE_NOT_FOUND',
11560
+ );
11561
+ }
11562
+ throw error;
11563
+ }
11564
+ const projectSection = _optionalChain$6([cozeFileContent, 'access', _3 => _3.match, 'call', _4 => _4(
11565
+ /^\s*\[project\]\s*(?:#.*)?$([\s\S]*?)(?=^\s*\[[^\]]+\]\s*(?:#.*)?$|(?![\s\S]))/mu,
11566
+ ), 'optionalAccess', _5 => _5[1]]);
11567
+ const readProjectString = (key) =>
11568
+ _optionalChain$6([projectSection
11569
+ , 'optionalAccess', _6 => _6.match, 'call', _7 => _7(new RegExp(`^\\s*${key}\\s*=\\s*["']([^"']+)["']`, 'mu')), 'optionalAccess', _8 => _8[1]
11570
+ , 'optionalAccess', _9 => _9.trim, 'call', _10 => _10()]);
11571
+ const name = readProjectString('name');
11572
+ const projectType = readProjectString('project_type');
11573
+ const projectId = readProjectString('project_id');
11574
+ const appId = readProjectString('app_id');
11575
+ const hasUnquotedId = (key) =>
11576
+ Boolean(_optionalChain$6([projectSection, 'optionalAccess', _11 => _11.match, 'call', _12 => _12(new RegExp(`^\\s*${key}\\s*=\\s*(?!["'])\\S+`, 'mu'))]));
11577
+ if (hasUnquotedId('project_id') || hasUnquotedId('app_id')) {
11578
+ throw new CliError(
11579
+ '.coze [project].project_id and app_id must be quoted decimal strings.',
11580
+ 'INVALID_COZE_FILE',
11581
+ );
11582
+ }
11583
+ if (projectId && !isId(projectId)) {
11584
+ throw new CliError('.coze [project].project_id must be a quoted decimal string.', 'INVALID_COZE_FILE');
11585
+ }
11586
+ if (appId && !isId(appId)) {
11587
+ throw new CliError('.coze [project].app_id must be a quoted decimal string.', 'INVALID_COZE_FILE');
11588
+ }
11589
+ return { name, projectType, projectId, appId, cozeFileContent };
11590
+ };
11591
+
11592
+ const updateProjectValue = (content, key, value) => {
11593
+ const sectionMatch = /^\s*\[project\]\s*(?:#.*)?$/mu.exec(content);
11594
+ if (!sectionMatch || sectionMatch.index === undefined) {
11595
+ const prefix = `[project]\n${key} = ${JSON.stringify(value)}\n\n`;
11596
+ return `${prefix}${content}`;
11597
+ }
11598
+ const sectionStart = sectionMatch.index + sectionMatch[0].length;
11599
+ const following = content.slice(sectionStart);
11600
+ const nextSection = /^\s*\[[^\]]+\]\s*(?:#.*)?$/mu.exec(following);
11601
+ const sectionEnd = _optionalChain$6([nextSection, 'optionalAccess', _13 => _13.index]) === undefined
11602
+ ? content.length
11603
+ : sectionStart + nextSection.index;
11604
+ const before = content.slice(0, sectionStart);
11605
+ let body = content.slice(sectionStart, sectionEnd);
11606
+ const keyPattern = new RegExp(`^(\\s*)${key}\\s*=.*$`, 'mu');
11607
+ if (keyPattern.test(body)) {
11608
+ body = body.replace(keyPattern, `$1${key} = ${JSON.stringify(value)}`);
11609
+ } else {
11610
+ const separator = body.startsWith('\n') || body.startsWith('\r\n') ? '' : '\n';
11611
+ body = `${separator}${body}`;
11612
+ const trailingNewline = body.endsWith('\n') ? '' : '\n';
11613
+ body = `${body}${trailingNewline}${key} = ${JSON.stringify(value)}\n`;
11614
+ }
11615
+ return `${before}${body}${content.slice(sectionEnd)}`;
11616
+ };
11617
+
11618
+ const writeProjectBinding = async (
11619
+ sourceRoot,
11620
+ binding,
11621
+ ) => {
11622
+ const path = node_path.join(sourceRoot, '.coze');
11623
+ let content = await promises.readFile(path, 'utf8');
11624
+ if (binding.projectId) {
11625
+ content = updateProjectValue(content, 'project_id', binding.projectId);
11626
+ }
11627
+ if (binding.appId) {
11628
+ content = updateProjectValue(content, 'app_id', binding.appId);
11629
+ }
11630
+ const tempPath = node_path.join(node_path.dirname(path), `.coze-${node_crypto.randomUUID()}.tmp`);
11631
+ try {
11632
+ await promises.writeFile(tempPath, content, { encoding: 'utf8', mode: 0o600 });
11633
+ await promises.rename(tempPath, path);
11634
+ } finally {
11635
+ await promises.rm(tempPath, { force: true });
11636
+ }
11637
+ return readProjectMetadata(sourceRoot);
11638
+ };
11639
+
11640
+ const ensureProjectMetadata = async (
11641
+ sourceRoot,
11642
+ options,
11643
+ ) => {
11644
+ try {
11645
+ return await readProjectMetadata(sourceRoot);
11646
+ } catch (error) {
11647
+ if ((error ).code !== 'COZE_FILE_NOT_FOUND' || !options.allowCreate) {
11648
+ throw error;
11649
+ }
11650
+ }
11651
+ const name = _optionalChain$6([options, 'access', _14 => _14.name, 'optionalAccess', _15 => _15.trim, 'call', _16 => _16()]) || 'Pages application';
11652
+ const projectType = _optionalChain$6([options, 'access', _17 => _17.projectType, 'optionalAccess', _18 => _18.trim, 'call', _19 => _19()]) || 'web';
11653
+ await promises.writeFile(
11654
+ node_path.join(sourceRoot, '.coze'),
11655
+ `[project]\nname = ${JSON.stringify(name)}\nproject_type = ${JSON.stringify(projectType)}\n`,
11656
+ { encoding: 'utf8', mode: 0o600 },
11657
+ );
11658
+ return readProjectMetadata(sourceRoot);
11659
+ };
11660
+
11661
+ 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; }
11662
+ const isFile = async (path) => {
11663
+ try {
11664
+ return (await promises.stat(path)).isFile();
11665
+ } catch (error) {
11666
+ if ((error ).code === 'ENOENT') {
11667
+ return false;
11668
+ }
11669
+ throw error;
11670
+ }
11671
+ };
11672
+
11673
+ const validatePagesSource = async (
11674
+ sourceRoot,
11675
+ cozeFileContent,
11676
+ ) => {
11677
+ if (await isFile(node_path.join(sourceRoot, 'index.html'))) {
11678
+ return;
11679
+ }
11680
+
11681
+ let config;
11682
+ try {
11683
+ config = TOML.parse(cozeFileContent);
11684
+ } catch (error) {
11685
+ throw new CliError(
11686
+ `Unable to parse .coze: ${error instanceof Error ? error.message : String(error)}`,
11687
+ 'INVALID_COZE_FILE',
11688
+ );
11689
+ }
11690
+ const project = config.project ;
11691
+ if (typeof _optionalChain$5([project, 'optionalAccess', _ => _.template]) !== 'string' || project.template.trim().toLowerCase() !== 'nextjs') {
11692
+ throw new CliError(
11693
+ 'Pages source contains no index.html; .coze project.template must be "nextjs".',
11694
+ 'PAGES_BUILD_CONFIG_REQUIRED',
11695
+ );
11696
+ }
11697
+ const deploy = config.deploy ;
11698
+ const build = _optionalChain$5([deploy, 'optionalAccess', _2 => _2.build]);
11699
+ if (!Array.isArray(build) || build.length === 0 || !build.every(part => typeof part === 'string' && part.length > 0)) {
11700
+ throw new CliError(
11701
+ 'Pages source contains no index.html; .coze deploy.build must be a non-empty string array.',
11702
+ 'PAGES_BUILD_CONFIG_REQUIRED',
11703
+ );
11704
+ }
11705
+ };
11706
+
11707
+ const readDeployLocalContext = async (
11708
+ sourceRoot,
11709
+ requestedApplicationType,
11710
+ appId,
11711
+ client,
11712
+ ) => {
11713
+ const sourceSnapshot = resolveSourceSnapshot(sourceRoot);
11714
+ let applicationTypeHint = requestedApplicationType;
11715
+ let effectiveAppId = appId;
11716
+ if (!effectiveAppId) {
11717
+ try {
11718
+ effectiveAppId = (await ensureProjectMetadata(sourceRoot, { allowCreate: false })).appId;
11719
+ } catch (error) {
11720
+ if ((error ).code !== 'COZE_FILE_NOT_FOUND') {
11721
+ throw error;
11722
+ }
11723
+ }
11724
+ }
11725
+ if (!applicationTypeHint && effectiveAppId) {
11726
+ applicationTypeHint = (await client.getApplication(effectiveAppId)).application_type;
11727
+ }
11728
+ const isPagesDeployment = applicationTypeHint === 'pages';
11729
+ const metadata = await ensureProjectMetadata(sourceRoot, {
11730
+ allowCreate: isPagesDeployment,
11731
+ projectType: isPagesDeployment ? 'web' : undefined,
11732
+ });
11733
+ if (isPagesDeployment) {
11734
+ await validatePagesSource(sourceRoot, metadata.cozeFileContent);
11735
+ }
11736
+ return { ...sourceSnapshot, metadata, isPagesDeployment };
11737
+ };
11738
+
11739
+ const registerDeployReadCommands = (deploy) => {
11740
+ deploy
11741
+ .command('online')
11742
+ .description('Show the current online deployment')
11743
+ .option('--app-id <appId>', 'Application ID')
11744
+ .action(async (options, command) => {
11745
+ const runtime = await getRuntime(command);
11746
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
11747
+ const data = await runtime.client.getOnlineDeployHistory(appId);
11748
+ runtime.output.print({
11749
+ app_id: appId,
11750
+ items: (data.deploy_history_list || []).map(item => ({
11751
+ deploy_history_id: item.deploy_history_id,
11752
+ status: getDeployStatusText(item.status),
11753
+ commit_hash: item.commit_hash_short || item.commit_hash,
11754
+ created_at: item.created_at,
11755
+ deploy_detail: formatDeployDetails(item),
11756
+ domains: item.domain_list || [],
11757
+ })),
11758
+ });
11759
+ });
11760
+
11761
+ deploy
11762
+ .command('rollback-check')
11763
+ .description('Check whether a deployment supports database rollback')
11764
+ .requiredOption('--deploy-id <deployId>', 'Target deployment history ID')
11765
+ .option('--app-id <appId>', 'Application ID')
11766
+ .action(async (options, command) => {
11767
+ const runtime = await getRuntime(command);
11768
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
11769
+ const data = await runtime.client.checkRollbackDatabase({
11770
+ app_id: appId,
11771
+ deploy_history_id: options.deployId || '',
11772
+ });
11773
+ runtime.output.print({ app_id: appId, deploy_history_id: options.deployId, ...data });
11774
+ });
11775
+
11776
+ deploy
11777
+ .command('log-count')
11778
+ .description('Show runtime log count and limit')
11779
+ .option('--app-id <appId>', 'Application ID')
11780
+ .action(async (options, command) => {
11781
+ const runtime = await getRuntime(command);
11782
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
11783
+ const data = await runtime.client.getRuntimeLogCount(appId);
11784
+ runtime.output.print({ app_id: appId, ...data });
11785
+ });
11786
+
11787
+ deploy
11788
+ .command('count')
11789
+ .description('Show successful deployment count')
11790
+ .option('--app-id <appId>', 'Application ID')
11791
+ .action(async (options, command) => {
11792
+ const runtime = await getRuntime(command);
11793
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
11794
+ const data = await runtime.client.getDeployCount(appId);
11795
+ runtime.output.print({ app_id: appId, ...data });
11796
+ });
11797
+ };
11798
+
11799
+ function _nullishCoalesce$2(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
11800
+
11801
+ const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
11802
+ const RESERVED_ENV_PREFIX = 'COZE_';
11803
+
11804
+ const assertEnvKey = (key) => {
11805
+ if (!ENV_KEY_PATTERN.test(key)) {
11806
+ throw new CliError(
11807
+ `Invalid environment variable name: ${key}`,
11808
+ 'ENV_KEY_INVALID',
11809
+ );
11810
+ }
11811
+ if (key.startsWith(RESERVED_ENV_PREFIX)) {
11812
+ throw new CliError(
11813
+ `${RESERVED_ENV_PREFIX} is reserved for platform environment variables.`,
11814
+ 'ENV_KEY_RESERVED',
11815
+ );
11816
+ }
11817
+ };
11818
+
11819
+ const readEnvFile = async (sourceRoot) => {
11820
+ try {
11821
+ return await promises.readFile(node_path.join(sourceRoot, '.env'), 'utf8');
11822
+ } catch (error) {
11823
+ if ((error ).code === 'ENOENT') {
11824
+ return undefined;
11825
+ }
11826
+ throw new CliError('Unable to read the local .env file.', 'ENV_FILE_READ_FAILED');
11827
+ }
11828
+ };
11829
+
11830
+ const parseEnvFile = (content) => {
11831
+ try {
11832
+ const values = node_util.parseEnv(content);
11833
+ if (Object.keys(values).some(key => !ENV_KEY_PATTERN.test(key))) {
11834
+ throw new Error('invalid environment variable name');
11835
+ }
11836
+ return values;
11837
+ } catch (e) {
11838
+ throw new CliError('The local .env file is invalid.', 'ENV_FILE_INVALID');
11839
+ }
11840
+ };
11841
+
11842
+ const assignmentPattern = (key) =>
11843
+ new RegExp(`^\\s*(?:export\\s+)?${key}\\s*=`, 'u');
11844
+
11845
+ const formatEnvValue = (value) => {
11846
+ if (value.includes('\n') || value.includes('\r')) {
11847
+ throw new CliError(
11848
+ 'Environment variable values must be single-line.',
11849
+ 'ENV_VALUE_INVALID',
11850
+ );
11851
+ }
11852
+ if (!value.includes("'")) {
11853
+ return `'${value}'`;
11854
+ }
11855
+ if (!value.includes('"')) {
11856
+ return `"${value}"`;
11857
+ }
11858
+ if (value === value.trim() && !value.includes('#')) {
11859
+ return value;
11860
+ }
11861
+ throw new CliError(
11862
+ 'Environment variable values containing both quote types cannot also contain surrounding whitespace or #.',
11863
+ 'ENV_VALUE_INVALID',
11864
+ );
11865
+ };
11866
+
11867
+ const writeEnvFile = async (sourceRoot, content) => {
11868
+ try {
11869
+ await promises.writeFile(node_path.join(sourceRoot, '.env'), content, { encoding: 'utf8', mode: 0o600 });
11870
+ } catch (e2) {
11871
+ throw new CliError('Unable to write the local .env file.', 'ENV_FILE_WRITE_FAILED');
11872
+ }
11873
+ };
11874
+
11875
+ const listProjectEnv = async (
11876
+ sourceRoot,
11877
+ ) => {
11878
+ const content = await readEnvFile(sourceRoot);
11879
+ if (content === undefined) {
11880
+ return {};
11881
+ }
11882
+ return Object.fromEntries(
11883
+ Object.entries(parseEnvFile(content))
11884
+ .filter(([key]) => !key.startsWith(RESERVED_ENV_PREFIX))
11885
+ .map(([key, value]) => [key, _nullishCoalesce$2(value, () => ( ''))]),
11886
+ );
11887
+ };
11888
+
11889
+ const setProjectEnv = async (
11890
+ sourceRoot,
11891
+ key,
11892
+ value,
11893
+ ) => {
11894
+ assertEnvKey(key);
11895
+ const content = (await readEnvFile(sourceRoot)) || '';
11896
+ if (content) {
11897
+ parseEnvFile(content);
11898
+ }
11899
+ const lines = content.split(/\r?\n/u);
11900
+ const pattern = assignmentPattern(key);
11901
+ const replacement = `${key}=${formatEnvValue(value)}`;
11902
+ const updatedLines = [];
11903
+ let replaced = false;
11904
+ for (const line of lines) {
11905
+ if (pattern.test(line)) {
11906
+ if (!replaced) {
11907
+ updatedLines.push(replacement);
11908
+ replaced = true;
11909
+ }
11910
+ } else {
11911
+ updatedLines.push(line);
11912
+ }
11913
+ }
11914
+ if (!replaced) {
11915
+ while (updatedLines[updatedLines.length - 1] === '') {
11916
+ updatedLines.pop();
11917
+ }
11918
+ updatedLines.push(replacement);
11919
+ }
11920
+ while (updatedLines[updatedLines.length - 1] === '') {
11921
+ updatedLines.pop();
11922
+ }
11923
+ await writeEnvFile(sourceRoot, `${updatedLines.join('\n')}\n`);
11924
+ };
11925
+
11926
+ const deleteProjectEnv = async (
11927
+ sourceRoot,
11928
+ key,
11929
+ ) => {
11930
+ assertEnvKey(key);
11931
+ const content = await readEnvFile(sourceRoot);
11932
+ if (content === undefined) {
11933
+ return false;
11934
+ }
11935
+ parseEnvFile(content);
11936
+ const pattern = assignmentPattern(key);
11937
+ const lines = content.split(/\r?\n/u);
11938
+ const filtered = lines.filter(line => !pattern.test(line));
11939
+ if (filtered.length === lines.length) {
11940
+ return false;
11941
+ }
11942
+ await writeEnvFile(sourceRoot, filtered.join('\n'));
11943
+ return true;
11944
+ };
11945
+
11946
+ const readProjectEnv = async (
11947
+ sourceRoot,
11948
+ ) => {
11949
+ const content = await readEnvFile(sourceRoot);
11950
+ if (content === undefined) {
11951
+ return [];
11952
+ }
11953
+ const values = parseEnvFile(content);
11954
+
11955
+ return Object.entries(values)
11956
+ .filter(([key]) => !key.startsWith(RESERVED_ENV_PREFIX))
11957
+ .map(([key, value]) => ({
11958
+ secret_id: '',
11959
+ secret_key: key,
11960
+ secret_val: _nullishCoalesce$2(value, () => ( '')),
11961
+ secret_type: 'user_custom',
11962
+ }));
11963
+ };
11964
+
11965
+ const resolveSourceRoot = (cwd, options) =>
11966
+ node_path.resolve(cwd, options.sourceRoot || '.');
11967
+
11968
+ const addSourceRootOption = (command) =>
11969
+ command.option('--source-root <sourceRoot>', 'Local project root', '.');
11970
+
11971
+ const registerEnv = (code) => {
11972
+ const env = code
11973
+ .command('env')
11974
+ .description('Manage the local project .env file');
11975
+
11976
+ addSourceRootOption(env.command('list').description('List local environment variables')).action(
11977
+ async (options, command) => {
11978
+ const runtime = await getRuntime(command);
11979
+ const sourceRoot = resolveSourceRoot(runtime.cwd, options);
11980
+ runtime.output.print({
11981
+ source_root: sourceRoot,
11982
+ variables: await listProjectEnv(sourceRoot),
11983
+ });
11984
+ },
11985
+ );
11986
+
11987
+ addSourceRootOption(
11988
+ env
11989
+ .command('set <key> <value>')
11990
+ .description('Set a local environment variable'),
11991
+ ).action(
11992
+ async (
11993
+ key,
11994
+ value,
11995
+ options,
11996
+ command,
11997
+ ) => {
11998
+ const runtime = await getRuntime(command);
11999
+ const sourceRoot = resolveSourceRoot(runtime.cwd, options);
12000
+ await setProjectEnv(sourceRoot, key, value);
12001
+ runtime.output.print({ source_root: sourceRoot, key, updated: true });
12002
+ },
12003
+ );
12004
+
12005
+ addSourceRootOption(
12006
+ env.command('delete <key>').description('Delete a local environment variable'),
12007
+ ).action(async (key, options, command) => {
12008
+ const runtime = await getRuntime(command);
12009
+ const sourceRoot = resolveSourceRoot(runtime.cwd, options);
12010
+ runtime.output.print({
12011
+ source_root: sourceRoot,
12012
+ key,
12013
+ deleted: await deleteProjectEnv(sourceRoot, key),
12014
+ });
12015
+ });
12016
+ };
12017
+
12018
+ function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }
12019
+ const CONNECTOR_IDS = {
12020
+ wechat: '10000127',
12021
+ douyin: '10000126',
12022
+ } ;
12023
+
12024
+
12025
+
12026
+
12027
+
12028
+
12029
+
12030
+
12031
+
12032
+
12033
+
12034
+
12035
+
12036
+
12037
+ const resolveConnectorId = (platform) => {
12038
+ const connectorId = CONNECTOR_IDS[platform ];
12039
+ if (!connectorId) {
12040
+ throw new CliError(
12041
+ `Unsupported Mini-program platform ${String(platform)}; expected wechat or douyin.`,
12042
+ 'INVALID_MINIPROGRAM_PLATFORM',
12043
+ );
12044
+ }
12045
+ return connectorId;
12046
+ };
12047
+
12048
+ const resolveProjectId = async (
12049
+ command,
12050
+ options,
12051
+ ) => {
12052
+ if (_optionalChain$4([options, 'access', _ => _.projectId, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()])) {
12053
+ return options.projectId.trim();
12054
+ }
12055
+ const runtime = await getRuntime(command);
12056
+ const sourceRoot = node_path.resolve(runtime.cwd, options.sourceRoot || '.');
12057
+ const metadata = await readProjectMetadata(sourceRoot);
12058
+ if (!metadata.projectId) {
12059
+ throw new CliError(
12060
+ 'Project ID is required. Pass --project-id or use a source directory whose .coze [project] contains project_id.',
12061
+ 'PROJECT_ID_REQUIRED',
12062
+ );
12063
+ }
12064
+ return metadata.projectId;
12065
+ };
12066
+
12067
+ const registerMiniProgram = (code) => {
12068
+ const miniProgram = code
12069
+ .command('mini-program')
12070
+ .alias('miniprogram')
12071
+ .description('Manage WeChat or Douyin Mini-program authorization');
12072
+
12073
+ miniProgram
12074
+ .command('status')
12075
+ .requiredOption('--platform <platform>', 'wechat or douyin')
12076
+ .option('--project-id <projectId>', 'Deployment Project ID')
12077
+ .option('--source-root <sourceRoot>', 'Directory containing .coze', '.')
12078
+ .action(async (options, command) => {
12079
+ const runtime = await getRuntime(command);
12080
+ const projectId = await resolveProjectId(command, options);
12081
+ const connectorId = resolveConnectorId(options.platform);
12082
+ const data = await runtime.client.getMiniProgramAuthStatus({
12083
+ project_id: projectId,
12084
+ connector_id: connectorId,
12085
+ });
12086
+ runtime.output.print({ project_id: projectId, platform: options.platform, ...data });
12087
+ });
12088
+
12089
+ miniProgram
12090
+ .command('bind')
12091
+ .requiredOption('--platform <platform>', 'wechat or douyin')
12092
+ .requiredOption('--mini-app-id <miniAppId>', 'Mini-program AppID')
12093
+ .requiredOption('--redirect-url <redirectUrl>', 'OAuth callback URL')
12094
+ .option('--project-id <projectId>', 'Deployment Project ID')
12095
+ .option('--source-root <sourceRoot>', 'Directory containing .coze', '.')
12096
+ .option('--override', 'Move an AppID already bound to another project owned by you')
12097
+ .action(async (options, command) => {
12098
+ const runtime = await getRuntime(command);
12099
+ const projectId = await resolveProjectId(command, options);
12100
+ const connectorId = resolveConnectorId(options.platform);
12101
+ const data = await runtime.client.bindMiniProgramAuth({
12102
+ project_id: projectId,
12103
+ connector_id: connectorId,
12104
+ redirect_url: options.redirectUrl || '',
12105
+ auth_params: { app_id: options.miniAppId || '' },
12106
+ override: _nullishCoalesce$1(options.override, () => ( false)),
12107
+ });
12108
+ runtime.output.print({
12109
+ project_id: projectId,
12110
+ platform: options.platform,
12111
+ mini_app_id: options.miniAppId,
12112
+ ...data,
12113
+ });
12114
+ });
12115
+
12116
+ miniProgram
12117
+ .command('submit-code')
12118
+ .requiredOption('--platform <platform>', 'wechat or douyin')
12119
+ .requiredOption('--mini-app-id <miniAppId>', 'Mini-program AppID')
12120
+ .requiredOption('--code <code>', 'OAuth authorization code')
12121
+ .requiredOption('--verify-state <verifyState>', 'State returned by bind')
12122
+ .option('--project-id <projectId>', 'Deployment Project ID')
12123
+ .option('--source-root <sourceRoot>', 'Directory containing .coze', '.')
12124
+ .action(async (options, command) => {
12125
+ const runtime = await getRuntime(command);
12126
+ const projectId = await resolveProjectId(command, options);
12127
+ await runtime.client.submitMiniProgramAuthCode({
12128
+ project_id: projectId,
12129
+ connector_id: resolveConnectorId(options.platform),
12130
+ code: options.code || '',
12131
+ verify_state: options.verifyState || '',
12132
+ auth_params: { app_id: options.miniAppId || '' },
12133
+ });
12134
+ runtime.output.print({ project_id: projectId, platform: options.platform, bound: true });
12135
+ });
12136
+
12137
+ miniProgram
12138
+ .command('unbind')
12139
+ .requiredOption('--platform <platform>', 'wechat or douyin')
12140
+ .option('--project-id <projectId>', 'Deployment Project ID')
12141
+ .option('--source-root <sourceRoot>', 'Directory containing .coze', '.')
12142
+ .action(async (options, command) => {
12143
+ const runtime = await getRuntime(command);
12144
+ const projectId = await resolveProjectId(command, options);
12145
+ await runtime.client.unbindMiniProgramAuth({
12146
+ project_id: projectId,
12147
+ connector_id: resolveConnectorId(options.platform),
12148
+ });
12149
+ runtime.output.print({ project_id: projectId, platform: options.platform, unbound: true });
12150
+ });
12151
+ };
12152
+
12153
+ // 服务端 deploy_app/list 的 page_size 上限,超了会被判参数错误。
12154
+ // 客户端先拦一道,是为了把错误说在本地(带上上限值),而不是回一句服务端的通用参数错误。
12155
+ const APP_LIST_MAX_PAGE_SIZE = 100;
12156
+
12157
+ // page_token 是**页码的十进制字符串**(服务端口径,与 deploy_history/list 一致),不是不透明游标。
12158
+ // 所以这里能、也应该在本地校验:`--page-token abc` 早报错,比发出去再被拒强。
12159
+ const parsePositiveInt = (
12160
+ raw,
12161
+ option,
12162
+ code,
12163
+ max,
12164
+ ) => {
12165
+ const value = Number(raw);
12166
+ if (!Number.isSafeInteger(value) || value <= 0) {
12167
+ throw new CliError(`${option} must be a positive integer.`, code, { [option]: raw });
12168
+ }
12169
+ if (max !== undefined && value > max) {
12170
+ throw new CliError(`${option} must not exceed ${String(max)}.`, code, { [option]: raw });
12171
+ }
12172
+ return value;
12173
+ };
12174
+
12175
+ // ⛔ 别再用 `Number(options.pageSize || 20)`:`--page-size abc` 会算出 NaN,
12176
+ // JSON.stringify 把它写成 null 发给服务端,最后表现为「参数没生效」而不是「参数写错了」。
12177
+ const parsePageSize = (
12178
+ raw,
12179
+ fallback,
12180
+ max,
12181
+ ) => {
12182
+ if (raw === undefined || raw === '') {
12183
+ return fallback;
12184
+ }
12185
+ return parsePositiveInt(raw, '--page-size', 'INVALID_PAGE_SIZE', max);
12186
+ };
12187
+
12188
+ const parsePageToken = (raw) => {
12189
+ if (raw === undefined || raw === '') {
12190
+ return undefined;
12191
+ }
12192
+ parsePositiveInt(raw, '--page-token', 'INVALID_PAGE_TOKEN');
12193
+ return raw;
12194
+ };
12195
+
12196
+
12197
+
12198
+
12199
+
12200
+
12201
+
12202
+ // collectAllPages 顺着 next_page_token 把所有页取回来。
12203
+ //
12204
+ // 服务端从「全量单页」改成真分页之后,`app list` 一次只回一页;想要「我的全部应用」就得翻页。
12205
+ // 与其让每个调用方各写一遍循环,不如给一个 --all。
12206
+ //
12207
+ // ⚠️ 不设页数上限截断:静默截断正是这次要修掉的毛病。只防死循环——服务端如果一直回同一个
12208
+ // token(或说 has_more 却不给 token),直接报错,而不是无限翻。
12209
+ const collectAllPages = async (
12210
+ fetchPage,
12211
+ ) => {
12212
+ const items = [];
12213
+ const seen = new Set();
12214
+ let pageToken;
12215
+ let pages = 0;
12216
+ for (;;) {
12217
+ const page = await fetchPage(pageToken);
12218
+ items.push(...(page.items || []));
12219
+ pages += 1;
12220
+ if (!page.has_more) {
12221
+ return { items, pages };
12222
+ }
12223
+ const next = page.next_page_token;
12224
+ if (!next || seen.has(next)) {
12225
+ throw new CliError(
12226
+ 'The server reported more pages but returned no usable next_page_token.',
12227
+ 'INVALID_PAGE_TOKEN',
12228
+ { next_page_token: next, pages },
12229
+ );
12230
+ }
12231
+ seen.add(next);
12232
+ pageToken = next;
12233
+ }
12234
+ };
12235
+
12236
+ 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; }
12237
+
12238
+ const POLL_INTERVAL_MS = 3000;
12239
+ const MAX_CONSECUTIVE_RETRIES = 5;
12240
+ const TRANSIENT_RPC_ERROR_CODE = 230000001;
12241
+
12242
+ const wait = async () =>
12243
+ new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS));
12244
+
12245
+ const isRetryablePollError = (error) =>
12246
+ error instanceof CliError &&
12247
+ error.code === 'API_REJECTED' &&
12248
+ Number(_optionalChain$3([error, 'access', _ => _.details, 'optionalAccess', _2 => _2.business_code])) === TRANSIENT_RPC_ERROR_CODE;
12249
+
12250
+ const pollHistory = async (
12251
+ command,
12252
+ appId,
12253
+ deployHistoryId,
12254
+ ) => {
12255
+ const runtime = await getRuntime(command);
12256
+ const startedAt = Date.now();
12257
+ let consecutiveFailures = 0;
12258
+ while (true) {
12259
+ try {
12260
+ const history = await runtime.client.getDeployHistory({
12261
+ app_id: appId,
12262
+ deploy_history_id: deployHistoryId,
12263
+ });
12264
+ consecutiveFailures = 0;
12265
+ const status = getDeployStatusText(history.status);
12266
+ runtime.output.debug(
12267
+ `[deploy] History ${deployHistoryId}: ${status} (${String(Math.floor((Date.now() - startedAt) / 1000))}s elapsed)`,
12268
+ );
12269
+ if (history.status && TERMINAL_STATUSES.has(history.status)) {
12270
+ return history;
12271
+ }
12272
+ } catch (error) {
12273
+ if (!isRetryablePollError(error) || consecutiveFailures >= MAX_CONSECUTIVE_RETRIES) {
12274
+ throw error;
12275
+ }
12276
+ consecutiveFailures += 1;
12277
+ runtime.output.debug(
12278
+ `[deploy] Status check failed transiently; retrying (${String(consecutiveFailures)}/${String(MAX_CONSECUTIVE_RETRIES)}).`,
12279
+ );
12280
+ }
12281
+ await wait();
12282
+ }
12283
+ };
12284
+
12285
+ const GENERAL_PROJECT_TYPE = 9;
12286
+
12287
+ /**
12288
+ * Map `.coze` `[project].project_type` to the VibeProjectType used when creating the
12289
+ * deployment project.
12290
+ *
12291
+ * The values on the left are the ones the deploy server understands (see `cozefileutil`
12292
+ * `ResolveDeployKindByProjectType` / `GeneralProjectTypeByCozeProjectType` in coze-coding);
12293
+ * the numbers on the right are `VibeProjectType` (idl/coze.coding.ide/project.thrift).
12294
+ *
12295
+ * Keeping the two in sync matters beyond project metadata: the created project type decides
12296
+ * the project-scoped `COZE_PROJECT_TYPE` secret injected into the runtime, whether a Postgres
12297
+ * database is provisioned for the project, and whether the traffic gateway enforces inbound
12298
+ * auth. Creating an `agent` project as General(9) therefore deploys successfully but leaves a
12299
+ * dead service: the agent template reads `COZE_PROJECT_TYPE` to pick its graph and needs
12300
+ * `PGDATABASE_URL` on startup.
12301
+ *
12302
+ * VibeProjectType WebApp(3) and AssistantAgent(8) are intentionally absent: no `.coze`
12303
+ * project_type maps to them.
12304
+ */
12305
+ const resolveCreationProjectType = (
12306
+ projectType,
12307
+ ) => {
12308
+ switch (projectType) {
12309
+ case 'agent':
12310
+ return 1;
12311
+ case 'workflow':
12312
+ case 'automation':
12313
+ return 2;
12314
+ case 'app':
12315
+ return 4;
12316
+ case 'skill':
12317
+ return 5;
12318
+ case 'web':
12319
+ case 'backend':
12320
+ return 6;
12321
+ case 'miniapp':
12322
+ case 'miniprogram':
12323
+ return 7;
12324
+ default:
12325
+ return GENERAL_PROJECT_TYPE;
12326
+ }
12327
+ };
12328
+
12329
+ const formatDeployment = (deployment) =>
12330
+ typeof deployment === 'object' && deployment
12331
+ ? {
12332
+ ...(deployment ),
12333
+ status: getDeployStatusText(
12334
+ Number((deployment ).status),
12335
+ ),
12336
+ }
12337
+ : undefined;
12338
+
12339
+ const formatApplication = (application) => ({
12340
+ ...application,
12341
+ online_deployment: formatDeployment(application.online_deployment),
12342
+ latest_deployment: formatDeployment(application.latest_deployment),
12343
+ });
12344
+
12345
+ // 对应 IDL 的 MetricTimeRange,数值与 V1 保持一致。
12346
+ const TIME_RANGES = {
12347
+ day: 1,
12348
+ week: 2,
12349
+ month: 3,
12350
+ yesterday: 4,
12351
+ 'three-days': 5,
12352
+ };
12353
+
12354
+ const resolveTimeRange = (value) => {
12355
+ const timeRange = TIME_RANGES[value || 'day'];
12356
+ if (!timeRange) {
12357
+ throw new CliError(
12358
+ `Invalid time range; expected one of ${Object.keys(TIME_RANGES).join(', ')}.`,
12359
+ 'INVALID_TIME_RANGE',
12360
+ { time_range: value },
12361
+ );
12362
+ }
12363
+ return timeRange;
12364
+ };
12365
+
12366
+ const UNIT_TYPES = { dev: 1, prod: 2 };
12367
+
12368
+ // 改 Application 本身的两条写操作,都要显式 --yes 才生效。
12369
+ // 单独拎出来是因为它们和 registerApp 里其余只读命令性质不同(会改线上资产),
12370
+ // 顺带让 registerApp 保持在 max-line-per-function 之内。
12371
+ const registerAppMutations = (app) => {
12372
+ app
12373
+ .command('rename <name>')
12374
+ .description('Rename an application')
12375
+ .option('--app-id <appId>', 'Application ID')
12376
+ .option('--yes', 'Confirm rename')
12377
+ .action(async (name, options, command) => {
12378
+ if (!options.yes) {
12379
+ throw new CliError('Pass --yes to rename the application.', 'CONFIRMATION_REQUIRED');
12380
+ }
12381
+ const normalizedName = name.trim();
12382
+ if (!normalizedName || normalizedName.length > 255) {
12383
+ throw new CliError(
12384
+ 'Application name must contain 1 to 255 characters.',
12385
+ 'INVALID_APPLICATION_NAME',
12386
+ );
12387
+ }
12388
+ const runtime = await getRuntime(command);
12389
+ const appId = await requireAppId(runtime.cwd, options.appId);
12390
+ const application = await runtime.client.updateApplication({
12391
+ app_id: appId,
12392
+ name: normalizedName,
12393
+ });
12394
+ runtime.output.print(
12395
+ formatApplication(application ),
12396
+ );
12397
+ });
12398
+ app
12399
+ // 删除是终态、不可撤销,所以和 rename 一样必须显式 --yes。
12400
+ //
12401
+ // 服务端只接受 **Stopped** 的应用:还在服务的先 `code deploy stop --yes`,否则会拿到一条
12402
+ // 带当前状态的报错。这里刻意不替用户先停 —— 停服会真的把线上服务摘掉,那得是用户自己按的。
12403
+ .command('delete')
12404
+ .description('Delete a stopped application (irreversible)')
12405
+ .option('--app-id <appId>', 'Application ID')
12406
+ .option('--yes', 'Confirm delete')
12407
+ .action(async (options, command) => {
12408
+ if (!options.yes) {
12409
+ throw new CliError('Pass --yes to delete the application.', 'CONFIRMATION_REQUIRED');
12410
+ }
12411
+ const runtime = await getRuntime(command);
12412
+ const appId = await requireAppId(runtime.cwd, options.appId);
12413
+ await runtime.client.deleteApplication(appId);
12414
+ // 本地 .coze 里的 app_id 不动(这条命令可能是在别的目录带 --app-id 跑的),但要说清楚:
12415
+ // 不清掉它,同目录下一次 deploy 会打到一个已删除的应用上、被服务端拒。
12416
+ runtime.output.print({
12417
+ app_id: appId,
12418
+ deleted: true,
12419
+ note: 'Remove app_id from .coze [project] before deploying this directory again.',
12420
+ });
12421
+ });
12422
+ };
12423
+
12424
+ const registerApp = (code) => {
12425
+ const app = code.command('app').description('Manage deployment applications');
12426
+ registerAppMutations(app);
12427
+ app
12428
+ .command('list')
12429
+ // 列的是当前登录用户名下**跨 Project** 的全部 Application。没有 --project-id:
12430
+ // V2 的资产归属是 Owner 而不是 Project,同一个 Project 下的应用可以分属不同用户。
12431
+ // 也不传 user_id:服务端直接从登录态取,客户端传了也只能传自己。
12432
+ //
12433
+ // ⚠️ 服务端是真分页(一页最多 100 条),一次调用只回一页。要「我的全部应用」用 --all,
12434
+ // 它顺着 next_page_token 翻到底 —— 别再默认第一页就是全部。
12435
+ .option('--page-token <pageToken>', 'Pagination token (page number)')
12436
+ .option('--page-size <pageSize>', 'Page size', '20')
12437
+ .option('--all', 'Fetch every page by following next_page_token')
12438
+ .action(async (options, command) => {
12439
+ const pageSize = parsePageSize(options.pageSize, 20, APP_LIST_MAX_PAGE_SIZE);
12440
+ const pageToken = parsePageToken(options.pageToken);
12441
+ if (options.all && pageToken) {
12442
+ throw new CliError(
12443
+ '--all fetches every page and cannot be combined with --page-token.',
12444
+ 'INVALID_PAGE_TOKEN',
12445
+ { page_token: options.pageToken },
12446
+ );
12447
+ }
12448
+ const runtime = await getRuntime(command);
12449
+ const format = (items) =>
12450
+ items.map(item => formatApplication(item ));
12451
+ if (options.all) {
12452
+ const { items, pages } = await collectAllPages(next =>
12453
+ runtime.client.listApplications({ page_token: next, page_size: pageSize }),
12454
+ );
12455
+ runtime.output.print({ items: format(items), pages, has_more: false });
12456
+ return;
12457
+ }
12458
+ const data = await runtime.client.listApplications({
12459
+ page_token: pageToken,
12460
+ page_size: pageSize,
12461
+ });
12462
+ runtime.output.print({
12463
+ items: format(data.items),
12464
+ next_page_token: data.next_page_token,
12465
+ has_more: data.has_more,
12466
+ });
12467
+ });
12468
+ app
12469
+ .command('show')
12470
+ .requiredOption('--app-id <appId>', 'Application ID')
12471
+ .action(async (options, command) => {
12472
+ const runtime = await getRuntime(command);
12473
+ runtime.output.print(
12474
+ formatApplication(
12475
+ (await runtime.client.getApplication(options.appId))
12476
+
12477
+
12478
+ ,
12479
+ ),
12480
+ );
12481
+ });
12482
+ app
12483
+ .command('analytics')
12484
+ .description('Show PV / UV charts')
12485
+ .option('--app-id <appId>', 'Application ID')
12486
+ .option(
12487
+ '--time-range <timeRange>',
12488
+ `Time range: ${Object.keys(TIME_RANGES).join(', ')}`,
12489
+ 'day',
12490
+ )
12491
+ .action(async (options, command) => {
12492
+ const timeRange = resolveTimeRange(options.timeRange);
12493
+ const runtime = await getRuntime(command);
12494
+ const appId = await requireAppId(runtime.cwd, options.appId);
12495
+ const data = await runtime.client.getUserAnalyticsMetrics({
12496
+ app_id: appId,
12497
+ time_range: timeRange,
12498
+ });
12499
+ runtime.output.print({ app_id: appId, charts: data.charts || [] });
12500
+ });
12501
+ app
12502
+ .command('metrics')
12503
+ .description('Show application runtime metrics')
12504
+ .option('--app-id <appId>', 'Application ID')
12505
+ .option(
12506
+ '--time-range <timeRange>',
12507
+ `Time range: ${Object.keys(TIME_RANGES).join(', ')}`,
12508
+ 'day',
12509
+ )
12510
+ .action(async (options, command) => {
12511
+ const timeRange = resolveTimeRange(options.timeRange);
12512
+ const runtime = await getRuntime(command);
12513
+ const appId = await requireAppId(runtime.cwd, options.appId);
12514
+ const data = await runtime.client.getApplicationMetrics({
12515
+ app_id: appId,
12516
+ time_range: timeRange,
12517
+ });
12518
+ runtime.output.print({
12519
+ app_id: appId,
12520
+ charts: data.charts || [],
12521
+ stats: data.stats || [],
12522
+ });
12523
+ });
12524
+ app
12525
+ .command('usage')
12526
+ .description('Show monthly hosted usage')
12527
+ .option('--app-id <appId>', 'Application ID')
12528
+ .requiredOption('--bill-month <billMonth>', 'Billing month in YYYY-MM format')
12529
+ .action(async (options, command) => {
12530
+ const billMonth = options.billMonth || '';
12531
+ if (!/^\d{4}-(?:0[1-9]|1[0-2])$/u.test(billMonth)) {
12532
+ throw new CliError(
12533
+ 'Invalid billing month; expected YYYY-MM.',
12534
+ 'INVALID_BILL_MONTH',
12535
+ { bill_month: billMonth },
12536
+ );
12537
+ }
12538
+ const runtime = await getRuntime(command);
12539
+ const appId = await requireAppId(runtime.cwd, options.appId);
12540
+ const data = await runtime.client.getHostedUsageMonthly({
12541
+ app_id: appId,
12542
+ bill_month: billMonth,
12543
+ });
12544
+ runtime.output.print({ app_id: appId, summary: data.summary });
12545
+ });
12546
+ };
12547
+
12548
+ const registerDomain = (code) => {
12549
+ const domain = code.command('domain').description('Manage application domains');
12550
+ domain
12551
+ .command('list')
12552
+ .option('--app-id <appId>', 'Application ID')
12553
+ .option('--unit-type <unitType>', 'Unit type: dev or prod', 'prod')
12554
+ .action(async (options, command) => {
12555
+ const unitType = UNIT_TYPES[options.unitType || 'prod'];
12556
+ if (!unitType) {
12557
+ throw new CliError(
12558
+ 'Invalid unit type; expected dev or prod.',
12559
+ 'INVALID_UNIT_TYPE',
12560
+ { unit_type: options.unitType },
12561
+ );
12562
+ }
12563
+ const runtime = await getRuntime(command);
12564
+ const appId = await requireAppId(runtime.cwd, options.appId);
12565
+ const data = await runtime.client.listDomains(appId, unitType);
12566
+ runtime.output.print({
12567
+ app_id: appId,
12568
+ unit_type: options.unitType || 'prod',
12569
+ items: (data.items || []).map(item => ({
12570
+ id: item.id,
12571
+ domain_host: item.domain_host,
12572
+ })),
12573
+ });
12574
+ });
12575
+ domain
12576
+ // 改的是系统分配的 <prefix>.coze.site 的 prefix,不是 `domain add` 加进来的自定义域名 ——
12577
+ // 那类域名服务端只有 create/delete,域名串本身改不了。
12578
+ //
12579
+ // 和 rename 一样要 --yes:旧默认域名会立刻停止指向本应用,已经发出去的链接会失效。
12580
+ .command('set-prefix <prefix>')
12581
+ .description('Change the default domain prefix (<prefix>.coze.site)')
12582
+ .option('--app-id <appId>', 'Application ID')
12583
+ .option('--yes', 'Confirm prefix change')
12584
+ .action(async (prefix, options, command) => {
12585
+ if (!options.yes) {
12586
+ throw new CliError(
12587
+ 'Pass --yes to change the default domain prefix.',
12588
+ 'CONFIRMATION_REQUIRED',
12589
+ );
12590
+ }
12591
+ const normalizedPrefix = prefix.trim();
12592
+ // 只做形态校验:长度、保留词、占用与权益都由服务端判,客户端不复制第二套规则。
12593
+ if (!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(normalizedPrefix)) {
12594
+ throw new CliError(
12595
+ 'Invalid prefix; use lowercase letters, digits and hyphens, not starting or ending with a hyphen.',
12596
+ 'INVALID_DOMAIN_PREFIX',
12597
+ { prefix },
12598
+ );
12599
+ }
12600
+ const runtime = await getRuntime(command);
12601
+ const appId = await requireAppId(runtime.cwd, options.appId);
12602
+ const data = await runtime.client.updateDefaultDomainPrefix({
12603
+ app_id: appId,
12604
+ prefix: normalizedPrefix,
12605
+ });
12606
+ runtime.output.print({
12607
+ app_id: appId,
12608
+ prefix: normalizedPrefix,
12609
+ old_domain_host: data.old_domain_host_canonical,
12610
+ new_domain_host: data.new_domain_host_canonical,
12611
+ });
12612
+ });
12613
+ domain
12614
+ .command('add <domain>')
12615
+ .option('--app-id <appId>', 'Application ID')
12616
+ .action(async (domainHost, options, command) => {
12617
+ if (!/^[a-zA-Z0-9](?:[a-zA-Z0-9-]*\.)+[a-zA-Z0-9-]+$/u.test(domainHost)) {
12618
+ throw new CliError('Invalid domain.', 'INVALID_DOMAIN', { domain: domainHost });
12619
+ }
12620
+ const runtime = await getRuntime(command);
12621
+ const appId = await requireAppId(runtime.cwd, options.appId);
12622
+ await runtime.client.createDomain({ app_id: appId, domain: domainHost });
12623
+ runtime.output.print({ app_id: appId, domain: domainHost });
12624
+ });
12625
+ };
12626
+
12627
+ 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; }
12628
+
12629
+ const firstPage = { page: 1, size: 1 };
12630
+
12631
+ const listSpaceRequest = (runtime) => ({
12632
+ ...(runtime.config.organizationId
12633
+ ? { organization_id: runtime.config.organizationId }
12634
+ : {}),
12635
+ ...(runtime.config.enterpriseId
12636
+ ? { enterprise_id: runtime.config.enterpriseId }
12637
+ : {}),
12638
+ });
12639
+
12640
+ const resolveDeploymentSpaceId = async (runtime) => {
12641
+ const configuredSpaceId = _optionalChain$2([runtime, 'access', _ => _.config, 'access', _2 => _2.spaceId, 'optionalAccess', _3 => _3.trim, 'call', _4 => _4()]);
12642
+ const request = listSpaceRequest(runtime);
12643
+ if (configuredSpaceId) {
12644
+ const data = await runtime.client.listSpaces(request);
12645
+ if (!data.bot_space_list.some(space => space.id === configuredSpaceId)) {
12646
+ throw new CliError(
12647
+ `Space ID ${configuredSpaceId} is invalid or is not available to the current account.`,
12648
+ 'INVALID_SPACE_ID',
12649
+ );
12650
+ }
12651
+ return configuredSpaceId;
12652
+ }
12653
+
12654
+ const data = await runtime.client.listSpaces({ ...request, ...firstPage });
12655
+ const space = data.bot_space_list.find(item => item.id);
12656
+ if (!space) {
12657
+ throw new CliError(
12658
+ 'No available Space was found for the current account. Create or join a Space before deploying.',
12659
+ 'SPACE_NOT_FOUND',
12660
+ );
12661
+ }
12662
+
12663
+ runtime.config.spaceId = space.id;
12664
+ try {
12665
+ await saveSharedConfig({ spaceId: space.id }, runtime.globalOptions);
12666
+ } catch (error) {
12667
+ runtime.output.warn(`Unable to save the auto-selected Space: ${String(error)}`);
12668
+ }
12669
+ runtime.output.debug(`Auto-selected Space: ${space.name || space.id} (${space.id})`);
12670
+ return space.id;
12671
+ };
12672
+
12673
+ const PACKAGE_SCRIPT_CANDIDATES = [
12674
+ node_path.resolve(__dirname, 'deploy/package-project.js'),
12675
+ node_path.resolve(__dirname, '../../../scripts/deploy/package-project.js'),
12676
+ ];
12677
+
12678
+ const packageCommand = (args) => {
12679
+ const packageScript = PACKAGE_SCRIPT_CANDIDATES.find(candidate =>
12680
+ node_fs.existsSync(candidate),
12681
+ );
12682
+ if (!packageScript) {
12683
+ throw new CliError(
12684
+ 'The deployment packaging script is missing from this coze-dev installation.',
12685
+ 'SOURCE_PACKAGE_FAILED',
12686
+ );
12687
+ }
12688
+ return [packageScript, ...args];
12689
+ };
12690
+
12691
+ const runPackageScript = async (args, debug = false) =>
12692
+ new Promise((resolvePromise, reject) => {
12693
+ const child = node_child_process.spawn(process.execPath, packageCommand(args), {
12694
+ stdio: ['ignore', 'pipe', 'pipe'],
12695
+ });
12696
+ let errorOutput = '';
12697
+ const forward = (chunk) => {
12698
+ const text = chunk.toString();
12699
+ if (debug) {
12700
+ process.stderr.write(text);
12701
+ }
12702
+ errorOutput = `${errorOutput}${text}`.slice(-65536);
12703
+ };
12704
+ child.stdout.on('data', forward);
12705
+ child.stderr.on('data', forward);
12706
+ child.once('error', reject);
12707
+ child.once('close', code => {
12708
+ if (code === 0) {
12709
+ resolvePromise();
12710
+ return;
12711
+ }
12712
+ reject(new Error(
12713
+ `Packaging process exited with code ${String(code)}${errorOutput ? `\n${errorOutput.trim()}` : ''}`,
12714
+ ));
12715
+ });
12716
+ });
12717
+
12718
+
12719
+
12720
+
12721
+
12722
+
12723
+
12724
+
12725
+
12726
+
12727
+
12728
+
12729
+ const createSourcePackageArchive = async (
12730
+ sourceRoot,
12731
+ applicationType = 'service',
12732
+ debug = false,
12733
+ ) => {
12734
+ const tempDirectory = await promises.mkdtemp(node_path.join(node_os.tmpdir(), 'coze-deploy-source-'));
12735
+ const outputPath = node_path.join(tempDirectory, 'source.tar.gz');
12736
+ try {
12737
+ await runPackageScript(
12738
+ [sourceRoot, outputPath, ...(applicationType === 'pages' ? ['--pages'] : [])],
12739
+ debug,
12740
+ );
12741
+ const info = await promises.stat(outputPath);
12742
+ if (info.size === 0) {
12743
+ throw new CliError('Source package is empty.', 'SOURCE_PACKAGE_FAILED');
12744
+ }
12745
+ return {
12746
+ path: outputPath,
12747
+ sizeBytes: info.size,
12748
+ cleanup: () => promises.rm(tempDirectory, { recursive: true, force: true }),
12749
+ };
12750
+ } catch (error) {
12751
+ await promises.rm(tempDirectory, { recursive: true, force: true });
12752
+ if (error instanceof CliError) {
12753
+ throw error;
12754
+ }
12755
+ throw new CliError(
12756
+ `Unable to package local source: ${error instanceof Error ? error.message : String(error)}`,
12757
+ 'SOURCE_PACKAGE_FAILED',
12758
+ );
12759
+ }
12760
+ };
12761
+
12762
+ const UPLOAD_SESSION_FILENAME = '.coze-deploy-upload.json';
12763
+
12764
+
12765
+
12766
+
12767
+
12768
+
12769
+
12770
+
12771
+
12772
+
12773
+
12774
+ const isUploadSession = (value) => {
12775
+ if (!value || typeof value !== 'object') {
12776
+ return false;
12777
+ }
12778
+ const session = value ;
12779
+ return typeof session.idempotencyKey === 'string' &&
12780
+ typeof session.createdAt === 'number' &&
12781
+ typeof session.sourcePackageSizeBytes === 'number' &&
12782
+ Boolean(session.request && typeof session.request === 'object');
12783
+ };
12784
+
12785
+ const readUploadSession = async (sourceRoot) => {
12786
+ try {
12787
+ const parsed = safeJsonParse(
12788
+ await promises.readFile(node_path.join(sourceRoot, UPLOAD_SESSION_FILENAME), 'utf8'),
12789
+ undefined,
12790
+ );
12791
+ return isUploadSession(parsed) ? parsed : undefined;
12792
+ } catch (error) {
12793
+ if ((error ).code === 'ENOENT') {
12794
+ return undefined;
12795
+ }
12796
+ throw error;
12797
+ }
12798
+ };
12799
+
12800
+ const writeUploadSession = async (sourceRoot, session) => {
12801
+ const path = node_path.join(sourceRoot, UPLOAD_SESSION_FILENAME);
12802
+ const tempPath = node_path.join(node_path.dirname(path), `.coze-deploy-upload-${node_crypto.randomUUID()}.tmp`);
12803
+ await promises.mkdir(node_path.dirname(path), { recursive: true });
12804
+ try {
12805
+ await promises.writeFile(tempPath, `${JSON.stringify(session, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
12806
+ await promises.rename(tempPath, path);
12807
+ } finally {
12808
+ await promises.rm(tempPath, { force: true });
12809
+ }
12810
+ };
12811
+
12812
+ const removeUploadSession = async (sourceRoot) => {
12813
+ await promises.rm(node_path.join(sourceRoot, UPLOAD_SESSION_FILENAME), { force: true });
12814
+ };
12815
+
12816
+ 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; }
12817
+ const INLINE_SOURCE_PACKAGE_MAX_BYTES = 1024 * 1024;
12818
+ const PRE_DEPLOY_SESSION_TTL_MS = 2 * 60 * 60 * 1000;
12819
+
12820
+ const uploadFile = async (
12821
+ uploadUrl,
12822
+ requiredHeaders,
12823
+ archive,
12824
+ ) => {
12825
+ const uploadRequest = {
12826
+ method: 'PUT',
12827
+ headers: requiredHeaders,
12828
+ body: node_stream.Readable.toWeb(node_fs.createReadStream(archive.path)) ,
12829
+ duplex: 'half',
12830
+ };
12831
+ const response = await fetch(uploadUrl, uploadRequest);
12832
+ if (!response.ok) {
12833
+ throw new CliError(`Direct artifact upload failed: ${response.status} ${response.statusText}`, 'ARTIFACT_UPLOAD_FAILED');
12834
+ }
12835
+ };
12836
+
12837
+ const createDeploymentWithSourcePackage = async (
12838
+ client,
12839
+ request,
12840
+ archive,
12841
+ sourceRoot,
12842
+ ) => {
12843
+ if (archive.sizeBytes <= INLINE_SOURCE_PACKAGE_MAX_BYTES) {
12844
+ const content = await promises.readFile(archive.path);
12845
+ return {
12846
+ uploadMode: 'inline' ,
12847
+ result: await client.createDeployHistory({ ...request, source_package_base64: content.toString('base64') }),
12848
+ };
12849
+ }
12850
+
12851
+ const savedSession = await readUploadSession(sourceRoot);
12852
+ let retryRequest = request;
12853
+ let reconciledSession = savedSession;
12854
+ if (_optionalChain$1([savedSession, 'optionalAccess', _ => _.appId]) && savedSession.deployHistoryId) {
12855
+ const history = await client.getDeployHistory({
12856
+ app_id: savedSession.appId,
12857
+ deploy_history_id: savedSession.deployHistoryId,
12858
+ });
12859
+ switch (history.status) {
12860
+ case DEPLOY_STATUS.preDeploy:
12861
+ // The server is authoritative for the session lifetime. Reuse the
12862
+ // original key even if the local two-hour clock is close to expiry;
12863
+ // pre_upload will either refresh the URL or release an expired slot.
12864
+ break;
12865
+ case DEPLOY_STATUS.pending:
12866
+ case DEPLOY_STATUS.running:
12867
+ case DEPLOY_STATUS.interrupted:
12868
+ case DEPLOY_STATUS.succeeded:
12869
+ // The previous create request was accepted but its response may have
12870
+ // been lost. Do not upload or create another deployment.
12871
+ await removeUploadSession(sourceRoot);
12872
+ return {
12873
+ uploadMode: 'direct' ,
12874
+ result: {
12875
+ app_id: savedSession.appId,
12876
+ deploy_history_id: savedSession.deployHistoryId,
12877
+ status: history.status,
12878
+ version: typeof history.version === 'number' ? history.version : undefined,
12879
+ },
12880
+ };
12881
+ case DEPLOY_STATUS.failed:
12882
+ case DEPLOY_STATUS.canceled:
12883
+ // The reserved history can no longer be claimed. Start a new upload
12884
+ // against the Application that pre_upload already created.
12885
+ await removeUploadSession(sourceRoot);
12886
+ reconciledSession = undefined;
12887
+ retryRequest = {
12888
+ ...request,
12889
+ project_id: undefined,
12890
+ app_id: savedSession.appId,
12891
+ };
12892
+ break;
12893
+ default:
12894
+ throw new CliError(
12895
+ `Unable to reconcile pre-deploy history ${savedSession.deployHistoryId}: unknown status ${String(history.status)}.`,
12896
+ 'INVALID_RESPONSE',
12897
+ );
12898
+ }
12899
+ }
12900
+ const liveSavedSession = reconciledSession && (
12901
+ reconciledSession.appId && reconciledSession.deployHistoryId ||
12902
+ Date.now() - reconciledSession.createdAt < PRE_DEPLOY_SESSION_TTL_MS
12903
+ )
12904
+ ? reconciledSession
12905
+ : undefined;
12906
+ if (liveSavedSession && liveSavedSession.sourcePackageSizeBytes !== archive.sizeBytes) {
12907
+ throw new CliError(
12908
+ 'A different source package is waiting for upload. Cancel that deployment or wait for its two-hour session to expire.',
12909
+ 'PRE_DEPLOY_SOURCE_CHANGED',
12910
+ );
12911
+ }
12912
+ if (reconciledSession && !liveSavedSession) {
12913
+ await removeUploadSession(sourceRoot);
12914
+ }
12915
+ const resumableSession = liveSavedSession;
12916
+ const session = resumableSession || {
12917
+ idempotencyKey: node_crypto.randomUUID(),
12918
+ createdAt: Date.now(),
12919
+ sourcePackageSizeBytes: archive.sizeBytes,
12920
+ request: retryRequest,
12921
+ };
12922
+ // Persist before preDeployUpload: if the server creates PreDeploy but the response is lost,
12923
+ // the next CLI run must reuse the same idempotency key.
12924
+ await writeUploadSession(sourceRoot, session);
12925
+ const preDeploy = await client.preDeployUpload({
12926
+ ...session.request,
12927
+ source_package_size_bytes: String(archive.sizeBytes),
12928
+ idempotency_key: session.idempotencyKey,
12929
+ });
12930
+ await writeUploadSession(sourceRoot, {
12931
+ ...session,
12932
+ appId: preDeploy.app_id,
12933
+ deployHistoryId: preDeploy.deploy_history_id,
12934
+ uploadReceipt: preDeploy.upload_receipt,
12935
+ });
12936
+ await uploadFile(preDeploy.upload_url, preDeploy.required_headers || {}, archive);
12937
+ const result = await client.createDeployHistory({
12938
+ ...session.request,
12939
+ project_id: undefined,
12940
+ app_id: preDeploy.app_id,
12941
+ pre_deploy_history_id: preDeploy.deploy_history_id,
12942
+ upload_receipt: preDeploy.upload_receipt,
12943
+ source_package_size_bytes: String(archive.sizeBytes),
12944
+ });
12945
+ await removeUploadSession(sourceRoot);
12946
+ return { uploadMode: 'direct' , result };
12947
+ };
12948
+
12949
+ function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } async function _asyncOptionalChain(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 = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
12950
+ const SUPPORTED_MINIPROGRAM_CONNECTOR_IDS = new Set(['10000127', '10000126']);
12951
+ const collectConnectorId = (value, previous) => [
12952
+ ...previous,
12953
+ value,
12954
+ ];
12955
+
12956
+ const getConnectorConfigs = (connectorIds) =>
12957
+ (connectorIds || []).map(connectorId => {
12958
+ if (!SUPPORTED_MINIPROGRAM_CONNECTOR_IDS.has(connectorId)) {
12959
+ throw new CliError(
12960
+ `Unsupported connector ID ${connectorId}; expected 10000127 (WeChat) or 10000126 (Douyin).`,
12961
+ 'INVALID_CONNECTOR_ID',
12962
+ );
12963
+ }
12964
+ return { connector_id: connectorId };
12965
+ });
12966
+
12967
+ // Keep deployment option and output contracts together for auditing against the V2 IDL.
12968
+ // eslint-disable-next-line @coze-arch/max-line-per-function -- keep V2 deployment contracts together
12969
+ const registerDeploy = (code) => {
12970
+ const deploy = code
12971
+ .command('deploy')
12972
+ .description('Deploy an application using deployment V2')
12973
+ .option('--source-root <sourceRoot>', 'Local source root', '.')
12974
+ .option('--project-id <projectId>', 'Project ID for the first deployment')
12975
+ .option('--app-id <appId>', 'Application ID')
12976
+ .option(
12977
+ '--application-type <type>',
12978
+ 'Deployment application type: service, pages, or mini_program',
12979
+ )
12980
+ .option('-n, --name <name>', 'Application name for the first deployment')
12981
+ .option('--message <message>', 'Deployment message')
12982
+ .option(
12983
+ '--connector-id <connectorId>',
12984
+ 'Mini-program channel: 10000127 (WeChat) or 10000126 (Douyin); repeatable',
12985
+ collectConnectorId,
12986
+ [],
12987
+ )
12988
+ .option('--wait', 'Wait for deployment completion')
12989
+ .option('--yes', 'Confirm deployment')
12990
+ // eslint-disable-next-line @coze-arch/max-line-per-function -- deployment orchestration is one auditable flow
12991
+ .action(async (options, command) => {
12992
+ const runtime = await getRuntime(command);
12993
+ const sourceRoot = node_path.resolve(runtime.cwd, options.sourceRoot || '.');
12994
+ const requestedApplicationType = parseApplicationType(options.applicationType);
12995
+ runtime.output.debug(`[deploy] Reading local project: ${sourceRoot}`);
12996
+ const localContext =
12997
+ await readDeployLocalContext(
12998
+ sourceRoot,
12999
+ requestedApplicationType,
13000
+ options.appId,
13001
+ runtime.client,
13002
+ );
13003
+ const { commitHash, isPagesDeployment } = localContext;
13004
+ let { metadata } = localContext;
13005
+ const deploymentName = _nullishCoalesce(options.name, () => ( metadata.name));
13006
+ let projectId = options.projectId || metadata.projectId;
13007
+ let appId = options.appId || metadata.appId;
13008
+ const appIdFromCoze = Boolean(metadata.appId && !options.appId);
13009
+ let projectCreated = false;
13010
+ let linkedApplicationType;
13011
+ if (appId) {
13012
+ const linkedApplication = await runtime.client.getApplication(appId);
13013
+ linkedApplicationType = linkedApplication.application_type;
13014
+ const linkedProjectId = linkedApplication.project_id;
13015
+ if (!options.appId && projectId && linkedProjectId && projectId !== linkedProjectId) {
13016
+ throw new CliError(
13017
+ `Project ${projectId} does not own application ${appId}; it belongs to project ${linkedProjectId}.`,
13018
+ 'PROJECT_ID_CONFLICT',
13019
+ );
13020
+ }
13021
+ if (options.appId && linkedProjectId) {
13022
+ projectId = linkedProjectId;
13023
+ } else {
13024
+ projectId ||= linkedProjectId;
13025
+ }
13026
+ if (!projectId) {
13027
+ throw new CliError(
13028
+ `Application ${appId} did not return its associated project_id.`,
13029
+ 'INVALID_RESPONSE',
13030
+ );
13031
+ }
13032
+ const inferredApplicationType = linkedApplicationType === 'pages'
13033
+ ? 'pages'
13034
+ : inferApplicationTypeFromProjectType(metadata.projectType);
13035
+ const targetApplicationType = requestedApplicationType || inferredApplicationType;
13036
+ if (appIdFromCoze && targetApplicationType && linkedApplicationType !== targetApplicationType) {
13037
+ runtime.output.warn(
13038
+ `The linked application ${appId} is ${linkedApplicationType}, but ${targetApplicationType} is required. A new application will be created and written to .coze.`,
13039
+ );
13040
+ appId = undefined;
13041
+ }
13042
+ }
13043
+ if (!projectId) {
13044
+ runtime.output.debug('[deploy] Creating a dedicated deployment project...');
13045
+ const spaceId = await resolveDeploymentSpaceId(runtime);
13046
+ const project = await runtime.client.createDeploymentProject({
13047
+ space_id: spaceId,
13048
+ user_query: deploymentName || 'CLI deployment project',
13049
+ project_type: resolveCreationProjectType(metadata.projectType),
13050
+ create_source: 'cli',
13051
+ project_settings: { project_symbol: 'v3.5' },
13052
+ });
13053
+ projectId = project.project_id;
13054
+ projectCreated = true;
13055
+ }
13056
+ if (metadata.projectId !== projectId) {
13057
+ metadata = await writeProjectBinding(sourceRoot, { projectId });
13058
+ }
13059
+ runtime.output.debug(`[deploy] Using project ${projectId} from ${projectCreated ? 'new project' : options.projectId ? '--project-id' : appId ? 'application binding' : '.coze'}`);
13060
+ const cozeFileContent = metadata.cozeFileContent;
13061
+ runtime.output.debug('[deploy] Loading deployment configuration...');
13062
+ const serverConfig = await runtime.client.getDeployConfig({
13063
+ ...(appId ? { app_id: appId } : { project_id: projectId }),
13064
+ commit_hash: commitHash,
13065
+ ...(isPagesDeployment ? { application_type: 'pages' } : {}),
13066
+ ...(cozeFileContent ? { coze_file_content: cozeFileContent } : {}),
13067
+ });
13068
+ const config = withRequestedApplicationType(
13069
+ serverConfig,
13070
+ requestedApplicationType,
13071
+ Boolean(appId),
13072
+ );
13073
+ const applicationType = config.application_type;
13074
+ const connectorConfigs = getConnectorConfigs(options.connectorId);
13075
+ if (!options.yes) {
13076
+ runtime.output.debug('[deploy] Preflight complete; confirmation is required.');
13077
+ runtime.output.print({
13078
+ confirmation_required: true,
13079
+ app_id: appId,
13080
+ project_id: projectId,
13081
+ application_type: applicationType,
13082
+ commit_hash: commitHash,
13083
+ source_root: sourceRoot,
13084
+ deploy_config: config.deploy_config,
13085
+ current_version: config.current_version,
13086
+ next_version: config.next_version,
13087
+ risks: config.risk_list || [],
13088
+ ...(!appId && deploymentName ? { name: deploymentName } : {}),
13089
+ message: options.message,
13090
+ lane: runtime.globalOptions.lane || runtime.config.xTTEnv,
13091
+ });
13092
+ return;
13093
+ }
13094
+ let encryptEnvVariable;
13095
+ if (applicationType !== 'pages') {
13096
+ runtime.output.debug('[deploy] Reading and encrypting local environment variables...');
13097
+ const envSecrets = await readProjectEnv(sourceRoot);
13098
+ const encrypted = await runtime.client.encryptProjectSecret(projectId, envSecrets);
13099
+ encryptEnvVariable = encrypted.sealed_secrets;
13100
+ if (!encryptEnvVariable) {
13101
+ throw new CliError(
13102
+ 'The project secret encryption API returned no sealed_secrets.',
13103
+ 'INVALID_RESPONSE',
13104
+ );
13105
+ }
13106
+ }
13107
+ runtime.output.debug(
13108
+ `[deploy] Building and packaging ${applicationType} artifact...`,
13109
+ );
13110
+ const sourcePackage = await createSourcePackageArchive(
13111
+ sourceRoot,
13112
+ applicationType,
13113
+ runtime.globalOptions.debug,
13114
+ );
13115
+ runtime.output.debug(
13116
+ `[deploy] Package ready: ${String(sourcePackage.sizeBytes)} bytes`,
13117
+ );
13118
+ runtime.output.debug('[deploy] Uploading package and creating deployment...');
13119
+ const deploymentRequest = {
13120
+ ...(appId ? { app_id: appId } : { project_id: projectId }),
13121
+ application_type: applicationType,
13122
+ commit_hash: commitHash,
13123
+ ...(!appId
13124
+ ? { name: deploymentName, source_root: sourceRoot }
13125
+ : {}),
13126
+ is_sync_db_to_prod: false,
13127
+ table_sync_configs: [],
13128
+ connector_configs: connectorConfigs,
13129
+ ...(cozeFileContent ? { coze_file_content: cozeFileContent } : {}),
13130
+ ...(encryptEnvVariable
13131
+ ? { encrypt_env_variable: encryptEnvVariable }
13132
+ : {}),
13133
+ ...getCreateDeployConfig(config),
13134
+ };
13135
+ let deployment;
13136
+ try {
13137
+ deployment = await createDeploymentWithSourcePackage(runtime.client, deploymentRequest, sourcePackage, sourceRoot);
13138
+ } finally {
13139
+ await sourcePackage.cleanup();
13140
+ }
13141
+ const { result } = deployment;
13142
+ const deployHistoryId = resolveDeployHistoryId(
13143
+ result.deploy_history_id,
13144
+ result.prev_deploy_history_id,
13145
+ );
13146
+ if (!deployHistoryId) {
13147
+ throw new CliError('Deployment response returned no deploy_history_id.', 'INVALID_RESPONSE');
13148
+ }
13149
+ if (metadata.appId !== result.app_id || metadata.projectId !== projectId) {
13150
+ await writeProjectBinding(sourceRoot, {
13151
+ projectId,
13152
+ appId: result.app_id,
13153
+ });
13154
+ if (!appId) {
13155
+ runtime.output.warn(`Created application ${result.app_id} and saved it to .coze.`);
13156
+ }
13157
+ }
13158
+ if (options.wait) {
13159
+ runtime.output.debug('[deploy] Deployment accepted; waiting for completion...');
13160
+ } else {
13161
+ runtime.output.debug('[deploy] Deployment accepted.');
13162
+ }
13163
+ const history = options.wait
13164
+ ? await pollHistory(command, result.app_id, deployHistoryId)
13165
+ : undefined;
13166
+ runtime.output.print({
13167
+ app_id: result.app_id,
13168
+ deploy_history_id: deployHistoryId,
13169
+ version: result.version,
13170
+ commit_hash: commitHash,
13171
+ status: getDeployStatusText(_nullishCoalesce(_optionalChain([history, 'optionalAccess', _ => _.status]), () => ( result.status))),
13172
+ source_package_size_bytes: sourcePackage.sizeBytes,
13173
+ upload_mode: deployment.uploadMode,
13174
+ local_link: appId && !projectCreated ? 'unchanged' : 'written',
13175
+ });
13176
+ });
13177
+
13178
+ deploy
13179
+ .command('status')
13180
+ .option('--app-id <appId>', 'Application ID')
13181
+ .option('--deploy-id <deployId>', 'Deployment history ID')
13182
+ .action(async (options, command) => {
13183
+ const runtime = await getRuntime(command);
13184
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13185
+ let deployHistoryId = options.deployId;
13186
+ if (!deployHistoryId) {
13187
+ deployHistoryId = await _asyncOptionalChain([(
13188
+ await runtime.client.listDeployHistory({ app_id: appId, page_size: 1 })
13189
+ ), 'access', async _2 => _2.deploy_history_list, 'optionalAccess', async _3 => _3[0], 'optionalAccess', async _4 => _4.deploy_history_id]);
13190
+ }
13191
+ if (!deployHistoryId) {
13192
+ throw new CliError('No deployment history found.', 'DEPLOYMENT_NOT_FOUND');
13193
+ }
13194
+ const history = await runtime.client.getDeployHistory({
13195
+ app_id: appId,
13196
+ deploy_history_id: deployHistoryId,
13197
+ });
13198
+ runtime.output.print({
13199
+ app_id: appId,
13200
+ deploy_history_id: deployHistoryId,
13201
+ status: getDeployStatusText(history.status),
13202
+ commit_hash: history.commit_hash,
13203
+ domains: history.domain_list || [],
13204
+ error_analysis: history.error_analysis,
13205
+ deploy_detail: formatDeployDetails(history),
13206
+ connector_data_list: history.connector_data_list || [],
13207
+ });
13208
+ });
13209
+
13210
+ deploy
13211
+ .command('list')
13212
+ .option('--app-id <appId>', 'Application ID')
13213
+ .option('--page-size <pageSize>', 'Page size', '10')
13214
+ .option('--page-token <pageToken>', 'Page token (page number)')
13215
+ .action(async (options, command) => {
13216
+ // 先在本地校验:`--page-size abc` 以前算出 NaN 发出去,表现成「参数没生效」。
13217
+ const pageSize = parsePageSize(options.pageSize, 10);
13218
+ const pageToken = parsePageToken(options.pageToken);
13219
+ const runtime = await getRuntime(command);
13220
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13221
+ const data = await runtime.client.listDeployHistory({
13222
+ app_id: appId,
13223
+ page_size: pageSize,
13224
+ page_token: pageToken,
13225
+ });
13226
+ runtime.output.print({
13227
+ items: (data.deploy_history_list || []).map(item => ({
13228
+ deploy_history_id: item.deploy_history_id,
13229
+ status: getDeployStatusText(item.status),
13230
+ commit_hash: item.commit_hash_short || item.commit_hash,
13231
+ created_at: item.created_at,
13232
+ can_rollback: item.can_rollback,
13233
+ deploy_detail: formatDeployDetails(item),
13234
+ connector_data_list: item.connector_data_list || [],
13235
+ })),
13236
+ next_page_token: data.next_page_token,
13237
+ has_more: data.has_more,
13238
+ });
13239
+ });
13240
+
13241
+ registerDeployReadCommands(deploy);
13242
+
13243
+ deploy
13244
+ .command('cancel')
13245
+ .requiredOption('--deploy-id <deployId>', 'Deployment history ID')
13246
+ .option('--app-id <appId>', 'Application ID')
13247
+ .option('--yes', 'Confirm cancellation')
13248
+ .action(async (options, command) => {
13249
+ const parentOptions = getDeployParentOptions(command);
13250
+ if (!options.yes && !parentOptions.yes) {
13251
+ throw new CliError('Pass --yes to cancel deployment.', 'CONFIRMATION_REQUIRED');
13252
+ }
13253
+ const runtime = await getRuntime(command);
13254
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13255
+ await runtime.client.cancelDeployHistory({
13256
+ app_id: appId,
13257
+ deploy_history_id: options.deployId || '',
13258
+ });
13259
+ runtime.output.print({ app_id: appId, canceled: true });
13260
+ });
13261
+
13262
+ deploy
13263
+ .command('rollback')
13264
+ .requiredOption('--deploy-id <deployId>', 'Target deployment history ID')
13265
+ .option('--app-id <appId>', 'Application ID')
13266
+ .option('--rollback-database', 'Rollback database')
13267
+ .option('--yes', 'Confirm rollback')
13268
+ .action(async (options, command) => {
13269
+ const parentOptions = getDeployParentOptions(command);
13270
+ if (!options.yes && !parentOptions.yes) {
13271
+ throw new CliError('Pass --yes to rollback.', 'CONFIRMATION_REQUIRED');
13272
+ }
13273
+ const runtime = await getRuntime(command);
13274
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13275
+ const data = await runtime.client.rollbackDeployHistory({
13276
+ app_id: appId,
13277
+ target_deploy_history_id: options.deployId || '',
13278
+ rollback_database: _nullishCoalesce(options.rollbackDatabase, () => ( false)),
13279
+ });
13280
+ runtime.output.print({ app_id: appId, ...data });
13281
+ });
13282
+
13283
+ // stop 不可逆(删函数 → Stopped,只能重新部署),pause 可逆(→ Paused,resume 能推回 Ready)。
13284
+ const applicationActions = {
13285
+ stop: (client, appId) => client.stopApplication(appId),
13286
+ resume: (client, appId) => client.resumeApplication(appId),
13287
+ pause: (client, appId) => client.pauseApplication(appId),
13288
+ } ;
13289
+
13290
+ for (const action of Object.keys(applicationActions) ) {
13291
+ deploy
13292
+ .command(action)
13293
+ .option('--app-id <appId>', 'Application ID')
13294
+ .option('--yes', `Confirm ${action}`)
13295
+ .action(async (options, command) => {
13296
+ const parentOptions = getDeployParentOptions(command);
13297
+ if (!options.yes && !parentOptions.yes) {
13298
+ throw new CliError(`Pass --yes to ${action}.`, 'CONFIRMATION_REQUIRED');
13299
+ }
13300
+ const runtime = await getRuntime(command);
13301
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13302
+ await applicationActions[action](runtime.client, appId);
13303
+ runtime.output.print({ app_id: appId, action, success: true });
13304
+ });
13305
+ }
13306
+
13307
+ deploy
13308
+ .command('logs')
13309
+ .option('--app-id <appId>', 'Application ID')
13310
+ .option('--start-time <startTime>', 'Start time in milliseconds')
13311
+ .option('--end-time <endTime>', 'End time in milliseconds')
13312
+ .option('--limit <limit>', 'Page size')
13313
+ .option('--cursor <cursor>', 'Pagination cursor')
13314
+ .option('--query <query>', 'Log keyword')
13315
+ .option('--level <level>', 'all, info, warn, or error')
13316
+ .action(async (options, command) => {
13317
+ const runtime = await getRuntime(command);
13318
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13319
+ runtime.output.print(
13320
+ await runtime.client.searchRuntimeLog({
13321
+ app_id: appId,
13322
+ start_time: options.startTime,
13323
+ end_time: options.endTime,
13324
+ limit: options.limit,
13325
+ cursor: options.cursor,
13326
+ query: options.query,
13327
+ level: options.level,
13328
+ }),
13329
+ );
13330
+ });
13331
+
13332
+ deploy
13333
+ .command('build-log')
13334
+ .requiredOption('--deploy-id <deployId>', 'Deployment history ID')
13335
+ .option('--key <key>', 'Deployment log key; inferred when the deployment has one log')
13336
+ .option('--app-id <appId>', 'Application ID')
13337
+ .action(async (options, command) => {
13338
+ const runtime = await getRuntime(command);
13339
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13340
+ let key = _optionalChain([options, 'access', _5 => _5.key, 'optionalAccess', _6 => _6.trim, 'call', _7 => _7()]);
13341
+ if (!key) {
13342
+ const history = await runtime.client.getDeployHistory({
13343
+ app_id: appId,
13344
+ deploy_history_id: options.deployId || '',
13345
+ });
13346
+ const keys = getDeployLogKeys(history);
13347
+ if (keys.length === 0) {
13348
+ throw new CliError(
13349
+ 'The deployment has no build log key yet. Retry after deployment stages start.',
13350
+ 'BUILD_LOG_NOT_READY',
13351
+ );
13352
+ }
13353
+ if (keys.length > 1) {
13354
+ throw new CliError(
13355
+ 'The deployment has multiple build logs. Pass --key using deploy status output.',
13356
+ 'BUILD_LOG_KEY_REQUIRED',
13357
+ { available_keys: keys },
13358
+ );
13359
+ }
13360
+ key = keys[0];
13361
+ }
13362
+ if (!key) {
13363
+ throw new CliError('Deployment log key is empty.', 'BUILD_LOG_NOT_READY');
13364
+ }
13365
+ runtime.output.print(
13366
+ await runtime.client.getBuildLog({
13367
+ app_id: appId,
13368
+ deploy_history_id: options.deployId || '',
13369
+ key,
13370
+ }),
13371
+ );
13372
+ });
13373
+
13374
+ deploy
13375
+ .command('config')
13376
+ .option('--app-id <appId>', 'Application ID')
13377
+ .option('--commit-id <commitId>', 'Commit hash')
13378
+ .action(async (options, command) => {
13379
+ const runtime = await getRuntime(command);
13380
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13381
+ const application = await runtime.client.getApplication(appId);
13382
+ const commitHash = options.commitId || _optionalChain([application, 'access', _8 => _8.latest_deployment, 'optionalAccess', _9 => _9.commit_hash]);
13383
+ if (!commitHash) {
13384
+ throw new CliError('No deployment commit is available.', 'DEPLOYMENT_NOT_FOUND');
13385
+ }
13386
+ const applicationType = application.application_type;
13387
+ const cozeFileContent = applicationType === 'pages'
13388
+ ? undefined
13389
+ : (await readProjectMetadata(node_path.resolve(runtime.cwd))).cozeFileContent;
13390
+ runtime.output.print(
13391
+ await runtime.client.getDeployConfig({
13392
+ app_id: appId,
13393
+ commit_hash: commitHash,
13394
+ ...(applicationType === 'pages' ? { application_type: 'pages' } : {}),
13395
+ ...(cozeFileContent ? { coze_file_content: cozeFileContent } : {}),
13396
+ }),
13397
+ );
13398
+ });
13399
+ };
13400
+
13401
+ const registerCommands = (program) => {
13402
+ registerAuth(program);
13403
+ registerContext(program);
13404
+ registerDoctor(program);
13405
+ const code = program.command('code').description('Deployment operations');
13406
+ registerApp(code);
13407
+ registerDeploy(code);
13408
+ registerDomain(code);
13409
+ registerEnv(code);
13410
+ registerMiniProgram(code);
13411
+ };
13412
+
13413
+ const configureDeployCommand = (command) => {
13414
+ markDeployCommand(command)
13415
+ .description('Deploy and manage Coze applications')
13416
+ .option('--format <format>', 'Output format: json or text', 'json')
13417
+ .option('--config <path>', 'Shared Coze CLI config path')
13418
+ .option('--org-id <id>', 'Override organization ID')
13419
+ .option('--space-id <id>', 'Override space ID')
13420
+ .option('--lane <name>', 'Route API requests to the specified PPE lane')
13421
+ .option('--api-base-url <url>', 'Override API base URL')
13422
+ .option('--debug', 'Print debug diagnostics')
13423
+ .showHelpAfterError()
13424
+ .exitOverride();
13425
+ registerCommands(command);
13426
+ return command;
13427
+ };
13428
+
13429
+ const registerCommand = (program) => {
13430
+ configureDeployCommand(program.command('deploy'));
13431
+ };
13432
+
13433
+ const readFormat = (argv) => {
13434
+ const index = argv.indexOf('--format');
13435
+ return index >= 0 && argv[index + 1] === 'text' ? 'text' : 'json';
13436
+ };
13437
+
13438
+ const handleDeployError = (error, argv = process.argv) => {
13439
+ if (
13440
+ error instanceof commander.CommanderError &&
13441
+ ['commander.helpDisplayed', 'commander.version'].includes(error.code)
13442
+ ) {
13443
+ return;
13444
+ }
13445
+ const output = new Output(readFormat(argv), argv.includes('--debug'));
13446
+ output.print({ error: toErrorPayload(error) });
13447
+ process.exitCode = error instanceof commander.CommanderError ? 4 : 1;
13448
+ };
13449
+
13450
+ const commands = [
13451
+ registerCommand$1,
13452
+ registerCommand$4,
13453
+ registerCommand$7,
13454
+ registerCommand$5,
13455
+ registerCommand$6,
13456
+ registerCommand$3,
13457
+ registerCommand$2,
13458
+ registerCommand,
13459
+ ];
13460
+
13461
+ const main = async () => {
13462
+ // 初始化 Slardar 监控
13463
+ initSlardar();
13464
+
13465
+ // 监听未捕获的异常
13466
+ process.on('uncaughtException', async (error) => {
13467
+ reportError(error, {
13468
+ type: 'uncaughtException',
13469
+ context: 'global',
13470
+ });
13471
+ await flushSlardar();
13472
+ process.exit(1);
13473
+ });
13474
+
13475
+ // 监听未处理的 Promise rejection
13476
+ process.on('unhandledRejection', async (reason) => {
13477
+ const error = reason instanceof Error ? reason : new Error(String(reason));
13478
+ reportError(error, {
13479
+ type: 'unhandledRejection',
13480
+ context: 'global',
13481
+ });
13482
+ await flushSlardar();
13483
+ process.exit(1);
13484
+ });
13485
+
13486
+ const program = new commander.Command();
13487
+
13488
+ program
13489
+ .name('coze-dev')
13490
+ .description(
13491
+ 'Coze Coding CLI - Project template engine for frontend stacks',
13492
+ )
13493
+ .version(packageJson.version);
13494
+
13495
+ commands.forEach(initCmd => initCmd(program));
13496
+
13497
+ // 在 help 输出中添加模板信息
13498
+ program.addHelpText('after', generateTemplatesHelpText());
13499
+
13500
+ // 使用 parseAsync 等待命令执行完成
13501
+ try {
13502
+ await program.parseAsync(process.argv);
13503
+ } catch (error) {
13504
+ if (process.argv[2] === 'deploy') {
13505
+ handleDeployError(error);
13506
+ } else {
13507
+ throw error;
13508
+ }
13509
+ }
10371
13510
 
10372
13511
  // 统一在命令执行完成后 flush
10373
13512
  // 注意:如果命令中调用了 process.exit(),不会执行到这里