@lazycatcloud/lzc-cli 1.3.12 → 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 +9 -0
- package/lib/app/apkshell.js +37 -40
- package/lib/app/index.js +187 -186
- 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 -214
- package/lib/appstore/login.js +146 -143
- package/lib/appstore/prePublish.js +101 -100
- package/lib/appstore/publish.js +253 -256
- package/lib/box/index.js +82 -77
- package/lib/config/index.js +58 -54
- package/lib/debug_bridge.js +280 -330
- 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 +536 -552
- 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/appstore/index.js
CHANGED
|
@@ -1,224 +1,215 @@
|
|
|
1
|
-
import { Publish } from
|
|
2
|
-
import logger from
|
|
3
|
-
import { PrePublish } from
|
|
4
|
-
import { reLogin, request } from
|
|
5
|
-
import fs from
|
|
6
|
-
import { sleep } from
|
|
7
|
-
import {
|
|
1
|
+
import { Publish } from './publish.js';
|
|
2
|
+
import logger from 'loglevel';
|
|
3
|
+
import { PrePublish } from './prePublish.js';
|
|
4
|
+
import { reLogin, request } from './login.js';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { sleep } from '../utils.js';
|
|
7
|
+
import { t } from '../i18n/index.js';
|
|
8
|
+
import { appStoreServerUrl } from './env.js';
|
|
8
9
|
|
|
9
10
|
export function appstoreCommand(program) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
11
|
+
let subCommands = [
|
|
12
|
+
{
|
|
13
|
+
command: 'login',
|
|
14
|
+
desc: t('lzc_cli.lib.appstore.index.login_cmd_desc', '登录'),
|
|
15
|
+
handler: async () => {
|
|
16
|
+
await reLogin();
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
command: 'pre-publish <pkgPath>',
|
|
21
|
+
desc: t('lzc_cli.lib.appstore.index.pre_publish_cmd_desc', '发布到内测'),
|
|
22
|
+
builder: (args) => {
|
|
23
|
+
args.option('c', {
|
|
24
|
+
alias: 'changelog',
|
|
25
|
+
describe: t('lzc_cli.lib.appstore.index.pre_publish_cmd_changelog_desc', '更改日志'),
|
|
26
|
+
type: 'string',
|
|
27
|
+
});
|
|
28
|
+
args.option('F', {
|
|
29
|
+
alias: 'file',
|
|
30
|
+
describe: t('lzc_cli.lib.appstore.index.pre_publish_cmd_changelog_file_desc', '更改日志文件'),
|
|
31
|
+
type: 'string',
|
|
32
|
+
});
|
|
33
|
+
args.option('G', {
|
|
34
|
+
alias: 'gid',
|
|
35
|
+
describe: t('lzc_cli.lib.appstore.index.pre_publish_cmd_gid_desc', '内测组ID'),
|
|
36
|
+
type: 'string',
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
handler: async ({ pkgPath, changelog, file, gid }) => {
|
|
40
|
+
const p = new PrePublish();
|
|
41
|
+
if (!changelog && file) {
|
|
42
|
+
changelog = fs.readFileSync(file, 'utf8');
|
|
43
|
+
}
|
|
44
|
+
await p.publish(pkgPath, changelog, gid);
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
command: 'publish <pkgPath>',
|
|
49
|
+
desc: t('lzc_cli.lib.appstore.index.publish_cmd_desc', '发布到商店'),
|
|
50
|
+
builder: (args) => {
|
|
51
|
+
args.option('c', {
|
|
52
|
+
alias: 'changelog',
|
|
53
|
+
describe: t('lzc_cli.lib.appstore.index.publish_cmd_changelog_desc', '更新日志'),
|
|
54
|
+
type: 'string',
|
|
55
|
+
});
|
|
56
|
+
args.option('clang', {
|
|
57
|
+
alias: 'changelog-locale',
|
|
58
|
+
describe: t('lzc_cli.lib.appstore.index.publish_cmd_changelog_lang_desc', '更新日志语言标识,默认通过当前 shell 语言环境识别'),
|
|
59
|
+
type: 'string',
|
|
60
|
+
});
|
|
61
|
+
args.option('F', {
|
|
62
|
+
alias: 'file',
|
|
63
|
+
describe: t('lzc_cli.lib.appstore.index.publish_cmd_changelog_file_desc', '更新日志文件'),
|
|
64
|
+
type: 'string',
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
handler: async ({ pkgPath, changelog, changelogLocale, file }) => {
|
|
68
|
+
const locale = changelogLocale ?? program.locale();
|
|
69
|
+
const p = new Publish();
|
|
70
|
+
if (!changelog && file) {
|
|
71
|
+
changelog = fs.readFileSync(file, 'utf8');
|
|
72
|
+
}
|
|
73
|
+
await p.publish(pkgPath, changelog, locale);
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
command: 'copy-image <img>',
|
|
78
|
+
desc: t('lzc_cli.lib.appstore.index.copy_image_cmd_desc', `复制镜像至懒猫微服官方源`),
|
|
79
|
+
builder: (yargs) => {
|
|
80
|
+
yargs.option('arch', {
|
|
81
|
+
describe: "image arch 'amd64', 'arm64'",
|
|
82
|
+
default: 'amd64',
|
|
83
|
+
type: 'string',
|
|
84
|
+
});
|
|
85
|
+
// 出于 CI 目的增加控制是否打印进度选项
|
|
86
|
+
yargs.option('trace-level', {
|
|
87
|
+
describe: "trace level 'verbose', 'quiet'",
|
|
88
|
+
default: 'verbose',
|
|
89
|
+
type: 'string',
|
|
90
|
+
});
|
|
91
|
+
return yargs;
|
|
92
|
+
},
|
|
93
|
+
handler: async ({ img: imageName, arch: platform, traceLevel }) => {
|
|
94
|
+
const uploadUrl = `${appStoreServerUrl}/api/v3/developer/app/docker/image/push/v3/copy?image=${imageName}&platform=${platform}`;
|
|
95
|
+
const progressUrl = `${appStoreServerUrl}/api/v3/developer/app/docker/image/push/v3/progress?image=${imageName}&platform=${platform}`;
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const useCI = traceLevel === 'quiet';
|
|
98
|
+
const _logger = logger;
|
|
99
|
+
_logger.setLevel(useCI ? _logger.levels.ERROR : _logger.levels.INFO);
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
let prevLineCount = 0 // 新增:记录上次输出行数
|
|
113
|
-
let layers = []
|
|
101
|
+
_logger.info(`Waiting ... ( copy ${imageName} (${platform}) to lazycat offical registry)`);
|
|
102
|
+
try {
|
|
103
|
+
const resp = await request(uploadUrl);
|
|
104
|
+
if (resp.ok) {
|
|
105
|
+
_logger.info('uploading');
|
|
106
|
+
} else {
|
|
107
|
+
_logger.error('error: ', resp, await resp.text());
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
sleep(1000);
|
|
111
|
+
let prevLineCount = 0; // 新增:记录上次输出行数
|
|
112
|
+
let layers = [];
|
|
114
113
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
114
|
+
let refreshProgress = (lys) => {
|
|
115
|
+
if (useCI) {
|
|
116
|
+
// 日志级别为 quiet 时不输出进度(用于 CI 目的)
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// 关键修改:动态回退多行
|
|
120
|
+
process.stdout.write('\x1B[?25l'); // 隐藏光标
|
|
121
|
+
if (prevLineCount > 0) {
|
|
122
|
+
process.stdout.write(`\x1B[${prevLineCount}A`); // 移动光标到之前输出的起始行
|
|
123
|
+
}
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
`${v.hash.substring(0, 8)}: [${progressBar}] ${v.progress}%`
|
|
133
|
-
)
|
|
134
|
-
})
|
|
125
|
+
// 构建多行进度字符串
|
|
126
|
+
let output = [];
|
|
127
|
+
(lys || []).forEach((v) => {
|
|
128
|
+
const progressBar = '#'.repeat(v.progress) + ' '.repeat(100 - v.progress);
|
|
129
|
+
output.push(`${v.hash.substring(0, 8)}: [${progressBar}] ${v.progress}%`);
|
|
130
|
+
});
|
|
135
131
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
132
|
+
// 清除旧行并写入新内容
|
|
133
|
+
output.forEach((line) => {
|
|
134
|
+
process.stdout.write('\x1B[2K'); // 清除当前行
|
|
135
|
+
process.stdout.write(line + '\n');
|
|
136
|
+
});
|
|
137
|
+
prevLineCount = output.length; // 记录本次输出行数
|
|
138
|
+
process.stdout.write('\x1B[?25h'); // 恢复光标显示
|
|
139
|
+
};
|
|
144
140
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
console.error(err)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
]
|
|
141
|
+
for (;;) {
|
|
142
|
+
const pgsResp = await request(progressUrl);
|
|
143
|
+
if (pgsResp.ok) {
|
|
144
|
+
const pgs = JSON.parse(await pgsResp.text());
|
|
145
|
+
if (pgs.finished) {
|
|
146
|
+
(layers ? layers : [])?.forEach((v) => {
|
|
147
|
+
v.progress = 100;
|
|
148
|
+
});
|
|
149
|
+
if (pgs.errmsg) {
|
|
150
|
+
throw Error(`failed to copyimage ${imageName} err: ${pgs.errmsg}`);
|
|
151
|
+
}
|
|
152
|
+
if (!useCI) {
|
|
153
|
+
refreshProgress(layers);
|
|
154
|
+
process.stdout.write('\n');
|
|
155
|
+
_logger.info('uploaded: ', pgs.lzc_image);
|
|
156
|
+
} else {
|
|
157
|
+
// 日志级别为 quiet 时仅输出结果(用于 CI 目的)
|
|
158
|
+
console.log(pgs.lzc_image);
|
|
159
|
+
}
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
layers = pgs?.layers;
|
|
163
|
+
refreshProgress(layers);
|
|
164
|
+
await sleep(1000);
|
|
165
|
+
} else {
|
|
166
|
+
throw Error(`error: ${await resp.text()}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} catch (err) {
|
|
170
|
+
_logger.error(err?.message ?? 'unknown exception');
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
command: 'my-images',
|
|
176
|
+
desc: t('lzc_cli.lib.appstore.index.my_images_cmd_desc', '查看已上传镜像列表'),
|
|
177
|
+
handler: async () => {
|
|
178
|
+
const url = `${appStoreServerUrl}/api/v3/developer/app/docker/image/push/v3/myimages`;
|
|
179
|
+
try {
|
|
180
|
+
const resp = await request(url);
|
|
181
|
+
if (resp.ok) {
|
|
182
|
+
const ilist = JSON.parse(await resp.text());
|
|
183
|
+
ilist.sort((a, b) => {
|
|
184
|
+
return new Date(b.UpdatedAt).getTime() - new Date(a.UpdatedAt).getTime();
|
|
185
|
+
});
|
|
186
|
+
const tableItems = [];
|
|
187
|
+
ilist?.forEach((v) => {
|
|
188
|
+
if (v.errmsg) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
tableItems.push({
|
|
192
|
+
'Source Image': v.source_image,
|
|
193
|
+
'Lazycat Image': v.lzc_image,
|
|
194
|
+
'Updated At': new Date(v.UpdatedAt).toLocaleString(),
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
console.table(tableItems);
|
|
198
|
+
} else {
|
|
199
|
+
logger.error('error: ', await resp.text());
|
|
200
|
+
}
|
|
201
|
+
} catch (err) {
|
|
202
|
+
console.error(err);
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
];
|
|
216
207
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
208
|
+
program.command({
|
|
209
|
+
command: 'appstore',
|
|
210
|
+
desc: t('lzc_cli.lib.appstore.index.appstore_cmd_desc', '应用商店'),
|
|
211
|
+
builder: (args) => {
|
|
212
|
+
args.command(subCommands);
|
|
213
|
+
},
|
|
214
|
+
});
|
|
224
215
|
}
|