esa-cli 0.0.1-beta.9 → 0.0.2-beta.0

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 (44) hide show
  1. package/README.md +4 -6
  2. package/bin/enter.cjs +0 -1
  3. package/dist/README.md +4 -6
  4. package/dist/bin/enter.cjs +0 -1
  5. package/dist/commands/commit/index.js +2 -2
  6. package/dist/commands/deploy/index.js +4 -2
  7. package/dist/commands/deployments/list.js +2 -1
  8. package/dist/commands/dev/build.js +57 -0
  9. package/dist/commands/dev/doProcess.js +10 -2
  10. package/dist/commands/dev/ew2/devEntry.js +9 -0
  11. package/dist/commands/dev/ew2/devPack.js +185 -0
  12. package/dist/commands/dev/ew2/mock/cache.js +32 -0
  13. package/dist/commands/dev/ew2/mock/kv.js +45 -0
  14. package/dist/commands/dev/ew2/server.js +234 -0
  15. package/dist/commands/dev/index.js +111 -49
  16. package/dist/commands/dev/{config → mockWorker}/devEntry.js +3 -2
  17. package/dist/commands/dev/{devPack.js → mockWorker/devPack.js} +10 -8
  18. package/dist/commands/dev/{server.js → mockWorker/server.js} +43 -37
  19. package/dist/commands/init/index.js +117 -42
  20. package/dist/commands/login/index.js +2 -2
  21. package/dist/commands/logout.js +0 -4
  22. package/dist/commands/route/list.js +2 -1
  23. package/dist/commands/routine/list.js +6 -4
  24. package/dist/components/mutiLevelSelect.js +69 -0
  25. package/dist/i18n/locales.json +120 -4
  26. package/dist/index.js +8 -0
  27. package/dist/libs/api.js +155 -0
  28. package/dist/libs/logger.js +42 -31
  29. package/dist/libs/service.js +178 -0
  30. package/dist/package.json +13 -5
  31. package/dist/utils/checkDevPort.js +19 -14
  32. package/dist/utils/checkOS.js +32 -0
  33. package/dist/utils/fileMd5.js +18 -0
  34. package/dist/utils/fileUtils/index.js +1 -1
  35. package/dist/utils/install/installEw2.sh +33 -0
  36. package/dist/utils/{installRuntime.js → installDeno.js} +15 -15
  37. package/dist/utils/installEw2.js +127 -0
  38. package/dist/utils/stepsRunner.js +33 -0
  39. package/dist/zh_CN.md +4 -5
  40. package/package.json +13 -5
  41. package/dist/commands/dev/config/devBuild.js +0 -26
  42. package/dist/libs/request.js +0 -98
  43. /package/dist/commands/dev/{config → mockWorker}/mock/cache.js +0 -0
  44. /package/dist/commands/dev/{config → mockWorker}/mock/kv.js +0 -0
@@ -8,48 +8,53 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import spawn from 'cross-spawn';
11
- import logger from '../../libs/logger.js';
11
+ import logger from '../../../libs/logger.js';
12
12
  import path from 'path';
13
- import t from '../../i18n/index.js';
14
- import { getDevConf } from '../../utils/fileUtils/index.js';
15
- import { getRoot } from '../../utils/fileUtils/base.js';
16
- class WorkerServer {
13
+ import t from '../../../i18n/index.js';
14
+ import { getDevConf } from '../../../utils/fileUtils/index.js';
15
+ import { getRoot } from '../../../utils/fileUtils/base.js';
16
+ class MockWorkerServer {
17
17
  constructor(props) {
18
18
  this.instance = null;
19
19
  this.restarting = false;
20
20
  this.command = props.command || 'deno';
21
- this.start();
22
21
  }
23
22
  start() {
24
- var _a, _b, _c;
25
23
  if (this.instance) {
26
24
  return;
27
25
  }
28
- const root = getRoot();
29
- const inspectPort = getDevConf('inspectPort', 'dev', 9229);
30
- // @ts-ignore
31
- const id = global.id || '';
32
- let inspectOption = '--inspect';
33
- if (inspectPort !== 9229) {
34
- inspectOption = `--inspect=127.0.0.1:${inspectPort}`;
35
- }
36
- this.instance = spawn(this.command, [
37
- 'run',
38
- '--no-lock',
39
- '--allow-net',
40
- '--allow-read',
41
- '--allow-write',
42
- inspectOption,
43
- path.join(root, `.dev/index-${id}.js`),
44
- id
45
- ], {
46
- stdio: ['pipe', 'pipe', 'pipe']
26
+ return new Promise((resolve) => {
27
+ var _a, _b, _c;
28
+ const root = getRoot();
29
+ const inspectPort = getDevConf('inspectPort', 'dev', 9229);
30
+ // @ts-ignore
31
+ const id = global.id || '';
32
+ let inspectOption = '--inspect';
33
+ if (inspectPort !== 9229) {
34
+ inspectOption = `--inspect=127.0.0.1:${inspectPort}`;
35
+ }
36
+ this.instance = spawn(this.command, [
37
+ 'run',
38
+ '--no-lock',
39
+ '--allow-net',
40
+ '--allow-read',
41
+ '--allow-write',
42
+ '--allow-env',
43
+ inspectOption,
44
+ path.join(root, `.dev/index-${id}.js`),
45
+ id
46
+ ], {
47
+ stdio: ['pipe', 'pipe', 'pipe']
48
+ });
49
+ (_a = this.instance.stdout) === null || _a === void 0 ? void 0 : _a.setEncoding('utf8');
50
+ (_b = this.instance.stdout) === null || _b === void 0 ? void 0 : _b.on('data', this.stdoutHandler.bind(this));
51
+ (_c = this.instance.stderr) === null || _c === void 0 ? void 0 : _c.on('data', this.stderrHandler.bind(this));
52
+ this.instance.on('close', this.closeHandler.bind(this));
53
+ this.instance.on('error', this.errorHandler.bind(this));
54
+ setTimeout(() => {
55
+ resolve(true);
56
+ }, 500);
47
57
  });
48
- (_a = this.instance.stdout) === null || _a === void 0 ? void 0 : _a.setEncoding('utf8');
49
- (_b = this.instance.stdout) === null || _b === void 0 ? void 0 : _b.on('data', this.stdoutHandler.bind(this));
50
- (_c = this.instance.stderr) === null || _c === void 0 ? void 0 : _c.on('data', this.stderrHandler.bind(this));
51
- this.instance.on('close', this.closeHandler.bind(this));
52
- this.instance.on('error', this.errorHandler.bind(this));
53
58
  }
54
59
  stdoutHandler(chunk) {
55
60
  logger.log(chunk.toString().trim());
@@ -58,7 +63,6 @@ class WorkerServer {
58
63
  logger.subError(chunk.toString().trim());
59
64
  }
60
65
  errorHandler(err) {
61
- console.log(err);
62
66
  logger.error(err.message ? err.message : err);
63
67
  this.instance && this.instance.kill();
64
68
  }
@@ -67,7 +71,8 @@ class WorkerServer {
67
71
  this.restarting = false;
68
72
  return;
69
73
  }
70
- logger.info(t('dev_server_closed').d('Worker server closed'));
74
+ logger.log(t('dev_server_closed').d('Worker server closed'));
75
+ logger.info('Worker server closed');
71
76
  // @ts-ignore
72
77
  global.port = undefined;
73
78
  }
@@ -78,12 +83,12 @@ class WorkerServer {
78
83
  stop() {
79
84
  return new Promise((resolve) => {
80
85
  if (!this.instance) {
81
- resolve(0);
86
+ resolve(false);
82
87
  return;
83
88
  }
84
89
  const onExit = (code, signal) => {
85
90
  this.instance = null;
86
- resolve(1);
91
+ resolve(true);
87
92
  };
88
93
  this.instance.on('exit', onExit);
89
94
  this.instance.kill('SIGTERM');
@@ -94,8 +99,9 @@ class WorkerServer {
94
99
  this.restarting = true;
95
100
  yield this.stop();
96
101
  this.start();
97
- logger.info(t('dev_server_restart').d('Worker server restarted'));
102
+ logger.log(t('dev_server_restart').d('Worker server restarted'));
103
+ logger.info('Worker server restarted');
98
104
  });
99
105
  }
100
106
  }
101
- export default WorkerServer;
107
+ export default MockWorkerServer;
@@ -12,7 +12,7 @@ import path from 'path';
12
12
  import Template from '../../libs/templates/index.js';
13
13
  import { installGit } from '../../libs/git/index.js';
14
14
  import { descriptionInput } from '../../components/descriptionInput.js';
15
- import { generateConfigFile, getProjectConfig, getTemplatesConfig, templateHubPath, updateProjectConfigFile } from '../../utils/fileUtils/index.js';
15
+ import { generateConfigFile, getCliConfig, getProjectConfig, getTemplatesConfig, templateHubPath, updateProjectConfigFile } from '../../utils/fileUtils/index.js';
16
16
  import t from '../../i18n/index.js';
17
17
  import logger from '../../libs/logger.js';
18
18
  import SelectItems from '../../components/selectInput.js';
@@ -22,6 +22,26 @@ import { ApiService } from '../../libs/apiService.js';
22
22
  import { exit } from 'process';
23
23
  import { checkRoutineExist } from '../../utils/checkIsRoutineCreated.js';
24
24
  import { execSync } from 'child_process';
25
+ import MultiLevelSelect from '../../components/mutiLevelSelect.js';
26
+ import { getDirName } from '../../utils/fileUtils/base.js';
27
+ import { yesNoPromptAndExecute } from '../deploy/helper.js';
28
+ import { checkIsLoginSuccess } from '../utils.js';
29
+ export const getTemplateInstances = (templateHubPath) => {
30
+ return fs
31
+ .readdirSync(templateHubPath)
32
+ .filter((item) => {
33
+ const itemPath = path.join(templateHubPath, item);
34
+ return (fs.statSync(itemPath).isDirectory() &&
35
+ !['.git', 'node_modules', 'lib'].includes(item));
36
+ })
37
+ .map((item) => {
38
+ var _a;
39
+ const projectPath = path.join(templateHubPath, item);
40
+ const projectConfig = getProjectConfig(projectPath);
41
+ const templateName = (_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _a !== void 0 ? _a : '';
42
+ return new Template(projectPath, templateName);
43
+ });
44
+ };
25
45
  const secondSetOfItems = [
26
46
  { label: 'Yes', value: 'yesInstall' },
27
47
  { label: 'No', value: 'noInstall' }
@@ -41,13 +61,85 @@ const init = {
41
61
  })
42
62
  };
43
63
  export default init;
64
+ export const preInstallDependencies = (targetPath) => __awaiter(void 0, void 0, void 0, function* () {
65
+ const packageJsonPath = path.join(targetPath, 'package.json');
66
+ if (fs.existsSync(packageJsonPath)) {
67
+ logger.log(t('init_install_dependence').d('⌛️ Installing dependencies...'));
68
+ execSync('npm install esa-template', {
69
+ stdio: 'inherit',
70
+ cwd: targetPath
71
+ });
72
+ logger.success(t('init_install_dependencies_success').d('Dependencies installed successfully.'));
73
+ logger.log(t('init_build_project').d('⌛️ Building project...'));
74
+ execSync('npm run build', { stdio: 'inherit', cwd: targetPath });
75
+ logger.success(t('init_build_project_success').d('Project built successfully.'));
76
+ }
77
+ });
78
+ export const transferTemplatesToSelectItem = (configs, templateInstanceList, lang) => {
79
+ if (!configs)
80
+ return [];
81
+ return configs.map((config) => {
82
+ var _a, _b;
83
+ const name = config.Title_EN;
84
+ const value = (_b = (_a = templateInstanceList.find((template) => {
85
+ return name === template.title;
86
+ })) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : '';
87
+ const children = transferTemplatesToSelectItem(config.children, templateInstanceList);
88
+ return {
89
+ label: lang === 'en' ? config.Title_EN : config.Title_ZH,
90
+ value: value,
91
+ key: name,
92
+ children
93
+ };
94
+ });
95
+ };
96
+ function checkAndUpdatePackage(packageName) {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ try {
99
+ // 获取当前安装的版本
100
+ const __dirname = getDirName(import.meta.url);
101
+ const packageJsonPath = path.join(__dirname, '../../../');
102
+ const versionInfo = execSync(`npm list ${packageName}`, {
103
+ cwd: packageJsonPath
104
+ }).toString();
105
+ const match = versionInfo.match(new RegExp(`(${packageName})@([0-9.]+)`));
106
+ const currentVersion = match ? match[2] : '';
107
+ // 获取最新版本
108
+ const latestVersion = execSync(`npm view ${packageName} version`)
109
+ .toString()
110
+ .trim();
111
+ if (currentVersion !== latestVersion) {
112
+ logger.log(t('display_current_esa_template_version').d(`Current esa-template version:`) +
113
+ chalk.green(currentVersion) +
114
+ ' ' +
115
+ t('display_latest_esa_template_version').d(`Latest esa-template version:`) +
116
+ chalk.green(latestVersion));
117
+ yield yesNoPromptAndExecute(t('is_update_to_latest_version').d('Do you want to update templates to latest version?'), () => __awaiter(this, void 0, void 0, function* () {
118
+ logger.log(t('updating_esa_template_to_latest_version', { packageName }).d(`Updating ${packageName} to the latest version...`));
119
+ execSync(`rm -rf node_modules/${packageName} &&rm -rf package-lock.json &&npm install ${packageName}@latest`, {
120
+ cwd: packageJsonPath
121
+ });
122
+ logger.log(t('updated_esa_template_to_latest_version', { packageName }).d(`${packageName} updated successfully`));
123
+ return true;
124
+ }));
125
+ }
126
+ else {
127
+ logger.log(t('esa_template_is_latest_version', { packageName }).d(`${packageName} is latest.`));
128
+ }
129
+ }
130
+ catch (error) {
131
+ if (error instanceof Error) {
132
+ logger.error('检测和更新包时发生错误,跳过更新模版');
133
+ }
134
+ }
135
+ });
136
+ }
44
137
  export function handleInit(argv) {
45
138
  return __awaiter(this, void 0, void 0, function* () {
139
+ var _a;
46
140
  const { config } = argv;
47
- // // 更新npm包
48
- // const __dirname = getDirName(import.meta.url);
49
- // const projectPath = path.join(__dirname, '../../..');
50
- // execSync('npm install', { stdio: 'ignore', cwd: projectPath });
141
+ // 更新template npm包
142
+ yield checkAndUpdatePackage('esa-template');
51
143
  if (config !== undefined) {
52
144
  yield generateConfigFile(String(config));
53
145
  return;
@@ -58,43 +150,19 @@ export function handleInit(argv) {
58
150
  logger.error(t('init_name_error').d('Error: The project name must be at least 2 characters long and can only contain lowercase letters, numbers, and hyphens.'));
59
151
  return;
60
152
  }
61
- const templatePaths = fs.readdirSync(templateHubPath).filter((item) => {
62
- const itemPath = path.join(templateHubPath, item);
63
- const stats = fs.statSync(itemPath);
64
- return (stats.isDirectory() &&
65
- item !== '.git' &&
66
- item !== 'node_modules' &&
67
- item !== 'lib');
68
- });
69
- const templateList = templatePaths.map((item) => {
70
- var _a;
71
- const projectPath = templateHubPath + '/' + item;
72
- const projectConfig = getProjectConfig(projectPath);
73
- const templateName = (_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _a !== void 0 ? _a : '';
74
- return new Template(projectPath, templateName);
75
- });
153
+ const templateInstanceList = getTemplateInstances(templateHubPath);
76
154
  const templateConfig = getTemplatesConfig();
77
- const firstSetOfItems = templateConfig
78
- .map((template) => {
79
- const name = template.Title_EN;
80
- const templatePath = templateList.find((item) => {
81
- return name === item.title;
82
- });
83
- return templatePath
84
- ? {
85
- label: name,
86
- value: templatePath.path
87
- }
88
- : null;
89
- })
90
- .filter((item) => item !== null);
155
+ const cliConfig = getCliConfig();
156
+ const lang = (_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.lang) !== null && _a !== void 0 ? _a : 'en';
157
+ const firstSetOfItems = transferTemplatesToSelectItem(templateConfig, templateInstanceList, lang);
91
158
  let selectTemplate;
92
159
  let targetPath;
93
160
  let projectConfig;
94
161
  const preInstallDependencies = () => __awaiter(this, void 0, void 0, function* () {
95
162
  const packageJsonPath = path.join(targetPath, 'package.json');
96
163
  if (fs.existsSync(packageJsonPath)) {
97
- logger.info(t('init_install_dependence').d('⌛️ Installing dependencies...'));
164
+ logger.log('Install dependencies');
165
+ logger.log(t('init_install_dependence').d('⌛️ Installing dependencies...'));
98
166
  execSync('npm install', { stdio: 'inherit', cwd: targetPath });
99
167
  logger.success(t('init_install_dependencies_success').d('Dependencies installed successfully.'));
100
168
  logger.log(t('init_build_project').d('⌛️ Building project...'));
@@ -103,13 +171,15 @@ export function handleInit(argv) {
103
171
  }
104
172
  });
105
173
  const handleFirstSelection = (item) => __awaiter(this, void 0, void 0, function* () {
174
+ if (item.key === 'exit') {
175
+ process.exit(0);
176
+ }
106
177
  const configPath = item.value;
107
178
  selectTemplate = new Template(configPath, name);
108
179
  projectConfig = getProjectConfig(configPath);
109
180
  if (!projectConfig)
110
181
  return logger.notInProject();
111
182
  const newPath = process.cwd() + '/' + name;
112
- console.log(newPath);
113
183
  targetPath = newPath;
114
184
  if (fs.existsSync(newPath)) {
115
185
  logger.error(t('already_exist_file_error').d('Error: The project already exists. It looks like a folder named "<project-name>" is already present in the current directory. Please try the following options: 1. Choose a different project name. 2. Delete the existing folder if it\'s not needed: `rm -rf <project-name>` (use with caution!). 3. Move to a different directory before running the init command.'));
@@ -119,25 +189,30 @@ export function handleInit(argv) {
119
189
  projectConfig.name = name;
120
190
  updateProjectConfigFile(projectConfig, newPath);
121
191
  preInstallDependencies();
122
- logger.info(t('init_git').d('Do you want to init git in your project?'));
192
+ logger.log(t('init_git').d('Do you want to init git in your project?'));
123
193
  SelectItems({
124
194
  items: secondSetOfItems,
125
195
  handleSelect: handleSecondSelection
126
196
  });
127
197
  });
128
- const handleSecondSelection = (item) => {
198
+ const handleSecondSelection = (item) => __awaiter(this, void 0, void 0, function* () {
129
199
  if (item.value === 'yesInstall') {
130
200
  installGit(targetPath);
131
201
  }
132
202
  else {
133
- logger.info(t('init_skip_git').d('Git installation was skipped.'));
203
+ logger.log(t('init_skip_git').d('Git installation was skipped.'));
204
+ }
205
+ const isLoginSuccess = yield checkIsLoginSuccess();
206
+ if (!isLoginSuccess) {
207
+ logger.log(chalk.yellow(t('not_login_auto_deploy').d('You are not logged in, automatic deployment cannot be performed. Please log in later and manually deploy.')));
208
+ process.exit(0);
134
209
  }
135
- logger.info(t('auto_deploy').d('Do you want to deploy your project?'));
210
+ logger.log(t('auto_deploy').d('Do you want to deploy your project?'));
136
211
  SelectItems({
137
212
  items: secondSetOfItems,
138
213
  handleSelect: handleThirdSelection
139
214
  });
140
- };
215
+ });
141
216
  const handleThirdSelection = (item) => __awaiter(this, void 0, void 0, function* () {
142
217
  var _a, _b, _c;
143
218
  // 选择自动生成版本并发布
@@ -155,7 +230,7 @@ export function handleInit(argv) {
155
230
  exit(0);
156
231
  });
157
232
  try {
158
- SelectItems({
233
+ MultiLevelSelect({
159
234
  items: firstSetOfItems,
160
235
  handleSelect: handleFirstSelection
161
236
  });
@@ -54,12 +54,12 @@ export function handleLogin() {
54
54
  }
55
55
  else {
56
56
  logger.error(t('pre_login_failed').d('The previously entered Access Key ID (AK) and Secret Access Key (SK) are incorrect. Please enter them again.'));
57
- logger.info(`${t('login_logging').d('Logging in')}...`);
57
+ logger.log(`${t('login_logging').d('Logging in')}...`);
58
58
  yield getUserInputAuthInfo();
59
59
  }
60
60
  }
61
61
  else {
62
- logger.info(`${t('login_logging').d('Logging in')}...`);
62
+ logger.log(`${t('login_logging').d('Logging in')}...`);
63
63
  yield getUserInputAuthInfo();
64
64
  }
65
65
  });
@@ -8,7 +8,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { getCliConfig, updateCliConfigFile } from '../utils/fileUtils/index.js';
11
- import { checkIsLoginSuccess } from './utils.js';
12
11
  import logger from '../libs/logger.js';
13
12
  import t from '../i18n/index.js';
14
13
  const logout = {
@@ -28,9 +27,6 @@ export function handleLogout(argv) {
28
27
  if (!cliConfig) {
29
28
  return;
30
29
  }
31
- const isSuccess = yield checkIsLoginSuccess();
32
- if (!isSuccess)
33
- return;
34
30
  if (!cliConfig.auth) {
35
31
  cliConfig.auth = { accessKeyId: '', accessKeySecret: '' };
36
32
  }
@@ -52,7 +52,8 @@ export function handleListRoutes() {
52
52
  export function displayRelatedRouteList(routeList) {
53
53
  return __awaiter(this, void 0, void 0, function* () {
54
54
  const table = new Table({
55
- head: ['Route', 'Site']
55
+ head: ['Route', 'Site'],
56
+ colWidths: [30, 30]
56
57
  });
57
58
  for (let i = 0; i < routeList.length; i++) {
58
59
  const route = routeList[i];
@@ -25,6 +25,7 @@ import { checkIsLoginSuccess } from '../utils.js';
25
25
  import chalk from 'chalk';
26
26
  import { ApiService } from '../../libs/apiService.js';
27
27
  import t from '../../i18n/index.js';
28
+ import moment from 'moment';
28
29
  const list = {
29
30
  command: 'list',
30
31
  describe: `📋 ${t('list_describe').d('List all your routines')}`,
@@ -61,7 +62,7 @@ export function handleList(argv) {
61
62
  const res = yield server.getRoutineUserInfo();
62
63
  const routineList = res === null || res === void 0 ? void 0 : res.Routines;
63
64
  if (routineList) {
64
- console.log(chalk.bold.bgGray(`📃 ${t('list_routine_name_title').d('List all of routine')}:`));
65
+ logger.log(chalk.bold.bgGray(`📃 ${t('list_routine_name_title').d('List all of routine')}:`));
65
66
  displayRoutineList(routineList);
66
67
  }
67
68
  });
@@ -69,15 +70,16 @@ export function handleList(argv) {
69
70
  export function displayRoutineList(versionList) {
70
71
  return __awaiter(this, void 0, void 0, function* () {
71
72
  const table = new Table({
72
- head: ['Name', 'Created', 'Description']
73
+ head: ['Name', 'Created', 'Description'],
74
+ colWidths: [20, 25, 30]
73
75
  });
74
76
  versionList.forEach((version) => {
75
77
  table.push([
76
78
  version.RoutineName,
77
- new Date(version.CreateTime).toLocaleString(),
79
+ moment(version.CreateTime).format('YYYY/MM/DD HH:mm:ss'),
78
80
  Base64.decode(version.Description)
79
81
  ]);
80
82
  });
81
- console.log(table.toString());
83
+ console.table(table.toString());
82
84
  });
83
85
  }
@@ -0,0 +1,69 @@
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
+ });
9
+ };
10
+ import React, { useState } from 'react';
11
+ import { render, Text, useApp } from 'ink';
12
+ import SelectInput from 'ink-select-input';
13
+ import Item from './selectItem.js';
14
+ import t from '../i18n/index.js';
15
+ const Indicator = ({ isSelected }) => {
16
+ return React.createElement(Text, null, isSelected ? '👉 ' : ' ');
17
+ };
18
+ const EXIT_ITEM = {
19
+ label: t('exit_select_init_template').d('Exit'),
20
+ key: 'exit',
21
+ value: '__exit__'
22
+ };
23
+ const RETURN_ITEM = {
24
+ label: t('return_select_init_template').d('Return'),
25
+ key: 'return',
26
+ value: '__return__'
27
+ };
28
+ const MultiLevelSelect = ({ items, handleSelect, handleExit }) => {
29
+ const { exit } = useApp();
30
+ const [stack, setStack] = useState([[...items, EXIT_ITEM]]);
31
+ const currentItems = stack[stack.length - 1];
32
+ const onSelect = (item) => {
33
+ if (item.value === '__return__') {
34
+ if (stack.length > 1) {
35
+ // 返回上一级菜单
36
+ setStack(stack.slice(0, -1));
37
+ }
38
+ else {
39
+ // 顶层菜单,执行退出逻辑
40
+ handleExit();
41
+ exit();
42
+ }
43
+ return;
44
+ }
45
+ if (item.children && item.children.length > 0) {
46
+ setStack([...stack, [...item.children, RETURN_ITEM]]); // 在子层级中添加“退出”选项
47
+ }
48
+ else {
49
+ handleSelect(item);
50
+ exit();
51
+ }
52
+ };
53
+ return (React.createElement(SelectInput, { items: currentItems, onSelect: onSelect, itemComponent: Item, indicatorComponent: Indicator, limit: 10 }));
54
+ };
55
+ export const MultiLevelSelectComponent = (props) => __awaiter(void 0, void 0, void 0, function* () {
56
+ const { items, handleSelect, handleExit } = props;
57
+ return new Promise((resolve) => {
58
+ const { unmount } = render(React.createElement(MultiLevelSelect, { items: items, handleSelect: (item) => {
59
+ unmount();
60
+ handleSelect && handleSelect(item);
61
+ resolve(item);
62
+ }, handleExit: () => {
63
+ unmount();
64
+ handleExit && handleExit();
65
+ resolve(null);
66
+ } }));
67
+ });
68
+ });
69
+ export default MultiLevelSelectComponent;