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.
@@ -16,7 +16,7 @@ import promptParameter from '../../utils/prompt.js';
16
16
  import { validateAndInitializeProject, generateCodeVersion } from '../common/utils.js';
17
17
  const commit = {
18
18
  command: 'commit [entry]',
19
- describe: `📥 ${t('commit_describe').d('Commit your code, save as a new version')}`,
19
+ describe: `📦 ${t('commit_describe').d('Commit your code, save as a new version')}`,
20
20
  builder: (yargs) => {
21
21
  return yargs
22
22
  .option('minify', {
@@ -69,11 +69,6 @@ export function handleCommit(argv) {
69
69
  }
70
70
  logger.startSubStep('Generating code version');
71
71
  const res = yield generateCodeVersion(projectName, description, argv === null || argv === void 0 ? void 0 : argv.entry, argv === null || argv === void 0 ? void 0 : argv.assets, argv === null || argv === void 0 ? void 0 : argv.minify);
72
- const { isSuccess } = res || {};
73
- if (!isSuccess) {
74
- logger.endSubStep('Generate version failed');
75
- exit(1);
76
- }
77
72
  const codeVersion = (_b = (_a = res === null || res === void 0 ? void 0 : res.res) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.CodeVersion;
78
73
  if (!codeVersion) {
79
74
  logger.endSubStep('Missing CodeVersion in response');
@@ -120,97 +120,100 @@ export function generateCodeVersion(projectName_1, description_1, entry_1, asset
120
120
  return __awaiter(this, arguments, void 0, function* (projectName, description, entry, assets, minify = false, projectPath) {
121
121
  var _a;
122
122
  const { zip, sourceList, dynamicSources } = yield compress(entry, assets, minify, projectPath);
123
- // Pretty print upload directory tree
124
- const buildTree = (paths, decorateTopLevel) => {
125
- const root = { children: new Map(), isFile: false };
126
- const sorted = [...paths].sort((a, b) => a.localeCompare(b));
127
- for (const p of sorted) {
128
- const parts = p.split('/').filter(Boolean);
129
- let node = root;
130
- for (let i = 0; i < parts.length; i++) {
131
- const part = parts[i];
132
- if (!node.children.has(part)) {
133
- node.children.set(part, { children: new Map(), isFile: false });
123
+ try {
124
+ // Pretty print upload directory tree
125
+ const buildTree = (paths, decorateTopLevel) => {
126
+ const root = { children: new Map(), isFile: false };
127
+ const sorted = [...paths].sort((a, b) => a.localeCompare(b));
128
+ for (const p of sorted) {
129
+ const parts = p.split('/').filter(Boolean);
130
+ let node = root;
131
+ for (let i = 0; i < parts.length; i++) {
132
+ const part = parts[i];
133
+ if (!node.children.has(part)) {
134
+ node.children.set(part, { children: new Map(), isFile: false });
135
+ }
136
+ const child = node.children.get(part);
137
+ if (i === parts.length - 1)
138
+ child.isFile = true;
139
+ node = child;
134
140
  }
135
- const child = node.children.get(part);
136
- if (i === parts.length - 1)
137
- child.isFile = true;
138
- node = child;
139
141
  }
140
- }
141
- const lines = [];
142
- const render = (node, prefix, depth) => {
143
- const entries = [...node.children.entries()];
144
- entries.forEach(([_name, _child], idx) => {
145
- const isLast = idx === entries.length - 1;
146
- const connector = isLast ? '' : '';
147
- const nextPrefix = prefix + (isLast ? ' ' : '│ ');
148
- const displayName = depth === 0 ? decorateTopLevel(_name) : _name;
149
- lines.push(prefix + connector + displayName);
150
- render(_child, nextPrefix, depth + 1);
151
- });
142
+ const lines = [];
143
+ const render = (node, prefix, depth) => {
144
+ const entries = [...node.children.entries()];
145
+ entries.forEach(([_name, _child], idx) => {
146
+ const isLast = idx === entries.length - 1;
147
+ const connector = isLast ? '└ ' : '├ ';
148
+ const nextPrefix = prefix + (isLast ? ' ' : '');
149
+ const displayName = depth === 0 ? decorateTopLevel(_name) : _name;
150
+ lines.push(prefix + connector + displayName);
151
+ render(_child, nextPrefix, depth + 1);
152
+ });
153
+ };
154
+ render(root, '', 0);
155
+ return lines.length ? lines : ['-'];
152
156
  };
153
- render(root, '', 0);
154
- return lines.length ? lines : ['-'];
155
- };
156
- const header = chalk.hex('#22c55e')('UPLOAD') + ' Files to be uploaded (source paths)';
157
- logger.block();
158
- logger.log(header);
159
- const dynamicSet = new Set(dynamicSources);
160
- const LIMIT = 300;
161
- const staticPaths = sourceList
162
- .filter((p) => !dynamicSet.has(p))
163
- .sort((a, b) => a.localeCompare(b));
164
- const dynamicPaths = sourceList
165
- .filter((p) => dynamicSet.has(p))
166
- .sort((a, b) => a.localeCompare(b));
167
- let omitted = 0;
168
- let shownStatic = staticPaths;
169
- if (staticPaths.length > LIMIT) {
170
- shownStatic = staticPaths.slice(0, LIMIT);
171
- omitted = staticPaths.length - LIMIT;
172
- }
173
- // Compute top-level markers based on whether a top-level bucket contains dynamic/static files
174
- const topLevelStats = new Map();
175
- const addStat = (p, isDynamic) => {
176
- const top = p.split('/')[0] || p;
177
- const stat = topLevelStats.get(top) || {
178
- hasDynamic: false,
179
- hasStatic: false
157
+ const header = chalk.hex('#22c55e')('UPLOAD') + ' Files to be uploaded (source paths)';
158
+ logger.block();
159
+ logger.log(header);
160
+ const dynamicSet = new Set(dynamicSources);
161
+ const LIMIT = 300;
162
+ const staticPaths = sourceList
163
+ .filter((p) => !dynamicSet.has(p))
164
+ .sort((a, b) => a.localeCompare(b));
165
+ const dynamicPaths = sourceList
166
+ .filter((p) => dynamicSet.has(p))
167
+ .sort((a, b) => a.localeCompare(b));
168
+ let omitted = 0;
169
+ let shownStatic = staticPaths;
170
+ if (staticPaths.length > LIMIT) {
171
+ shownStatic = staticPaths.slice(0, LIMIT);
172
+ omitted = staticPaths.length - LIMIT;
173
+ }
174
+ // Compute top-level markers based on whether a top-level bucket contains dynamic/static files
175
+ const topLevelStats = new Map();
176
+ const addStat = (p, isDynamic) => {
177
+ const top = p.split('/')[0] || p;
178
+ const stat = topLevelStats.get(top) || {
179
+ hasDynamic: false,
180
+ hasStatic: false
181
+ };
182
+ if (isDynamic)
183
+ stat.hasDynamic = true;
184
+ else
185
+ stat.hasStatic = true;
186
+ topLevelStats.set(top, stat);
180
187
  };
181
- if (isDynamic)
182
- stat.hasDynamic = true;
183
- else
184
- stat.hasStatic = true;
185
- topLevelStats.set(top, stat);
186
- };
187
- dynamicPaths.forEach((p) => addStat(p, true));
188
- shownStatic.forEach((p) => addStat(p, false));
189
- const dynamicMarker = chalk.bold.yellowBright(' (dynamic)');
190
- const staticMarker = chalk.bold.greenBright(' (static)');
191
- const decorateTopLevel = (name) => {
192
- const stat = topLevelStats.get(name);
193
- if (!stat)
188
+ dynamicPaths.forEach((p) => addStat(p, true));
189
+ shownStatic.forEach((p) => addStat(p, false));
190
+ const dynamicMarker = chalk.bold.yellowBright(' (dynamic)');
191
+ const staticMarker = chalk.bold.greenBright(' (static)');
192
+ const decorateTopLevel = (name) => {
193
+ const stat = topLevelStats.get(name);
194
+ if (!stat)
195
+ return name;
196
+ if (stat.hasDynamic && stat.hasStatic) {
197
+ return `${name}${dynamicMarker}${staticMarker}`;
198
+ }
199
+ if (stat.hasDynamic)
200
+ return `${name}${dynamicMarker}`;
201
+ if (stat.hasStatic)
202
+ return `${name}${staticMarker}`;
194
203
  return name;
195
- if (stat.hasDynamic && stat.hasStatic) {
196
- return `${name}${dynamicMarker}${staticMarker}`;
204
+ };
205
+ const combined = [...dynamicPaths, ...shownStatic];
206
+ const treeLines = buildTree(combined, decorateTopLevel);
207
+ for (const line of treeLines) {
208
+ logger.log(line);
197
209
  }
198
- if (stat.hasDynamic)
199
- return `${name}${dynamicMarker}`;
200
- if (stat.hasStatic)
201
- return `${name}${staticMarker}`;
202
- return name;
203
- };
204
- const combined = [...dynamicPaths, ...shownStatic];
205
- const treeLines = buildTree(combined, decorateTopLevel);
206
- for (const line of treeLines) {
207
- logger.log(line);
208
- }
209
- if (omitted > 0) {
210
- const note = chalk.gray(`Only show the first ${LIMIT} static files, omitted ${omitted} files`);
211
- logger.log(note);
210
+ if (omitted > 0) {
211
+ const note = chalk.gray(`仅展示前 ${LIMIT} 个静态文件,已省略 ${omitted} 个`);
212
+ logger.log(note);
213
+ }
214
+ logger.block();
212
215
  }
213
- logger.block();
216
+ catch (_b) { }
214
217
  const projectConfig = getProjectConfig(projectPath);
215
218
  const notFoundStrategy = normalizeNotFoundStrategy((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.assets) === null || _a === void 0 ? void 0 : _a.notFoundStrategy);
216
219
  logger.startSubStep('Generating code version');
@@ -75,7 +75,6 @@ export function handleDeploy(argv) {
75
75
  getRoot().split(/[\\/]/).pop() ||
76
76
  '', true, true);
77
77
  }
78
- exit(success ? 0 : 1);
79
78
  });
80
79
  }
81
80
  export default deploy;
@@ -52,7 +52,7 @@ export function handleDeleteDeployments(argv) {
52
52
  const isInteractive = argv.i;
53
53
  if (isInteractive) {
54
54
  const { allVersions, stagingVersions, productionVersions } = yield getRoutineCodeVersions(projectConfig.name);
55
- // Show information about versions being deployed
55
+ // 显示正在部署的版本信息
56
56
  if (stagingVersions.length > 0 || productionVersions.length > 0) {
57
57
  logger.log(chalk.yellow('⚠️ Currently deploying versions:'));
58
58
  if (stagingVersions.length > 0) {
@@ -64,7 +64,7 @@ export function handleDeleteDeployments(argv) {
64
64
  logger.log('');
65
65
  }
66
66
  logger.log(t('delete_deployments_table_title').d(' Version ID Description'));
67
- // Filter out versions being deployed
67
+ // 过滤掉正在部署的版本
68
68
  const selectList = allVersions
69
69
  .filter((item) => {
70
70
  var _a, _b;
@@ -4,7 +4,7 @@ import deploymentsList from './list.js';
4
4
  let yargsIns;
5
5
  const deploymentsCommand = {
6
6
  command: 'deployments [script]',
7
- describe: `🚀 ${t('deployments_describe').d('Manage your deployments')}`,
7
+ describe: `📜 ${t('deployments_describe').d('Manage your deployments')}`,
8
8
  builder: (yargs) => {
9
9
  yargsIns = yargs;
10
10
  return yargs
@@ -16,7 +16,7 @@ import { getRoot, getDirName } from '../../../utils/fileUtils/base.js';
16
16
  import { getDevConf } from '../../../utils/fileUtils/index.js';
17
17
  import { EW2Path } from '../../../utils/installEw2.js';
18
18
  import devBuild from '../build.js';
19
- // Generate available Ew2 port
19
+ // 生成可用的Ew2端口
20
20
  const generateEw2Port = () => __awaiter(void 0, void 0, void 0, function* () {
21
21
  let ew2port = 3322;
22
22
  let portAvailable = yield checkPort(ew2port);
@@ -60,7 +60,7 @@ conf_path = "${erConfPath}"
60
60
  fs.promises.writeFile(erConfPath, erConf)
61
61
  ]);
62
62
  };
63
- // Generate entry file
63
+ // 生成入口文件
64
64
  const generateEntry = (id, projectEntry, userRoot, port) => __awaiter(void 0, void 0, void 0, function* () {
65
65
  const __dirname = getDirName(import.meta.url);
66
66
  const devDir = path.resolve(userRoot, '.dev');
@@ -85,20 +85,20 @@ const generateEntry = (id, projectEntry, userRoot, port) => __awaiter(void 0, vo
85
85
  .replace(/'\$userPath'/g, `'${projectEntry.replace(/\\/g, '/')}'`)
86
86
  .replace(/\$userPort/g, `${port}`));
87
87
  });
88
- // Preliminary preparation
88
+ // 前期准备
89
89
  const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(void 0, void 0, void 0, function* () {
90
90
  const options = {};
91
91
  const currentOptions = { entry, port, localUpstream };
92
- // Support running multiple workers simultaneously
92
+ // 支持同时跑多个 worker
93
93
  const id = new Date().getTime().toString();
94
94
  // @ts-ignore
95
95
  global.id = id;
96
- // Generate entry file
96
+ // 生成入口文件
97
97
  yield generateEntry(id, entry, userRoot, port);
98
- // Generate Ew2 configuration
98
+ // 生成 Ew2 配置
99
99
  const ew2port = yield generateEw2Port();
100
100
  yield writeEw2config(id, ew2port, userRoot);
101
- // Configuration items for each dev session, distinguished by id in one file
101
+ // 给每一次 dev 的配置项,在一个文件中通过 id 区分
102
102
  if (fs.existsSync(configPath)) {
103
103
  const currentConfig = fs
104
104
  .readFileSync(configPath, 'utf-8')
@@ -106,7 +106,7 @@ const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(
106
106
  const currentConfigObj = JSON.parse(currentConfig);
107
107
  const currentIds = Object.keys(currentConfigObj);
108
108
  if (currentIds[0] && /^\d+$/.test(currentIds[0])) {
109
- // Remove unused entries
109
+ // 删除没有用到的入口
110
110
  for (let currentId of currentIds) {
111
111
  const unused = yield checkPort(currentConfigObj[currentId].port);
112
112
  if (unused) {
@@ -155,7 +155,7 @@ const devPack = () => __awaiter(void 0, void 0, void 0, function* () {
155
155
  }
156
156
  else {
157
157
  logger.notInProject();
158
- process.exit(1);
158
+ process.exit(0);
159
159
  }
160
160
  return prepare(path.resolve(userRoot, '.dev/devConfig.js'), projectEntry, port, localUpstream, userRoot)
161
161
  .then(() => {
@@ -1,5 +1,24 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { getRoot } from '../../../utils/fileUtils/base.js';
4
+ import t from '../../../i18n/index.js';
1
5
  class EdgeKV {
2
- constructor() { }
6
+ constructor() {
7
+ const root = getRoot();
8
+ const kvPath = path.join(root, 'kv.json');
9
+ if (fs.existsSync(kvPath)) {
10
+ try {
11
+ const kvJson = fs.readFileSync(kvPath, 'utf8');
12
+ const kvJsonObj = JSON.parse(kvJson);
13
+ Object.keys(kvJsonObj).forEach((namespace) => {
14
+ EdgeKV.store.set(namespace, new Map(Object.entries(kvJsonObj[namespace])));
15
+ });
16
+ }
17
+ catch (err) {
18
+ console.log(t('kv_parse_failed').d('kv.json parse failed, use empty local kv store.'));
19
+ }
20
+ }
21
+ }
3
22
  get(key, namespace) {
4
23
  const store = EdgeKV.store.get(namespace);
5
24
  if (!store || !store.has(key)) {
@@ -103,7 +103,7 @@ class EdgeKV {
103
103
  headers: { 'Content-Type': 'application/json' }
104
104
  }
105
105
  );
106
- // Check if key exists
106
+ // 判断是否存在key
107
107
  let isGetFailed = false;
108
108
  fetchRes.headers.forEach((v, k) => {
109
109
  if (k === 'kv-get-empty') {
@@ -134,10 +134,10 @@ class EdgeKV {
134
134
  );
135
135
  }
136
136
  case 'stream':
137
- const stream = fetchRes.body;
137
+ const value = await fetchRes.text();
138
138
  return new ReadableStream({
139
139
  start(controller) {
140
- controller.enqueue(new TextEncoder().encode('hello world'));
140
+ controller.enqueue(new TextEncoder().encode(value));
141
141
  controller.close();
142
142
  }
143
143
  });
@@ -187,7 +187,7 @@ class Ew2Server {
187
187
  agent: new HttpProxyAgent(`http://127.0.0.1:${ew2Port}`)
188
188
  });
189
189
  const workerHeaders = Object.fromEntries(workerRes.headers.entries());
190
- // Solve gzip compatibility issue, prevent net::ERR_CONTENT_DECODING_FAILED
190
+ // 解决 gzip 兼容性问题,防止net::ERR_CONTENT_DECODING_FAILED
191
191
  workerHeaders['content-encoding'] = 'identity';
192
192
  if (workerRes.body) {
193
193
  res.writeHead(workerRes.status, workerHeaders);
@@ -236,6 +236,7 @@ class Ew2Server {
236
236
  const key = url.searchParams.get('key');
237
237
  const namespace = url.searchParams.get('namespace');
238
238
  const body = yield this.parseKVBody(req);
239
+ console.log(body);
239
240
  if (!key || !namespace) {
240
241
  return {
241
242
  success: false
@@ -187,7 +187,7 @@ const dev = {
187
187
  yield worker.start();
188
188
  }
189
189
  catch (err) {
190
- logger.error(`Worker start failed: ${err}`);
190
+ console.log('Track err', err);
191
191
  process.exit(1);
192
192
  }
193
193
  const ignored = (path) => {
@@ -40,12 +40,12 @@ const generateEntry = (id, projectEntry, userRoot) => __awaiter(void 0, void 0,
40
40
  const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(void 0, void 0, void 0, function* () {
41
41
  const options = {};
42
42
  const currentOptions = { entry, port, localUpstream };
43
- // Support running multiple deno instances simultaneously
43
+ // 支持同时跑多个 deno
44
44
  const id = new Date().getTime().toString();
45
45
  // @ts-ignore
46
46
  global.id = id;
47
47
  yield generateEntry(id, entry, userRoot);
48
- // Configuration items for each dev session, distinguished by id in one file
48
+ // 给每一次 dev 的配置项,在一个文件中通过 id 区分
49
49
  if (fs.existsSync(configPath)) {
50
50
  const currentConfig = fs
51
51
  .readFileSync(configPath, 'utf-8')
@@ -101,7 +101,7 @@ const devPack = () => __awaiter(void 0, void 0, void 0, function* () {
101
101
  }
102
102
  else {
103
103
  logger.notInProject();
104
- process.exit(1);
104
+ process.exit(0);
105
105
  }
106
106
  return prepare(path.resolve(userRoot, '.dev/devConfig.js'), projectEntry, port, localUpstream, userRoot)
107
107
  .then(() => {
@@ -14,7 +14,7 @@ import { getProjectConfig } from '../../utils/fileUtils/index.js';
14
14
  import { bindRoutineWithDomain, checkDirectory, checkIsLoginSuccess, validDomain, validName } from '../utils.js';
15
15
  const addDomain = {
16
16
  command: 'add <domain>',
17
- describe: `📥 ${t('domain_add_describe').d('Bind a domain to a routine')}`,
17
+ describe: `🔗 ${t('domain_add_describe').d('Bind a domain to a routine')}`,
18
18
  builder: (yargs) => {
19
19
  return yargs
20
20
  .positional('domain', {
@@ -5,7 +5,7 @@ import listDomain from './list.js';
5
5
  let yargsIns;
6
6
  const domainCommand = {
7
7
  command: 'domain [script]',
8
- describe: `🚀 ${t('domain_describe').d('Manage the domain names bound to your routine')}`,
8
+ describe: `🔗 ${t('domain_describe').d('Manage the domain names bound to your routine')}`,
9
9
  builder: (yargs) => {
10
10
  yargsIns = yargs;
11
11
  return yargs
@@ -100,7 +100,7 @@ export function checkAndUpdatePackage(packageName) {
100
100
  const spinner = logger.ora;
101
101
  spinner.text = t('checking_template_update').d('Checking esa-template updates...');
102
102
  spinner.start();
103
- // Get currently installed version
103
+ // 获取当前安装的版本
104
104
  const __dirname = getDirName(import.meta.url);
105
105
  const packageJsonPath = path.join(__dirname, '../../../');
106
106
  let versionInfo;
@@ -124,7 +124,7 @@ export function checkAndUpdatePackage(packageName) {
124
124
  }
125
125
  const match = versionInfo.match(new RegExp(`(${packageName})@([0-9.]+)`));
126
126
  const currentVersion = match ? match[2] : '';
127
- // Get latest version
127
+ // 获取最新版本
128
128
  const latestVersion = execSync(`npm view ${packageName} version`, {
129
129
  cwd: packageJsonPath
130
130
  })
@@ -173,10 +173,11 @@ export function checkAndUpdatePackage(packageName) {
173
173
  });
174
174
  }
175
175
  export const getFrameworkConfig = (framework) => {
176
- // Read template.jsonc from init directory
176
+ // 从init目录读取template.jsonc
177
177
  const templatePath = path.join(getDirName(import.meta.url), 'template.jsonc');
178
178
  const jsonc = fs.readFileSync(templatePath, 'utf-8');
179
179
  const json = JSON.parse(jsonc);
180
+ console.log(json);
180
181
  return json[framework];
181
182
  };
182
183
  /**
@@ -184,7 +185,7 @@ export const getFrameworkConfig = (framework) => {
184
185
  * @returns 框架全部配置
185
186
  */
186
187
  export const getAllFrameworkConfig = () => {
187
- // Read template.jsonc from init directory
188
+ // 从init目录读取template.jsonc
188
189
  const templatePath = path.join(getDirName(import.meta.url), 'template.jsonc');
189
190
  const jsonc = fs.readFileSync(templatePath, 'utf-8');
190
191
  const json = JSON.parse(jsonc);
@@ -231,7 +232,7 @@ export function getInitParamsFromArgv(argv) {
231
232
  params.deploy = Boolean(a.deploy);
232
233
  return params;
233
234
  }
234
- // Configure project name
235
+ // 配置项目名称
235
236
  export const configProjectName = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
236
237
  if (initParams.name) {
237
238
  log.step(`Project name configured ${initParams.name}`);
@@ -592,7 +593,7 @@ export const initGit = (initParams) => __awaiter(void 0, void 0, void 0, functio
592
593
  export function getGitVersion() {
593
594
  return __awaiter(this, void 0, void 0, function* () {
594
595
  try {
595
- let stdout = yield execCommand(['git', '--version'], {
596
+ const stdout = yield execCommand(['git', '--version'], {
596
597
  useSpinner: false,
597
598
  silent: true,
598
599
  captureOutput: true
@@ -608,7 +609,7 @@ export function getGitVersion() {
608
609
  }
609
610
  export function isGitInstalled() {
610
611
  return __awaiter(this, void 0, void 0, function* () {
611
- return (yield getGitVersion()) !== '' && (yield getGitVersion()) !== null;
612
+ return (yield getGitVersion()) !== null;
612
613
  });
613
614
  }
614
615
  /**
@@ -684,6 +685,7 @@ function ensureGitignore(projectRoot, assetsDirectory) {
684
685
  ? `${existingContent.replace(/\n$/, '')}\n${toAppend.join('\n')}\n`
685
686
  : `${toAppend.join('\n')}\n`;
686
687
  fs.writeFileSync(gitignorePath, newContent, 'utf-8');
688
+ logger.log('Updated .gitignore');
687
689
  }
688
690
  catch (_a) {
689
691
  // Do not fail init due to .gitignore issues
@@ -55,7 +55,7 @@
55
55
  "astro": {
56
56
  "label": "Astro",
57
57
  "useGit": false,
58
- "command": "npm create astro@4.13.1",
58
+ "command": "npm create-astro@4.13.1",
59
59
  "params": "--no-install",
60
60
  "assets": {
61
61
  "directory": "./dist"
@@ -12,7 +12,7 @@ import logger from '../libs/logger.js';
12
12
  import { getCliConfig, updateCliConfigFile } from '../utils/fileUtils/index.js';
13
13
  const logout = {
14
14
  command: 'logout',
15
- describe: `📥 ${t('logout_describe').d('Logout')}`,
15
+ describe: `🚪 ${t('logout_describe').d('Logout')}`,
16
16
  builder: (yargs) => {
17
17
  return yargs;
18
18
  },
@@ -14,11 +14,10 @@ import logger from '../../libs/logger.js';
14
14
  import { validRoutine } from '../../utils/checkIsRoutineCreated.js';
15
15
  import { getProjectConfig } from '../../utils/fileUtils/index.js';
16
16
  import { checkDirectory, checkIsLoginSuccess } from '../utils.js';
17
- import { routeBuilder } from '../../components/routeBuilder.js';
18
17
  import { transferRouteToRuleString } from './helper.js';
19
18
  const addRoute = {
20
- command: 'add',
21
- describe: `📥 ${t('route_add_describe').d('Bind a Route to a routine')}`,
19
+ command: 'add [route] [site]',
20
+ describe: `🚄 ${t('route_add_describe').d('Bind a Route to a routine')}`,
22
21
  builder: (yargs) => {
23
22
  return yargs
24
23
  .option('route', {
@@ -79,6 +78,7 @@ export function handlerAddRoute(argv) {
79
78
  name: i.SiteName,
80
79
  value: i.SiteId
81
80
  }));
81
+ // 获取路由名称,支持直接通过参数传入
82
82
  let routeName = argv.alias;
83
83
  if (!routeName) {
84
84
  const response = yield inquirer.prompt([
@@ -99,18 +99,35 @@ export function handlerAddRoute(argv) {
99
99
  let siteName = argv.site;
100
100
  let siteId;
101
101
  if (!siteName) {
102
- const response = yield inquirer.prompt([
103
- {
104
- type: 'list',
105
- name: 'routeSite',
106
- message: t('create_route_site').d('Select a site that is active in your account:'),
107
- choices: siteList
102
+ if (argv._.length > 2) {
103
+ siteName = argv._[2];
104
+ }
105
+ // 如果仍未提供站点名称,则提示选择
106
+ if (!siteName) {
107
+ const response = yield inquirer.prompt([
108
+ {
109
+ type: 'list',
110
+ name: 'routeSite',
111
+ message: t('create_route_site').d('Select a site that is active in your account:'),
112
+ choices: siteList
113
+ }
114
+ ]);
115
+ siteId = response.routeSite;
116
+ }
117
+ else {
118
+ // 根据站点名称查找对应的站点ID
119
+ const matchedSite = siteList.find((site) => site.name === siteName);
120
+ if (matchedSite) {
121
+ siteId = matchedSite.value;
108
122
  }
109
- ]);
110
- siteId = response.routeSite;
123
+ else {
124
+ logger.error(t('site_not_found').d(`Site "${siteName}" not found in your account`));
125
+ return;
126
+ }
127
+ }
111
128
  }
112
129
  else {
113
- // Find corresponding site ID by site name
130
+ // 根据站点名称查找对应的站点ID
114
131
  const matchedSite = siteList.find((site) => site.name === siteName);
115
132
  if (matchedSite) {
116
133
  siteId = matchedSite.value;
@@ -120,24 +137,40 @@ export function handlerAddRoute(argv) {
120
137
  return;
121
138
  }
122
139
  }
140
+ // 获取路由值,支持直接通过参数传入
123
141
  let inputRoute = argv.route;
124
142
  if (!inputRoute) {
125
- // Get selected site name for route building
126
- const selectedSite = siteList.find((site) => site.value === siteId);
127
- const displaySiteName = selectedSite ? selectedSite.name : siteName;
128
- // Use route builder
129
- const builtRoute = yield routeBuilder(displaySiteName);
130
- if (!builtRoute) {
131
- logger.info(t('route_build_cancelled').d('Route building cancelled'));
132
- return;
143
+ // 如果参数中提供了路由值,使用它
144
+ if (argv._.length > 1) {
145
+ inputRoute = argv._[1];
146
+ }
147
+ // 如果仍未提供路由值,则提示输入
148
+ if (!inputRoute) {
149
+ const response = yield inquirer.prompt([
150
+ {
151
+ type: 'input',
152
+ name: 'inputRoute',
153
+ message: t('create_route_route').d('Enter a Route (e.g., example.com/*):'),
154
+ validate: (input) => {
155
+ if (!input) {
156
+ return t('route_input_required').d('Route is required');
157
+ }
158
+ if (!input.includes('*') && !input.includes('/')) {
159
+ return t('route_format_invalid').d('Route format is invalid. Please include wildcard (*) or path (/)');
160
+ }
161
+ return true;
162
+ }
163
+ }
164
+ ]);
165
+ inputRoute = response.inputRoute;
133
166
  }
134
- inputRoute = builtRoute;
135
167
  }
136
168
  const rule = transferRouteToRuleString(inputRoute);
137
169
  if (!rule) {
138
170
  logger.error(t('route_format_invalid').d('Invalid route format'));
139
171
  return;
140
172
  }
173
+ // 获取站点名称用于显示
141
174
  const selectedSite = siteList.find((site) => site.value === siteId);
142
175
  const displaySiteName = selectedSite ? selectedSite.name : siteName;
143
176
  const req = {