@lazycatcloud/lzc-cli 2.0.0-pre.0 → 2.0.0-pre.2
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 +46 -7
- package/changelog.md +56 -19
- package/lib/app/apkshell.js +7 -44
- package/lib/app/index.js +5 -1
- package/lib/app/lpk_build.js +266 -56
- package/lib/app/lpk_build_images.js +424 -229
- package/lib/app/lpk_build_images_local.js +425 -0
- package/lib/app/lpk_build_images_pack_local.js +409 -0
- package/lib/app/lpk_create.js +158 -83
- package/lib/app/lpk_create_generator.js +35 -42
- package/lib/app/lpk_devshell.js +6 -2
- package/lib/app/lpk_installer.js +4 -3
- package/lib/app/manifest_build.js +259 -0
- package/lib/app/project_cp.js +5 -10
- package/lib/app/project_deploy.js +80 -11
- package/lib/app/project_exec.js +48 -11
- package/lib/app/project_info.js +59 -59
- package/lib/app/project_log.js +5 -10
- package/lib/app/project_runtime.js +113 -18
- package/lib/app/project_start.js +6 -11
- package/lib/app/project_sync.js +499 -0
- package/lib/appstore/apkshell.js +50 -0
- package/lib/appstore/publish.js +54 -15
- package/lib/build_remote.js +0 -1
- package/lib/config/index.js +1 -1
- package/lib/debug_bridge.js +217 -47
- package/lib/i18n/locales/en/translation.json +262 -262
- package/lib/i18n/locales/zh/translation.json +262 -262
- package/lib/lpk/core.js +2 -1
- package/lib/migrate/index.js +52 -0
- package/lib/package_info.js +135 -0
- package/lib/shellapi.js +35 -1
- package/lib/sig/core.js +2 -2
- package/lib/utils.js +92 -15
- package/package.json +89 -89
- package/scripts/cli.js +2 -0
- package/scripts/smoke/frontend-dev-entry.mjs +104 -0
- package/scripts/smoke/template-project.mjs +311 -0
- package/template/_lpk/README.md +6 -3
- package/template/_lpk/gui-vnc.manifest.yml.in +0 -9
- package/template/_lpk/hello-vue.manifest.yml.in +38 -0
- package/template/_lpk/manifest.yml.in +0 -9
- package/template/_lpk/package.yml.in +7 -0
- package/template/_lpk/todolist-golang.manifest.yml.in +23 -9
- package/template/_lpk/todolist-java.manifest.yml.in +23 -9
- package/template/_lpk/todolist-python.manifest.yml.in +31 -9
- package/template/_lpk/todolist-serverless.manifest.yml.in +38 -0
- package/template/blank/lzc-build.dev.yml +4 -0
- package/template/blank/lzc-build.yml +0 -2
- package/template/blank/lzc-manifest.yml +3 -12
- package/template/blank/package.yml +7 -0
- package/template/golang/Dockerfile +1 -1
- package/template/golang/Dockerfile.dev +20 -0
- package/template/golang/README.md +22 -11
- package/template/golang/_lzcdevignore +21 -0
- package/template/golang/lzc-build.dev.yml +12 -0
- package/template/golang/lzc-build.yml +0 -5
- package/template/golang/main.go +1 -1
- package/template/golang/manifest.dev.page.js +24 -0
- package/template/golang/run.sh +7 -0
- package/template/gui-vnc/README.md +5 -1
- package/template/gui-vnc/lzc-build.dev.yml +4 -0
- package/template/gui-vnc/lzc-build.yml +0 -5
- package/template/python/Dockerfile +2 -2
- package/template/python/Dockerfile.dev +18 -0
- package/template/python/README.md +28 -11
- package/template/python/_lzcdevignore +21 -0
- package/template/python/app.py +1 -1
- package/template/python/lzc-build.dev.yml +12 -0
- package/template/python/lzc-build.yml +0 -5
- package/template/python/manifest.dev.page.js +25 -0
- package/template/python/run.sh +12 -1
- package/template/springboot/Dockerfile +1 -1
- package/template/springboot/Dockerfile.dev +20 -0
- package/template/springboot/README.md +22 -11
- package/template/springboot/_lzcdevignore +21 -0
- package/template/springboot/lzc-build.dev.yml +12 -0
- package/template/springboot/lzc-build.yml +0 -5
- package/template/springboot/manifest.dev.page.js +24 -0
- package/template/springboot/run.sh +7 -0
- package/template/vue/README.md +14 -27
- package/template/vue/_gitignore +0 -1
- package/template/vue/lzc-build.dev.yml +7 -0
- package/template/vue/lzc-build.yml +0 -2
- package/template/vue/manifest.dev.page.js +50 -0
- package/template/vue/src/App.vue +1 -1
- package/template/vue-minidb/README.md +11 -19
- package/template/vue-minidb/_gitignore +0 -1
- package/template/vue-minidb/lzc-build.dev.yml +7 -0
- package/template/vue-minidb/lzc-build.yml +0 -2
- package/template/vue-minidb/manifest.dev.page.js +50 -0
- package/template/blank/_gitignore +0 -1
package/lib/app/lpk_create.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logger from 'loglevel';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
|
-
import { contextDirname,
|
|
3
|
+
import { contextDirname, ensureDir, ensureDirectoryExists, dumpToYaml, isFileExist, isValidAppId, envsubstr } from '../utils.js';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { TemplateConfig } from './lpk_create_generator.js';
|
|
6
6
|
import fs from 'node:fs';
|
|
@@ -8,103 +8,113 @@ import yaml from 'js-yaml';
|
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import { t } from '../i18n/index.js';
|
|
10
10
|
|
|
11
|
-
let fsPromises = fs.promises;
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
{
|
|
20
|
-
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_java',
|
|
21
|
-
defaultText: 'todolist-java (Java Todo示例)',
|
|
22
|
-
value: 'todolist-java',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_python',
|
|
26
|
-
defaultText: 'todolist-python (Python Todo示例)',
|
|
27
|
-
value: 'todolist-python',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_golang',
|
|
31
|
-
defaultText: 'todolist-golang (Golang Todo示例)',
|
|
32
|
-
value: 'todolist-golang',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_gui_vnc',
|
|
36
|
-
defaultText: 'gui-vnc (GUI VNC Embed示例)',
|
|
37
|
-
value: 'gui-vnc',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_serverless',
|
|
41
|
-
defaultText: 'todolist-serverless (Serverless Todo示例)',
|
|
42
|
-
value: 'todolist-serverless',
|
|
43
|
-
},
|
|
44
|
-
];
|
|
12
|
+
function fakeLoadManifestText(text) {
|
|
13
|
+
let obj = {
|
|
14
|
+
application: {
|
|
15
|
+
subdomain: undefined,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
45
18
|
|
|
46
|
-
|
|
47
|
-
|
|
19
|
+
const normalizeValue = (value) => {
|
|
20
|
+
const commentIndex = value.indexOf(' #');
|
|
21
|
+
if (commentIndex >= 0) {
|
|
22
|
+
value = value.slice(0, commentIndex);
|
|
23
|
+
}
|
|
24
|
+
return value.trim();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
String(text ?? '').split('\n').forEach((rawLine) => {
|
|
28
|
+
const line = rawLine.trim();
|
|
29
|
+
const arr = line.split(':');
|
|
30
|
+
if (arr.length !== 2) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
let [key, value] = arr;
|
|
34
|
+
value = normalizeValue(value);
|
|
35
|
+
if (!obj.package && key === 'package') {
|
|
36
|
+
obj.package = value;
|
|
37
|
+
}
|
|
38
|
+
if (!obj.application.subdomain && key === 'subdomain') {
|
|
39
|
+
obj.application.subdomain = value;
|
|
40
|
+
}
|
|
41
|
+
if (!obj.version && key === 'version') {
|
|
42
|
+
obj.version = value;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return obj;
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
async function renderTemplateText(templateFilePath, templateVars) {
|
|
49
|
+
const templateText = fs.readFileSync(templateFilePath, 'utf-8');
|
|
50
|
+
return await envsubstr(templateText, {
|
|
51
|
+
options: {
|
|
52
|
+
envs: Object.entries(templateVars).map(([key, value]) => ({
|
|
53
|
+
name: key.replace(/-/g, '_'),
|
|
54
|
+
value,
|
|
55
|
+
})),
|
|
56
|
+
syntax: 'default',
|
|
57
|
+
protect: false,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function loadTemplateYaml(text, fallbackLoader) {
|
|
63
|
+
try {
|
|
64
|
+
return {
|
|
65
|
+
data: yaml.load(text),
|
|
66
|
+
excp: false,
|
|
67
|
+
};
|
|
68
|
+
} catch {
|
|
69
|
+
return {
|
|
70
|
+
data: fallbackLoader(text),
|
|
71
|
+
excp: true,
|
|
72
|
+
};
|
|
58
73
|
}
|
|
59
|
-
return type;
|
|
60
74
|
}
|
|
61
75
|
|
|
62
|
-
export class
|
|
63
|
-
constructor(defaultAppID) {
|
|
76
|
+
export class LpkTemplateFile {
|
|
77
|
+
constructor(defaultAppID, outputFileName, fallbackLoader = (text) => yaml.load(text)) {
|
|
64
78
|
this.pwd = contextDirname(import.meta.url);
|
|
65
|
-
this.manifest = {};
|
|
66
|
-
this.manifestText = '';
|
|
67
79
|
this.defaultAppID = defaultAppID;
|
|
80
|
+
this.outputFileName = outputFileName;
|
|
81
|
+
this.fallbackLoader = fallbackLoader;
|
|
82
|
+
this.data = {};
|
|
83
|
+
this.text = '';
|
|
84
|
+
this.excpTemplate = false;
|
|
68
85
|
}
|
|
69
86
|
|
|
70
|
-
async init(
|
|
71
|
-
if (!
|
|
72
|
-
|
|
87
|
+
async init(templateFilePath, askInfo = false, templateVars = null) {
|
|
88
|
+
if (!templateFilePath) {
|
|
89
|
+
throw new Error(`template file is required for ${this.outputFileName}`);
|
|
73
90
|
}
|
|
74
91
|
|
|
92
|
+
let vars = templateVars;
|
|
75
93
|
if (askInfo) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
value,
|
|
83
|
-
})),
|
|
84
|
-
syntax: 'default',
|
|
85
|
-
protect: false,
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
this.manifest = yaml.load(this.manifestText);
|
|
89
|
-
} else {
|
|
90
|
-
try {
|
|
91
|
-
this.manifest = loadFromYaml(manifestFilePath);
|
|
92
|
-
} catch (err) {
|
|
93
|
-
this.manifest = fakeLoadManifestYml(manifestFilePath);
|
|
94
|
-
this.excpManifest = true;
|
|
95
|
-
}
|
|
94
|
+
vars = vars || (await this.askLpkInfo());
|
|
95
|
+
this.text = await renderTemplateText(templateFilePath, vars);
|
|
96
|
+
const loaded = loadTemplateYaml(this.text, this.fallbackLoader);
|
|
97
|
+
this.data = loaded.data;
|
|
98
|
+
this.excpTemplate = loaded.excp;
|
|
99
|
+
return vars;
|
|
96
100
|
}
|
|
101
|
+
|
|
102
|
+
const templateText = fs.readFileSync(templateFilePath, 'utf-8');
|
|
103
|
+
const loaded = loadTemplateYaml(templateText, this.fallbackLoader);
|
|
104
|
+
this.data = loaded.data;
|
|
105
|
+
this.excpTemplate = loaded.excp;
|
|
106
|
+
return vars;
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
async create(outputDir) {
|
|
100
|
-
let outputFilePath = path.join(outputDir,
|
|
110
|
+
let outputFilePath = path.join(outputDir, this.outputFileName);
|
|
101
111
|
logger.debug(`create file ${outputFilePath}`);
|
|
102
112
|
ensureDir(outputFilePath);
|
|
103
|
-
if (this.
|
|
104
|
-
fs.writeFileSync(outputFilePath, this.
|
|
113
|
+
if (this.text) {
|
|
114
|
+
fs.writeFileSync(outputFilePath, this.text);
|
|
105
115
|
return;
|
|
106
116
|
}
|
|
107
|
-
return dumpToYaml(this.
|
|
117
|
+
return dumpToYaml(this.data, outputFilePath);
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
async askLpkInfo() {
|
|
@@ -126,34 +136,99 @@ export class LpkManifest {
|
|
|
126
136
|
},
|
|
127
137
|
},
|
|
128
138
|
]);
|
|
129
|
-
|
|
139
|
+
return {
|
|
130
140
|
name: appId,
|
|
131
141
|
package: `cloud.lazycat.app.${appId}`,
|
|
132
142
|
subdomain: appId,
|
|
133
143
|
};
|
|
134
|
-
return answer;
|
|
135
144
|
}
|
|
136
145
|
}
|
|
137
146
|
|
|
147
|
+
export class LpkManifest extends LpkTemplateFile {
|
|
148
|
+
constructor(defaultAppID) {
|
|
149
|
+
super(defaultAppID, 'lzc-manifest.yml', fakeLoadManifestText);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export class LpkPackageFile extends LpkTemplateFile {
|
|
154
|
+
constructor(defaultAppID) {
|
|
155
|
+
super(defaultAppID, 'package.yml');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const PROJECT_TEMPLATE_OPTIONS = [
|
|
160
|
+
{
|
|
161
|
+
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_hello_vue',
|
|
162
|
+
defaultText: 'hello-vue (Vue基础模板)',
|
|
163
|
+
value: 'hello-vue',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_java',
|
|
167
|
+
defaultText: 'todolist-java (Java Todo示例)',
|
|
168
|
+
value: 'todolist-java',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_python',
|
|
172
|
+
defaultText: 'todolist-python (Python Todo示例)',
|
|
173
|
+
value: 'todolist-python',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_golang',
|
|
177
|
+
defaultText: 'todolist-golang (Golang Todo示例)',
|
|
178
|
+
value: 'todolist-golang',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_gui_vnc',
|
|
182
|
+
defaultText: 'gui-vnc (GUI VNC Embed示例)',
|
|
183
|
+
value: 'gui-vnc',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
i18nKey: 'lzc_cli.lib.app.lpk_create.template_option_todolist_serverless',
|
|
187
|
+
defaultText: 'todolist-serverless (Serverless Todo示例)',
|
|
188
|
+
value: 'todolist-serverless',
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
export function listProjectTemplateValues() {
|
|
193
|
+
return PROJECT_TEMPLATE_OPTIONS.map((item) => item.value);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function normalizeTemplateType(rawType) {
|
|
197
|
+
const type = String(rawType ?? '').trim();
|
|
198
|
+
if (!type) {
|
|
199
|
+
return '';
|
|
200
|
+
}
|
|
201
|
+
const allowedTypes = listProjectTemplateValues();
|
|
202
|
+
if (!allowedTypes.includes(type)) {
|
|
203
|
+
throw new Error(`Unsupported template "${type}". Available templates: ${allowedTypes.join(', ')}`);
|
|
204
|
+
}
|
|
205
|
+
return type;
|
|
206
|
+
}
|
|
207
|
+
|
|
138
208
|
export class TemplateInit {
|
|
139
209
|
constructor(cwd, name, type) {
|
|
140
210
|
this.cwd = cwd;
|
|
141
211
|
this.name = name;
|
|
142
212
|
this.type = normalizeTemplateType(type);
|
|
143
213
|
this.lpkManifest = new LpkManifest(name);
|
|
214
|
+
this.lpkPackageFile = new LpkPackageFile(name);
|
|
144
215
|
}
|
|
145
216
|
|
|
146
217
|
async init() {
|
|
147
218
|
this.type = await chooseTemplate(this.type);
|
|
148
219
|
|
|
149
|
-
|
|
150
|
-
const typeTemplatePath = path.join(
|
|
151
|
-
const
|
|
152
|
-
|
|
220
|
+
const templateRoot = path.join(contextDirname(import.meta.url), '..', '..', 'template', '_lpk');
|
|
221
|
+
const typeTemplatePath = path.join(templateRoot, `${this.type}.manifest.yml.in`);
|
|
222
|
+
const manifestTemplatePath = isFileExist(typeTemplatePath) ? typeTemplatePath : path.join(templateRoot, 'manifest.yml.in');
|
|
223
|
+
const packageTemplatePath = path.join(templateRoot, 'package.yml.in');
|
|
224
|
+
const templateVars = await this.lpkManifest.init(manifestTemplatePath, true);
|
|
225
|
+
await this.lpkPackageFile.init(packageTemplatePath, true, templateVars);
|
|
153
226
|
}
|
|
154
227
|
|
|
155
228
|
async create() {
|
|
156
|
-
|
|
229
|
+
const outputDir = path.resolve(this.cwd, this.name);
|
|
230
|
+
await this.lpkManifest.create(outputDir);
|
|
231
|
+
await this.lpkPackageFile.create(outputDir);
|
|
157
232
|
}
|
|
158
233
|
}
|
|
159
234
|
|
|
@@ -4,7 +4,6 @@ import fs from 'fs';
|
|
|
4
4
|
import { isBinaryFileSync } from 'isbinaryfile';
|
|
5
5
|
import { contextDirname } from '../utils.js';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
-
// import spawn from "cross-spawn"
|
|
8
7
|
import logger from 'loglevel';
|
|
9
8
|
import { t } from '../i18n/index.js';
|
|
10
9
|
|
|
@@ -27,7 +26,6 @@ async function loadFiles(dirPath, prefix = '') {
|
|
|
27
26
|
} else {
|
|
28
27
|
content = fs.readFileSync(sourcePath, 'utf8');
|
|
29
28
|
}
|
|
30
|
-
// change _ prefix file into dot file
|
|
31
29
|
if (p.startsWith('_')) {
|
|
32
30
|
p = p.replace('_', '.');
|
|
33
31
|
}
|
|
@@ -56,28 +54,6 @@ export async function generate(type, to, opts = {}) {
|
|
|
56
54
|
writeFileTree(to, files);
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
function appCreateSuccessTip(name) {
|
|
60
|
-
console.log(
|
|
61
|
-
chalk.green(
|
|
62
|
-
t(
|
|
63
|
-
'lzc_cli.lib.app.lpk_create_generator.app_create_success_tip',
|
|
64
|
-
`
|
|
65
|
-
✨ 懒猫微服应用已创建成功 !
|
|
66
|
-
✨ 先完成第一次部署,确认手机/PC都可以访问
|
|
67
|
-
cd {{ name }}
|
|
68
|
-
npm install
|
|
69
|
-
lzc-cli project deploy
|
|
70
|
-
lzc-cli project info
|
|
71
|
-
`,
|
|
72
|
-
{
|
|
73
|
-
name,
|
|
74
|
-
interpolation: { escapeValue: false }
|
|
75
|
-
},
|
|
76
|
-
).trim(),
|
|
77
|
-
),
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
57
|
function appCreateSuccessTipByCommands(name, installCommand = '') {
|
|
82
58
|
const installBlock = installCommand ? `\n ${installCommand}` : '';
|
|
83
59
|
console.log(
|
|
@@ -86,10 +62,13 @@ function appCreateSuccessTipByCommands(name, installCommand = '') {
|
|
|
86
62
|
'lzc_cli.lib.app.lpk_create_generator.app_create_success_tip_common',
|
|
87
63
|
`
|
|
88
64
|
✨ 懒猫微服应用已创建成功 !
|
|
89
|
-
✨
|
|
65
|
+
✨ First deploy and open the app once
|
|
90
66
|
cd {{ name }}{{ installBlock }}
|
|
91
67
|
lzc-cli project deploy
|
|
92
68
|
lzc-cli project info
|
|
69
|
+
ℹ By default, project commands use lzc-build.dev.yml when it exists.
|
|
70
|
+
Each command prints the active Build config.
|
|
71
|
+
Use --release if you want to operate on lzc-build.yml.
|
|
93
72
|
`,
|
|
94
73
|
{
|
|
95
74
|
name,
|
|
@@ -113,11 +92,13 @@ export const TemplateConfig = {
|
|
|
113
92
|
t(
|
|
114
93
|
'lzc_cli.lib.app.lpk_create_generator.template_config_vue3_green',
|
|
115
94
|
`
|
|
116
|
-
🛠
|
|
117
|
-
|
|
118
|
-
|
|
95
|
+
🛠 Open the app first.
|
|
96
|
+
If the frontend dev server is not running yet, the app page will show the expected port and next step.
|
|
97
|
+
Then start local frontend dev:
|
|
98
|
+
npm run dev
|
|
99
|
+
The command output prints the active Build config.
|
|
100
|
+
🔎 For troubleshooting:
|
|
119
101
|
lzc-cli project log -f
|
|
120
|
-
lzc-cli project exec /bin/sh
|
|
121
102
|
`,
|
|
122
103
|
).trim(),
|
|
123
104
|
),
|
|
@@ -135,11 +116,14 @@ export const TemplateConfig = {
|
|
|
135
116
|
t(
|
|
136
117
|
'lzc_cli.lib.app.lpk_create_generator.template_config_springboot_green',
|
|
137
118
|
`
|
|
138
|
-
🛠
|
|
139
|
-
|
|
119
|
+
🛠 Open the app first.
|
|
120
|
+
If the backend dev service is not ready yet, the app page will tell you how to sync or copy code and how to start the service.
|
|
121
|
+
Recommended backend dev loop:
|
|
122
|
+
lzc-cli project sync --watch
|
|
123
|
+
lzc-cli project exec /bin/sh
|
|
124
|
+
The command output prints the active Build config.
|
|
140
125
|
🔎 For troubleshooting:
|
|
141
126
|
lzc-cli project log -f
|
|
142
|
-
lzc-cli project exec /bin/sh
|
|
143
127
|
`,
|
|
144
128
|
).trim(),
|
|
145
129
|
),
|
|
@@ -157,11 +141,14 @@ export const TemplateConfig = {
|
|
|
157
141
|
t(
|
|
158
142
|
'lzc_cli.lib.app.lpk_create_generator.template_config_python_green',
|
|
159
143
|
`
|
|
160
|
-
🛠
|
|
161
|
-
|
|
144
|
+
🛠 Open the app first.
|
|
145
|
+
If the backend dev service is not ready yet, the app page will tell you how to sync or copy code and how to start the service.
|
|
146
|
+
Recommended backend dev loop:
|
|
147
|
+
lzc-cli project sync --watch
|
|
148
|
+
lzc-cli project exec /bin/sh
|
|
149
|
+
The command output prints the active Build config.
|
|
162
150
|
🔎 For troubleshooting:
|
|
163
151
|
lzc-cli project log -f
|
|
164
|
-
lzc-cli project exec /bin/sh
|
|
165
152
|
`,
|
|
166
153
|
).trim(),
|
|
167
154
|
),
|
|
@@ -179,12 +166,15 @@ export const TemplateConfig = {
|
|
|
179
166
|
t(
|
|
180
167
|
'lzc_cli.lib.app.lpk_create_generator.template_config_golang_green',
|
|
181
168
|
`
|
|
182
|
-
🛠
|
|
183
|
-
|
|
169
|
+
🛠 Open the app first.
|
|
170
|
+
If the backend dev service is not ready yet, the app page will tell you how to sync or copy code and how to start the service.
|
|
171
|
+
Recommended backend dev loop:
|
|
172
|
+
lzc-cli project sync --watch
|
|
173
|
+
lzc-cli project exec /bin/sh
|
|
174
|
+
The command output prints the active Build config.
|
|
184
175
|
🔎 For troubleshooting:
|
|
185
176
|
lzc-cli project log -f
|
|
186
|
-
|
|
187
|
-
`,
|
|
177
|
+
`,
|
|
188
178
|
).trim(),
|
|
189
179
|
),
|
|
190
180
|
);
|
|
@@ -203,6 +193,7 @@ export const TemplateConfig = {
|
|
|
203
193
|
`
|
|
204
194
|
🛠 GUI VNC app (embedded image template):
|
|
205
195
|
lzc-cli project deploy
|
|
196
|
+
The command output prints the active Build config.
|
|
206
197
|
🔎 For troubleshooting:
|
|
207
198
|
lzc-cli project log -f
|
|
208
199
|
lzc-cli project exec -s desktop /bin/sh
|
|
@@ -223,11 +214,13 @@ export const TemplateConfig = {
|
|
|
223
214
|
t(
|
|
224
215
|
'lzc_cli.lib.app.lpk_create_generator.template_config_vue_minidb_green',
|
|
225
216
|
`
|
|
226
|
-
🛠
|
|
227
|
-
|
|
217
|
+
🛠 Open the app first.
|
|
218
|
+
If the frontend dev server is not running yet, the app page will show the expected port and next step.
|
|
219
|
+
Then start local frontend dev:
|
|
220
|
+
npm run dev
|
|
221
|
+
The command output prints the active Build config.
|
|
228
222
|
🔎 For troubleshooting:
|
|
229
223
|
lzc-cli project log -f
|
|
230
|
-
lzc-cli project exec /bin/sh
|
|
231
224
|
`,
|
|
232
225
|
).trim(),
|
|
233
226
|
),
|
package/lib/app/lpk_devshell.js
CHANGED
|
@@ -384,11 +384,15 @@ class DevShell {
|
|
|
384
384
|
const rsyncCmd = isWindows ? path.join(contextDirname(import.meta.url), '..', '..', 'template', '_lpk', 'win-rsync', 'rsync.exe') : `rsync`;
|
|
385
385
|
|
|
386
386
|
try {
|
|
387
|
-
const rsyncArgs = [
|
|
387
|
+
const rsyncArgs = [];
|
|
388
|
+
if (rsyncDebug) {
|
|
389
|
+
rsyncArgs.push(rsyncDebug);
|
|
390
|
+
}
|
|
391
|
+
rsyncArgs.push('--recursive', '--relative', '--perms', '--update', '-F', '--filter=:- .gitignore', '--ignore-errors', '.', dest);
|
|
388
392
|
logger.debug(t('lzc_cli.lib.app.lpk_devshell.sync_project_code_tips', '同步代码: '), rsyncCmd, rsyncArgs.join(' '));
|
|
389
393
|
const rsyncStream = spawn.sync(rsyncCmd, rsyncArgs, {
|
|
390
394
|
env: { ...process.env, RSYNC_PASSWORD: 'fakefakefake' },
|
|
391
|
-
shell:
|
|
395
|
+
shell: false,
|
|
392
396
|
stdio: ['ignore', isDebugMode() ? 'inherit' : 'ignore', 'inherit'],
|
|
393
397
|
});
|
|
394
398
|
} catch (err) {
|
package/lib/app/lpk_installer.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import logger from 'loglevel';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { Downloader, extractLpkSync } from '../utils.js';
|
|
5
|
+
import { loadEffectiveManifestFromFiles } from '../package_info.js';
|
|
5
6
|
import { DebugBridge } from '../debug_bridge.js';
|
|
6
7
|
import shellapi from '../shellapi.js';
|
|
7
8
|
import { t } from '../i18n/index.js';
|
|
@@ -95,8 +96,8 @@ export class LpkInstaller {
|
|
|
95
96
|
const tempDir = fs.mkdtempSync('.lzc-cli-install');
|
|
96
97
|
let manifest;
|
|
97
98
|
try {
|
|
98
|
-
|
|
99
|
-
manifest =
|
|
99
|
+
extractLpkSync(pkgPath, tempDir, ['manifest.yml', 'package.yml', 'icon.png']);
|
|
100
|
+
manifest = loadEffectiveManifestFromFiles(path.join(tempDir, 'manifest.yml')).manifest;
|
|
100
101
|
if (!manifest['application']['subdomain']) {
|
|
101
102
|
throw t('lzc_cli.lib.app.lpk_installer.install_from_file_manifest_not_exists_app_subdomain_fail', 'manifest.yml 中的 `application.subdomain` 字段不能为空');
|
|
102
103
|
}
|