@lazycatcloud/lzc-cli 1.2.62 → 1.2.64
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 +11 -0
- package/lib/app/index.js +1 -0
- package/lib/app/lpk_installer.js +18 -12
- package/lib/appstore/login.js +124 -123
- package/lib/debug_bridge.js +6 -1
- package/lib/utils.js +4 -5
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
# 1.2.64
|
|
2
|
+
1. 升级 dozzle,支持查看所有容器日志
|
|
3
|
+
2. 修复 devshell ssh 多路复用错误
|
|
4
|
+
|
|
5
|
+
# 1.2.63
|
|
6
|
+
|
|
7
|
+
1. 处理开发者账号无法登陆问题
|
|
8
|
+
|
|
1
9
|
# 1.2.62
|
|
10
|
+
|
|
2
11
|
1. 修复部分 windows 机器无法登陆开发者账号问题
|
|
3
12
|
|
|
4
13
|
# 1.2.61
|
|
14
|
+
|
|
5
15
|
1. 修复 lzc-build 文件配置 `compose.override` 字段不生效问题
|
|
6
16
|
|
|
7
17
|
# 1.2.60
|
|
18
|
+
|
|
8
19
|
1. 添加用户登录友好提示
|
|
9
20
|
2. 移除已弃用模版
|
|
10
21
|
3. 支持 lzc-build 文件配置 `compose.override` 字段
|
package/lib/app/index.js
CHANGED
package/lib/app/lpk_installer.js
CHANGED
|
@@ -25,9 +25,9 @@ function findOnceLpkByDir(dir = process.cwd()) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export class LpkInstaller {
|
|
28
|
-
constructor() {}
|
|
28
|
+
constructor() { }
|
|
29
29
|
|
|
30
|
-
async init() {}
|
|
30
|
+
async init() { }
|
|
31
31
|
|
|
32
32
|
// deploy 构建和安装
|
|
33
33
|
async deploy(builder) {
|
|
@@ -119,17 +119,23 @@ export class LpkInstaller {
|
|
|
119
119
|
fs.rmSync(tempDir, { recursive: true })
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
try {
|
|
123
|
+
const bridge = new DebugBridge()
|
|
124
|
+
await bridge.init()
|
|
125
|
+
logger.info("开始安装应用")
|
|
126
|
+
await bridge.install(pkgPath, manifest ? manifest["package"] : "")
|
|
127
|
+
logger.info("\n")
|
|
128
|
+
logger.info(`安装成功!`)
|
|
129
|
+
if (manifest) {
|
|
130
|
+
logger.info(
|
|
131
|
+
`👉 请在浏览器中访问 https://${manifest["application"]["subdomain"]}.${shellapi.boxname}.heiyu.space`
|
|
132
|
+
)
|
|
133
|
+
logger.info(`👉 并使用微服的用户名和密码登录`)
|
|
134
|
+
}
|
|
135
|
+
} catch(error) {
|
|
136
|
+
logger.error(
|
|
137
|
+
`安装失败: ${error}`
|
|
131
138
|
)
|
|
132
|
-
logger.info(`👉 并使用微服的用户名和密码登录`)
|
|
133
139
|
}
|
|
134
140
|
}
|
|
135
141
|
}
|
package/lib/appstore/login.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fetch from "node-fetch"
|
|
2
2
|
import path from "path"
|
|
3
|
+
import url from "url"
|
|
3
4
|
import logger from "loglevel"
|
|
4
5
|
import env from "../config/env.js"
|
|
5
6
|
import inquirer from "inquirer"
|
|
@@ -7,156 +8,156 @@ import inquirer from "inquirer"
|
|
|
7
8
|
const accountServerUrl = "https://account.lazycat.cloud"
|
|
8
9
|
|
|
9
10
|
function join(...params) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
let x = ""
|
|
12
|
+
try {
|
|
13
|
+
// fix: url path join failed for windows
|
|
14
|
+
const u = new url.URL(params[0])
|
|
15
|
+
params.splice(0, 1)
|
|
16
|
+
u.pathname = path.posix.join(u.pathname, ...params)
|
|
17
|
+
x = u.toString()
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.warn(error)
|
|
20
|
+
x = path.join(...params)
|
|
21
|
+
}
|
|
22
|
+
return x
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
async function login(username, password) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
26
|
+
return fetch(join(accountServerUrl, "/api/login/signin"), {
|
|
27
|
+
method: "POST",
|
|
28
|
+
body: new URLSearchParams({
|
|
29
|
+
username: username,
|
|
30
|
+
password: password
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
.then(async (res) => {
|
|
34
|
+
let bodyText = await res.text()
|
|
35
|
+
let body = JSON.parse(bodyText)
|
|
36
|
+
if (body.success) {
|
|
37
|
+
return Promise.resolve(body.data)
|
|
38
|
+
}
|
|
39
|
+
return Promise.reject(body.message)
|
|
40
|
+
})
|
|
41
|
+
.then((data) => {
|
|
42
|
+
env.set({ token: data.token }, true)
|
|
43
|
+
logger.info("登录成功!")
|
|
44
|
+
})
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
async function isLogin() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
48
|
+
try {
|
|
49
|
+
let token = env.get("token")
|
|
50
|
+
if (!token) {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
return fetch(join(accountServerUrl, "/api/user/current"), {
|
|
54
|
+
method: "GET",
|
|
55
|
+
headers: {
|
|
56
|
+
"X-User-Token": token
|
|
57
|
+
}
|
|
58
|
+
}).then(async (res) => {
|
|
59
|
+
let bodyText = await res.text()
|
|
60
|
+
let body = JSON.parse(bodyText)
|
|
61
|
+
if (body.success) {
|
|
62
|
+
return token
|
|
63
|
+
}
|
|
64
|
+
logger.debug(body.message)
|
|
65
|
+
return false
|
|
66
|
+
})
|
|
67
|
+
} catch (e) {
|
|
68
|
+
logger.trace(e)
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
async function askUserInfo() {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
74
|
+
const noEmpty = (value) => value != ""
|
|
75
|
+
return await inquirer.prompt([
|
|
76
|
+
{
|
|
77
|
+
type: "input",
|
|
78
|
+
name: "username",
|
|
79
|
+
message: "请输入登录用户名",
|
|
80
|
+
validate: noEmpty
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: "password",
|
|
84
|
+
mask: "*",
|
|
85
|
+
name: "password",
|
|
86
|
+
message: "请输入登录密码",
|
|
87
|
+
validate: noEmpty
|
|
88
|
+
}
|
|
89
|
+
])
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
async function interactiveLogin() {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
try {
|
|
94
|
+
let info = await askUserInfo()
|
|
95
|
+
await login(info.username, info.password)
|
|
96
|
+
} catch (e) {
|
|
97
|
+
logger.debug("login error: ", e)
|
|
98
|
+
logger.error("帐号或者密码错误,请重新输入!")
|
|
99
|
+
return interactiveLogin()
|
|
100
|
+
}
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
function tipsFirstLogin() {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
let token = env.get("token")
|
|
105
|
+
if (!token) {
|
|
106
|
+
// 还没登录过的用户提示用户前往 https://developer.lazycat.cloud/manage 注册开发者账号
|
|
107
|
+
logger.info("请登录懒猫微服社区账号,账号注册以及开发者权限申请地址: https://developer.lazycat.cloud/manage")
|
|
108
|
+
}
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
export async function reLogin() {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
112
|
+
let token = await isLogin()
|
|
113
|
+
if (token) {
|
|
114
|
+
const questions = [
|
|
115
|
+
{
|
|
116
|
+
name: "relogin",
|
|
117
|
+
type: "input",
|
|
118
|
+
default: "n",
|
|
119
|
+
message: "检测到已经登录,是否重新登录(y/n):"
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
const answers = await inquirer.prompt(questions)
|
|
123
|
+
if (answers.relogin.toLowerCase() === "n") {
|
|
124
|
+
logger.info(`token: ${token}`)
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
tipsFirstLogin()
|
|
129
|
+
}
|
|
130
|
+
await interactiveLogin()
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
export async function autoLogin() {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
let token = await isLogin()
|
|
135
|
+
if (token) {
|
|
136
|
+
logger.debug("appstore 已经登录")
|
|
137
|
+
return
|
|
138
|
+
} else {
|
|
139
|
+
tipsFirstLogin()
|
|
140
|
+
}
|
|
140
141
|
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
logger.debug("token错误,尝试自动登录")
|
|
143
|
+
await interactiveLogin()
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
export async function request(url, options = {}) {
|
|
146
|
-
|
|
147
|
+
await autoLogin()
|
|
147
148
|
|
|
148
|
-
|
|
149
|
+
const token = env.get("token")
|
|
149
150
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
let headers = {
|
|
152
|
+
"X-User-Token": token,
|
|
153
|
+
cookie: `userToken=${token}`
|
|
154
|
+
}
|
|
155
|
+
if (options.headers) {
|
|
156
|
+
headers = Object.assign({}, options.headers, headers)
|
|
157
|
+
}
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
options = Object.assign({}, options, { headers })
|
|
160
|
+
logger.trace(`fetch ${url}`, options)
|
|
160
161
|
|
|
161
|
-
|
|
162
|
+
return fetch(url, options)
|
|
162
163
|
}
|
package/lib/debug_bridge.js
CHANGED
|
@@ -30,6 +30,7 @@ export function sshCmdArgs(...args) {
|
|
|
30
30
|
const defaultOptions = [
|
|
31
31
|
`-o "StrictHostKeyChecking=no"`,
|
|
32
32
|
`-o "UserKnownHostsFile=/dev/null"`,
|
|
33
|
+
`-o "ControlMaster=no"`,
|
|
33
34
|
"-q",
|
|
34
35
|
"-p 22222",
|
|
35
36
|
`${isTraceMode() ? "-v" : ""}`
|
|
@@ -126,7 +127,11 @@ export class DebugBridge {
|
|
|
126
127
|
return true
|
|
127
128
|
} catch (err) {
|
|
128
129
|
logger.debug("canPublicKey error: ", err)
|
|
129
|
-
|
|
130
|
+
if (err?.code == "ETIMEOUT") {
|
|
131
|
+
throw `域名解析失败,请检查代理软件是否对*.heiyu.space拦截`
|
|
132
|
+
} else {
|
|
133
|
+
return false
|
|
134
|
+
}
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
|
package/lib/utils.js
CHANGED
|
@@ -484,21 +484,20 @@ export async function resolveDomain(domain) {
|
|
|
484
484
|
try {
|
|
485
485
|
// Set machine's dns server as defalut dns server
|
|
486
486
|
dns.setServers(["[fc03:1136:3800::1]"])
|
|
487
|
-
|
|
488
487
|
const [ipv6Addresses, ipv4Addresses] = await Promise.allSettled([
|
|
489
488
|
__resolveDomain(domain, true),
|
|
490
489
|
__resolveDomain(domain, false)
|
|
491
490
|
])
|
|
492
491
|
if (ipv6Addresses.status == "fulfilled") {
|
|
493
492
|
return ipv6Addresses.value
|
|
494
|
-
} else if (ipv4Addresses.status
|
|
493
|
+
} else if (ipv4Addresses.status == "fulfilled") {
|
|
495
494
|
return ipv4Addresses.value
|
|
496
495
|
} else {
|
|
497
|
-
throw
|
|
496
|
+
throw ipv6Addresses.reason
|
|
498
497
|
}
|
|
499
498
|
} catch (error) {
|
|
500
|
-
logger.error(
|
|
501
|
-
throw
|
|
499
|
+
logger.error(`无法解析域名 ${domain}: `, error)
|
|
500
|
+
throw error
|
|
502
501
|
}
|
|
503
502
|
}
|
|
504
503
|
|