@lazycatcloud/lzc-cli 1.2.63 → 1.2.65
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/index.js +1 -0
- package/lib/app/lpk_installer.js +18 -12
- package/lib/appstore/env.js +10 -0
- package/lib/appstore/index.js +9 -5
- package/lib/appstore/login.js +128 -125
- package/lib/appstore/publish.js +96 -64
- package/lib/debug_bridge.js +6 -1
- package/lib/utils.js +14 -5
- package/package.json +1 -1
package/changelog.md
CHANGED
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
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: Bin
|
|
3
|
+
* @Date: 2025-04-14
|
|
4
|
+
* @FilePath: /lzc-cli/lib/appstore/env.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const accountServerUrl = "https://account.lazycat.cloud"
|
|
8
|
+
const appStoreServerUrl = "https://appstore.api.lazycat.cloud"
|
|
9
|
+
|
|
10
|
+
export { accountServerUrl, appStoreServerUrl }
|
package/lib/appstore/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { PrePublish } from "./prePublish.js"
|
|
|
4
4
|
import { reLogin, request } from "./login.js"
|
|
5
5
|
import fs from "node:fs"
|
|
6
6
|
import { sleep } from "../utils.js"
|
|
7
|
+
import { appStoreServerUrl } from "./env.js"
|
|
7
8
|
|
|
8
9
|
export function appstoreCommand(program) {
|
|
9
10
|
let subCommands = [
|
|
@@ -58,24 +59,27 @@ export function appstoreCommand(program) {
|
|
|
58
59
|
})
|
|
59
60
|
},
|
|
60
61
|
handler: async ({ pkgPath, changelog, file }) => {
|
|
62
|
+
const locale = program.locale()
|
|
61
63
|
const p = new Publish()
|
|
62
64
|
if (!changelog && file) {
|
|
63
65
|
changelog = fs.readFileSync(file, "utf8")
|
|
64
66
|
}
|
|
65
|
-
await p.publish(pkgPath, changelog)
|
|
67
|
+
await p.publish(pkgPath, changelog, locale)
|
|
66
68
|
}
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
71
|
command: "copy-image <imageName>",
|
|
70
72
|
desc: "复制镜像至懒猫微服官方源",
|
|
71
73
|
handler: async ({ imageName }) => {
|
|
72
|
-
const baseUrl =
|
|
74
|
+
const baseUrl = `${appStoreServerUrl}/api/v3/developer`
|
|
73
75
|
logger.info(
|
|
74
76
|
`Waiting ... ( copy ${imageName} to lazycat offical registry)`
|
|
75
77
|
)
|
|
76
78
|
try {
|
|
77
|
-
for (
|
|
78
|
-
const resp = await request(
|
|
79
|
+
for (;;) {
|
|
80
|
+
const resp = await request(
|
|
81
|
+
`${baseUrl}/app/docker/image/push?image=${imageName}&v=2`
|
|
82
|
+
)
|
|
79
83
|
if (resp.ok) {
|
|
80
84
|
const tag = await resp.text()
|
|
81
85
|
if (tag.length == 0) {
|
|
@@ -87,7 +91,7 @@ export function appstoreCommand(program) {
|
|
|
87
91
|
logger.error("error: ", await resp.text())
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
break
|
|
94
|
+
break
|
|
91
95
|
}
|
|
92
96
|
} catch (err) {
|
|
93
97
|
console.error(err)
|
package/lib/appstore/login.js
CHANGED
|
@@ -4,160 +4,163 @@ import url from "url"
|
|
|
4
4
|
import logger from "loglevel"
|
|
5
5
|
import env from "../config/env.js"
|
|
6
6
|
import inquirer from "inquirer"
|
|
7
|
-
|
|
8
|
-
const accountServerUrl = "https://account.lazycat.cloud"
|
|
7
|
+
import { accountServerUrl } from "./env.js"
|
|
9
8
|
|
|
10
9
|
function join(...params) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
let x = ""
|
|
11
|
+
try {
|
|
12
|
+
// fix: url path join failed for windows
|
|
13
|
+
const u = new url.URL(params[0])
|
|
14
|
+
params.splice(0, 1)
|
|
15
|
+
u.pathname = path.posix.join(u.pathname, ...params)
|
|
16
|
+
x = u.toString()
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.warn(error)
|
|
19
|
+
x = path.join(...params)
|
|
20
|
+
}
|
|
21
|
+
return x
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
async function login(username, password) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
25
|
+
return fetch(join(accountServerUrl, "/api/login/signin"), {
|
|
26
|
+
method: "POST",
|
|
27
|
+
body: new URLSearchParams({
|
|
28
|
+
username: username,
|
|
29
|
+
password: password
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
.then(async (res) => {
|
|
33
|
+
let bodyText = await res.text()
|
|
34
|
+
let body = JSON.parse(bodyText)
|
|
35
|
+
if (body.success) {
|
|
36
|
+
return Promise.resolve(body.data)
|
|
37
|
+
}
|
|
38
|
+
return Promise.reject(body.message)
|
|
39
|
+
})
|
|
40
|
+
.then((data) => {
|
|
41
|
+
env.set({ token: data.token }, true)
|
|
42
|
+
logger.info("登录成功!")
|
|
43
|
+
})
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
async function isLogin() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
47
|
+
try {
|
|
48
|
+
let token = env.get("token")
|
|
49
|
+
if (!token) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
return fetch(join(accountServerUrl, "/api/user/current"), {
|
|
53
|
+
method: "GET",
|
|
54
|
+
headers: {
|
|
55
|
+
"X-User-Token": token
|
|
56
|
+
}
|
|
57
|
+
}).then(async (res) => {
|
|
58
|
+
let bodyText = await res.text()
|
|
59
|
+
let body = JSON.parse(bodyText)
|
|
60
|
+
if (body.success) {
|
|
61
|
+
return token
|
|
62
|
+
}
|
|
63
|
+
logger.debug(body.message)
|
|
64
|
+
return false
|
|
65
|
+
})
|
|
66
|
+
} catch (e) {
|
|
67
|
+
logger.trace(e)
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
async function askUserInfo() {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
const noEmpty = (value) => value != ""
|
|
74
|
+
return await inquirer.prompt([
|
|
75
|
+
{
|
|
76
|
+
type: "input",
|
|
77
|
+
name: "username",
|
|
78
|
+
message: "请输入登录用户名",
|
|
79
|
+
validate: noEmpty
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: "password",
|
|
83
|
+
mask: "*",
|
|
84
|
+
name: "password",
|
|
85
|
+
message: "请输入登录密码",
|
|
86
|
+
validate: noEmpty
|
|
87
|
+
}
|
|
88
|
+
])
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
async function interactiveLogin() {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
try {
|
|
93
|
+
let info = await askUserInfo()
|
|
94
|
+
await login(info.username, info.password)
|
|
95
|
+
} catch (e) {
|
|
96
|
+
logger.debug("login error: ", e)
|
|
97
|
+
logger.error("帐号或者密码错误,请重新输入!")
|
|
98
|
+
return interactiveLogin()
|
|
99
|
+
}
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
function tipsFirstLogin() {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
let token = env.get("token")
|
|
104
|
+
if (!token) {
|
|
105
|
+
// 还没登录过的用户提示用户前往 https://developer.lazycat.cloud/manage 注册开发者账号
|
|
106
|
+
logger.info(
|
|
107
|
+
"请登录懒猫微服社区账号,账号注册以及开发者权限申请地址: https://developer.lazycat.cloud/manage"
|
|
108
|
+
)
|
|
109
|
+
}
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
export async function reLogin() {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
113
|
+
let token = await isLogin()
|
|
114
|
+
if (token) {
|
|
115
|
+
const questions = [
|
|
116
|
+
{
|
|
117
|
+
name: "relogin",
|
|
118
|
+
type: "input",
|
|
119
|
+
default: "n",
|
|
120
|
+
message: "检测到已经登录,是否重新登录(y/n):"
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
const answers = await inquirer.prompt(questions)
|
|
124
|
+
if (answers.relogin.toLowerCase() === "n") {
|
|
125
|
+
logger.info(`token: ${token}`)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
tipsFirstLogin()
|
|
130
|
+
}
|
|
131
|
+
await interactiveLogin()
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
export async function autoLogin() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
let token = await isLogin()
|
|
136
|
+
if (token) {
|
|
137
|
+
logger.debug("appstore 已经登录")
|
|
138
|
+
return
|
|
139
|
+
} else {
|
|
140
|
+
tipsFirstLogin()
|
|
141
|
+
}
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
logger.debug("token错误,尝试自动登录")
|
|
144
|
+
await interactiveLogin()
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
export async function request(url, options = {}) {
|
|
147
|
-
|
|
148
|
+
await autoLogin()
|
|
149
|
+
|
|
150
|
+
const token = env.get("token")
|
|
148
151
|
|
|
149
|
-
|
|
152
|
+
let headers = {
|
|
153
|
+
"X-User-Token": token,
|
|
154
|
+
cookie: `userToken=${token}`
|
|
155
|
+
}
|
|
156
|
+
if (options.headers) {
|
|
157
|
+
headers = Object.assign({}, options.headers, headers)
|
|
158
|
+
}
|
|
150
159
|
|
|
151
|
-
|
|
152
|
-
"X-User-Token": token,
|
|
153
|
-
cookie: `userToken=${token}`
|
|
154
|
-
}
|
|
155
|
-
if (options.headers) {
|
|
156
|
-
headers = Object.assign({}, options.headers, headers)
|
|
157
|
-
}
|
|
160
|
+
// logger.debug("token", token)
|
|
158
161
|
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
options = Object.assign({}, options, { headers })
|
|
163
|
+
logger.trace(`fetch ${url}`, options)
|
|
161
164
|
|
|
162
|
-
|
|
165
|
+
return fetch(url, options)
|
|
163
166
|
}
|
package/lib/appstore/publish.js
CHANGED
|
@@ -9,35 +9,45 @@ import {
|
|
|
9
9
|
isPngWithFile,
|
|
10
10
|
unzipSync,
|
|
11
11
|
loadFromYaml,
|
|
12
|
-
isValidPackageName
|
|
12
|
+
isValidPackageName,
|
|
13
|
+
getLanguageForLocale
|
|
13
14
|
} from "../utils.js"
|
|
15
|
+
import { appStoreServerUrl } from "./env.js"
|
|
14
16
|
|
|
15
|
-
async function askChangeLog() {
|
|
17
|
+
async function askChangeLog(locale) {
|
|
16
18
|
const noEmpty = (value) => value != ""
|
|
17
19
|
return await inquirer.prompt([
|
|
18
20
|
{
|
|
19
21
|
name: "changelog",
|
|
20
22
|
type: "editor",
|
|
21
|
-
message:
|
|
23
|
+
message: `填写 changelog 内容 (${locale})`,
|
|
22
24
|
validate: noEmpty
|
|
23
25
|
}
|
|
24
26
|
])
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
async function getCategories(baseUrl) {
|
|
28
|
-
const response = await request(`${baseUrl}/
|
|
29
|
-
|
|
29
|
+
async function getCategories(baseUrl, locale = "zh") {
|
|
30
|
+
const response = await request(`${baseUrl}/app/category?size=100`, {
|
|
31
|
+
method: "GET"
|
|
32
|
+
})
|
|
33
|
+
const langKey = getLanguageForLocale(locale)
|
|
34
|
+
const { items: data } = await response.json()
|
|
35
|
+
console.log("data", data)
|
|
30
36
|
return data
|
|
31
37
|
.sort((a, b) => a.index - b.index)
|
|
32
|
-
.map((cat) =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
.map((cat) => {
|
|
39
|
+
let localize_name = (cat?.localize_name ?? {})[langKey] ?? undefined
|
|
40
|
+
return {
|
|
41
|
+
name: localize_name ?? cat.name,
|
|
42
|
+
value: cat.id
|
|
43
|
+
}
|
|
44
|
+
})
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
async function askPublishAppInfo(baseUrl, manifest) {
|
|
47
|
+
async function askPublishAppInfo(baseUrl, manifest, locale) {
|
|
39
48
|
// 获取分类列表
|
|
40
|
-
const categories = await getCategories(baseUrl)
|
|
49
|
+
// const categories = await getCategories(baseUrl, locale)
|
|
50
|
+
const langKey = getLanguageForLocale(locale)
|
|
41
51
|
|
|
42
52
|
const questions = [
|
|
43
53
|
{
|
|
@@ -49,56 +59,62 @@ async function askPublishAppInfo(baseUrl, manifest) {
|
|
|
49
59
|
},
|
|
50
60
|
{
|
|
51
61
|
type: "input",
|
|
52
|
-
name: "
|
|
53
|
-
message: "
|
|
62
|
+
name: "package",
|
|
63
|
+
message: "请输入应用包标识符:",
|
|
54
64
|
default: manifest["package"],
|
|
55
65
|
validate: (input) =>
|
|
56
|
-
isValidPackageName(input)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
type: "input",
|
|
60
|
-
name: "description",
|
|
61
|
-
message: "请输入应用描述:",
|
|
62
|
-
default: manifest["description"] || ""
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
type: "input",
|
|
66
|
-
name: "brief",
|
|
67
|
-
message: "请输入应用简介(简单的概述):",
|
|
68
|
-
default: ""
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: "checkbox",
|
|
72
|
-
name: "category",
|
|
73
|
-
message: "请选择应用分类:",
|
|
74
|
-
choices: categories,
|
|
75
|
-
validate: (input) => (input.length > 0 ? true : "请至少选择一个分类")
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
type: "input",
|
|
79
|
-
name: "keywords",
|
|
80
|
-
message: "请输入关键词(用逗号分隔):",
|
|
81
|
-
default: ""
|
|
66
|
+
isValidPackageName(input)
|
|
67
|
+
? true
|
|
68
|
+
: "应用包标识符不符合规范,建议使用反向域名表示法"
|
|
82
69
|
},
|
|
70
|
+
// {
|
|
71
|
+
// type: "input",
|
|
72
|
+
// name: "description",
|
|
73
|
+
// message: "请输入应用描述:",
|
|
74
|
+
// default: manifest["description"] || ""
|
|
75
|
+
// },
|
|
76
|
+
// {
|
|
77
|
+
// type: "input",
|
|
78
|
+
// name: "brief",
|
|
79
|
+
// message: "请输入应用简介(简单的概述):",
|
|
80
|
+
// default: ""
|
|
81
|
+
// },
|
|
82
|
+
// 开发者暂时不能配置应用分类
|
|
83
|
+
// {
|
|
84
|
+
// type: "checkbox",
|
|
85
|
+
// name: "category",
|
|
86
|
+
// message: "请选择应用分类:",
|
|
87
|
+
// choices: categories,
|
|
88
|
+
// validate: (input) => (input.length > 0 ? true : "请至少选择一个分类")
|
|
89
|
+
// },
|
|
90
|
+
// {
|
|
91
|
+
// type: "input",
|
|
92
|
+
// name: "keywords",
|
|
93
|
+
// message: "请输入关键词(用逗号分隔):",
|
|
94
|
+
// default: ""
|
|
95
|
+
// },
|
|
83
96
|
{
|
|
84
97
|
type: "input",
|
|
85
98
|
name: "source",
|
|
86
|
-
message: "
|
|
99
|
+
message: "请输入应用来源(原创应用可不填):",
|
|
87
100
|
default: manifest["homepage"] || ""
|
|
88
101
|
},
|
|
89
102
|
{
|
|
90
103
|
type: "input",
|
|
91
104
|
name: "author",
|
|
92
|
-
message: "
|
|
105
|
+
message: "请输入作者名称(原创应用可不填):",
|
|
93
106
|
default: manifest["author"] || ""
|
|
94
107
|
}
|
|
95
108
|
]
|
|
96
109
|
|
|
97
110
|
const answers = await inquirer.prompt(questions)
|
|
98
|
-
return
|
|
111
|
+
return {
|
|
112
|
+
language: langKey, // 应用主要语言(后续需要做成可以让用户选择)
|
|
113
|
+
...answers
|
|
114
|
+
}
|
|
99
115
|
}
|
|
100
116
|
|
|
101
|
-
async function askWhetherCreateLPK(baseUrl, manifest) {
|
|
117
|
+
async function askWhetherCreateLPK(baseUrl, manifest, locale) {
|
|
102
118
|
const answers = await inquirer.prompt([
|
|
103
119
|
{
|
|
104
120
|
name: "continue",
|
|
@@ -109,10 +125,16 @@ async function askWhetherCreateLPK(baseUrl, manifest) {
|
|
|
109
125
|
}
|
|
110
126
|
])
|
|
111
127
|
if (answers.continue.toLowerCase() === "y") {
|
|
112
|
-
const appInfo = await askPublishAppInfo(baseUrl, manifest)
|
|
113
|
-
const crateAppRes = await request(`${baseUrl}/
|
|
128
|
+
const appInfo = await askPublishAppInfo(baseUrl, manifest, locale)
|
|
129
|
+
const crateAppRes = await request(`${baseUrl}/app/create`, {
|
|
114
130
|
method: "POST",
|
|
115
|
-
body: JSON.stringify(
|
|
131
|
+
body: JSON.stringify({
|
|
132
|
+
package: appInfo.package,
|
|
133
|
+
language: appInfo.language,
|
|
134
|
+
name: appInfo.name,
|
|
135
|
+
source: appInfo.source,
|
|
136
|
+
source_author: appInfo.author
|
|
137
|
+
})
|
|
116
138
|
})
|
|
117
139
|
logger.debug("create app res: ", await crateAppRes.text())
|
|
118
140
|
logger.info(`创建 ${manifest["package"]} 应用成功!`)
|
|
@@ -131,7 +153,7 @@ async function askWhetherCreateLPK(baseUrl, manifest) {
|
|
|
131
153
|
}
|
|
132
154
|
|
|
133
155
|
export class Publish {
|
|
134
|
-
constructor(baseUrl =
|
|
156
|
+
constructor(baseUrl = `${appStoreServerUrl}/api/v3/developer`) {
|
|
135
157
|
this.baseUrl = baseUrl
|
|
136
158
|
}
|
|
137
159
|
|
|
@@ -170,16 +192,17 @@ export class Publish {
|
|
|
170
192
|
try {
|
|
171
193
|
unzipSync(pkgPath, tempDir, ["manifest.yml"])
|
|
172
194
|
const manifest = loadFromYaml(path.join(tempDir, "manifest.yml"))
|
|
173
|
-
const checkUrl =
|
|
195
|
+
const checkUrl =
|
|
196
|
+
this.baseUrl + `/app/check/exist?package=${manifest["package"]}`
|
|
174
197
|
const res = await request(checkUrl, { method: "GET" })
|
|
175
198
|
if (res.status >= 400) {
|
|
176
199
|
logger.error("检测应用是否存在出错, 错误状态码为: ", res.status)
|
|
177
|
-
logger.error(await res.
|
|
200
|
+
logger.error(await res.json())
|
|
178
201
|
return { manifest, appIdExisted: true } // 默认认为已经存在
|
|
179
202
|
} else {
|
|
180
|
-
const
|
|
181
|
-
logger.debug(`check appId[${manifest["package"]}] exist: ${
|
|
182
|
-
return { manifest, appIdExisted:
|
|
203
|
+
const { exist = false } = await res.json()
|
|
204
|
+
logger.debug(`check appId[${manifest["package"]}] exist: ${exist}`)
|
|
205
|
+
return { manifest, appIdExisted: exist }
|
|
183
206
|
}
|
|
184
207
|
} finally {
|
|
185
208
|
fs.rmSync(tempDir, { recursive: true })
|
|
@@ -189,19 +212,20 @@ export class Publish {
|
|
|
189
212
|
/**
|
|
190
213
|
* @param {string} pkgPath
|
|
191
214
|
* @param {string} changelog
|
|
215
|
+
* @param {string} locale
|
|
192
216
|
*/
|
|
193
|
-
async publish(pkgPath, changelog) {
|
|
217
|
+
async publish(pkgPath, changelog, locale = "zh") {
|
|
194
218
|
if (!Publish.preCheck(pkgPath)) return
|
|
195
219
|
|
|
196
220
|
const { manifest, appIdExisted } = await this.checkAppIdExist(pkgPath)
|
|
197
221
|
if (!appIdExisted) {
|
|
198
|
-
await askWhetherCreateLPK(this.baseUrl, manifest)
|
|
222
|
+
await askWhetherCreateLPK(this.baseUrl, manifest, locale)
|
|
199
223
|
}
|
|
200
224
|
|
|
201
225
|
await autoLogin()
|
|
202
226
|
|
|
203
227
|
if (!changelog) {
|
|
204
|
-
const answer = await askChangeLog()
|
|
228
|
+
const answer = await askChangeLog(locale)
|
|
205
229
|
changelog = answer.changelog
|
|
206
230
|
}
|
|
207
231
|
changelog = changelog.trim() // clean space ^:)
|
|
@@ -210,7 +234,7 @@ export class Publish {
|
|
|
210
234
|
const form = new FormData()
|
|
211
235
|
form.append("file", fs.createReadStream(pkgPath))
|
|
212
236
|
|
|
213
|
-
const uploadURL = this.baseUrl + "/
|
|
237
|
+
const uploadURL = this.baseUrl + "/app/lpk/upload"
|
|
214
238
|
logger.debug("upload url is", uploadURL)
|
|
215
239
|
|
|
216
240
|
const res = await request(uploadURL, {
|
|
@@ -225,17 +249,25 @@ export class Publish {
|
|
|
225
249
|
const lpkInfo = await JSON.parse(text)
|
|
226
250
|
logger.debug("upload lpk response", lpkInfo)
|
|
227
251
|
|
|
228
|
-
const sendURL = this.baseUrl + `/
|
|
252
|
+
const sendURL = this.baseUrl + `/app/${lpkInfo.package}/review/create`
|
|
229
253
|
logger.debug("publish url is", sendURL)
|
|
230
254
|
|
|
231
255
|
const formData = {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
256
|
+
version: {
|
|
257
|
+
// supportPC: lpkInfo.supportPC,
|
|
258
|
+
// supportMobile: lpkInfo.supportMobile,
|
|
259
|
+
package: lpkInfo.package,
|
|
260
|
+
name: lpkInfo.version,
|
|
261
|
+
icon_path: lpkInfo.iconPath,
|
|
262
|
+
pkg_path: lpkInfo.url,
|
|
263
|
+
unsupported_platforms: lpkInfo.unsupportedPlatforms,
|
|
264
|
+
min_os_version: lpkInfo.minOsVersion,
|
|
265
|
+
changelogs: {}
|
|
266
|
+
}
|
|
238
267
|
}
|
|
268
|
+
// changelogs 本地化
|
|
269
|
+
const langKey = getLanguageForLocale(locale)
|
|
270
|
+
formData.version.changelogs[langKey] = changelog
|
|
239
271
|
|
|
240
272
|
logger.debug("form data is", formData)
|
|
241
273
|
|
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
|
|
|
@@ -656,3 +655,13 @@ export function checkRsync() {
|
|
|
656
655
|
resolve()
|
|
657
656
|
})
|
|
658
657
|
}
|
|
658
|
+
|
|
659
|
+
export function getLanguageForLocale(locale) {
|
|
660
|
+
locale = locale.replace("_", "-")
|
|
661
|
+
try {
|
|
662
|
+
let l = new Intl.Locale(locale)
|
|
663
|
+
return l.language
|
|
664
|
+
} catch (error) {
|
|
665
|
+
return locale
|
|
666
|
+
}
|
|
667
|
+
}
|