esa-cli 0.0.2-beta.16 → 0.0.2-beta.19
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 +4 -4
- package/dist/commands/common/utils.js +108 -11
- package/dist/commands/deploy/helper.js +11 -11
- package/dist/commands/deploy/index.js +9 -10
- package/dist/commands/init/helper.js +90 -5
- package/dist/commands/init/index.js +2 -2
- package/dist/commands/init/template.jsonc +1 -1
- package/dist/commands/route/add.js +19 -51
- package/dist/commands/routine/list.js +38 -20
- package/dist/components/routeBuilder.js +68 -0
- package/dist/docs/Commands_en.md +34 -1
- package/dist/docs/Commands_zh_CN.md +38 -2
- package/dist/i18n/locales.json +72 -0
- package/dist/index.js +11 -1
- package/dist/libs/apiService.js +4 -2
- package/dist/libs/logger.js +41 -2
- package/dist/utils/checkIsRoutineCreated.js +1 -8
- package/dist/utils/checkVersion.js +118 -0
- package/dist/utils/compress.js +27 -9
- package/dist/utils/fileUtils/index.js +36 -13
- package/package.json +10 -11
|
@@ -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
|
+
});
|
package/dist/docs/Commands_en.md
CHANGED
|
@@ -72,7 +72,7 @@ esa deploy [entry]
|
|
|
72
72
|
- -v, --version string: Version to deploy (skip interactive selection)
|
|
73
73
|
- -e, --environment string: Environment to deploy to. Choices: staging | production
|
|
74
74
|
- -n, --name string: Name of the routine
|
|
75
|
-
- -a, --assets
|
|
75
|
+
- -a, --assets string: Assets directory (e.g., ./dist)
|
|
76
76
|
- -d, --description string: Description of the version
|
|
77
77
|
- -m, --minify boolean: Minify the code
|
|
78
78
|
|
|
@@ -153,6 +153,39 @@ esa route delete <routeName>
|
|
|
153
153
|
- list: List all related routes
|
|
154
154
|
- delete <routeName>: Delete a related route
|
|
155
155
|
|
|
156
|
+
#### esa route add
|
|
157
|
+
|
|
158
|
+
Bind a route to the current routine.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
esa route add [route] [site] [--alias <routeName>] [--route <route>] [--site <site>]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- Positionals (optional):
|
|
165
|
+
- route: The route value, e.g. example.com/_ or _.example.com/\*
|
|
166
|
+
- site: The site name, e.g. example.com
|
|
167
|
+
|
|
168
|
+
- Options:
|
|
169
|
+
- -r, --route string: Route value, e.g. example.com/\*
|
|
170
|
+
- Host supports leading `*` for suffix match (e.g., `*.example.com`)
|
|
171
|
+
- Path supports trailing `*` for prefix match (e.g., `/api/*`)
|
|
172
|
+
- -s, --site string: Site name (must be an active site)
|
|
173
|
+
- -a, --alias string: Route name (alias)
|
|
174
|
+
|
|
175
|
+
- Interactive behavior:
|
|
176
|
+
- If `--alias` is missing, you will be prompted to input a route name
|
|
177
|
+
- If `--site` is missing, you will be prompted to choose from active sites
|
|
178
|
+
- If `--route` is missing, you will be prompted to input the route value
|
|
179
|
+
|
|
180
|
+
- Route matching notes:
|
|
181
|
+
- Host supports `*` prefix: `*.example.com` matches any host ending with `.example.com`
|
|
182
|
+
- Path supports `*` suffix: `/api/*` matches any path starting with `/api/`
|
|
183
|
+
- Examples: `example.com/*`, `*.example.com/`, `*.example.com/api/*`
|
|
184
|
+
|
|
185
|
+
- Examples:
|
|
186
|
+
- `esa route add -a home -s example.com -r example.com/*`
|
|
187
|
+
- `esa route add example.com/* example.com -a home`
|
|
188
|
+
|
|
156
189
|
---
|
|
157
190
|
|
|
158
191
|
### esa login
|
|
@@ -70,7 +70,7 @@ esa deploy [entry]
|
|
|
70
70
|
- -v, --version string:指定要部署的版本(跳过交互选择)
|
|
71
71
|
- -e, --environment string:部署环境。可选:staging | production
|
|
72
72
|
- -n, --name string:边缘函数名称
|
|
73
|
-
- -a, --assets
|
|
73
|
+
- -a, --assets string:静态资源目录(例如:./dist)
|
|
74
74
|
- -d, --description string:版本描述
|
|
75
75
|
- -m, --minify boolean:是否压缩代码
|
|
76
76
|
|
|
@@ -115,7 +115,7 @@ esa site list
|
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
- 子命令:
|
|
118
|
-
- list
|
|
118
|
+
- list:列出所有已激活站点
|
|
119
119
|
|
|
120
120
|
---
|
|
121
121
|
|
|
@@ -151,6 +151,39 @@ esa route delete <routeName>
|
|
|
151
151
|
- list:查看所有已绑定路由
|
|
152
152
|
- delete `<routeName>`:删除已绑定路由
|
|
153
153
|
|
|
154
|
+
#### esa route add
|
|
155
|
+
|
|
156
|
+
为当前边缘函数绑定一个路由。
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
esa route add [route] [site] [--alias <routeName>] [--route <route>] [--site <site>]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- 位置参数(可选):
|
|
163
|
+
- route:路由值,例如:example.com/_ 或 _.example.com/\*
|
|
164
|
+
- site:站点名称,例如:example.com
|
|
165
|
+
|
|
166
|
+
- 选项:
|
|
167
|
+
- -r, --route string:路由值,例如:example.com/\*
|
|
168
|
+
- 主机名支持以 `*` 开头表示后缀匹配(如:`*.example.com`)
|
|
169
|
+
- 路径支持以 `*` 结尾表示前缀匹配(如:`/api/*`)
|
|
170
|
+
- -s, --site string:站点名称(需为已激活站点)
|
|
171
|
+
- -a, --alias string:路由名称(别名)
|
|
172
|
+
|
|
173
|
+
- 交互提示:
|
|
174
|
+
- 未提供 `--alias` 时,会提示输入路由名称
|
|
175
|
+
- 未提供 `--site` 时,会列出账号下已激活站点供选择
|
|
176
|
+
- 未提供 `--route` 时,会提示输入路由值
|
|
177
|
+
|
|
178
|
+
- 路由匹配说明:
|
|
179
|
+
- host 支持前缀 `*`:`*.example.com` 表示匹配所有以 `.example.com` 结尾的域名
|
|
180
|
+
- path 支持后缀 `*`:`/api/*` 表示匹配以 `/api/` 开头的路径
|
|
181
|
+
- 示例:`example.com/*`、`*.example.com/`、`*.example.com/api/*`
|
|
182
|
+
|
|
183
|
+
- 示例:
|
|
184
|
+
- `esa route add -a home -s example.com -r example.com/*`
|
|
185
|
+
- `esa route add example.com/* example.com -a home`
|
|
186
|
+
|
|
154
187
|
---
|
|
155
188
|
|
|
156
189
|
### esa login
|
|
@@ -164,6 +197,9 @@ esa login
|
|
|
164
197
|
- 选项:
|
|
165
198
|
- --access-key-id, --ak string:AccessKey ID (AK)
|
|
166
199
|
- --access-key-secret, --sk string:AccessKey Secret (SK)
|
|
200
|
+
- 从环境变量中读取process.env
|
|
201
|
+
- ESA_ACCESS_KEY_ID
|
|
202
|
+
- ESA_ACCESS_KEY_SECRET
|
|
167
203
|
|
|
168
204
|
---
|
|
169
205
|
|
package/dist/i18n/locales.json
CHANGED
|
@@ -1234,5 +1234,77 @@
|
|
|
1234
1234
|
"step": {
|
|
1235
1235
|
"en": "Step:",
|
|
1236
1236
|
"zh_CN": ""
|
|
1237
|
+
},
|
|
1238
|
+
"version_title_update_available": {
|
|
1239
|
+
"en": "ESA CLI Update Available",
|
|
1240
|
+
"zh_CN": "ESA CLI 有新版本可用"
|
|
1241
|
+
},
|
|
1242
|
+
"version_current": {
|
|
1243
|
+
"en": "Current",
|
|
1244
|
+
"zh_CN": "当前版本"
|
|
1245
|
+
},
|
|
1246
|
+
"version_latest": {
|
|
1247
|
+
"en": "Latest",
|
|
1248
|
+
"zh_CN": "最新版本"
|
|
1249
|
+
},
|
|
1250
|
+
"version_note": {
|
|
1251
|
+
"en": "Note",
|
|
1252
|
+
"zh_CN": "提示"
|
|
1253
|
+
},
|
|
1254
|
+
"version_note_incompatible": {
|
|
1255
|
+
"en": "This version may have incompatibilities, please upgrade soon.",
|
|
1256
|
+
"zh_CN": "当前版本可能存在不兼容,建议尽快升级至最新版本。"
|
|
1257
|
+
},
|
|
1258
|
+
"version_update": {
|
|
1259
|
+
"en": "Update",
|
|
1260
|
+
"zh_CN": "升级"
|
|
1261
|
+
},
|
|
1262
|
+
"version_continue": {
|
|
1263
|
+
"en": "You can continue using the current version; commands will proceed.",
|
|
1264
|
+
"zh_CN": "你可以继续使用当前版本;命令将继续执行。"
|
|
1265
|
+
},
|
|
1266
|
+
"version_prompt_update_now": {
|
|
1267
|
+
"en": "Update now to the latest version?",
|
|
1268
|
+
"zh_CN": "是否立即更新到最新版本?"
|
|
1269
|
+
},
|
|
1270
|
+
"version_update_failed": {
|
|
1271
|
+
"en": "Global update failed. You may need elevated permissions (sudo) or use yarn/pnpm:",
|
|
1272
|
+
"zh_CN": "全局更新失败。你可能需要更高权限(sudo)或使用 yarn/pnpm:"
|
|
1273
|
+
},
|
|
1274
|
+
"deploy_option_keyword": {
|
|
1275
|
+
"en": "Keyword to search for routines",
|
|
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 取消"
|
|
1237
1309
|
}
|
|
1238
1310
|
}
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import routeCommand from './commands/route/index.js';
|
|
|
24
24
|
import routine from './commands/routine/index.js';
|
|
25
25
|
import site from './commands/site/index.js';
|
|
26
26
|
import t from './i18n/index.js';
|
|
27
|
-
import { handleCheckVersion } from './utils/checkVersion.js';
|
|
27
|
+
import { handleCheckVersion, checkCLIVersion } from './utils/checkVersion.js';
|
|
28
28
|
import { getCliConfig } from './utils/fileUtils/index.js';
|
|
29
29
|
const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
30
|
const argv = hideBin(process.argv);
|
|
@@ -39,6 +39,16 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
39
39
|
.version(false)
|
|
40
40
|
.wrap(null)
|
|
41
41
|
.help()
|
|
42
|
+
.middleware((argv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
try {
|
|
44
|
+
// Pass current command (first positional) so version check can decide prompting behavior
|
|
45
|
+
yield checkCLIVersion((argv._ && argv._[0] ? String(argv._[0]) : ''));
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
console.log(e);
|
|
49
|
+
console.log('error');
|
|
50
|
+
}
|
|
51
|
+
}))
|
|
42
52
|
.epilogue(`${t('main_epilogue').d('For more information, visit ESA')}: ${chalk.underline.blue('https://www.aliyun.com/product/esa')}`)
|
|
43
53
|
.options('version', {
|
|
44
54
|
describe: t('main_version_describe').d('Show version'),
|
package/dist/libs/apiService.js
CHANGED
|
@@ -219,7 +219,7 @@ export class ApiService {
|
|
|
219
219
|
return null;
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
|
-
listUserRoutines() {
|
|
222
|
+
listUserRoutines(requestParams) {
|
|
223
223
|
return __awaiter(this, void 0, void 0, function* () {
|
|
224
224
|
try {
|
|
225
225
|
let params = {
|
|
@@ -236,7 +236,9 @@ export class ApiService {
|
|
|
236
236
|
return this;
|
|
237
237
|
}
|
|
238
238
|
};
|
|
239
|
-
let request = new $OpenApi.OpenApiRequest(
|
|
239
|
+
let request = new $OpenApi.OpenApiRequest({
|
|
240
|
+
query: requestParams || {}
|
|
241
|
+
});
|
|
240
242
|
let runtime = {
|
|
241
243
|
toMap: function () {
|
|
242
244
|
return this;
|
package/dist/libs/logger.js
CHANGED
|
@@ -175,8 +175,47 @@ class Logger {
|
|
|
175
175
|
console.log(message);
|
|
176
176
|
}
|
|
177
177
|
notInProject() {
|
|
178
|
-
|
|
179
|
-
this.error(
|
|
178
|
+
this.block();
|
|
179
|
+
this.error('Missing ESA project configuration (esa.jsonc or esa.toml)');
|
|
180
|
+
this.block();
|
|
181
|
+
this.log('If there is code to deploy, you can either:');
|
|
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 add the following to your "esa.jsonc" file:');
|
|
184
|
+
console.log('```jsonc\n' +
|
|
185
|
+
'{\n' +
|
|
186
|
+
' "name": "my-routine",\n' +
|
|
187
|
+
' "entry": "src/index.ts",\n' +
|
|
188
|
+
' "dev": { "port": 18080 }\n' +
|
|
189
|
+
'}\n' +
|
|
190
|
+
'```');
|
|
191
|
+
this.subLog('- Or, if you prefer TOML, add to your "esa.toml":');
|
|
192
|
+
console.log('```toml\n' +
|
|
193
|
+
'name = "my-routine"\n' +
|
|
194
|
+
'entry = "src/index.ts"\n' +
|
|
195
|
+
'\n' +
|
|
196
|
+
'[dev]\n' +
|
|
197
|
+
'port = 18080\n' +
|
|
198
|
+
'```\n');
|
|
199
|
+
this.log('If you are deploying a directory of static assets, you can either:');
|
|
200
|
+
this.subLog(`- Add the assets directory to your "esa.jsonc" and run ${chalk.green('esa deploy -a ./dist')}`);
|
|
201
|
+
console.log('```jsonc\n' +
|
|
202
|
+
'{\n' +
|
|
203
|
+
' "name": "my-routine",\n' +
|
|
204
|
+
' "assets": {\n' +
|
|
205
|
+
' "directory": "./dist"\n' +
|
|
206
|
+
' }\n' +
|
|
207
|
+
'}\n' +
|
|
208
|
+
'```');
|
|
209
|
+
this.subLog(`- Or add to your "esa.toml" and run ${chalk.green('esa deploy -a ./dist')}`);
|
|
210
|
+
console.log('```toml\n' +
|
|
211
|
+
'name = "my-routine"\n' +
|
|
212
|
+
'\n' +
|
|
213
|
+
'[assets]\n' +
|
|
214
|
+
'directory = "./dist"\n' +
|
|
215
|
+
'```\n');
|
|
216
|
+
this.log('Alternatively, initialize a new ESA project:');
|
|
217
|
+
this.log(chalk.green('$ esa init my-routine'));
|
|
218
|
+
this.block();
|
|
180
219
|
}
|
|
181
220
|
pathEacces(localPath) {
|
|
182
221
|
this.block();
|
|
@@ -8,11 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { exit } from 'process';
|
|
11
|
+
import { log } from '@clack/prompts';
|
|
11
12
|
import chalk from 'chalk';
|
|
12
13
|
import t from '../i18n/index.js';
|
|
13
14
|
import { ApiService } from '../libs/apiService.js';
|
|
14
15
|
import logger from '../libs/logger.js';
|
|
15
|
-
import { log } from '@clack/prompts';
|
|
16
16
|
export function isRoutineExist(name) {
|
|
17
17
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18
18
|
const server = yield ApiService.getInstance();
|
|
@@ -48,17 +48,10 @@ export function ensureRoutineExists(name) {
|
|
|
48
48
|
});
|
|
49
49
|
const isSuccess = (createRes === null || createRes === void 0 ? void 0 : createRes.data.Status) === 'OK';
|
|
50
50
|
if (isSuccess) {
|
|
51
|
-
// logger.endSubStep(
|
|
52
|
-
// t('routine_create_success').d('Routine created successfully.')
|
|
53
|
-
// );
|
|
54
51
|
logger.endSubStep('Routine created successfully');
|
|
55
|
-
// tlog.success(
|
|
56
|
-
// t('routine_create_success').d('Routine created successfully.')
|
|
57
|
-
// );
|
|
58
52
|
}
|
|
59
53
|
else {
|
|
60
54
|
logger.endSubStep('Routine created failed');
|
|
61
|
-
// tlog.error(t('routine_create_fail').d('Routine created failed.'));
|
|
62
55
|
exit();
|
|
63
56
|
}
|
|
64
57
|
}
|
|
@@ -9,6 +9,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { promises as fs } from 'fs';
|
|
11
11
|
import path from 'path';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
import inquirer from 'inquirer';
|
|
14
|
+
import fetch from 'node-fetch';
|
|
15
|
+
import t from '../i18n/index.js';
|
|
16
|
+
import logger from '../libs/logger.js';
|
|
17
|
+
import execCommand from '../utils/command.js';
|
|
12
18
|
import { getDirName } from '../utils/fileUtils/base.js';
|
|
13
19
|
export function handleCheckVersion() {
|
|
14
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -24,3 +30,115 @@ export function handleCheckVersion() {
|
|
|
24
30
|
}
|
|
25
31
|
});
|
|
26
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* 检查CLI是否为最新版本,如果不是则提示用户更新
|
|
35
|
+
* @returns 是否为最新版本
|
|
36
|
+
*/
|
|
37
|
+
export function checkCLIVersion(currentCommand) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
try {
|
|
40
|
+
const __dirname = getDirName(import.meta.url);
|
|
41
|
+
const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
|
|
42
|
+
const jsonString = yield fs.readFile(packageJsonPath, 'utf-8');
|
|
43
|
+
const packageJson = JSON.parse(jsonString);
|
|
44
|
+
const currentVersion = packageJson.version;
|
|
45
|
+
const response = yield fetch('https://registry.npmjs.org/esa-cli/latest');
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
const data = (yield response.json());
|
|
50
|
+
const latestVersion = data.version;
|
|
51
|
+
if (currentVersion !== latestVersion) {
|
|
52
|
+
const accent = chalk.hex('#7C3AED').bold;
|
|
53
|
+
const labelColor = chalk.hex('#22c55e');
|
|
54
|
+
const currentLabelRaw = t('version_current').d('Current');
|
|
55
|
+
const latestLabelRaw = t('version_latest').d('Latest');
|
|
56
|
+
const noteLabelRaw = t('version_note').d('Note');
|
|
57
|
+
const updateLabelRaw = t('version_update').d('Update');
|
|
58
|
+
const labelsRaw = [
|
|
59
|
+
currentLabelRaw,
|
|
60
|
+
latestLabelRaw,
|
|
61
|
+
noteLabelRaw,
|
|
62
|
+
updateLabelRaw
|
|
63
|
+
];
|
|
64
|
+
const labelWidth = Math.max(...labelsRaw.map((l) => l.length));
|
|
65
|
+
const gap = ' ';
|
|
66
|
+
const padLabel = (raw, colored) => `${colored}${' '.repeat(labelWidth - raw.length)}`;
|
|
67
|
+
const lines = [
|
|
68
|
+
`${accent('🚀 ' + t('version_title_update_available').d('ESA CLI Update Available'))}`,
|
|
69
|
+
'',
|
|
70
|
+
`${padLabel(currentLabelRaw, labelColor(currentLabelRaw))}${gap}${chalk.yellowBright('v' + currentVersion)}`,
|
|
71
|
+
`${padLabel(latestLabelRaw, labelColor(latestLabelRaw))}${gap}${chalk.greenBright('v' + latestVersion)}`,
|
|
72
|
+
'',
|
|
73
|
+
`${padLabel(noteLabelRaw, chalk.yellowBright.bold(noteLabelRaw))}${gap}${chalk.yellowBright(t('version_note_incompatible').d('This version may have incompatibilities, please upgrade soon.'))}`,
|
|
74
|
+
'',
|
|
75
|
+
`${padLabel(updateLabelRaw, labelColor(updateLabelRaw))}${gap}${chalk.cyanBright('npm i -g esa-cli@latest')}`,
|
|
76
|
+
`${' '.repeat(labelWidth)}${gap}${chalk.cyanBright('yarn global add esa-cli@latest')}`,
|
|
77
|
+
`${' '.repeat(labelWidth)}${gap}${chalk.cyanBright('pnpm add -g esa-cli@latest')}`,
|
|
78
|
+
'',
|
|
79
|
+
`${chalk.gray(t('version_continue').d('You can continue using the current version; commands will proceed.'))}`
|
|
80
|
+
];
|
|
81
|
+
// Render with deploy-success-style box (cyan double border)
|
|
82
|
+
const stripAnsi = (s) => s.replace(/\x1B\[[0-?]*[ -\/]*[@-~]/g, '');
|
|
83
|
+
const contentWidth = Math.max(...lines.map((l) => stripAnsi(l).length));
|
|
84
|
+
const borderColor = chalk.hex('#00D4FF').bold;
|
|
85
|
+
const top = `${borderColor('╔')}${borderColor('═'.repeat(contentWidth + 2))}${borderColor('╗')}`;
|
|
86
|
+
const bottom = `${borderColor('╚')}${borderColor('═'.repeat(contentWidth + 2))}${borderColor('╝')}`;
|
|
87
|
+
const box = [
|
|
88
|
+
top,
|
|
89
|
+
...lines.map((l) => {
|
|
90
|
+
const pad = ' '.repeat(contentWidth - stripAnsi(l).length);
|
|
91
|
+
const left = borderColor('║');
|
|
92
|
+
const right = borderColor('║');
|
|
93
|
+
return `${left} ${l}${pad} ${right}`;
|
|
94
|
+
}),
|
|
95
|
+
bottom
|
|
96
|
+
];
|
|
97
|
+
logger.block();
|
|
98
|
+
box.forEach((l) => logger.log(l));
|
|
99
|
+
logger.block();
|
|
100
|
+
// Only prompt interactively on init command; others just display notice
|
|
101
|
+
if (currentCommand === 'init') {
|
|
102
|
+
const { updateNow } = yield inquirer.prompt([
|
|
103
|
+
{
|
|
104
|
+
type: 'confirm',
|
|
105
|
+
name: 'updateNow',
|
|
106
|
+
message: chalk.bold(t('version_prompt_update_now').d('Update now to the latest version?')),
|
|
107
|
+
default: true
|
|
108
|
+
}
|
|
109
|
+
]);
|
|
110
|
+
if (updateNow) {
|
|
111
|
+
const startText = 'Updating ESA CLI to latest (npm i -g esa-cli@latest)';
|
|
112
|
+
const doneText = 'ESA CLI update finished';
|
|
113
|
+
try {
|
|
114
|
+
const res = yield execCommand(['npm', 'i', '-g', 'esa-cli@latest'], {
|
|
115
|
+
startText,
|
|
116
|
+
doneText,
|
|
117
|
+
useSpinner: true,
|
|
118
|
+
interactive: false
|
|
119
|
+
});
|
|
120
|
+
if (!res.success) {
|
|
121
|
+
logger.warn(t('version_update_failed').d('Global update failed. You may need elevated permissions (sudo) or use yarn/pnpm:'));
|
|
122
|
+
logger.subLog('sudo npm i -g esa-cli@latest');
|
|
123
|
+
logger.subLog('yarn global add esa-cli@latest');
|
|
124
|
+
logger.subLog('pnpm add -g esa-cli@latest');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
logger.warn(t('version_update_failed').d('Global update failed. You may need elevated permissions (sudo) or use yarn/pnpm:'));
|
|
129
|
+
logger.subLog('sudo npm i -g esa-cli@latest');
|
|
130
|
+
logger.subLog('yarn global add esa-cli@latest');
|
|
131
|
+
logger.subLog('pnpm add -g esa-cli@latest');
|
|
132
|
+
}
|
|
133
|
+
logger.divider();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
package/dist/utils/compress.js
CHANGED
|
@@ -36,12 +36,15 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
36
36
|
var _a;
|
|
37
37
|
let code;
|
|
38
38
|
const zip = new AdmZip();
|
|
39
|
+
const fileList = [];
|
|
40
|
+
const sourceList = [];
|
|
41
|
+
const dynamicSources = [];
|
|
39
42
|
const projectConfig = getProjectConfig(projectPath);
|
|
40
43
|
let assetsDirectory = assetsDir || ((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.assets) === null || _a === void 0 ? void 0 : _a.directory);
|
|
41
|
-
assetsDirectory = path.resolve(projectPath !== null && projectPath !== void 0 ? projectPath : '', assetsDirectory !== null && assetsDirectory !== void 0 ? assetsDirectory : '');
|
|
42
44
|
const routineType = checkEdgeRoutineType(scriptEntry, assetsDir, projectPath);
|
|
43
|
-
if (!projectConfig) {
|
|
44
|
-
|
|
45
|
+
if (!projectConfig && !scriptEntry && !assetsDir) {
|
|
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);
|
|
45
48
|
}
|
|
46
49
|
// 参数优先:如果有参数则使用参数,否则使用配置文件中的值
|
|
47
50
|
const entry = scriptEntry || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry);
|
|
@@ -50,11 +53,10 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
50
53
|
chalk.red.bold('❌ File upload failed'),
|
|
51
54
|
'',
|
|
52
55
|
chalk.cyan('📋 Current configuration information:'),
|
|
53
|
-
`${chalk.white(
|
|
54
|
-
`${chalk.white(' 📄 Entry file:')} ${chalk.yellow(scriptEntry ||
|
|
56
|
+
`${chalk.white(` 📄 Entry file ${chalk.yellow('(dynamic)')} :`)} ${chalk.yellow(scriptEntry ||
|
|
55
57
|
(projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry) ||
|
|
56
58
|
chalk.gray(t('compress_not_configured').d('Not configured')))}`,
|
|
57
|
-
`${chalk.white(
|
|
59
|
+
`${chalk.white(` 🗂️ Assets directory ${chalk.yellow('(static)')} :`)} ${chalk.yellow(assetsDirectory || chalk.gray(t('compress_not_configured').d('Not configured')))}`,
|
|
58
60
|
'',
|
|
59
61
|
chalk.cyan('🔍 Possible issue causes:'),
|
|
60
62
|
chalk.white(' 1. Entry file path is incorrect or file does not exist'),
|
|
@@ -70,7 +72,7 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
70
72
|
: []),
|
|
71
73
|
...(assetsDirectory
|
|
72
74
|
? [
|
|
73
|
-
`${chalk.white(' 🗂️
|
|
75
|
+
`${chalk.white(' 🗂️ Assets directory:')} ${chalk.cyan.bold(path.resolve(projectPath !== null && projectPath !== void 0 ? projectPath : '', assetsDirectory))} ${chalk.gray(t('compress_check_directory_exists').d('(Check if directory exists)'))}`
|
|
74
76
|
]
|
|
75
77
|
: []),
|
|
76
78
|
...(!scriptEntry && !(projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry) && !assetsDirectory
|
|
@@ -89,6 +91,13 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
89
91
|
yield prodBuild(minify, buildEntry, projectPath);
|
|
90
92
|
code = readEdgeRoutineFile(projectPath);
|
|
91
93
|
zip.addFile(`routine/index.js`, Buffer.from(code || ''));
|
|
94
|
+
fileList.push('routine/index.js');
|
|
95
|
+
const relativeEntry = path
|
|
96
|
+
.relative(projectPath !== null && projectPath !== void 0 ? projectPath : '', buildEntry)
|
|
97
|
+
.split(path.sep)
|
|
98
|
+
.join('/');
|
|
99
|
+
sourceList.push(relativeEntry);
|
|
100
|
+
dynamicSources.push(relativeEntry);
|
|
92
101
|
}
|
|
93
102
|
assetsDirectory = path.resolve(projectPath !== null && projectPath !== void 0 ? projectPath : '', assetsDirectory !== null && assetsDirectory !== void 0 ? assetsDirectory : '');
|
|
94
103
|
// Add all files in the assets directory to the /assets directory
|
|
@@ -106,13 +115,22 @@ const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [s
|
|
|
106
115
|
}
|
|
107
116
|
else {
|
|
108
117
|
const fileContent = fs.readFileSync(fullPath);
|
|
109
|
-
const relativePath = path
|
|
118
|
+
const relativePath = path
|
|
119
|
+
.relative(assetsDirectory, fullPath)
|
|
120
|
+
.split(path.sep)
|
|
121
|
+
.join('/');
|
|
110
122
|
zip.addFile(`assets/${relativePath}`, fileContent);
|
|
123
|
+
fileList.push(`assets/${relativePath}`);
|
|
124
|
+
const relativeSrcPath = path
|
|
125
|
+
.relative(projectPath !== null && projectPath !== void 0 ? projectPath : '', fullPath)
|
|
126
|
+
.split(path.sep)
|
|
127
|
+
.join('/');
|
|
128
|
+
sourceList.push(relativeSrcPath);
|
|
111
129
|
}
|
|
112
130
|
}
|
|
113
131
|
};
|
|
114
132
|
addDirectoryToZip(assetsDirectory, 'assets');
|
|
115
133
|
}
|
|
116
|
-
return zip;
|
|
134
|
+
return { zip, fileList, sourceList, dynamicSources };
|
|
117
135
|
});
|
|
118
136
|
export default compress;
|