@lazycatcloud/lzc-cli 1.3.1 → 1.3.3
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/appstore/index.js +91 -16
- package/lib/appstore/login.js +15 -5
- package/lib/appstore/publish.js +11 -6
- package/package.json +1 -1
package/changelog.md
CHANGED
package/lib/appstore/index.js
CHANGED
|
@@ -71,33 +71,108 @@ export function appstoreCommand(program) {
|
|
|
71
71
|
command: "copy-image <imageName>",
|
|
72
72
|
desc: "复制镜像至懒猫微服官方源",
|
|
73
73
|
handler: async ({ imageName }) => {
|
|
74
|
-
const
|
|
74
|
+
const uploadUrl = `${appStoreServerUrl}/api/v3/developer/app/docker/image/push/v3/copy?image=${imageName}`
|
|
75
|
+
const progressUrl = `${appStoreServerUrl}/api/v3/developer/app/docker/image/push/v3/progress?image=${imageName}`
|
|
75
76
|
logger.info(
|
|
76
77
|
`Waiting ... ( copy ${imageName} to lazycat offical registry)`
|
|
77
78
|
)
|
|
78
79
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
const resp = await request(uploadUrl)
|
|
81
|
+
if (resp.ok) {
|
|
82
|
+
logger.info("uploading")
|
|
83
|
+
} else {
|
|
84
|
+
logger.error("error: ", resp, await resp.text())
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
sleep(1000)
|
|
88
|
+
let prevLineCount = 0; // 新增:记录上次输出行数
|
|
89
|
+
let layers = []
|
|
90
|
+
|
|
91
|
+
let refreshProgress = (lys) => {
|
|
92
|
+
// 关键修改:动态回退多行
|
|
93
|
+
process.stdout.write('\x1B[?25l'); // 隐藏光标
|
|
94
|
+
if (prevLineCount > 0) {
|
|
95
|
+
process.stdout.write(`\x1B[${prevLineCount}A`); // 移动光标到之前输出的起始行
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 构建多行进度字符串
|
|
99
|
+
let output = [];
|
|
100
|
+
(lys || []).forEach(v => {
|
|
101
|
+
const progressBar = '#'.repeat(v.progress) + ' '.repeat(100 - v.progress);
|
|
102
|
+
output.push(`${v.hash.substring(0, 8)}: [${progressBar}] ${v.progress}%`);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// 清除旧行并写入新内容
|
|
106
|
+
output.forEach(line => {
|
|
107
|
+
process.stdout.write('\x1B[2K'); // 清除当前行
|
|
108
|
+
process.stdout.write(line + '\n');
|
|
109
|
+
});
|
|
110
|
+
prevLineCount = output.length; // 记录本次输出行数
|
|
111
|
+
process.stdout.write('\x1B[?25h'); // 恢复光标显示
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (; ;) {
|
|
115
|
+
const pgsResp = await request(progressUrl);
|
|
116
|
+
if (pgsResp.ok) {
|
|
117
|
+
const pgs = JSON.parse(await pgsResp.text());
|
|
118
|
+
if (pgs.finished) {
|
|
119
|
+
(layers ? layers : [])?.forEach(v => {
|
|
120
|
+
v.progress = 100
|
|
121
|
+
});
|
|
122
|
+
refreshProgress(layers)
|
|
123
|
+
process.stdout.write("\n");
|
|
124
|
+
if (pgs.errmsg) {
|
|
125
|
+
logger.error("failed to copyimage ", imageName, " err:", pgs.errmsg);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
logger.info("uploaded: ", pgs.lzc_image);
|
|
129
|
+
break;
|
|
88
130
|
}
|
|
89
|
-
|
|
131
|
+
layers = pgs?.layers
|
|
132
|
+
refreshProgress(layers)
|
|
133
|
+
await sleep(1000);
|
|
90
134
|
} else {
|
|
91
|
-
logger.error("error: ", await resp.text())
|
|
135
|
+
logger.error("error: ", await resp.text());
|
|
136
|
+
break;
|
|
92
137
|
}
|
|
93
|
-
|
|
94
|
-
break
|
|
95
138
|
}
|
|
96
139
|
} catch (err) {
|
|
97
140
|
console.error(err)
|
|
98
141
|
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
command: "my-images",
|
|
146
|
+
desc: "查看已上传镜像列表",
|
|
147
|
+
handler: async () => {
|
|
148
|
+
const url = `${appStoreServerUrl}/api/v3/developer/app/docker/image/push/v3/myimages`
|
|
149
|
+
try {
|
|
150
|
+
const resp = await request(url)
|
|
151
|
+
if (resp.ok) {
|
|
152
|
+
const ilist = JSON.parse(await resp.text())
|
|
153
|
+
ilist.sort((a, b) => {
|
|
154
|
+
return new Date(b.UpdatedAt).getTime() - new Date(a.UpdatedAt).getTime()
|
|
155
|
+
})
|
|
156
|
+
const tableItems = []
|
|
157
|
+
ilist?.forEach(v => {
|
|
158
|
+
if (v.errmsg) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
tableItems.push({
|
|
162
|
+
"Source Image": v.source_image,
|
|
163
|
+
"Lazycat Image": v.lzc_image,
|
|
164
|
+
"Updated At": new Date(v.UpdatedAt).toLocaleString(),
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
console.table(tableItems)
|
|
168
|
+
} else {
|
|
169
|
+
logger.error("error: ", await resp.text())
|
|
170
|
+
}
|
|
171
|
+
} catch (err) {
|
|
172
|
+
console.error(err)
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
},
|
|
101
176
|
]
|
|
102
177
|
|
|
103
178
|
program.command({
|
package/lib/appstore/login.js
CHANGED
|
@@ -31,11 +31,17 @@ async function login(username, password) {
|
|
|
31
31
|
})
|
|
32
32
|
.then(async (res) => {
|
|
33
33
|
let bodyText = await res.text()
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
try {
|
|
35
|
+
let body = JSON.parse(bodyText)
|
|
36
|
+
if (body.success) {
|
|
37
|
+
return Promise.resolve(body.data)
|
|
38
|
+
}
|
|
39
|
+
throw body
|
|
40
|
+
} catch (error) {
|
|
41
|
+
error.responseStatus = res.status
|
|
42
|
+
error.responseBody = bodyText
|
|
43
|
+
return Promise.reject(error)
|
|
37
44
|
}
|
|
38
|
-
return Promise.reject(body.message)
|
|
39
45
|
})
|
|
40
46
|
.then((data) => {
|
|
41
47
|
env.set({ token: data.token }, true)
|
|
@@ -94,7 +100,11 @@ async function interactiveLogin() {
|
|
|
94
100
|
await login(info.username, info.password)
|
|
95
101
|
} catch (e) {
|
|
96
102
|
logger.debug("login error: ", e)
|
|
97
|
-
|
|
103
|
+
if (e?.errorCode == 0 || e?.message == "密码错误") {
|
|
104
|
+
logger.error("帐号或者密码错误,请重新输入!")
|
|
105
|
+
} else {
|
|
106
|
+
logger.error(`登录失败,${e?.message ?? e}`)
|
|
107
|
+
}
|
|
98
108
|
return interactiveLogin()
|
|
99
109
|
}
|
|
100
110
|
}
|
package/lib/appstore/publish.js
CHANGED
|
@@ -224,12 +224,6 @@ export class Publish {
|
|
|
224
224
|
|
|
225
225
|
await autoLogin()
|
|
226
226
|
|
|
227
|
-
if (!changelog) {
|
|
228
|
-
const answer = await askChangeLog(locale)
|
|
229
|
-
changelog = answer.changelog
|
|
230
|
-
}
|
|
231
|
-
changelog = changelog.trim() // clean space ^:)
|
|
232
|
-
|
|
233
227
|
logger.info("正在提交审核...")
|
|
234
228
|
const form = new FormData()
|
|
235
229
|
form.append("file", fs.createReadStream(pkgPath))
|
|
@@ -248,6 +242,17 @@ export class Publish {
|
|
|
248
242
|
}
|
|
249
243
|
const lpkInfo = await JSON.parse(text)
|
|
250
244
|
logger.debug("upload lpk response", lpkInfo)
|
|
245
|
+
if (res.status >= 400) {
|
|
246
|
+
logger.error(`LPK 文件上传失败,err: ${lpkInfo?.message ?? lpkInfo}`)
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 填写更新日志
|
|
251
|
+
if (!changelog) {
|
|
252
|
+
const answer = await askChangeLog(locale)
|
|
253
|
+
changelog = answer.changelog
|
|
254
|
+
}
|
|
255
|
+
changelog = changelog.trim() // clean space ^:)
|
|
251
256
|
|
|
252
257
|
const sendURL = this.baseUrl + `/app/${lpkInfo.package}/review/create`
|
|
253
258
|
logger.debug("publish url is", sendURL)
|