@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_build.js
CHANGED
|
@@ -2,28 +2,16 @@ import path from 'node:path';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import zlib from 'node:zlib';
|
|
4
4
|
import logger from 'loglevel';
|
|
5
|
-
import {
|
|
6
|
-
isDirExist,
|
|
7
|
-
isDirSync,
|
|
8
|
-
isFileExist,
|
|
9
|
-
dumpToYaml,
|
|
10
|
-
envTemplateFile,
|
|
11
|
-
isValidPackageName,
|
|
12
|
-
tarContentDir,
|
|
13
|
-
isPngWithFile,
|
|
14
|
-
isMacOs,
|
|
15
|
-
isWindows,
|
|
16
|
-
isLinux,
|
|
17
|
-
} from '../utils.js';
|
|
5
|
+
import { isDirExist, isDirSync, isFileExist, dumpToYaml, envTemplateFile, isValidPackageName, tarContentDir, isPngWithFile, isMacOs, isWindows, isLinux } from '../utils.js';
|
|
18
6
|
import spawn from 'cross-spawn';
|
|
19
|
-
import {
|
|
7
|
+
import { loadEffectiveManifest, splitManifestAndPackageInfo, findManifestStaticFields, PACKAGE_FILE_NAME } from '../package_info.js';
|
|
8
|
+
import { buildVarsFromEnvEntries, normalizeBuildEnvEntries, preprocessManifestFile } from './manifest_build.js';
|
|
20
9
|
import archiver from 'archiver';
|
|
21
10
|
import yaml from 'js-yaml';
|
|
22
11
|
import { buildConfiguredImagesToTempDir } from './lpk_build_images.js';
|
|
23
12
|
import { pipeline } from 'node:stream/promises';
|
|
24
13
|
import { t } from '../i18n/index.js';
|
|
25
14
|
import mergeWith from 'lodash.mergewith';
|
|
26
|
-
import { DEFAULT_BUILD_BASE_FILE } from '../build_remote.js';
|
|
27
15
|
|
|
28
16
|
async function archiveFolderTo(appDir, out, format = 'zip') {
|
|
29
17
|
return new Promise(async (resolve, reject) => {
|
|
@@ -110,6 +98,74 @@ function rewriteManifestEmbeddedImages(manifest, resolvedImageByAlias) {
|
|
|
110
98
|
return walk(manifest);
|
|
111
99
|
}
|
|
112
100
|
|
|
101
|
+
function rewriteManifestEmbeddedImagesInText(rawText, resolvedImageByAlias) {
|
|
102
|
+
if (!resolvedImageByAlias || typeof resolvedImageByAlias !== 'object') {
|
|
103
|
+
return rawText;
|
|
104
|
+
}
|
|
105
|
+
let output = String(rawText ?? '');
|
|
106
|
+
for (const [alias, resolved] of Object.entries(resolvedImageByAlias)) {
|
|
107
|
+
if (!alias || !resolved) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
111
|
+
const pattern = new RegExp(`embed:${escapedAlias}(?!@sha256:[0-9a-fA-F]{64})`, 'g');
|
|
112
|
+
output = output.replace(pattern, `embed:${alias}@${resolved}`);
|
|
113
|
+
}
|
|
114
|
+
return output;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function rewriteTopLevelManifestScalarInText(rawText, key, value) {
|
|
118
|
+
const normalizedValue = String(value ?? '').trim();
|
|
119
|
+
if (!normalizedValue) {
|
|
120
|
+
return rawText;
|
|
121
|
+
}
|
|
122
|
+
const lines = String(rawText ?? '').split('\n');
|
|
123
|
+
const pattern = new RegExp(`^(\\s*)${key}:(\\s*)([^#]*?)(\\s*(#.*))?$`);
|
|
124
|
+
let replaced = false;
|
|
125
|
+
const output = lines.map((line) => {
|
|
126
|
+
if (replaced) {
|
|
127
|
+
return line;
|
|
128
|
+
}
|
|
129
|
+
const match = line.match(pattern);
|
|
130
|
+
if (!match) {
|
|
131
|
+
return line;
|
|
132
|
+
}
|
|
133
|
+
replaced = true;
|
|
134
|
+
const indent = match[1] ?? '';
|
|
135
|
+
const spacing = match[2] ?? ' ';
|
|
136
|
+
const comment = match[4] ?? '';
|
|
137
|
+
return `${indent}${key}:${spacing}${normalizedValue}${comment}`;
|
|
138
|
+
});
|
|
139
|
+
return output.join('\n');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function removeTopLevelManifestFieldsInText(rawText, keys) {
|
|
143
|
+
const wanted = new Set((keys ?? []).map((key) => String(key ?? '').trim()).filter(Boolean));
|
|
144
|
+
if (wanted.size === 0) {
|
|
145
|
+
return String(rawText ?? '');
|
|
146
|
+
}
|
|
147
|
+
const lines = String(rawText ?? '').split('\n');
|
|
148
|
+
const output = [];
|
|
149
|
+
let skipping = false;
|
|
150
|
+
|
|
151
|
+
for (const line of lines) {
|
|
152
|
+
const trimmed = line.trim();
|
|
153
|
+
const indent = line.length - line.trimStart().length;
|
|
154
|
+
if (indent === 0 && !trimmed.startsWith('#')) {
|
|
155
|
+
const match = trimmed.match(/^([A-Za-z0-9_]+):/);
|
|
156
|
+
if (match && wanted.has(match[1])) {
|
|
157
|
+
skipping = true;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
skipping = false;
|
|
161
|
+
}
|
|
162
|
+
if (!skipping) {
|
|
163
|
+
output.push(line);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return output.join('\n');
|
|
167
|
+
}
|
|
168
|
+
|
|
113
169
|
async function fetchIconTo(options, cwd, destDir) {
|
|
114
170
|
if (!options['icon']) {
|
|
115
171
|
logger.warn(t('lzc_cli.lib.app.lpk_build.fetch_icon_to_icon_empty_fail', '图标icon 没有指定'));
|
|
@@ -250,6 +306,50 @@ function mergeBuildOptions(baseOptions, topOptions) {
|
|
|
250
306
|
});
|
|
251
307
|
}
|
|
252
308
|
|
|
309
|
+
function applyPkgIdSuffix(packageId, suffix) {
|
|
310
|
+
const normalizedPackageId = String(packageId ?? '').trim();
|
|
311
|
+
const normalizedSuffix = String(suffix ?? '').trim();
|
|
312
|
+
if (!normalizedSuffix) {
|
|
313
|
+
return normalizedPackageId;
|
|
314
|
+
}
|
|
315
|
+
if (!normalizedPackageId) {
|
|
316
|
+
throw new Error('package is empty, cannot apply pkg_id_suffix');
|
|
317
|
+
}
|
|
318
|
+
return `${normalizedPackageId}.${normalizedSuffix}`;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function validatePackageFileForArchiveFormat(hasPackageFile, archiveFormat) {
|
|
322
|
+
const format = String(archiveFormat ?? '')
|
|
323
|
+
.trim()
|
|
324
|
+
.toLowerCase();
|
|
325
|
+
if (format === 'tar' && !hasPackageFile) {
|
|
326
|
+
throw new Error('package.yml is required for tar-based LPK v2 packages');
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function hasBuildEnvEntries(envEntries) {
|
|
331
|
+
return Array.isArray(envEntries) && envEntries.length > 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function shouldUseV2PackageLayout({ forceV2 = false, hasPackageFile = false, hasImagesConfig = false, buildEnvEntries = [] } = {}) {
|
|
335
|
+
return !!forceV2 || !!hasPackageFile || !!hasImagesConfig || hasBuildEnvEntries(buildEnvEntries);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function logDeprecatedStaticFieldWarning(manifestPath, fields) {
|
|
339
|
+
if (!Array.isArray(fields) || fields.length === 0) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
logger.warn(`Building LPK v2. Static package fields in ${manifestPath} are deprecated and will be written to package.yml: ${fields.join(', ')}`);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function normalizeBuildOptions(options) {
|
|
346
|
+
const normalized = { ...(options ?? {}) };
|
|
347
|
+
if (Object.prototype.hasOwnProperty.call(normalized, 'envs')) {
|
|
348
|
+
normalized['envs'] = normalizeBuildEnvEntries(normalized['envs']);
|
|
349
|
+
}
|
|
350
|
+
return normalized;
|
|
351
|
+
}
|
|
352
|
+
|
|
253
353
|
function loadYamlIfExists(filePath) {
|
|
254
354
|
if (!filePath || !isFileExist(filePath)) {
|
|
255
355
|
return {};
|
|
@@ -264,16 +364,43 @@ async function loadTemplatedYamlIfExists(filePath, env) {
|
|
|
264
364
|
return yaml.load(await envTemplateFile(filePath, env)) ?? {};
|
|
265
365
|
}
|
|
266
366
|
|
|
367
|
+
function isDevBuildConfigName(buildConfigFile) {
|
|
368
|
+
return path.basename(String(buildConfigFile ?? '').trim()) === 'lzc-build.dev.yml';
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function resolveParentBuildConfigPath(optionsFilePath) {
|
|
372
|
+
if (!isDevBuildConfigName(optionsFilePath)) {
|
|
373
|
+
return '';
|
|
374
|
+
}
|
|
375
|
+
const parentPath = path.join(path.dirname(optionsFilePath), 'lzc-build.yml');
|
|
376
|
+
if (!isFileExist(parentPath)) {
|
|
377
|
+
return '';
|
|
378
|
+
}
|
|
379
|
+
return parentPath;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function detectBuildProfile(buildConfigFile) {
|
|
383
|
+
return isDevBuildConfigName(buildConfigFile) ? 'dev' : 'release';
|
|
384
|
+
}
|
|
385
|
+
|
|
267
386
|
export class LpkBuild {
|
|
268
|
-
constructor(cwd, buildConfigFile) {
|
|
387
|
+
constructor(cwd, buildConfigFile, options = {}) {
|
|
269
388
|
this.pwd = cwd ?? process.cwd();
|
|
389
|
+
this.forceV2 = !!options.forceV2;
|
|
270
390
|
|
|
271
391
|
this.optionsFilePath = path.join(this.pwd, buildConfigFile);
|
|
272
|
-
this.
|
|
273
|
-
this.options = mergeBuildOptions(loadYamlIfExists(this.
|
|
392
|
+
this.parentOptionsFilePath = resolveParentBuildConfigPath(this.optionsFilePath);
|
|
393
|
+
this.options = normalizeBuildOptions(mergeBuildOptions(loadYamlIfExists(this.parentOptionsFilePath), loadYamlIfExists(this.optionsFilePath)));
|
|
394
|
+
this.buildProfile = detectBuildProfile(this.optionsFilePath);
|
|
274
395
|
|
|
275
396
|
this.manifestFilePath = this.options['manifest'] ? path.join(this.pwd, this.options['manifest']) : path.join(this.pwd, 'lzc-manifest.yml');
|
|
397
|
+
this.packageFilePath = path.join(this.pwd, PACKAGE_FILE_NAME);
|
|
276
398
|
this.manifest = null;
|
|
399
|
+
this.sourceManifest = null;
|
|
400
|
+
this.packageInfo = null;
|
|
401
|
+
this.hasPackageFile = false;
|
|
402
|
+
this.buildVars = null;
|
|
403
|
+
this.preprocessedManifestText = '';
|
|
277
404
|
|
|
278
405
|
this.beforeBuildPackageFn = [];
|
|
279
406
|
this.beforeDumpYamlFn = [];
|
|
@@ -283,12 +410,25 @@ export class LpkBuild {
|
|
|
283
410
|
|
|
284
411
|
// init 时替换 lzc-build.yml 中的模板字段
|
|
285
412
|
async init() {
|
|
286
|
-
const
|
|
413
|
+
const sourceLoaded = loadEffectiveManifest(this.manifestFilePath, {
|
|
414
|
+
packageFilePath: this.packageFilePath,
|
|
415
|
+
});
|
|
287
416
|
const primitive = convenientEnv();
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
const
|
|
291
|
-
|
|
417
|
+
const baseTemplateEnv = Object.assign({}, primitive, sourceLoaded.manifest);
|
|
418
|
+
const firstParentOptions = await loadTemplatedYamlIfExists(this.parentOptionsFilePath, baseTemplateEnv);
|
|
419
|
+
const firstTopOptions = await loadTemplatedYamlIfExists(this.optionsFilePath, baseTemplateEnv);
|
|
420
|
+
const firstOptions = normalizeBuildOptions(mergeBuildOptions(firstParentOptions, firstTopOptions));
|
|
421
|
+
const buildVars = buildVarsFromEnvEntries(firstOptions['envs']);
|
|
422
|
+
const finalTemplateEnv = Object.assign({}, baseTemplateEnv, buildVars);
|
|
423
|
+
const parentOptions = await loadTemplatedYamlIfExists(this.parentOptionsFilePath, finalTemplateEnv);
|
|
424
|
+
const topOptions = await loadTemplatedYamlIfExists(this.optionsFilePath, finalTemplateEnv);
|
|
425
|
+
this.options = normalizeBuildOptions(mergeBuildOptions(parentOptions, topOptions));
|
|
426
|
+
this.manifest = null;
|
|
427
|
+
this.sourceManifest = null;
|
|
428
|
+
this.packageInfo = null;
|
|
429
|
+
this.hasPackageFile = false;
|
|
430
|
+
this.buildVars = buildVarsFromEnvEntries(this.options['envs']);
|
|
431
|
+
this.preprocessedManifestText = '';
|
|
292
432
|
return this;
|
|
293
433
|
}
|
|
294
434
|
|
|
@@ -314,17 +454,40 @@ export class LpkBuild {
|
|
|
314
454
|
this.beforeDumpLpkFn.push(fn);
|
|
315
455
|
}
|
|
316
456
|
|
|
457
|
+
getBuildVars() {
|
|
458
|
+
if (!this.buildVars) {
|
|
459
|
+
this.buildVars = buildVarsFromEnvEntries(this.options['envs']);
|
|
460
|
+
}
|
|
461
|
+
return this.buildVars;
|
|
462
|
+
}
|
|
463
|
+
|
|
317
464
|
async getManifest() {
|
|
318
465
|
if (this.manifest) {
|
|
319
466
|
return this.manifest;
|
|
320
467
|
}
|
|
321
468
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
469
|
+
this.preprocessedManifestText = preprocessManifestFile(this.manifestFilePath, {
|
|
470
|
+
profile: this.buildProfile,
|
|
471
|
+
envs: this.getBuildVars(),
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
const loaded = loadEffectiveManifest(this.manifestFilePath, {
|
|
475
|
+
manifestText: this.preprocessedManifestText,
|
|
476
|
+
packageFilePath: this.packageFilePath,
|
|
477
|
+
});
|
|
478
|
+
this.excpManifest = loaded.excpManifest;
|
|
479
|
+
this.sourceManifest = loaded.sourceManifest;
|
|
480
|
+
this.packageInfo = loaded.packageInfo;
|
|
481
|
+
this.hasPackageFile = loaded.hasPackageFile;
|
|
482
|
+
this.manifest = loaded.manifest;
|
|
483
|
+
|
|
484
|
+
const packageWithSuffix = applyPkgIdSuffix(this.manifest['package'], this.options['pkg_id_suffix']);
|
|
485
|
+
if (packageWithSuffix !== this.manifest['package']) {
|
|
486
|
+
this.manifest = { ...this.manifest, package: packageWithSuffix };
|
|
487
|
+
if (this.hasPackageFile) {
|
|
488
|
+
this.packageInfo = { ...(this.packageInfo ?? {}), package: packageWithSuffix };
|
|
489
|
+
}
|
|
490
|
+
}
|
|
328
491
|
|
|
329
492
|
if (!isValidPackageName(this.manifest['package'])) {
|
|
330
493
|
throw t('lzc_cli.lib.app.lpk_build.get_manifest_package_name_fail', `{{ package }} 含有非法字符,请使用正确的包名格式(java的包名格式),如:cloud.lazycat.apps.video`, {
|
|
@@ -332,7 +495,7 @@ export class LpkBuild {
|
|
|
332
495
|
});
|
|
333
496
|
}
|
|
334
497
|
|
|
335
|
-
if (!this.manifest
|
|
498
|
+
if (!this.manifest?.application?.subdomain) {
|
|
336
499
|
throw t('lzc_cli.lib.app.lpk_build.get_manifest_subdomain_empty', `application 模块下的 subdomain 字段不能为空`);
|
|
337
500
|
}
|
|
338
501
|
|
|
@@ -340,6 +503,8 @@ export class LpkBuild {
|
|
|
340
503
|
}
|
|
341
504
|
|
|
342
505
|
async exec() {
|
|
506
|
+
await this.getManifest();
|
|
507
|
+
|
|
343
508
|
if (this.beforeBuildPackageFn.length > 0) {
|
|
344
509
|
this.options = await this.beforeBuildPackageFn.reduce(async (prev, curr) => {
|
|
345
510
|
return await curr(await prev);
|
|
@@ -352,6 +517,7 @@ export class LpkBuild {
|
|
|
352
517
|
let p = spawn.sync(cmd, [cmdArgs, this.options['buildscript']], {
|
|
353
518
|
cwd: this.pwd,
|
|
354
519
|
stdio: 'inherit',
|
|
520
|
+
env: { ...process.env, ...this.getBuildVars() },
|
|
355
521
|
});
|
|
356
522
|
if (p.status != 0) {
|
|
357
523
|
throw t('lzc_cli.lib.app.lpk_build.exec_build_fail', `构建失败`);
|
|
@@ -379,31 +545,37 @@ export class LpkBuild {
|
|
|
379
545
|
let browserExtension = this.options['browser-extension'];
|
|
380
546
|
let aiPodService = this.options['ai-pod-service'];
|
|
381
547
|
try {
|
|
382
|
-
|
|
548
|
+
const hasContentDir = !!contentdir;
|
|
549
|
+
const needsContentArchive = hasContentDir || this.beforeTarContentFn.length > 0;
|
|
550
|
+
let tempContentDir = '';
|
|
551
|
+
if (hasContentDir) {
|
|
383
552
|
contentdir = path.resolve(this.pwd, contentdir);
|
|
384
553
|
if (!isDirExist(contentdir)) {
|
|
385
554
|
throw `${contentdir} 不存在`;
|
|
386
555
|
}
|
|
387
556
|
} else {
|
|
388
557
|
logger.warn(t('lzc_cli.lib.app.lpk_build.exec_skip_copy_contentdir', '跳过拷贝 contentdir 内容'));
|
|
389
|
-
// 当没有指定的 contentdir 的时候,也生成一个空的文件夹
|
|
390
|
-
// 原因是:可能其他地方会复制内容进来,像 devshell 中的会在打包的时候,将ssh key拷贝进来
|
|
391
|
-
contentdir = fs.mkdtempSync(path.join(tempDir, 'fake-contentdir'));
|
|
392
558
|
}
|
|
393
559
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
560
|
+
if (needsContentArchive) {
|
|
561
|
+
if (!hasContentDir) {
|
|
562
|
+
// 没有显式 contentdir 时,仅在 hook 需要写入内容时创建临时目录。
|
|
563
|
+
tempContentDir = fs.mkdtempSync(path.join(tempDir, 'fake-contentdir'));
|
|
564
|
+
contentdir = tempContentDir;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (this.beforeTarContentFn.length > 0) {
|
|
568
|
+
await this.beforeTarContentFn.reduce(async (prev, curr) => {
|
|
569
|
+
let _prev = await prev;
|
|
570
|
+
await curr(_prev, this.options);
|
|
571
|
+
return _prev;
|
|
572
|
+
}, contentdir);
|
|
573
|
+
}
|
|
574
|
+
await tarContentDir(['./'], path.join(tempDir, 'content.tar'), contentdir);
|
|
401
575
|
}
|
|
402
|
-
await tarContentDir(['./'], path.join(tempDir, 'content.tar'), contentdir);
|
|
403
576
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
fs.rmSync(contentdir, { recursive: true });
|
|
577
|
+
if (tempContentDir) {
|
|
578
|
+
fs.rmSync(tempContentDir, { recursive: true });
|
|
407
579
|
}
|
|
408
580
|
|
|
409
581
|
if (browserExtension) {
|
|
@@ -439,6 +611,9 @@ export class LpkBuild {
|
|
|
439
611
|
let manifest = await this.getManifest();
|
|
440
612
|
if (process.env.LZC_VERSION) {
|
|
441
613
|
manifest.version = process.env.LZC_VERSION;
|
|
614
|
+
if (this.hasPackageFile) {
|
|
615
|
+
this.packageInfo = { ...(this.packageInfo ?? {}), version: process.env.LZC_VERSION };
|
|
616
|
+
}
|
|
442
617
|
}
|
|
443
618
|
if (this.beforeDumpYamlFn.length > 0) {
|
|
444
619
|
manifest = await this.beforeDumpYamlFn.reduce(async (prev, curr) => {
|
|
@@ -461,19 +636,41 @@ export class LpkBuild {
|
|
|
461
636
|
|
|
462
637
|
const hasImagesConfig = !!this.options['images'];
|
|
463
638
|
|
|
464
|
-
let useTarPackage = false;
|
|
465
639
|
let embeddedImageSummary = null;
|
|
466
640
|
if (hasImagesConfig) {
|
|
467
641
|
const buildResult = await buildConfiguredImagesToTempDir(this.options['images'], manifest, this.pwd, tempDir, {
|
|
468
642
|
remote: this.options['remote'],
|
|
469
643
|
});
|
|
470
644
|
if (buildResult.imageCount > 0) {
|
|
471
|
-
useTarPackage = true;
|
|
472
645
|
embeddedImageSummary = buildResult;
|
|
473
646
|
manifest = rewriteManifestEmbeddedImages(manifest, buildResult.resolvedImageByAlias);
|
|
474
647
|
}
|
|
475
648
|
}
|
|
476
|
-
|
|
649
|
+
|
|
650
|
+
const useV2PackageLayout = shouldUseV2PackageLayout({
|
|
651
|
+
forceV2: this.forceV2,
|
|
652
|
+
hasPackageFile: this.hasPackageFile,
|
|
653
|
+
hasImagesConfig,
|
|
654
|
+
buildEnvEntries: this.options['envs'],
|
|
655
|
+
});
|
|
656
|
+
if (useV2PackageLayout) {
|
|
657
|
+
logDeprecatedStaticFieldWarning(this.manifestFilePath, findManifestStaticFields(this.sourceManifest));
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
let manifestOutput = manifest;
|
|
661
|
+
let packageInfoOutput = null;
|
|
662
|
+
if (useV2PackageLayout) {
|
|
663
|
+
const split = splitManifestAndPackageInfo(manifest, this.packageInfo);
|
|
664
|
+
manifestOutput = split.manifest;
|
|
665
|
+
packageInfoOutput = split.packageInfo;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const archiveFormat = useV2PackageLayout ? 'tar' : 'zip';
|
|
669
|
+
validatePackageFileForArchiveFormat(!!packageInfoOutput, archiveFormat);
|
|
670
|
+
if (!useV2PackageLayout) {
|
|
671
|
+
logger.warn('Building legacy LPK v1 metadata layout. Run "lzc-cli migrate" to move static package fields into package.yml.');
|
|
672
|
+
}
|
|
673
|
+
if (embeddedImageSummary && embeddedImageSummary.imageCount > 0) {
|
|
477
674
|
const contentTar = path.join(tempDir, 'content.tar');
|
|
478
675
|
const contentTarGz = path.join(tempDir, 'content.tar.gz');
|
|
479
676
|
if (isFileExist(contentTar)) {
|
|
@@ -482,19 +679,32 @@ export class LpkBuild {
|
|
|
482
679
|
}
|
|
483
680
|
}
|
|
484
681
|
|
|
485
|
-
if (process.env.LZC_MANIFEST_TEMPLATE &&
|
|
486
|
-
logger.debug('copy
|
|
487
|
-
fs.
|
|
682
|
+
if (process.env.LZC_MANIFEST_TEMPLATE && archiveFormat === 'zip') {
|
|
683
|
+
logger.debug('copy processed manifest\n', this.manifestFilePath);
|
|
684
|
+
fs.writeFileSync(path.join(tempDir, 'manifest.yml'), this.preprocessedManifestText);
|
|
488
685
|
} else {
|
|
489
|
-
logger.debug('manifest\n',
|
|
490
|
-
// 异常的manifest,就将源文件给转到lpk内
|
|
686
|
+
logger.debug('manifest\n', manifestOutput);
|
|
491
687
|
if (this.excpManifest) {
|
|
492
|
-
|
|
688
|
+
let rawManifest = this.preprocessedManifestText || fs.readFileSync(this.manifestFilePath, 'utf8');
|
|
689
|
+
if (archiveFormat === 'zip') {
|
|
690
|
+
rawManifest = rewriteTopLevelManifestScalarInText(rawManifest, 'package', manifest.package);
|
|
691
|
+
rawManifest = rewriteTopLevelManifestScalarInText(rawManifest, 'version', manifest.version);
|
|
692
|
+
} else {
|
|
693
|
+
rawManifest = removeTopLevelManifestFieldsInText(rawManifest, Object.keys(packageInfoOutput ?? {}));
|
|
694
|
+
}
|
|
695
|
+
if (embeddedImageSummary?.resolvedImageByAlias) {
|
|
696
|
+
rawManifest = rewriteManifestEmbeddedImagesInText(rawManifest, embeddedImageSummary.resolvedImageByAlias);
|
|
697
|
+
}
|
|
698
|
+
fs.writeFileSync(path.join(tempDir, 'manifest.yml'), rawManifest);
|
|
493
699
|
} else {
|
|
494
|
-
dumpToYaml(
|
|
700
|
+
dumpToYaml(manifestOutput, path.join(tempDir, 'manifest.yml'));
|
|
495
701
|
}
|
|
496
702
|
}
|
|
497
703
|
|
|
704
|
+
if (packageInfoOutput) {
|
|
705
|
+
dumpToYaml(packageInfoOutput, path.join(tempDir, PACKAGE_FILE_NAME));
|
|
706
|
+
}
|
|
707
|
+
|
|
498
708
|
// compose.override.yml
|
|
499
709
|
if (this.options['compose_override']) {
|
|
500
710
|
dumpToYaml(this.options['compose_override'], path.join(tempDir, 'compose.override.yml'));
|
|
@@ -513,7 +723,7 @@ export class LpkBuild {
|
|
|
513
723
|
packName = path.resolve(pkgout, `${manifest.package}-v${manifest.version}${ext}`);
|
|
514
724
|
}
|
|
515
725
|
|
|
516
|
-
const lpkPath = await archiveFolderTo(tempDir, packName,
|
|
726
|
+
const lpkPath = await archiveFolderTo(tempDir, packName, archiveFormat);
|
|
517
727
|
logger.info(
|
|
518
728
|
`${t('lzc_cli.lib.app.lpk_build.exec_output_lpk_path', '输出lpk包 {{ path }}', {
|
|
519
729
|
path: lpkPath.path,
|