@lazycatcloud/lzc-cli 1.2.26 → 1.2.28
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/lib/app/apkshell.js +37 -0
- package/lib/app/index.js +74 -74
- package/lib/app/lpk_build.js +113 -117
- package/lib/app/lpk_create.js +78 -148
- package/lib/app/lpk_create_generator.js +101 -74
- package/lib/app/lpk_debug_bridge.js +69 -60
- package/lib/app/lpk_devshell.js +228 -227
- package/lib/app/lpk_devshell_docker.js +28 -28
- package/lib/app/lpk_installer.js +59 -49
- package/lib/appstore/index.js +29 -29
- package/lib/appstore/login.js +64 -64
- package/lib/appstore/prePublish.js +68 -68
- package/lib/appstore/publish.js +55 -55
- package/lib/box/index.js +25 -25
- package/lib/env.js +18 -18
- package/lib/shellapi.js +55 -58
- package/lib/utils.js +228 -151
- package/package.json +7 -1
- package/scripts/cli.js +56 -56
- package/template/_lpk/manifest.yml.in +8 -8
- package/template/vue/README.md +29 -0
- package/template/vue/index.html +13 -0
- package/template/vue/lzc-build.yml +59 -0
- package/template/vue/lzc-icon.png +0 -0
- package/template/vue/package.json +20 -0
- package/template/vue/public/vite.svg +1 -0
- package/template/vue/src/App.vue +30 -0
- package/template/vue/src/assets/vue.svg +1 -0
- package/template/vue/src/components/HelloWorld.vue +41 -0
- package/template/vue/src/main.ts +5 -0
- package/template/vue/src/style.css +79 -0
- package/template/vue/src/vite-env.d.ts +1 -0
- package/template/vue/tsconfig.app.json +24 -0
- package/template/vue/tsconfig.json +7 -0
- package/template/vue/tsconfig.node.json +22 -0
- package/template/vue/vite.config.ts +7 -0
package/lib/utils.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import path from "path"
|
|
2
|
-
import fs from "fs"
|
|
3
|
-
import os from "os"
|
|
4
|
-
import glob from "fast-glob"
|
|
5
|
-
import yaml from "js-yaml"
|
|
6
|
-
import mergeWith from "lodash.mergewith"
|
|
7
|
-
import { dirname } from "path"
|
|
8
|
-
import { fileURLToPath } from "url"
|
|
9
|
-
import ignore from "ignore"
|
|
10
|
-
import { createHash } from "node:crypto"
|
|
11
|
-
import https from "node:https"
|
|
12
|
-
import http from "node:http"
|
|
13
|
-
import zlib from "node:zlib"
|
|
14
|
-
import process from "node:process"
|
|
15
|
-
import { spawnSync } from "node:child_process"
|
|
16
|
-
import logger from "loglevel"
|
|
17
|
-
import * as tar from "tar"
|
|
1
|
+
import path from "path"
|
|
2
|
+
import fs from "fs"
|
|
3
|
+
import os from "os"
|
|
4
|
+
import glob from "fast-glob"
|
|
5
|
+
import yaml from "js-yaml"
|
|
6
|
+
import mergeWith from "lodash.mergewith"
|
|
7
|
+
import { dirname } from "path"
|
|
8
|
+
import { fileURLToPath } from "url"
|
|
9
|
+
import ignore from "ignore"
|
|
10
|
+
import { createHash } from "node:crypto"
|
|
11
|
+
import https from "node:https"
|
|
12
|
+
import http from "node:http"
|
|
13
|
+
import zlib from "node:zlib"
|
|
14
|
+
import process from "node:process"
|
|
15
|
+
import { spawnSync } from "node:child_process"
|
|
16
|
+
import logger from "loglevel"
|
|
17
|
+
import * as tar from "tar"
|
|
18
|
+
import dns from "node:dns/promises"
|
|
18
19
|
|
|
19
20
|
export const envsubstr = async (templateContents, args) => {
|
|
20
|
-
const parse = await importDefault("envsub/js/envsub-parser.js")
|
|
21
|
-
return parse(templateContents, args)
|
|
22
|
-
}
|
|
21
|
+
const parse = await importDefault("envsub/js/envsub-parser.js")
|
|
22
|
+
return parse(templateContents, args)
|
|
23
|
+
}
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* 确保文件夹存在
|
|
@@ -27,31 +28,70 @@ export const envsubstr = async (templateContents, args) => {
|
|
|
27
28
|
*
|
|
28
29
|
*/
|
|
29
30
|
export function ensureDir(filePath) {
|
|
30
|
-
let dirPath
|
|
31
|
+
let dirPath
|
|
31
32
|
if (filePath.endsWith("/")) {
|
|
32
|
-
dirPath = filePath
|
|
33
|
+
dirPath = filePath
|
|
33
34
|
} else {
|
|
34
|
-
dirPath = path.dirname(filePath)
|
|
35
|
+
dirPath = path.dirname(filePath)
|
|
35
36
|
}
|
|
36
37
|
if (!fs.existsSync(dirPath)) {
|
|
37
|
-
fs.mkdirSync(dirPath, { recursive: true })
|
|
38
|
+
fs.mkdirSync(dirPath, { recursive: true })
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
export function ensureDirectoryExists(filePath, isRenameOrClear) {
|
|
43
|
+
let result = { isExists: false, renamedFileName: undefined }
|
|
44
|
+
try {
|
|
45
|
+
const stats = fs.statSync(filePath) // 获取文件或目录的状态
|
|
46
|
+
result.isExists = true
|
|
47
|
+
if (isRenameOrClear) {
|
|
48
|
+
if (stats.isDirectory()) {
|
|
49
|
+
const newPath = getUniquePath(filePath)
|
|
50
|
+
result.renamedFileName = path.basename(newPath)
|
|
51
|
+
fs.renameSync(filePath, newPath)
|
|
52
|
+
} else {
|
|
53
|
+
fs.rmSync(filePath)
|
|
54
|
+
}
|
|
55
|
+
fs.mkdirSync(filePath, { recursive: true })
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (err.code === "ENOENT") {
|
|
59
|
+
fs.mkdirSync(filePath, { recursive: true })
|
|
60
|
+
} else {
|
|
61
|
+
throw `创建文件夹${filePath}错误: ${err}`
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 如果该路径已存在,则返回带递增数字的路径
|
|
68
|
+
function getUniquePath(basePath) {
|
|
69
|
+
let dirName = path.basename(basePath)
|
|
70
|
+
let dirPath = basePath
|
|
71
|
+
let index = 1
|
|
72
|
+
// 检查是否存在同名目录
|
|
73
|
+
while (fs.existsSync(dirPath)) {
|
|
74
|
+
dirName = `${path.basename(basePath, path.extname(basePath))}_${index}`
|
|
75
|
+
dirPath = path.join(path.dirname(basePath), dirName)
|
|
76
|
+
index++
|
|
77
|
+
}
|
|
78
|
+
return dirPath
|
|
79
|
+
}
|
|
80
|
+
|
|
41
81
|
export async function createTemplateFileCommon(templateFile, outputFile, env) {
|
|
42
82
|
const options = {
|
|
43
83
|
envs: toPair(env),
|
|
44
84
|
syntax: "default",
|
|
45
|
-
protect: false
|
|
46
|
-
}
|
|
85
|
+
protect: false
|
|
86
|
+
}
|
|
47
87
|
const output = await envsubstr(fs.readFileSync(templateFile, "utf-8"), {
|
|
48
|
-
options
|
|
49
|
-
})
|
|
50
|
-
fs.writeFileSync(outputFile, output)
|
|
88
|
+
options
|
|
89
|
+
})
|
|
90
|
+
fs.writeFileSync(outputFile, output)
|
|
51
91
|
}
|
|
52
92
|
|
|
53
93
|
export function loadFromYaml(file) {
|
|
54
|
-
return yaml.load(fs.readFileSync(file, "utf8"))
|
|
94
|
+
return yaml.load(fs.readFileSync(file, "utf8"))
|
|
55
95
|
}
|
|
56
96
|
|
|
57
97
|
export function dumpToYaml(template, target) {
|
|
@@ -59,113 +99,113 @@ export function dumpToYaml(template, target) {
|
|
|
59
99
|
target,
|
|
60
100
|
yaml.dump(template, {
|
|
61
101
|
styles: {
|
|
62
|
-
"!!null": "empty"
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
)
|
|
102
|
+
"!!null": "empty" // dump null as ""
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
)
|
|
66
106
|
}
|
|
67
107
|
|
|
68
108
|
export function toPair(object) {
|
|
69
109
|
return Object.keys(object).map((key) => {
|
|
70
|
-
let value = object[key] ? object[key].toString() : ""
|
|
71
|
-
key = key.replace(/-/g, "_")
|
|
110
|
+
let value = object[key] ? object[key].toString() : ""
|
|
111
|
+
key = key.replace(/-/g, "_")
|
|
72
112
|
return {
|
|
73
113
|
name: key,
|
|
74
|
-
value
|
|
75
|
-
}
|
|
76
|
-
})
|
|
114
|
+
value
|
|
115
|
+
}
|
|
116
|
+
})
|
|
77
117
|
}
|
|
78
118
|
|
|
79
119
|
export async function envTemplateFile(templateFile, env) {
|
|
80
|
-
const template = yaml.load(fs.readFileSync(templateFile, "utf8"))
|
|
120
|
+
const template = yaml.load(fs.readFileSync(templateFile, "utf8"))
|
|
81
121
|
const options = {
|
|
82
122
|
envs: toPair(env),
|
|
83
123
|
syntax: "default",
|
|
84
|
-
protect: false
|
|
85
|
-
}
|
|
124
|
+
protect: false
|
|
125
|
+
}
|
|
86
126
|
return await envsubstr(
|
|
87
127
|
yaml.dump(template, {
|
|
88
128
|
styles: {
|
|
89
|
-
"!!null": "empty"
|
|
90
|
-
}
|
|
129
|
+
"!!null": "empty" // dump null as ""
|
|
130
|
+
}
|
|
91
131
|
}),
|
|
92
|
-
{ options }
|
|
93
|
-
)
|
|
132
|
+
{ options }
|
|
133
|
+
)
|
|
94
134
|
}
|
|
95
135
|
|
|
96
136
|
export function mergeYamlInMemory(args) {
|
|
97
137
|
if (args.length == 0) {
|
|
98
|
-
return {}
|
|
138
|
+
return {}
|
|
99
139
|
} else if (args.length == 1) {
|
|
100
|
-
return args[0]
|
|
140
|
+
return args[0]
|
|
101
141
|
}
|
|
102
142
|
return args.reduce((prev, curr) => {
|
|
103
143
|
let result = mergeWith(prev, curr, (objValue, srcValue) => {
|
|
104
144
|
if (Array.isArray(objValue)) {
|
|
105
|
-
return objValue.concat(srcValue)
|
|
145
|
+
return objValue.concat(srcValue)
|
|
106
146
|
}
|
|
107
|
-
})
|
|
108
|
-
return result
|
|
109
|
-
}, {})
|
|
147
|
+
})
|
|
148
|
+
return result
|
|
149
|
+
}, {})
|
|
110
150
|
}
|
|
111
151
|
|
|
112
152
|
export function contextDirname(url = import.meta.url) {
|
|
113
|
-
return dirname(fileURLToPath(url))
|
|
153
|
+
return dirname(fileURLToPath(url))
|
|
114
154
|
}
|
|
115
155
|
|
|
116
156
|
export async function importDefault(pkgPath) {
|
|
117
|
-
let mod = await import(pkgPath)
|
|
118
|
-
return mod.default
|
|
157
|
+
let mod = await import(pkgPath)
|
|
158
|
+
return mod.default
|
|
119
159
|
}
|
|
120
160
|
|
|
121
161
|
export class GitIgnore {
|
|
122
162
|
constructor(root) {
|
|
123
|
-
this.root = root
|
|
124
|
-
this.ignores = []
|
|
163
|
+
this.root = root
|
|
164
|
+
this.ignores = []
|
|
125
165
|
}
|
|
126
166
|
|
|
127
167
|
async collect() {
|
|
128
168
|
const files = await glob(["**/.gitignore"], {
|
|
129
169
|
cwd: this.root,
|
|
130
170
|
dot: true,
|
|
131
|
-
deep: 3
|
|
132
|
-
})
|
|
171
|
+
deep: 3
|
|
172
|
+
})
|
|
133
173
|
|
|
134
|
-
files.forEach((f) => this._add(f))
|
|
174
|
+
files.forEach((f) => this._add(f))
|
|
135
175
|
}
|
|
136
176
|
|
|
137
177
|
_add(ignoreFile) {
|
|
138
|
-
let data = fs.readFileSync(ignoreFile, "utf8")
|
|
139
|
-
let ig = ignore({ allowRelativePaths: true })
|
|
140
|
-
ig.add(data.split("\n"))
|
|
178
|
+
let data = fs.readFileSync(ignoreFile, "utf8")
|
|
179
|
+
let ig = ignore({ allowRelativePaths: true })
|
|
180
|
+
ig.add(data.split("\n"))
|
|
141
181
|
this.ignores.push({
|
|
142
182
|
ig,
|
|
143
|
-
dir: path.dirname(ignoreFile)
|
|
144
|
-
})
|
|
183
|
+
dir: path.dirname(ignoreFile)
|
|
184
|
+
})
|
|
145
185
|
}
|
|
146
186
|
|
|
147
187
|
contain(filepath) {
|
|
148
188
|
return this.ignores.some(({ ig, dir }) => {
|
|
149
189
|
// 去除不应该计算ignore 的文件
|
|
150
190
|
if (!filepath.startsWith(dir)) {
|
|
151
|
-
return false
|
|
191
|
+
return false
|
|
152
192
|
}
|
|
153
193
|
|
|
154
|
-
return ig.ignores(path.relative(dir, filepath))
|
|
155
|
-
})
|
|
194
|
+
return ig.ignores(path.relative(dir, filepath))
|
|
195
|
+
})
|
|
156
196
|
}
|
|
157
197
|
}
|
|
158
198
|
|
|
159
199
|
export function isDirSync(path) {
|
|
160
|
-
let stat = fs.statSync(path)
|
|
161
|
-
return stat.isDirectory()
|
|
200
|
+
let stat = fs.statSync(path)
|
|
201
|
+
return stat.isDirectory()
|
|
162
202
|
}
|
|
163
203
|
|
|
164
204
|
export function isDirExist(path) {
|
|
165
205
|
try {
|
|
166
|
-
return isDirSync(path)
|
|
206
|
+
return isDirSync(path)
|
|
167
207
|
} catch {
|
|
168
|
-
return false
|
|
208
|
+
return false
|
|
169
209
|
}
|
|
170
210
|
}
|
|
171
211
|
|
|
@@ -173,173 +213,182 @@ export function isFileExist(path) {
|
|
|
173
213
|
try {
|
|
174
214
|
fs.accessSync(
|
|
175
215
|
path,
|
|
176
|
-
fs.constants.W_OK | fs.constants.R_OK | fs.constants.F_OK
|
|
177
|
-
)
|
|
178
|
-
return true
|
|
216
|
+
fs.constants.W_OK | fs.constants.R_OK | fs.constants.F_OK
|
|
217
|
+
)
|
|
218
|
+
return true
|
|
179
219
|
} catch {
|
|
180
|
-
return false
|
|
220
|
+
return false
|
|
181
221
|
}
|
|
182
222
|
}
|
|
183
223
|
|
|
184
224
|
export async function sleep(ms) {
|
|
185
225
|
return new Promise((resolve) => {
|
|
186
|
-
setTimeout(resolve, ms)
|
|
187
|
-
})
|
|
226
|
+
setTimeout(resolve, ms)
|
|
227
|
+
})
|
|
188
228
|
}
|
|
189
229
|
|
|
190
230
|
export async function md5String(str) {
|
|
191
|
-
const hash = createHash("md5")
|
|
192
|
-
hash.update(str)
|
|
193
|
-
return hash.digest("hex")
|
|
231
|
+
const hash = createHash("md5")
|
|
232
|
+
hash.update(str)
|
|
233
|
+
return hash.digest("hex")
|
|
194
234
|
}
|
|
195
235
|
|
|
196
236
|
export async function md5File(filepath) {
|
|
197
|
-
const hash = createHash("md5")
|
|
198
|
-
const input = fs.createReadStream(filepath)
|
|
237
|
+
const hash = createHash("md5")
|
|
238
|
+
const input = fs.createReadStream(filepath)
|
|
199
239
|
return new Promise((resolve) => {
|
|
200
240
|
input.on("readable", () => {
|
|
201
|
-
const data = input.read()
|
|
241
|
+
const data = input.read()
|
|
202
242
|
if (data) {
|
|
203
|
-
hash.update(data)
|
|
243
|
+
hash.update(data)
|
|
204
244
|
} else {
|
|
205
|
-
resolve(hash.digest("hex"))
|
|
245
|
+
resolve(hash.digest("hex"))
|
|
206
246
|
}
|
|
207
|
-
})
|
|
208
|
-
})
|
|
247
|
+
})
|
|
248
|
+
})
|
|
209
249
|
}
|
|
210
250
|
|
|
211
251
|
export class Downloader {
|
|
212
252
|
constructor() {}
|
|
213
253
|
|
|
214
254
|
showDownloadingProgress(received, total) {
|
|
215
|
-
let percentage = ((received * 100) / total).toFixed(2)
|
|
216
|
-
process.stdout.write("\r")
|
|
255
|
+
let percentage = ((received * 100) / total).toFixed(2)
|
|
256
|
+
process.stdout.write("\r")
|
|
217
257
|
process.stdout.write(
|
|
218
258
|
percentage +
|
|
219
259
|
"% | " +
|
|
220
260
|
received +
|
|
221
261
|
" bytes downloaded out of " +
|
|
222
262
|
total +
|
|
223
|
-
" bytes."
|
|
224
|
-
)
|
|
263
|
+
" bytes."
|
|
264
|
+
)
|
|
225
265
|
}
|
|
226
266
|
|
|
227
267
|
download(url, savePath, enableGzip = false) {
|
|
228
|
-
let tmpPath = savePath + ".tmp"
|
|
229
|
-
const options = new URL(url)
|
|
230
|
-
let request = url.startsWith("https") ? https.request : http.request
|
|
268
|
+
let tmpPath = savePath + ".tmp"
|
|
269
|
+
const options = new URL(url)
|
|
270
|
+
let request = url.startsWith("https") ? https.request : http.request
|
|
231
271
|
|
|
232
272
|
return new Promise((resolve, reject) => {
|
|
233
273
|
const req = request(options, (res) => {
|
|
234
274
|
if (res.statusCode != 200) {
|
|
235
|
-
reject(`下载 ${url} 失败`)
|
|
236
|
-
return
|
|
275
|
+
reject(`下载 ${url} 失败`)
|
|
276
|
+
return
|
|
237
277
|
}
|
|
238
278
|
|
|
239
|
-
let total = parseInt(res.headers["content-length"])
|
|
240
|
-
let recive = 0
|
|
279
|
+
let total = parseInt(res.headers["content-length"])
|
|
280
|
+
let recive = 0
|
|
241
281
|
res.on("data", (chunk) => {
|
|
242
|
-
recive += chunk.length
|
|
243
|
-
this.showDownloadingProgress(recive, total)
|
|
244
|
-
})
|
|
282
|
+
recive += chunk.length
|
|
283
|
+
this.showDownloadingProgress(recive, total)
|
|
284
|
+
})
|
|
245
285
|
|
|
246
|
-
let outputFile = fs.createWriteStream(tmpPath, { flags: "w+" })
|
|
286
|
+
let outputFile = fs.createWriteStream(tmpPath, { flags: "w+" })
|
|
247
287
|
if (enableGzip) {
|
|
248
|
-
let decoder = zlib.createUnzip()
|
|
249
|
-
res.pipe(decoder).pipe(outputFile)
|
|
288
|
+
let decoder = zlib.createUnzip()
|
|
289
|
+
res.pipe(decoder).pipe(outputFile)
|
|
250
290
|
} else {
|
|
251
|
-
res.pipe(outputFile)
|
|
291
|
+
res.pipe(outputFile)
|
|
252
292
|
}
|
|
253
293
|
|
|
254
|
-
outputFile.on("error", reject)
|
|
294
|
+
outputFile.on("error", reject)
|
|
255
295
|
outputFile.on("finish", () => {
|
|
256
|
-
fs.renameSync(tmpPath, savePath)
|
|
257
|
-
process.stdout.write("\n")
|
|
258
|
-
resolve()
|
|
259
|
-
})
|
|
260
|
-
})
|
|
261
|
-
req.on("error", reject)
|
|
262
|
-
req.end()
|
|
263
|
-
})
|
|
296
|
+
fs.renameSync(tmpPath, savePath)
|
|
297
|
+
process.stdout.write("\n")
|
|
298
|
+
resolve()
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
req.on("error", reject)
|
|
302
|
+
req.end()
|
|
303
|
+
})
|
|
264
304
|
}
|
|
265
305
|
}
|
|
266
306
|
|
|
267
307
|
export class FileLocker {
|
|
268
308
|
constructor(id) {
|
|
269
|
-
this.filename = undefined
|
|
270
|
-
this.fd = undefined
|
|
271
|
-
this.id = id
|
|
309
|
+
this.filename = undefined
|
|
310
|
+
this.fd = undefined
|
|
311
|
+
this.id = id
|
|
272
312
|
}
|
|
273
313
|
lock() {
|
|
274
|
-
this.filename = path.resolve(os.tmpdir(), "lzc-cli-file-lock", this.id)
|
|
275
|
-
ensureDir(this.filename)
|
|
314
|
+
this.filename = path.resolve(os.tmpdir(), "lzc-cli-file-lock", this.id)
|
|
315
|
+
ensureDir(this.filename)
|
|
276
316
|
|
|
277
317
|
try {
|
|
278
|
-
this.fd = fs.openSync(this.filename, "wx+")
|
|
318
|
+
this.fd = fs.openSync(this.filename, "wx+")
|
|
279
319
|
} catch (e) {
|
|
280
320
|
if (e.code == "EEXIST" && !this.withOpen(this.filename)) {
|
|
281
|
-
logger.debug("filelock exist open with w+")
|
|
282
|
-
this.fd = fs.openSync(this.filename, "w+")
|
|
321
|
+
logger.debug("filelock exist open with w+")
|
|
322
|
+
this.fd = fs.openSync(this.filename, "w+")
|
|
283
323
|
} else {
|
|
284
|
-
throw e
|
|
324
|
+
throw e
|
|
285
325
|
}
|
|
286
326
|
}
|
|
287
327
|
}
|
|
288
328
|
unlock() {
|
|
289
329
|
if (this.fd) {
|
|
290
|
-
fs.closeSync(this.fd)
|
|
291
|
-
fs.rmSync(this.filename)
|
|
292
|
-
this.fd = undefined
|
|
293
|
-
this.filename = undefined
|
|
330
|
+
fs.closeSync(this.fd)
|
|
331
|
+
fs.rmSync(this.filename)
|
|
332
|
+
this.fd = undefined
|
|
333
|
+
this.filename = undefined
|
|
294
334
|
}
|
|
295
335
|
}
|
|
296
336
|
withOpen(filename) {
|
|
297
|
-
const p = spawnSync("lsof", ["-w", "-t", filename])
|
|
337
|
+
const p = spawnSync("lsof", ["-w", "-t", filename])
|
|
298
338
|
if (p.status === 0) {
|
|
299
|
-
return true
|
|
339
|
+
return true
|
|
300
340
|
} else {
|
|
301
|
-
return false
|
|
341
|
+
return false
|
|
302
342
|
}
|
|
303
343
|
}
|
|
304
344
|
}
|
|
305
345
|
|
|
346
|
+
export function isValidAppId(appId) {
|
|
347
|
+
// 暂时去掉 - 的支持
|
|
348
|
+
// const regex = new RegExp("^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$")
|
|
349
|
+
const regex = new RegExp("^[a-z][a-z0-9]{0,61}[a-zA-Z0-9]$")
|
|
350
|
+
return regex.test(appId)
|
|
351
|
+
}
|
|
352
|
+
|
|
306
353
|
export function isValidPackageName(packageName) {
|
|
307
|
-
|
|
308
|
-
|
|
354
|
+
// 暂时去掉 - 的支持
|
|
355
|
+
// const regex = new RegExp("^(?:[a-z][a-z0-9-]*\\.)+[a-z][a-z0-9-]*$")
|
|
356
|
+
const regex = new RegExp("^(?:[a-z][a-z0-9]*\\.)+[a-z][a-z0-9]*$")
|
|
357
|
+
return regex.test(packageName)
|
|
309
358
|
}
|
|
310
359
|
|
|
311
360
|
export function isUserApp(manifest) {
|
|
312
|
-
return !!manifest["application"]["user_app"]
|
|
361
|
+
return !!manifest["application"]["user_app"]
|
|
313
362
|
}
|
|
314
363
|
|
|
315
364
|
export async function tarContentDir(from, to, cwd = "./") {
|
|
316
365
|
return new Promise((resolve, reject) => {
|
|
317
|
-
const dest = fs.createWriteStream(to)
|
|
366
|
+
const dest = fs.createWriteStream(to)
|
|
318
367
|
tar
|
|
319
368
|
.c(
|
|
320
369
|
{
|
|
321
370
|
cwd: cwd,
|
|
322
371
|
filter: (filePath) => {
|
|
323
|
-
logger.debug(`tar gz ${filePath}`)
|
|
324
|
-
return true
|
|
372
|
+
logger.debug(`tar gz ${filePath}`)
|
|
373
|
+
return true
|
|
325
374
|
},
|
|
326
375
|
sync: true,
|
|
327
376
|
portable: {
|
|
328
377
|
uid: 0,
|
|
329
|
-
gid: 0
|
|
330
|
-
}
|
|
378
|
+
gid: 0
|
|
379
|
+
}
|
|
331
380
|
},
|
|
332
|
-
from
|
|
381
|
+
from
|
|
333
382
|
)
|
|
334
383
|
.pipe(dest)
|
|
335
384
|
.on("close", () => {
|
|
336
|
-
logger.debug(`pack: ${dest.path}`)
|
|
337
|
-
resolve(dest.path)
|
|
385
|
+
logger.debug(`pack: ${dest.path}`)
|
|
386
|
+
resolve(dest.path)
|
|
338
387
|
})
|
|
339
388
|
.on("error", (err) => {
|
|
340
|
-
reject(err)
|
|
341
|
-
})
|
|
342
|
-
})
|
|
389
|
+
reject(err)
|
|
390
|
+
})
|
|
391
|
+
})
|
|
343
392
|
}
|
|
344
393
|
|
|
345
394
|
/**
|
|
@@ -350,7 +399,7 @@ export async function tarContentDir(from, to, cwd = "./") {
|
|
|
350
399
|
*/
|
|
351
400
|
function isPngWithBuffer(buffer) {
|
|
352
401
|
if (!buffer || buffer.length < 8) {
|
|
353
|
-
return false
|
|
402
|
+
return false
|
|
354
403
|
}
|
|
355
404
|
return (
|
|
356
405
|
buffer[0] === 0x89 &&
|
|
@@ -361,15 +410,43 @@ function isPngWithBuffer(buffer) {
|
|
|
361
410
|
buffer[5] === 0x0a &&
|
|
362
411
|
buffer[6] === 0x1a &&
|
|
363
412
|
buffer[7] === 0x0a
|
|
364
|
-
)
|
|
413
|
+
)
|
|
365
414
|
}
|
|
366
415
|
|
|
367
416
|
export function isPngWithFile(filepath) {
|
|
368
|
-
if (!isFileExist(filepath)) return false
|
|
369
|
-
const buf = fs.readFileSync(filepath)
|
|
370
|
-
return isPngWithBuffer(buf)
|
|
417
|
+
if (!isFileExist(filepath)) return false
|
|
418
|
+
const buf = fs.readFileSync(filepath)
|
|
419
|
+
return isPngWithBuffer(buf)
|
|
371
420
|
}
|
|
372
421
|
|
|
373
422
|
export function isDebugMode() {
|
|
374
|
-
return logger.getLevel() <= logger.levels.DEBUG
|
|
423
|
+
return logger.getLevel() <= logger.levels.DEBUG
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export async function resolveDomain(domain) {
|
|
427
|
+
try {
|
|
428
|
+
// Set machine's dns server as defalut dns server
|
|
429
|
+
dns.setServers(["[fc03:1136:3800::1]"])
|
|
430
|
+
const [ipv6Addresses, ipv4Addresses] = await Promise.allSettled([
|
|
431
|
+
dns.resolve6(domain),
|
|
432
|
+
dns.resolve4(domain)
|
|
433
|
+
])
|
|
434
|
+
let resolvedAddress
|
|
435
|
+
if (
|
|
436
|
+
ipv6Addresses.status === "fulfilled" &&
|
|
437
|
+
ipv6Addresses.value.length > 0
|
|
438
|
+
) {
|
|
439
|
+
resolvedAddress = ipv6Addresses.value[0]
|
|
440
|
+
} else if (
|
|
441
|
+
ipv4Addresses.status === "fulfilled" &&
|
|
442
|
+
ipv4Addresses.value.length > 0
|
|
443
|
+
) {
|
|
444
|
+
resolvedAddress = ipv4Addresses.value[0]
|
|
445
|
+
} else {
|
|
446
|
+
throw new Error(`无法解析域名 ${domain}`)
|
|
447
|
+
}
|
|
448
|
+
return resolvedAddress
|
|
449
|
+
} catch (error) {
|
|
450
|
+
throw new Error(`无法解析域名 ${domain}: ${error.message}`)
|
|
451
|
+
}
|
|
375
452
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.28",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"files": [
|
|
6
6
|
"template",
|
|
@@ -44,6 +44,12 @@
|
|
|
44
44
|
"@types/command-exists": "^1.2.3",
|
|
45
45
|
"prettier": "^3.3.3"
|
|
46
46
|
},
|
|
47
|
+
"prettier": {
|
|
48
|
+
"bracketSameLine": true,
|
|
49
|
+
"htmlWhitespaceSensitivity": "ignore",
|
|
50
|
+
"semi": false,
|
|
51
|
+
"trailingComma": "none"
|
|
52
|
+
},
|
|
47
53
|
"publishConfig": {
|
|
48
54
|
"registry": "https://registry.npmjs.org",
|
|
49
55
|
"access": "public"
|