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
|
@@ -7,16 +7,21 @@ 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-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
10
|
import { execSync } from 'child_process';
|
|
16
|
-
import
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { exit } from 'process';
|
|
13
|
+
import { confirm as clackConfirm, isCancel, log, outro } from '@clack/prompts';
|
|
17
14
|
import chalk from 'chalk';
|
|
18
|
-
import
|
|
15
|
+
import fs from 'fs-extra';
|
|
16
|
+
import Haikunator from 'haikunator';
|
|
17
|
+
import t from '../../i18n/index.js';
|
|
18
|
+
import logger from '../../libs/logger.js';
|
|
19
|
+
import Template from '../../libs/templates/index.js';
|
|
20
|
+
import { execCommand } from '../../utils/command.js';
|
|
19
21
|
import { getDirName } from '../../utils/fileUtils/base.js';
|
|
22
|
+
import { generateConfigFile, getCliConfig, getProjectConfig, getTemplatesConfig, templateHubPath, updateProjectConfigFile } from '../../utils/fileUtils/index.js';
|
|
23
|
+
import promptParameter from '../../utils/prompt.js';
|
|
24
|
+
import { commitAndDeployVersion } from '../common/utils.js';
|
|
20
25
|
export const getTemplateInstances = (templateHubPath) => {
|
|
21
26
|
return fs
|
|
22
27
|
.readdirSync(templateHubPath)
|
|
@@ -46,6 +51,7 @@ export const transferTemplatesToSelectItem = (configs, templateInstanceList, lan
|
|
|
46
51
|
return {
|
|
47
52
|
label: lang === 'en' ? config.Title_EN : config.Title_ZH,
|
|
48
53
|
value: value,
|
|
54
|
+
hint: lang === 'en' ? config.Desc_EN : config.Desc_ZH,
|
|
49
55
|
children
|
|
50
56
|
};
|
|
51
57
|
});
|
|
@@ -66,53 +72,680 @@ export const preInstallDependencies = (targetPath) => __awaiter(void 0, void 0,
|
|
|
66
72
|
else {
|
|
67
73
|
logger.log(t('no_build_script').d('No build script found in package.json, skipping build step.'));
|
|
68
74
|
}
|
|
75
|
+
// After build, try to infer assets directory if not explicitly known
|
|
76
|
+
try {
|
|
77
|
+
const candidates = ['dist', 'build', 'out'];
|
|
78
|
+
for (const dir of candidates) {
|
|
79
|
+
const abs = path.join(targetPath, dir);
|
|
80
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isDirectory()) {
|
|
81
|
+
// Update config file if present and assets not set
|
|
82
|
+
const projectConfig = getProjectConfig(targetPath);
|
|
83
|
+
if (projectConfig) {
|
|
84
|
+
const { updateProjectConfigFile } = yield import('../../utils/fileUtils/index.js');
|
|
85
|
+
if (!projectConfig.assets || !projectConfig.assets.directory) {
|
|
86
|
+
yield updateProjectConfigFile({ assets: { directory: dir } }, targetPath);
|
|
87
|
+
logger.success(`Detected build output "${dir}" and updated assets.directory`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (_a) { }
|
|
69
95
|
}
|
|
70
96
|
});
|
|
71
97
|
export function checkAndUpdatePackage(packageName) {
|
|
72
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
73
99
|
try {
|
|
74
|
-
|
|
100
|
+
const spinner = logger.ora;
|
|
101
|
+
spinner.text = t('checking_template_update').d('Checking esa-template updates...');
|
|
102
|
+
spinner.start();
|
|
103
|
+
// Get currently installed version
|
|
75
104
|
const __dirname = getDirName(import.meta.url);
|
|
76
|
-
console.log(__dirname);
|
|
77
105
|
const packageJsonPath = path.join(__dirname, '../../../');
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
let versionInfo;
|
|
107
|
+
try {
|
|
108
|
+
versionInfo = execSync(`npm list ${packageName}`, {
|
|
109
|
+
cwd: packageJsonPath
|
|
110
|
+
}).toString();
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
spinner.text = t('template_updating').d('Updating templates to latest...');
|
|
114
|
+
execSync(`rm -rf node_modules/${packageName}`, {
|
|
115
|
+
cwd: packageJsonPath
|
|
116
|
+
});
|
|
117
|
+
execSync(`npm install ${packageName}@latest`, {
|
|
118
|
+
cwd: packageJsonPath,
|
|
119
|
+
stdio: 'inherit'
|
|
120
|
+
});
|
|
121
|
+
spinner.stop();
|
|
122
|
+
logger.log(`├ ${t('template_updated_to_latest').d('Templates updated to latest.')}`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
81
125
|
const match = versionInfo.match(new RegExp(`(${packageName})@([0-9.]+)`));
|
|
82
126
|
const currentVersion = match ? match[2] : '';
|
|
83
|
-
//
|
|
127
|
+
// Get latest version
|
|
84
128
|
const latestVersion = execSync(`npm view ${packageName} version`, {
|
|
85
129
|
cwd: packageJsonPath
|
|
86
130
|
})
|
|
87
131
|
.toString()
|
|
88
132
|
.trim();
|
|
89
133
|
if (currentVersion !== latestVersion) {
|
|
134
|
+
spinner.stop();
|
|
90
135
|
logger.log(t('display_current_esa_template_version').d(`Current esa-template version:`) +
|
|
91
136
|
chalk.green(currentVersion) +
|
|
92
137
|
' ' +
|
|
93
138
|
t('display_latest_esa_template_version').d(`Latest esa-template version:`) +
|
|
94
139
|
chalk.green(latestVersion));
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
name: 'isUpdate',
|
|
140
|
+
logger.stopSpinner();
|
|
141
|
+
const isUpdate = yield clackConfirm({
|
|
98
142
|
message: t('is_update_to_latest_version').d('Do you want to update templates to latest version?')
|
|
99
143
|
});
|
|
100
|
-
if (isUpdate) {
|
|
101
|
-
|
|
144
|
+
if (!isCancel(isUpdate) && isUpdate) {
|
|
145
|
+
spinner.start(t('template_updating').d('Updating templates to latest...'));
|
|
146
|
+
execSync(`rm -rf node_modules/${packageName}`, {
|
|
147
|
+
cwd: packageJsonPath
|
|
148
|
+
});
|
|
149
|
+
execSync(`rm -rf package-lock.json`, {
|
|
102
150
|
cwd: packageJsonPath
|
|
103
151
|
});
|
|
104
|
-
|
|
152
|
+
execSync(`npm install ${packageName}@latest`, {
|
|
153
|
+
cwd: packageJsonPath,
|
|
154
|
+
stdio: 'inherit'
|
|
155
|
+
});
|
|
156
|
+
spinner.stop();
|
|
157
|
+
logger.log(`├ ${t('updated_esa_template_to_latest_version', { packageName }).d(`${packageName} updated successfully`)}`);
|
|
105
158
|
}
|
|
106
159
|
}
|
|
107
160
|
else {
|
|
108
|
-
|
|
161
|
+
spinner.stop();
|
|
162
|
+
logger.log(` ${t('checking_esa_template_finished').d(`Checking esa-template finished.`)}`);
|
|
163
|
+
t('esa_template_is_latest_version', { packageName }).d(`${packageName} is latest.`);
|
|
164
|
+
logger.divider();
|
|
109
165
|
}
|
|
110
166
|
}
|
|
111
167
|
catch (error) {
|
|
112
168
|
console.log(error);
|
|
113
169
|
if (error instanceof Error) {
|
|
114
|
-
logger.
|
|
170
|
+
logger.ora.fail(t('check_and_update_package_error').d('Error: An error occurred while checking and updating the package, skipping template update'));
|
|
115
171
|
}
|
|
116
172
|
}
|
|
117
173
|
});
|
|
118
174
|
}
|
|
175
|
+
export const getFrameworkConfig = (framework) => {
|
|
176
|
+
// Read template.jsonc from init directory
|
|
177
|
+
const templatePath = path.join(getDirName(import.meta.url), 'template.jsonc');
|
|
178
|
+
const jsonc = fs.readFileSync(templatePath, 'utf-8');
|
|
179
|
+
const json = JSON.parse(jsonc);
|
|
180
|
+
return json[framework];
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* 获取框架全部配置
|
|
184
|
+
* @returns 框架全部配置
|
|
185
|
+
*/
|
|
186
|
+
export const getAllFrameworkConfig = () => {
|
|
187
|
+
// Read template.jsonc from init directory
|
|
188
|
+
const templatePath = path.join(getDirName(import.meta.url), 'template.jsonc');
|
|
189
|
+
const jsonc = fs.readFileSync(templatePath, 'utf-8');
|
|
190
|
+
const json = JSON.parse(jsonc);
|
|
191
|
+
return json;
|
|
192
|
+
};
|
|
193
|
+
export function getInitParamsFromArgv(argv) {
|
|
194
|
+
const a = argv;
|
|
195
|
+
const HaikunatorCtor = Haikunator;
|
|
196
|
+
const haikunator = new HaikunatorCtor();
|
|
197
|
+
const params = {
|
|
198
|
+
name: ''
|
|
199
|
+
};
|
|
200
|
+
if (a.yes) {
|
|
201
|
+
params.name = haikunator.haikunate();
|
|
202
|
+
params.git = true;
|
|
203
|
+
params.deploy = true;
|
|
204
|
+
params.template = 'Hello World';
|
|
205
|
+
params.framework = undefined;
|
|
206
|
+
params.language = undefined;
|
|
207
|
+
params.yes = true;
|
|
208
|
+
}
|
|
209
|
+
if (typeof a.name === 'string')
|
|
210
|
+
params.name = a.name;
|
|
211
|
+
if (typeof a.template === 'string' && a.template) {
|
|
212
|
+
params.template = a.template;
|
|
213
|
+
params.framework = undefined;
|
|
214
|
+
params.language = undefined;
|
|
215
|
+
params.category = 'template';
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
const fw = a.framework;
|
|
219
|
+
const lang = a.language;
|
|
220
|
+
if (fw) {
|
|
221
|
+
params.framework = fw;
|
|
222
|
+
params.category = 'framework';
|
|
223
|
+
}
|
|
224
|
+
if (lang) {
|
|
225
|
+
params.language = lang;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (typeof a.git === 'boolean')
|
|
229
|
+
params.git = Boolean(a.git);
|
|
230
|
+
if (typeof a.deploy === 'boolean')
|
|
231
|
+
params.deploy = Boolean(a.deploy);
|
|
232
|
+
return params;
|
|
233
|
+
}
|
|
234
|
+
// Configure project name
|
|
235
|
+
export const configProjectName = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
236
|
+
if (initParams.name) {
|
|
237
|
+
log.step(`Project name configured ${initParams.name}`);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const HaikunatorCtor = Haikunator;
|
|
241
|
+
const haikunator = new HaikunatorCtor();
|
|
242
|
+
const defaultName = haikunator.haikunate();
|
|
243
|
+
const name = (yield promptParameter({
|
|
244
|
+
type: 'text',
|
|
245
|
+
question: `${t('init_input_name').d('Enter the name of project:')}`,
|
|
246
|
+
label: 'Project name',
|
|
247
|
+
defaultValue: defaultName,
|
|
248
|
+
validate: (input) => {
|
|
249
|
+
if (input === '' || input === undefined) {
|
|
250
|
+
initParams.name = defaultName;
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
const regex = /^[a-z0-9-]{2,}$/;
|
|
254
|
+
if (!regex.test(input)) {
|
|
255
|
+
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.');
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
}));
|
|
260
|
+
initParams.name = name;
|
|
261
|
+
});
|
|
262
|
+
export const configCategory = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
263
|
+
if (initParams.category || initParams.framework || initParams.template) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const initMode = (yield promptParameter({
|
|
267
|
+
type: 'select',
|
|
268
|
+
question: 'How would you like to initialize the project?',
|
|
269
|
+
label: 'Init mode',
|
|
270
|
+
choices: [
|
|
271
|
+
{ name: 'Framework Starter', value: 'framework' },
|
|
272
|
+
{
|
|
273
|
+
name: 'Function Template',
|
|
274
|
+
value: 'template'
|
|
275
|
+
}
|
|
276
|
+
]
|
|
277
|
+
}));
|
|
278
|
+
initParams.category = initMode;
|
|
279
|
+
});
|
|
280
|
+
/*
|
|
281
|
+
选择模板
|
|
282
|
+
如果选择的是framework,则选择具体的模版 vue /react等
|
|
283
|
+
如果选择的是template,则选择具体的模版 esa template
|
|
284
|
+
*/
|
|
285
|
+
export const configTemplate = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
286
|
+
if (initParams.template) {
|
|
287
|
+
log.step(`Template configured ${initParams.template}`);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (initParams.framework) {
|
|
291
|
+
log.step(`Framework configured ${initParams.framework}`);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (initParams.category === 'template') {
|
|
295
|
+
const templateItems = prepareTemplateItems();
|
|
296
|
+
const selectedTemplatePath = yield promptParameter({
|
|
297
|
+
type: 'multiLevelSelect',
|
|
298
|
+
question: 'Select a template:',
|
|
299
|
+
treeItems: templateItems
|
|
300
|
+
});
|
|
301
|
+
if (!selectedTemplatePath)
|
|
302
|
+
return null;
|
|
303
|
+
// TODO
|
|
304
|
+
initParams.template = selectedTemplatePath;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
const allFrameworkConfig = getAllFrameworkConfig();
|
|
308
|
+
const fw = (yield promptParameter({
|
|
309
|
+
type: 'select',
|
|
310
|
+
question: 'Select a framework',
|
|
311
|
+
label: 'Framework',
|
|
312
|
+
choices: Object.keys(allFrameworkConfig).map((fw) => {
|
|
313
|
+
var _a;
|
|
314
|
+
return ({
|
|
315
|
+
name: allFrameworkConfig[fw].label,
|
|
316
|
+
value: fw,
|
|
317
|
+
hint: (_a = allFrameworkConfig[fw]) === null || _a === void 0 ? void 0 : _a.hint
|
|
318
|
+
});
|
|
319
|
+
})
|
|
320
|
+
}));
|
|
321
|
+
initParams.framework = fw;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
export const configLanguage = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
325
|
+
if (initParams.language) {
|
|
326
|
+
log.info(`Language configured ${initParams.language}`);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const framework = initParams.framework;
|
|
330
|
+
if (!framework) {
|
|
331
|
+
log.info('Framework config not configured, language skipped');
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const frameworkConfig = getFrameworkConfig(framework);
|
|
335
|
+
if (frameworkConfig.language) {
|
|
336
|
+
const language = (yield promptParameter({
|
|
337
|
+
type: 'select',
|
|
338
|
+
question: t('init_language_select').d('Select programming language:'),
|
|
339
|
+
label: 'Language',
|
|
340
|
+
choices: [
|
|
341
|
+
{
|
|
342
|
+
name: t('init_language_typescript').d('TypeScript (.ts) - Type-safe JavaScript, recommended'),
|
|
343
|
+
value: 'typescript'
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
name: t('init_language_javascript').d('JavaScript (.js) - Traditional JavaScript'),
|
|
347
|
+
value: 'javascript'
|
|
348
|
+
}
|
|
349
|
+
],
|
|
350
|
+
defaultValue: 'typescript'
|
|
351
|
+
}));
|
|
352
|
+
initParams.language = language;
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
export const createProject = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
356
|
+
var _a;
|
|
357
|
+
if (initParams.template) {
|
|
358
|
+
// resolve template value: it may be a filesystem path or a template title
|
|
359
|
+
let selectedTemplatePath = initParams.template;
|
|
360
|
+
if (!path.isAbsolute(selectedTemplatePath) ||
|
|
361
|
+
!fs.existsSync(selectedTemplatePath)) {
|
|
362
|
+
const instances = getTemplateInstances(templateHubPath);
|
|
363
|
+
const matched = instances.find((it) => it.title === initParams.template);
|
|
364
|
+
if (matched) {
|
|
365
|
+
selectedTemplatePath = matched.path;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (!fs.existsSync(selectedTemplatePath)) {
|
|
369
|
+
outro(`Project creation failed: cannot resolve template "${initParams.template}"`);
|
|
370
|
+
exit(1);
|
|
371
|
+
}
|
|
372
|
+
const res = yield initializeProject(selectedTemplatePath, initParams.name);
|
|
373
|
+
if (!res) {
|
|
374
|
+
outro(`Project creation failed`);
|
|
375
|
+
exit(1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (initParams.framework) {
|
|
379
|
+
const framework = initParams.framework;
|
|
380
|
+
const frameworkConfig = getFrameworkConfig(framework);
|
|
381
|
+
const command = frameworkConfig.command;
|
|
382
|
+
const templateFlag = ((_a = frameworkConfig.language) === null || _a === void 0 ? void 0 : _a[initParams.language || 'typescript']) || '';
|
|
383
|
+
const extraParams = frameworkConfig.params || '';
|
|
384
|
+
const full = `${command} ${initParams.name} ${templateFlag} ${extraParams}`.trim();
|
|
385
|
+
const res = yield execCommand(['sh', '-lc', full], {
|
|
386
|
+
interactive: true,
|
|
387
|
+
startText: `Starting to execute framework command ${chalk.gray(full)}`,
|
|
388
|
+
doneText: `Framework command executed ${chalk.gray(full)}`
|
|
389
|
+
});
|
|
390
|
+
if (!res.success) {
|
|
391
|
+
outro(`Framework command execution failed`);
|
|
392
|
+
exit(1);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
export const installDependencies = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
397
|
+
if (initParams.template) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
401
|
+
const res = yield execCommand(['npm', 'install'], {
|
|
402
|
+
cwd: targetPath,
|
|
403
|
+
useSpinner: true,
|
|
404
|
+
silent: true,
|
|
405
|
+
startText: 'Installing dependencies',
|
|
406
|
+
doneText: 'Dependencies installed'
|
|
407
|
+
});
|
|
408
|
+
if (!res.success) {
|
|
409
|
+
outro(`Dependencies installation failed`);
|
|
410
|
+
exit(1);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
/**
|
|
414
|
+
* Apply configured file edits (方式1: overwrite) after project scaffold
|
|
415
|
+
*/
|
|
416
|
+
export const applyFileEdits = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
417
|
+
var _a;
|
|
418
|
+
if (!initParams.framework) {
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
const frameworkConfig = getFrameworkConfig(initParams.framework || '');
|
|
422
|
+
const edits = frameworkConfig.fileEdits || [];
|
|
423
|
+
if (!edits.length)
|
|
424
|
+
return true;
|
|
425
|
+
logger.startSubStep(`Applying file edits`);
|
|
426
|
+
const __dirname = getDirName(import.meta.url);
|
|
427
|
+
try {
|
|
428
|
+
const toRegexFromGlob = (pattern) => {
|
|
429
|
+
// Very small glob subset: *, ?, {a,b,c}
|
|
430
|
+
let escaped = pattern
|
|
431
|
+
.replace(/[-/\\^$+?.()|[\]{}]/g, '\\$&') // escape regex specials first
|
|
432
|
+
.replace(/\\\*/g, '.*')
|
|
433
|
+
.replace(/\\\?/g, '.');
|
|
434
|
+
// restore and convert {a,b} to (a|b)
|
|
435
|
+
escaped = escaped.replace(/\\\{([^}]+)\\\}/g, (_, inner) => {
|
|
436
|
+
const parts = inner.split(',').map((s) => s.trim());
|
|
437
|
+
return `(${parts.join('|')})`;
|
|
438
|
+
});
|
|
439
|
+
return new RegExp('^' + escaped + '$');
|
|
440
|
+
};
|
|
441
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
442
|
+
const listRootFiles = () => {
|
|
443
|
+
try {
|
|
444
|
+
return fs.readdirSync(targetPath);
|
|
445
|
+
}
|
|
446
|
+
catch (_a) {
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
for (const edit of edits) {
|
|
451
|
+
if (((_a = edit.when) === null || _a === void 0 ? void 0 : _a.language) && initParams.language) {
|
|
452
|
+
if (edit.when.language !== initParams.language)
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
let matchedFiles = [];
|
|
456
|
+
if (edit.matchType === 'exact') {
|
|
457
|
+
const absExact = path.join(targetPath, edit.match);
|
|
458
|
+
matchedFiles = fs.existsSync(absExact) ? [edit.match] : [];
|
|
459
|
+
}
|
|
460
|
+
else if (edit.matchType === 'glob') {
|
|
461
|
+
const regex = toRegexFromGlob(edit.match);
|
|
462
|
+
matchedFiles = listRootFiles().filter((name) => regex.test(name));
|
|
463
|
+
}
|
|
464
|
+
else if (edit.matchType === 'regex') {
|
|
465
|
+
const regex = new RegExp(edit.match);
|
|
466
|
+
matchedFiles = listRootFiles().filter((name) => regex.test(name));
|
|
467
|
+
}
|
|
468
|
+
if (!matchedFiles.length)
|
|
469
|
+
continue;
|
|
470
|
+
// resolve content
|
|
471
|
+
let payload = null;
|
|
472
|
+
if (edit.fromFile) {
|
|
473
|
+
const absFrom = path.isAbsolute(edit.fromFile)
|
|
474
|
+
? edit.fromFile
|
|
475
|
+
: path.join(__dirname, edit.fromFile);
|
|
476
|
+
payload = fs.readFileSync(absFrom, 'utf-8');
|
|
477
|
+
}
|
|
478
|
+
else if (typeof edit.content === 'string') {
|
|
479
|
+
payload = edit.content;
|
|
480
|
+
}
|
|
481
|
+
for (const rel of matchedFiles) {
|
|
482
|
+
const abs = path.join(targetPath, rel);
|
|
483
|
+
if (payload == null)
|
|
484
|
+
continue;
|
|
485
|
+
if (!fs.existsSync(abs))
|
|
486
|
+
continue; // Only overwrite existing files
|
|
487
|
+
fs.ensureDirSync(path.dirname(abs));
|
|
488
|
+
fs.writeFileSync(abs, payload, 'utf-8');
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
logger.endSubStep('File edits applied');
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
catch (_b) {
|
|
495
|
+
outro(`File edits application failed`);
|
|
496
|
+
exit(1);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
export const installESACli = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
500
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
501
|
+
const res = yield execCommand(['npm', 'install', '-D', 'esa-cli'], {
|
|
502
|
+
cwd: targetPath,
|
|
503
|
+
useSpinner: true,
|
|
504
|
+
silent: true,
|
|
505
|
+
startText: 'Installing ESA CLI',
|
|
506
|
+
doneText: 'ESA CLI installed in the project'
|
|
507
|
+
});
|
|
508
|
+
if (!res.success) {
|
|
509
|
+
outro(`ESA CLI installation failed`);
|
|
510
|
+
exit(1);
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
export const updateConfigFile = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
514
|
+
var _a, _b;
|
|
515
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
516
|
+
const configFormat = 'jsonc';
|
|
517
|
+
logger.startSubStep(`Updating config file`);
|
|
518
|
+
try {
|
|
519
|
+
if (initParams.framework) {
|
|
520
|
+
const frameworkConfig = getFrameworkConfig(initParams.framework);
|
|
521
|
+
const assetsDirectory = (_a = frameworkConfig.assets) === null || _a === void 0 ? void 0 : _a.directory;
|
|
522
|
+
const notFoundStrategy = (_b = frameworkConfig.assets) === null || _b === void 0 ? void 0 : _b.notFoundStrategy;
|
|
523
|
+
yield generateConfigFile(initParams.name, {
|
|
524
|
+
assets: assetsDirectory ? { directory: assetsDirectory } : undefined
|
|
525
|
+
}, targetPath, configFormat, notFoundStrategy);
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
// TODO revise template config file later
|
|
529
|
+
// console.log(
|
|
530
|
+
// 'test:',
|
|
531
|
+
// initParams.name,
|
|
532
|
+
// undefined,
|
|
533
|
+
// targetPath,
|
|
534
|
+
// configFormat
|
|
535
|
+
// );
|
|
536
|
+
// logger.startSubStep(`Updating config file`);
|
|
537
|
+
// await generateConfigFile(initParams.name, undefined, targetPath, 'toml');
|
|
538
|
+
}
|
|
539
|
+
logger.endSubStep('Config file updated');
|
|
540
|
+
}
|
|
541
|
+
catch (_c) {
|
|
542
|
+
outro(`Config file update failed`);
|
|
543
|
+
exit(1);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
export const initGit = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
547
|
+
var _a;
|
|
548
|
+
const frameworkConfig = getFrameworkConfig(initParams.framework || '');
|
|
549
|
+
if ((frameworkConfig === null || frameworkConfig === void 0 ? void 0 : frameworkConfig.useGit) === false) {
|
|
550
|
+
log.step('Git skipped');
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
const gitInstalled = yield isGitInstalled();
|
|
554
|
+
if (!gitInstalled) {
|
|
555
|
+
log.step('You have not installed Git, Git skipped');
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
if (!initParams.git) {
|
|
559
|
+
const initGit = (yield promptParameter({
|
|
560
|
+
type: 'confirm',
|
|
561
|
+
question: t('init_git').d('Do you want to init git in your project?'),
|
|
562
|
+
label: 'Init git',
|
|
563
|
+
defaultValue: false
|
|
564
|
+
}));
|
|
565
|
+
initParams.git = initGit;
|
|
566
|
+
}
|
|
567
|
+
if (initParams.git) {
|
|
568
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
569
|
+
const res = yield execCommand(['git', 'init'], {
|
|
570
|
+
cwd: targetPath,
|
|
571
|
+
silent: true,
|
|
572
|
+
startText: 'Initializing git',
|
|
573
|
+
doneText: 'Git initialized'
|
|
574
|
+
});
|
|
575
|
+
if (!res.success) {
|
|
576
|
+
outro(`Git initialization failed`);
|
|
577
|
+
exit(1);
|
|
578
|
+
}
|
|
579
|
+
// Ensure .gitignore exists and has sensible defaults
|
|
580
|
+
yield ensureGitignore(targetPath, (_a = frameworkConfig === null || frameworkConfig === void 0 ? void 0 : frameworkConfig.assets) === null || _a === void 0 ? void 0 : _a.directory);
|
|
581
|
+
}
|
|
582
|
+
return true;
|
|
583
|
+
});
|
|
584
|
+
export function getGitVersion() {
|
|
585
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
586
|
+
try {
|
|
587
|
+
let stdout = yield execCommand(['git', '--version'], {
|
|
588
|
+
useSpinner: false,
|
|
589
|
+
silent: true,
|
|
590
|
+
captureOutput: true
|
|
591
|
+
});
|
|
592
|
+
const gitVersion = stdout.stdout.replace(/^git\s+version\s+/, '');
|
|
593
|
+
return gitVersion;
|
|
594
|
+
}
|
|
595
|
+
catch (_a) {
|
|
596
|
+
log.error('Failed to get Git version');
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
export function isGitInstalled() {
|
|
602
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
603
|
+
return (yield getGitVersion()) !== '' && (yield getGitVersion()) !== null;
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Create or update .gitignore in project root with sensible defaults.
|
|
608
|
+
* - Preserves existing entries and comments
|
|
609
|
+
* - Avoids duplicates
|
|
610
|
+
* - Adds framework assets directory if provided
|
|
611
|
+
*/
|
|
612
|
+
function ensureGitignore(projectRoot, assetsDirectory) {
|
|
613
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
614
|
+
try {
|
|
615
|
+
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
616
|
+
const defaults = [
|
|
617
|
+
'# Logs',
|
|
618
|
+
'logs',
|
|
619
|
+
'*.log',
|
|
620
|
+
'npm-debug.log*',
|
|
621
|
+
'yarn-debug.log*',
|
|
622
|
+
'yarn-error.log*',
|
|
623
|
+
'pnpm-debug.log*',
|
|
624
|
+
'',
|
|
625
|
+
'# Node modules',
|
|
626
|
+
'node_modules/',
|
|
627
|
+
'',
|
|
628
|
+
'# Build output',
|
|
629
|
+
'dist/',
|
|
630
|
+
'build/',
|
|
631
|
+
'out/',
|
|
632
|
+
'.next/',
|
|
633
|
+
'.nuxt/',
|
|
634
|
+
'coverage/',
|
|
635
|
+
'.vite/',
|
|
636
|
+
'',
|
|
637
|
+
'# Env files',
|
|
638
|
+
'.env',
|
|
639
|
+
'.env.local',
|
|
640
|
+
'.env.development.local',
|
|
641
|
+
'.env.test.local',
|
|
642
|
+
'.env.production.local',
|
|
643
|
+
'',
|
|
644
|
+
'# IDE/editor',
|
|
645
|
+
'.DS_Store',
|
|
646
|
+
'.idea/',
|
|
647
|
+
'.vscode/',
|
|
648
|
+
'',
|
|
649
|
+
'# Misc caches',
|
|
650
|
+
'.eslintcache',
|
|
651
|
+
'.parcel-cache/',
|
|
652
|
+
'.turbo/',
|
|
653
|
+
'.cache/'
|
|
654
|
+
];
|
|
655
|
+
// Include assets directory if provided and not a common default
|
|
656
|
+
if (assetsDirectory &&
|
|
657
|
+
!['dist', 'build', 'out'].includes(assetsDirectory.replace(/\/$/, ''))) {
|
|
658
|
+
defaults.push('', '# Project assets output', `${assetsDirectory}/`);
|
|
659
|
+
}
|
|
660
|
+
let existingContent = '';
|
|
661
|
+
if (fs.existsSync(gitignorePath)) {
|
|
662
|
+
existingContent = fs.readFileSync(gitignorePath, 'utf-8');
|
|
663
|
+
}
|
|
664
|
+
const existingLines = new Set(existingContent.split(/\r?\n/).map((l) => l.trimEnd()));
|
|
665
|
+
const toAppend = [];
|
|
666
|
+
for (const line of defaults) {
|
|
667
|
+
if (!existingLines.has(line)) {
|
|
668
|
+
toAppend.push(line);
|
|
669
|
+
existingLines.add(line);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
// If nothing to add, keep as is
|
|
673
|
+
if (!toAppend.length)
|
|
674
|
+
return;
|
|
675
|
+
const newContent = existingContent
|
|
676
|
+
? `${existingContent.replace(/\n$/, '')}\n${toAppend.join('\n')}\n`
|
|
677
|
+
: `${toAppend.join('\n')}\n`;
|
|
678
|
+
fs.writeFileSync(gitignorePath, newContent, 'utf-8');
|
|
679
|
+
}
|
|
680
|
+
catch (_a) {
|
|
681
|
+
// Do not fail init due to .gitignore issues
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
export const buildProject = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
686
|
+
if (initParams.template) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
690
|
+
const res = yield execCommand(['npm', 'run', 'build'], {
|
|
691
|
+
useSpinner: true,
|
|
692
|
+
silent: true,
|
|
693
|
+
startText: 'Building project',
|
|
694
|
+
doneText: 'Project built',
|
|
695
|
+
cwd: targetPath
|
|
696
|
+
});
|
|
697
|
+
if (!res.success) {
|
|
698
|
+
outro(`Build project failed`);
|
|
699
|
+
exit(1);
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
export function prepareTemplateItems() {
|
|
703
|
+
var _a;
|
|
704
|
+
const templateInstanceList = getTemplateInstances(templateHubPath);
|
|
705
|
+
const templateConfig = getTemplatesConfig();
|
|
706
|
+
const cliConfig = getCliConfig();
|
|
707
|
+
const lang = (_a = cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.lang) !== null && _a !== void 0 ? _a : 'en';
|
|
708
|
+
return transferTemplatesToSelectItem(templateConfig, templateInstanceList, lang);
|
|
709
|
+
}
|
|
710
|
+
export const deployProject = (initParams) => __awaiter(void 0, void 0, void 0, function* () {
|
|
711
|
+
if (!initParams.deploy) {
|
|
712
|
+
log.step('Deploy project skipped');
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
const targetPath = path.join(process.cwd(), initParams.name);
|
|
716
|
+
const res = yield commitAndDeployVersion(initParams.name, undefined, undefined, 'Init project', targetPath, 'all');
|
|
717
|
+
if (!res) {
|
|
718
|
+
outro(`Deploy project failed`);
|
|
719
|
+
exit(1);
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
export function initializeProject(selectedTemplatePath, name) {
|
|
723
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
724
|
+
const selectTemplate = new Template(selectedTemplatePath, name);
|
|
725
|
+
const projectConfig = getProjectConfig(selectedTemplatePath);
|
|
726
|
+
if (!projectConfig) {
|
|
727
|
+
logger.notInProject();
|
|
728
|
+
return null;
|
|
729
|
+
}
|
|
730
|
+
const targetPath = path.join(process.cwd(), name);
|
|
731
|
+
if (fs.existsSync(targetPath)) {
|
|
732
|
+
logger.block();
|
|
733
|
+
logger.tree([
|
|
734
|
+
`${chalk.bgRed(' ERROR ')} ${chalk.bold.red(t('init_abort').d('Initialization aborted'))}`,
|
|
735
|
+
`${chalk.gray(t('reason').d('Reason:'))} ${chalk.red(t('dir_already_exists').d('Target directory already exists'))}`,
|
|
736
|
+
`${chalk.gray(t('path').d('Path:'))} ${chalk.cyan(targetPath)}`,
|
|
737
|
+
chalk.gray(t('try').d('Try one of the following:')),
|
|
738
|
+
`- ${chalk.white(t('try_diff_name').d('Choose a different project name'))}`,
|
|
739
|
+
`- ${chalk.white(t('try_remove').d('Remove the directory:'))} ${chalk.yellow(`rm -rf "${name}”`)}`,
|
|
740
|
+
`- ${chalk.white(t('try_another_dir').d('Run the command in another directory'))}`
|
|
741
|
+
]);
|
|
742
|
+
logger.block();
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
yield fs.copy(selectedTemplatePath, targetPath);
|
|
746
|
+
projectConfig.name = name;
|
|
747
|
+
yield updateProjectConfigFile(projectConfig, targetPath);
|
|
748
|
+
yield preInstallDependencies(targetPath);
|
|
749
|
+
return { template: selectTemplate, targetPath };
|
|
750
|
+
});
|
|
751
|
+
}
|