@coze-arch/cli 0.0.36-alpha.8cf839 → 0.0.36-alpha.fde2b5

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.
@@ -61,12 +61,11 @@ PID_FILE="${LOG_DIR}/phaser-dev.pid"
61
61
  mkdir -p "${LOG_DIR}"
62
62
 
63
63
  echo "Starting Phaser dev server on port ${DEPLOY_RUN_PORT}..."
64
- COZE_PHASER_GAME_ENV=DEV nohup pnpm vite \
64
+ server_pid="$(COZE_PHASER_GAME_ENV=DEV node scripts/spawn-detached.cjs \
65
+ "${LOG_FILE}" pnpm vite \
65
66
  --port "${DEPLOY_RUN_PORT}" \
66
67
  --host 127.0.0.1 \
67
- --strictPort \
68
- > "${LOG_FILE}" 2>&1 < /dev/null &
69
- server_pid=$!
68
+ --strictPort)"
70
69
  echo "${server_pid}" > "${PID_FILE}"
71
70
 
72
71
  sleep 1
@@ -77,7 +76,6 @@ if ! kill -0 "${server_pid}" 2>/dev/null; then
77
76
  exit 1
78
77
  fi
79
78
 
80
- disown "${server_pid}" 2>/dev/null || true
81
79
  echo "Phaser dev server started (PID: ${server_pid})."
82
80
  echo "Log file: ${LOG_FILE}"
83
81
  echo "PID file: ${PID_FILE}"
@@ -0,0 +1,29 @@
1
+ const fs = require('node:fs');
2
+ const { spawn } = require('node:child_process');
3
+
4
+ const [logFile, command, ...args] = process.argv.slice(2);
5
+
6
+ if (!logFile || !command) {
7
+ process.stderr.write(
8
+ 'Usage: node scripts/spawn-detached.cjs <log-file> <command> [...args]\n',
9
+ );
10
+ process.exit(1);
11
+ }
12
+
13
+ const logFd = fs.openSync(logFile, 'a');
14
+ const child = spawn(command, args, {
15
+ cwd: process.cwd(),
16
+ detached: process.platform !== 'win32',
17
+ env: process.env,
18
+ stdio: ['ignore', logFd, logFd],
19
+ });
20
+
21
+ fs.closeSync(logFd);
22
+ child.unref();
23
+
24
+ if (!child.pid) {
25
+ process.stderr.write('Failed to start detached process.\n');
26
+ process.exit(1);
27
+ }
28
+
29
+ process.stdout.write(String(child.pid));
@@ -61,12 +61,11 @@ PID_FILE="${LOG_DIR}/phaser-start.pid"
61
61
  mkdir -p "${LOG_DIR}"
62
62
 
63
63
  echo "Starting Phaser production server on port ${DEPLOY_RUN_PORT}..."
64
- COZE_PHASER_GAME_ENV=PROD nohup pnpm vite preview \
64
+ server_pid="$(COZE_PHASER_GAME_ENV=PROD node scripts/spawn-detached.cjs \
65
+ "${LOG_FILE}" pnpm vite preview \
65
66
  --port "${DEPLOY_RUN_PORT}" \
66
67
  --host 127.0.0.1 \
67
- --strictPort \
68
- > "${LOG_FILE}" 2>&1 < /dev/null &
69
- server_pid=$!
68
+ --strictPort)"
70
69
  echo "${server_pid}" > "${PID_FILE}"
71
70
 
72
71
  sleep 1
@@ -77,7 +76,6 @@ if ! kill -0 "${server_pid}" 2>/dev/null; then
77
76
  exit 1
78
77
  fi
79
78
 
80
- disown "${server_pid}" 2>/dev/null || true
81
79
  echo "Phaser production server started (PID: ${server_pid})."
82
80
  echo "Log file: ${LOG_FILE}"
83
81
  echo "PID file: ${PID_FILE}"
package/lib/cli.js CHANGED
@@ -2113,7 +2113,7 @@ const EventBuilder = {
2113
2113
  };
2114
2114
 
2115
2115
  var name = "@coze-arch/cli";
2116
- var version = "0.0.36-alpha.8cf839";
2116
+ var version = "0.0.36-alpha.fde2b5";
2117
2117
  var description = "coze coding devtools cli";
2118
2118
  var license = "MIT";
2119
2119
  var author = "fanwenjie.fe@bytedance.com";
@@ -11743,7 +11743,157 @@ const readDeployLocalContext = async (
11743
11743
  return { ...sourceSnapshot, metadata, isPagesDeployment };
11744
11744
  };
11745
11745
 
11746
+ // 服务端 deploy_app/list 的 page_size 上限,超了会被判参数错误。
11747
+ // 客户端先拦一道,是为了把错误说在本地(带上上限值),而不是回一句服务端的通用参数错误。
11748
+ const APP_LIST_MAX_PAGE_SIZE = 100;
11749
+
11750
+ // page_token 是**页码的十进制字符串**(服务端口径,与 deploy_history/list 一致),不是不透明游标。
11751
+ // 所以这里能、也应该在本地校验:`--page-token abc` 早报错,比发出去再被拒强。
11752
+ const parsePositiveInt = (
11753
+ raw,
11754
+ option,
11755
+ code,
11756
+ max,
11757
+ ) => {
11758
+ const value = Number(raw);
11759
+ if (!Number.isSafeInteger(value) || value <= 0) {
11760
+ throw new CliError(`${option} must be a positive integer.`, code, { [option]: raw });
11761
+ }
11762
+ if (max !== undefined && value > max) {
11763
+ throw new CliError(`${option} must not exceed ${String(max)}.`, code, { [option]: raw });
11764
+ }
11765
+ return value;
11766
+ };
11767
+
11768
+ // ⛔ 别再用 `Number(options.pageSize || 20)`:`--page-size abc` 会算出 NaN,
11769
+ // JSON.stringify 把它写成 null 发给服务端,最后表现为「参数没生效」而不是「参数写错了」。
11770
+ const parsePageSize = (
11771
+ raw,
11772
+ fallback,
11773
+ max,
11774
+ ) => {
11775
+ if (raw === undefined || raw === '') {
11776
+ return fallback;
11777
+ }
11778
+ return parsePositiveInt(raw, '--page-size', 'INVALID_PAGE_SIZE', max);
11779
+ };
11780
+
11781
+ const parsePageToken = (raw) => {
11782
+ if (raw === undefined || raw === '') {
11783
+ return undefined;
11784
+ }
11785
+ parsePositiveInt(raw, '--page-token', 'INVALID_PAGE_TOKEN');
11786
+ return raw;
11787
+ };
11788
+
11789
+
11790
+
11791
+
11792
+
11793
+
11794
+
11795
+ // collectAllPages 顺着 next_page_token 把所有页取回来。
11796
+ //
11797
+ // 服务端从「全量单页」改成真分页之后,`app list` 一次只回一页;想要「我的全部应用」就得翻页。
11798
+ // 与其让每个调用方各写一遍循环,不如给一个 --all。
11799
+ //
11800
+ // ⚠️ 不设页数上限截断:静默截断正是这次要修掉的毛病。只防死循环——服务端如果一直回同一个
11801
+ // token(或说 has_more 却不给 token),直接报错,而不是无限翻。
11802
+ const collectAllPages = async (
11803
+ fetchPage,
11804
+ ) => {
11805
+ const items = [];
11806
+ const seen = new Set();
11807
+ let pageToken;
11808
+ let pages = 0;
11809
+ for (;;) {
11810
+ const page = await fetchPage(pageToken);
11811
+ items.push(...(page.items || []));
11812
+ pages += 1;
11813
+ if (!page.has_more) {
11814
+ return { items, pages };
11815
+ }
11816
+ const next = page.next_page_token;
11817
+ if (!next || seen.has(next)) {
11818
+ throw new CliError(
11819
+ 'The server reported more pages but returned no usable next_page_token.',
11820
+ 'INVALID_PAGE_TOKEN',
11821
+ { next_page_token: next, pages },
11822
+ );
11823
+ }
11824
+ seen.add(next);
11825
+ pageToken = next;
11826
+ }
11827
+ };
11828
+
11829
+ 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; }
11830
+
11746
11831
  const registerDeployReadCommands = (deploy) => {
11832
+ deploy
11833
+ .command('status')
11834
+ .option('--app-id <appId>', 'Application ID')
11835
+ .option('--deploy-id <deployId>', 'Deployment history ID')
11836
+ .action(async (options, command) => {
11837
+ const runtime = await getRuntime(command);
11838
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
11839
+ let deployHistoryId = options.deployId;
11840
+ if (!deployHistoryId) {
11841
+ deployHistoryId = await _asyncOptionalChain([(
11842
+ await runtime.client.listDeployHistory({ app_id: appId, page_size: 1 })
11843
+ ), 'access', async _ => _.deploy_history_list, 'optionalAccess', async _2 => _2[0], 'optionalAccess', async _3 => _3.deploy_history_id]);
11844
+ }
11845
+ if (!deployHistoryId) {
11846
+ throw new CliError('No deployment history found.', 'DEPLOYMENT_NOT_FOUND');
11847
+ }
11848
+ const history = await runtime.client.getDeployHistory({
11849
+ app_id: appId,
11850
+ deploy_history_id: deployHistoryId,
11851
+ });
11852
+ runtime.output.print({
11853
+ app_id: appId,
11854
+ deploy_history_id: deployHistoryId,
11855
+ status: getDeployStatusText(history.status),
11856
+ commit_hash: history.commit_hash,
11857
+ domains: history.domain_list || [],
11858
+ error_analysis: history.error_analysis,
11859
+ deploy_detail: formatDeployDetails(history),
11860
+ connector_data_list: history.connector_data_list || [],
11861
+ mobile_artifact_list: history.mobile_artifact_list || [],
11862
+ });
11863
+ });
11864
+
11865
+ deploy
11866
+ .command('list')
11867
+ .option('--app-id <appId>', 'Application ID')
11868
+ .option('--page-size <pageSize>', 'Page size', '10')
11869
+ .option('--page-token <pageToken>', 'Page token (page number)')
11870
+ .action(async (options, command) => {
11871
+ // 先在本地校验:`--page-size abc` 以前算出 NaN 发出去,表现成「参数没生效」。
11872
+ const pageSize = parsePageSize(options.pageSize, 10);
11873
+ const pageToken = parsePageToken(options.pageToken);
11874
+ const runtime = await getRuntime(command);
11875
+ const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
11876
+ const data = await runtime.client.listDeployHistory({
11877
+ app_id: appId,
11878
+ page_size: pageSize,
11879
+ page_token: pageToken,
11880
+ });
11881
+ runtime.output.print({
11882
+ items: (data.deploy_history_list || []).map(item => ({
11883
+ deploy_history_id: item.deploy_history_id,
11884
+ status: getDeployStatusText(item.status),
11885
+ commit_hash: item.commit_hash_short || item.commit_hash,
11886
+ created_at: item.created_at,
11887
+ can_rollback: item.can_rollback,
11888
+ deploy_detail: formatDeployDetails(item),
11889
+ connector_data_list: item.connector_data_list || [],
11890
+ mobile_artifact_list: item.mobile_artifact_list || [],
11891
+ })),
11892
+ next_page_token: data.next_page_token,
11893
+ has_more: data.has_more,
11894
+ });
11895
+ });
11896
+
11747
11897
  deploy
11748
11898
  .command('online')
11749
11899
  .description('Show the current online deployment')
@@ -11761,6 +11911,7 @@ const registerDeployReadCommands = (deploy) => {
11761
11911
  created_at: item.created_at,
11762
11912
  deploy_detail: formatDeployDetails(item),
11763
11913
  domains: item.domain_list || [],
11914
+ mobile_artifact_list: item.mobile_artifact_list || [],
11764
11915
  })),
11765
11916
  });
11766
11917
  });
@@ -11957,89 +12108,6 @@ const registerMiniProgram = (code) => {
11957
12108
  });
11958
12109
  };
11959
12110
 
11960
- // 服务端 deploy_app/list 的 page_size 上限,超了会被判参数错误。
11961
- // 客户端先拦一道,是为了把错误说在本地(带上上限值),而不是回一句服务端的通用参数错误。
11962
- const APP_LIST_MAX_PAGE_SIZE = 100;
11963
-
11964
- // page_token 是**页码的十进制字符串**(服务端口径,与 deploy_history/list 一致),不是不透明游标。
11965
- // 所以这里能、也应该在本地校验:`--page-token abc` 早报错,比发出去再被拒强。
11966
- const parsePositiveInt = (
11967
- raw,
11968
- option,
11969
- code,
11970
- max,
11971
- ) => {
11972
- const value = Number(raw);
11973
- if (!Number.isSafeInteger(value) || value <= 0) {
11974
- throw new CliError(`${option} must be a positive integer.`, code, { [option]: raw });
11975
- }
11976
- if (max !== undefined && value > max) {
11977
- throw new CliError(`${option} must not exceed ${String(max)}.`, code, { [option]: raw });
11978
- }
11979
- return value;
11980
- };
11981
-
11982
- // ⛔ 别再用 `Number(options.pageSize || 20)`:`--page-size abc` 会算出 NaN,
11983
- // JSON.stringify 把它写成 null 发给服务端,最后表现为「参数没生效」而不是「参数写错了」。
11984
- const parsePageSize = (
11985
- raw,
11986
- fallback,
11987
- max,
11988
- ) => {
11989
- if (raw === undefined || raw === '') {
11990
- return fallback;
11991
- }
11992
- return parsePositiveInt(raw, '--page-size', 'INVALID_PAGE_SIZE', max);
11993
- };
11994
-
11995
- const parsePageToken = (raw) => {
11996
- if (raw === undefined || raw === '') {
11997
- return undefined;
11998
- }
11999
- parsePositiveInt(raw, '--page-token', 'INVALID_PAGE_TOKEN');
12000
- return raw;
12001
- };
12002
-
12003
-
12004
-
12005
-
12006
-
12007
-
12008
-
12009
- // collectAllPages 顺着 next_page_token 把所有页取回来。
12010
- //
12011
- // 服务端从「全量单页」改成真分页之后,`app list` 一次只回一页;想要「我的全部应用」就得翻页。
12012
- // 与其让每个调用方各写一遍循环,不如给一个 --all。
12013
- //
12014
- // ⚠️ 不设页数上限截断:静默截断正是这次要修掉的毛病。只防死循环——服务端如果一直回同一个
12015
- // token(或说 has_more 却不给 token),直接报错,而不是无限翻。
12016
- const collectAllPages = async (
12017
- fetchPage,
12018
- ) => {
12019
- const items = [];
12020
- const seen = new Set();
12021
- let pageToken;
12022
- let pages = 0;
12023
- for (;;) {
12024
- const page = await fetchPage(pageToken);
12025
- items.push(...(page.items || []));
12026
- pages += 1;
12027
- if (!page.has_more) {
12028
- return { items, pages };
12029
- }
12030
- const next = page.next_page_token;
12031
- if (!next || seen.has(next)) {
12032
- throw new CliError(
12033
- 'The server reported more pages but returned no usable next_page_token.',
12034
- 'INVALID_PAGE_TOKEN',
12035
- { next_page_token: next, pages },
12036
- );
12037
- }
12038
- seen.add(next);
12039
- pageToken = next;
12040
- }
12041
- };
12042
-
12043
12111
  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; }
12044
12112
 
12045
12113
  const POLL_INTERVAL_MS = 3000;
@@ -12753,7 +12821,7 @@ const createDeploymentWithSourcePackage = async (
12753
12821
  return { uploadMode: 'direct' , result };
12754
12822
  };
12755
12823
 
12756
- 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; }
12824
+ 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; }
12757
12825
  const SUPPORTED_MINIPROGRAM_CONNECTOR_IDS = new Set(['10000127', '10000126']);
12758
12826
  const collectConnectorId = (value, previous) => [
12759
12827
  ...previous,
@@ -12996,69 +13064,7 @@ const registerDeploy = (code) => {
12996
13064
  source_package_size_bytes: sourcePackage.sizeBytes,
12997
13065
  upload_mode: deployment.uploadMode,
12998
13066
  local_link: appId && !projectCreated ? 'unchanged' : 'written',
12999
- });
13000
- });
13001
-
13002
- deploy
13003
- .command('status')
13004
- .option('--app-id <appId>', 'Application ID')
13005
- .option('--deploy-id <deployId>', 'Deployment history ID')
13006
- .action(async (options, command) => {
13007
- const runtime = await getRuntime(command);
13008
- const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13009
- let deployHistoryId = options.deployId;
13010
- if (!deployHistoryId) {
13011
- deployHistoryId = await _asyncOptionalChain([(
13012
- await runtime.client.listDeployHistory({ app_id: appId, page_size: 1 })
13013
- ), 'access', async _3 => _3.deploy_history_list, 'optionalAccess', async _4 => _4[0], 'optionalAccess', async _5 => _5.deploy_history_id]);
13014
- }
13015
- if (!deployHistoryId) {
13016
- throw new CliError('No deployment history found.', 'DEPLOYMENT_NOT_FOUND');
13017
- }
13018
- const history = await runtime.client.getDeployHistory({
13019
- app_id: appId,
13020
- deploy_history_id: deployHistoryId,
13021
- });
13022
- runtime.output.print({
13023
- app_id: appId,
13024
- deploy_history_id: deployHistoryId,
13025
- status: getDeployStatusText(history.status),
13026
- commit_hash: history.commit_hash,
13027
- domains: history.domain_list || [],
13028
- error_analysis: history.error_analysis,
13029
- deploy_detail: formatDeployDetails(history),
13030
- connector_data_list: history.connector_data_list || [],
13031
- });
13032
- });
13033
-
13034
- deploy
13035
- .command('list')
13036
- .option('--app-id <appId>', 'Application ID')
13037
- .option('--page-size <pageSize>', 'Page size', '10')
13038
- .option('--page-token <pageToken>', 'Page token (page number)')
13039
- .action(async (options, command) => {
13040
- // 先在本地校验:`--page-size abc` 以前算出 NaN 发出去,表现成「参数没生效」。
13041
- const pageSize = parsePageSize(options.pageSize, 10);
13042
- const pageToken = parsePageToken(options.pageToken);
13043
- const runtime = await getRuntime(command);
13044
- const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13045
- const data = await runtime.client.listDeployHistory({
13046
- app_id: appId,
13047
- page_size: pageSize,
13048
- page_token: pageToken,
13049
- });
13050
- runtime.output.print({
13051
- items: (data.deploy_history_list || []).map(item => ({
13052
- deploy_history_id: item.deploy_history_id,
13053
- status: getDeployStatusText(item.status),
13054
- commit_hash: item.commit_hash_short || item.commit_hash,
13055
- created_at: item.created_at,
13056
- can_rollback: item.can_rollback,
13057
- deploy_detail: formatDeployDetails(item),
13058
- connector_data_list: item.connector_data_list || [],
13059
- })),
13060
- next_page_token: data.next_page_token,
13061
- has_more: data.has_more,
13067
+ mobile_artifact_list: _optionalChain([history, 'optionalAccess', _3 => _3.mobile_artifact_list]) || [],
13062
13068
  });
13063
13069
  });
13064
13070
 
@@ -13161,7 +13167,7 @@ const registerDeploy = (code) => {
13161
13167
  .action(async (options, command) => {
13162
13168
  const runtime = await getRuntime(command);
13163
13169
  const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13164
- let key = _optionalChain([options, 'access', _6 => _6.key, 'optionalAccess', _7 => _7.trim, 'call', _8 => _8()]);
13170
+ let key = _optionalChain([options, 'access', _4 => _4.key, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]);
13165
13171
  if (!key) {
13166
13172
  const history = await runtime.client.getDeployHistory({
13167
13173
  app_id: appId,
@@ -13203,7 +13209,7 @@ const registerDeploy = (code) => {
13203
13209
  const runtime = await getRuntime(command);
13204
13210
  const appId = await requireAppId(runtime.cwd, getDeployAppIdOption(options, command));
13205
13211
  const application = await runtime.client.getApplication(appId);
13206
- const commitHash = options.commitId || _optionalChain([application, 'access', _9 => _9.latest_deployment, 'optionalAccess', _10 => _10.commit_hash]);
13212
+ const commitHash = options.commitId || _optionalChain([application, 'access', _7 => _7.latest_deployment, 'optionalAccess', _8 => _8.commit_hash]);
13207
13213
  if (!commitHash) {
13208
13214
  throw new CliError('No deployment commit is available.', 'DEPLOYMENT_NOT_FOUND');
13209
13215
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coze-arch/cli",
3
- "version": "0.0.36-alpha.8cf839",
3
+ "version": "0.0.36-alpha.fde2b5",
4
4
  "private": false,
5
5
  "description": "coze coding devtools cli",
6
6
  "license": "MIT",