esa-cli 0.0.5 → 1.0.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 (85) hide show
  1. package/README.md +32 -149
  2. package/dist/commands/commit/index.js +49 -104
  3. package/dist/commands/commit/prodBuild.js +2 -3
  4. package/dist/commands/common/constant.js +4 -4
  5. package/dist/commands/common/utils.js +419 -0
  6. package/dist/commands/config.js +2 -2
  7. package/dist/commands/deploy/helper.js +43 -49
  8. package/dist/commands/deploy/index.js +51 -174
  9. package/dist/commands/deployments/delete.js +32 -22
  10. package/dist/commands/deployments/index.js +4 -4
  11. package/dist/commands/deployments/list.js +21 -34
  12. package/dist/commands/dev/build.js +3 -3
  13. package/dist/commands/dev/doProcess.js +5 -5
  14. package/dist/commands/dev/ew2/cacheService.js +33 -0
  15. package/dist/commands/dev/ew2/devEntry.js +2 -1
  16. package/dist/commands/dev/ew2/devPack.js +31 -20
  17. package/dist/commands/dev/ew2/kvService.js +50 -0
  18. package/dist/commands/dev/ew2/mock/cache.js +99 -15
  19. package/dist/commands/dev/ew2/mock/kv.js +142 -21
  20. package/dist/commands/dev/ew2/server.js +163 -28
  21. package/dist/commands/dev/index.js +17 -18
  22. package/dist/commands/dev/mockWorker/devPack.js +19 -10
  23. package/dist/commands/dev/mockWorker/server.js +7 -6
  24. package/dist/commands/domain/add.js +4 -4
  25. package/dist/commands/domain/delete.js +3 -3
  26. package/dist/commands/domain/index.js +4 -4
  27. package/dist/commands/domain/list.js +7 -7
  28. package/dist/commands/init/helper.js +654 -21
  29. package/dist/commands/init/index.js +88 -152
  30. package/dist/commands/init/snippets/nextjs/next.config.mjs +6 -0
  31. package/dist/commands/init/snippets/nextjs/next.config.ts +7 -0
  32. package/dist/commands/init/snippets/react-router/react-router.config.ts +7 -0
  33. package/dist/commands/init/template.jsonc +84 -0
  34. package/dist/commands/init/types.js +1 -0
  35. package/dist/commands/lang.js +2 -2
  36. package/dist/commands/login/index.js +74 -34
  37. package/dist/commands/logout.js +6 -6
  38. package/dist/commands/route/add.js +101 -43
  39. package/dist/commands/route/delete.js +6 -6
  40. package/dist/commands/route/helper.js +9 -10
  41. package/dist/commands/route/index.js +4 -4
  42. package/dist/commands/route/list.js +4 -4
  43. package/dist/commands/routine/delete.js +9 -8
  44. package/dist/commands/routine/index.js +6 -5
  45. package/dist/commands/routine/list.js +45 -39
  46. package/dist/commands/site/index.js +3 -3
  47. package/dist/commands/site/list.js +6 -7
  48. package/dist/commands/utils.js +61 -25
  49. package/dist/components/descriptionInput.js +1 -1
  50. package/dist/components/filterSelector.js +1 -1
  51. package/dist/components/mutiLevelSelect.js +19 -20
  52. package/dist/components/mutiSelectTable.js +1 -1
  53. package/dist/components/routeBuilder.js +68 -0
  54. package/dist/components/selectInput.js +2 -3
  55. package/dist/components/selectItem.js +1 -1
  56. package/dist/docs/Commands_en.md +164 -117
  57. package/dist/docs/Commands_zh_CN.md +155 -107
  58. package/dist/docs/Config_en.md +70 -0
  59. package/dist/docs/Config_zh_CN.md +68 -0
  60. package/dist/i18n/index.js +2 -2
  61. package/dist/i18n/locales.json +414 -82
  62. package/dist/index.js +28 -13
  63. package/dist/libs/api.js +3 -6
  64. package/dist/libs/apiService.js +192 -69
  65. package/dist/libs/git/index.js +86 -9
  66. package/dist/libs/interface.js +0 -1
  67. package/dist/libs/logger.js +162 -10
  68. package/dist/libs/service.js +2 -2
  69. package/dist/libs/templates/index.js +1 -1
  70. package/dist/utils/checkAssetsExist.js +80 -0
  71. package/dist/utils/checkDevPort.js +5 -19
  72. package/dist/utils/checkEntryFileExist.js +10 -0
  73. package/dist/utils/checkIsRoutineCreated.js +27 -21
  74. package/dist/utils/checkVersion.js +119 -1
  75. package/dist/utils/command.js +149 -0
  76. package/dist/utils/compress.js +142 -0
  77. package/dist/utils/download.js +8 -8
  78. package/dist/utils/fileMd5.js +1 -1
  79. package/dist/utils/fileUtils/index.js +136 -45
  80. package/dist/utils/installDeno.js +4 -4
  81. package/dist/utils/installEw2.js +9 -9
  82. package/dist/utils/openInBrowser.js +1 -1
  83. package/dist/utils/prompt.js +97 -0
  84. package/package.json +23 -12
  85. package/zh_CN.md +29 -154
@@ -7,16 +7,17 @@ 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 fs from 'fs';
11
10
  import { execSync } from 'child_process';
12
- import { isInstalledGit } from '../libs/git/index.js';
13
- import { getCliConfig, projectConfigPath } from '../utils/fileUtils/index.js';
14
- import { getRoot } from '../utils/fileUtils/base.js';
11
+ import fs from 'fs';
15
12
  import chalk from 'chalk';
16
13
  import t from '../i18n/index.js';
14
+ import api from '../libs/api.js';
17
15
  import { ApiService } from '../libs/apiService.js';
16
+ import { isInstalledGit } from '../libs/git/index.js';
18
17
  import logger from '../libs/logger.js';
19
- import api from '../libs/api.js';
18
+ import { getRoot } from '../utils/fileUtils/base.js';
19
+ import { getCliConfig, projectConfigPath } from '../utils/fileUtils/index.js';
20
+ import { getRoutineDetails } from './common/utils.js';
20
21
  export const checkDirectory = (isCheckGit = false) => {
21
22
  const root = getRoot();
22
23
  if (fs.existsSync(projectConfigPath)) {
@@ -57,60 +58,85 @@ export const bindRoutineWithDomain = (name, domain) => __awaiter(void 0, void 0,
57
58
  const response = yield server.createRoutineRelatedRecord(createReq);
58
59
  const isBindSuccess = (response === null || response === void 0 ? void 0 : response.data.Status) === 'OK';
59
60
  if (isBindSuccess) {
60
- logger.success(t('utils_bind_success', { domain }).d(`Binding domain ${domain} to routine successfully`));
61
+ logger.success(t('utils_bind_success', { domain }).d(`Binding domain ${domain} to project successfully`));
61
62
  }
62
63
  else {
63
- logger.error(t('utils_bind_error', { domain }).d(`Binding domain ${domain} to routine failed`));
64
+ logger.error(t('utils_bind_error', { domain }).d(`Binding domain ${domain} to project failed`));
64
65
  }
65
66
  }
66
67
  else {
67
68
  logger.error(t('utils_domain_error').d('Domain is not active'));
68
69
  }
69
70
  });
70
- export const getRoutineVersionList = (name) => __awaiter(void 0, void 0, void 0, function* () {
71
- var _a, _b;
72
- const req = { name };
73
- const res = yield api.listRoutineCodeVersions(req);
74
- return (_b = (_a = res.body) === null || _a === void 0 ? void 0 : _a.codeVersions) !== null && _b !== void 0 ? _b : [];
75
- });
76
71
  export function validName(name) {
77
72
  return /^[a-zA-Z0-9-_]+$/.test(name);
78
73
  }
79
- // 校验域名是否有效
74
+ // Validate if domain is valid
80
75
  export function validDomain(domain) {
81
76
  return /^(?:[a-z0-9-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(domain);
82
77
  }
83
78
  export function checkIsLoginSuccess() {
84
79
  return __awaiter(this, void 0, void 0, function* () {
80
+ var _a, _b;
81
+ let accessKeyId = process.env.ESA_ACCESS_KEY_ID;
82
+ let accessKeySecret = process.env.ESA_ACCESS_KEY_SECRET;
83
+ let endpoint = process.env.ESA_ENDPOINT;
85
84
  const cliConfig = getCliConfig();
86
- const namedCommand = chalk.green('esa login');
87
- if (!cliConfig || !cliConfig.auth) {
88
- return false;
85
+ if (!accessKeyId || !accessKeySecret) {
86
+ accessKeyId = (_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _a === void 0 ? void 0 : _a.accessKeyId;
87
+ accessKeySecret = (_b = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.auth) === null || _b === void 0 ? void 0 : _b.accessKeySecret;
88
+ }
89
+ if (!endpoint) {
90
+ endpoint = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.endpoint;
89
91
  }
90
- if (!cliConfig.auth.accessKeyId || !cliConfig.auth.accessKeySecret) {
92
+ const namedCommand = chalk.green('esa-cli login');
93
+ if (!accessKeyId || !accessKeySecret) {
91
94
  logger.log(`❌ ${t('utils_login_error').d('Maybe you are not logged in yet.')}`);
92
95
  logger.log(`🔔 ${t('utils_login_error_config', { namedCommand }).d(`Please run command to login: ${namedCommand}`)}`);
93
96
  return false;
94
97
  }
98
+ return yield validateLoginCredentials(accessKeyId, accessKeySecret, endpoint, namedCommand);
99
+ });
100
+ }
101
+ /**
102
+ * 验证登录凭据的公共函数
103
+ * @param accessKeyId AccessKey ID
104
+ * @param accessKeySecret AccessKey Secret
105
+ * @param namedCommand 命令名称(用于错误提示)
106
+ * @param showError 是否显示错误信息
107
+ * @returns 登录是否成功
108
+ */
109
+ export function validateLoginCredentials(accessKeyId_1, accessKeySecret_1, endpoint_1, namedCommand_1) {
110
+ return __awaiter(this, arguments, void 0, function* (accessKeyId, accessKeySecret, endpoint, namedCommand, showError = true) {
95
111
  const server = yield ApiService.getInstance();
96
- server.updateConfig(cliConfig);
112
+ server.updateConfig({
113
+ auth: {
114
+ accessKeyId,
115
+ accessKeySecret
116
+ },
117
+ endpoint: endpoint
118
+ });
97
119
  const res = yield server.checkLogin();
98
120
  if (res.success) {
99
121
  return true;
100
122
  }
101
- logger.log(res.message || '');
102
- logger.log(`❌ ${t('utils_login_error').d('Maybe you are not logged in yet.')}`);
103
- logger.log(`🔔 ${t('utils_login_error_config', { namedCommand }).d(`Please run command to login: ${namedCommand}`)}`);
123
+ if (showError) {
124
+ logger.log(res.message || '');
125
+ logger.log(`❌ ${t('utils_login_error').d('Maybe you are not logged in yet.')}`);
126
+ if (namedCommand) {
127
+ logger.log(`🔔 ${t('utils_login_error_config', { namedCommand }).d(`Please run command to login: ${namedCommand}`)}`);
128
+ }
129
+ }
104
130
  return false;
105
131
  });
106
132
  }
107
133
  export function isValidRouteForDomain(route, domain) {
108
- // 构建一个允许子域和任意路径的正则表达式
109
- // 例如,匹配形式如 *.example.com/* 的URL
134
+ // Build a regex that allows subdomains and arbitrary paths
135
+ // For example, match URLs like *.example.com/*
110
136
  return route.includes(domain);
111
137
  }
112
138
  export function escapeRegExp(string) {
113
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& 表示整个被匹配的字符串
139
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& represents the entire matched string
114
140
  }
115
141
  export const getAllSites = () => __awaiter(void 0, void 0, void 0, function* () {
116
142
  var _a;
@@ -138,3 +164,13 @@ export const getAllSites = () => __awaiter(void 0, void 0, void 0, function* ()
138
164
  };
139
165
  });
140
166
  });
167
+ export const getRoutineCodeVersions = (projectName) => __awaiter(void 0, void 0, void 0, function* () {
168
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
169
+ const routineDetail = yield getRoutineDetails(projectName);
170
+ const req = { name: projectName };
171
+ const res = yield api.listRoutineCodeVersions(req);
172
+ const allVersions = (_b = (_a = res.body) === null || _a === void 0 ? void 0 : _a.codeVersions) !== null && _b !== void 0 ? _b : [];
173
+ const stagingVersions = ((_g = (_f = (_e = (_d = (_c = routineDetail === null || routineDetail === void 0 ? void 0 : routineDetail.data) === null || _c === void 0 ? void 0 : _c.Envs) === null || _d === void 0 ? void 0 : _d.find((item) => item.Env === 'staging')) === null || _e === void 0 ? void 0 : _e.CodeDeploy) === null || _f === void 0 ? void 0 : _f.CodeVersions) === null || _g === void 0 ? void 0 : _g.map((item) => item.CodeVersion)) || [];
174
+ const productionVersions = ((_m = (_l = (_k = (_j = (_h = routineDetail === null || routineDetail === void 0 ? void 0 : routineDetail.data) === null || _h === void 0 ? void 0 : _h.Envs) === null || _j === void 0 ? void 0 : _j.find((item) => item.Env === 'production')) === null || _k === void 0 ? void 0 : _k.CodeDeploy) === null || _l === void 0 ? void 0 : _l.CodeVersions) === null || _m === void 0 ? void 0 : _m.map((item) => item.CodeVersion)) || [];
175
+ return { allVersions, stagingVersions, productionVersions };
176
+ });
@@ -7,9 +7,9 @@ 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 React, { useState } from 'react';
11
10
  import { Box, render, Text } from 'ink';
12
11
  import TextInput from 'ink-text-input';
12
+ import React, { useState } from 'react';
13
13
  export const DescriptionInput = ({ prompt, onSubmit, required }) => {
14
14
  const [input, setInput] = useState('');
15
15
  const [error, setError] = useState('');
@@ -51,7 +51,7 @@ export const FilterSelector = ({ data, onSubmit, hideCount = 20 }) => {
51
51
  else if (tabPressCount === 1) {
52
52
  const filteredDataInner = data.filter((site) => site.label.includes(inputValue));
53
53
  setFilteredData(filteredDataInner);
54
- // 匹配结果大于等于1个时,进入选择模式
54
+ // Enter selection mode when match results >= 1
55
55
  if ((filteredDataInner.length >= 1 &&
56
56
  showAll &&
57
57
  filteredDataInner.length > hideCount) ||
@@ -7,7 +7,7 @@ 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 inquirer from 'inquirer';
10
+ import { isCancel, select as clackSelect } from '@clack/prompts';
11
11
  import logger from '../libs/logger.js';
12
12
  /**
13
13
  * Perform multi-level selection and return the final selected template path
@@ -21,36 +21,35 @@ export default function multiLevelSelect(items_1) {
21
21
  const stack = []; // Stack to store previous level options for back navigation
22
22
  let selectedPath = null;
23
23
  while (selectedPath === null) {
24
- const { choice } = yield inquirer.prompt([
25
- {
26
- type: 'list',
27
- name: 'choice',
28
- message,
29
- pageSize: 10,
30
- choices: [
31
- ...currentItems.map((item) => ({ name: item.label, value: item })),
32
- ...(stack.length > 0 ? [{ name: 'Back', value: 'back' }] : []), // Show "Back" if there’s a previous level
33
- { name: 'Exit', value: 'exit' }
34
- ]
35
- }
36
- ]);
37
- if (choice === 'exit') {
24
+ const choice = (yield clackSelect({
25
+ message,
26
+ options: [
27
+ ...currentItems.map((item) => ({
28
+ label: item.label,
29
+ value: item.value,
30
+ hint: item.hint
31
+ })),
32
+ ...(stack.length > 0 ? [{ label: 'Back', value: '__back__' }] : [])
33
+ ]
34
+ }));
35
+ if (isCancel(choice)) {
38
36
  logger.log('User canceled the operation.');
39
37
  return null;
40
38
  }
41
- if (choice === 'back') {
39
+ if (choice === '__back__') {
42
40
  currentItems = stack.pop(); // Return to the previous level
43
41
  continue;
44
42
  }
45
43
  // If a category with children is selected
46
- if (choice.children && choice.children.length > 0) {
44
+ const selected = currentItems.find((i) => i.value === choice);
45
+ if (selected && selected.children && selected.children.length > 0) {
47
46
  stack.push(currentItems); // Save the current level
48
- currentItems = choice.children; // Move to the next level
49
- message = `Select a template under ${choice.label}:`;
47
+ currentItems = selected.children; // Move to the next level
48
+ message = `Select a template under ${selected.label}:`;
50
49
  }
51
50
  else {
52
51
  // A leaf node (no children) is selected, end the selection
53
- selectedPath = choice.value;
52
+ selectedPath = choice;
54
53
  }
55
54
  }
56
55
  return selectedPath;
@@ -7,8 +7,8 @@ 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 React, { useState } from 'react';
11
10
  import { Box, render, Text, useInput } from 'ink';
11
+ import React, { useState } from 'react';
12
12
  import t from '../i18n/index.js';
13
13
  export const MultiSelectTable = ({ items, itemsPerRow, onSubmit, boxWidth = 25 }) => {
14
14
  const [selectedIndexes, setSelectedIndexes] = useState(new Set());
@@ -0,0 +1,68 @@
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 { Box, render, Text } from 'ink';
11
+ import TextInput from 'ink-text-input';
12
+ import React, { useState } from 'react';
13
+ 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')
35
+ .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);
40
+ 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
+ } }));
67
+ });
68
+ });
@@ -1,7 +1,6 @@
1
- import React from 'react';
2
- import { render } from 'ink';
1
+ import { render, Text } from 'ink';
3
2
  import SelectInput from 'ink-select-input';
4
- import { Text } from 'ink';
3
+ import React from 'react';
5
4
  import Item from './selectItem.js';
6
5
  const Indicator = ({ isSelected }) => {
7
6
  return React.createElement(Text, null, isSelected ? '👉 ' : ' ');
@@ -1,5 +1,5 @@
1
- import * as React from 'react';
2
1
  import { Text } from 'ink';
2
+ import * as React from 'react';
3
3
  function Item({ isSelected = false, label }) {
4
4
  return React.createElement(Text, { color: isSelected ? 'green' : undefined }, label);
5
5
  }