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