@lazycatcloud/lzc-cli 1.3.11 → 1.3.13
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/changelog.md +24 -0
- package/lib/app/apkshell.js +37 -40
- package/lib/app/index.js +187 -179
- package/lib/app/lpk_build.js +341 -358
- package/lib/app/lpk_create.js +135 -155
- package/lib/app/lpk_create_generator.js +74 -66
- package/lib/app/lpk_devshell.js +444 -533
- package/lib/app/lpk_devshell_docker.js +48 -47
- package/lib/app/lpk_installer.js +119 -123
- package/lib/appstore/index.js +205 -209
- package/lib/appstore/login.js +146 -143
- package/lib/appstore/prePublish.js +101 -100
- package/lib/appstore/publish.js +254 -256
- package/lib/box/index.js +82 -77
- package/lib/config/env.js +2 -2
- package/lib/config/index.js +58 -54
- package/lib/debug_bridge.js +280 -320
- package/lib/docker/index.js +84 -86
- package/lib/i18n/README.md +25 -0
- package/lib/i18n/index.js +37 -0
- package/lib/i18n/locales/en/translation.json +251 -0
- package/lib/i18n/locales/zh/translation.json +251 -0
- package/lib/shellapi.js +122 -146
- package/lib/utils.js +539 -553
- package/package.json +6 -8
- package/scripts/cli.js +81 -77
- package/scripts/lzc-docker-compose.js +34 -33
- package/scripts/lzc-docker.js +34 -33
package/lib/app/lpk_create.js
CHANGED
|
@@ -1,129 +1,110 @@
|
|
|
1
|
-
import logger from
|
|
2
|
-
import inquirer from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
fakeLoadManifestYml
|
|
13
|
-
} from "../utils.js"
|
|
14
|
-
import path from "node:path"
|
|
15
|
-
import { TemplateConfig } from "./lpk_create_generator.js"
|
|
16
|
-
import fs from "node:fs"
|
|
17
|
-
import yaml from "js-yaml"
|
|
18
|
-
import chalk from "chalk"
|
|
19
|
-
let fsPromises = fs.promises
|
|
1
|
+
import logger from 'loglevel';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { contextDirname, loadFromYaml, envTemplateFile, ensureDir, ensureDirectoryExists, dumpToYaml, isFileExist, isValidAppId, fakeLoadManifestYml } from '../utils.js';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { TemplateConfig } from './lpk_create_generator.js';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import yaml from 'js-yaml';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { t } from '../i18n/index.js';
|
|
10
|
+
|
|
11
|
+
let fsPromises = fs.promises;
|
|
20
12
|
|
|
21
13
|
export class LpkManifest {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
subdomain: appId
|
|
80
|
-
}
|
|
81
|
-
return answer
|
|
82
|
-
}
|
|
14
|
+
constructor(defaultAppID) {
|
|
15
|
+
this.pwd = contextDirname(import.meta.url);
|
|
16
|
+
this.manifest = {};
|
|
17
|
+
this.defaultAppID = defaultAppID;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async init(manifestFilePath, askInfo = false) {
|
|
21
|
+
if (!manifestFilePath) {
|
|
22
|
+
manifestFilePath = path.join(this.pwd, '..', '..', 'template', '_lpk', 'manifest.yml.in');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (askInfo) {
|
|
26
|
+
let answer = await this.askLpkInfo();
|
|
27
|
+
this.manifest = yaml.load(await envTemplateFile(manifestFilePath, answer));
|
|
28
|
+
} else {
|
|
29
|
+
try {
|
|
30
|
+
this.manifest = loadFromYaml(manifestFilePath);
|
|
31
|
+
} catch (err) {
|
|
32
|
+
this.manifest = fakeLoadManifestYml(manifestFilePath);
|
|
33
|
+
this.excpManifest = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async create(outputDir) {
|
|
39
|
+
let outputFilePath = path.join(outputDir, 'lzc-manifest.yml');
|
|
40
|
+
logger.debug(`create file ${outputFilePath}`);
|
|
41
|
+
ensureDir(outputFilePath);
|
|
42
|
+
return dumpToYaml(this.manifest, outputFilePath);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async askLpkInfo() {
|
|
46
|
+
const { appId } = await inquirer.prompt([
|
|
47
|
+
{
|
|
48
|
+
type: 'input',
|
|
49
|
+
name: 'appId',
|
|
50
|
+
message: t('lzc_cli.lib.app.lpk_create.ask_lpk_info_message', `请输入应用ID,例如 app-demo1`),
|
|
51
|
+
default: this.defaultAppID,
|
|
52
|
+
validate: (input) => {
|
|
53
|
+
if (isValidAppId(input)) {
|
|
54
|
+
return true;
|
|
55
|
+
} else {
|
|
56
|
+
return t(
|
|
57
|
+
'lzc_cli.lib.app.lpk_create.ask_lpk_info_validate_fail',
|
|
58
|
+
`允许小写字母或数字或-的组合,但不以数字开头,且不能以 - 开头或结束,也不能有连续的短横线 --`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
const answer = {
|
|
65
|
+
name: appId,
|
|
66
|
+
package: `cloud.lazycat.app.${appId}`,
|
|
67
|
+
subdomain: appId,
|
|
68
|
+
};
|
|
69
|
+
return answer;
|
|
70
|
+
}
|
|
83
71
|
}
|
|
84
72
|
|
|
85
73
|
export class TemplateInit {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const templatePath = isFileExist(typeTemplatePath) ? typeTemplatePath : ""
|
|
108
|
-
await this.lpkManifest.init(templatePath, true)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async create() {
|
|
112
|
-
await this.lpkManifest.create(path.resolve(this.cwd, this.name))
|
|
113
|
-
}
|
|
74
|
+
constructor(cwd, name, type) {
|
|
75
|
+
this.cwd = cwd;
|
|
76
|
+
this.name = name;
|
|
77
|
+
this.type = type;
|
|
78
|
+
this.lpkManifest = new LpkManifest(name);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async init() {
|
|
82
|
+
if (!this.type) {
|
|
83
|
+
this.type = await chooseTemplate();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 优先使用模板项目自定义的模板文件
|
|
87
|
+
const typeTemplatePath = path.join(contextDirname(import.meta.url), '..', '..', 'template', '_lpk', `${this.type}.manifest.yml.in`);
|
|
88
|
+
const templatePath = isFileExist(typeTemplatePath) ? typeTemplatePath : '';
|
|
89
|
+
await this.lpkManifest.init(templatePath, true);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async create() {
|
|
93
|
+
await this.lpkManifest.create(path.resolve(this.cwd, this.name));
|
|
94
|
+
}
|
|
114
95
|
}
|
|
115
96
|
|
|
116
97
|
export async function chooseTemplate() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
98
|
+
return (
|
|
99
|
+
await inquirer.prompt([
|
|
100
|
+
{
|
|
101
|
+
name: 'type',
|
|
102
|
+
message: t('lzc_cli.lib.app.lpk_create.choose_template_message', '选择项目构建模板'),
|
|
103
|
+
type: 'list',
|
|
104
|
+
choices: ['vue3'],
|
|
105
|
+
},
|
|
106
|
+
])
|
|
107
|
+
)['type'];
|
|
127
108
|
}
|
|
128
109
|
|
|
129
110
|
// 创建一个应用
|
|
@@ -131,43 +112,42 @@ export async function chooseTemplate() {
|
|
|
131
112
|
// - 根据 lpk manifest 模板中所需要的字段填充manifest
|
|
132
113
|
// - 调用模板的hook
|
|
133
114
|
class LpkCreate {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
115
|
+
constructor(name, cwd = process.cwd()) {
|
|
116
|
+
this.name = name;
|
|
117
|
+
this.cwd = cwd ?? process.cwd();
|
|
118
|
+
this.appDir = path.resolve(this.cwd, this.name);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async init() {
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async exec() {
|
|
126
|
+
const type = await chooseTemplate();
|
|
127
|
+
const template = new TemplateInit(this.cwd, this.name, type);
|
|
128
|
+
await template.init();
|
|
129
|
+
|
|
130
|
+
console.log(chalk.green(t('lzc_cli.lib.app.lpk_create.exec_init_project_tips', `✨ 初始化项目 {{name}}`, { name: this.name })));
|
|
131
|
+
const { isExists, renamedFileName } = ensureDirectoryExists(this.appDir, true);
|
|
132
|
+
if (isExists && renamedFileName) {
|
|
133
|
+
console.warn(
|
|
134
|
+
chalk.yellow(
|
|
135
|
+
t('lzc_cli.lib.app.lpk_create.exec_init_project_name_exist_tips', `! 检测到相同目录,已自动将旧目录重命名为 {{renamedFileName}}`, {
|
|
136
|
+
renamedFileName,
|
|
137
|
+
}),
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
await TemplateConfig[type].build(path.resolve(this.cwd, this.name));
|
|
142
|
+
|
|
143
|
+
console.log(chalk.green(t('lzc_cli.lib.app.lpk_create.exec_init_project_success_tips', `✨ 初始化懒猫云应用`)));
|
|
144
|
+
await TemplateConfig[type].after(this.name, this.cwd);
|
|
145
|
+
|
|
146
|
+
await template.create();
|
|
147
|
+
}
|
|
168
148
|
}
|
|
169
149
|
|
|
170
150
|
export default async (name, cwd = process.cwd()) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
151
|
+
const lpk = await new LpkCreate(name, cwd).init();
|
|
152
|
+
return await lpk.exec();
|
|
153
|
+
};
|
|
@@ -1,91 +1,99 @@
|
|
|
1
|
-
import glob from
|
|
2
|
-
import path from
|
|
3
|
-
import fs from
|
|
4
|
-
import { isBinaryFileSync } from
|
|
5
|
-
import { contextDirname
|
|
6
|
-
import chalk from
|
|
7
|
-
import spawn from "cross-spawn"
|
|
8
|
-
import logger from
|
|
1
|
+
import glob from 'fast-glob';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { isBinaryFileSync } from 'isbinaryfile';
|
|
5
|
+
import { contextDirname } from '../utils.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
// import spawn from "cross-spawn"
|
|
8
|
+
import logger from 'loglevel';
|
|
9
|
+
import { t } from '../i18n/index.js';
|
|
9
10
|
|
|
10
|
-
const __dirname = contextDirname(import.meta.url)
|
|
11
|
+
const __dirname = contextDirname(import.meta.url);
|
|
11
12
|
|
|
12
|
-
async function loadFiles(dirPath, prefix =
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
async function loadFiles(dirPath, prefix = '') {
|
|
14
|
+
const templateRoot = path.join(__dirname, '..', '..', 'template');
|
|
15
|
+
const templateDir = path.join(templateRoot, dirPath);
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const _files = await glob(['**/*', '**/.*', '.*'], { cwd: templateDir });
|
|
18
|
+
let content;
|
|
19
|
+
let files = {};
|
|
20
|
+
for (let p of _files) {
|
|
21
|
+
const sourcePath = path.join(templateDir, p);
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
const statInfo = fs.statSync(sourcePath);
|
|
24
|
+
const mode = statInfo.mode;
|
|
25
|
+
if (isBinaryFileSync(sourcePath)) {
|
|
26
|
+
content = fs.readFileSync(sourcePath);
|
|
27
|
+
} else {
|
|
28
|
+
content = fs.readFileSync(sourcePath, 'utf8');
|
|
29
|
+
}
|
|
30
|
+
// change _ prefix file into dot file
|
|
31
|
+
if (p.startsWith('_')) {
|
|
32
|
+
p = p.replace('_', '.');
|
|
33
|
+
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
files[path.join(prefix, p)] = {
|
|
36
|
+
content,
|
|
37
|
+
mode,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return files;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
function writeFileTree(target, files) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
Object.keys(files).forEach((p) => {
|
|
45
|
+
const filePath = path.join(target, p);
|
|
46
|
+
if (!fs.existsSync(path.dirname(filePath))) {
|
|
47
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
logger.debug(t('lzc_cli.lib.app.lpk_create_generator.write_file_tree_create_file', `创建文件 {{filePath}}`, { filePath }));
|
|
50
|
+
fs.writeFileSync(filePath, files[p].content, { mode: files[p].mode });
|
|
51
|
+
});
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export async function generate(type, to, opts = {}) {
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
const files = await loadFiles(type, opts.prefix);
|
|
56
|
+
writeFileTree(to, files);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
function appCreateSuccessTip(name) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
console.log(
|
|
61
|
+
chalk.green(
|
|
62
|
+
t(
|
|
63
|
+
'lzc_cli.lib.app.lpk_create_generator.app_create_success_tip',
|
|
64
|
+
`
|
|
62
65
|
✨ 懒猫微服应用已创建成功 !
|
|
63
66
|
✨ 进行下面步骤后即可进入容器开发
|
|
64
|
-
cd
|
|
67
|
+
cd {{name}}
|
|
65
68
|
lzc-cli project devshell
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
`,
|
|
70
|
+
{ name },
|
|
71
|
+
).trim(),
|
|
72
|
+
),
|
|
73
|
+
);
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
export const TemplateConfig = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
vue3: {
|
|
78
|
+
build: async (to, option) => {
|
|
79
|
+
await generate('vue', to, option);
|
|
80
|
+
},
|
|
81
|
+
after: async function (name) {
|
|
82
|
+
appCreateSuccessTip(name);
|
|
83
|
+
console.log(
|
|
84
|
+
chalk.green(
|
|
85
|
+
t(
|
|
86
|
+
'lzc_cli.lib.app.lpk_create_generator.template_config_vue3_green',
|
|
87
|
+
`
|
|
81
88
|
⚙️ 进入应用容器后执行下面命令:
|
|
82
89
|
npm install
|
|
83
90
|
npm run dev
|
|
84
91
|
🚀 启动应用:
|
|
85
92
|
进入微服客户端启动器页面点击应用图标来测试应用
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
93
|
+
`,
|
|
94
|
+
).trim(),
|
|
95
|
+
),
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|