@lazycatcloud/lzc-cli 1.3.13 → 2.0.0-pre.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 +30 -5
- package/changelog.md +16 -0
- package/lib/app/index.js +174 -58
- package/lib/app/lpk_build.js +197 -18
- package/lib/app/lpk_build_images.js +728 -0
- package/lib/app/lpk_create.js +96 -23
- package/lib/app/lpk_create_generator.js +150 -12
- package/lib/app/lpk_devshell.js +35 -21
- package/lib/app/lpk_embed_images.js +257 -0
- package/lib/app/lpk_installer.js +15 -7
- package/lib/app/project_cp.js +64 -0
- package/lib/app/project_deploy.js +33 -0
- package/lib/app/project_exec.js +45 -0
- package/lib/app/project_info.js +106 -0
- package/lib/app/project_log.js +67 -0
- package/lib/app/project_runtime.js +261 -0
- package/lib/app/project_start.js +100 -0
- package/lib/appstore/index.js +56 -16
- package/lib/appstore/publish.js +16 -13
- package/lib/box/index.js +103 -6
- package/lib/box/ssh_remote.js +259 -0
- package/lib/build_remote.js +22 -0
- package/lib/config/index.js +4 -3
- package/lib/debug_bridge.js +837 -44
- package/lib/docker/index.js +30 -10
- package/lib/i18n/index.js +1 -0
- package/lib/i18n/locales/en/translation.json +263 -250
- package/lib/i18n/locales/zh/translation.json +57 -44
- package/lib/lpk/core.js +487 -0
- package/lib/lpk/index.js +210 -0
- package/lib/shellapi.js +5 -5
- package/lib/sig/core.js +254 -0
- package/lib/sig/index.js +88 -0
- package/lib/utils.js +17 -12
- package/package.json +4 -3
- package/scripts/cli.js +4 -0
- package/template/_lpk/README.md +11 -3
- package/template/_lpk/gui-vnc.manifest.yml.in +27 -0
- package/template/_lpk/manifest.yml.in +4 -2
- package/template/_lpk/todolist-golang.manifest.yml.in +16 -0
- package/template/_lpk/todolist-java.manifest.yml.in +15 -0
- package/template/_lpk/todolist-python.manifest.yml.in +15 -0
- package/template/_lpk/vue.lzc-build.yml.in +0 -44
- package/template/blank/_gitignore +1 -0
- package/template/blank/lzc-build.yml +25 -40
- package/template/blank/lzc-manifest.yml +14 -7
- package/template/golang/Dockerfile +19 -0
- package/template/golang/README.md +33 -0
- package/template/golang/_gitignore +3 -0
- package/template/golang/go.mod +3 -0
- package/template/golang/lzc-build.yml +21 -0
- package/template/golang/lzc-icon.png +0 -0
- package/template/golang/main.go +252 -0
- package/template/golang/run.sh +3 -0
- package/template/golang/web/index.html +238 -0
- package/template/gui-vnc/README.md +19 -0
- package/template/gui-vnc/_gitignore +2 -0
- package/template/gui-vnc/images/Dockerfile +30 -0
- package/template/gui-vnc/images/kasmvnc.yaml +33 -0
- package/template/gui-vnc/images/startup-script.desktop +9 -0
- package/template/gui-vnc/images/startup-script.sh +6 -0
- package/template/gui-vnc/lzc-build.yml +23 -0
- package/template/gui-vnc/lzc-icon.png +0 -0
- package/template/python/Dockerfile +15 -0
- package/template/python/README.md +33 -0
- package/template/python/_gitignore +3 -0
- package/template/python/app.py +110 -0
- package/template/python/lzc-build.yml +21 -0
- package/template/python/lzc-icon.png +0 -0
- package/template/python/requirements.txt +1 -0
- package/template/python/run.sh +3 -0
- package/template/python/web/index.html +238 -0
- package/template/springboot/Dockerfile +20 -0
- package/template/springboot/README.md +33 -0
- package/template/springboot/_gitignore +3 -0
- package/template/springboot/lzc-build.yml +21 -0
- package/template/springboot/lzc-icon.png +0 -0
- package/template/springboot/pom.xml +38 -0
- package/template/springboot/run.sh +3 -0
- package/template/springboot/src/main/java/cloud/lazycat/app/Application.java +132 -0
- package/template/springboot/src/main/resources/application.properties +1 -0
- package/template/springboot/src/main/resources/static/index.html +238 -0
- package/template/vue/README.md +17 -7
- package/template/vue/_gitignore +1 -0
- package/template/vue/lzc-build.yml +31 -42
- package/template/vue/src/App.vue +36 -25
- package/template/vue/src/style.css +106 -49
- package/template/vue-minidb/README.md +34 -0
- package/template/vue-minidb/_gitignore +26 -0
- package/template/vue-minidb/index.html +13 -0
- package/template/vue-minidb/lzc-build.yml +48 -0
- package/template/vue-minidb/lzc-icon.png +0 -0
- package/template/vue-minidb/package.json +21 -0
- package/template/vue-minidb/public/vite.svg +1 -0
- package/template/vue-minidb/src/App.vue +206 -0
- package/template/vue-minidb/src/assets/vue.svg +1 -0
- package/template/vue-minidb/src/main.ts +5 -0
- package/template/vue-minidb/src/style.css +136 -0
- package/template/vue-minidb/src/vite-env.d.ts +1 -0
- package/template/vue-minidb/tsconfig.app.json +24 -0
- package/template/vue-minidb/tsconfig.json +7 -0
- package/template/vue-minidb/tsconfig.node.json +22 -0
- package/template/vue-minidb/vite.config.ts +10 -0
- /package/template/{vue → vue-minidb}/src/components/HelloWorld.vue +0 -0
package/lib/app/lpk_build.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import zlib from 'node:zlib';
|
|
3
4
|
import logger from 'loglevel';
|
|
4
5
|
import {
|
|
5
|
-
loadFromYaml,
|
|
6
6
|
isDirExist,
|
|
7
7
|
isDirSync,
|
|
8
8
|
isFileExist,
|
|
@@ -19,12 +19,16 @@ import spawn from 'cross-spawn';
|
|
|
19
19
|
import { LpkManifest } from './lpk_create.js';
|
|
20
20
|
import archiver from 'archiver';
|
|
21
21
|
import yaml from 'js-yaml';
|
|
22
|
+
import { buildConfiguredImagesToTempDir } from './lpk_build_images.js';
|
|
23
|
+
import { pipeline } from 'node:stream/promises';
|
|
22
24
|
import { t } from '../i18n/index.js';
|
|
25
|
+
import mergeWith from 'lodash.mergewith';
|
|
26
|
+
import { DEFAULT_BUILD_BASE_FILE } from '../build_remote.js';
|
|
23
27
|
|
|
24
28
|
async function archiveFolderTo(appDir, out, format = 'zip') {
|
|
25
29
|
return new Promise(async (resolve, reject) => {
|
|
26
30
|
if (!fs.existsSync(appDir)) {
|
|
27
|
-
reject(new Error(t('lzc_cli.lib.app.lpk_build.archive_folder_to_exist_fail', `{{appDir}} 文件夹不存在`, { appDir })));
|
|
31
|
+
reject(new Error(t('lzc_cli.lib.app.lpk_build.archive_folder_to_exist_fail', `{{appDir}} 文件夹不存在`, { appDir, interpolation: { escapeValue: false } })));
|
|
28
32
|
return;
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -46,6 +50,66 @@ async function archiveFolderTo(appDir, out, format = 'zip') {
|
|
|
46
50
|
});
|
|
47
51
|
}
|
|
48
52
|
|
|
53
|
+
async function gzipFileTo(inputPath, outputPath) {
|
|
54
|
+
const source = fs.createReadStream(inputPath);
|
|
55
|
+
const gzip = zlib.createGzip({ mtime: 0 });
|
|
56
|
+
const target = fs.createWriteStream(outputPath);
|
|
57
|
+
await pipeline(source, gzip, target);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function rewriteManifestEmbeddedImages(manifest, resolvedImageByAlias) {
|
|
61
|
+
const EMBED_PREFIX = 'embed:';
|
|
62
|
+
if (!resolvedImageByAlias || typeof resolvedImageByAlias !== 'object') {
|
|
63
|
+
return manifest;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const parseAlias = (rawValue) => {
|
|
67
|
+
const trimmed = String(rawValue ?? '').trim();
|
|
68
|
+
if (!trimmed.startsWith(EMBED_PREFIX)) {
|
|
69
|
+
return '';
|
|
70
|
+
}
|
|
71
|
+
const rest = trimmed.slice(EMBED_PREFIX.length).trim();
|
|
72
|
+
if (!rest) {
|
|
73
|
+
throw new Error(`Invalid image reference "${rawValue}", alias is required after "${EMBED_PREFIX}"`);
|
|
74
|
+
}
|
|
75
|
+
const at = rest.indexOf('@');
|
|
76
|
+
const alias = (at >= 0 ? rest.slice(0, at) : rest).trim();
|
|
77
|
+
if (!alias) {
|
|
78
|
+
throw new Error(`Invalid image reference "${rawValue}", alias is required after "${EMBED_PREFIX}"`);
|
|
79
|
+
}
|
|
80
|
+
return alias;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const walk = (value) => {
|
|
84
|
+
if (typeof value === 'string') {
|
|
85
|
+
const alias = parseAlias(value);
|
|
86
|
+
if (alias) {
|
|
87
|
+
const resolved = resolvedImageByAlias[alias];
|
|
88
|
+
if (!resolved) {
|
|
89
|
+
throw new Error(`Cannot resolve embedded image alias "${alias}" to final image reference`);
|
|
90
|
+
}
|
|
91
|
+
return `${EMBED_PREFIX}${alias}@${resolved}`;
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
if (Array.isArray(value)) {
|
|
96
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
97
|
+
value[index] = walk(value[index]);
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
if (value && typeof value === 'object') {
|
|
102
|
+
for (const [key, item] of Object.entries(value)) {
|
|
103
|
+
value[key] = walk(item);
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
return value;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return walk(manifest);
|
|
111
|
+
}
|
|
112
|
+
|
|
49
113
|
async function fetchIconTo(options, cwd, destDir) {
|
|
50
114
|
if (!options['icon']) {
|
|
51
115
|
logger.warn(t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_empty_fail', '图标icon 没有指定'));
|
|
@@ -63,15 +127,20 @@ async function fetchIconTo(options, cwd, destDir) {
|
|
|
63
127
|
}
|
|
64
128
|
|
|
65
129
|
if (!isFileExist(iconPath)) {
|
|
66
|
-
logger.warn(t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_file_not_exist_fail', `图标icon {{iconPath}} 不存在`, { iconPath }));
|
|
130
|
+
logger.warn(t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_file_not_exist_fail', `图标icon {{ iconPath }} 不存在`, { iconPath, interpolation: { escapeValue: false } }));
|
|
67
131
|
return;
|
|
68
132
|
}
|
|
69
133
|
|
|
70
134
|
if (!isPngWithFile(iconPath)) {
|
|
71
|
-
logger.warn(
|
|
135
|
+
logger.warn(
|
|
136
|
+
t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_not_is_png_fail', `图标icon {{ iconPath }} 验证失败(不是一个png格式)`, {
|
|
137
|
+
iconPath,
|
|
138
|
+
interpolation: { escapeValue: false },
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
72
141
|
return;
|
|
73
142
|
} else {
|
|
74
|
-
logger.debug(t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_is_png', `图标icon {{iconPath}} 验证成功(png格式)`, { iconPath }));
|
|
143
|
+
logger.debug(t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_is_png', `图标icon {{ iconPath }} 验证成功(png格式)`, { iconPath, interpolation: { escapeValue: false } }));
|
|
75
144
|
}
|
|
76
145
|
|
|
77
146
|
fs.copyFileSync(iconPath, path.join(destDir, 'icon.png'));
|
|
@@ -97,7 +166,12 @@ async function fetchLzcDeployParamTo(options, cwd, destDir) {
|
|
|
97
166
|
}
|
|
98
167
|
|
|
99
168
|
if (!isFileExist(deployParamsPath)) {
|
|
100
|
-
logger.warn(
|
|
169
|
+
logger.warn(
|
|
170
|
+
t('lzc_cli.lib.app.lpk_build.fetch_lzc_deploy_param_to_not_exist', `deploy_params {{ deployParamsPath }} 不存在`, {
|
|
171
|
+
deployParamsPath,
|
|
172
|
+
interpolation: { escapeValue: false },
|
|
173
|
+
}),
|
|
174
|
+
);
|
|
101
175
|
return;
|
|
102
176
|
}
|
|
103
177
|
|
|
@@ -151,12 +225,52 @@ function convenientEnv() {
|
|
|
151
225
|
);
|
|
152
226
|
}
|
|
153
227
|
|
|
228
|
+
function formatBytes(bytes) {
|
|
229
|
+
const value = Number(bytes ?? 0);
|
|
230
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
231
|
+
return '0 B';
|
|
232
|
+
}
|
|
233
|
+
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
|
|
234
|
+
let size = value;
|
|
235
|
+
let unitIndex = 0;
|
|
236
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
237
|
+
size /= 1024;
|
|
238
|
+
unitIndex += 1;
|
|
239
|
+
}
|
|
240
|
+
const digits = unitIndex === 0 ? 0 : 2;
|
|
241
|
+
return `${size.toFixed(digits)} ${units[unitIndex]}`;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function mergeBuildOptions(baseOptions, topOptions) {
|
|
245
|
+
return mergeWith({}, baseOptions ?? {}, topOptions ?? {}, (objValue, srcValue) => {
|
|
246
|
+
if (Array.isArray(srcValue)) {
|
|
247
|
+
return srcValue;
|
|
248
|
+
}
|
|
249
|
+
return undefined;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function loadYamlIfExists(filePath) {
|
|
254
|
+
if (!filePath || !isFileExist(filePath)) {
|
|
255
|
+
return {};
|
|
256
|
+
}
|
|
257
|
+
return yaml.load(fs.readFileSync(filePath, 'utf8')) ?? {};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function loadTemplatedYamlIfExists(filePath, env) {
|
|
261
|
+
if (!filePath || !isFileExist(filePath)) {
|
|
262
|
+
return {};
|
|
263
|
+
}
|
|
264
|
+
return yaml.load(await envTemplateFile(filePath, env)) ?? {};
|
|
265
|
+
}
|
|
266
|
+
|
|
154
267
|
export class LpkBuild {
|
|
155
268
|
constructor(cwd, buildConfigFile) {
|
|
156
269
|
this.pwd = cwd ?? process.cwd();
|
|
157
270
|
|
|
158
271
|
this.optionsFilePath = path.join(this.pwd, buildConfigFile);
|
|
159
|
-
this.
|
|
272
|
+
this.optionsBaseFilePath = path.join(path.dirname(this.optionsFilePath), DEFAULT_BUILD_BASE_FILE);
|
|
273
|
+
this.options = mergeBuildOptions(loadYamlIfExists(this.optionsBaseFilePath), loadYamlIfExists(this.optionsFilePath));
|
|
160
274
|
|
|
161
275
|
this.manifestFilePath = this.options['manifest'] ? path.join(this.pwd, this.options['manifest']) : path.join(this.pwd, 'lzc-manifest.yml');
|
|
162
276
|
this.manifest = null;
|
|
@@ -171,7 +285,10 @@ export class LpkBuild {
|
|
|
171
285
|
async init() {
|
|
172
286
|
const manifest = await this.getManifest();
|
|
173
287
|
const primitive = convenientEnv();
|
|
174
|
-
|
|
288
|
+
const env = Object.assign({}, primitive, manifest);
|
|
289
|
+
const baseOptions = await loadTemplatedYamlIfExists(this.optionsBaseFilePath, env);
|
|
290
|
+
const topOptions = await loadTemplatedYamlIfExists(this.optionsFilePath, env);
|
|
291
|
+
this.options = mergeBuildOptions(baseOptions, topOptions);
|
|
175
292
|
return this;
|
|
176
293
|
}
|
|
177
294
|
|
|
@@ -210,7 +327,7 @@ export class LpkBuild {
|
|
|
210
327
|
this.excpManifest = lpkM.excpManifest;
|
|
211
328
|
|
|
212
329
|
if (!isValidPackageName(this.manifest['package'])) {
|
|
213
|
-
throw t('lzc_cli.lib.app.lpk_build.get_manifest_package_name_fail', `{{package}} 含有非法字符,请使用正确的包名格式(java的包名格式),如:cloud.lazycat.apps.video`, {
|
|
330
|
+
throw t('lzc_cli.lib.app.lpk_build.get_manifest_package_name_fail', `{{ package }} 含有非法字符,请使用正确的包名格式(java的包名格式),如:cloud.lazycat.apps.video`, {
|
|
214
331
|
package: this.manifest['package'],
|
|
215
332
|
});
|
|
216
333
|
}
|
|
@@ -245,9 +362,16 @@ export class LpkBuild {
|
|
|
245
362
|
|
|
246
363
|
// 输出路径
|
|
247
364
|
let packName = this.options['lpkPath'];
|
|
248
|
-
|
|
249
|
-
if (!packName
|
|
250
|
-
|
|
365
|
+
let pkgout = '';
|
|
366
|
+
if (!packName) {
|
|
367
|
+
const rawPkgout = this.options['pkgout'];
|
|
368
|
+
if (rawPkgout !== undefined && rawPkgout !== null && typeof rawPkgout !== 'string') {
|
|
369
|
+
throw t('lzc_cli.lib.app.lpk_build.exec_pkgout_invalid_type', 'pkgout must be a string when specified');
|
|
370
|
+
}
|
|
371
|
+
pkgout = path.resolve(this.pwd, typeof rawPkgout === 'string' && rawPkgout.trim() !== '' ? rawPkgout : './');
|
|
372
|
+
if (!isDirExist(pkgout)) {
|
|
373
|
+
throw t('lzc_cli.lib.app.lpk_build.exec_pkgout_not_exist', `{{ pkgout }} 不存在`, { pkgout, interpolation: { escapeValue: false } });
|
|
374
|
+
}
|
|
251
375
|
}
|
|
252
376
|
|
|
253
377
|
const tempDir = fs.mkdtempSync('.lzc-cli-build');
|
|
@@ -291,15 +415,19 @@ export class LpkBuild {
|
|
|
291
415
|
} else if (isFileExist(browserExtension)) {
|
|
292
416
|
fs.copyFileSync(browserExtension, path.join(tempDir, 'extension.zip'));
|
|
293
417
|
} else {
|
|
294
|
-
throw t('lzc_cli.lib.app.lpk_build.exec_browser_extension_not_exist', `{{browserExtension}} 不存在`, {
|
|
418
|
+
throw t('lzc_cli.lib.app.lpk_build.exec_browser_extension_not_exist', `{{ browserExtension }} 不存在`, {
|
|
419
|
+
browserExtension,
|
|
420
|
+
interpolation: { escapeValue: false },
|
|
421
|
+
});
|
|
295
422
|
}
|
|
296
423
|
}
|
|
297
424
|
|
|
298
425
|
if (aiPodService) {
|
|
299
426
|
aiPodService = path.resolve(this.pwd, aiPodService);
|
|
300
427
|
if (!isDirExist(aiPodService)) {
|
|
301
|
-
throw t('lzc_cli.lib.app.lpk_build.exec_ai_pos_service_not_exist', `{{aiPodService}} 不存在`, {
|
|
428
|
+
throw t('lzc_cli.lib.app.lpk_build.exec_ai_pos_service_not_exist', `{{ aiPodService }} 不存在`, {
|
|
302
429
|
aiPodService,
|
|
430
|
+
interpolation: { escapeValue: false },
|
|
303
431
|
});
|
|
304
432
|
}
|
|
305
433
|
fs.cpSync(aiPodService, path.join(tempDir, 'ai-pod-service'), {
|
|
@@ -318,7 +446,43 @@ export class LpkBuild {
|
|
|
318
446
|
}, manifest);
|
|
319
447
|
}
|
|
320
448
|
|
|
321
|
-
if (
|
|
449
|
+
if (Object.prototype.hasOwnProperty.call(this.options, 'embed_images')) {
|
|
450
|
+
throw new Error('embed_images is removed, please use lzc-build.yml images and manifest embed:alias');
|
|
451
|
+
}
|
|
452
|
+
if (Object.prototype.hasOwnProperty.call(this.options, 'embed_all_images')) {
|
|
453
|
+
throw new Error('embed_all_images is removed');
|
|
454
|
+
}
|
|
455
|
+
if (Object.prototype.hasOwnProperty.call(this.options, 'upstream_registry')) {
|
|
456
|
+
throw new Error('upstream_registry is renamed to upstream_match');
|
|
457
|
+
}
|
|
458
|
+
if (Object.prototype.hasOwnProperty.call(this.options, 'upstream_match') || Object.prototype.hasOwnProperty.call(this.options, 'upstream-match')) {
|
|
459
|
+
throw new Error('upstream_match is moved to lzc-build.yml images.<alias>.upstream-match');
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const hasImagesConfig = !!this.options['images'];
|
|
463
|
+
|
|
464
|
+
let useTarPackage = false;
|
|
465
|
+
let embeddedImageSummary = null;
|
|
466
|
+
if (hasImagesConfig) {
|
|
467
|
+
const buildResult = await buildConfiguredImagesToTempDir(this.options['images'], manifest, this.pwd, tempDir, {
|
|
468
|
+
remote: this.options['remote'],
|
|
469
|
+
});
|
|
470
|
+
if (buildResult.imageCount > 0) {
|
|
471
|
+
useTarPackage = true;
|
|
472
|
+
embeddedImageSummary = buildResult;
|
|
473
|
+
manifest = rewriteManifestEmbeddedImages(manifest, buildResult.resolvedImageByAlias);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (useTarPackage) {
|
|
477
|
+
const contentTar = path.join(tempDir, 'content.tar');
|
|
478
|
+
const contentTarGz = path.join(tempDir, 'content.tar.gz');
|
|
479
|
+
if (isFileExist(contentTar)) {
|
|
480
|
+
await gzipFileTo(contentTar, contentTarGz);
|
|
481
|
+
fs.rmSync(contentTar, { force: true });
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (process.env.LZC_MANIFEST_TEMPLATE && !useTarPackage) {
|
|
322
486
|
logger.debug('copy origin manifest\n', this.manifestFilePath);
|
|
323
487
|
fs.copyFileSync(this.manifestFilePath, path.join(tempDir, 'manifest.yml'));
|
|
324
488
|
} else {
|
|
@@ -345,11 +509,26 @@ export class LpkBuild {
|
|
|
345
509
|
}
|
|
346
510
|
|
|
347
511
|
if (!packName) {
|
|
348
|
-
|
|
512
|
+
const ext = '.lpk';
|
|
513
|
+
packName = path.resolve(pkgout, `${manifest.package}-v${manifest.version}${ext}`);
|
|
349
514
|
}
|
|
350
515
|
|
|
351
|
-
const lpkPath = await archiveFolderTo(tempDir, packName);
|
|
352
|
-
logger.info(
|
|
516
|
+
const lpkPath = await archiveFolderTo(tempDir, packName, useTarPackage ? 'tar' : 'zip');
|
|
517
|
+
logger.info(
|
|
518
|
+
`${t('lzc_cli.lib.app.lpk_build.exec_output_lpk_path', '输出lpk包 {{ path }}', {
|
|
519
|
+
path: lpkPath.path,
|
|
520
|
+
interpolation: { escapeValue: false }, // https://www.i18next.com/translation-function/interpolation#unescape
|
|
521
|
+
})}`,
|
|
522
|
+
);
|
|
523
|
+
if (embeddedImageSummary && embeddedImageSummary.imageCount > 0) {
|
|
524
|
+
logger.info('Embedded image upstream summary:');
|
|
525
|
+
for (const [alias, upstream] of Object.entries(embeddedImageSummary.upstreamByAlias ?? {})) {
|
|
526
|
+
logger.info(`- ${alias}: ${upstream || '(none, full embed)'}`);
|
|
527
|
+
}
|
|
528
|
+
logger.info(
|
|
529
|
+
`Embedded image layer size: ${formatBytes(embeddedImageSummary.embeddedLayerBytes)} (${embeddedImageSummary.embeddedLayerBytes} bytes, ${embeddedImageSummary.embeddedLayerCount} unique layers)`,
|
|
530
|
+
);
|
|
531
|
+
}
|
|
353
532
|
|
|
354
533
|
return lpkPath.path;
|
|
355
534
|
} finally {
|