esa-cli 0.0.2-beta.1 → 0.0.2-beta.10

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.
@@ -15,7 +15,6 @@ import { ApiService } from '../../libs/apiService.js';
15
15
  import prodBuild from './prodBuild.js';
16
16
  import logger from '../../libs/logger.js';
17
17
  import t from '../../i18n/index.js';
18
- import { exit } from 'process';
19
18
  const commit = {
20
19
  command: 'commit [entry]',
21
20
  describe: `đŸ“„ ${t('commit_describe').d('Commit your code, save as a new version')}`,
@@ -87,7 +86,6 @@ export function handleCommit(argv) {
87
86
  return;
88
87
  yield releaseOfficialVersion(edgeRoutine);
89
88
  }
90
- exit(0);
91
89
  }
92
90
  catch (error) {
93
91
  logger.error(`${t('common_error_occurred').d('An error occurred:')} ${error}`);
@@ -126,6 +124,7 @@ export function uploadEdgeRoutineCode(edgeRoutine) {
126
124
  return true;
127
125
  }
128
126
  catch (error) {
127
+ logger.error('123');
129
128
  logger.error(`${t('common_error_occurred').d('An error occurred:')} ${error}`);
130
129
  process.exit(0);
131
130
  }
@@ -1,23 +1,4 @@
1
1
  import t from '../../i18n/index.js';
2
- export const SUMMARIES_LIST = [
3
- {
4
- title: t('summery_cd').d('Enter your routine project folder'),
5
- command: '💡 cd [Your Routine Name]'
6
- },
7
- {
8
- title: t('summery_dev').d('Start a local development server for your project'),
9
- command: '💡 esa dev'
10
- },
11
- {
12
- title: t('summery_commit').d('Save a new version of code'),
13
- command: '💡 esa commit'
14
- },
15
- // Use Deploy or Release?
16
- {
17
- title: t('summery_deploy').d('Deploy your project to different environments'),
18
- command: '💡 esa deploy'
19
- }
20
- ];
21
2
  export const getSummary = (routineName) => {
22
3
  return [
23
4
  {
@@ -81,7 +81,7 @@ const generateEntry = (id, projectEntry, userRoot) => __awaiter(void 0, void 0,
81
81
  const destPath = path.resolve(mockDevDir, file);
82
82
  yield fs.promises.copyFile(srcPath, destPath);
83
83
  }
84
- return fs.promises.writeFile(devEntry, devEntryTempFile.replace(/'\$userPath'/g, `'${projectEntry}'`));
84
+ return fs.promises.writeFile(devEntry, devEntryTempFile.replace(/'\$userPath'/g, `'${projectEntry.replace(/\\/g, '/')}'`));
85
85
  });
86
86
  // ć‰æœŸć‡†ć€‡
87
87
  const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(void 0, void 0, void 0, function* () {
@@ -106,27 +106,13 @@ const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(
106
106
  if (currentIds[0] && /^\d+$/.test(currentIds[0])) {
107
107
  // ćˆ é™€æČĄæœ‰ç”šćˆ°çš„ć…„揣
108
108
  for (let currentId of currentIds) {
109
- const useful = yield checkPort(currentConfigObj[currentId].port);
110
- if (useful) {
111
- const unusedEntry = path.resolve(userRoot, `.dev/index-${currentId}.js`);
112
- const unusedTemp = path.resolve(userRoot, `.dev/devEntry-${currentId}.js`);
113
- const unusedConfig = path.resolve(userRoot, `.dev/config-${currentId}.toml`);
114
- if (fs.existsSync(unusedEntry)) {
115
- fs.rmSync(unusedEntry, {
116
- force: true,
117
- recursive: true,
118
- maxRetries: 5
119
- });
120
- }
121
- if (fs.existsSync(unusedTemp)) {
122
- fs.rmSync(unusedTemp, {
123
- force: true,
124
- recursive: true,
125
- maxRetries: 5
126
- });
127
- }
128
- if (fs.existsSync(unusedConfig)) {
129
- fs.rmSync(unusedConfig, {
109
+ const unused = yield checkPort(currentConfigObj[currentId].port);
110
+ if (unused) {
111
+ const devDir = path.resolve(userRoot, '.dev');
112
+ const files = fs.readdirSync(devDir);
113
+ const filesToDelete = files.filter((file) => file.includes(currentId));
114
+ for (const file of filesToDelete) {
115
+ fs.rmSync(path.resolve(devDir, file), {
130
116
  force: true,
131
117
  recursive: true,
132
118
  maxRetries: 5
@@ -164,8 +150,7 @@ const devPack = (...args_1) => __awaiter(void 0, [...args_1], void 0, function*
164
150
  .then(() => {
165
151
  logger.ora.succeed(t('dev_pack_config_success').d('Config created successfully'));
166
152
  return devBuild({
167
- minify,
168
- isNode: true
153
+ minify
169
154
  });
170
155
  })
171
156
  .then(() => {
@@ -128,7 +128,6 @@ class Ew2Server {
128
128
  }
129
129
  createServer() {
130
130
  this.server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
131
- var _a;
132
131
  try {
133
132
  const host = req.headers.host;
134
133
  const url = req.url;
@@ -148,18 +147,20 @@ class Ew2Server {
148
147
  // è§Łć†ł gzip ć…Œćźčæ€§é—źéą˜ïŒŒé˜Čæ­ąnet::ERR_CONTENT_DECODING_FAILED
149
148
  workerHeaders['content-encoding'] = 'identity';
150
149
  if (workerRes.body) {
151
- if ((_a = workerRes.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('text/')) {
152
- const text = yield workerRes.text();
153
- // ć‡șçŽ°æąèĄŒçŹŠäč‹ç±»äŒšćŻŒè‡Ž content-length 䞍䞀臎
154
- workerHeaders['content-length'] =
155
- Buffer.byteLength(text).toString();
156
- res.writeHead(workerRes.status, workerHeaders);
157
- res.end(text);
158
- }
159
- else {
160
- res.writeHead(workerRes.status, workerHeaders);
161
- workerRes.body.pipe(res);
162
- }
150
+ // if (workerRes.headers.get('content-type')?.includes('text/')) {
151
+ // const text = await workerRes.text();
152
+ // // ć‡șçŽ°æąèĄŒçŹŠäč‹ç±»äŒšćŻŒè‡Ž content-length 䞍䞀臎
153
+ // workerHeaders['content-length'] =
154
+ // Buffer.byteLength(text).toString();
155
+ // console.log(workerHeaders['content-length']);
156
+ // res.writeHead(workerRes.status, workerHeaders);
157
+ // res.end(text);
158
+ // } else {
159
+ // res.writeHead(workerRes.status, workerHeaders);
160
+ // workerRes.body.pipe(res);
161
+ // }
162
+ res.writeHead(workerRes.status, workerHeaders);
163
+ workerRes.body.pipe(res);
163
164
  logger.log(`[ESA Dev] ${req.method} ${url} ${getColorForStatusCode(workerRes.status, workerRes.statusText)}`);
164
165
  }
165
166
  else {
@@ -27,7 +27,8 @@ import checkAndInputPort from '../../utils/checkDevPort.js';
27
27
  import { checkOS, Platforms } from '../../utils/checkOS.js';
28
28
  let yargsIns;
29
29
  const OS = checkOS();
30
- const useEw2 = OS === Platforms.AppleArm || Platforms.AppleIntel || Platforms.LinuxX86;
30
+ const EW2OS = [Platforms.AppleArm, Platforms.AppleIntel, Platforms.LinuxX86];
31
+ const useEw2 = EW2OS.includes(OS);
31
32
  const dev = {
32
33
  command: 'dev [entry]',
33
34
  describe: `đŸ’» ${t('dev_describe').d('Start a local server for developing your routine')}`,
@@ -35,7 +35,7 @@ const generateEntry = (id, projectEntry, userRoot) => __awaiter(void 0, void 0,
35
35
  const destPath = path.resolve(mockDevDir, file);
36
36
  yield fs.promises.copyFile(srcPath, destPath);
37
37
  }
38
- return fs.promises.writeFile(devEntry, devEntryTempFile.replace(/'\$userPath'/g, `'${projectEntry}'`));
38
+ return fs.promises.writeFile(devEntry, devEntryTempFile.replace(/'\$userPath'/g, `'${projectEntry.replace(/\\/g, '/')}'`));
39
39
  });
40
40
  const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(void 0, void 0, void 0, function* () {
41
41
  const options = {};
@@ -51,22 +51,24 @@ const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(
51
51
  .readFileSync(configPath, 'utf-8')
52
52
  .replace('export default ', '');
53
53
  const currentConfigObj = JSON.parse(currentConfig);
54
- const cIds = Object.keys(currentConfigObj);
55
- if (cIds[0] && /^\d+$/.test(cIds[0])) {
56
- for (let cid of cIds) {
57
- const useful = yield checkPort(currentConfigObj[cid].port);
58
- if (useful) {
59
- const unusedEntry = path.resolve(userRoot, `.dev/index-${cid}.js`);
60
- const unusedTemp = path.resolve(userRoot, `.dev/devEntry-${cid}.js`);
61
- if (fs.existsSync(unusedEntry)) {
62
- fs.rmSync(unusedEntry);
63
- }
64
- if (fs.existsSync(unusedTemp)) {
65
- fs.rmSync(unusedTemp);
54
+ const currentIds = Object.keys(currentConfigObj);
55
+ if (currentIds[0] && /^\d+$/.test(currentIds[0])) {
56
+ for (let currentId of currentIds) {
57
+ const unused = yield checkPort(currentConfigObj[currentId].port);
58
+ if (unused) {
59
+ const devDir = path.resolve(userRoot, '.dev');
60
+ const files = fs.readdirSync(devDir);
61
+ const filesToDelete = files.filter((file) => file.includes(currentId));
62
+ for (const file of filesToDelete) {
63
+ fs.rmSync(path.resolve(devDir, file), {
64
+ force: true,
65
+ recursive: true,
66
+ maxRetries: 5
67
+ });
66
68
  }
67
69
  }
68
70
  else {
69
- options[cid] = currentConfigObj[cid];
71
+ options[currentId] = currentConfigObj[currentId];
70
72
  }
71
73
  }
72
74
  }
@@ -0,0 +1,113 @@
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 fs from 'fs-extra';
11
+ import path from 'path';
12
+ import Template from '../../libs/templates/index.js';
13
+ import { getProjectConfig } from '../../utils/fileUtils/index.js';
14
+ import logger from '../../libs/logger.js';
15
+ import { execSync } from 'child_process';
16
+ import t from '../../i18n/index.js';
17
+ import chalk from 'chalk';
18
+ import { getDirName } from '../../utils/fileUtils/base.js';
19
+ import inquirer from 'inquirer';
20
+ export const getTemplateInstances = (templateHubPath) => {
21
+ return fs
22
+ .readdirSync(templateHubPath)
23
+ .filter((item) => {
24
+ const itemPath = path.join(templateHubPath, item);
25
+ return (fs.statSync(itemPath).isDirectory() &&
26
+ !['.git', 'node_modules', 'lib'].includes(item));
27
+ })
28
+ .map((item) => {
29
+ var _a;
30
+ const projectPath = path.join(templateHubPath, item);
31
+ const projectConfig = getProjectConfig(projectPath);
32
+ const templateName = (_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _a !== void 0 ? _a : '';
33
+ return new Template(projectPath, templateName);
34
+ });
35
+ };
36
+ export const transferTemplatesToSelectItem = (configs, templateInstanceList, lang) => {
37
+ if (!configs)
38
+ return [];
39
+ return configs.map((config) => {
40
+ var _a, _b;
41
+ const title = config.Title_EN;
42
+ const value = (_b = (_a = templateInstanceList.find((template) => {
43
+ return title === template.title;
44
+ })) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : '';
45
+ const children = transferTemplatesToSelectItem(config.children, templateInstanceList, lang);
46
+ return {
47
+ label: lang === 'en' ? config.Title_EN : config.Title_ZH,
48
+ value: value,
49
+ children
50
+ };
51
+ });
52
+ };
53
+ export const preInstallDependencies = (targetPath) => __awaiter(void 0, void 0, void 0, function* () {
54
+ const packageJsonPath = path.join(targetPath, 'package.json');
55
+ if (fs.existsSync(packageJsonPath)) {
56
+ logger.log(t('init_install_dependence').d('⌛ Installing dependencies...'));
57
+ execSync('npm install', { stdio: 'inherit', cwd: targetPath });
58
+ logger.success(t('init_install_dependencies_success').d('Dependencies installed successfully.'));
59
+ // Read and parse package.json to check for build script
60
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
61
+ if (packageJson.scripts && packageJson.scripts.build) {
62
+ logger.log(t('init_build_project').d('⌛ Building project...'));
63
+ execSync('npm run build', { stdio: 'inherit', cwd: targetPath });
64
+ logger.success(t('init_build_project_success').d('Project built successfully.'));
65
+ }
66
+ else {
67
+ logger.log(t('no_build_script').d('No build script found in package.json, skipping build step.'));
68
+ }
69
+ }
70
+ });
71
+ export function checkAndUpdatePackage(packageName) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ try {
74
+ // èŽ·ć–ćœ“ć‰ćź‰èŁ…çš„ç‰ˆæœŹ
75
+ const __dirname = getDirName(import.meta.url);
76
+ const packageJsonPath = path.join(__dirname, '../../../');
77
+ const versionInfo = execSync(`npm list ${packageName}`).toString();
78
+ const match = versionInfo.match(new RegExp(`(${packageName})@([0-9.]+)`));
79
+ const currentVersion = match ? match[2] : '';
80
+ // èŽ·ć–æœ€æ–°ç‰ˆæœŹ
81
+ const latestVersion = execSync(`npm view ${packageName} version`)
82
+ .toString()
83
+ .trim();
84
+ if (currentVersion !== latestVersion) {
85
+ logger.log(t('display_current_esa_template_version').d(`Current esa-template version:`) +
86
+ chalk.green(currentVersion) +
87
+ ' ' +
88
+ t('display_latest_esa_template_version').d(`Latest esa-template version:`) +
89
+ chalk.green(latestVersion));
90
+ const { isUpdate } = yield inquirer.prompt({
91
+ type: 'confirm',
92
+ name: 'isUpdate',
93
+ message: t('is_update_to_latest_version').d('Do you want to update templates to latest version?')
94
+ });
95
+ if (isUpdate) {
96
+ execSync(`rm -rf node_modules/${packageName} &&rm -rf package-lock.json &&npm install ${packageName}@latest`, {
97
+ cwd: packageJsonPath
98
+ });
99
+ logger.log(t('updated_esa_template_to_latest_version', { packageName }).d(`${packageName} updated successfully`));
100
+ }
101
+ }
102
+ else {
103
+ logger.log(t('esa_template_is_latest_version', { packageName }).d(`${packageName} is latest.`));
104
+ }
105
+ }
106
+ catch (error) {
107
+ console.log(error);
108
+ if (error instanceof Error) {
109
+ logger.error('æŁ€æ”‹ć’Œæ›Žæ–°ćŒ…æ—¶ć‘ç”Ÿé”™èŻŻïŒŒè·łèż‡æ›Žæ–°æšĄç‰ˆ');
110
+ }
111
+ }
112
+ });
113
+ }
@@ -9,43 +9,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import fs from 'fs-extra';
11
11
  import path from 'path';
12
+ import inquirer from 'inquirer';
13
+ import { exit } from 'process';
12
14
  import Template from '../../libs/templates/index.js';
13
15
  import { installGit } from '../../libs/git/index.js';
14
- import { descriptionInput } from '../../components/descriptionInput.js';
16
+ import multiLevelSelect from '../../components/mutiLevelSelect.js';
15
17
  import { generateConfigFile, getCliConfig, getProjectConfig, getTemplatesConfig, templateHubPath, updateProjectConfigFile } from '../../utils/fileUtils/index.js';
16
18
  import t from '../../i18n/index.js';
17
19
  import logger from '../../libs/logger.js';
18
- import SelectItems from '../../components/selectInput.js';
19
20
  import { quickDeploy } from '../deploy/index.js';
20
- import chalk from 'chalk';
21
21
  import { ApiService } from '../../libs/apiService.js';
22
- import { exit } from 'process';
23
22
  import { checkRoutineExist } from '../../utils/checkIsRoutineCreated.js';
24
- import { execSync } from 'child_process';
25
- import MultiLevelSelect from '../../components/mutiLevelSelect.js';
26
- import { getDirName } from '../../utils/fileUtils/base.js';
27
- import { yesNoPromptAndExecute } from '../deploy/helper.js';
28
23
  import { checkIsLoginSuccess } from '../utils.js';
29
- export const getTemplateInstances = (templateHubPath) => {
30
- return fs
31
- .readdirSync(templateHubPath)
32
- .filter((item) => {
33
- const itemPath = path.join(templateHubPath, item);
34
- return (fs.statSync(itemPath).isDirectory() &&
35
- !['.git', 'node_modules', 'lib'].includes(item));
36
- })
37
- .map((item) => {
38
- var _a;
39
- const projectPath = path.join(templateHubPath, item);
40
- const projectConfig = getProjectConfig(projectPath);
41
- const templateName = (_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _a !== void 0 ? _a : '';
42
- return new Template(projectPath, templateName);
43
- });
44
- };
45
- const secondSetOfItems = [
46
- { label: 'Yes', value: 'yesInstall' },
47
- { label: 'No', value: 'noInstall' }
48
- ];
24
+ import chalk from 'chalk';
25
+ import { checkAndUpdatePackage, getTemplateInstances, preInstallDependencies, transferTemplatesToSelectItem } from './helper.js';
49
26
  const init = {
50
27
  command: 'init',
51
28
  describe: `đŸ“„ ${t('init_describe').d('Initialize a routine with a template')}`,
@@ -58,186 +35,141 @@ const init = {
58
35
  },
59
36
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
60
37
  yield handleInit(argv);
38
+ exit(0);
61
39
  })
62
40
  };
63
41
  export default init;
64
- export const preInstallDependencies = (targetPath) => __awaiter(void 0, void 0, void 0, function* () {
65
- const packageJsonPath = path.join(targetPath, 'package.json');
66
- if (fs.existsSync(packageJsonPath)) {
67
- logger.log(t('init_install_dependence').d('⌛ Installing dependencies...'));
68
- execSync('npm install esa-template', {
69
- stdio: 'inherit',
70
- cwd: targetPath
71
- });
72
- logger.success(t('init_install_dependencies_success').d('Dependencies installed successfully.'));
73
- logger.log(t('init_build_project').d('⌛ Building project...'));
74
- execSync('npm run build', { stdio: 'inherit', cwd: targetPath });
75
- logger.success(t('init_build_project_success').d('Project built successfully.'));
76
- }
77
- });
78
- export const transferTemplatesToSelectItem = (configs, templateInstanceList, lang) => {
79
- if (!configs)
80
- return [];
81
- return configs.map((config) => {
82
- var _a, _b;
83
- const name = config.Title_EN;
84
- const value = (_b = (_a = templateInstanceList.find((template) => {
85
- return name === template.title;
86
- })) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : '';
87
- const children = transferTemplatesToSelectItem(config.children, templateInstanceList);
88
- return {
89
- label: lang === 'en' ? config.Title_EN : config.Title_ZH,
90
- value: value,
91
- key: name,
92
- children
93
- };
94
- });
95
- };
96
- function checkAndUpdatePackage(packageName) {
42
+ export function promptProjectName() {
97
43
  return __awaiter(this, void 0, void 0, function* () {
98
- try {
99
- // èŽ·ć–ćœ“ć‰ćź‰èŁ…çš„ç‰ˆæœŹ
100
- const __dirname = getDirName(import.meta.url);
101
- const packageJsonPath = path.join(__dirname, '../../../');
102
- const versionInfo = execSync(`npm list ${packageName}`, {
103
- cwd: packageJsonPath
104
- }).toString();
105
- const match = versionInfo.match(new RegExp(`(${packageName})@([0-9.]+)`));
106
- const currentVersion = match ? match[2] : '';
107
- // èŽ·ć–æœ€æ–°ç‰ˆæœŹ
108
- const latestVersion = execSync(`npm view ${packageName} version`)
109
- .toString()
110
- .trim();
111
- if (currentVersion !== latestVersion) {
112
- logger.log(t('display_current_esa_template_version').d(`Current esa-template version:`) +
113
- chalk.green(currentVersion) +
114
- ' ' +
115
- t('display_latest_esa_template_version').d(`Latest esa-template version:`) +
116
- chalk.green(latestVersion));
117
- yield yesNoPromptAndExecute(t('is_update_to_latest_version').d('Do you want to update templates to latest version?'), () => __awaiter(this, void 0, void 0, function* () {
118
- logger.log(t('updating_esa_template_to_latest_version', { packageName }).d(`Updating ${packageName} to the latest version...`));
119
- execSync(`rm -rf node_modules/${packageName} &&rm -rf package-lock.json &&npm install ${packageName}@latest`, {
120
- cwd: packageJsonPath
121
- });
122
- logger.log(t('updated_esa_template_to_latest_version', { packageName }).d(`${packageName} updated successfully`));
44
+ const { name } = yield inquirer.prompt([
45
+ {
46
+ type: 'input',
47
+ name: 'name',
48
+ message: `đŸ–Šïž ${t('init_input_name').d('Enter the name of edgeRoutine:')}`,
49
+ validate: (input) => {
50
+ const regex = /^[a-z0-9-]{2,}$/;
51
+ if (!regex.test(input)) {
52
+ return t('init_name_error').d('Error: The project name must be at least 2 characters long and can only contain lowercase letters, numbers, and hyphens.');
53
+ }
123
54
  return true;
124
- }));
55
+ }
125
56
  }
126
- else {
127
- logger.log(t('esa_template_is_latest_version', { packageName }).d(`${packageName} is latest.`));
57
+ ]);
58
+ return name;
59
+ });
60
+ }
61
+ export function prepareTemplateItems() {
62
+ var _a;
63
+ const templateInstanceList = getTemplateInstances(templateHubPath);
64
+ const templateConfig = getTemplatesConfig();
65
+ const cliConfig = getCliConfig();
66
+ const lang = (_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.lang) !== null && _a !== void 0 ? _a : 'en';
67
+ return transferTemplatesToSelectItem(templateConfig, templateInstanceList, lang);
68
+ }
69
+ export function selectTemplate(items) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ const selectedTemplatePath = yield multiLevelSelect(items, 'Select a template:');
72
+ if (!selectedTemplatePath) {
73
+ logger.log(t('init_cancel').d('User canceled the operation.'));
74
+ return null;
75
+ }
76
+ return selectedTemplatePath;
77
+ });
78
+ }
79
+ export function initializeProject(selectedTemplatePath, name) {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ const selectTemplate = new Template(selectedTemplatePath, name);
82
+ const projectConfig = getProjectConfig(selectedTemplatePath);
83
+ if (!projectConfig) {
84
+ logger.notInProject();
85
+ return null;
86
+ }
87
+ const targetPath = path.join(process.cwd(), name);
88
+ if (fs.existsSync(targetPath)) {
89
+ logger.error(t('already_exist_file_error').d('Error: The project already exists. It looks like a folder named "<project-name>" is already present in the current directory. Please try the following options: 1. Choose a different project name. 2. Delete the existing folder if it\'s not needed: `rm -rf <project-name>` (use with caution!). 3. Move to a different directory before running the init command.'));
90
+ return null;
91
+ }
92
+ yield fs.copy(selectedTemplatePath, targetPath);
93
+ projectConfig.name = name;
94
+ yield updateProjectConfigFile(projectConfig, targetPath);
95
+ yield preInstallDependencies(targetPath);
96
+ return { template: selectTemplate, targetPath };
97
+ });
98
+ }
99
+ export function handleGitInitialization(targetPath) {
100
+ return __awaiter(this, void 0, void 0, function* () {
101
+ const { initGit } = yield inquirer.prompt([
102
+ {
103
+ type: 'list',
104
+ name: 'initGit',
105
+ message: t('init_git').d('Do you want to init git in your project?'),
106
+ choices: ['Yes', 'No']
128
107
  }
108
+ ]);
109
+ if (initGit === 'Yes') {
110
+ installGit(targetPath);
111
+ }
112
+ else {
113
+ logger.log(t('init_skip_git').d('Git installation was skipped.'));
129
114
  }
130
- catch (error) {
131
- if (error instanceof Error) {
132
- logger.error('æŁ€æ”‹ć’Œæ›Žæ–°ćŒ…æ—¶ć‘ç”Ÿé”™èŻŻïŒŒè·łèż‡æ›Žæ–°æšĄç‰ˆ');
115
+ });
116
+ }
117
+ export function handleDeployment(targetPath, projectConfig) {
118
+ return __awaiter(this, void 0, void 0, function* () {
119
+ var _a, _b, _c;
120
+ const isLoginSuccess = yield checkIsLoginSuccess();
121
+ if (!isLoginSuccess) {
122
+ logger.log(chalk.yellow(t('not_login_auto_deploy').d('You are not logged in, automatic deployment cannot be performed. Please log in later and manually deploy.')));
123
+ return;
124
+ }
125
+ const { deploy } = yield inquirer.prompt([
126
+ {
127
+ type: 'list',
128
+ name: 'deploy',
129
+ message: t('auto_deploy').d('Do you want to deploy your project?'),
130
+ choices: ['Yes', 'No']
133
131
  }
132
+ ]);
133
+ if (deploy === 'Yes') {
134
+ yield checkRoutineExist((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _a !== void 0 ? _a : '', targetPath);
135
+ yield quickDeploy(targetPath, projectConfig);
136
+ const service = yield ApiService.getInstance();
137
+ const res = yield service.getRoutine({ Name: (_b = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _b !== void 0 ? _b : '' });
138
+ const defaultUrl = (_c = res === null || res === void 0 ? void 0 : res.data) === null || _c === void 0 ? void 0 : _c.DefaultRelatedRecord;
139
+ const visitUrl = defaultUrl ? 'http://' + defaultUrl : '';
140
+ logger.success(`${t('init_deploy_success').d('Project deployment completed. Visit: ')}${chalk.yellowBright(visitUrl)}`);
141
+ logger.warn(t('deploy_url_warn').d('The domain may take some time to take effect, please try again later.'));
134
142
  }
135
143
  });
136
144
  }
137
145
  export function handleInit(argv) {
138
146
  return __awaiter(this, void 0, void 0, function* () {
139
- var _a;
140
- const { config } = argv;
141
- // 曎新template npm挅
147
+ // Update the template package (currently commented out)
142
148
  yield checkAndUpdatePackage('esa-template');
143
- if (config !== undefined) {
149
+ // If config option is provided, generate config file and exit
150
+ const config = getCliConfig();
151
+ if (config === undefined) {
144
152
  yield generateConfigFile(String(config));
145
- return;
146
153
  }
147
- const name = yield descriptionInput(`đŸ–Šïž ${t('init_input_name').d('Enter the name of edgeRoutine:')}`, true);
148
- const regex = /^[a-z0-9-]{2,}$/;
149
- if (!regex.test(name)) {
150
- logger.error(t('init_name_error').d('Error: The project name must be at least 2 characters long and can only contain lowercase letters, numbers, and hyphens.'));
154
+ const name = yield promptProjectName();
155
+ const templateItems = prepareTemplateItems();
156
+ // Select a template
157
+ const selectedTemplatePath = yield selectTemplate(templateItems);
158
+ if (!selectedTemplatePath) {
151
159
  return;
152
160
  }
153
- const templateInstanceList = getTemplateInstances(templateHubPath);
154
- const templateConfig = getTemplatesConfig();
155
- const cliConfig = getCliConfig();
156
- const lang = (_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.lang) !== null && _a !== void 0 ? _a : 'en';
157
- const firstSetOfItems = transferTemplatesToSelectItem(templateConfig, templateInstanceList, lang);
158
- let selectTemplate;
159
- let targetPath;
160
- let projectConfig;
161
- const preInstallDependencies = () => __awaiter(this, void 0, void 0, function* () {
162
- const packageJsonPath = path.join(targetPath, 'package.json');
163
- if (fs.existsSync(packageJsonPath)) {
164
- logger.log('Install dependencies');
165
- logger.log(t('init_install_dependence').d('⌛ Installing dependencies...'));
166
- execSync('npm install', { stdio: 'inherit', cwd: targetPath });
167
- logger.success(t('init_install_dependencies_success').d('Dependencies installed successfully.'));
168
- logger.log(t('init_build_project').d('⌛ Building project...'));
169
- execSync('npm run build', { stdio: 'inherit', cwd: targetPath });
170
- logger.success(t('init_build_project_success').d('Project built successfully.'));
171
- }
172
- });
173
- const handleFirstSelection = (item) => __awaiter(this, void 0, void 0, function* () {
174
- if (item.key === 'exit') {
175
- process.exit(0);
176
- }
177
- const configPath = item.value;
178
- selectTemplate = new Template(configPath, name);
179
- projectConfig = getProjectConfig(configPath);
180
- if (!projectConfig)
181
- return logger.notInProject();
182
- const newPath = process.cwd() + '/' + name;
183
- targetPath = newPath;
184
- if (fs.existsSync(newPath)) {
185
- logger.error(t('already_exist_file_error').d('Error: The project already exists. It looks like a folder named "<project-name>" is already present in the current directory. Please try the following options: 1. Choose a different project name. 2. Delete the existing folder if it\'s not needed: `rm -rf <project-name>` (use with caution!). 3. Move to a different directory before running the init command.'));
186
- exit(0);
187
- }
188
- yield fs.copy(configPath, newPath);
189
- projectConfig.name = name;
190
- updateProjectConfigFile(projectConfig, newPath);
191
- preInstallDependencies();
192
- logger.log(t('init_git').d('Do you want to init git in your project?'));
193
- SelectItems({
194
- items: secondSetOfItems,
195
- handleSelect: handleSecondSelection
196
- });
197
- });
198
- const handleSecondSelection = (item) => __awaiter(this, void 0, void 0, function* () {
199
- if (item.value === 'yesInstall') {
200
- installGit(targetPath);
201
- }
202
- else {
203
- logger.log(t('init_skip_git').d('Git installation was skipped.'));
204
- }
205
- const isLoginSuccess = yield checkIsLoginSuccess();
206
- if (!isLoginSuccess) {
207
- logger.log(chalk.yellow(t('not_login_auto_deploy').d('You are not logged in, automatic deployment cannot be performed. Please log in later and manually deploy.')));
208
- process.exit(0);
209
- }
210
- logger.log(t('auto_deploy').d('Do you want to deploy your project?'));
211
- SelectItems({
212
- items: secondSetOfItems,
213
- handleSelect: handleThirdSelection
214
- });
215
- });
216
- const handleThirdSelection = (item) => __awaiter(this, void 0, void 0, function* () {
217
- var _a, _b, _c;
218
- // 选择è‡ȘćŠšç”Ÿæˆç‰ˆæœŹćč¶ć‘ćžƒ
219
- if (item.value === 'yesInstall') {
220
- yield checkRoutineExist((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _a !== void 0 ? _a : '', targetPath);
221
- projectConfig && (yield quickDeploy(targetPath, projectConfig));
222
- const service = yield ApiService.getInstance();
223
- const res = yield service.getRoutine({ Name: (_b = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) !== null && _b !== void 0 ? _b : '' });
224
- const defaultUrl = (_c = res === null || res === void 0 ? void 0 : res.data) === null || _c === void 0 ? void 0 : _c.DefaultRelatedRecord;
225
- const visitUrl = defaultUrl ? 'http://' + defaultUrl : '';
226
- logger.success(`${t('init_deploy_success').d('Project deployment completed. Visit: ')}${chalk.yellowBright(visitUrl)}`);
227
- logger.warn(t('deploy_url_warn').d('The domain may take some time to take effect, please try again later.'));
228
- }
229
- selectTemplate.printSummary();
230
- exit(0);
231
- });
232
- try {
233
- MultiLevelSelect({
234
- items: firstSetOfItems,
235
- handleSelect: handleFirstSelection
236
- });
237
- }
238
- catch (error) {
239
- logger.error(t('init_error').d('An error occurred while initializing.'));
240
- console.log(error);
161
+ // Initialize project files and configuration
162
+ const project = yield initializeProject(selectedTemplatePath, name);
163
+ if (!project) {
164
+ return;
241
165
  }
166
+ const { template, targetPath } = project;
167
+ // Handle Git initialization
168
+ yield handleGitInitialization(targetPath);
169
+ // Handle deployment
170
+ const projectConfig = getProjectConfig(targetPath);
171
+ yield handleDeployment(targetPath, projectConfig);
172
+ template.printSummary();
173
+ return;
242
174
  });
243
175
  }
@@ -7,63 +7,52 @@ 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
- import { render, Text, useApp } from 'ink';
12
- import SelectInput from 'ink-select-input';
13
- import Item from './selectItem.js';
14
- import t from '../i18n/index.js';
15
- const Indicator = ({ isSelected }) => {
16
- return React.createElement(Text, null, isSelected ? '👉 ' : ' ');
17
- };
18
- const EXIT_ITEM = {
19
- label: t('exit_select_init_template').d('Exit'),
20
- key: 'exit',
21
- value: '__exit__'
22
- };
23
- const RETURN_ITEM = {
24
- label: t('return_select_init_template').d('Return'),
25
- key: 'return',
26
- value: '__return__'
27
- };
28
- const MultiLevelSelect = ({ items, handleSelect, handleExit }) => {
29
- const { exit } = useApp();
30
- const [stack, setStack] = useState([[...items, EXIT_ITEM]]);
31
- const currentItems = stack[stack.length - 1];
32
- const onSelect = (item) => {
33
- if (item.value === '__return__') {
34
- if (stack.length > 1) {
35
- // èż”ć›žäžŠäž€çș§èœć•
36
- setStack(stack.slice(0, -1));
10
+ import inquirer from 'inquirer';
11
+ import logger from '../libs/logger.js';
12
+ /**
13
+ * Perform multi-level selection and return the final selected template path
14
+ * @param items Array of selection items (including categories and sub-templates)
15
+ * @param message Initial prompt message
16
+ * @returns Selected template path, or null if the user exits
17
+ */
18
+ export default function multiLevelSelect(items_1) {
19
+ return __awaiter(this, arguments, void 0, function* (items, message = 'Select a template:') {
20
+ let currentItems = items; // Current level options
21
+ const stack = []; // Stack to store previous level options for back navigation
22
+ let selectedPath = null;
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') {
38
+ logger.log('User canceled the operation.');
39
+ return null;
40
+ }
41
+ if (choice === 'back') {
42
+ currentItems = stack.pop(); // Return to the previous level
43
+ continue;
44
+ }
45
+ // If a category with children is selected
46
+ if (choice.children && choice.children.length > 0) {
47
+ stack.push(currentItems); // Save the current level
48
+ currentItems = choice.children; // Move to the next level
49
+ message = `Select a template under ${choice.label}:`;
37
50
  }
38
51
  else {
39
- // éĄ¶ć±‚èœć•ïŒŒæ‰§èĄŒé€€ć‡ș逻蟑
40
- handleExit();
41
- exit();
52
+ // A leaf node (no children) is selected, end the selection
53
+ selectedPath = choice.value;
42
54
  }
43
- return;
44
- }
45
- if (item.children && item.children.length > 0) {
46
- setStack([...stack, [...item.children, RETURN_ITEM]]); // ćœšć­ć±‚çș§äž­æ·»ćŠ â€œé€€ć‡ș”选éĄč
47
55
  }
48
- else {
49
- handleSelect(item);
50
- exit();
51
- }
52
- };
53
- return (React.createElement(SelectInput, { items: currentItems, onSelect: onSelect, itemComponent: Item, indicatorComponent: Indicator, limit: 10 }));
54
- };
55
- export const MultiLevelSelectComponent = (props) => __awaiter(void 0, void 0, void 0, function* () {
56
- const { items, handleSelect, handleExit } = props;
57
- return new Promise((resolve) => {
58
- const { unmount } = render(React.createElement(MultiLevelSelect, { items: items, handleSelect: (item) => {
59
- unmount();
60
- handleSelect && handleSelect(item);
61
- resolve(item);
62
- }, handleExit: () => {
63
- unmount();
64
- handleExit && handleExit();
65
- resolve(null);
66
- } }));
56
+ return selectedPath;
67
57
  });
68
- });
69
- export default MultiLevelSelectComponent;
58
+ }
@@ -476,8 +476,8 @@
476
476
  "zh_CN": "routeäžćˆæł•"
477
477
  },
478
478
  "install_runtime_explain": {
479
- "en": "Under the beta phase, we are temporarily using Deno as the local development runtime. It needs to be installed first.",
480
- "zh_CN": "朹Betaé˜¶æź”ïŒŒæˆ‘ä»Źäœżç”šäș†Deno暂时䜜äžșæœŹćœ°ćŒ€ć‘èżèĄŒæ—¶ïŒŒéœ€èŠć…ˆćź‰èŁ…æ‰ćŻä»„dev。"
479
+ "en": "Our runtime does not yet support this OS. We are temporarily using Deno as the local development runtime, which needs to be installed first.",
480
+ "zh_CN": "æˆ‘ä»Źçš„Runtimeèż˜äžæ”ŻæŒæ­€æ“äœœçł»ç»ŸïŒŒæˆ‘ä»Źæš‚æ—¶äœżç”šDeno䜜äžșæœŹćœ°ćŒ€ć‘runtimeïŒŒéœ€èŠć…ˆćź‰èŁ…ă€‚"
481
481
  },
482
482
  "install_runtime_tip": {
483
483
  "en": "🔔 Runtime must be installed to use esa dev. Installing...",
@@ -894,5 +894,45 @@
894
894
  "dev_url_invalid": {
895
895
  "en": "Invalid URL: ${url}. Please enter a valid URL.",
896
896
  "zh_CN": "äžæ˜Żæ­ŁçĄźçš„URL: ${url}. èŻ·èŸ“ć…„æ­ŁçĄźçš„URL."
897
+ },
898
+ "deno_download_failed": {
899
+ "en": "Download failed",
900
+ "zh_CN": "äž‹èœœć€±èŽ„"
901
+ },
902
+ "deno_unzip_failed": {
903
+ "en": "Unzip failed",
904
+ "zh_CN": "è§ŁćŽ‹ć€±èŽ„"
905
+ },
906
+ "deno_add_path_failed": {
907
+ "en": "Add BinDir to Path failed",
908
+ "zh_CN": "æ·»ćŠ çŽŻćąƒć˜é‡ć€±èŽ„"
909
+ },
910
+ "deno_install_success": {
911
+ "en": "Runtime install success!",
912
+ "zh_CN": "Runtime ćź‰èŁ…æˆćŠŸïŒ"
913
+ },
914
+ "deno_download_success": {
915
+ "en": "Download success",
916
+ "zh_CN": "äž‹èœœæˆćŠŸ"
917
+ },
918
+ "deno_install_success_tips": {
919
+ "en": "Please run ${dev} again",
920
+ "zh_CN": "èŻ·é‡æ–°èżèĄŒ ${dev}"
921
+ },
922
+ "no_build_script": {
923
+ "en": "No build script found in package.json, skipping build step.",
924
+ "zh_CN": "朹 package.json äž­æœȘæ‰Ÿćˆ°æž„ć»șè„šæœŹïŒŒè·łèż‡æž„ć»șæ­„éȘ€ă€‚"
925
+ },
926
+ "init_cancel": {
927
+ "en": "User canceled the operation.",
928
+ "zh_CN": "ç”šæˆ·ć–æ¶ˆäș†æ“äœœă€‚"
929
+ },
930
+ "routine_create_success": {
931
+ "en": "Routine created successfully.",
932
+ "zh_CN": "èŸčçŒ˜ć‡œæ•°ćˆ›ć»șæˆćŠŸ"
933
+ },
934
+ "routine_create_fail": {
935
+ "en": "Routine created failed.",
936
+ "zh_CN": "èŸčçŒ˜ć‡œæ•°ćˆ›ć»șć€±èŽ„"
897
937
  }
898
938
  }
package/dist/index.js CHANGED
@@ -26,7 +26,6 @@ import { getCliConfig } from './utils/fileUtils/index.js';
26
26
  import { handleCheckVersion } from './utils/checkVersion.js';
27
27
  import t from './i18n/index.js';
28
28
  import site from './commands/site/index.js';
29
- import { quickDeployRoutine } from './libs/service.js';
30
29
  const main = () => __awaiter(void 0, void 0, void 0, function* () {
31
30
  const argv = hideBin(process.argv);
32
31
  const cliConfig = getCliConfig();
@@ -74,13 +73,6 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
74
73
  esa.command(logout);
75
74
  esa.command(config);
76
75
  esa.command(lang);
77
- esa.command('t', false, () => { }, (args) => __awaiter(void 0, void 0, void 0, function* () {
78
- const res = yield quickDeployRoutine({
79
- name: 'test',
80
- code: 'test'
81
- });
82
- // console.log(res);
83
- }));
84
76
  esa.group(['help', 'version'], 'Options:');
85
77
  esa.parse();
86
78
  });
@@ -10,7 +10,7 @@ import { getProjectConfig } from '../utils/fileUtils/index.js';
10
10
  const transport = new DailyRotateFile({
11
11
  filename: path.join(os.homedir(), '.esa-logs/esa-debug-%DATE%.log'),
12
12
  level: 'info',
13
- datePattern: 'YYYY-MM-DD-HH:mm:ss',
13
+ datePattern: 'YYYY-MM-DD-HH',
14
14
  zippedArchive: true,
15
15
  maxSize: '10m',
16
16
  maxFiles: '7d'
@@ -1,5 +1,6 @@
1
1
  import { getSummary } from '../../commands/common/constant.js';
2
2
  import chalk from 'chalk';
3
+ import logger from '../logger.js';
3
4
  export default class Template {
4
5
  constructor(path, title) {
5
6
  this.path = path;
@@ -10,7 +11,7 @@ export default class Template {
10
11
  list.forEach((summary) => {
11
12
  const title = chalk.bold(summary.title);
12
13
  const command = chalk.green(summary.command);
13
- console.log(`${title}: ${command}`);
14
+ logger.log(`${title}: ${command}`);
14
15
  });
15
16
  }
16
17
  }
@@ -51,11 +51,22 @@ export function checkRoutineExist(name, entry) {
51
51
  return acc;
52
52
  }, []);
53
53
  const spec = yield displaySelectSpec(specList);
54
- yield createEdgeRoutine({
54
+ console.log({
55
55
  name: name,
56
56
  specName: spec,
57
57
  code: code
58
58
  });
59
+ const res = yield createEdgeRoutine({
60
+ name: name,
61
+ specName: spec,
62
+ code: code
63
+ });
64
+ if (res) {
65
+ logger.success(t('routine_create_success').d('Routine created successfully.'));
66
+ }
67
+ else {
68
+ logger.error(t('routine_create_fail').d('Routine created failed.'));
69
+ }
59
70
  }
60
71
  });
61
72
  }
@@ -13,7 +13,7 @@ import path from 'path';
13
13
  export function handleCheckVersion() {
14
14
  return __awaiter(this, void 0, void 0, function* () {
15
15
  const __dirname = getDirName(import.meta.url);
16
- const packageJsonPath = path.join(__dirname, '..', 'package.json');
16
+ const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
17
17
  try {
18
18
  const jsonString = yield fs.readFile(packageJsonPath, 'utf-8');
19
19
  const packageJson = JSON.parse(jsonString);
@@ -0,0 +1,182 @@
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 fetch from 'node-fetch';
11
+ import * as fs from 'fs/promises';
12
+ import * as path from 'path';
13
+ import os from 'os';
14
+ import AdmZip from 'adm-zip';
15
+ import { exec } from 'child_process';
16
+ import { promisify } from 'util';
17
+ import t from '../i18n/index.js';
18
+ import logger from '../libs/logger.js';
19
+ import chalk from 'chalk';
20
+ const execAsync = promisify(exec);
21
+ function getBinDir() {
22
+ const home = os.homedir();
23
+ return path.join(home || '', '.deno', 'bin');
24
+ }
25
+ /**
26
+ * 䞋蜜文件
27
+ * @param url èżœçš‹æ–‡ä»¶URL
28
+ * @param dest æœŹćœ°äżć­˜è·ŻćŸ„
29
+ */
30
+ export function downloadFile(url, dest) {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ const response = yield fetch(url);
33
+ if (!response.ok) {
34
+ throw new Error(`Error downloading file: ${response.status} ${response.statusText}`);
35
+ }
36
+ const fileStream = yield fs.open(dest, 'w');
37
+ return new Promise((resolve, reject) => {
38
+ var _a, _b;
39
+ (_a = response.body) === null || _a === void 0 ? void 0 : _a.pipe(fileStream.createWriteStream());
40
+ (_b = response.body) === null || _b === void 0 ? void 0 : _b.on('error', (err) => {
41
+ fileStream.close();
42
+ reject(err);
43
+ });
44
+ fileStream.createWriteStream().on('finish', () => {
45
+ fileStream.close();
46
+ resolve();
47
+ });
48
+ });
49
+ });
50
+ }
51
+ /**
52
+ * è§ŁćŽ‹Zip文件 adm æ˜ŻćŒæ­„çš„
53
+ * @param zipPath Zipæ–‡ä»¶è·ŻćŸ„
54
+ * @param extractPath è§ŁćŽ‹ç›źæ ‡ç›źćœ•
55
+ */
56
+ export function unzipFile(zipPath, extractPath) {
57
+ const zip = new AdmZip(zipPath);
58
+ zip.extractAllTo(extractPath, true);
59
+ logger.info(`UnzipFile success: from ${zipPath} to ${extractPath}`);
60
+ }
61
+ /**
62
+ * èŽ·ć–ç”šæˆ·çš„ PATH çŽŻćąƒć˜é‡ïŒˆwin䞋䞓甚
63
+ * @returns 甚户 PATH
64
+ */
65
+ function getUserPath() {
66
+ return __awaiter(this, void 0, void 0, function* () {
67
+ const { stdout } = yield execAsync('reg query "HKCU\\Environment" /v Path');
68
+ const match = stdout.match(/Path\s+REG_EXPAND_SZ\s+(.*)/i);
69
+ if (match && match[1]) {
70
+ return match[1].trim();
71
+ }
72
+ return '';
73
+ });
74
+ }
75
+ /**
76
+ * æŁ€æŸ„ BinDir æ˜ŻćŠćœšç”šæˆ·çš„ PATH 䞭win䞋䞓甚
77
+ * @param binDir BinDir è·ŻćŸ„
78
+ * @returns æ˜ŻćŠćŒ…ć«
79
+ */
80
+ function isBinDirInPath(binDir) {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ const userPath = yield getUserPath();
83
+ return userPath
84
+ .split(';')
85
+ .map((p) => p.toLowerCase())
86
+ .includes(binDir.toLowerCase());
87
+ });
88
+ }
89
+ /**
90
+ * 氆 BinDir æ·»ćŠ ćˆ°ç”šæˆ·çš„ PATH çŽŻćąƒć˜é‡ïŒˆwin䞋䞓甚
91
+ * @param binDir BinDir è·ŻćŸ„
92
+ */
93
+ function addBinDirToPath(binDir) {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ // äœżç”š setx æ·»ćŠ ćˆ° PATH
96
+ // setx ćŻč PATH 的长ćșŠæœ‰2047ć­—çŹŠçš„é™ćˆ¶
97
+ const command = `setx Path "%Path%;${binDir}"`;
98
+ try {
99
+ yield execAsync(command);
100
+ logger.info(`Path add success: ${binDir}`);
101
+ }
102
+ catch (error) {
103
+ throw new Error(`Add BinDir to Path failed: ${error}`);
104
+ }
105
+ });
106
+ }
107
+ export function downloadRuntimeAndUnzipForWindows() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ try {
110
+ const BinDir = getBinDir();
111
+ const DenoZip = path.join(BinDir, 'deno.zip');
112
+ const Target = 'x86_64-pc-windows-msvc';
113
+ const DownloadUrl = `http://esa-runtime.myalicdn.com/runtime/deno-${Target}.zip`;
114
+ logger.ora.start('Downloading...');
115
+ try {
116
+ yield fs.mkdir(BinDir, { recursive: true });
117
+ }
118
+ catch (error) {
119
+ const err = error;
120
+ logger.ora.fail();
121
+ logger.error(`mkdir error ${BinDir}: ${err.message}`);
122
+ process.exit(1);
123
+ }
124
+ try {
125
+ yield downloadFile(DownloadUrl, DenoZip);
126
+ }
127
+ catch (error) {
128
+ const err = error;
129
+ logger.ora.fail();
130
+ logger.error(`${t('deno_download_failed').d('Download failed')}: ${err.message}`);
131
+ process.exit(1);
132
+ }
133
+ logger.info(`Unzip file to: ${BinDir}`);
134
+ try {
135
+ logger.ora.text = 'Unzip...';
136
+ unzipFile(DenoZip, BinDir);
137
+ }
138
+ catch (error) {
139
+ const err = error;
140
+ logger.ora.fail();
141
+ logger.error(`${t('deno_unzip_failed').d('Unzip failed')}: ${err.message}`);
142
+ process.exit(1);
143
+ }
144
+ try {
145
+ logger.ora.text = 'Deleting temp file...';
146
+ yield fs.unlink(DenoZip);
147
+ logger.ora.succeed('Download success');
148
+ logger.info(`Delete temp file: ${DenoZip}`);
149
+ }
150
+ catch (error) {
151
+ logger.warn(`Delete temp file ${DenoZip} failed: ${error}`);
152
+ }
153
+ try {
154
+ logger.ora.text = 'Adding Bin dir to PATH...';
155
+ const inPath = yield isBinDirInPath(BinDir);
156
+ if (!inPath) {
157
+ logger.info(`${BinDir} not in PATH`);
158
+ yield addBinDirToPath(BinDir);
159
+ }
160
+ else {
161
+ logger.info(`${BinDir} in PATH already`);
162
+ }
163
+ }
164
+ catch (error) {
165
+ const err = error;
166
+ logger.ora.fail();
167
+ logger.error(`${t('deno_add_path_failed').d('Add BinDir to Path failed')}: ${err.message}`);
168
+ process.exit(1);
169
+ }
170
+ logger.success(t('deno_install_success').d('Runtime install success!'));
171
+ logger.block();
172
+ const dev = chalk.green('esa dev');
173
+ logger.log(t('deno_install_success_tips', { dev }).d(`Please run ${dev} again`));
174
+ }
175
+ catch (error) {
176
+ const err = error;
177
+ logger.ora.fail();
178
+ logger.error(`Download Error: ${err.message}`);
179
+ process.exit(1);
180
+ }
181
+ });
182
+ }
@@ -11,7 +11,7 @@ export const getRoot = (root) => {
11
11
  if (typeof root === 'undefined') {
12
12
  root = process.cwd();
13
13
  }
14
- if (root === '/') {
14
+ if (path.parse(root).root === root) {
15
15
  return process.cwd();
16
16
  }
17
17
  const file = path.join(root, cliConfigFile);
@@ -9,16 +9,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { exec, execSync } from 'child_process';
11
11
  import os from 'os';
12
- import { getDirName } from './fileUtils/base.js';
13
- import logger from '../libs/logger.js';
14
12
  import path from 'path';
13
+ import logger from '../libs/logger.js';
14
+ import { getDirName } from './fileUtils/base.js';
15
+ import { downloadRuntimeAndUnzipForWindows } from './download.js';
15
16
  import t from '../i18n/index.js';
16
17
  export function preCheckDeno() {
17
18
  return __awaiter(this, void 0, void 0, function* () {
18
19
  const command = yield checkDenoInstalled();
19
20
  if (!command) {
20
- logger.error(t('install_runtime_explain').d('Under the beta phase, we are temporarily using Deno as the local development runtime. It needs to be installed first.'));
21
- installDeno();
21
+ logger.error(t('install_runtime_explain').d('Our runtime does not yet support this OS. We are temporarily using Deno as the local development runtime, which needs to be installed first.'));
22
+ yield installDeno();
22
23
  return false;
23
24
  }
24
25
  return command;
@@ -45,7 +46,6 @@ export function checkDenoInstalled() {
45
46
  resolve(res);
46
47
  })
47
48
  .catch((err) => {
48
- console.log(err);
49
49
  resolve(false);
50
50
  });
51
51
  });
@@ -57,8 +57,8 @@ export function installDeno() {
57
57
  const p = path.join(__dirname, './install');
58
58
  switch (os.platform()) {
59
59
  case 'win32':
60
- installCommand = `powershell.exe -Command "Get-Content '${p}/install.ps1' | iex"`;
61
- break;
60
+ yield downloadRuntimeAndUnzipForWindows();
61
+ return true;
62
62
  case 'darwin':
63
63
  case 'linux':
64
64
  installCommand = `sh ${p}/install.sh`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esa-cli",
3
- "version": "0.0.2-beta.1",
3
+ "version": "0.0.2-beta.10",
4
4
  "description": "A CLI for operating Alibaba Cloud ESA EdgeRoutine (Edge Functions).",
5
5
  "main": "bin/enter.cjs",
6
6
  "type": "module",
@@ -37,6 +37,7 @@
37
37
  "@testing-library/dom": "^10.4.0",
38
38
  "@testing-library/jest-dom": "^6.5.0",
39
39
  "@testing-library/react": "^16.0.1",
40
+ "@types/adm-zip": "^0.5.7",
40
41
  "@types/babel__generator": "^7.6.8",
41
42
  "@types/babel__traverse": "^7.20.6",
42
43
  "@types/cli-table": "^0.3.4",
@@ -74,7 +75,7 @@
74
75
  "@iarna/toml": "^2.2.5",
75
76
  "@types/inquirer": "^9.0.7",
76
77
  "@vitest/coverage-istanbul": "^2.0.4",
77
- "axios": "^1.7.7",
78
+ "adm-zip": "^0.5.16",
78
79
  "chalk": "^5.3.0",
79
80
  "chokidar": "^3.5.3",
80
81
  "cli-table3": "^0.6.5",