esa-cli 0.0.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -149
- package/dist/commands/commit/index.js +49 -104
- package/dist/commands/commit/prodBuild.js +2 -3
- package/dist/commands/common/constant.js +4 -4
- package/dist/commands/common/utils.js +419 -0
- package/dist/commands/config.js +2 -2
- package/dist/commands/deploy/helper.js +43 -49
- package/dist/commands/deploy/index.js +51 -174
- package/dist/commands/deployments/delete.js +32 -22
- package/dist/commands/deployments/index.js +4 -4
- package/dist/commands/deployments/list.js +21 -34
- package/dist/commands/dev/build.js +3 -3
- package/dist/commands/dev/doProcess.js +5 -5
- package/dist/commands/dev/ew2/cacheService.js +33 -0
- package/dist/commands/dev/ew2/devEntry.js +2 -1
- package/dist/commands/dev/ew2/devPack.js +31 -20
- package/dist/commands/dev/ew2/kvService.js +50 -0
- package/dist/commands/dev/ew2/mock/cache.js +99 -15
- package/dist/commands/dev/ew2/mock/kv.js +142 -21
- package/dist/commands/dev/ew2/server.js +163 -28
- package/dist/commands/dev/index.js +17 -18
- package/dist/commands/dev/mockWorker/devPack.js +19 -10
- package/dist/commands/dev/mockWorker/server.js +7 -6
- package/dist/commands/domain/add.js +4 -4
- package/dist/commands/domain/delete.js +3 -3
- package/dist/commands/domain/index.js +4 -4
- package/dist/commands/domain/list.js +7 -7
- package/dist/commands/init/helper.js +654 -21
- package/dist/commands/init/index.js +88 -152
- package/dist/commands/init/snippets/nextjs/next.config.mjs +6 -0
- package/dist/commands/init/snippets/nextjs/next.config.ts +7 -0
- package/dist/commands/init/snippets/react-router/react-router.config.ts +7 -0
- package/dist/commands/init/template.jsonc +84 -0
- package/dist/commands/init/types.js +1 -0
- package/dist/commands/lang.js +2 -2
- package/dist/commands/login/index.js +74 -34
- package/dist/commands/logout.js +6 -6
- package/dist/commands/route/add.js +101 -43
- package/dist/commands/route/delete.js +6 -6
- package/dist/commands/route/helper.js +9 -10
- package/dist/commands/route/index.js +4 -4
- package/dist/commands/route/list.js +4 -4
- package/dist/commands/routine/delete.js +9 -8
- package/dist/commands/routine/index.js +6 -5
- package/dist/commands/routine/list.js +45 -39
- package/dist/commands/site/index.js +3 -3
- package/dist/commands/site/list.js +6 -7
- package/dist/commands/utils.js +61 -25
- package/dist/components/descriptionInput.js +1 -1
- package/dist/components/filterSelector.js +1 -1
- package/dist/components/mutiLevelSelect.js +19 -20
- package/dist/components/mutiSelectTable.js +1 -1
- package/dist/components/routeBuilder.js +68 -0
- package/dist/components/selectInput.js +2 -3
- package/dist/components/selectItem.js +1 -1
- package/dist/docs/Commands_en.md +164 -117
- package/dist/docs/Commands_zh_CN.md +155 -107
- package/dist/docs/Config_en.md +70 -0
- package/dist/docs/Config_zh_CN.md +68 -0
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/locales.json +414 -82
- package/dist/index.js +28 -13
- package/dist/libs/api.js +3 -6
- package/dist/libs/apiService.js +192 -69
- package/dist/libs/git/index.js +86 -9
- package/dist/libs/interface.js +0 -1
- package/dist/libs/logger.js +162 -10
- package/dist/libs/service.js +2 -2
- package/dist/libs/templates/index.js +1 -1
- package/dist/utils/checkAssetsExist.js +80 -0
- package/dist/utils/checkDevPort.js +5 -19
- package/dist/utils/checkEntryFileExist.js +10 -0
- package/dist/utils/checkIsRoutineCreated.js +27 -21
- package/dist/utils/checkVersion.js +119 -1
- package/dist/utils/command.js +149 -0
- package/dist/utils/compress.js +142 -0
- package/dist/utils/download.js +8 -8
- package/dist/utils/fileMd5.js +1 -1
- package/dist/utils/fileUtils/index.js +136 -45
- package/dist/utils/installDeno.js +4 -4
- package/dist/utils/installEw2.js +9 -9
- package/dist/utils/openInBrowser.js +1 -1
- package/dist/utils/prompt.js +97 -0
- package/package.json +23 -12
- package/zh_CN.md +29 -154
|
@@ -0,0 +1,149 @@
|
|
|
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 { spawn } from 'child_process';
|
|
11
|
+
import { cancel, spinner } from '@clack/prompts';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
/**
|
|
14
|
+
* Execute a shell command with rich options (spinner, capture, env, cwd).
|
|
15
|
+
*/
|
|
16
|
+
export const execCommand = (command_1, ...args_1) => __awaiter(void 0, [command_1, ...args_1], void 0, function* (command, options = {}) {
|
|
17
|
+
const { startText, doneText, silent = false, captureOutput = false, useSpinner = true, realtimeOutput = false, interactive = false, env, cwd, transformOutput, fallbackOutput, errorMessage } = options;
|
|
18
|
+
// Determine stdio mode based on options
|
|
19
|
+
// If realtimeOutput is true, we need to pipe to capture and display output in real-time
|
|
20
|
+
// If spinner is used without realtimeOutput, pipe to avoid TTY contention
|
|
21
|
+
// If silent is true, pipe to suppress output
|
|
22
|
+
// If captureOutput is true, pipe to capture output
|
|
23
|
+
// If interactive is true, always inherit stdio so prompts can be shown and accept input
|
|
24
|
+
const shouldPipe = !interactive && (realtimeOutput || useSpinner || silent || captureOutput);
|
|
25
|
+
const stdio = interactive
|
|
26
|
+
? 'inherit'
|
|
27
|
+
: shouldPipe
|
|
28
|
+
? 'pipe'
|
|
29
|
+
: 'inherit';
|
|
30
|
+
// start
|
|
31
|
+
const startMsg = startText || `Running: ${command.join(' ')}`;
|
|
32
|
+
const s = spinner();
|
|
33
|
+
// When realtimeOutput is enabled, don't use spinner as it conflicts with real-time output
|
|
34
|
+
if (useSpinner && !realtimeOutput && !interactive) {
|
|
35
|
+
s.start(startMsg);
|
|
36
|
+
}
|
|
37
|
+
else if (!silent) {
|
|
38
|
+
if (interactive) {
|
|
39
|
+
console.log(chalk.gray('│'));
|
|
40
|
+
console.log(chalk.gray('├ ') + startMsg);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(startMsg);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
let stdout = '';
|
|
48
|
+
let stderr = '';
|
|
49
|
+
// Use spawn for string[] commands to avoid shell quoting issues
|
|
50
|
+
const program = command[0];
|
|
51
|
+
const args = command.slice(1);
|
|
52
|
+
yield new Promise((resolve, reject) => {
|
|
53
|
+
var _a, _b;
|
|
54
|
+
const child = spawn(program, args, {
|
|
55
|
+
stdio,
|
|
56
|
+
cwd,
|
|
57
|
+
env: Object.assign(Object.assign({}, process.env), env),
|
|
58
|
+
shell: false
|
|
59
|
+
});
|
|
60
|
+
if (stdio === 'pipe') {
|
|
61
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (chunk) => {
|
|
62
|
+
const chunkStr = String(chunk);
|
|
63
|
+
stdout += chunkStr;
|
|
64
|
+
// Real-time output: display immediately if enabled and not silent
|
|
65
|
+
if (realtimeOutput && !silent) {
|
|
66
|
+
process.stdout.write(chunkStr);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (chunk) => {
|
|
70
|
+
const chunkStr = String(chunk);
|
|
71
|
+
stderr += chunkStr;
|
|
72
|
+
// Real-time output: display immediately if enabled and not silent
|
|
73
|
+
if (realtimeOutput && !silent) {
|
|
74
|
+
process.stderr.write(chunkStr);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
child.on('error', (error) => {
|
|
79
|
+
reject(error);
|
|
80
|
+
});
|
|
81
|
+
child.on('close', (code) => {
|
|
82
|
+
if (code && code !== 0) {
|
|
83
|
+
reject({ stdout, stderr, message: `Exit code ${code}` });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
resolve();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
// Preserve original output for optional mirroring
|
|
91
|
+
const bufferedStdout = stdout;
|
|
92
|
+
const bufferedStderr = stderr;
|
|
93
|
+
if (transformOutput) {
|
|
94
|
+
stdout = transformOutput(stdout);
|
|
95
|
+
}
|
|
96
|
+
const endMsg = typeof doneText === 'function' ? doneText(stdout) : doneText || 'Done';
|
|
97
|
+
if (useSpinner && !realtimeOutput && !interactive) {
|
|
98
|
+
s.stop(endMsg);
|
|
99
|
+
}
|
|
100
|
+
else if (!silent) {
|
|
101
|
+
if (interactive) {
|
|
102
|
+
console.log(chalk.gray('├ ') + endMsg);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.log(endMsg);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// If spinner was used and user expects output (silent=false, captureOutput=false),
|
|
109
|
+
// and realtimeOutput is not enabled, print the buffered child output now to avoid interfering with spinner rendering.
|
|
110
|
+
if (useSpinner &&
|
|
111
|
+
!silent &&
|
|
112
|
+
!captureOutput &&
|
|
113
|
+
!realtimeOutput &&
|
|
114
|
+
!interactive) {
|
|
115
|
+
if (bufferedStdout)
|
|
116
|
+
process.stdout.write(bufferedStdout);
|
|
117
|
+
if (bufferedStderr)
|
|
118
|
+
process.stderr.write(bufferedStderr);
|
|
119
|
+
}
|
|
120
|
+
return { success: true, stdout, stderr };
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
const e = err;
|
|
124
|
+
const stdout = (e === null || e === void 0 ? void 0 : e.stdout) ? String(e.stdout) : '';
|
|
125
|
+
const stderr = (e === null || e === void 0 ? void 0 : e.stderr) ? String(e.stderr) : (e === null || e === void 0 ? void 0 : e.message) || '';
|
|
126
|
+
const msg = (fallbackOutput && fallbackOutput(err)) ||
|
|
127
|
+
(stderr ? `Command failed: ${stdout}` : 'Command failed');
|
|
128
|
+
if (useSpinner && !realtimeOutput && !interactive)
|
|
129
|
+
s.stop(msg);
|
|
130
|
+
else if (!silent)
|
|
131
|
+
console.error(msg);
|
|
132
|
+
// Mirror buffered outputs on failure when spinner is used and not silent and realtimeOutput is not enabled
|
|
133
|
+
if (useSpinner &&
|
|
134
|
+
!silent &&
|
|
135
|
+
!captureOutput &&
|
|
136
|
+
!realtimeOutput &&
|
|
137
|
+
!interactive) {
|
|
138
|
+
if (stdout)
|
|
139
|
+
process.stdout.write(stdout);
|
|
140
|
+
if (stderr)
|
|
141
|
+
process.stderr.write(stderr);
|
|
142
|
+
}
|
|
143
|
+
if (errorMessage) {
|
|
144
|
+
cancel(errorMessage);
|
|
145
|
+
}
|
|
146
|
+
return { success: false, stdout, stderr };
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
export default execCommand;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Toml Example:
|
|
3
|
+
name = "DeepSeek model invocation"
|
|
4
|
+
description = 'How to invoke DeepSeek series models through API calls on the BaiLian platform.'
|
|
5
|
+
entry = "src/index.js"
|
|
6
|
+
assets = ["src/assets"]
|
|
7
|
+
codeVersions = [ ]
|
|
8
|
+
|
|
9
|
+
[assets]
|
|
10
|
+
directory = './assets/'
|
|
11
|
+
|
|
12
|
+
[dev]
|
|
13
|
+
port = 18080
|
|
14
|
+
localUpstream = ''
|
|
15
|
+
*/
|
|
16
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
17
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
19
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
20
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
21
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
22
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
import fs from 'fs';
|
|
26
|
+
import path from 'path';
|
|
27
|
+
import { exit } from 'process';
|
|
28
|
+
import AdmZip from 'adm-zip';
|
|
29
|
+
import chalk from 'chalk';
|
|
30
|
+
import prodBuild from '../commands/commit/prodBuild.js';
|
|
31
|
+
import t from '../i18n/index.js';
|
|
32
|
+
import logger from '../libs/logger.js';
|
|
33
|
+
import { checkEdgeRoutineType, EDGE_ROUTINE_TYPE } from './checkAssetsExist.js';
|
|
34
|
+
import { getProjectConfig, readEdgeRoutineFile } from './fileUtils/index.js';
|
|
35
|
+
const compress = (scriptEntry_1, assetsDir_1, ...args_1) => __awaiter(void 0, [scriptEntry_1, assetsDir_1, ...args_1], void 0, function* (scriptEntry, assetsDir, minify = false, projectPath) {
|
|
36
|
+
var _a;
|
|
37
|
+
let code;
|
|
38
|
+
const zip = new AdmZip();
|
|
39
|
+
const fileList = [];
|
|
40
|
+
const sourceList = [];
|
|
41
|
+
const dynamicSources = [];
|
|
42
|
+
const projectConfig = getProjectConfig(projectPath);
|
|
43
|
+
let assetsDirectory = assetsDir || ((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.assets) === null || _a === void 0 ? void 0 : _a.directory);
|
|
44
|
+
const routineType = checkEdgeRoutineType(scriptEntry, assetsDir, projectPath);
|
|
45
|
+
if (!projectConfig && !scriptEntry && !assetsDir) {
|
|
46
|
+
logger.error([
|
|
47
|
+
'esa.jsonc (recommended) or esa.toml is not found and script entry or assets directory is not provided by command line',
|
|
48
|
+
'',
|
|
49
|
+
'See configuration guide:',
|
|
50
|
+
`- English: ${chalk.underline('https://github.com/aliyun/alibabacloud-esa-cli/blob/main/docs/Config_en.md')}`,
|
|
51
|
+
`- 中文: ${chalk.underline('https://github.com/aliyun/alibabacloud-esa-cli/blob/main/docs/Config_zh_CN.md')}`
|
|
52
|
+
].join('\n'));
|
|
53
|
+
exit(1);
|
|
54
|
+
}
|
|
55
|
+
// Parameter priority: use parameters if available, otherwise use values from config file
|
|
56
|
+
const entry = scriptEntry || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry);
|
|
57
|
+
if (routineType === EDGE_ROUTINE_TYPE.NOT_EXIST) {
|
|
58
|
+
const errorMessage = [
|
|
59
|
+
chalk.red.bold('❌ File upload failed'),
|
|
60
|
+
'',
|
|
61
|
+
chalk.cyan('📋 Current configuration information:'),
|
|
62
|
+
`${chalk.white(` 📄 Entry file ${chalk.yellow('(dynamic)')} :`)} ${chalk.yellow(scriptEntry ||
|
|
63
|
+
(projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry) ||
|
|
64
|
+
chalk.gray(t('compress_not_configured').d('Not configured')))}`,
|
|
65
|
+
`${chalk.white(` 🗂️ Assets directory ${chalk.yellow('(static)')} :`)} ${chalk.yellow(assetsDirectory || chalk.gray(t('compress_not_configured').d('Not configured')))}`,
|
|
66
|
+
'',
|
|
67
|
+
chalk.cyan('🔍 Possible issue causes:'),
|
|
68
|
+
chalk.white(' 1. Entry file path is incorrect or file does not exist'),
|
|
69
|
+
chalk.white(' 2. Assets directory path is incorrect or directory does not exist'),
|
|
70
|
+
chalk.white(` 3. Project configuration file ${chalk.yellow('esa.jsonc')} (recommended) or ${chalk.yellow('esa.toml')} format error`),
|
|
71
|
+
chalk.white(` 4. Relative path format error, please use ${chalk.yellow('./xxx')} format`),
|
|
72
|
+
'',
|
|
73
|
+
chalk.yellow.bold(`📍 Please check if the following ${chalk.red('absolute paths')} are correct:`),
|
|
74
|
+
...(scriptEntry || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry)
|
|
75
|
+
? [
|
|
76
|
+
`${chalk.white(' 📄 Entry file:')} ${chalk.cyan.bold(path.resolve(projectPath !== null && projectPath !== void 0 ? projectPath : '', scriptEntry || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry) || ''))} ${chalk.gray(t('compress_check_file_exists').d('(Check if file exists)'))}`
|
|
77
|
+
]
|
|
78
|
+
: []),
|
|
79
|
+
...(assetsDirectory
|
|
80
|
+
? [
|
|
81
|
+
`${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)'))}`
|
|
82
|
+
]
|
|
83
|
+
: []),
|
|
84
|
+
...(!scriptEntry && !(projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry) && !assetsDirectory
|
|
85
|
+
? [
|
|
86
|
+
chalk.yellow.bold(' ⚠️ You need to configure at least one of entry file or assets directory')
|
|
87
|
+
]
|
|
88
|
+
: []),
|
|
89
|
+
''
|
|
90
|
+
].join('\n');
|
|
91
|
+
logger.error(errorMessage);
|
|
92
|
+
exit(1);
|
|
93
|
+
}
|
|
94
|
+
if (routineType === EDGE_ROUTINE_TYPE.JS_ONLY ||
|
|
95
|
+
routineType === EDGE_ROUTINE_TYPE.JS_AND_ASSETS) {
|
|
96
|
+
const buildEntry = path.resolve(projectPath !== null && projectPath !== void 0 ? projectPath : '', entry !== null && entry !== void 0 ? entry : '');
|
|
97
|
+
yield prodBuild(minify, buildEntry, projectPath);
|
|
98
|
+
code = readEdgeRoutineFile(projectPath);
|
|
99
|
+
zip.addFile(`routine/index.js`, Buffer.from(code || ''));
|
|
100
|
+
fileList.push('routine/index.js');
|
|
101
|
+
const relativeEntry = path
|
|
102
|
+
.relative(projectPath !== null && projectPath !== void 0 ? projectPath : '', buildEntry)
|
|
103
|
+
.split(path.sep)
|
|
104
|
+
.join('/');
|
|
105
|
+
sourceList.push(relativeEntry);
|
|
106
|
+
dynamicSources.push(relativeEntry);
|
|
107
|
+
}
|
|
108
|
+
assetsDirectory = path.resolve(projectPath !== null && projectPath !== void 0 ? projectPath : '', assetsDirectory !== null && assetsDirectory !== void 0 ? assetsDirectory : '');
|
|
109
|
+
// Add all files in the assets directory to the /assets directory
|
|
110
|
+
if ((routineType === EDGE_ROUTINE_TYPE.JS_AND_ASSETS ||
|
|
111
|
+
routineType === EDGE_ROUTINE_TYPE.ASSETS_ONLY) &&
|
|
112
|
+
assetsDirectory &&
|
|
113
|
+
fs.existsSync(assetsDirectory)) {
|
|
114
|
+
const addDirectoryToZip = (dirPath, zipPath) => {
|
|
115
|
+
const files = fs.readdirSync(dirPath);
|
|
116
|
+
for (const file of files) {
|
|
117
|
+
const fullPath = path.join(dirPath, file);
|
|
118
|
+
const stat = fs.statSync(fullPath);
|
|
119
|
+
if (stat.isDirectory()) {
|
|
120
|
+
addDirectoryToZip(fullPath, path.join(zipPath, file));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const fileContent = fs.readFileSync(fullPath);
|
|
124
|
+
const relativePath = path
|
|
125
|
+
.relative(assetsDirectory, fullPath)
|
|
126
|
+
.split(path.sep)
|
|
127
|
+
.join('/');
|
|
128
|
+
zip.addFile(`assets/${relativePath}`, fileContent);
|
|
129
|
+
fileList.push(`assets/${relativePath}`);
|
|
130
|
+
const relativeSrcPath = path
|
|
131
|
+
.relative(projectPath !== null && projectPath !== void 0 ? projectPath : '', fullPath)
|
|
132
|
+
.split(path.sep)
|
|
133
|
+
.join('/');
|
|
134
|
+
sourceList.push(relativeSrcPath);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
addDirectoryToZip(assetsDirectory, 'assets');
|
|
139
|
+
}
|
|
140
|
+
return { zip, fileList, sourceList, dynamicSources };
|
|
141
|
+
});
|
|
142
|
+
export default compress;
|
package/dist/utils/download.js
CHANGED
|
@@ -7,16 +7,16 @@ 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
|
|
10
|
+
import { exec } from 'child_process';
|
|
11
11
|
import * as fs from 'fs/promises';
|
|
12
|
-
import * as path from 'path';
|
|
13
12
|
import os from 'os';
|
|
14
|
-
import
|
|
15
|
-
import { exec } from 'child_process';
|
|
13
|
+
import * as path from 'path';
|
|
16
14
|
import { promisify } from 'util';
|
|
15
|
+
import AdmZip from 'adm-zip';
|
|
16
|
+
import chalk from 'chalk';
|
|
17
|
+
import fetch from 'node-fetch';
|
|
17
18
|
import t from '../i18n/index.js';
|
|
18
19
|
import logger from '../libs/logger.js';
|
|
19
|
-
import chalk from 'chalk';
|
|
20
20
|
const execAsync = promisify(exec);
|
|
21
21
|
function getBinDir() {
|
|
22
22
|
const home = os.homedir();
|
|
@@ -92,8 +92,8 @@ function isBinDirInPath(binDir) {
|
|
|
92
92
|
*/
|
|
93
93
|
function addBinDirToPath(binDir) {
|
|
94
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
//
|
|
96
|
-
// setx
|
|
95
|
+
// Use setx to add to PATH
|
|
96
|
+
// setx has a 2047 character limit for PATH
|
|
97
97
|
const command = `setx Path "%Path%;${binDir}"`;
|
|
98
98
|
try {
|
|
99
99
|
yield execAsync(command);
|
|
@@ -169,7 +169,7 @@ export function downloadRuntimeAndUnzipForWindows() {
|
|
|
169
169
|
}
|
|
170
170
|
logger.success(t('deno_install_success').d('Runtime install success!'));
|
|
171
171
|
logger.block();
|
|
172
|
-
const dev = chalk.green('esa dev');
|
|
172
|
+
const dev = chalk.green('esa-cli dev');
|
|
173
173
|
logger.log(t('deno_install_success_tips', { dev }).d(`Please run ${dev} again`));
|
|
174
174
|
}
|
|
175
175
|
catch (error) {
|
package/dist/utils/fileMd5.js
CHANGED
|
@@ -7,19 +7,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import fs from 'fs';
|
|
10
|
+
import fs, { promises as fsPromises } from 'fs';
|
|
11
11
|
import os from 'os';
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import toml from '@iarna/toml';
|
|
14
|
-
import { promises as fsPromises } from 'fs';
|
|
15
|
-
import { getDirName, getRoot } from './base.js';
|
|
16
|
-
import logger from '../../libs/logger.js';
|
|
17
14
|
import t from '../../i18n/index.js';
|
|
18
|
-
|
|
15
|
+
import logger from '../../libs/logger.js';
|
|
16
|
+
import { getDirName, getRoot } from './base.js';
|
|
19
17
|
const __dirname = getDirName(import.meta.url);
|
|
20
18
|
const root = getRoot();
|
|
21
|
-
|
|
19
|
+
// Function to get the actual project config file path (supports both .jsonc and .toml)
|
|
20
|
+
export const getProjectConfigPath = (filePath = root) => {
|
|
21
|
+
const configFormats = ['esa.jsonc', 'esa.toml'];
|
|
22
|
+
for (const format of configFormats) {
|
|
23
|
+
const configPath = path.join(filePath, format);
|
|
24
|
+
if (fs.existsSync(configPath)) {
|
|
25
|
+
return configPath;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Default to .jsonc if no config file exists
|
|
29
|
+
return path.join(filePath, 'esa.jsonc');
|
|
30
|
+
};
|
|
31
|
+
export const projectConfigPath = getProjectConfigPath();
|
|
22
32
|
export const cliConfigPath = path.join(os.homedir(), '.esa/config/default.toml');
|
|
33
|
+
// Function to get the actual config file path (supports both .toml and .jsonc)
|
|
34
|
+
export const getCliConfigPath = () => {
|
|
35
|
+
const configDir = path.join(os.homedir(), '.esa/config');
|
|
36
|
+
const jsoncPath = path.join(configDir, 'default.jsonc');
|
|
37
|
+
const tomlPath = path.join(configDir, 'default.toml');
|
|
38
|
+
// Check if JSONC file exists first, then fallback to TOML
|
|
39
|
+
if (fs.existsSync(jsoncPath)) {
|
|
40
|
+
return jsoncPath;
|
|
41
|
+
}
|
|
42
|
+
return tomlPath;
|
|
43
|
+
};
|
|
23
44
|
export const hiddenConfigDir = path.join(os.homedir(), '.esa/config');
|
|
24
45
|
export const generateHiddenConfigDir = () => {
|
|
25
46
|
if (!fs.existsSync(hiddenConfigDir)) {
|
|
@@ -29,7 +50,7 @@ export const generateHiddenConfigDir = () => {
|
|
|
29
50
|
export const generateToml = (path) => {
|
|
30
51
|
if (!fs.existsSync(path)) {
|
|
31
52
|
fs.writeFileSync(path, '', 'utf-8');
|
|
32
|
-
//
|
|
53
|
+
// Add default endpoint
|
|
33
54
|
const defaultConfig = {
|
|
34
55
|
endpoint: 'esa.cn-hangzhou.aliyuncs.com'
|
|
35
56
|
};
|
|
@@ -38,20 +59,34 @@ export const generateToml = (path) => {
|
|
|
38
59
|
};
|
|
39
60
|
export const generateDefaultConfig = () => {
|
|
40
61
|
generateHiddenConfigDir();
|
|
41
|
-
|
|
62
|
+
const configPath = getCliConfigPath();
|
|
63
|
+
generateToml(configPath);
|
|
42
64
|
};
|
|
43
65
|
export function updateProjectConfigFile(configUpdate_1) {
|
|
44
66
|
return __awaiter(this, arguments, void 0, function* (configUpdate, filePath = root) {
|
|
45
|
-
const configPath =
|
|
67
|
+
const configPath = getProjectConfigPath(filePath);
|
|
46
68
|
try {
|
|
47
69
|
let configFileContent = yield fsPromises.readFile(configPath, 'utf8');
|
|
48
|
-
let config
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
let config;
|
|
71
|
+
let updatedConfigString;
|
|
72
|
+
// Detect file format based on file extension
|
|
73
|
+
if (configPath.endsWith('.jsonc') || configPath.endsWith('.json')) {
|
|
74
|
+
// Handle JSONC format
|
|
75
|
+
const jsonContent = configFileContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
|
76
|
+
config = JSON.parse(jsonContent);
|
|
77
|
+
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
78
|
+
updatedConfigString = JSON.stringify(config, null, 2) + '\n';
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Handle TOML format (default)
|
|
82
|
+
config = toml.parse(configFileContent);
|
|
83
|
+
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
84
|
+
updatedConfigString = toml.stringify(config);
|
|
85
|
+
}
|
|
51
86
|
yield fsPromises.writeFile(configPath, updatedConfigString);
|
|
52
87
|
}
|
|
53
88
|
catch (error) {
|
|
54
|
-
logger.error(`Error updating
|
|
89
|
+
logger.error(`Error updating config file: ${error}`);
|
|
55
90
|
logger.pathEacces(__dirname);
|
|
56
91
|
}
|
|
57
92
|
});
|
|
@@ -59,16 +94,30 @@ export function updateProjectConfigFile(configUpdate_1) {
|
|
|
59
94
|
export function updateCliConfigFile(configUpdate) {
|
|
60
95
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
96
|
try {
|
|
62
|
-
|
|
63
|
-
let
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
97
|
+
const configPath = getCliConfigPath();
|
|
98
|
+
let configFileContent = yield fsPromises.readFile(configPath, 'utf8');
|
|
99
|
+
let config;
|
|
100
|
+
let updatedConfigString;
|
|
101
|
+
// Detect file format based on file extension
|
|
102
|
+
if (configPath.endsWith('.jsonc') || configPath.endsWith('.json')) {
|
|
103
|
+
// Handle JSONC format
|
|
104
|
+
const jsonContent = configFileContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
|
105
|
+
config = JSON.parse(jsonContent);
|
|
106
|
+
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
107
|
+
updatedConfigString = JSON.stringify(config, null, 2) + '\n';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Handle TOML format (default)
|
|
111
|
+
config = toml.parse(configFileContent);
|
|
112
|
+
config = Object.assign(Object.assign({}, config), configUpdate);
|
|
113
|
+
updatedConfigString = toml.stringify(config);
|
|
114
|
+
}
|
|
115
|
+
yield fsPromises.writeFile(configPath, updatedConfigString);
|
|
67
116
|
}
|
|
68
117
|
catch (error) {
|
|
69
|
-
logger.error(`Error updating
|
|
118
|
+
logger.error(`Error updating config file: ${error}`);
|
|
70
119
|
logger.pathEacces(__dirname);
|
|
71
|
-
throw new Error('
|
|
120
|
+
throw new Error('Config update error');
|
|
72
121
|
}
|
|
73
122
|
});
|
|
74
123
|
}
|
|
@@ -76,35 +125,46 @@ export function readConfigFile(configPath) {
|
|
|
76
125
|
if (fs.existsSync(configPath)) {
|
|
77
126
|
const configFileContent = fs.readFileSync(configPath, 'utf-8');
|
|
78
127
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
128
|
+
if (configPath.endsWith('.jsonc') || configPath.endsWith('.json')) {
|
|
129
|
+
// Remove comments for JSON parsing
|
|
130
|
+
const jsonContent = configFileContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
|
131
|
+
const config = JSON.parse(jsonContent);
|
|
132
|
+
return config;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// TOML format
|
|
136
|
+
const config = toml.parse(configFileContent);
|
|
137
|
+
return config;
|
|
138
|
+
}
|
|
81
139
|
}
|
|
82
140
|
catch (error) {
|
|
83
|
-
logger.error(`Error parsing
|
|
141
|
+
logger.error(`Error parsing config file: ${error}`);
|
|
84
142
|
return null;
|
|
85
143
|
}
|
|
86
144
|
}
|
|
87
145
|
return null;
|
|
88
146
|
}
|
|
89
147
|
export function getCliConfig() {
|
|
90
|
-
const
|
|
148
|
+
const configPath = getCliConfigPath();
|
|
149
|
+
const res = readConfigFile(configPath);
|
|
91
150
|
if (!res) {
|
|
92
151
|
return null;
|
|
93
152
|
}
|
|
94
153
|
return res;
|
|
95
154
|
}
|
|
96
155
|
export function getProjectConfig(filePath = root) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
156
|
+
// Try to find config file in order of preference: .jsonc, .toml
|
|
157
|
+
const configFormats = ['esa.jsonc', 'esa.toml'];
|
|
158
|
+
for (const format of configFormats) {
|
|
159
|
+
const configPath = path.join(filePath, format);
|
|
160
|
+
const config = readConfigFile(configPath);
|
|
161
|
+
if (config) {
|
|
162
|
+
return config;
|
|
163
|
+
}
|
|
100
164
|
}
|
|
101
|
-
return
|
|
165
|
+
return null;
|
|
102
166
|
}
|
|
103
167
|
export function readEdgeRoutineFile(projectPath = root) {
|
|
104
|
-
const projectConfig = getProjectConfig(projectPath);
|
|
105
|
-
if (!projectConfig) {
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
168
|
const pubFilePath = `.dev/pub.js`;
|
|
109
169
|
const edgeRoutinePath = path.join(projectPath, pubFilePath);
|
|
110
170
|
if (fs.existsSync(edgeRoutinePath)) {
|
|
@@ -122,26 +182,57 @@ export function getConfigurations() {
|
|
|
122
182
|
return [null, null];
|
|
123
183
|
}
|
|
124
184
|
}
|
|
125
|
-
export function generateConfigFile(
|
|
126
|
-
return __awaiter(this,
|
|
127
|
-
var _a;
|
|
128
|
-
const
|
|
129
|
-
const currentDirName = path.basename(
|
|
130
|
-
const entry = (
|
|
185
|
+
export function generateConfigFile(projectName_1, initConfigs_1, targetDir_1) {
|
|
186
|
+
return __awaiter(this, arguments, void 0, function* (projectName, initConfigs, targetDir, configFormat = 'jsonc', notFoundStrategy) {
|
|
187
|
+
var _a, _b;
|
|
188
|
+
const outputDir = targetDir !== null && targetDir !== void 0 ? targetDir : process.cwd();
|
|
189
|
+
const currentDirName = path.basename(outputDir);
|
|
190
|
+
const entry = (_a = initConfigs === null || initConfigs === void 0 ? void 0 : initConfigs.dev) === null || _a === void 0 ? void 0 : _a.entry;
|
|
131
191
|
const port = (initConfigs === null || initConfigs === void 0 ? void 0 : initConfigs.port) || 18080;
|
|
132
192
|
const name = projectName || currentDirName;
|
|
193
|
+
const assetsDirectory = (_b = initConfigs === null || initConfigs === void 0 ? void 0 : initConfigs.assets) === null || _b === void 0 ? void 0 : _b.directory;
|
|
194
|
+
let newFilePath;
|
|
195
|
+
let genConfig;
|
|
196
|
+
if (configFormat === 'jsonc') {
|
|
197
|
+
newFilePath = path.join(outputDir, 'esa.jsonc');
|
|
198
|
+
const configObj = { name };
|
|
199
|
+
if (entry)
|
|
200
|
+
configObj.entry = entry;
|
|
201
|
+
if (assetsDirectory) {
|
|
202
|
+
configObj.assets = { directory: assetsDirectory };
|
|
203
|
+
if (notFoundStrategy) {
|
|
204
|
+
configObj.assets.notFoundStrategy =
|
|
205
|
+
notFoundStrategy;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
configObj.dev = { port };
|
|
209
|
+
genConfig = JSON.stringify(configObj, null, 2) + '\n';
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Default to TOML format
|
|
213
|
+
newFilePath = path.join(outputDir, 'esa.toml');
|
|
214
|
+
const configObj = {
|
|
215
|
+
name,
|
|
216
|
+
dev: { port }
|
|
217
|
+
};
|
|
218
|
+
if (entry)
|
|
219
|
+
configObj.entry = entry;
|
|
220
|
+
if (assetsDirectory) {
|
|
221
|
+
configObj.assets = { directory: assetsDirectory };
|
|
222
|
+
if (notFoundStrategy) {
|
|
223
|
+
configObj.assets.notFoundStrategy =
|
|
224
|
+
notFoundStrategy;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
genConfig = toml.stringify(configObj);
|
|
228
|
+
}
|
|
133
229
|
if (fs.existsSync(newFilePath)) {
|
|
134
|
-
logger.error(
|
|
230
|
+
logger.error(`${path.basename(newFilePath)}` +
|
|
231
|
+
t('generate_config_error').d('already exists'));
|
|
135
232
|
return;
|
|
136
233
|
}
|
|
137
234
|
else {
|
|
138
|
-
const genConfig = `name = "${name}"
|
|
139
|
-
entry = "${entry}"
|
|
140
|
-
[dev]
|
|
141
|
-
port = ${port}
|
|
142
|
-
`;
|
|
143
235
|
yield fsPromises.writeFile(newFilePath, genConfig, 'utf-8');
|
|
144
|
-
logger.success(t('generate_config_success').d('Generated esa.toml'));
|
|
145
236
|
}
|
|
146
237
|
});
|
|
147
238
|
}
|
|
@@ -10,10 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { exec, execSync } from 'child_process';
|
|
11
11
|
import os from 'os';
|
|
12
12
|
import path from 'path';
|
|
13
|
+
import t from '../i18n/index.js';
|
|
13
14
|
import logger from '../libs/logger.js';
|
|
14
|
-
import { getDirName } from './fileUtils/base.js';
|
|
15
15
|
import { downloadRuntimeAndUnzipForWindows } from './download.js';
|
|
16
|
-
import
|
|
16
|
+
import { getDirName } from './fileUtils/base.js';
|
|
17
17
|
export function preCheckDeno() {
|
|
18
18
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
const command = yield checkDenoInstalled();
|
|
@@ -45,7 +45,7 @@ export function checkDenoInstalled() {
|
|
|
45
45
|
.then((res) => {
|
|
46
46
|
resolve(res);
|
|
47
47
|
})
|
|
48
|
-
.catch((
|
|
48
|
+
.catch(() => {
|
|
49
49
|
resolve(false);
|
|
50
50
|
});
|
|
51
51
|
});
|
|
@@ -66,7 +66,7 @@ export function installDeno() {
|
|
|
66
66
|
default:
|
|
67
67
|
installCommand = `sh ${p}/install.sh`;
|
|
68
68
|
}
|
|
69
|
-
logger.warn(t('install_runtime_tip').d(`🔔 Runtime must be installed to use esa dev. Installing...`));
|
|
69
|
+
logger.warn(t('install_runtime_tip').d(`🔔 Runtime must be installed to use esa-cli dev. Installing...`));
|
|
70
70
|
try {
|
|
71
71
|
execSync(installCommand, { stdio: 'inherit' });
|
|
72
72
|
logger.success(t('install_runtime_success').d(`Runtime installed.`));
|