esa-cli 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +206 -22
  2. package/bin/enter.cjs +45 -12
  3. package/dist/bin/enter.cjs +45 -12
  4. package/dist/commands/commit/index.js +5 -4
  5. package/dist/commands/deployments/delete.js +1 -1
  6. package/dist/commands/deployments/list.js +1 -1
  7. package/dist/commands/dev/build.js +4 -1
  8. package/dist/commands/dev/doProcess.js +94 -36
  9. package/dist/commands/domain/add.js +1 -1
  10. package/dist/commands/domain/delete.js +2 -3
  11. package/dist/commands/domain/list.js +1 -1
  12. package/dist/commands/init/helper.js +12 -8
  13. package/dist/commands/init/index.js +3 -4
  14. package/dist/commands/login/index.js +9 -5
  15. package/dist/commands/logout.js +3 -3
  16. package/dist/commands/route/add.js +1 -1
  17. package/dist/commands/route/delete.js +1 -1
  18. package/dist/commands/route/list.js +1 -1
  19. package/dist/commands/routine/delete.js +1 -2
  20. package/dist/commands/routine/list.js +1 -1
  21. package/dist/commands/site/list.js +1 -1
  22. package/dist/commands/utils.js +9 -3
  23. package/dist/components/mutiSelectTable.js +16 -83
  24. package/dist/components/routeBuilder.js +30 -54
  25. package/dist/components/selectInput.js +27 -13
  26. package/dist/docs/Commands_en.md +14 -2
  27. package/dist/docs/Commands_zh_CN.md +11 -1
  28. package/dist/i18n/locales.json +1 -1
  29. package/dist/index.js +8 -3
  30. package/dist/libs/api.js +0 -8
  31. package/dist/libs/logger.js +7 -2
  32. package/dist/utils/fileMd5.js +13 -3
  33. package/dist/utils/fileUtils/base.js +14 -18
  34. package/dist/utils/fileUtils/index.js +20 -0
  35. package/package.json +18 -20
  36. package/zh_CN.md +2 -2
  37. package/dist/components/descriptionInput.js +0 -38
  38. package/dist/components/filterSelector.js +0 -132
  39. package/dist/components/selectItem.js +0 -6
  40. package/dist/components/yesNoPrompt.js +0 -9
@@ -17,7 +17,7 @@ const listDomain = {
17
17
  command: 'list',
18
18
  describe: `🔍 ${t('domain_list_describe').d('List all related domains')}`,
19
19
  handler: () => __awaiter(void 0, void 0, void 0, function* () {
20
- handleListDomains();
20
+ yield handleListDomains();
21
21
  })
22
22
  };
23
23
  export default listDomain;
@@ -257,7 +257,7 @@ export const configProjectName = (initParams) => __awaiter(void 0, void 0, void
257
257
  return true;
258
258
  }
259
259
  }));
260
- initParams.name = name;
260
+ initParams.name = name || defaultName;
261
261
  });
262
262
  export const configCategory = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
263
263
  if (initParams.category || initParams.framework || initParams.template) {
@@ -429,7 +429,7 @@ export const applyFileEdits = (initParams) => __awaiter(void 0, void 0, void 0,
429
429
  // Very small glob subset: *, ?, {a,b,c}
430
430
  let escaped = pattern
431
431
  .replace(/[-/\\^$+?.()|[\]{}]/g, '\\$&') // escape regex specials first
432
- .replace(/\\\*/g, '.*')
432
+ .replace(/\*/g, '.*')
433
433
  .replace(/\\\?/g, '.');
434
434
  // restore and convert {a,b} to (a|b)
435
435
  escaped = escaped.replace(/\\\{([^}]+)\\\}/g, (_, inner) => {
@@ -455,7 +455,10 @@ export const applyFileEdits = (initParams) => __awaiter(void 0, void 0, void 0,
455
455
  let matchedFiles = [];
456
456
  if (edit.matchType === 'exact') {
457
457
  const absExact = path.join(targetPath, edit.match);
458
- matchedFiles = fs.existsSync(absExact) ? [edit.match] : [];
458
+ matchedFiles =
459
+ fs.existsSync(absExact) || edit.createIfMissing !== false
460
+ ? [edit.match]
461
+ : [];
459
462
  }
460
463
  else if (edit.matchType === 'glob') {
461
464
  const regex = toRegexFromGlob(edit.match);
@@ -482,8 +485,8 @@ export const applyFileEdits = (initParams) => __awaiter(void 0, void 0, void 0,
482
485
  const abs = path.join(targetPath, rel);
483
486
  if (payload == null)
484
487
  continue;
485
- if (!fs.existsSync(abs))
486
- continue; // Only overwrite existing files
488
+ if (!fs.existsSync(abs) && edit.createIfMissing === false)
489
+ continue;
487
490
  fs.ensureDirSync(path.dirname(abs));
488
491
  fs.writeFileSync(abs, payload, 'utf-8');
489
492
  }
@@ -497,7 +500,7 @@ export const applyFileEdits = (initParams) => __awaiter(void 0, void 0, void 0,
497
500
  }
498
501
  });
499
502
  export const installESACli = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
500
- if (!initParams.installEsaCli) {
503
+ if (typeof initParams.installEsaCli !== 'boolean') {
501
504
  const install = (yield promptParameter({
502
505
  type: 'confirm',
503
506
  question: 'Do you want to install esa-cli as a dev dependency?',
@@ -567,7 +570,7 @@ export const initGit = (initParams) => __awaiter(void 0, void 0, void 0, functio
567
570
  log.step('You have not installed Git, Git skipped');
568
571
  return true;
569
572
  }
570
- if (!initParams.git) {
573
+ if (typeof initParams.git !== 'boolean') {
571
574
  const initGit = (yield promptParameter({
572
575
  type: 'confirm',
573
576
  question: t('init_git').d('Do you want to init git in your project?'),
@@ -612,7 +615,8 @@ export function getGitVersion() {
612
615
  }
613
616
  export function isGitInstalled() {
614
617
  return __awaiter(this, void 0, void 0, function* () {
615
- return (yield getGitVersion()) !== '' && (yield getGitVersion()) !== null;
618
+ const gitVersion = yield getGitVersion();
619
+ return gitVersion !== '' && gitVersion !== null;
616
620
  });
617
621
  }
618
622
  /**
@@ -57,8 +57,7 @@ const init = {
57
57
  })
58
58
  .option('install-esa-cli', {
59
59
  describe: 'Install esa-cli as a dev dependency',
60
- type: 'boolean',
61
- default: false
60
+ type: 'boolean'
62
61
  });
63
62
  },
64
63
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
@@ -67,7 +66,7 @@ const init = {
67
66
  })
68
67
  };
69
68
  export default init;
70
- const handleInit = (argv) => __awaiter(void 0, void 0, void 0, function* () {
69
+ export const handleInit = (argv) => __awaiter(void 0, void 0, void 0, function* () {
71
70
  yield checkAndUpdatePackage('esa-template');
72
71
  const initParams = getInitParamsFromArgv(argv);
73
72
  yield create(initParams);
@@ -96,7 +95,7 @@ const config = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
96
95
  });
97
96
  const deploy = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
98
97
  intro(`Deploy an application with ESA ${chalk.gray('Step 3 of 3')}`);
99
- if (!initParams.deploy) {
98
+ if (typeof initParams.deploy !== 'boolean') {
100
99
  const deploy = (yield promptParameter({
101
100
  type: 'confirm',
102
101
  question: t('auto_deploy').d('Do you want to deploy your project?'),
@@ -66,17 +66,21 @@ const login = {
66
66
  });
67
67
  },
68
68
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
69
- handleLogin(argv);
69
+ yield handleLogin(argv);
70
70
  })
71
71
  };
72
72
  export default login;
73
73
  export function handleLogin(argv) {
74
74
  return __awaiter(this, void 0, void 0, function* () {
75
75
  generateDefaultConfig();
76
- const envSecurityToken = process.env.ESA_SECURITY_TOKEN;
77
- if (process.env.ESA_ACCESS_KEY_ID &&
78
- process.env.ESA_ACCESS_KEY_SECRET) {
79
- const result = yield validateCredentials(process.env.ESA_ACCESS_KEY_ID, process.env.ESA_ACCESS_KEY_SECRET, envSecurityToken);
76
+ const envAccessKeyId = process.env.ALIBABA_CLOUD_ACCESS_KEY_ID ||
77
+ process.env.ESA_ACCESS_KEY_ID;
78
+ const envAccessKeySecret = process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET ||
79
+ process.env.ESA_ACCESS_KEY_SECRET;
80
+ const envSecurityToken = process.env.ALIBABA_CLOUD_SECURITY_TOKEN ||
81
+ process.env.ESA_SECURITY_TOKEN;
82
+ if (envAccessKeyId && envAccessKeySecret) {
83
+ const result = yield validateCredentials(envAccessKeyId, envAccessKeySecret, envSecurityToken);
80
84
  if (result.valid) {
81
85
  logger.log(t('login_get_credentials_from_environment_variables').d('Get credentials from environment variables'));
82
86
  logger.success(t('login_success').d('Login success!'));
@@ -16,9 +16,9 @@ const logout = {
16
16
  builder: (yargs) => {
17
17
  return yargs;
18
18
  },
19
- handler: () => {
20
- handleLogout();
21
- }
19
+ handler: () => __awaiter(void 0, void 0, void 0, function* () {
20
+ yield handleLogout();
21
+ })
22
22
  };
23
23
  export default logout;
24
24
  export function handleLogout() {
@@ -47,7 +47,7 @@ const addRoute = {
47
47
  });
48
48
  },
49
49
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
50
- handlerAddRoute(argv);
50
+ yield handlerAddRoute(argv);
51
51
  })
52
52
  };
53
53
  export function handlerAddRoute(argv) {
@@ -34,7 +34,7 @@ const deleteRoute = {
34
34
  });
35
35
  },
36
36
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
37
- handleDeleteRoute(argv);
37
+ yield handleDeleteRoute(argv);
38
38
  })
39
39
  };
40
40
  export default deleteRoute;
@@ -19,7 +19,7 @@ const listRoute = {
19
19
  command: 'list',
20
20
  describe: `🔍 ${t('route_list_describe').d('List all related routes')}`,
21
21
  handler: () => __awaiter(void 0, void 0, void 0, function* () {
22
- handleListRoutes();
22
+ yield handleListRoutes();
23
23
  })
24
24
  };
25
25
  export default listRoute;
@@ -20,13 +20,12 @@ const deleteCommand = {
20
20
  .positional('projectName', {
21
21
  describe: t('delete_routineName_positional_describe').d('The name of the project to delete'),
22
22
  type: 'string',
23
- array: true,
24
23
  demandOption: true
25
24
  })
26
25
  .usage(`${t('common_usage').d('Usage')}: $0 delete <projectName>`);
27
26
  },
28
27
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
29
- handleDelete(argv);
28
+ yield handleDelete(argv);
30
29
  })
31
30
  };
32
31
  export default deleteCommand;
@@ -27,7 +27,7 @@ const list = {
27
27
  .usage(`${t('common_usage').d('Usage')}: \$0 list [--keyword <keyword>]`);
28
28
  },
29
29
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
30
- handleList(argv);
30
+ yield handleList(argv);
31
31
  })
32
32
  };
33
33
  export default list;
@@ -19,7 +19,7 @@ const list = {
19
19
  return yargs.usage(`${t('common_usage').d('Usage')}: \$0 list []`);
20
20
  },
21
21
  handler: () => __awaiter(void 0, void 0, void 0, function* () {
22
- handleList();
22
+ yield handleList();
23
23
  })
24
24
  };
25
25
  export default list;
@@ -80,9 +80,15 @@ export function checkIsLoginSuccess() {
80
80
  return __awaiter(this, void 0, void 0, function* () {
81
81
  var _a, _b, _c;
82
82
  const cliConfig = getCliConfig();
83
- let accessKeyId = process.env.ESA_ACCESS_KEY_ID || ((_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _a === void 0 ? void 0 : _a.accessKeyId);
84
- let accessKeySecret = process.env.ESA_ACCESS_KEY_SECRET || ((_b = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _b === void 0 ? void 0 : _b.accessKeySecret);
85
- const securityToken = process.env.ESA_SECURITY_TOKEN || ((_c = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _c === void 0 ? void 0 : _c.securityToken);
83
+ let accessKeyId = process.env.ALIBABA_CLOUD_ACCESS_KEY_ID ||
84
+ process.env.ESA_ACCESS_KEY_ID ||
85
+ ((_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _a === void 0 ? void 0 : _a.accessKeyId);
86
+ let accessKeySecret = process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET ||
87
+ process.env.ESA_ACCESS_KEY_SECRET ||
88
+ ((_b = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _b === void 0 ? void 0 : _b.accessKeySecret);
89
+ const securityToken = process.env.ALIBABA_CLOUD_SECURITY_TOKEN ||
90
+ process.env.ESA_SECURITY_TOKEN ||
91
+ ((_c = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _c === void 0 ? void 0 : _c.securityToken);
86
92
  if (accessKeyId && accessKeySecret) {
87
93
  const result = yield validateCredentials(accessKeyId, accessKeySecret, securityToken);
88
94
  const server = yield ApiService.getInstance();
@@ -7,89 +7,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { Box, render, Text, useInput } from 'ink';
11
- import React, { useState } from 'react';
10
+ import { multiselect, isCancel, cancel } from '@clack/prompts';
12
11
  import t from '../i18n/index.js';
13
- export const MultiSelectTable = ({ items, itemsPerRow, onSubmit, boxWidth = 25 }) => {
14
- const [selectedIndexes, setSelectedIndexes] = useState(new Set());
15
- const [cursorRow, setCursorRow] = useState(0);
16
- const [cursorCol, setCursorCol] = useState(0);
17
- const rows = [];
18
- for (let i = 0; i < items.length; i += itemsPerRow) {
19
- rows.push(items.slice(i, i + itemsPerRow));
20
- }
21
- const totalRows = Math.ceil(items.length / itemsPerRow);
22
- const toggleSelect = (row, col) => {
23
- const key = `${row}:${col}`;
24
- setSelectedIndexes((prevSelectedIndexes) => {
25
- const newSelectedIndexes = new Set(prevSelectedIndexes);
26
- if (newSelectedIndexes.has(key)) {
27
- newSelectedIndexes.delete(key);
28
- }
29
- else {
30
- newSelectedIndexes.add(key);
31
- }
32
- return newSelectedIndexes;
33
- });
34
- };
35
- const handleSubmission = () => {
36
- const selectedItems = Array.from(selectedIndexes).map((key) => {
37
- const [row, col] = key.split(':').map(Number);
38
- return rows[row][col];
39
- });
40
- onSubmit(selectedItems);
41
- };
42
- useInput((input, key) => {
43
- if (key.leftArrow) {
44
- setCursorCol((prev) => Math.max(prev - 1, 0));
45
- }
46
- else if (key.rightArrow) {
47
- setCursorCol((prev) => Math.min(prev + 1, itemsPerRow - 1));
48
- }
49
- else if (key.upArrow) {
50
- setCursorRow((prev) => Math.max(prev - 1, 0));
51
- }
52
- else if (key.downArrow) {
53
- setCursorRow((prev) => Math.min(prev + 1, totalRows - 1));
54
- }
55
- else if (input === ' ') {
56
- toggleSelect(cursorRow, cursorCol);
57
- }
58
- else if (key.tab) {
59
- setCursorCol((prevCol) => {
60
- let newCol = prevCol + 1;
61
- let newRow = cursorRow;
62
- if (newCol >= itemsPerRow) {
63
- newCol = 0;
64
- newRow = cursorRow + 1;
65
- if (newRow >= totalRows) {
66
- newRow = 0;
67
- }
68
- setCursorRow(newRow);
69
- }
70
- return newCol;
71
- });
72
- }
73
- else if (key.return) {
74
- handleSubmission();
75
- }
76
- });
77
- return (React.createElement(Box, { flexDirection: "column" },
78
- rows.map((rowItems, row) => (React.createElement(Box, { key: row, flexDirection: "row" }, rowItems.map((item, col) => (React.createElement(Box, { key: `${row}:${col}`, width: boxWidth },
79
- React.createElement(Text, { color: cursorRow === row && cursorCol === col ? 'green' : undefined },
80
- selectedIndexes.has(`${row}:${col}`) ? '✅' : ' ',
81
- item.label))))))),
82
- React.createElement(Box, { flexDirection: "column" },
83
- React.createElement(Text, null,
84
- "\uD83D\uDD14",
85
- ' ',
86
- t('deploy_select_table_tip').d('Use arrow keys to move, space to select, and enter to submit.')))));
87
- };
88
- export const displayMultiSelectTable = (items_1, ...args_1) => __awaiter(void 0, [items_1, ...args_1], void 0, function* (items, itemsPerRow = 7, boxWidth = 25) {
89
- return new Promise((resolve) => {
90
- const { unmount } = render(React.createElement(MultiSelectTable, { items: items, itemsPerRow: itemsPerRow, onSubmit: (selectedItems) => {
91
- unmount();
92
- resolve(selectedItems.map((item) => item.label));
93
- }, boxWidth: boxWidth }));
12
+ /**
13
+ * Multi-select prompt based on @clack/prompts.
14
+ * Replaces the previous ink grid table; keeps the same signature so
15
+ * existing call sites stay unchanged (itemsPerRow/boxWidth are obsolete).
16
+ */
17
+ export const displayMultiSelectTable = (items_1, ...args_1) => __awaiter(void 0, [items_1, ...args_1], void 0, function* (items, _itemsPerRow = 7, _boxWidth = 25) {
18
+ const value = yield multiselect({
19
+ message: t('deploy_select_table_tip').d('Use arrow keys to move, space to select, and enter to submit.'),
20
+ options: items.map((item) => ({ label: item.label, value: item.label })),
21
+ required: false
94
22
  });
23
+ if (isCancel(value)) {
24
+ cancel('Operation cancelled.');
25
+ process.exit(130);
26
+ }
27
+ return value;
95
28
  });
@@ -7,62 +7,38 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { Box, render, Text } from 'ink';
11
- import TextInput from 'ink-text-input';
12
- import React, { useState } from 'react';
10
+ import { text, isCancel } from '@clack/prompts';
11
+ import chalk from 'chalk';
13
12
  import t from '../i18n/index.js';
14
- export const RouteBuilder = ({ siteName, onSubmit, onCancel }) => {
15
- const [prefix, setPrefix] = useState('');
16
- const [suffix, setSuffix] = useState('');
17
- const [currentInput, setCurrentInput] = useState('prefix');
18
- const [error, setError] = useState('');
19
- const handleSubmit = () => {
20
- if (currentInput === 'prefix') {
21
- setCurrentInput('suffix');
22
- return;
23
- }
24
- // Build complete route, add dot before prefix and slash before suffix if not empty
25
- const prefixWithDot = prefix ? `${prefix}.` : '';
26
- const suffixWithDot = suffix ? `/${suffix}` : '';
27
- const route = `${prefixWithDot}${siteName}${suffixWithDot}`;
28
- onSubmit(route);
29
- };
30
- const handleCancel = () => {
31
- onCancel();
32
- };
33
- const currentPrompt = currentInput === 'prefix'
34
- ? t('route_builder_prefix_prompt')
13
+ import logger from '../libs/logger.js';
14
+ /**
15
+ * Interactively build a route for the given site (prefix + suffix),
16
+ * based on @clack/prompts. Returns the built route, or null if cancelled.
17
+ */
18
+ export const routeBuilder = (siteName) => __awaiter(void 0, void 0, void 0, function* () {
19
+ logger.log(`Building route for site: ${chalk.cyan(siteName)}`);
20
+ const prefix = yield text({
21
+ message: t('route_builder_prefix_prompt')
35
22
  .d(`Enter route prefix for ${siteName} (e.g., abc, def):`)
36
- .replace('${siteName}', siteName)
37
- : t('route_builder_suffix_prompt')
38
- .d(`Enter route suffix for ${siteName} (e.g., *, users/*):`)
39
- .replace('${siteName}', siteName);
23
+ .replace('${siteName}', siteName),
24
+ defaultValue: ''
25
+ });
26
+ if (isCancel(prefix)) {
27
+ return null;
28
+ }
40
29
  const prefixWithDot = prefix ? `${prefix}.` : '';
41
- const suffixWithDot = suffix ? `/${suffix}` : '';
42
- const preview = `Preview: ${prefixWithDot}${siteName}${suffixWithDot}`;
43
- return (React.createElement(Box, { flexDirection: "column" },
44
- React.createElement(Box, null,
45
- React.createElement(Text, null, "Building route for site: "),
46
- React.createElement(Text, { color: "cyan" }, siteName)),
47
- React.createElement(Box, { marginTop: 1 },
48
- React.createElement(Text, null, currentPrompt)),
49
- React.createElement(Box, { marginTop: 1 },
50
- React.createElement(TextInput, { value: currentInput === 'prefix' ? prefix : suffix, onChange: currentInput === 'prefix' ? setPrefix : setSuffix, onSubmit: handleSubmit })),
51
- preview && (React.createElement(Box, { marginTop: 1 },
52
- React.createElement(Text, { color: "green" }, preview))),
53
- React.createElement(Box, { marginTop: 1 },
54
- React.createElement(Text, { color: "gray" }, t('route_builder_instructions').d('Press Enter to continue, Ctrl+C to cancel'))),
55
- error && (React.createElement(Box, { marginTop: 1 },
56
- React.createElement(Text, { color: "red" }, error)))));
57
- };
58
- export const routeBuilder = (siteName) => __awaiter(void 0, void 0, void 0, function* () {
59
- return new Promise((resolve) => {
60
- const { unmount } = render(React.createElement(RouteBuilder, { siteName: siteName, onSubmit: (route) => {
61
- unmount();
62
- resolve(route);
63
- }, onCancel: () => {
64
- unmount();
65
- resolve(null);
66
- } }));
30
+ const suffix = yield text({
31
+ message: t('route_builder_suffix_prompt')
32
+ .d(`Enter route suffix for ${siteName} (e.g., *, users/*):`)
33
+ .replace('${siteName}', siteName),
34
+ placeholder: `Preview: ${prefixWithDot}${siteName}`,
35
+ defaultValue: ''
67
36
  });
37
+ if (isCancel(suffix)) {
38
+ return null;
39
+ }
40
+ const suffixWithSlash = suffix ? `/${suffix}` : '';
41
+ const route = `${prefixWithDot}${siteName}${suffixWithSlash}`;
42
+ logger.log(chalk.green(`Preview: ${route}`));
43
+ return route;
68
44
  });
@@ -1,16 +1,30 @@
1
- import { render, Text } from 'ink';
2
- import SelectInput from 'ink-select-input';
3
- import React from 'react';
4
- import Item from './selectItem.js';
5
- const Indicator = ({ isSelected }) => {
6
- return React.createElement(Text, null, isSelected ? '👉 ' : ' ');
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
7
9
  };
8
- const SelectItems = ({ items, handleSelect }) => {
9
- const { unmount } = render(React.createElement(SelectInput, { items: items, onSelect: onSelect, itemComponent: Item, indicatorComponent: Indicator }));
10
- function onSelect(item) {
11
- unmount();
12
- handleSelect(item);
10
+ import { select, isCancel, cancel } from '@clack/prompts';
11
+ /**
12
+ * Single-choice select prompt based on @clack/prompts.
13
+ * Keeps the callback-style API of the previous ink implementation
14
+ * so existing call sites stay unchanged.
15
+ */
16
+ const SelectItems = (_a) => __awaiter(void 0, [_a], void 0, function* ({ items, handleSelect, message = 'Please select' }) {
17
+ const value = yield select({
18
+ message,
19
+ options: items.map((item) => ({ label: item.label, value: item.value }))
20
+ });
21
+ if (isCancel(value)) {
22
+ cancel('Operation cancelled.');
23
+ process.exit(130);
13
24
  }
14
- return unmount;
15
- };
25
+ const selected = items.find((item) => item.value === value);
26
+ if (selected) {
27
+ yield handleSelect(selected);
28
+ }
29
+ });
16
30
  export default SelectItems;
@@ -345,11 +345,23 @@ AccessKey ID (AK)
345
345
  **--access-key-secret, --sk** _optional_
346
346
  AccessKey Secret (SK)
347
347
 
348
- **Environment Variables**
349
- Read from environment variables:
348
+ **--sts-token** _optional_
349
+
350
+ Temporary STS credentials in `AccessKeyId,AccessKeySecret,SecurityToken` or JSON format
351
+
352
+ **Environment Variables**
353
+
354
+ The standard Alibaba Cloud variables are preferred:
355
+
356
+ - **ALIBABA_CLOUD_ACCESS_KEY_ID**
357
+ - **ALIBABA_CLOUD_ACCESS_KEY_SECRET**
358
+ - **ALIBABA_CLOUD_SECURITY_TOKEN** _(optional)_
359
+
360
+ The legacy variables remain supported as lower-priority fallbacks:
350
361
 
351
362
  - **ESA_ACCESS_KEY_ID**
352
363
  - **ESA_ACCESS_KEY_SECRET**
364
+ - **ESA_SECURITY_TOKEN** _(optional)_
353
365
 
354
366
  ---
355
367
 
@@ -357,10 +357,20 @@ esa-cli login [OPTIONS]
357
357
  **--access-key-secret, --sk** _可选_
358
358
  **AccessKey Secret (SK)**
359
359
 
360
- **环境变量** _从环境变量中读取:_
360
+ **--sts-token** _可选_
361
+ **临时 STS 凭证,支持 `AccessKeyId,AccessKeySecret,SecurityToken` 或 JSON 格式**
362
+
363
+ **环境变量** _优先读取阿里云标准环境变量:_
364
+
365
+ - **ALIBABA_CLOUD_ACCESS_KEY_ID**
366
+ - **ALIBABA_CLOUD_ACCESS_KEY_SECRET**
367
+ - **ALIBABA_CLOUD_SECURITY_TOKEN** _可选_
368
+
369
+ **以下旧变量继续作为低优先级兼容项:**
361
370
 
362
371
  - **ESA_ACCESS_KEY_ID**
363
372
  - **ESA_ACCESS_KEY_SECRET**
373
+ - **ESA_SECURITY_TOKEN** _可选_
364
374
 
365
375
  ---
366
376
 
@@ -164,7 +164,7 @@
164
164
  "zh_CN": "帮助"
165
165
  },
166
166
  "common_sub_command_fail": {
167
- "en": "Use esa-cli <command> -h to see help",
167
+ "en": "Use ${cliName} <command> -h to see help",
168
168
  "zh_CN": "使用 esa-cli <command> -h 查看帮助"
169
169
  },
170
170
  "deployments_delete_describe": {
package/dist/index.js CHANGED
@@ -27,15 +27,20 @@ import t from './i18n/index.js';
27
27
  import logger from './libs/logger.js';
28
28
  import { handleCheckVersion, checkCLIVersion } from './utils/checkVersion.js';
29
29
  import { getCliConfig } from './utils/fileUtils/index.js';
30
+ const cliName = process.env.ALIBABA_CLOUD_ESA_CLI_COMPAT_MODE || 'esa-cli';
30
31
  const main = () => __awaiter(void 0, void 0, void 0, function* () {
31
32
  const argv = hideBin(process.argv);
32
33
  const cliConfig = getCliConfig();
33
34
  const esa = yargs(argv)
34
35
  .strict()
35
36
  .fail((msg, err) => {
36
- console.error(msg, err);
37
+ if (msg)
38
+ console.error(msg);
39
+ if (err)
40
+ console.error(err);
41
+ process.exit(1);
37
42
  })
38
- .scriptName('esa-cli')
43
+ .scriptName(cliName)
39
44
  .locale((cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.lang) || 'en')
40
45
  .version(false)
41
46
  .wrap(null)
@@ -78,7 +83,7 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
78
83
  esa.command('*', false, () => { }, (args) => {
79
84
  if (args._.length > 0) {
80
85
  // Unknown command
81
- console.error(t('common_sub_command_fail').d('Use esa-cli <command> -h to see help'));
86
+ console.error(t('common_sub_command_fail').d(`Use ${cliName} <command> -h to see help`));
82
87
  }
83
88
  else {
84
89
  if (args.v) {
package/dist/libs/api.js CHANGED
@@ -113,14 +113,6 @@ class Client {
113
113
  const request = new $ESA.DeleteRoutineCodeVersionRequest(params);
114
114
  return this.callApi(this.client.deleteRoutineCodeVersionWithOptions.bind(this.client), request);
115
115
  }
116
- createRoutineRelatedRoute(params) {
117
- const request = new $ESA.CreateRoutineRelatedRouteRequest(params);
118
- return this.callApi(this.client.createRoutineRelatedRouteWithOptions.bind(this.client), request);
119
- }
120
- deleteRoutineRelatedRoute(params) {
121
- const request = new $ESA.DeleteRoutineRelatedRouteRequest(params);
122
- return this.callApi(this.client.deleteRoutineRelatedRouteWithOptions.bind(this.client), request);
123
- }
124
116
  listSites(params) {
125
117
  const request = new $ESA.ListSitesRequest(params);
126
118
  return this.callApi(this.client.listSitesWithOptions.bind(this.client), request);
@@ -7,7 +7,10 @@ import { format, createLogger } from 'winston';
7
7
  import DailyRotateFile from 'winston-daily-rotate-file';
8
8
  import t from '../i18n/index.js';
9
9
  import { getProjectConfig } from '../utils/fileUtils/index.js';
10
- const transport = new DailyRotateFile({
10
+ const shouldWriteLogFile = () => process.env.NODE_ENV !== 'test' &&
11
+ !process.env.VITEST &&
12
+ !process.env.VITEST_WORKER_ID;
13
+ const createFileTransport = () => new DailyRotateFile({
11
14
  filename: path.join(os.homedir(), '.esa-logs/esa-debug-%DATE%.log'),
12
15
  level: 'info',
13
16
  datePattern: 'YYYY-MM-DD-HH',
@@ -46,10 +49,12 @@ class Logger {
46
49
  }
47
50
  return `${printTimestamp} [${chalk.green(printLabel)}] ${colorizedLevel} in ${chalk.italic(projName)}: ${message}`;
48
51
  });
52
+ const transports = shouldWriteLogFile() ? [createFileTransport()] : [];
49
53
  this.logger = createLogger({
50
54
  level: 'info',
51
55
  format: combine(label({ label: 'ESA' }), timestamp(), customFormat),
52
- transports: [transport]
56
+ silent: transports.length === 0,
57
+ transports
53
58
  });
54
59
  this.spinner = ora('Loading...');
55
60
  }
@@ -4,15 +4,25 @@ export function calculateFileMD5(filePath) {
4
4
  return new Promise((resolve, reject) => {
5
5
  const hash = crypto.createHash('md5');
6
6
  const fileStream = fs.createReadStream(filePath);
7
+ let md5sum = '';
8
+ let settled = false;
7
9
  fileStream.on('data', (data) => {
8
10
  hash.update(data);
9
11
  });
10
12
  fileStream.on('end', () => {
11
- const md5sum = hash.digest('hex');
12
- resolve(md5sum);
13
+ md5sum = hash.digest('hex');
14
+ });
15
+ fileStream.on('close', () => {
16
+ if (!settled) {
17
+ settled = true;
18
+ resolve(md5sum);
19
+ }
13
20
  });
14
21
  fileStream.on('error', (err) => {
15
- reject(err);
22
+ if (!settled) {
23
+ settled = true;
24
+ reject(err);
25
+ }
16
26
  });
17
27
  });
18
28
  }