@lazycatcloud/lzc-cli 1.1.4 → 1.1.5
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/cmds/dev.js +2 -0
- package/lib/box/index.js +2 -0
- package/lib/box/qemu_vm_mgr.js +25 -12
- package/lib/builder.js +12 -1
- package/lib/dev.js +4 -5
- package/lib/sdk.js +25 -0
- package/package.json +2 -2
- package/template/vue/vue.config.js +15 -0
package/cmds/dev.js
CHANGED
|
@@ -4,6 +4,7 @@ import chalk from "chalk";
|
|
|
4
4
|
import Dev from "../lib/dev.js";
|
|
5
5
|
import env, { sdkEnv } from "../lib/env.js";
|
|
6
6
|
import BoxAPI from "../lib/api.js";
|
|
7
|
+
import { dockerPullLzcAppsImage } from "../lib/sdk.js";
|
|
7
8
|
|
|
8
9
|
// this set of api target box
|
|
9
10
|
class Develop {
|
|
@@ -26,6 +27,7 @@ class Develop {
|
|
|
26
27
|
|
|
27
28
|
if (build) {
|
|
28
29
|
appdev.reset();
|
|
30
|
+
await dockerPullLzcAppsImage(sdkEnv.sdkUrl);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
// 当如果已经连接。直接连接ssh
|
package/lib/box/index.js
CHANGED
|
@@ -25,6 +25,8 @@ async function initQemuVM(ensureResources = false) {
|
|
|
25
25
|
scheme.path = path.join(contextDirname(), "box-emulator", scheme.path);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
fs.mkdirSync(scheme.path, { recursive: true });
|
|
29
|
+
|
|
28
30
|
if (ensureResources) {
|
|
29
31
|
// 使用本地网络 api 调试 new QemuResource(scheme.path, "http://127.0.0.1");
|
|
30
32
|
let resource = new QemuResource(scheme.path);
|
package/lib/box/qemu_vm_mgr.js
CHANGED
|
@@ -5,10 +5,11 @@ import path from "node:path";
|
|
|
5
5
|
import inquirer from "inquirer";
|
|
6
6
|
import https from "node:https";
|
|
7
7
|
import http from "node:http";
|
|
8
|
-
import lz4 from "lz4";
|
|
9
8
|
import process from "node:process";
|
|
10
9
|
import net from "node:net";
|
|
11
10
|
import fetch from "node-fetch";
|
|
11
|
+
import zlib from "node:zlib";
|
|
12
|
+
import os from "node:os";
|
|
12
13
|
|
|
13
14
|
async function getFreePort() {
|
|
14
15
|
return new Promise((resolve, reject) => {
|
|
@@ -39,7 +40,7 @@ export class QemuResource {
|
|
|
39
40
|
*/
|
|
40
41
|
constructor(
|
|
41
42
|
diskDir = "~/.cache/box-emulator",
|
|
42
|
-
downloadUrl = "https://dl.lazycat.cloud/sdk
|
|
43
|
+
downloadUrl = "https://dl.lazycat.cloud/sdk"
|
|
43
44
|
) {
|
|
44
45
|
this.diskDir = diskDir;
|
|
45
46
|
this.downloadUrl = downloadUrl;
|
|
@@ -71,7 +72,7 @@ export class QemuResource {
|
|
|
71
72
|
* 目前的更新,只是使用 md5 来判断是否需要重新下载 md5, 并不会使用 md5 来判断所下载的数据是否正确。
|
|
72
73
|
*/
|
|
73
74
|
async shouldUpdate() {
|
|
74
|
-
let oldMd5Path = path.join(this.diskDir, "disk-system.qcow2.
|
|
75
|
+
let oldMd5Path = path.join(this.diskDir, "disk-system.qcow2.md5");
|
|
75
76
|
|
|
76
77
|
// 如果不存在 md5 文件,直接返回需要更新
|
|
77
78
|
try {
|
|
@@ -83,7 +84,7 @@ export class QemuResource {
|
|
|
83
84
|
// 拉取最新的 md5
|
|
84
85
|
let newMd5;
|
|
85
86
|
try {
|
|
86
|
-
let url = `${this.downloadUrl}/disk-system.qcow2.
|
|
87
|
+
let url = `${this.downloadUrl}/vm/disk-system.qcow2.md5`;
|
|
87
88
|
let res = await fetch(url);
|
|
88
89
|
if (res.status !== 200) {
|
|
89
90
|
return false;
|
|
@@ -109,26 +110,34 @@ export class QemuResource {
|
|
|
109
110
|
} catch {}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
await this.downloadOVMF();
|
|
112
114
|
await this.downloadSystemDisk();
|
|
113
115
|
await this.downloadPrivateKey();
|
|
114
116
|
await this.downloadSystemDiskMd5();
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
async downloadOVMF() {
|
|
120
|
+
let name = `${os.arch()}.OVMF.fd`;
|
|
121
|
+
let savePath = path.join(this.diskDir, name);
|
|
122
|
+
let url = `${this.downloadUrl}/${name}`;
|
|
123
|
+
await this.download(url, savePath);
|
|
124
|
+
}
|
|
125
|
+
|
|
117
126
|
async downloadSystemDiskMd5() {
|
|
118
|
-
let savePath = path.join(this.diskDir, "disk-system.qcow2.
|
|
119
|
-
let url = `${this.downloadUrl}/disk-system.qcow2.
|
|
127
|
+
let savePath = path.join(this.diskDir, "disk-system.qcow2.md5");
|
|
128
|
+
let url = `${this.downloadUrl}/vm/disk-system.qcow2.md5`;
|
|
120
129
|
await this.download(url, savePath);
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
async downloadSystemDisk() {
|
|
124
133
|
let savePath = path.join(this.diskDir, "disk-system.qcow2");
|
|
125
|
-
let url = `${this.downloadUrl}/disk-system.qcow2.
|
|
134
|
+
let url = `${this.downloadUrl}/vm/disk-system.qcow2.gz`;
|
|
126
135
|
await this.download(url, savePath, true);
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
async downloadPrivateKey() {
|
|
130
139
|
let savePath = path.join(this.diskDir, "id_rsa");
|
|
131
|
-
let url = `${this.downloadUrl}/id_rsa`;
|
|
140
|
+
let url = `${this.downloadUrl}/vm/id_rsa`;
|
|
132
141
|
await this.download(url, savePath);
|
|
133
142
|
fs.chmodSync(savePath, 0o400);
|
|
134
143
|
return;
|
|
@@ -147,7 +156,7 @@ export class QemuResource {
|
|
|
147
156
|
);
|
|
148
157
|
}
|
|
149
158
|
|
|
150
|
-
download(url, savePath,
|
|
159
|
+
download(url, savePath, enableGzip = false) {
|
|
151
160
|
let tmpPath = savePath + ".tmp";
|
|
152
161
|
const options = new URL(url);
|
|
153
162
|
let request = url.startsWith("https") ? https.request : http.request;
|
|
@@ -167,8 +176,8 @@ export class QemuResource {
|
|
|
167
176
|
});
|
|
168
177
|
|
|
169
178
|
let outputFile = fs.createWriteStream(tmpPath, { flags: "w+" });
|
|
170
|
-
if (
|
|
171
|
-
let decoder =
|
|
179
|
+
if (enableGzip) {
|
|
180
|
+
let decoder = zlib.createUnzip();
|
|
172
181
|
res.pipe(decoder).pipe(outputFile);
|
|
173
182
|
} else {
|
|
174
183
|
res.pipe(outputFile);
|
|
@@ -385,7 +394,11 @@ export class QemuVM {
|
|
|
385
394
|
* 寻找默认可用的 bios 文件
|
|
386
395
|
*/
|
|
387
396
|
findBIOS() {
|
|
388
|
-
let includes = [
|
|
397
|
+
let includes = [
|
|
398
|
+
"/usr/share/ovmf/x64/OVMF.fd",
|
|
399
|
+
"/usr/share/ovmf/OVMF.fd",
|
|
400
|
+
path.join(this.scheme.path, `${os.arch()}.OVMF.fd`),
|
|
401
|
+
];
|
|
389
402
|
for (let file of includes) {
|
|
390
403
|
try {
|
|
391
404
|
fs.accessSync(file, fs.constants.F_OK);
|
package/lib/builder.js
CHANGED
|
@@ -4,7 +4,7 @@ import path from "path";
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import execa from "execa";
|
|
6
6
|
// import { archiveFolder } from "./utils.js";
|
|
7
|
-
import { DockerClient } from "./sdk.js";
|
|
7
|
+
import { dockerPullLzcAppsImage, DockerClient } from "./sdk.js";
|
|
8
8
|
import { DockerfileParser } from "dockerfile-ast";
|
|
9
9
|
import glob from "fast-glob";
|
|
10
10
|
import ignore from "@balena/dockerignore";
|
|
@@ -213,6 +213,17 @@ export default class Builder {
|
|
|
213
213
|
console.log(host);
|
|
214
214
|
const docker = await new DockerClient(host).init();
|
|
215
215
|
try {
|
|
216
|
+
// TODO, 使用 docker.pull 方法会失败, 原因未知, 使用 workaround 方案
|
|
217
|
+
// docker.pull(
|
|
218
|
+
// "hello-world",
|
|
219
|
+
// // "registry.lazycat.cloud/lzc/lzcapp:0.1",
|
|
220
|
+
// // { authconfig: { auth: "bG5rczpsbmtzMjAyMA==" } },
|
|
221
|
+
// (err, stream) => {
|
|
222
|
+
// console.log("====", err, stream);
|
|
223
|
+
// }
|
|
224
|
+
// );
|
|
225
|
+
await dockerPullLzcAppsImage(host);
|
|
226
|
+
|
|
216
227
|
return new Promise(async (resolve, reject) => {
|
|
217
228
|
let refresher = new StatusRefresher();
|
|
218
229
|
|
package/lib/dev.js
CHANGED
|
@@ -15,6 +15,7 @@ import _get from "lodash.get";
|
|
|
15
15
|
import { execPreBuild } from "./builder.js";
|
|
16
16
|
import Key from "./key.js";
|
|
17
17
|
import chokidar from "chokidar";
|
|
18
|
+
import commandExists from "command-exists";
|
|
18
19
|
|
|
19
20
|
import Archiver from "../lib/archiver.js";
|
|
20
21
|
|
|
@@ -138,14 +139,12 @@ class DevModule {
|
|
|
138
139
|
keyFile,
|
|
139
140
|
].join(" ");
|
|
140
141
|
// 检查rsync工具是否存在:提示用户
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
stdio: "ignore",
|
|
144
|
-
});
|
|
145
|
-
} catch {
|
|
142
|
+
const rsyncExisted = commandExists.sync('rsync')
|
|
143
|
+
if (!rsyncExisted) {
|
|
146
144
|
console.log(chalk.red("请检查 rsync 是否安装,路径是否正确!"));
|
|
147
145
|
process.exit();
|
|
148
146
|
}
|
|
147
|
+
// FIXME: 下方执行命令不确定是否有兼容性问题
|
|
149
148
|
execSync(
|
|
150
149
|
`rsync --rsh='${rsh}' -czrPR . root@${appAddr}:/root/${this.appId} --filter=':- .gitignore' --exclude='node_modules' --exclude='.git' --delete`,
|
|
151
150
|
{ stdio: ["ignore", "ignore", "inherit"] }
|
package/lib/sdk.js
CHANGED
|
@@ -124,3 +124,28 @@ export class SSHClient {
|
|
|
124
124
|
);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
+
|
|
128
|
+
export async function dockerPullLzcAppsImage(host) {
|
|
129
|
+
console.log(chalk.yellow("* 更新lzcapp镜像, 未来可能会移除此操作"));
|
|
130
|
+
const opts = await connectOptions(host);
|
|
131
|
+
const client = new SSHClient(opts);
|
|
132
|
+
await client.connect();
|
|
133
|
+
try {
|
|
134
|
+
const stream = await client.exec(
|
|
135
|
+
"docker pull registry.lazycat.cloud/lzc/lzcapp:0.1"
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
stream.stdout.pipe(process.stdout);
|
|
140
|
+
stream.stderr.pipe(process.stdout);
|
|
141
|
+
stream.on("close", () => {
|
|
142
|
+
client.close();
|
|
143
|
+
resolve();
|
|
144
|
+
});
|
|
145
|
+
stream.on("error", (e) => reject(e));
|
|
146
|
+
});
|
|
147
|
+
} catch (e) {
|
|
148
|
+
client.close();
|
|
149
|
+
throw e;
|
|
150
|
+
}
|
|
151
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "mocha",
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
"lodash.merge": "^4.6.2",
|
|
49
49
|
"lodash.mergewith": "^4.6.2",
|
|
50
50
|
"log-update": "^5.0.0",
|
|
51
|
-
"lz4": "^0.6.5",
|
|
52
51
|
"minimist": "^1.2.5",
|
|
53
52
|
"node-fetch": "^2.6.6",
|
|
54
53
|
"node-stream-zip": "^1.15.0",
|
|
@@ -59,6 +58,7 @@
|
|
|
59
58
|
"yargs": "^17.5.1"
|
|
60
59
|
},
|
|
61
60
|
"devDependencies": {
|
|
61
|
+
"@types/command-exists": "^1.2.0",
|
|
62
62
|
"chai": "^4.3.6",
|
|
63
63
|
"mocha": "^9.2.2",
|
|
64
64
|
"prettier": "^2.5.0"
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
const nodeVersions = process.versions.node.split(".");
|
|
2
|
+
if (
|
|
3
|
+
nodeVersions[0] >= 17 &&
|
|
4
|
+
process.env["NODE_OPTIONS"].search(/--openssl-legacy-provider/) == -1
|
|
5
|
+
) {
|
|
6
|
+
console.warn(`
|
|
7
|
+
当前 nodejs 版本为 ${process.version}
|
|
8
|
+
|
|
9
|
+
nodejs 17.0.0 后的版本由于使用的 openssl 3.0 的原因。需要使用设置
|
|
10
|
+
export NODE_OPTIONS=--openssl-legacy-provider
|
|
11
|
+
|
|
12
|
+
推荐使用 vue3 进行开发。
|
|
13
|
+
`);
|
|
14
|
+
}
|
|
15
|
+
|
|
1
16
|
module.exports = {
|
|
2
17
|
devServer: {
|
|
3
18
|
historyApiFallback: true,
|