esa-cli 0.0.2-beta.2 → 0.0.2-beta.20

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.
Files changed (82) hide show
  1. package/dist/commands/commit/index.js +48 -115
  2. package/dist/commands/commit/prodBuild.js +2 -3
  3. package/dist/commands/common/constant.js +0 -19
  4. package/dist/commands/common/utils.js +416 -0
  5. package/dist/commands/config.js +1 -1
  6. package/dist/commands/deploy/helper.js +51 -72
  7. package/dist/commands/deploy/index.js +50 -188
  8. package/dist/commands/deployments/delete.js +32 -22
  9. package/dist/commands/deployments/index.js +2 -2
  10. package/dist/commands/deployments/list.js +22 -38
  11. package/dist/commands/dev/build.js +3 -3
  12. package/dist/commands/dev/doProcess.js +5 -5
  13. package/dist/commands/dev/ew2/cacheService.js +33 -0
  14. package/dist/commands/dev/ew2/devEntry.js +2 -1
  15. package/dist/commands/dev/ew2/devPack.js +39 -43
  16. package/dist/commands/dev/ew2/kvService.js +27 -0
  17. package/dist/commands/dev/ew2/mock/cache.js +99 -15
  18. package/dist/commands/dev/ew2/mock/kv.js +142 -21
  19. package/dist/commands/dev/ew2/server.js +165 -29
  20. package/dist/commands/dev/index.js +17 -17
  21. package/dist/commands/dev/mockWorker/devPack.js +35 -24
  22. package/dist/commands/dev/mockWorker/server.js +7 -6
  23. package/dist/commands/domain/add.js +2 -2
  24. package/dist/commands/domain/delete.js +7 -7
  25. package/dist/commands/domain/index.js +2 -2
  26. package/dist/commands/domain/list.js +10 -10
  27. package/dist/commands/init/helper.js +759 -0
  28. package/dist/commands/init/index.js +88 -220
  29. package/dist/commands/init/snippets/nextjs/next.config.mjs +6 -0
  30. package/dist/commands/init/snippets/nextjs/next.config.ts +7 -0
  31. package/dist/commands/init/snippets/react-router/react-router.config.ts +7 -0
  32. package/dist/commands/init/template.jsonc +84 -0
  33. package/dist/commands/init/types.js +1 -0
  34. package/dist/commands/lang.js +2 -2
  35. package/dist/commands/login/index.js +74 -34
  36. package/dist/commands/logout.js +5 -5
  37. package/dist/commands/route/add.js +105 -49
  38. package/dist/commands/route/delete.js +33 -27
  39. package/dist/commands/route/helper.js +123 -0
  40. package/dist/commands/route/index.js +2 -2
  41. package/dist/commands/route/list.js +56 -17
  42. package/dist/commands/routine/delete.js +2 -2
  43. package/dist/commands/routine/index.js +2 -2
  44. package/dist/commands/routine/list.js +43 -37
  45. package/dist/commands/site/index.js +1 -1
  46. package/dist/commands/site/list.js +6 -7
  47. package/dist/commands/utils.js +59 -23
  48. package/dist/components/descriptionInput.js +1 -1
  49. package/dist/components/filterSelector.js +1 -1
  50. package/dist/components/mutiLevelSelect.js +43 -55
  51. package/dist/components/mutiSelectTable.js +1 -1
  52. package/dist/components/routeBuilder.js +68 -0
  53. package/dist/components/selectInput.js +2 -3
  54. package/dist/components/selectItem.js +1 -1
  55. package/dist/docs/Commands_en.md +142 -131
  56. package/dist/docs/Commands_zh_CN.md +139 -127
  57. package/dist/i18n/index.js +2 -2
  58. package/dist/i18n/locales.json +435 -23
  59. package/dist/index.js +27 -20
  60. package/dist/libs/api.js +32 -9
  61. package/dist/libs/apiService.js +267 -88
  62. package/dist/libs/git/index.js +86 -9
  63. package/dist/libs/interface.js +0 -1
  64. package/dist/libs/logger.js +162 -10
  65. package/dist/libs/service.js +2 -2
  66. package/dist/libs/templates/index.js +3 -2
  67. package/dist/utils/checkAssetsExist.js +80 -0
  68. package/dist/utils/checkDevPort.js +3 -17
  69. package/dist/utils/checkEntryFileExist.js +10 -0
  70. package/dist/utils/checkIsRoutineCreated.js +28 -27
  71. package/dist/utils/checkVersion.js +119 -1
  72. package/dist/utils/command.js +149 -0
  73. package/dist/utils/compress.js +136 -0
  74. package/dist/utils/download.js +182 -0
  75. package/dist/utils/fileMd5.js +1 -1
  76. package/dist/utils/fileUtils/base.js +1 -1
  77. package/dist/utils/fileUtils/index.js +136 -44
  78. package/dist/utils/installDeno.js +8 -8
  79. package/dist/utils/installEw2.js +7 -7
  80. package/dist/utils/openInBrowser.js +1 -1
  81. package/dist/utils/prompt.js +97 -0
  82. package/package.json +19 -12
@@ -7,15 +7,13 @@ 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 { getProjectConfig, readEdgeRoutineFile } from '../../utils/fileUtils/index.js';
11
- import { checkDirectory, checkIsLoginSuccess } from '../utils.js';
12
- import { displaySelectSpec } from '../deploy/index.js';
13
- import { descriptionInput } from '../../components/descriptionInput.js';
14
- import { ApiService } from '../../libs/apiService.js';
15
- import prodBuild from './prodBuild.js';
16
- import logger from '../../libs/logger.js';
17
- import t from '../../i18n/index.js';
18
10
  import { exit } from 'process';
11
+ import { intro, outro } from '@clack/prompts';
12
+ import chalk from 'chalk';
13
+ import t from '../../i18n/index.js';
14
+ import logger from '../../libs/logger.js';
15
+ import promptParameter from '../../utils/prompt.js';
16
+ import { validateAndInitializeProject, generateCodeVersion } from '../common/utils.js';
19
17
  const commit = {
20
18
  command: 'commit [entry]',
21
19
  describe: `📥 ${t('commit_describe').d('Commit your code, save as a new version')}`,
@@ -27,126 +25,61 @@ const commit = {
27
25
  type: 'boolean',
28
26
  default: false
29
27
  })
30
- .positional('entry', {
31
- describe: t('dev_entry_describe').d('Entry file of the Routine'),
32
- type: 'string',
33
- demandOption: false
28
+ .option('assets', {
29
+ alias: 'a',
30
+ describe: t('commit_option_assets').d('Assets directory'),
31
+ type: 'string'
32
+ })
33
+ .option('description', {
34
+ alias: 'd',
35
+ describe: t('commit_option_description').d('Description for the routine/version (skip interactive input)'),
36
+ type: 'string'
37
+ })
38
+ .option('name', {
39
+ alias: 'n',
40
+ describe: t('commit_option_name').d('Edge Routine name'),
41
+ type: 'string'
34
42
  });
35
43
  },
36
44
  handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
37
- handleCommit(argv);
45
+ yield handleCommit(argv);
46
+ exit();
38
47
  })
39
48
  };
40
49
  export default commit;
41
50
  export function handleCommit(argv) {
42
51
  return __awaiter(this, void 0, void 0, function* () {
43
- var _a, _b, _c;
44
- if (!checkDirectory())
52
+ var _a, _b;
53
+ intro(`Commit an application with ESA`);
54
+ const projectInfo = yield validateAndInitializeProject(argv === null || argv === void 0 ? void 0 : argv.name);
55
+ if (!projectInfo)
45
56
  return;
46
- const projectConfig = getProjectConfig();
47
- if (!projectConfig)
48
- return logger.notInProject();
49
- if (!(yield checkIsLoginSuccess()))
50
- return;
51
- yield prodBuild(!!argv.minify, argv === null || argv === void 0 ? void 0 : argv.entry);
52
- try {
53
- const server = yield ApiService.getInstance();
54
- const req = { Name: projectConfig.name };
55
- const response = yield server.getRoutine(req, false);
56
- let specName = (_a = response === null || response === void 0 ? void 0 : response.data.Envs[0].SpecName) !== null && _a !== void 0 ? _a : '50ms';
57
- let action = 'Creating';
58
- let description;
59
- if (!response) {
60
- logger.log(`🙅 ${t('commit_er_not_exist').d('No routine found, creating a new one')}`);
61
- description = yield descriptionInput(`🖊️ ${t('commit_er_description').d('Enter a description for the routine')}:`, false);
62
- const specList = ((_c = (_b = (yield server.ListRoutineOptionalSpecs())) === null || _b === void 0 ? void 0 : _b.data.Specs) !== null && _c !== void 0 ? _c : []).reduce((acc, item) => {
63
- if (item.IsAvailable) {
64
- acc.push(item.SpecName);
65
- }
66
- return acc;
67
- }, []);
68
- specName = yield displaySelectSpec(specList);
69
- }
70
- else {
71
- logger.log(`🔄 ${t('commit_er_exist').d('Routine exists, updating the code')}`);
72
- description = yield descriptionInput(`🖊️ ${t('commit_version_description').d('Enter a description for the version')}:`, false);
73
- action = 'Updating';
74
- }
75
- const code = readEdgeRoutineFile() || '';
76
- const edgeRoutine = {
77
- name: projectConfig.name,
78
- code,
79
- description,
80
- specName
81
- };
82
- if (action === 'Creating') {
83
- yield createEdgeRoutine(edgeRoutine);
84
- }
85
- else {
86
- if (!(yield uploadEdgeRoutineCode(edgeRoutine)))
87
- return;
88
- yield releaseOfficialVersion(edgeRoutine);
89
- }
90
- exit(0);
91
- }
92
- catch (error) {
93
- logger.error(`${t('common_error_occurred').d('An error occurred:')} ${error}`);
94
- }
95
- });
96
- }
97
- export function createEdgeRoutine(edgeRoutine) {
98
- return __awaiter(this, void 0, void 0, function* () {
99
- try {
100
- const server = yield ApiService.getInstance();
101
- const res = yield server.createRoutine(edgeRoutine);
102
- const createResult = (res === null || res === void 0 ? void 0 : res.data.Status) === 'OK';
103
- if (!createResult) {
104
- logger.error(t('commit_create_er_fail').d('An error occurred while trying to create a routine'));
105
- return false;
106
- }
107
- logger.success(t('commit_create_er_success').d('Routine created successfully.'));
108
- return yield uploadEdgeRoutineCode(edgeRoutine);
57
+ const { projectName } = projectInfo;
58
+ let description;
59
+ if (argv.description) {
60
+ description = argv.description;
109
61
  }
110
- catch (error) {
111
- logger.error(`${t('common_error_occurred').d('An error occurred:')} ${error}`);
112
- return false;
113
- }
114
- });
115
- }
116
- export function uploadEdgeRoutineCode(edgeRoutine) {
117
- return __awaiter(this, void 0, void 0, function* () {
118
- try {
119
- const server = yield ApiService.getInstance();
120
- const uploadResult = yield server.getRoutineStagingCodeUploadInfo(edgeRoutine);
121
- if (!uploadResult) {
122
- logger.error(t('commit_upload_fail').d('An error occurred while trying to upload your code'));
123
- process.exit(0);
124
- }
125
- logger.success(t('commit_upload_success').d('Code uploaded successfully.'));
126
- return true;
127
- }
128
- catch (error) {
129
- logger.error(`${t('common_error_occurred').d('An error occurred:')} ${error}`);
130
- process.exit(0);
62
+ else {
63
+ description = (yield promptParameter({
64
+ type: 'text',
65
+ question: t('commit_version_description').d('Enter a description for the version'),
66
+ label: 'Description',
67
+ defaultValue: ''
68
+ }));
131
69
  }
132
- });
133
- }
134
- export function releaseOfficialVersion(edgeRoutine) {
135
- return __awaiter(this, void 0, void 0, function* () {
136
- var _a;
137
- const param = {
138
- Name: edgeRoutine.name,
139
- CodeDescription: (_a = edgeRoutine.description) !== null && _a !== void 0 ? _a : ''
140
- };
141
- const server = yield ApiService.getInstance();
142
- const commitResult = yield server.commitRoutineStagingCode(param);
143
- if (commitResult) {
144
- logger.success(t('commit_success').d('Code version committed successfully.'));
145
- return true;
70
+ logger.startSubStep('Generating code version');
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);
146
76
  }
147
- else {
148
- logger.error(t('commit_fail').d('An error occurred while trying to commit your code.'));
77
+ 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
+ if (!codeVersion) {
79
+ logger.endSubStep('Missing CodeVersion in response');
149
80
  return false;
150
81
  }
82
+ logger.endSubStep(`Version generated: ${codeVersion}`);
83
+ outro(`Code version ${chalk.bold(codeVersion)} generated successfully`);
151
84
  });
152
85
  }
@@ -7,15 +7,14 @@ 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';
11
+ import path from 'path';
10
12
  import esbuild from 'esbuild';
11
13
  import { lessLoader } from 'esbuild-plugin-less';
12
- import path from 'path';
13
- import fs from 'fs';
14
14
  import { getRoot } from '../../utils/fileUtils/base.js';
15
15
  import { NODE_EXTERNALS } from '../common/constant.js';
16
16
  const userRoot = getRoot();
17
17
  const entry = path.resolve(userRoot, 'src/index.js');
18
- const outfile = path.resolve(userRoot, '.dev/pub.js');
19
18
  export default function () {
20
19
  return __awaiter(this, arguments, void 0, function* (minify = false, customEntry, outputPath) {
21
20
  const entryPoint = customEntry
@@ -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
  {
@@ -0,0 +1,416 @@
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 chalk from 'chalk';
11
+ import t from '../../i18n/index.js';
12
+ import { ApiService } from '../../libs/apiService.js';
13
+ import logger from '../../libs/logger.js';
14
+ import { ensureRoutineExists } from '../../utils/checkIsRoutineCreated.js';
15
+ import compress from '../../utils/compress.js';
16
+ import { getProjectConfig } from '../../utils/fileUtils/index.js';
17
+ import sleep from '../../utils/sleep.js';
18
+ import { checkIsLoginSuccess } from '../utils.js';
19
+ function normalizeNotFoundStrategy(value) {
20
+ if (!value)
21
+ return undefined;
22
+ const lower = value.toLowerCase();
23
+ if (lower === 'singlepageapplication') {
24
+ return 'SinglePageApplication';
25
+ }
26
+ return value;
27
+ }
28
+ export function commitRoutineWithAssets(requestParams, zipBuffer) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ try {
31
+ const server = yield ApiService.getInstance();
32
+ const apiResult = yield server.CreateRoutineWithAssetsCodeVersion(requestParams);
33
+ if (!apiResult || !apiResult.data.OssPostConfig) {
34
+ return {
35
+ isSuccess: false,
36
+ res: null
37
+ };
38
+ }
39
+ const ossConfig = apiResult.data.OssPostConfig;
40
+ if (!ossConfig.OSSAccessKeyId ||
41
+ !ossConfig.Signature ||
42
+ !ossConfig.Url ||
43
+ !ossConfig.Key ||
44
+ !ossConfig.Policy) {
45
+ console.error('Missing required OSS configuration fields');
46
+ return {
47
+ isSuccess: false,
48
+ res: null
49
+ };
50
+ }
51
+ let uploadSuccess = false;
52
+ for (let i = 0; i < 3; i++) {
53
+ uploadSuccess = yield server.uploadToOss({
54
+ OSSAccessKeyId: ossConfig.OSSAccessKeyId,
55
+ Signature: ossConfig.Signature,
56
+ Url: ossConfig.Url,
57
+ Key: ossConfig.Key,
58
+ Policy: ossConfig.Policy,
59
+ XOssSecurityToken: ossConfig.XOssSecurityToken || ''
60
+ }, zipBuffer);
61
+ if (uploadSuccess) {
62
+ break;
63
+ }
64
+ }
65
+ return {
66
+ isSuccess: uploadSuccess,
67
+ res: apiResult
68
+ };
69
+ }
70
+ catch (error) {
71
+ console.error('Error in createRoutineWithAssetsCodeVersion:', error);
72
+ return {
73
+ isSuccess: false,
74
+ res: null
75
+ };
76
+ }
77
+ });
78
+ }
79
+ /**
80
+ * 通用的项目验证和初始化函数
81
+ * 包含目录检查、项目配置获取、登录检查、routine存在性检查
82
+ */
83
+ export function validateAndInitializeProject(name, projectPath) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ const projectConfig = getProjectConfig(projectPath);
86
+ // allow missing config, derive name from cwd when not provided
87
+ const projectName = name ||
88
+ (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) ||
89
+ process.cwd().split(/[\\/]/).pop();
90
+ if (!projectName) {
91
+ logger.notInProject();
92
+ return null;
93
+ }
94
+ logger.startSubStep('Checking login status');
95
+ const isSuccess = yield checkIsLoginSuccess();
96
+ if (!isSuccess) {
97
+ logger.endSubStep('You are not logged in');
98
+ return null;
99
+ }
100
+ logger.endSubStep('Logged in');
101
+ yield ensureRoutineExists(projectName);
102
+ return { projectConfig: projectConfig || null, projectName };
103
+ });
104
+ }
105
+ /**
106
+ * 通用的routine详情获取函数
107
+ */
108
+ export function getRoutineDetails(projectName) {
109
+ return __awaiter(this, void 0, void 0, function* () {
110
+ const server = yield ApiService.getInstance();
111
+ const req = { Name: projectName };
112
+ return yield server.getRoutine(req, false);
113
+ });
114
+ }
115
+ /**
116
+ * 通用的代码压缩和提交函数
117
+ * 支持assets和普通代码两种模式
118
+ */
119
+ export function generateCodeVersion(projectName_1, description_1, entry_1, assets_1) {
120
+ return __awaiter(this, arguments, void 0, function* (projectName, description, entry, assets, minify = false, projectPath) {
121
+ var _a;
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 });
134
+ }
135
+ const child = node.children.get(part);
136
+ if (i === parts.length - 1)
137
+ child.isFile = true;
138
+ node = child;
139
+ }
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
+ });
152
+ };
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
180
+ };
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)
194
+ return name;
195
+ if (stat.hasDynamic && stat.hasStatic) {
196
+ return `${name}${dynamicMarker}${staticMarker}`;
197
+ }
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);
212
+ }
213
+ logger.block();
214
+ const projectConfig = getProjectConfig(projectPath);
215
+ const notFoundStrategy = normalizeNotFoundStrategy((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.assets) === null || _a === void 0 ? void 0 : _a.notFoundStrategy);
216
+ logger.startSubStep('Generating code version');
217
+ const requestParams = {
218
+ Name: projectName,
219
+ CodeDescription: description,
220
+ ExtraInfo: JSON.stringify({ Source: 'CLI' })
221
+ };
222
+ if (notFoundStrategy) {
223
+ requestParams.ConfOptions = {
224
+ NotFoundStrategy: notFoundStrategy
225
+ };
226
+ }
227
+ const res = yield commitRoutineWithAssets(requestParams, zip === null || zip === void 0 ? void 0 : zip.toBuffer());
228
+ if (res === null || res === void 0 ? void 0 : res.isSuccess) {
229
+ return {
230
+ isSuccess: true,
231
+ res: res === null || res === void 0 ? void 0 : res.res
232
+ };
233
+ }
234
+ else {
235
+ return {
236
+ isSuccess: false,
237
+ res: null
238
+ };
239
+ }
240
+ });
241
+ }
242
+ /**
243
+ * 根据 env 在一个或多个环境部署
244
+ */
245
+ export function deployToEnvironments(name, codeVersion, env) {
246
+ return __awaiter(this, void 0, void 0, function* () {
247
+ if (env === 'all') {
248
+ const isStagingSuccess = yield deployCodeVersion(name, codeVersion, 'staging');
249
+ const isProdSuccess = yield deployCodeVersion(name, codeVersion, 'production');
250
+ return isStagingSuccess && isProdSuccess;
251
+ }
252
+ return yield deployCodeVersion(name, codeVersion, env);
253
+ });
254
+ }
255
+ /**
256
+ * 通用的快速部署函数
257
+ * 结合了压缩、提交和部署的完整流程
258
+ */
259
+ export function commitAndDeployVersion(projectName_1, scriptEntry_1, assets_1) {
260
+ return __awaiter(this, arguments, void 0, function* (projectName, scriptEntry, assets, description = '', projectPath, env = 'production', minify = false, version) {
261
+ var _a, _b, _c;
262
+ const projectInfo = yield validateAndInitializeProject(projectName, projectPath);
263
+ if (!projectInfo) {
264
+ return false;
265
+ }
266
+ const { projectConfig } = projectInfo;
267
+ // 2) Use existing version or generate a new one
268
+ if (version) {
269
+ logger.startSubStep(`Using existing version ${version}`);
270
+ const deployed = yield deployToEnvironments(projectInfo.projectName, version, env);
271
+ logger.endSubStep(deployed ? 'Deploy finished' : 'Deploy failed');
272
+ return deployed;
273
+ }
274
+ const res = yield generateCodeVersion(projectInfo.projectName, description, scriptEntry || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.entry), assets || ((_a = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.assets) === null || _a === void 0 ? void 0 : _a.directory), minify || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.minify), projectPath);
275
+ const isCommitSuccess = res === null || res === void 0 ? void 0 : res.isSuccess;
276
+ if (!isCommitSuccess) {
277
+ logger.endSubStep('Generate version failed');
278
+ return false;
279
+ }
280
+ const codeVersion = (_c = (_b = res === null || res === void 0 ? void 0 : res.res) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.CodeVersion;
281
+ if (!codeVersion) {
282
+ logger.endSubStep('Missing CodeVersion in response');
283
+ return false;
284
+ }
285
+ logger.endSubStep(`Version generated: ${codeVersion}`);
286
+ // 3) Deploy to specified environment(s)
287
+ const deployed = yield deployToEnvironments(projectInfo.projectName, codeVersion, env);
288
+ return deployed;
289
+ });
290
+ }
291
+ /**
292
+ * 通用的版本部署函数
293
+ */
294
+ export function deployCodeVersion(name, codeVersion, environment) {
295
+ return __awaiter(this, void 0, void 0, function* () {
296
+ const server = yield ApiService.getInstance();
297
+ // Ensure the committed code version is ready before deploying
298
+ const isReady = yield waitForCodeVersionReady(name, codeVersion, environment);
299
+ if (!isReady) {
300
+ logger.error('The code version is not ready for deployment.');
301
+ return false;
302
+ }
303
+ const res = yield server.createRoutineCodeDeployment({
304
+ Name: name,
305
+ CodeVersions: [{ Percentage: 100, CodeVersion: codeVersion }],
306
+ Strategy: 'percentage',
307
+ Env: environment
308
+ });
309
+ if (res) {
310
+ return true;
311
+ }
312
+ else {
313
+ return false;
314
+ }
315
+ });
316
+ }
317
+ /**
318
+ * Poll routine code version status until it becomes ready
319
+ */
320
+ export function waitForCodeVersionReady(name_1, codeVersion_1, env_1) {
321
+ return __awaiter(this, arguments, void 0, function* (name, codeVersion, env, timeoutMs = 5 * 60 * 1000, intervalMs = 1000) {
322
+ var _a, _b;
323
+ if (!name || !codeVersion) {
324
+ return false;
325
+ }
326
+ const server = yield ApiService.getInstance();
327
+ const start = Date.now();
328
+ logger.startSubStep(`Waiting for code version ${codeVersion} to be ready...`);
329
+ while (Date.now() - start < timeoutMs) {
330
+ try {
331
+ const info = yield server.getRoutineCodeVersionInfo({
332
+ Name: name,
333
+ CodeVersion: codeVersion
334
+ });
335
+ const status = (_b = (_a = info === null || info === void 0 ? void 0 : info.data) === null || _a === void 0 ? void 0 : _a.Status) === null || _b === void 0 ? void 0 : _b.toLowerCase();
336
+ if (status === 'init') {
337
+ yield sleep(intervalMs);
338
+ continue;
339
+ }
340
+ else if (status === 'available') {
341
+ logger.endSubStep(`Code version ${chalk.cyan(codeVersion)} is deployed to ${env}.`);
342
+ return true;
343
+ }
344
+ else {
345
+ logger.error(`Code version ${chalk.cyan(codeVersion)} build ${status}.`);
346
+ return false;
347
+ }
348
+ }
349
+ catch (e) {
350
+ // swallow and retry until timeout
351
+ }
352
+ }
353
+ logger.error(`⏰ Waiting for code version ${chalk.cyan(codeVersion)} timed out.`);
354
+ return false;
355
+ });
356
+ }
357
+ /**
358
+ * 通用的部署成功显示函数
359
+ * 显示部署成功信息、访问链接和后续操作指南
360
+ */
361
+ export function displayDeploySuccess(projectName_1) {
362
+ return __awaiter(this, arguments, void 0, function* (projectName, showDomainGuide = true, showRouteGuide = true) {
363
+ var _a;
364
+ const service = yield ApiService.getInstance();
365
+ const res = yield service.getRoutine({ Name: projectName });
366
+ const defaultUrl = (_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.DefaultRelatedRecord;
367
+ const visitUrl = defaultUrl ? 'https://' + defaultUrl : '';
368
+ const accent = chalk.hex('#7C3AED');
369
+ const label = chalk.hex('#22c55e');
370
+ const subtle = chalk.gray;
371
+ const title = `${chalk.bold('🚀 ')}${chalk.bold(t('init_deploy_success').d('Deploy Success'))}`;
372
+ const lineUrl = `${label('URL')} ${visitUrl ? chalk.yellowBright(visitUrl) : subtle('-')}`;
373
+ const lineProject = `${label('APP')} ${chalk.cyan(projectName || '-')}`;
374
+ const lineCd = projectName
375
+ ? `${label('TIP')} ${t('deploy_success_cd').d('Enter project directory')}: ${chalk.green(`cd ${projectName}`)}`
376
+ : '';
377
+ const guides = [];
378
+ if (showDomainGuide) {
379
+ guides.push(`${label('TIP')} ${t('deploy_success_guide').d('Add a custom domain')}: ${chalk.green('esa domain add <DOMAIN>')}`);
380
+ }
381
+ if (showRouteGuide) {
382
+ guides.push(`${label('TIP')} ${t('deploy_success_guide_2').d('Add routes for a site')}: ${chalk.green('esa route add -r <ROUTE> -s <SITE>')}`);
383
+ }
384
+ const tip = `${subtle(t('deploy_url_warn').d('The domain may take some time to take effect, please try again later.'))}`;
385
+ const lines = [
386
+ accent(title),
387
+ '',
388
+ lineProject,
389
+ lineUrl,
390
+ lineCd ? '' : '',
391
+ lineCd || '',
392
+ guides.length ? '' : '',
393
+ ...guides,
394
+ guides.length ? '' : '',
395
+ tip
396
+ ];
397
+ const stripAnsi = (s) => s.replace(/\x1B\[[0-?]*[ -\/]*[@-~]/g, '');
398
+ const contentWidth = Math.max(...lines.map((l) => stripAnsi(l).length));
399
+ const borderColor = chalk.hex('#00D4FF').bold;
400
+ const top = `${borderColor('╔')}${borderColor('═'.repeat(contentWidth + 2))}${borderColor('╗')}`;
401
+ const bottom = `${borderColor('╚')}${borderColor('═'.repeat(contentWidth + 2))}${borderColor('╝')}`;
402
+ const boxLines = [
403
+ top,
404
+ ...lines.map((l) => {
405
+ const pad = ' '.repeat(contentWidth - stripAnsi(l).length);
406
+ const left = borderColor('║');
407
+ const right = borderColor('║');
408
+ return `${left} ${l}${pad} ${right}`;
409
+ }),
410
+ bottom
411
+ ];
412
+ logger.block();
413
+ boxLines.forEach((l) => logger.log(l));
414
+ logger.block();
415
+ });
416
+ }
@@ -1,8 +1,8 @@
1
1
  import fs from 'fs';
2
2
  import spawn from 'cross-spawn';
3
- import { projectConfigPath, cliConfigPath } from '../utils/fileUtils/index.js';
4
3
  import t from '../i18n/index.js';
5
4
  import logger from '../libs/logger.js';
5
+ import { projectConfigPath, cliConfigPath } from '../utils/fileUtils/index.js';
6
6
  const editConfigFile = (configPath) => {
7
7
  const editor = process.env.EDITOR || 'vi';
8
8
  spawn(editor, [configPath], {