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