@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 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);
@@ -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/vm"
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.lz4.md5");
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.lz4.md5`;
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.lz4.md5");
119
- let url = `${this.downloadUrl}/disk-system.qcow2.lz4.md5`;
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.lz4`;
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, enableLz4 = false) {
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 (enableLz4) {
171
- let decoder = lz4.createDecoderStream();
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 = ["/usr/share/ovmf/x64/OVMF.fd", "/usr/share/ovmf/OVMF.fd"];
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
- try {
142
- execSync("rsync -V", {
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.4",
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,