@lazycatcloud/lzc-cli 1.2.56 → 1.2.58
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 +12 -0
- package/lib/app/apkshell.js +15 -1
- package/lib/app/lpk_build.js +11 -2
- package/lib/box/index.js +18 -0
- package/lib/debug_bridge.js +9 -3
- package/lib/utils.js +81 -53
- package/package.json +5 -1
- package/scripts/cli.js +8 -2
package/changelog.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# 1.2.58
|
|
2
|
+
|
|
3
|
+
1. 使用 127.0.0.1 替代 localhost 避免解析错误
|
|
4
|
+
2. 修复最新版本检测
|
|
5
|
+
|
|
6
|
+
# 1.2.57
|
|
7
|
+
|
|
8
|
+
1. 支持独立添加公钥到开发者工具中去 `lzc-cli box add-public-key`
|
|
9
|
+
2. 支持选择使用公钥类型,不再优先使用 id_ed25519
|
|
10
|
+
3. 添加 nodejs 版本检测, 要求最低版本 >=18
|
|
11
|
+
4. 添加 dns 解析错误提示
|
|
12
|
+
|
|
1
13
|
# 1.2.56
|
|
2
14
|
|
|
3
15
|
1. 修复没有写权限的lpk文件,不能通过 lzc-cli app install 安装
|
package/lib/app/apkshell.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import fs from "node:fs"
|
|
2
2
|
import logger from "loglevel"
|
|
3
|
-
import
|
|
3
|
+
import axios from "axios"
|
|
4
|
+
|
|
5
|
+
// 创建 Axios 实例
|
|
6
|
+
const api = axios.create()
|
|
7
|
+
|
|
8
|
+
// 添加响应拦截器
|
|
9
|
+
api.interceptors.response.use(
|
|
10
|
+
(response) => response, // 直接返回响应
|
|
11
|
+
(error) => {
|
|
12
|
+
if (error.response && error.response.status === 304) {
|
|
13
|
+
return Promise.resolve(error.response) // 返回响应以便后续处理
|
|
14
|
+
}
|
|
15
|
+
return Promise.reject(error) // 其他错误继续抛出
|
|
16
|
+
}
|
|
17
|
+
)
|
|
4
18
|
|
|
5
19
|
export async function triggerApk(id, name, iconPath) {
|
|
6
20
|
if (!id) {
|
package/lib/app/lpk_build.js
CHANGED
|
@@ -293,8 +293,17 @@ export class LpkBuild {
|
|
|
293
293
|
return await curr(await prev, this.options)
|
|
294
294
|
}, manifest)
|
|
295
295
|
}
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
|
|
297
|
+
if (process.env.LZC_MANIFEST_TEMPLATE) {
|
|
298
|
+
logger.debug("copy origin manifest\n", this.manifestFilePath)
|
|
299
|
+
fs.copyFileSync(
|
|
300
|
+
this.manifestFilePath,
|
|
301
|
+
path.join(tempDir, "manifest.yml")
|
|
302
|
+
)
|
|
303
|
+
} else {
|
|
304
|
+
logger.debug("manifest\n", manifest)
|
|
305
|
+
dumpToYaml(manifest, path.join(tempDir, "manifest.yml"))
|
|
306
|
+
}
|
|
298
307
|
|
|
299
308
|
// 打包 lpk
|
|
300
309
|
if (this.beforeDumpLpkFn.length > 0) {
|
package/lib/box/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import logger from "loglevel"
|
|
1
2
|
import shellapi from "../shellapi.js"
|
|
3
|
+
import { findSshPublicKey, selectSshPublicKey } from "../utils.js"
|
|
2
4
|
|
|
3
5
|
export function boxCommand(box) {
|
|
4
6
|
let subCommands = [
|
|
@@ -51,6 +53,22 @@ export function boxCommand(box) {
|
|
|
51
53
|
})
|
|
52
54
|
console.table(list)
|
|
53
55
|
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
command: "add-public-key",
|
|
59
|
+
desc: "添加public-key到开发者工具中",
|
|
60
|
+
handler: async () => {
|
|
61
|
+
await shellapi.init()
|
|
62
|
+
const keys = await findSshPublicKey()
|
|
63
|
+
const sshInfo = await selectSshPublicKey(keys)
|
|
64
|
+
logger.debug("ssh public key info", sshInfo)
|
|
65
|
+
const pk = Buffer.from(sshInfo.content.trimLeft()).toString("base64")
|
|
66
|
+
logger.warn(
|
|
67
|
+
`请点击下面的连接,或者复制到浏览器中打开,点击申请完成添加
|
|
68
|
+
-> https://dev.${shellapi.boxname}.heiyu.space/auth?key=${pk}
|
|
69
|
+
`
|
|
70
|
+
)
|
|
71
|
+
}
|
|
54
72
|
}
|
|
55
73
|
]
|
|
56
74
|
box.command({
|
package/lib/debug_bridge.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
resolveDomain,
|
|
8
8
|
sleep,
|
|
9
9
|
findSshPublicKey,
|
|
10
|
+
selectSshPublicKey,
|
|
10
11
|
isWindows,
|
|
11
12
|
contextDirname,
|
|
12
13
|
compareVersions
|
|
@@ -91,13 +92,18 @@ export class DebugBridge {
|
|
|
91
92
|
try {
|
|
92
93
|
await this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`)])
|
|
93
94
|
return true
|
|
94
|
-
} catch {
|
|
95
|
+
} catch (err) {
|
|
96
|
+
logger.debug("canPublicKey error: ", err)
|
|
95
97
|
return false
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
async sshApplyGrant() {
|
|
100
|
-
const
|
|
102
|
+
const keys = await findSshPublicKey()
|
|
103
|
+
logger.info(
|
|
104
|
+
"检测到您当前的环境还没有添加 ssh 公钥到 ‘懒猫开发者工具’ 中,请选择您需要添加的公钥类型"
|
|
105
|
+
)
|
|
106
|
+
const sshInfo = await selectSshPublicKey(keys)
|
|
101
107
|
logger.debug("ssh public key info", sshInfo)
|
|
102
108
|
|
|
103
109
|
const pk = Buffer.from(sshInfo.content.trimLeft()).toString("base64")
|
|
@@ -225,7 +231,7 @@ export class DebugBridge {
|
|
|
225
231
|
code == 0
|
|
226
232
|
? resolve(
|
|
227
233
|
compareVersions("0.1.12", backendVersion) >= 0
|
|
228
|
-
? `
|
|
234
|
+
? `127.0.0.1:5000/${tag}`
|
|
229
235
|
: `dev.${this.boxname}.heiyu.space/${tag}`
|
|
230
236
|
)
|
|
231
237
|
: reject(`在盒子中构建 image 失败`)
|
package/lib/utils.js
CHANGED
|
@@ -15,11 +15,12 @@ import process from "node:process"
|
|
|
15
15
|
import spawn from "cross-spawn"
|
|
16
16
|
import logger from "loglevel"
|
|
17
17
|
import * as tar from "tar"
|
|
18
|
-
import dns from "node:dns
|
|
19
|
-
import axios from "axios"
|
|
18
|
+
import dns from "node:dns"
|
|
20
19
|
import AdmZip from "adm-zip"
|
|
21
20
|
import commandExists from "command-exists"
|
|
22
21
|
import fetch from "node-fetch"
|
|
22
|
+
import semver from "semver"
|
|
23
|
+
import inquirer from "inquirer"
|
|
23
24
|
|
|
24
25
|
// lzc-cli 包的 pkgInfo 信息
|
|
25
26
|
export const pkgInfo = JSON.parse(
|
|
@@ -28,6 +29,24 @@ export const pkgInfo = JSON.parse(
|
|
|
28
29
|
)
|
|
29
30
|
)
|
|
30
31
|
|
|
32
|
+
export function checkNodejsVersion() {
|
|
33
|
+
const requiredVersion = pkgInfo.engines.node
|
|
34
|
+
if (!semver.satisfies(process.version, requiredVersion)) {
|
|
35
|
+
logger.error(
|
|
36
|
+
`检测到您当前的 nodejs 版本 ${process.version} 不匹配,lzc-cli 最低要求 nodejs 版本为 ${requiredVersion}, 请升级`
|
|
37
|
+
)
|
|
38
|
+
process.exit(1)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 如果版本小于 21.0.0 且大于等于 16.15.0,禁用 Fetch API 实验性警告
|
|
42
|
+
if (
|
|
43
|
+
semver.lt(process.version, "21.0.0") &&
|
|
44
|
+
semver.gte(process.version, "16.15.0")
|
|
45
|
+
) {
|
|
46
|
+
process.removeAllListeners("warning")
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
31
50
|
export async function getLatestVersion(controller, pkgName = pkgInfo.name) {
|
|
32
51
|
const url = `https://data.jsdelivr.com/v1/package/npm/${pkgName}`
|
|
33
52
|
try {
|
|
@@ -37,7 +56,7 @@ export async function getLatestVersion(controller, pkgName = pkgInfo.name) {
|
|
|
37
56
|
})
|
|
38
57
|
const content = await data.json()
|
|
39
58
|
const latestVersion = content["tags"]["latest"]
|
|
40
|
-
if (
|
|
59
|
+
if (semver.lt(pkgInfo.version, latestVersion)) {
|
|
41
60
|
logger.warn(
|
|
42
61
|
`检测到 ${pkgName} 最新版本为 ${latestVersion},使用 'npm i -g ${pkgName}@${latestVersion}' 升级到最新版本!`
|
|
43
62
|
)
|
|
@@ -49,20 +68,6 @@ export async function getLatestVersion(controller, pkgName = pkgInfo.name) {
|
|
|
49
68
|
}
|
|
50
69
|
}
|
|
51
70
|
|
|
52
|
-
// 创建 Axios 实例
|
|
53
|
-
export const api = axios.create()
|
|
54
|
-
|
|
55
|
-
// 添加响应拦截器
|
|
56
|
-
api.interceptors.response.use(
|
|
57
|
-
(response) => response, // 直接返回响应
|
|
58
|
-
(error) => {
|
|
59
|
-
if (error.response && error.response.status === 304) {
|
|
60
|
-
return Promise.resolve(error.response) // 返回响应以便后续处理
|
|
61
|
-
}
|
|
62
|
-
return Promise.reject(error) // 其他错误继续抛出
|
|
63
|
-
}
|
|
64
|
-
)
|
|
65
|
-
|
|
66
71
|
export const isMacOs = process.platform == "darwin"
|
|
67
72
|
export const isLinux = process.platform == "linux"
|
|
68
73
|
export const isWindows = process.platform == "win32"
|
|
@@ -456,31 +461,45 @@ export function isTraceMode() {
|
|
|
456
461
|
return logger.getLevel() <= logger.levels.TRACE
|
|
457
462
|
}
|
|
458
463
|
|
|
464
|
+
// 没有直接使用 dns/promise,因为这个 dns/promise 是在 15.0.0 后加入,如果低版本
|
|
465
|
+
// 会直接报错,连版本检测都到不了(包导入的太前面了)
|
|
466
|
+
async function __resolveDomain(domain, ipv6 = false) {
|
|
467
|
+
return new Promise((resolve, reject) => {
|
|
468
|
+
const callback = function (err, addresses) {
|
|
469
|
+
if (addresses && addresses.length > 0) {
|
|
470
|
+
resolve(addresses[0])
|
|
471
|
+
} else {
|
|
472
|
+
logger.trace("dns resolve error: ", err)
|
|
473
|
+
reject(err)
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (ipv6) {
|
|
477
|
+
dns.resolve6(domain, callback)
|
|
478
|
+
} else {
|
|
479
|
+
dns.resolve4(domain, callback)
|
|
480
|
+
}
|
|
481
|
+
})
|
|
482
|
+
}
|
|
483
|
+
|
|
459
484
|
export async function resolveDomain(domain) {
|
|
460
485
|
try {
|
|
461
486
|
// Set machine's dns server as defalut dns server
|
|
462
487
|
dns.setServers(["[fc03:1136:3800::1]"])
|
|
488
|
+
|
|
463
489
|
const [ipv6Addresses, ipv4Addresses] = await Promise.allSettled([
|
|
464
|
-
|
|
465
|
-
|
|
490
|
+
__resolveDomain(domain, true),
|
|
491
|
+
__resolveDomain(domain, false)
|
|
466
492
|
])
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
) {
|
|
472
|
-
resolvedAddress = ipv6Addresses.value[0]
|
|
473
|
-
} else if (
|
|
474
|
-
ipv4Addresses.status === "fulfilled" &&
|
|
475
|
-
ipv4Addresses.value.length > 0
|
|
476
|
-
) {
|
|
477
|
-
resolvedAddress = ipv4Addresses.value[0]
|
|
493
|
+
if (ipv6Addresses.status == "fulfilled") {
|
|
494
|
+
return ipv6Addresses.value
|
|
495
|
+
} else if (ipv4Addresses.status != "fulfilled") {
|
|
496
|
+
return ipv4Addresses.value
|
|
478
497
|
} else {
|
|
479
|
-
throw
|
|
498
|
+
throw `无法解析域名 ${domain}`
|
|
480
499
|
}
|
|
481
|
-
return resolvedAddress
|
|
482
500
|
} catch (error) {
|
|
483
|
-
|
|
501
|
+
logger.error("resolve domain: ", error)
|
|
502
|
+
throw `无法解析域名 ${domain}: ${error}`
|
|
484
503
|
}
|
|
485
504
|
}
|
|
486
505
|
|
|
@@ -508,6 +527,24 @@ export function unzipSync(zipPath, destPath, entries = []) {
|
|
|
508
527
|
}
|
|
509
528
|
}
|
|
510
529
|
|
|
530
|
+
export async function selectSshPublicKey(avaiableKeys) {
|
|
531
|
+
const keyNames = avaiableKeys.map((k) => k.path)
|
|
532
|
+
const selected = (
|
|
533
|
+
await inquirer.prompt([
|
|
534
|
+
{
|
|
535
|
+
name: "type",
|
|
536
|
+
message: "选择使用的公钥",
|
|
537
|
+
type: "list",
|
|
538
|
+
choices: keyNames
|
|
539
|
+
}
|
|
540
|
+
])
|
|
541
|
+
)["type"]
|
|
542
|
+
return {
|
|
543
|
+
path: selected,
|
|
544
|
+
content: fs.readFileSync(selected, "utf8")
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
511
548
|
export function findSshPublicKey() {
|
|
512
549
|
// 获取用户 HOME 目录
|
|
513
550
|
let homeDir
|
|
@@ -552,6 +589,7 @@ export function findSshPublicKey() {
|
|
|
552
589
|
"id_dsa.pub"
|
|
553
590
|
]
|
|
554
591
|
|
|
592
|
+
let avaiableKeys = []
|
|
555
593
|
try {
|
|
556
594
|
// 获取 .ssh 目录下所有文件
|
|
557
595
|
const files = fs.readdirSync(sshDir)
|
|
@@ -563,10 +601,10 @@ export function findSshPublicKey() {
|
|
|
563
601
|
// 验证文件是否可读
|
|
564
602
|
try {
|
|
565
603
|
fs.accessSync(keyPath, fs.constants.R_OK)
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
604
|
+
avaiableKeys.push({
|
|
605
|
+
keyName,
|
|
606
|
+
path: keyPath
|
|
607
|
+
})
|
|
570
608
|
} catch (error) {
|
|
571
609
|
console.warn(`Found ${keyName} but cannot read it:`, error.message)
|
|
572
610
|
continue
|
|
@@ -574,23 +612,13 @@ export function findSshPublicKey() {
|
|
|
574
612
|
}
|
|
575
613
|
}
|
|
576
614
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
return {
|
|
584
|
-
path: keyPath,
|
|
585
|
-
content: fs.readFileSync(keyPath, "utf8")
|
|
586
|
-
}
|
|
587
|
-
} catch (error) {
|
|
588
|
-
throw new Error(`Found ${pubKey} but cannot read it: ${error.message}`)
|
|
589
|
-
}
|
|
615
|
+
if (avaiableKeys.length == 0) {
|
|
616
|
+
throw new Error(
|
|
617
|
+
".ssh 目录没有没有找到任何 .pub 公钥. 请使用 ssh-keygen 生成"
|
|
618
|
+
)
|
|
619
|
+
} else {
|
|
620
|
+
return avaiableKeys
|
|
590
621
|
}
|
|
591
|
-
throw new Error(
|
|
592
|
-
".ssh 目录没有没有找到任何 .pub 公钥. 请使用 ssh-keygen 生成"
|
|
593
|
-
)
|
|
594
622
|
} catch (error) {
|
|
595
623
|
if (error.code === "ENOENT") {
|
|
596
624
|
throw new Error("不能查询 .ssh 目录")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.58",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepublishOnly": "node check-changelog.js"
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"lib",
|
|
12
12
|
"changelog.md"
|
|
13
13
|
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
14
17
|
"bin": {
|
|
15
18
|
"lzc-cli": "scripts/cli.js",
|
|
16
19
|
"lzc-docker": "scripts/lzc-docker.js",
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
"lodash.mergewith": "^4.6.2",
|
|
48
51
|
"loglevel": "^1.9.1",
|
|
49
52
|
"node-fetch": "^3.3.2",
|
|
53
|
+
"semver": "^7.6.3",
|
|
50
54
|
"tar": "^7.4.3",
|
|
51
55
|
"yargs": "^17.7.2"
|
|
52
56
|
},
|
package/scripts/cli.js
CHANGED
|
@@ -7,7 +7,12 @@ import yargs from "yargs"
|
|
|
7
7
|
import { hideBin } from "yargs/helpers"
|
|
8
8
|
import "../lib/log.js" // init logger
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
contextDirname,
|
|
12
|
+
pkgInfo,
|
|
13
|
+
getLatestVersion,
|
|
14
|
+
checkNodejsVersion
|
|
15
|
+
} from "../lib/utils.js"
|
|
11
16
|
import { boxCommand } from "../lib/box/index.js"
|
|
12
17
|
import { appstoreCommand } from "../lib/appstore/index.js"
|
|
13
18
|
import { lpkAppCommand, lpkProjectCommand } from "../lib/app/index.js"
|
|
@@ -56,8 +61,9 @@ lzcDockerCommand(program)
|
|
|
56
61
|
|
|
57
62
|
// 当没有参数的时候,默认显示帮助。
|
|
58
63
|
;(async () => {
|
|
59
|
-
|
|
64
|
+
checkNodejsVersion()
|
|
60
65
|
|
|
66
|
+
const controller = new AbortController()
|
|
61
67
|
const parser = program
|
|
62
68
|
.strict()
|
|
63
69
|
.showHelpOnFail(false, "使用 lzc-cli help 查看更多帮助")
|