esa-cli 0.0.2-beta.20 → 0.0.2-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/commit/index.js +1 -6
- package/dist/commands/common/utils.js +87 -84
- package/dist/commands/deploy/index.js +0 -1
- package/dist/commands/deployments/delete.js +2 -2
- package/dist/commands/deployments/index.js +1 -1
- package/dist/commands/dev/ew2/devPack.js +9 -9
- package/dist/commands/dev/ew2/kvService.js +20 -1
- package/dist/commands/dev/ew2/mock/kv.js +3 -3
- package/dist/commands/dev/ew2/server.js +2 -1
- package/dist/commands/dev/index.js +1 -1
- package/dist/commands/dev/mockWorker/devPack.js +3 -3
- package/dist/commands/domain/add.js +1 -1
- package/dist/commands/domain/index.js +1 -1
- package/dist/commands/init/helper.js +9 -7
- package/dist/commands/init/template.jsonc +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/route/add.js +54 -21
- package/dist/commands/route/helper.js +10 -9
- package/dist/commands/route/index.js +1 -1
- package/dist/commands/routine/index.js +1 -1
- package/dist/commands/routine/list.js +20 -38
- package/dist/commands/site/index.js +1 -1
- package/dist/commands/utils.js +4 -4
- package/dist/components/filterSelector.js +1 -1
- package/dist/i18n/locales.json +4 -36
- package/dist/libs/apiService.js +6 -7
- package/dist/libs/logger.js +4 -4
- package/dist/utils/checkIsRoutineCreated.js +1 -1
- package/dist/utils/compress.js +5 -5
- package/dist/utils/download.js +2 -2
- package/dist/utils/fileUtils/index.js +18 -69
- package/package.json +2 -1
- package/dist/components/routeBuilder.js +0 -68
|
@@ -72,7 +72,8 @@ export const transferRouteToRuleString = (routePath) => {
|
|
|
72
72
|
export const transferRuleStringToRoute = (ruleStr) => {
|
|
73
73
|
if (!ruleStr) {
|
|
74
74
|
return '';
|
|
75
|
-
}
|
|
75
|
+
}
|
|
76
|
+
// 去掉外层括号并按 " and " 分割
|
|
76
77
|
const cleanedRule = ruleStr.replace(/^\(|\)$/g, '');
|
|
77
78
|
const parts = cleanedRule.split(' and ');
|
|
78
79
|
if (parts.length !== 2) {
|
|
@@ -80,36 +81,36 @@ export const transferRuleStringToRoute = (ruleStr) => {
|
|
|
80
81
|
}
|
|
81
82
|
let host = '';
|
|
82
83
|
let uriPath = '';
|
|
83
|
-
//
|
|
84
|
+
// 处理host部分
|
|
84
85
|
const hostPart = parts[0].trim();
|
|
85
86
|
if (hostPart.startsWith(`${RuleMatchOperatorEndsWith}(${RuleMatchTypeHost},`)) {
|
|
86
|
-
//
|
|
87
|
+
// host匹配eq时的逻辑
|
|
87
88
|
// ends_with(http.host, "value")
|
|
88
89
|
const match = hostPart.match(/ends_with\(http\.host,\s*"([^"]+)"\)/);
|
|
89
90
|
if (match) {
|
|
90
|
-
host = `*${match[1]}`; //
|
|
91
|
+
host = `*${match[1]}`; // 加前缀 *
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
else if (hostPart.startsWith(`${RuleMatchTypeHost} ${RuleMatchOperatorEq}`)) {
|
|
94
|
-
//
|
|
95
|
+
// host匹配eq时的逻辑
|
|
95
96
|
// http.host eq "value"
|
|
96
97
|
const match = hostPart.match(/http\.host eq "([^"]+)"/);
|
|
97
98
|
if (match) {
|
|
98
99
|
host = match[1];
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
|
-
//
|
|
102
|
+
// 处理uriPath 部分
|
|
102
103
|
const uriPathPart = parts[1].trim();
|
|
103
104
|
if (uriPathPart.startsWith(`${RuleMatchOperatorStartsWith}(${RuleMatchTypeUriPath},`)) {
|
|
104
|
-
//
|
|
105
|
+
// uriPath匹配startsWith时的逻辑
|
|
105
106
|
// starts_with(http.request.uri.path, "value")
|
|
106
107
|
const match = uriPathPart.match(/starts_with\(http\.request\.uri\.path,\s*"([^"]+)"\)/);
|
|
107
108
|
if (match) {
|
|
108
|
-
uriPath = `${match[1]}*`; //
|
|
109
|
+
uriPath = `${match[1]}*`; // 加后缀 *
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
else if (uriPathPart.startsWith(`${RuleMatchTypeUriPath} ${RuleMatchOperatorEq}`)) {
|
|
112
|
-
//
|
|
113
|
+
// uriPath匹配eq时的逻辑
|
|
113
114
|
// http.request.uri.path eq "value"
|
|
114
115
|
const match = uriPathPart.match(/http\.request\.uri\.path eq "([^"]+)"/);
|
|
115
116
|
if (match) {
|
|
@@ -5,7 +5,7 @@ import listRoute from './list.js';
|
|
|
5
5
|
let yargsIns;
|
|
6
6
|
const routeCommand = {
|
|
7
7
|
command: 'route [script]',
|
|
8
|
-
describe:
|
|
8
|
+
describe: `🚄 ${t('route_describe').d('Manage the routes bound to your routine')}`,
|
|
9
9
|
builder: (yargs) => {
|
|
10
10
|
yargsIns = yargs;
|
|
11
11
|
return yargs
|
|
@@ -4,7 +4,7 @@ import routineList from './list.js';
|
|
|
4
4
|
let yargsIns;
|
|
5
5
|
const routineCommand = {
|
|
6
6
|
command: 'routine [script]',
|
|
7
|
-
describe:
|
|
7
|
+
describe: `🧭 ${t('routine_describe').d('Manage your routine')}`,
|
|
8
8
|
builder: (yargs) => {
|
|
9
9
|
yargsIns = yargs;
|
|
10
10
|
return yargs
|
|
@@ -18,55 +18,37 @@ const list = {
|
|
|
18
18
|
command: 'list',
|
|
19
19
|
describe: `📋 ${t('list_describe').d('List all your routines')}`,
|
|
20
20
|
builder: (yargs) => {
|
|
21
|
-
return yargs
|
|
22
|
-
.option('keyword', {
|
|
23
|
-
alias: 'k',
|
|
24
|
-
describe: t('deploy_option_keyword').d('Keyword to search for routines'),
|
|
25
|
-
type: 'string'
|
|
26
|
-
})
|
|
27
|
-
.usage(`${t('common_usage').d('Usage')}: \$0 list [--keyword <keyword>]`);
|
|
21
|
+
return yargs.usage(`${t('common_usage').d('Usage')}: \$0 list []`);
|
|
28
22
|
},
|
|
29
23
|
handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
24
|
handleList(argv);
|
|
31
25
|
})
|
|
32
26
|
};
|
|
33
27
|
export default list;
|
|
34
|
-
export function getAllRoutines(options) {
|
|
35
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
var _a;
|
|
37
|
-
const server = yield ApiService.getInstance();
|
|
38
|
-
const allRoutines = [];
|
|
39
|
-
let pageNumber = 1;
|
|
40
|
-
const pageSize = (options === null || options === void 0 ? void 0 : options.PageSize) || 50;
|
|
41
|
-
while (true) {
|
|
42
|
-
const res = yield server.listUserRoutines({
|
|
43
|
-
RegionId: options === null || options === void 0 ? void 0 : options.RegionId,
|
|
44
|
-
PageNumber: pageNumber,
|
|
45
|
-
PageSize: pageSize,
|
|
46
|
-
SearchKeyWord: options === null || options === void 0 ? void 0 : options.SearchKeyWord
|
|
47
|
-
});
|
|
48
|
-
if (!((_a = res === null || res === void 0 ? void 0 : res.body) === null || _a === void 0 ? void 0 : _a.Routines)) {
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
allRoutines.push(...res.body.Routines);
|
|
52
|
-
const totalCount = res.body.TotalCount;
|
|
53
|
-
const currentCount = allRoutines.length;
|
|
54
|
-
if (currentCount >= totalCount) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
pageNumber++;
|
|
58
|
-
}
|
|
59
|
-
return allRoutines;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
28
|
export function handleList(argv) {
|
|
63
29
|
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
const { site } = argv;
|
|
64
32
|
const isSuccess = yield checkIsLoginSuccess();
|
|
65
33
|
if (!isSuccess)
|
|
66
34
|
return;
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
35
|
+
const server = yield ApiService.getInstance();
|
|
36
|
+
if (site) {
|
|
37
|
+
const req = {
|
|
38
|
+
SiteSearchType: 'fuzzy',
|
|
39
|
+
Status: 'active',
|
|
40
|
+
PageNumber: 1,
|
|
41
|
+
PageSize: 50
|
|
42
|
+
};
|
|
43
|
+
const res = yield server.listSites(req);
|
|
44
|
+
const siteList = (_a = res === null || res === void 0 ? void 0 : res.data.Sites) !== null && _a !== void 0 ? _a : [];
|
|
45
|
+
const siteNameList = siteList === null || siteList === void 0 ? void 0 : siteList.map((item) => item.SiteName);
|
|
46
|
+
logger.log(chalk.bold.bgGray(`📃 ${t('list_site_name_title').d('List all of site names')}:`));
|
|
47
|
+
logger.tree(siteNameList);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const res = yield server.listUserRoutines();
|
|
51
|
+
const routineList = (_b = res === null || res === void 0 ? void 0 : res.body) === null || _b === void 0 ? void 0 : _b.Routines;
|
|
70
52
|
if (routineList) {
|
|
71
53
|
logger.log(chalk.bold.bgGray(`📃 ${t('list_routine_name_title').d('List all of routine')}:`));
|
|
72
54
|
displayRoutineList(routineList);
|
|
@@ -3,7 +3,7 @@ import siteList from './list.js';
|
|
|
3
3
|
let yargsIns;
|
|
4
4
|
const siteCommand = {
|
|
5
5
|
command: 'site [script]',
|
|
6
|
-
describe:
|
|
6
|
+
describe: `📈 ${t('site_describe').d('Manage your sites')}`,
|
|
7
7
|
builder: (yargs) => {
|
|
8
8
|
yargsIns = yargs;
|
|
9
9
|
return yargs
|
package/dist/commands/utils.js
CHANGED
|
@@ -71,7 +71,7 @@ export const bindRoutineWithDomain = (name, domain) => __awaiter(void 0, void 0,
|
|
|
71
71
|
export function validName(name) {
|
|
72
72
|
return /^[a-zA-Z0-9-_]+$/.test(name);
|
|
73
73
|
}
|
|
74
|
-
//
|
|
74
|
+
// 校验域名是否有效
|
|
75
75
|
export function validDomain(domain) {
|
|
76
76
|
return /^(?:[a-z0-9-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(domain);
|
|
77
77
|
}
|
|
@@ -131,12 +131,12 @@ export function validateLoginCredentials(accessKeyId_1, accessKeySecret_1, endpo
|
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
export function isValidRouteForDomain(route, domain) {
|
|
134
|
-
//
|
|
135
|
-
//
|
|
134
|
+
// 构建一个允许子域和任意路径的正则表达式
|
|
135
|
+
// 例如,匹配形式如 *.example.com/* 的URL
|
|
136
136
|
return route.includes(domain);
|
|
137
137
|
}
|
|
138
138
|
export function escapeRegExp(string) {
|
|
139
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $&
|
|
139
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& 表示整个被匹配的字符串
|
|
140
140
|
}
|
|
141
141
|
export const getAllSites = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
142
142
|
var _a;
|
|
@@ -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
|
-
//
|
|
54
|
+
// 匹配结果大于等于1个时,进入选择模式
|
|
55
55
|
if ((filteredDataInner.length >= 1 &&
|
|
56
56
|
showAll &&
|
|
57
57
|
filteredDataInner.length > hideCount) ||
|
package/dist/i18n/locales.json
CHANGED
|
@@ -204,8 +204,8 @@
|
|
|
204
204
|
"zh_CN": "读取 CLI 配置错误"
|
|
205
205
|
},
|
|
206
206
|
"dev_error_no_project_config": {
|
|
207
|
-
"en": "Error reading project configuration esa.
|
|
208
|
-
"zh_CN": "读取项目配置 esa.
|
|
207
|
+
"en": "Error reading project configuration esa.toml file.",
|
|
208
|
+
"zh_CN": "读取项目配置 esa.toml 文件错误"
|
|
209
209
|
},
|
|
210
210
|
"dev_build_start": {
|
|
211
211
|
"en": "Starting build process",
|
|
@@ -1271,40 +1271,8 @@
|
|
|
1271
1271
|
"en": "Global update failed. You may need elevated permissions (sudo) or use yarn/pnpm:",
|
|
1272
1272
|
"zh_CN": "全局更新失败。你可能需要更高权限(sudo)或使用 yarn/pnpm:"
|
|
1273
1273
|
},
|
|
1274
|
-
"
|
|
1275
|
-
"en": "
|
|
1274
|
+
"kv_parse_failed": {
|
|
1275
|
+
"en": "kv.json parse failed, use empty local kv store.",
|
|
1276
1276
|
"zh_CN": ""
|
|
1277
|
-
},
|
|
1278
|
-
"route_input_method": {
|
|
1279
|
-
"en": "How would you like to input the route?",
|
|
1280
|
-
"zh_CN": "您希望如何输入路由?"
|
|
1281
|
-
},
|
|
1282
|
-
"route_input_builder": {
|
|
1283
|
-
"en": "Use route builder (prefix + suffix)",
|
|
1284
|
-
"zh_CN": "使用路由构建器(前缀 + 后缀)"
|
|
1285
|
-
},
|
|
1286
|
-
"route_input_manual": {
|
|
1287
|
-
"en": "Enter route manually",
|
|
1288
|
-
"zh_CN": "手动输入路由"
|
|
1289
|
-
},
|
|
1290
|
-
"route_build_cancelled": {
|
|
1291
|
-
"en": "Route building cancelled",
|
|
1292
|
-
"zh_CN": "路由构建已取消"
|
|
1293
|
-
},
|
|
1294
|
-
"route_builder_prefix_prompt": {
|
|
1295
|
-
"en": "Enter route prefix for ${siteName} (e.g., api, v1):",
|
|
1296
|
-
"zh_CN": "为 ${siteName} 输入路由前缀(例如:api, v1):"
|
|
1297
|
-
},
|
|
1298
|
-
"route_builder_suffix_prompt": {
|
|
1299
|
-
"en": "Enter route suffix for ${siteName} (e.g., *, users/*):",
|
|
1300
|
-
"zh_CN": "为 ${siteName} 输入路由后缀(例如:*, users/*):"
|
|
1301
|
-
},
|
|
1302
|
-
"route_builder_preview": {
|
|
1303
|
-
"en": "Preview: ${siteName}${prefix}${suffix}",
|
|
1304
|
-
"zh_CN": "预览:{route}"
|
|
1305
|
-
},
|
|
1306
|
-
"route_builder_instructions": {
|
|
1307
|
-
"en": "Press Enter to continue, Ctrl+C to cancel",
|
|
1308
|
-
"zh_CN": "按回车键继续,Ctrl+C 取消"
|
|
1309
1277
|
}
|
|
1310
1278
|
}
|
package/dist/libs/apiService.js
CHANGED
|
@@ -90,6 +90,7 @@ export class ApiService {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
catch (error) {
|
|
93
|
+
console.log('error', error);
|
|
93
94
|
return {
|
|
94
95
|
success: false,
|
|
95
96
|
message: t('login_failed').d('An error occurred while trying to log in.')
|
|
@@ -100,15 +101,15 @@ export class ApiService {
|
|
|
100
101
|
quickDeployRoutine(edgeRoutine) {
|
|
101
102
|
return __awaiter(this, void 0, void 0, function* () {
|
|
102
103
|
try {
|
|
103
|
-
//
|
|
104
|
+
// 上传代码到unstable版本
|
|
104
105
|
const stagingRes = yield this.getRoutineStagingCodeUploadInfo(edgeRoutine);
|
|
105
106
|
if (stagingRes) {
|
|
106
|
-
//
|
|
107
|
+
// 生产版本
|
|
107
108
|
const commitRes = yield this.commitRoutineStagingCode({
|
|
108
109
|
Name: edgeRoutine.name,
|
|
109
110
|
CodeDescription: edgeRoutine.description
|
|
110
111
|
});
|
|
111
|
-
//
|
|
112
|
+
// 发布到生产环境
|
|
112
113
|
if (commitRes) {
|
|
113
114
|
const deployRes = yield this.publishRoutineCodeVersion({
|
|
114
115
|
Name: edgeRoutine.name,
|
|
@@ -218,7 +219,7 @@ export class ApiService {
|
|
|
218
219
|
return null;
|
|
219
220
|
});
|
|
220
221
|
}
|
|
221
|
-
listUserRoutines(
|
|
222
|
+
listUserRoutines() {
|
|
222
223
|
return __awaiter(this, void 0, void 0, function* () {
|
|
223
224
|
try {
|
|
224
225
|
let params = {
|
|
@@ -235,9 +236,7 @@ export class ApiService {
|
|
|
235
236
|
return this;
|
|
236
237
|
}
|
|
237
238
|
};
|
|
238
|
-
let request = new $OpenApi.OpenApiRequest(
|
|
239
|
-
query: requestParams || {}
|
|
240
|
-
});
|
|
239
|
+
let request = new $OpenApi.OpenApiRequest();
|
|
241
240
|
let runtime = {
|
|
242
241
|
toMap: function () {
|
|
243
242
|
return this;
|
package/dist/libs/logger.js
CHANGED
|
@@ -180,7 +180,7 @@ class Logger {
|
|
|
180
180
|
this.block();
|
|
181
181
|
this.log('If there is code to deploy, you can either:');
|
|
182
182
|
this.subLog(`- Specify an entry-point to your Routine via the command line (ex: ${chalk.green('esa deploy src/index.ts')})`);
|
|
183
|
-
this.subLog('- Or
|
|
183
|
+
this.subLog('- Or add the following to your "esa.jsonc" file:');
|
|
184
184
|
console.log('```jsonc\n' +
|
|
185
185
|
'{\n' +
|
|
186
186
|
' "name": "my-routine",\n' +
|
|
@@ -188,7 +188,7 @@ class Logger {
|
|
|
188
188
|
' "dev": { "port": 18080 }\n' +
|
|
189
189
|
'}\n' +
|
|
190
190
|
'```');
|
|
191
|
-
this.subLog('- Or, if you prefer TOML,
|
|
191
|
+
this.subLog('- Or, if you prefer TOML, add to your "esa.toml":');
|
|
192
192
|
console.log('```toml\n' +
|
|
193
193
|
'name = "my-routine"\n' +
|
|
194
194
|
'entry = "src/index.ts"\n' +
|
|
@@ -197,7 +197,7 @@ class Logger {
|
|
|
197
197
|
'port = 18080\n' +
|
|
198
198
|
'```\n');
|
|
199
199
|
this.log('If you are deploying a directory of static assets, you can either:');
|
|
200
|
-
this.subLog(`-
|
|
200
|
+
this.subLog(`- Add the assets directory to your "esa.jsonc" and run ${chalk.green('esa deploy -a ./dist')}`);
|
|
201
201
|
console.log('```jsonc\n' +
|
|
202
202
|
'{\n' +
|
|
203
203
|
' "name": "my-routine",\n' +
|
|
@@ -206,7 +206,7 @@ class Logger {
|
|
|
206
206
|
' }\n' +
|
|
207
207
|
'}\n' +
|
|
208
208
|
'```');
|
|
209
|
-
this.subLog(`- Or
|
|
209
|
+
this.subLog(`- Or add to your "esa.toml" and run ${chalk.green('esa deploy -a ./dist')}`);
|
|
210
210
|
console.log('```toml\n' +
|
|
211
211
|
'name = "my-routine"\n' +
|
|
212
212
|
'\n' +
|
|
@@ -26,7 +26,7 @@ export function validRoutine(name) {
|
|
|
26
26
|
const isCreatedRoutine = yield isRoutineExist(name);
|
|
27
27
|
if (!isCreatedRoutine) {
|
|
28
28
|
logger.warn(`${t('routine_not_exist').d('Routine does not exist, please create a new one. Run command:')} ${chalk.greenBright('esa deploy')}`);
|
|
29
|
-
exit(
|
|
29
|
+
exit(0);
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
32
|
}
|
package/dist/utils/compress.js
CHANGED
|
@@ -43,10 +43,10 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
43
43
|
let assetsDirectory = assetsDir || ((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.assets) === null || _a === void 0 ? void 0 : _a.directory);
|
|
44
44
|
const routineType = checkEdgeRoutineType(scriptEntry, assetsDir, projectPath);
|
|
45
45
|
if (!projectConfig && !scriptEntry && !assetsDir) {
|
|
46
|
-
logger.error('esa.jsonc
|
|
47
|
-
exit(
|
|
46
|
+
logger.error('esa.jsonc or esa.toml is not found and script entry or assets directory is not provided by command line');
|
|
47
|
+
exit(0);
|
|
48
48
|
}
|
|
49
|
-
//
|
|
49
|
+
// 参数优先:如果有参数则使用参数,否则使用配置文件中的值
|
|
50
50
|
const entry = scriptEntry || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry);
|
|
51
51
|
if (routineType === EDGE_ROUTINE_TYPE.NOT_EXIST) {
|
|
52
52
|
const errorMessage = [
|
|
@@ -61,7 +61,7 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
61
61
|
chalk.cyan('🔍 Possible issue causes:'),
|
|
62
62
|
chalk.white(' 1. Entry file path is incorrect or file does not exist'),
|
|
63
63
|
chalk.white(' 2. Assets directory path is incorrect or directory does not exist'),
|
|
64
|
-
chalk.white(` 3. Project configuration file ${chalk.yellow('esa.jsonc')}
|
|
64
|
+
chalk.white(` 3. Project configuration file ${chalk.yellow('esa.jsonc')} or ${chalk.yellow('esa.toml')} format error`),
|
|
65
65
|
chalk.white(` 4. Relative path format error, please use ${chalk.yellow('./xxx')} format`),
|
|
66
66
|
'',
|
|
67
67
|
chalk.yellow.bold(`📍 Please check if the following ${chalk.red('absolute paths')} are correct:`),
|
|
@@ -83,7 +83,7 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
83
83
|
''
|
|
84
84
|
].join('\n');
|
|
85
85
|
logger.error(errorMessage);
|
|
86
|
-
exit(
|
|
86
|
+
exit(0);
|
|
87
87
|
}
|
|
88
88
|
if (routineType === EDGE_ROUTINE_TYPE.JS_ONLY ||
|
|
89
89
|
routineType === EDGE_ROUTINE_TYPE.JS_AND_ASSETS) {
|
package/dist/utils/download.js
CHANGED
|
@@ -92,8 +92,8 @@ function isBinDirInPath(binDir) {
|
|
|
92
92
|
*/
|
|
93
93
|
function addBinDirToPath(binDir) {
|
|
94
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
//
|
|
96
|
-
// setx
|
|
95
|
+
// 使用 setx 添加到 PATH
|
|
96
|
+
// setx 对 PATH 的长度有2047字符的限制
|
|
97
97
|
const command = `setx Path "%Path%;${binDir}"`;
|
|
98
98
|
try {
|
|
99
99
|
yield execAsync(command);
|
|
@@ -17,31 +17,8 @@ import { getDirName, getRoot } from './base.js';
|
|
|
17
17
|
const projectConfigFile = 'esa.toml';
|
|
18
18
|
const __dirname = getDirName(import.meta.url);
|
|
19
19
|
const root = getRoot();
|
|
20
|
-
|
|
21
|
-
export const getProjectConfigPath = (filePath = root) => {
|
|
22
|
-
const configFormats = ['esa.jsonc', 'esa.toml'];
|
|
23
|
-
for (const format of configFormats) {
|
|
24
|
-
const configPath = path.join(filePath, format);
|
|
25
|
-
if (fs.existsSync(configPath)) {
|
|
26
|
-
return configPath;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
// Default to .jsonc if no config file exists
|
|
30
|
-
return path.join(filePath, 'esa.jsonc');
|
|
31
|
-
};
|
|
32
|
-
export const projectConfigPath = getProjectConfigPath();
|
|
20
|
+
export const projectConfigPath = path.join(root, projectConfigFile);
|
|
33
21
|
export const cliConfigPath = path.join(os.homedir(), '.esa/config/default.toml');
|
|
34
|
-
// Function to get the actual config file path (supports both .toml and .jsonc)
|
|
35
|
-
export const getCliConfigPath = () => {
|
|
36
|
-
const configDir = path.join(os.homedir(), '.esa/config');
|
|
37
|
-
const jsoncPath = path.join(configDir, 'default.jsonc');
|
|
38
|
-
const tomlPath = path.join(configDir, 'default.toml');
|
|
39
|
-
// Check if JSONC file exists first, then fallback to TOML
|
|
40
|
-
if (fs.existsSync(jsoncPath)) {
|
|
41
|
-
return jsoncPath;
|
|
42
|
-
}
|
|
43
|
-
return tomlPath;
|
|
44
|
-
};
|
|
45
22
|
export const hiddenConfigDir = path.join(os.homedir(), '.esa/config');
|
|
46
23
|
export const generateHiddenConfigDir = () => {
|
|
47
24
|
if (!fs.existsSync(hiddenConfigDir)) {
|
|
@@ -51,7 +28,7 @@ export const generateHiddenConfigDir = () => {
|
|
|
51
28
|
export const generateToml = (path) => {
|
|
52
29
|
if (!fs.existsSync(path)) {
|
|
53
30
|
fs.writeFileSync(path, '', 'utf-8');
|
|
54
|
-
//
|
|
31
|
+
// 添加默认的endpoint
|
|
55
32
|
const defaultConfig = {
|
|
56
33
|
endpoint: 'esa.cn-hangzhou.aliyuncs.com'
|
|
57
34
|
};
|
|
@@ -60,34 +37,20 @@ export const generateToml = (path) => {
|
|
|
60
37
|
};
|
|
61
38
|
export const generateDefaultConfig = () => {
|
|
62
39
|
generateHiddenConfigDir();
|
|
63
|
-
|
|
64
|
-
generateToml(configPath);
|
|
40
|
+
generateToml(cliConfigPath);
|
|
65
41
|
};
|
|
66
42
|
export function updateProjectConfigFile(configUpdate_1) {
|
|
67
43
|
return __awaiter(this, arguments, void 0, function* (configUpdate, filePath = root) {
|
|
68
|
-
const configPath =
|
|
44
|
+
const configPath = path.join(filePath, projectConfigFile);
|
|
69
45
|
try {
|
|
70
46
|
let configFileContent = yield fsPromises.readFile(configPath, 'utf8');
|
|
71
|
-
let config;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (configPath.endsWith('.jsonc') || configPath.endsWith('.json')) {
|
|
75
|
-
// Handle JSONC format
|
|
76
|
-
const jsonContent = configFileContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
|
77
|
-
config = JSON.parse(jsonContent);
|
|
78
|
-
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
79
|
-
updatedConfigString = JSON.stringify(config, null, 2) + '\n';
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
// Handle TOML format (default)
|
|
83
|
-
config = toml.parse(configFileContent);
|
|
84
|
-
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
85
|
-
updatedConfigString = toml.stringify(config);
|
|
86
|
-
}
|
|
47
|
+
let config = toml.parse(configFileContent);
|
|
48
|
+
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
49
|
+
const updatedConfigString = toml.stringify(config);
|
|
87
50
|
yield fsPromises.writeFile(configPath, updatedConfigString);
|
|
88
51
|
}
|
|
89
52
|
catch (error) {
|
|
90
|
-
logger.error(`Error updating
|
|
53
|
+
logger.error(`Error updating TOML file: ${error}`);
|
|
91
54
|
logger.pathEacces(__dirname);
|
|
92
55
|
}
|
|
93
56
|
});
|
|
@@ -95,30 +58,16 @@ export function updateProjectConfigFile(configUpdate_1) {
|
|
|
95
58
|
export function updateCliConfigFile(configUpdate) {
|
|
96
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
60
|
try {
|
|
98
|
-
|
|
99
|
-
let
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (configPath.endsWith('.jsonc') || configPath.endsWith('.json')) {
|
|
104
|
-
// Handle JSONC format
|
|
105
|
-
const jsonContent = configFileContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
|
106
|
-
config = JSON.parse(jsonContent);
|
|
107
|
-
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
108
|
-
updatedConfigString = JSON.stringify(config, null, 2) + '\n';
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
// Handle TOML format (default)
|
|
112
|
-
config = toml.parse(configFileContent);
|
|
113
|
-
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
114
|
-
updatedConfigString = toml.stringify(config);
|
|
115
|
-
}
|
|
116
|
-
yield fsPromises.writeFile(configPath, updatedConfigString);
|
|
61
|
+
let configFileContent = yield fsPromises.readFile(cliConfigPath, 'utf8');
|
|
62
|
+
let config = toml.parse(configFileContent);
|
|
63
|
+
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
64
|
+
const updatedConfigString = toml.stringify(config);
|
|
65
|
+
yield fsPromises.writeFile(cliConfigPath, updatedConfigString);
|
|
117
66
|
}
|
|
118
67
|
catch (error) {
|
|
119
|
-
logger.error(`Error updating
|
|
68
|
+
logger.error(`Error updating TOML file: ${error}`);
|
|
120
69
|
logger.pathEacces(__dirname);
|
|
121
|
-
throw new Error('
|
|
70
|
+
throw new Error('Login error');
|
|
122
71
|
}
|
|
123
72
|
});
|
|
124
73
|
}
|
|
@@ -139,6 +88,7 @@ export function readConfigFile(configPath) {
|
|
|
139
88
|
}
|
|
140
89
|
}
|
|
141
90
|
catch (error) {
|
|
91
|
+
console.log(error);
|
|
142
92
|
logger.error(`Error parsing config file: ${error}`);
|
|
143
93
|
return null;
|
|
144
94
|
}
|
|
@@ -146,8 +96,7 @@ export function readConfigFile(configPath) {
|
|
|
146
96
|
return null;
|
|
147
97
|
}
|
|
148
98
|
export function getCliConfig() {
|
|
149
|
-
const
|
|
150
|
-
const res = readConfigFile(configPath);
|
|
99
|
+
const res = readConfigFile(cliConfigPath);
|
|
151
100
|
if (!res) {
|
|
152
101
|
return null;
|
|
153
102
|
}
|
|
@@ -184,7 +133,7 @@ export function getConfigurations() {
|
|
|
184
133
|
}
|
|
185
134
|
}
|
|
186
135
|
export function generateConfigFile(projectName_1, initConfigs_1, targetDir_1) {
|
|
187
|
-
return __awaiter(this, arguments, void 0, function* (projectName, initConfigs, targetDir, configFormat = '
|
|
136
|
+
return __awaiter(this, arguments, void 0, function* (projectName, initConfigs, targetDir, configFormat = 'toml', notFoundStrategy) {
|
|
188
137
|
var _a, _b;
|
|
189
138
|
const outputDir = targetDir !== null && targetDir !== void 0 ? targetDir : process.cwd();
|
|
190
139
|
const currentDirName = path.basename(outputDir);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "esa-cli",
|
|
3
|
-
"version": "0.0.2-beta.
|
|
3
|
+
"version": "0.0.2-beta.21",
|
|
4
4
|
"description": "A CLI for operating Alibaba Cloud ESA EdgeRoutine (Edge Functions).",
|
|
5
5
|
"main": "bin/enter.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"@types/yargs": "^17.0.32",
|
|
55
55
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
56
56
|
"@typescript-eslint/parser": "^6.9.1",
|
|
57
|
+
"eslint-plugin-react": "latest",
|
|
57
58
|
"husky": "^8.0.3",
|
|
58
59
|
"jsdom": "^25.0.1",
|
|
59
60
|
"lint-staged": "^15.0.2",
|
|
@@ -1,68 +0,0 @@
|
|
|
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
|
-
});
|